logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Atmega 328p i 88p - fs1000a UART kiepska komunikacja [C]

pachol.95 31 Paź 2016 22:55 2736 33
  • #1 16031556
    pachol.95
    Poziom 9  
    Witam :)

    mam taki problem:

    zamysł jest taki. 2 ATmegi które miałem pod ręką czyli 88p i 328p. ATmega 88 odpowiedzialna na pomiar temperatury i wysłanie do 328p, która z kolei ma wyświetlić temperaturę na LCD.

    Miałem już jakieś małe przygody ogólnie z językiem C w tym z Arduino ale postanowiłem postawić sobie bardziej ambitne cele stąd (wydawało by się) prosty projekt opisany powyżej.

    Tak więc uruchomiłem LCD potem walczyłem z OneWire (DS18B20) ale poległem i skończyłem na LM35 ( ofc mowa o termometrze) i ostatni kawałek układanki nie chce się przypasować. Ładnie wszystko zainicjowałem (prędkości przesyłu itp się zgadzają) a tu klops nie wchodzi nawet w przerwanie jak tylko dojdą dane do niego (z wyjątkiem jednego uruchomienia gdzie przez chwilę działało potem się zepsuło) i od tamtej chwili no co bym nie robił jest źle. Odbiornik coś tam odbiera nadajnik coś tam nadaje (widać to po diodach na RX i TX) ale jakoś nie gra to ze sobą... Jasną rzeczą jest że próbowałem nie tylko przez radio ale normalnie po kablu TX->RX i też nie działało to za dobrze ... co może być nie tak?


    Kod: C / C++
    Zaloguj się, aby zobaczyć kod



    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    sorki za mieszane języki w komentarzach xD

    Moderowany przez dondu:

    Usunąłem zbędne znaczniki CODE

  • #2 16031568
    excray
    Poziom 41  
    Co z tym nadajnikiem i odbiornikiem? W dalszym ciągu nie napisałeś o tym czego używasz.
  • #3 16031572
    dondu
    Moderator na urlopie...
    1. Nie definiuj F_CPU w kodzie programu z tych powodów: http://mikrokontrolery.blogspot.com/2011/03/fcpu-gcc-gdzie-definiowac.html

    2. Tego nikt nie będzie sprawdzał z dokumentacją (pomijam już że zera i tak nic nie zmieniają):

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    3. Przyglądnij się i przeczytaj dokładnie komentarze dot. funkcji usart_inicjuj() w zakresie ustawiania baud:
    http://mikrokontrolery.blogspot.com/2011/03/rs-232-atmega8-komputer-terminal.html

    4. Czy stosujesz kwarce 8MHz, czy wewnętrzny generator RC?

    5. Fusebity prawidłowo ustawione?
  • #4 16031574
    pachol.95
    Poziom 9  
    kupiłem na ebay i jedyne co jest opisane to nadajnik jako fs1000a (jak napisane jest w temacie). Obrazek:


    Atmega 328p i 88p - fs1000a UART kiepska komunikacja [C]
  • #6 16031595
    piotr411
    Poziom 22  
    Nadajnik jaki zastosowałeś, nie działa po RS. Musi być napisana we właściwy sposób biblioteka. Jest pewna grupa ludzi twierdzących, że kodowanie w Manchester, załatwia sprawę, ale taka teza świadczy wyłącznie o nieznajomości zagadnienia. W Arduino masz namiastkę polowicznie działającego kodu w VirtualWire.h. Miłej zabawy.
  • #7 16031598
    pachol.95
    Poziom 9  
    1.F_CPU zdefiniowałem tylko do obliczenia BAUDRATE

    2. zdaje sobie z tego sprawę to jest to samo co:
    UCSR0C=(1<<URSEL01)|(3<<UCSZ00)

    3. zaraz zerknę ale przyznam się że BAUD zgapiłem od kogoś kto niby to uruchomił. Pisało tam że te moduły maks uciągną 2400 a bezpiecznie jest mniej żeby na pewno dały radę (przynajmniej ja tak to zrozumiałem)

    4. wewnętrzny.N ie musi być super dokładnie idealnie więc to wystarczy jak raz na jakiś czas wyrzuci krzaczka nic się nie stanie więc uznałem że wewnętrzny wystarczy

    5. Fusebity ustawiane w mkavrcalculatro więc myślę że jest ok xD

    Dodano po 1 [minuty]:

    piotr411 napisał:
    Nadajnik jaki zastosowałeś, nie działa po RS. Musi być napisana we właściwy sposób biblioteka. Jest pewna grupa ludzi twierdzących, że kodowanie w Manchester, załatwia sprawę, ale taka teza świadczy wyłącznie o nieznajomości zagadnienia. W Arduino masz namiastkę polowicznie działającego kodu w VirtualWire.h. Miłej zabawy.


    czyli rozumiem że na wzór VirtualWire muszę zrobić bibliotekę czysto do AVR?

    edit:
    tak sobie myślę ok do tych modułów trzeba biblioteki ale normalnie po kablu powinno dać radę chyba a jest to samo tylko bardzie powiedział bym statycznie :) nie zmieniają się znaki co sekundę jak głupie tylko powoli o ile wgl się zmienią.
  • #8 16031612
    excray
    Poziom 41  
    dondu napisał:
    Te układy działają bardzo dobrze.

    Ale nie z ramkami RS232.
    piotr411 napisał:
    Jest pewna grupa ludzi twierdzących, że kodowanie w Manchester, załatwia sprawę, ale taka teza świadczy wyłącznie o nieznajomości zagadnienia.

    Dlaczego tak twierdzisz? Bardzo dobrze pracują z kodowaniem manchester czy też z manchesterem różnicowym. Trzeba tylko pamiętać o preambule przed właściwą transmisją. Oczywiście jak ktoś woli, to może swoją wersję kodowania napisać. tylko po co skoro manchester działa bardzo dobrze i jest prosty do oprogramowania.
  • #9 16031629
    pachol.95
    Poziom 9  
    kurcze coś mi się o tym mencheser obiło o uszy ale myślałem że UART to UART jak będą cm od siebie to cokolwiek odbierze ale odbierze a tu nic z tych rzeczy. Czyli podsumowując dotychczasowe sprawy. Kod jest ok ale jak byk korzystał z RS232 a nie z radia? to co w końcu wybrać menchester czy VirtualWire? jecze jak by to nie był problem prosił bym o źródło gdzie mógł bym obczytać to kodowanie (jeśli nie to znajdę sam ale może ma ktoś coś w zakładkach czy gdzieś i oszczędziło by mi to czasu)
  • #11 16031648
    pachol.95
    Poziom 9  
    o super ^.^

    no nic jutro wolne to coś pokombinuje i zobaczymy :) w sumie mam RFM01 i 02 (gdzie znalazłem gotowe biblioteki) ale stwierdziłem że nie odpuszczę tym razem jak z czujnikiem temperatury (ogólnie początkowo zamysł był żeby czujnik i nadajnik miał ATtinny 2313 ale skoro poległem przy czujniku cyfrowym musiałem 328p zabrać :P )
  • #12 16031701
    piotr411
    Poziom 22  
    excray napisał:
    dondu napisał:
    Te układy działają bardzo dobrze.

    Ale nie z ramkami RS232.
    piotr411 napisał:
    Jest pewna grupa ludzi twierdzących, że kodowanie w Manchester, załatwia sprawę, ale taka teza świadczy wyłącznie o nieznajomości zagadnienia.

    Dlaczego tak twierdzisz? Bardzo dobrze pracują z kodowaniem manchester czy też z manchesterem różnicowym. Trzeba tylko pamiętać o preambule przed właściwą transmisją. Oczywiście jak ktoś woli, to może swoją wersję kodowania napisać. tylko po co skoro manchester działa bardzo dobrze i jest prosty do oprogramowania.


    Nie twierdzę, a stwierdzam, Manchester, jest przeznaczony do transmisji przewodowych, gdzie nie występują tak silne zakłócenia jak na 433MHz. W ASK przy odbiorze trzeba kontrolować każdy bit z osobna i korygować do każdego następnego, który nadejdzie. To kompletnie inna struktura programu niz tak którą oferuje VirtualWire. Jeśli jeszcze trafi się jakiś cieplejszy dzień, postaram się nakręcić film pokazujący zasięgi różnych modułów i sposoby kodowania. Powinno ładnie to uświadomić dlaczego Manchester to półśrodek.
    Jak bardzo zaprzesz się, to i po RS uzyskasz podobne efekty jak VW, sterującą pembułą podanie jak kierunkiem przepływu danych w RS485. Podając przed rozpoczęciem transmisji z innego portu stan wysoki o długości co najmniej 8x pojedynczego bitu. Jest wiele innych, "sztuczek" by ASK "zmusić" do poprawnej i rozsądnej transmisji. No i jeszcze najważniejsze, czyli odbiorniki, są fatalnej czułości, przeciętnie 100dBm, co nie pozwala "wyłuskać" danych przy słabszym zasięgu jak to ma miejsce w OFDM lub QPSK. Dlatego potrzeba specjalnego traktowania, a to dość absorbuje zagadnienie by wyjaśnić w 2 zdaniach. Po za tym, niechce w chodzi w spór, że "działa" w Manchester i to wystarczy ;) Może do sprawdzenia czy moduły są sprawne wystarczy, może do budowy termometr z zasięgiem 10 w porywach 20m wystarczy, ale to nie trendy droga :) Widać to w każdym wątku jak padnie hasło FS1000A.
  • #13 16031736
    pachol.95
    Poziom 9  
    hmmm bo właśnie obawiam się o zasięg. Może będzie to 20m ale po drodze strop ... najpierw chce to uruchomić dla własnej satysfakcji potem jak się sprawuje i czy da radę :) widzę muszę to na razie "jakoś" zrobić i poczytać potem o tych kodowaniach tak więc nie mogę się doczekać tych testów ;)
  • #14 16031877
    dasej
    Poziom 32  
    Witam.

    Co do zasięgu. Jak nadajnik i odbiornik leżą na stole obok siebie też mogą się nie widzieć z powodu zbyt silnego sygnału.
    Odsuń je od siebie chociaż na 1-1.5mb.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Kod pasuje do 88 i 328.
    Uruchamiasz w następujący sposób.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Kolejna sprawa kto w przerwaniu robi takie numery
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    przerwanie trwające 5 Sekund. Czysta porażka.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Powyżej Masz przykład przerwania ( tu akurat INT0 ). Niema żadnego wyświetlania danych i czekania w nieskończoność.
    Odczyt danych oraz poinformowanie programu że zostało wykonane przerwanie.
    Reszta ma być w programie.
    Ile razy Twój program będzie wchodził w przerwanie ( zanim zawiesi uC ) jak dostanie dane co 4 sekundy.
    Przerwanie przerwane przerwaniem.

    Moderowany przez dondu:

    W ostatnim przykładzie zakomentowałem zbędne wyłączanie przerwań INT0 i ich ponowne włączenie) przynajmniej dopóki autor nie wytłumaczy jaki ma to uzasadniony cel.

  • #15 16031980
    excray
    Poziom 41  
    piotr411 napisał:
    Manchester, jest przeznaczony do transmisji przewodowych, gdzie nie występują tak silne zakłócenia jak na 433MHz.

    To dziwne co piszesz, bo wielu producentów układów radiowych z modulacją ASK stosuje właśnie manchester do kodowania danych.
    piotr411 napisał:
    Dlatego potrzeba specjalnego traktowania, a to dość absorbuje zagadnienie by wyjaśnić w 2 zdaniach.

    Myślę, że jednak powinieneś. Skoro już zacząłeś tą dyskusję o wyższości niewiadomoczego (bo przecież chyba nie chcesz implementować QPFM w tym module za 2zł) nad manchesterem to wypadałoby ją obronić konstruktywnie. Więc jeśli masz inną koncepcję to ją przedstaw. Oczywiście miłoby było gdyby ta koncepcja zachowała analogiczną prędkość transmisji co przy kodowaniu manchester.
  • #16 16032115
    pachol.95
    Poziom 9  
    dasej napisał:
    przerwanie trwające 5 Sekund. Czysta porażka.


    wiem że tak być nie powinno ale to jest już n-ta wersja kodu i już się wkurzyłem że może mignie tekst i nie widać, stąd taki czas. Zauważ że nawet nie czyściłem LCD żeby tylko wyłapać chwilę gdzie wejdzie w przerwanie ale tego nie robił :/

    dasej napisał:
    Ile razy Twój program będzie wchodził w przerwanie ( zanim zawiesi uC ) jak dostanie dane co 4 sekundy.
    Przerwanie przerwane przerwaniem.


    a to nie jest tak że przerwanie blokuje inne przerwania samo z siebie?

    dasej napisał:
    uart_init(38400); // uruchomienie UART


    czemu akurat tyle ? wydaje mi się to za dużo (chyba że chodzi o to żeby właśnie blisko działało a daleko nie)
  • #17 16032196
    pachol.95
    Poziom 9  
    dasej napisał:

    pachol.95 napisał:

    a to nie jest tak że przerwanie blokuje inne przerwania samo z siebie?


    Musisz to zrobić Sam.


    wydawało mi się że właśnie jest jak mówię (co nie zmienia faktu że delay tam był zbędny ale jak mówiłem jest to wersja pod nazwą "rozpaczliwa" ;) )

    Tak więc zanim dondu się wypowie przytoczę jego artykuł ;P (mam nadzieję że dobrze go zrozumiałem)
    mikrokontrolery.blogspot.com


    EDIT:
    edytowałem trochę kod w kierunku tego co sugerował dasej. Wurzuciłem wszyskie delay i wszyskie LCD. Jako informacje że kiedykolwiek był w przerwniu przyjąłem zapalającą się diodę LED. Niestety nadal nie wchodzi mi w przerwanie. Zastanawia mnie to że te diody mało migają od nadawania i odbioru. Jak się wgrywa coś do arduino to migają cały czas a tu wygląda jak by cały czas przesyłał "1" mignie tylko na początku sygnału (co jest dobrym zachowaniem)
  • #18 16032408
    piotrva
    VIP Zasłużony dla elektroda
    dasej napisał:
    pachol.95 napisał:
    a to nie jest tak że przerwanie blokuje inne przerwania samo z siebie?

    Musisz to zrobić Sam.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Dla uart też są takie polecenia.


    Kolego, mylisz się. Wejście do danego przerwania powoduje skasowanie flagi I w rejestrze SREG. Więc wchodząc do danego przerwania, o ile na siłę nie wywołamy SEI, inne przerwania będą zablokowane.

    Nota katalogowa Atmega8 i podobnych napisał:
    The Global Interrupt Enable bit must be set for the interrupts to be enabled. The individual interrupt
    enable control is then performed in separate control registers. If the Global Interrupt Enable
    Register is cleared, none of the interrupts are enabled independent of the individual interrupt
    enable settings. The I-bit is cleared by hardware after an interrupt has occurred, and is set by
    the RETI instruction to enable subsequent interrupts. The I-bit can also be set and cleared by
    the application with the SEI and CLI instructions, as described in the Instruction Set Reference.
  • #19 16032456
    dasej
    Poziom 32  
    To ciekawe. Co fachowiec to pisze inaczej.

    Z artykułu kolegi Dondu Link
    wynika że jest możliwe wywołanie kolejnego przerwania jak z obsługi poprzedniego nie wyjdziemy.

    To kto ma rację. Nie pamiętam już gdzie o tym czytałem ale jak przerwanie nie jest zablokowane to procesor wywoła je powtórnie.
  • #21 16032489
    dasej
    Poziom 32  
    Wiele kolejnych nie zakończonych przerwań.

    Atmega 328p i 88p - fs1000a UART kiepska komunikacja [C]

    Czyli jak wejście w jedno przerwanie blokuje inne?
  • #22 16032497
    dondu
    Moderator na urlopie...
    dasej napisał:
    Wiele kolejnych nie zakończonych przerwań.

    Atmega 328p i 88p - fs1000a UART kiepska komunikacja [C]

    Czyli jak wejście w jedno przerwanie blokuje inne?


    Przeczytaj jeszcze raz ten punkt dokładnie: 4. BŁĄD: Włączanie przerwań w funkcji obsługującej przerwanie
    Rozpatruje on przypadek włączenia przerwań globalnych w funkcji przerwania.

    Twoje wnioski są błędne a kol. pachol.95 prawidłowe. :)
  • #24 16032523
    dondu
    Moderator na urlopie...
    Tak jak zacytowany w tym punkcie fragment dokumentacji (który także przytoczył piotrva) w momencie rozpoczęcia wykonywania przerwania, blokowana jest flaga I czyli globalne zezwolenie na przerwania.

    Powoduje ona to, że aktualnie wykonywana funkcja przerwania nie zostanie przerwana aż do jej zakończenia. W tym czasie flagi poszczególnych przerwań np. przepełnienia timera, czy ADC, itd mogą się ustawiać, ale nie powodują wykonania ich funkcji przerwań. Nastąpi to dopiero po wykonaniu aktualnie wykonywanej funkcji przerwania, której na końcu kompilator wykonuje rozkaz RETI który wychodzi z niej i włącza przerwania globalne..

    Dlatego punkt 4 uczula początkujących, by w funkcji przerwania nie włączali przerwań globalnych, bo mogą z tego wyniknąć katastrofalne problemy.

    Czy teraz rozumiesz jak to działa?
  • #25 16032527
    pachol.95
    Poziom 9  
    no to fajnie omówiliśmy sobie przerwania i wiem że teraz mam to ok :) jak odbierze sygnał wchodzi w przerwanie czyta sygnał przypisuje do zmiennej zapala diodę i wychodzi z przerwania. Tak niestety działa tylko w teorii.

    Pomijam już te kodowania i wgl na tą chwilę interesuje mnie nawet odbiór śmieci byle żeby weszło w przerwanie a tego nie robi :/

    Jeszcze pytanie czy bit RXCIE0 rejestru UCSR0B musi być ustawiony na 1? Bo wtedy wiesza się wszystko w momencie gdy dostaje zezwolenie na przerwania a do przerwania nadal nie wchodzi. Wcześniej raz zdarzyło się że wchodził faktycznie w te przerwanie bez tego bitu.
    Moja obecna procedura przerwania.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    init zmieniłem na :


    dasej napisał:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod



    z tym że baud nie dałem 38400 jak kolega sugerował tylko trzymam się wersji z tego właśnie innego powiedzmy poradnika że prędkość max 2400 b/s.
  • #26 16032546
    dasej
    Poziom 32  
    A tu zalecałeś blokowanie przerwania, w celu likwidacji drgań styków i zabezpieczenia się przed ponownym wywołaniem przerwania.

    Atmega 328p i 88p - fs1000a UART kiepska komunikacja [C]
  • #27 16032554
    dondu
    Moderator na urlopie...
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    W powyższej funkcji wywołujesz funkcję:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    która wykouje sprawdzenie flagi RXC0, której de facto stan jest znany, bo to ona decyduje o wykonaniu się przerwania USART_RXC_vect :)

    Wystarczy więc po prostu odebrać danę:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Inna sprawa to zasadność wywoływania przerwania, ale pomińmy ten wątek.
  • #28 16032559
    pachol.95
    Poziom 9  
    to nie ma robić nic innego jak tylko odbierać informacje stąd jak informacja dojdzie ma przerwać wszystko i ją odebrać - dla tego przerwanie. Ale niestety atmega328p chyba nie lubi atmegi88 i nie chce przestać rozmawiać ze swoimi pinami na rzecz sygnału od atmegi88 :d
  • #29 16032563
    dondu
    Moderator na urlopie...
    dasej napisał:
    A tu zalecałeś blokowanie przerwania, w celu likwidacji drgań styków i zabezpieczenia się przed ponownym wywołaniem przerwania.

    Atmega 328p i 88p - fs1000a UART kiepska komunikacja [C]

    Tam omawialiśmy przypadek podłączenia przycisku do pinu INT0 i wykorzystaniu przerwań: https://www.elektroda.pl/rtvforum/topic2955026.html#14259843

    Jeśli przycisk podłączasz pod pin INT0, to drgania spowodują wykonanie przerwań kilkukrotnie. W takiej sytuacji eliminację drgań styków można zrobić blokując przerwanie INT0 (na czas trwania drgań) w momencie wykrycia pierwszego impulsu.


    Edit:

    pachol.95 napisał:
    Ale niestety atmega328p chyba nie lubi atmegi88 i nie chce przestać rozmawiać ze swoimi pinami na rzecz sygnału od atmegi88 :d

    Musi działać - trzeba znaleźć błąd w podłączeniu lub programie.
    Warto mieć oscyloskop ...
  • #30 16032572
    dasej
    Poziom 32  
    To nie problem różnych procesorów.
    A po zatem Atmega88 i Atmega328 to to samo tylko pierwsza ma 8k falsha a druga 32k.
    Mówiąc z grubsza.
REKLAMA