alabastrowy Napisano Marzec 28, 2016 Udostępnij Napisano Marzec 28, 2016 Cześć, próbuję ostatnio ogarnąć temat komunikacji IR. Posiadam diodę ir + odbiornik TSOP2236. Przeczytałem dokumentację, poczytałem trochę o standardzie RC5 jednak ciągle nie za dużo mi wychodzi. Mianowicie posiadam atmegę8 którą chcę użyć jako nadajnik + arduino które sczytuje sygnały. Nie chcę opierać komunikacji na RC5 tylko chcę użyć jakiejś bardzo prymitywnej komunikacji 8 bitowej na początek, którą napiszę sam. Oto kod nadajnika który jest na atmedze 8. void pulse () { PORTB = 0b1; _delay_us(7); PORTB = 0b0; _delay_us(21); } void bit (int a) { switch (a) { case 0: for (int i=0; i<10; i++) pulse(); _delay_us(280); break; case 1: _delay_us(280); for (int i=0; i<10; i++) pulse(); } } int main() { DDRB = 0b1; DDRD = 0b0; PORTB = 0b0; for (;;) { if ((PINC & (1<<5))!=0) { bit(1); bit(1); bit(1); bit(1); bit(1); bit(1); bit(1); bit(1); _delay_ms(25); } if ((PINC & (1<<4))!=0) { bit(1); bit(1); bit(1); bit(0); bit(0); bit(0); bit(1); bit(1); _delay_ms(25); } } } Z tego co rozumiem odbiornik działa na takiej zasadzie że "falę migań" interpretuje jako stan niski a pauzę jako stan wysoki (to wywnioskowałem z RC5). Z tego co również wiem niekoniecznie ta fala musi być 32 mignięciami tylko może trwać mniejszą ilość pulsów - dlatego w mojej wersji jest 10 pulsów i odstęp równy długości 10 pulsów (nawet jak ustawię 32 pulsy zgodnie z RC5 to jest to samo). Ustawiłem odstęp między wysłaniem tych 8 bitów na 25ms. Problem jest następujący, że arduino sczytuje te bity w sposób totalnie dla mnie niezrozumiały : Arduino przechwytuje to stabilnie, w sensie jak wciskam guzik pierwszy to ciągle sczytuje te same bity, nie ma żadnych zakłóceń, a jak drugi to również stabilnie. Problem jest tylko taki że gdy oczekuje bitów 11111111 to arduino wyświetla zupełnie inne bity, czyli 10000111. Nie wiem zbytnio gdzie może tkwić problem. Tutaj jest kod odbiornika na arduino : #define IRpin 2 void setup() { pinMode (IRpin, INPUT_PULLUP); Serial.begin(9600); } const int rozmiar = 8; void loop() { if ((PIND & (1<<IRpin))==0) { for (int i =0; i<rozmiar; i++) { if ((PIND & (1<<IRpin))==0) Serial.print("1"); else Serial.print("0"); delayMicroseconds(560); if (i==rozmiar-1) { Serial.print("\n"); delay(25); } } } } Gdzie robię błąd? Zależy mi aby zrobić stabilne wysyłanie 8 bitów, i jak z nadajnika wysyłam 11111111 to takie też wyświetlają się na arduino. Link do komentarza Share on other sites More sharing options...
marek1707 Marzec 28, 2016 Udostępnij Marzec 28, 2016 Prosty test myślowy: narysuj jak wygląda nadawany przez Twój program przebieg. Pomijając paczki impulsów, ma on jakąś obwiednię czyli to co "oddaje" odbiornik IR - stan niski w czasie trwania paczki. Pokaż nam tutaj przykładowy sygnał odbiornika dla kombinacji np. 11001011 albo jakiejś innej nietrywialnej i nanieś na niego to, co będzie w tym czasie robił (rzeczywiście) Twój program odbiornika. Gdzie wypisze 1, gdzie 0, gdzie się synchronizuje do odbieranego przebiegu (bo przecież ani nie nadajesz dokładnie z zamierzoną prędkością ani nie czekasz dokładnie tyle ile chcesz) a gdzie będzie zwyczajnie czekał na delay'u. Wtedy przekonasz się czy ma to szansę działać a my zobaczymy czy rozumiesz działanie własnego kodu. 1 Link do komentarza Share on other sites More sharing options...
alabastrowy Marzec 28, 2016 Autor tematu Udostępnij Marzec 28, 2016 A więc swój program i odbiornik rozumiem w ten sposób : Górny przykład dotyczy wysłania 11111111 a ten dolny do wysłania 11100011 I wydaje mi się że tak powinien działać ale nie działa :/ To H i L odnosi się do odbiornika na arduino, który zaczyna sczytywać po wykryciu stanu niskiego, a następnie przeskakuje a długość jednego bitu i jak zastaje stan niski to powinien to interpretować jako 1, a jak stan wysoki to jako 0 Link do komentarza Share on other sites More sharing options...
deshipu Marzec 28, 2016 Udostępnij Marzec 28, 2016 A spróbuj te pionowe kreski narysować co 3.5 kratek, zamiast co 4 i zobacz jaki sygnał byś wtedy odczytał? 1 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
alabastrowy Marzec 28, 2016 Autor tematu Udostępnij Marzec 28, 2016 Czyli chodzi tu o to że jak mam delay w odbiorniku 560 to do tego trzeba jeszcze doliczyć trochę czasu jaki zajmuje wykonanie tamtego kodu? Czyli powiedzmy w sumie wychodzi ze sczytuje kod powiedzmy co 600us i dlatego to się rozjeżdża? Do tego zmierzacie? W takim razie czy nie wystarczy po prostu zmniejszyć lekko delay w odbiorniku i sprawdzić czy odpowiednio sczytuje? O to chodzi? W sensie wydaje mi się że już na takim pseudokodzie da się oprzeć jakieś zdalne sterowanie, bo da się rozróżnić klawisze, tylko tu bardziej chodzi że chcę temat zrozumieć i jak wysyłam bity 11111111 to takie chciałbym widzieć 😅 @EDIT Okej, udało mi się to ogarnąć 😅 Okazało się że zamiast zmniejszać odstęp na odbiorniku trzeba było go zwiększyć, dokładnie do 600us bo to atmega zwolniała, co pewnie jest spowodowane też tym że działa na 1mHz i trochę jej zajmuje dłużej to czasu wykonanie tych operacji 😋 + chyba tsop2236 działa odwrotnie, i to przerwę między miganiami interpretuje jako stan niski co też uwzględniłem Dzięki wielkie za naprowadzenie, już wszystko działa 🙂 Link do komentarza Share on other sites More sharing options...
deshipu Marzec 28, 2016 Udostępnij Marzec 28, 2016 Nie wiem dlaczego się rozjeżdża, trudno powiedzieć tak z czapy. Chyba byś musiał trochę poeksperymentować. Jeśli w atmedze8 używasz wewnętrznego oscylatora, to całkiem możliwe, że on nie jest super dokładny i, co gorsza, zmienia się w zależności od temperatury... 1 Link do komentarza Share on other sites More sharing options...
marek1707 Marzec 28, 2016 Udostępnij Marzec 28, 2016 Odbiornik nie musi synchronizować się z przychodzącym strumieniem tak długo, jak długo jesteś w stanie utrzymać jego timing w stosunku do strumienia. Na pewno źle robisz już na początku: po wykryciu pierwszego zera o d razu zaczynasz "skoki" co 560us a wtedy w każdym następnym próbkowaniu trafiasz akurat na obszar zmiany - czyli losowy odczyt. Gdybyś po wykryciu pierwszego zera odczekał po prostu (tylko raz) dodatkowe pół czasu paczki, następne próbkowania trafiałyby w środek stabilnego stanu linii. Jeszcze lepsza byłaby synchronizacja do każdego bitu: po wykryciu pierwszego zera czekasz 1.5 czasu paczki trafiając w 1/4 czasu nadawania następnego bitu. Od tej chwili aktywnie czekasz na zmianę stanu i wtedy odczytujesz stan linii. Ponieważ w Twoim kodowaniu zmiana zachodzi zawsze w połowie czasu nadawania bitu (CNB), odbiornik nie musi utrzymywać timingu strumienia aż przez 8 bitów. Wystarczy, że umie w miarę dobrze odliczyć 1.5 długości paczki (0.75 CNB). No a co się stanie, gdy pierwszy bit będzie 0? Narysuj to. 1 Link do komentarza Share on other sites More sharing options...
alabastrowy Marzec 28, 2016 Autor tematu Udostępnij Marzec 28, 2016 Odbiornik nie musi synchronizować się z przychodzącym strumieniem tak długo, jak długo jesteś w stanie utrzymać jego timing w stosunku do strumienia.Na pewno źle robisz już na początku: po wykryciu pierwszego zera o d razu zaczynasz "skoki" co 560us a wtedy w każdym następnym próbkowaniu trafiasz akurat na obszar zmiany - czyli losowy odczyt. Gdybyś po wykryciu pierwszego zera odczekał po prostu (tylko raz) dodatkowe pół czasu paczki, następne próbkowania trafiałyby w środek stabilnego stanu linii. Jeszcze lepsza byłaby synchronizacja do każdego bitu: po wykryciu pierwszego zera czekasz 1.5 czasu paczki trafiając w 1/4 czasu nadawania następnego bitu. Od tej chwili aktywnie czekasz na zmianę stanu i wtedy odczytujesz stan linii. Ponieważ w Twoim kodowaniu zmiana zachodzi zawsze w połowie czasu nadawania bitu (CNB), odbiornik nie musi utrzymywać timingu strumienia aż przez 8 bitów. Wystarczy, że umie w miarę dobrze odliczyć 1.5 długości paczki (0.75 CNB). No a co się stanie, gdy pierwszy bit będzie 0? Narysuj to. Poradziłem sobie już z tym, wystarczyło zwiększyć delay bo atmega8 zwalniała przez co się odczyt rozjeżdżał. A co do pytania gdy pierwszy bit będzie zerem, wydaje mi się że wtedy cały odczyt zostanie jakby zanegowany, czyli jakbyśmy mieli otrzymać 10010010 to otrzymamy 11101101 (jedynka z przodu gdyż zawsze czekamy na stan niski który interpretujemy jako 1), dlatego też się chyba ustala że pierwszy bit jest zawsze jedynką, albo jak w RC5 dwa pierwsze bity :-> Link do komentarza Share on other sites More sharing options...
marek1707 Marzec 28, 2016 Udostępnij Marzec 28, 2016 Teraz też się rozjeżdża tylko tego nie widzisz. Po pierwsze musisz próbkować w stanie gdy linia jest stabilna a tak jest wtedy gdy trafiasz w połowę płaskiego obszaru. Powiększenie opóźnienia przesunęło pierwszy odczyt poza strefę zmiany, ale przesuwa też kolejne odczyty coraz dalej. Takie coś jest bardzo niepewne, bo zależy od napięcia zasilania, temperatury i mocy sygnału odbieranego. Jeżeli kod niesie w sobie informację o synchronizacji bitów (a ten bifazowy tak właśnie ma) - skorzystaj z tego. Obowiązkowa zmiana w połowie CNB jest bardzo cenna. Nie zadowalaj się rozwiązaniem, które tylko wygląda, ze działa. Teraz zrobiłeś coś jak UART - synchronizację tylko do bitu startu. Po co w takim razie takie skomplikowane kodowanie bitów? Nie wystarczy po prostu wysłać je kolejno jako paczki lub przerwy? Przy tak prymitywnym odbiorniku, to na to samo wyjdzie. 1 Link do komentarza Share on other sites More sharing options...
alabastrowy Marzec 28, 2016 Autor tematu Udostępnij Marzec 28, 2016 Masz rację, zgodzę się ze wszystkim co piszesz. Tylko że póki co brak mi totalnie wiedzy aby zająć się tym bardziej dokładnie, nie miałem jeszcze nawet kontaktu z timerami czy przerwaniami, znam jedynie podstawy C++ i to wykorzystuję. Jak będę umiał więcej to z pewnością to poprawię. I teraz jak bardziej rozumiem ten temat to masz rację, wystarczyłoby wysyłać po prostu paczki lub przerwy i to by wystarczyło, ale użyłem już takiego kodowania bo myślałem że tak trzeba gdyż wszystkie tutoriale na internecie raczej już to kodowanie uwzględniały. Link do komentarza Share on other sites More sharing options...
marek1707 Marzec 29, 2016 Udostępnij Marzec 29, 2016 Nieprawda, nie brak Ci wiedzy i przenikliwości by wymyślić dobrą metodę odbioru przy pomocy narzędzi którymi dysponujesz. OK, nie stosujesz przerwań, timerów itp - fakt, to rzeczywiście pomaga, ale nawet na opóźnieniach możesz zrobić to lepiej lub gorzej. I właśnie o tym pisałem. Czasem drobna zmiana nie kosztująca nic oprócz dwóch minut główkowania może zmienić jakość rozwiązania z ledwo-ledwo działającego w bardzo dobre. Twój pomysł z próbkowaniem dokładnie w miejscu zmiany był beznadziejny. Żeby go poprawić wystarczyło zwiększyć (wyłącznie) pierwsze opóźnienie o 50% i wszystkie następne próbkowania zaczynały trafiać w połowę trwania płaskiego obszaru. To poprawiało radykalnie jakość próbkowania, ale wciąż wymagało dużej dokładności odmierzania czasu, bo suma 7 opóźnień musiała trafić w wąską połowę ostatniego bitu. Na pewno doświadczalne dobranie opóźnienia jest wtedy jakimś wyjściem, ale i tak jest to rozwiązanie dla tych dwóch sztuk procesorów, tego zasilania i tych temperatur - czyli marne. Zmiana na synchronizację co bit poprawia to kilkukrotnie, bo radykalnie zmniejsza wymagania na precyzję opóźnień. Zamiast tego wszystkiego Ty powiększyłeś wszystkie opóźnienia - wybrałeś wyjście najgorsze z możliwych. Rozumiesz? Nie musisz używać wyrafinowanych rozwiązań by poprawiać tak proste rzeczy. Minuta myślenia + 10 minut kodzenia + 30 minut testowania = pewnie działający odbiornik. Moim zdaniem warto. A jeśli chcesz przesyłać naprawdę proste informacje (który przycisk z kilku) to możesz wysyłać np. jeden impuls o różnej długości (i mierzyć jego długość), kilka identycznych impulsów blisko siebie (i liczyć ich liczbę) itd. A gdy już wchodzisz w transmisje takie jak zrobiłeś (kodowanie bifazowe jest wprost idealne dla odbiorników IR takich jak TSOP), warto pokusić się o jakąś kontrolę, np. wysyłać 8 bitów danych (czyli dodajesz z przodu dziewiąty bit startu np. zawsze = 1) w tym tylko 4 informacyjne - numer przycisku? Pozostałe 4 mogą być np. negacją tych 4 "ważnych". Jeśli odbierzesz bajt nie spełniający tego warunku to wiesz, że na pewno po drodze zdarzyło się coś złego i nie interpretujesz tego jako poprawnej informacji. Oczywiście dokładna analiza długości i położenia impulsów jest jeszcze lepsza i ładnie uzupełnia wykrywanie błędów na wyższych warstwach. Wygląda, że dużo ciekawej pracy przed Tobą 🙂 BTW: TSOP2236 na pewno nie działa odwrotnie. Jeżeli przy założeniu odwrotnej pracy Twój kod odbiera dobre ramki, to coś bardzo niedobrego tam się dzieje i wygląda, że nie panujesz nad pracą programu - jednego bądź drugiego. Przyjrzyj się temu, być może różnica opóźnień jest taka, że trafiasz w zupełnie inną strefę czasu nadawania bitów niż Ci się wydaje. 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ę »