Sheppard25 Napisano Wrzesień 4, 2024 Udostępnij Napisano Wrzesień 4, 2024 (edytowany) Czesc, mam wydawaloby sie prosty kod. Niestety zachowuje sie bardzo nieintuicyjnie, mam wrazenie ze to przez jakies opoznienia wewnatrz mikrokontrolera albo sam mikrokontroler nie zdazyl wszystkiego ustawic? Timer za czesto? (Co 1ms) Nie wiem. Zalozenie jest proste. Metoda send ma ustawic liczbe 16bitowa do wyslania, po czym wystawic jej pierwszy bit do wyslania. Timer odczytuje ten bit, wysyla zakodowany w Manchester i wywoluje ponownie funkcje, ktora tym razem ustawia nastepny bit i tak 16 razy az cala liczba zostanie wyslana. Tzn takie jest zalozenie. Niestety problem jest taki, ze po drodze gdzies gubione sa bity, ciezko mi zdebugowac co sie dzieje, poniewaz printy sie nie wyswietlaja (albo nie zawsze, moze to tez kwestia samej biblioteki uart, ktora ma delaye). Natomiast kod ktory wrzucam, bez printow, ktory powinien dzialac, nie wysyla niczego (sprawdzam analizatorem logicznym). Natomiast odokomentowujac delay'e w main.cpp juz wysyla. Ciezko mi sprecyzowac problem poniewaz wlasciwie mozna by powiedziec - nie dziala, dzieja sie rzeczy niestworzone 🙂 . Jakby ktos biegly byl w stanie rzucic okiem na kod, moze wylapie juz czytajac go gdzie jest problem. Dzieki main.cpp #include <avr/io.h> #include <util/delay.h> #include <MsUart.h> #include "MsRf.h" #include "MsHuminitySensor.h" #define TX_PIN PB4 #define ADC_PIN PB4 MsRf rf; ISR(TIM0_COMPA_vect) { rf.onTimerInterrupt(); } int main() { rf.send(456); // _delay_ms(10); // z tym delayem wysyla dane while (1) { } return 0; } MsRf.cpp #include "MsRf.h" MsUart uart(&DDRB, &PORTB, 4); MsRf::MsRf() { bitToTransmit = BitState::NODATA; bitIndex = 0; data = 0; transmitting = false; init(); MsTimer::init(); } void MsRf::init() { DATA_DDR |= (1 << DATA_PIN); } // Zmiana funkcji send, która teraz przyjmuje liczbę uint16_t zamiast stringa void MsRf::send(uint16_t number) { this->data = number; // Przechowuj liczbę w polu `data` setNextManchesterBits(); // Zainicjuj pierwszy zestaw bitów do transmisji } void MsRf::setNextManchesterBits() { // Sprawdzanie bitu na pozycji `bitIndex` uint8_t bit = ((data >> bitIndex) & 1); if (bit == 1) { bitToTransmit = BitState::HIGH; } else if (bit == 0) { bitToTransmit = BitState::LOW; } bitIndex++; // Jeżeli wszystkie 16 bitów zostały przesłane, resetujemy bitIndex if (bitIndex >= 16) { bitIndex = 0; // Resetujemy indeks bitów data = 0; // Koniec danych do transmisji bitToTransmit = BitState::NODATA; } } void MsRf::transmitFirstBit() { if (bitToTransmit == BitState::LOW) { // uart.print("1"); DATA_PORT |= (1 << DATA_PIN); // Gdy bit jest 0 najpierw pierwszy bit do góry } else { // uart.print("0"); DATA_PORT &= ~(1 << DATA_PIN); // Gdy bit jest 1 najpierw pierwszy bit do dołu } } void MsRf::transmitSecondBit() { if (bitToTransmit == BitState::LOW) { // uart.print("0"); DATA_PORT &= ~(1 << DATA_PIN); // Gdy bit jest 0 drugi bit na dół } else { // uart.print("1"); DATA_PORT |= (1 << DATA_PIN); // Gdy bit jest 1 drugi bit do góry } } void MsRf::onTimerInterrupt() { if (bitToTransmit != BitState::NODATA && !transmitting) { transmitFirstBit(); transmitting = true; return; } if (bitToTransmit != BitState::NODATA && transmitting) { transmitSecondBit(); setNextManchesterBits(); // Pobierz kolejne bity Manchester transmitting = false; } } Edytowano Wrzesień 4, 2024 przez Sheppard25 Link do komentarza Share on other sites More sharing options...
etet100 Wrzesień 5, 2024 Udostępnij Wrzesień 5, 2024 Wiem, to nie jest odpowiedź na pytanie, ale może wrzuć cały kompilowalny kod na githuba? Jeżeli nie znasz gita to zdecydowanie WARTO POZNAĆ. Często problem jest w zupełnie innym miejscu niż myślisz. Po takich wycinkach trudno zgadnąć. Link do komentarza Share on other sites More sharing options...
Tradiatore Wrzesień 5, 2024 Udostępnij Wrzesień 5, 2024 Nie widzę zdefiniowanego zegara F_CPU. Nie wiem, na której AVRce to robisz, ale mogą być rozbieżności z zegarem nadajnika i odbiornika przez to, że właśnie nie zdefiniowałeś symbolu F_CPU, szczególnie jeśli gdzieś wewnętrznie wykorzystywane są delaye - choć tych nie widzę. Wartość domyślnego taktowania, na pewno jest w dokumentacji, ale wiem że czasami trzeba się naszukać - sam spędziłem chyba z godzinę wertując dokumentację do ATmegi4809 😅. Dodatkowo, tak jak pisał etet100, przydałby się szerszy pogląd na projekt - plik MsRf.h między innymi. Link do komentarza Share on other sites More sharing options...
Sheppard25 Wrzesień 5, 2024 Autor tematu Udostępnij Wrzesień 5, 2024 (edytowany) @etet100 Jasne, proszę bardzo: https://github.com/sheppard30/Czujnik-wilgotnosci---nadajnik . Githuba oczywiście znam, jestem programistą 10 lat ponad tylko inna technologia 😉 @Tradiatore F_CPU chyba jest zdefiniowane gdzieś w bibliotekach ponieważ najeżdżając pokazuje poprawne taktowanie zgodne z fusbitami Kontroler: Attiny13a (ten malutki) 🙂 Odbiornik wydaje mi sie ze dziala dobrze, bo jak uda sie przeslac jakies dane to czasy trwania bitow sa dosc zblizone do poprawnych. PS Czy 1ms to nie za czesto na przerwanie? Moze ten mikrokontroler sie po prostu dławi, nie daje rady wykonać w 1ms tych wszystkich operacji? Edytowano Wrzesień 5, 2024 przez Sheppard25 Link do komentarza Share on other sites More sharing options...
Polecacz 101 Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Produkcja i montaż PCB - wybierz sprawdzone PCBWay! • Darmowe płytki dla studentów i projektów non-profit • Tylko 5$ za 10 prototypów PCB w 24 godziny • Usługa projektowania PCB na zlecenie • Montaż PCB od 30$ + bezpłatna dostawa i szablony • Darmowe narzędzie do podglądu plików Gerber Zobacz również » Film z fabryki PCBWay
etet100 Wrzesień 5, 2024 Udostępnij Wrzesień 5, 2024 Brakuje MsUart. On przypadkiem nie korzysta z timerów? Nie masz tu konfliktu? Jeśli masz wątpliwości czy 1ms to nie za szybko to po prostu zacznij od dużo dłuższych czasów. Nawet takich które są obserwowalne gołym okiem. Link do komentarza Share on other sites More sharing options...
Tradiatore Wrzesień 5, 2024 Udostępnij Wrzesień 5, 2024 @etet100 Z tego co napisał @Sheppard25 to program się kompiluje. Gdyby kompilator nie znalazł biblioteki MsUart, sypnąłby błędem. Ale rada co do zwiększenia okresu timera jest słuszna - spróbuj 😉 Link do komentarza Share on other sites More sharing options...
etet100 Wrzesień 5, 2024 Udostępnij Wrzesień 5, 2024 Gdyby się kompilował to bym nie pisał. Sądzę że tu może być problem: lib_extra_dirs = C:\Users\mscir\Projekty\Libraries Link do komentarza Share on other sites More sharing options...
Tradiatore Wrzesień 5, 2024 Udostępnij Wrzesień 5, 2024 Nie sprawdzałem, czy się kompiluje, ale z tego co napisał OP wynikało, że tak. Jeśli jednak brakuje biblioteki no to problem jakby w połowie rozwiązany. Link do komentarza Share on other sites More sharing options...
etet100 Wrzesień 5, 2024 Udostępnij Wrzesień 5, 2024 Ale ja nie twierdzę, że on się nie kompiluje u autora. On się nie kompiluje u mnie. Link do komentarza Share on other sites More sharing options...
Sheppard25 Wrzesień 5, 2024 Autor tematu Udostępnij Wrzesień 5, 2024 @etet100 @Tradiatore Celowo Wam wrzucilem wersje z wykomentowanym/usunietym wywolaniem biblioteki UART zeby pokazac ze bez niej to tez nie dziala. Ona nie ma w sobie timera, ma jednego delay'a na dlugosc taka jaka oczekuje odbiornik z danym boudem czyli np 1sek/9600. Ale tak jak napisalem, w przykladzie na repo tej biblioteki nie uzywam. Z wiekszymi czasami pewnie bedzie lepiej ale zastanawiam sie czy przy tym ze ten mikrokontroler jest maly i zadan na nim nie bedzie duzo, nie lepiej bedzie ustawic po prostu timera np z przerwaniami co 1 sekunde a bity wiadomosci wysylac z delayami (poniewaz zadna inna operacja na tym kontrolerze i tak nie bedzie wywolywana, ktora te delaye by zablokowaly). //edit ok widze ze jest stworzony obiekt UART ale ja nie korzystam z zadnej jego metody, wywolany jest jedynie konstruktor, dla pewnosci podaje tez linka do tej biblioteki. https://github.com/sheppard30/MsUart Link do komentarza Share on other sites More sharing options...
etet100 Wrzesień 5, 2024 Udostępnij Wrzesień 5, 2024 (edytowany) Jeśli masz ochotę to zerknij na kilka moich zmian. https://github.com/sheppard30/Czujnik-wilgotnosci---nadajnik/pull/1 Pewnie nie wszystkie są ważne. Mam niestety tą przypadłość, że zawsze muszę coś zmienić po swojemu. Szpilki w kanale 2 (słabo widoczne) to początek bitu. 00001110 No i wyrabia się z palcem w nosie. Docelowo możesz pewnie znacznie obniżyć taktowanie. Edytowano Wrzesień 5, 2024 przez etet100 Link do komentarza Share on other sites More sharing options...
Sheppard25 Wrzesień 5, 2024 Autor tematu Udostępnij Wrzesień 5, 2024 (edytowany) @etet100 dzięki wielkie, sporo fajnych patentów które sobie użyję. Postanowiłem jednak zmienić architekturę aplikacji, ponieważ uważam że użycie w tym konkretnym przypadku Timera było błędem a raczej było totalnie niepotrzebne. Jakie zadanie ma ten mikrokontroler? 1. Odczytać dane z pinu analogowego 2. Wysłać te dane Wszystko w interwale, np. kilku sekundowym a docelowo około godzinnym. I tutaj nie ma potrzeby używania Timera czy przerwań ponieważ: 1. Nie muszę reagować na żadne zewnętrzne sygnały. 2. Nie muszę wykonywać w "tle" w równych odstępach czasowych żadnych operacji, które są niezależne od innych i wszystko można prosto ogarnąć delayem. Co innego teraz na odbiorniku, gdzie postanowiłem użyć Atmegi 16A, która ma dużo pinów (potrzebuję do klawiatury i wyświetlacza). Taka klawiatura musi "nasłuchiwać" cały czas więc tutaj napewno Timer może się przydać. Natomiast to co mnie ciekawi jeszcze przy tym Attiny13a i mojej aplikacji, to konieczność podania delay'a na początku przed 'while'. Bez tego ucina bity jeżeli od razu cośbyłoby wysyłane. Edytowano Wrzesień 5, 2024 przez Sheppard25 Link do komentarza Share on other sites More sharing options...
etet100 Wrzesień 5, 2024 Udostępnij Wrzesień 5, 2024 (edytowany) Ja mam inne zdanie. To się aż prosi o użycie timera. Zwłaszcza jeśli nie bardzo potrzebny do czegoś innego. Taka asynchroniczna komunikacja jest zwykle krytyczna czasowo a żaden delay nie da równych odstępów. Po to powstały timery i przerwania żeby ich używać. A co do ucinania czegoś... szczerze nie zauważyłem. rf.init(); rf.send(0b01110000); while (1) { // rf.send(0b01110000); // _delay_ms(500); } Niczego nie obcina. Robię restart i oscyloskop ładnie łapie ten pierwszy bajt. Edytowano Wrzesień 5, 2024 przez etet100 Link do komentarza Share on other sites More sharing options...
Sheppard25 Wrzesień 5, 2024 Autor tematu Udostępnij Wrzesień 5, 2024 Przy Manchesterze te równe odstępy chyba nie są krytyczne, te pare mikrosekund nie zrobi różnicy. Niemniej skoro twierdzisz, że prosi się o jego użycie to użyłbyś go tak jak w moim oryginalnym rozwiązaniu do wysyłania bitów Manchester w równych interwałach czy jakoś inaczej? Link do komentarza Share on other sites More sharing options...
etet100 Wrzesień 5, 2024 Udostępnij Wrzesień 5, 2024 (edytowany) Dla samej satysfakcji i wprawy warto to zrobić. Na delayach to robią w przedszkolu (pół żartem oczywiście). Przy przerwaniach dochodzą pewne problemy (wyzwania), które lepiej poznać teraz, niż przy większych projektach. Ten czas jakoś tam istotny jednak jest. Ale faktem jest, że prędkości są minimalne, to i spore odchyłki nie będą miały znaczącego wpływu. Nie wiem czy czytałeś ten dokument https://ww1.microchip.com/downloads/en/AppNotes/Atmel-9164-Manchester-Coding-Basics_Application-Note.pdf A kod wygląda całkiem ok. Zawsze coś można poprawić ale podstawa wydaje mi się solidna. Tą ATMEGE16 bym jeszcze przemyślał. Nie bardzo sobie wyobrażam co ty zrobisz z tyloma liniami. To jest duże i nieporęczne. Edytowano Wrzesień 5, 2024 przez etet100 Link do komentarza Share on other sites More sharing options...
Pomocna odpowiedź
Bądź aktywny - zaloguj się lub utwórz konto!
Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony
Utwórz konto w ~20 sekund!
Zarejestruj nowe konto, to proste!
Zarejestruj się »Zaloguj się
Posiadasz własne konto? Użyj go!
Zaloguj się »