Jak przystosować domowego pilota do własnych celów?

Jak przystosować domowego pilota do własnych celów?

W amatorskich konstrukcjach często można spotkać się z wykorzystaniem pilotów. Dzięki nim możliwe jest np. zdalne uruchamianie lub sterowanie robotem.

W artykule opisałem, jak przystosować pilota do współpracy z własnymi robotami. Opis na przykładzie zmagań z pilotem firmy Philips.

W artykule Różne zastosowania podczerwieni – przegląd rozwiązań wspominałem, że mam zamiar opublikować więcej materiałów. W tym tekście postaram się wykorzystać zebrane informacje w praktyce. W artykule zostanie wykorzystany oscyloskop stworzony w domowych warunkach, który może okazać się przydatny również do innych zastosowań.

W amatorskich konstrukcjach nieraz można spotkać się z zastosowaniem pilota. Dzięki niemu możemy uruchamiać swojego robota z pewnej odległości (przydatne na zawodach), przełączać tryby pracy albo po prostu zdalnie nim sterować. Praktycznie wszystkie tego typu konstrukcje korzystają z pilotów w standardzie RC5. Nic dziwnego, w końcu Atmel udostępnił gotowy program do odczytywania tego kodu.

Ostatnio, gdy sam miałem potrzebę zastosowania sterowania na pilota, mój wybór także padł na RC5. Poszedłem na giełdę i kupiłem za 2 zł pierwszy lepszy pilot Philipsa (wcześniej gdzieś przeczytałem, że większość pilotów tej firmy korzysta z RC5, a po co przepłacać i czekać na dostawę w internecie). Oczywiście nie trudno się domyślić, że zakupiony sprzęt nie działał tak, jak bym tego oczekiwał. Postanowiłem nie poddawać się i rozkodować nowo nabytego pilota. Wynikami swojej pracy dzielę się na łamach tego artykułu.

Jak rozpoznać standard nadawania?

Pierwszym krokiem było poznanie istniejących sposobów kodowania. Co nieco napisałem o nich w poprzednim artykule. Dowiedziałem się, że istnieją dwa główne sposoby kodowania -manchester i kodowanie długością impulsu.

Poza tym kody pilotów pracują na różnych częstotliwościach, takich jak:

  • 36kHz
  • 38kHz
  • 40kHz
  • 56kHz

Niektóre starsze rozwiązania w ogóle nie używają modulacji częstotliwościowej. Do odczytania zmodulowanego sygnału używane są scalone dekodery, takie jak popularne TSOPy. Różne modele tego układu zostały stworzone do odczytywania popularnych częstotliwości kodowania. Poniżej tabela modeli TSOP22xx Vishaya:

PodczerwienPilot_1

Należy pamiętać, że czujnik odbiera pewien zakres częstotliwości w otoczeniu nominalnej.

Zwykle jest to zjawisko negatywne, ponieważ możemy w ten sposób odbierać zakłócenia z innych pilotów. W tym jednak wypadku, jest to zjawisko pożądane, ponieważ łatwiej będzie nam odczytać ramkę danych z pilota, nie dysponując dokładnie tym modelem czujnika, co trzeba. Poniżej wykres z noty katalogowej tego samego czujnika TSOP22xx, obrazujący siłę generowanego sygnału przez poszczególne częstotliwości w odniesieniu do nominalnej:

PodczerwienPilot_2

Ważne jest odpowiednie filtrowanie zakłóceń w takim czujniku. Najlepiej postępować zgodnie z zaleceniami producenta. Poniżej schemat sugerowany przez producenta czujników TSOP:

PodczerwienPilot_3

Zaczynamy testy

Pierwszym zadaniem jest więc określenie, na jakiej częstotliwości działa nasz pilot. Możliwe, że jest na to łatwiejszy sposób, ja jednak wybrałem dość toporne rozwiązanie. Postanowiłem zbudować na płytce stykowej prosty układ z czujnikiem, mikrokontrolerem i kilkoma diodami:

Schemat układu

Schemat układu

Układ ten będzie potrzebny praktycznie do wszystkich testów. We wszystkich programach używam wewnętrznego rezonatora 4MHz. Przewidziałem w schemacie wyjście UARTa, co będzie później bardzo przydatne przy debugowaniu.

Napisałem prosty program, który ma zwiększać wartość wyświetlaną na LEDach za każdym razem, kiedy wykryje stan wysoki na wejściu czujnika. Liczyłem, że pilot będzie pracował na 36kHz, co okazało się zgodne z prawdą. W przeciwnym wypadku musiałbym testować czujniki na inne częstotliwości.

Duże koncerny posiadają wiele standardów kodowania i używają nieraz kilku częstotliwości, np. Sony używa czasem częstotliwości 40kHz. Może testowana przeze mnie próbka nie była reprezentatywna, ale kody wszystkich pilotów jakie miałem można było odczytać za pomocą czujnika TSOP2236.

Interpretacja ramki danych

Kiedy już wiemy, że dysponujemy czujnikiem odczytującym dane z pilota, możemy przejść do głównego punktu programu. Naszym zadaniem będzie rozszyfrowanie ramki danych z pilota oraz określenie kodu poszczególnych przycisków.

Prosty oscyloskop

Do śledzenia przebiegów generowanych przez czujnik najlepiej użyć oscyloskopu. Tutaj pojawia się poważny problem. Profesjonalne oscyloskopy są bardzo drogie i mało kto może sobie na nie pozwolić. Jednak rozwiązanie jest prostsze, a przede wszystkim tańsze niż mogłoby się wydawać. Jedyne czego potrzebujemy to... starego kabla od słuchawek. Poza tym musimy zainstalować program Soundcard Oscilloscope. Dzięki niemu możemy używać przetwornika analogowego-cyfrowego naszej karty dźwiękowej jako wejścia oscyloskopu, natomiast przetwornika cyfrowo-analogowego jako generatora przebiegów.

Program umożliwia również tworzenie wykresów XY oraz śledzenie przebiegów w dziedzinie częstotliwości. Kabel od słuchawek przecinamy w odległości kilkudziesięciu centymetrów od wtyczki tak, aby można go było łatwo podłączyć do komputera i płytki testowej. Następnie ręką rozdzielamy dwie żyły i nożykiem zdejmujemy z każdej z nich izolację.

W każdej żyle powinna się znajdować kolejna warstwa izolacji, zawierająca przewód sygnałowy oraz nieizolowany przewód masy.

Wtyczka natomiast zawiera wyprowadzenia zgodne z poniższym obrazkiem:

PodczerwienPilot_5Na odsłonięte nożem przewody warto założyć drucik i rurkę termokurczliwą. W ten sposób otrzymamy prowizoryczną sondę oscyloskopu.

Używanie oscyloskopu

Domyślnym wejściem naszego oscyloskopu jest gniazdo mikrofonu, natomiast wyjściem generatora jest gniazdo słuchawkowe. Karta dźwiękowa jest przystosowana do generowania/odbierania przebiegów o częstotliwościach z zakresu słyszalności ludzkiego ucha, czyli w zakresie około 20-22000 Hz. Obsługa programu jest bardzo prosta.

Poniżej okno główne:

PodczerwienPilot_6

Pokrętłami Amplitude i Time skalujemy osie, za pomocą wartości Offset przesuwamy wartość początkową przebiegu na osi Y dla poszczególnych kanałów. W ramce Trigger możemy ustawić tryby wyzwalania. Dostępne opcje to:

  • Auto - przebieg jest wyświetlany cały czas na ekranie, nawet jeśli nie zostanie przekroczony próg wyzwalania.
  • Normal - za każdym razem, gdy próg zostanie przekroczony, pojawia się nowy przebieg.
  • Single - po wciśnięciu przycisku Run/Stop wyświetlany jest pierwszy przebieg po przekroczeniu progu wyzwalania.

Niżej można wybrać kanał, dla którego ustalamy warunki wyzwalania, rosnące lub opadające zbocze przebiegu (edge) oraz próg (threshold), jaki musi przekroczyć zbocze, aby zostało zarejestrowane przez oscyloskop.

W lewym dolnym rogu wykresu pojawia nam się przycisk Save, który zapisuje przebiegi zarówno w formie obrazka, jak i pliku csv. Dzięki temu dane z oscyloskopu można następnie analizować za pomocą przeznaczonych do tego programów.

Niektórzy mogą się dziwić, jak sprzętem odbierającym częstotliwości do 22kHz mamy zbadać sygnał o częstotliwości 36kHz.

Dlatego właśnie za pomocą oscyloskopu z karty dźwiękowej można również bez problemu zbadać przebiegi zmodulowane częstotliwością 56kHz.

Pomiary

Po podłączeniu czujnika zgodnie z zaleceniami producenta oraz poprowadzeniu wyjść OUT i GND do sondy oscyloskopu, mogłem rozpocząć badanie przebiegów. Oscyloskop ustawiłem w trybie single, a próg wyzwalania podniosłem na tyle, aby nie łapał śmieci. Poniżej przebieg dla klawisza "1":

PodczerwienPilot_7

Jedna rzecz nieco mnie zdziwiła. Otóż TSOP2236 domyślnie wskazuje stan wysoki, a do niskiego przechodzi kiedy otrzymuje daną. Z wykresu na oscyloskopie wynika natomiast, że jest odwrotnie. Po szybkim sprawdzeniu za pomocą miernika doszedłem do wniosku, że oscyloskop pokazuje odwrócone wartości.

Nie wiem, dlaczego tak się dzieje. Trzeba pamiętać, że to tylko prosta namiastka prawdziwego oscyloskopu, więc należy sobie jakoś radzić. W końcu czasy trwania poziomów logicznych są ok, a zmiana polaryzacji nie jest specjalnie kłopotliwa.

Dla porównania zapisałem przebiegi dla przycisków 2, 3, 4:

Interpretacja oscylogramów

Jak widzimy na przebiegach, każdy sygnał zaczyna się od dwóch długich impulsów. Następnie jest kilka dużo krótszych i kolejny długi. Do tego momentu każda ramka danych wygląda tak samo.

Różnią się dopiero ostatnią serią krótkich impulsów. Jeżeli porównamy te obserwacje ze znanymi kodami do pilotów, możemy dojść do wniosku, że początkowe długie sygnały służą do inicjalizacji. Następna seria krótkich impulsów to kod systemu, dlatego jest identyczny dla każdego przycisku.

Ostatnia seria krótkich impulsów, która jest różna dla każdego przycisku musi zawierać kody komend. Długości poszczególnych ramek różnią się od siebie, więc mamy do czynienia z kodowaniem za pomocą długości impulsu. Przyjrzyjmy się teraz seriom krótkim.

Jak widać, składają się z 9 stanów niskich (pamiętamy o wadzie oscyloskopu) o takiej samej długości oraz ośmiu stanów wysokich, których długość przybiera jedną z dwóch wartości. Nie wiemy, czy producent założył sobie dłuższy impuls jako 1 czy 0, ale tak naprawdę nas to nie obchodzi. Możemy przypisać te wartości po swojemu i odczytywać tak, jak nam wygodnie. Ja przyjąłem, że 0 to krótki sygnał, a 1 to długi.

Następnym krokiem jest poznanie dokładnych zależności czasowych. W tym celu posłużyłem się Matlabem, ale nada się do tego każdy program do obróbki danych, nawet zwykły Excel. Wyznaczyłem punkty początku i końca każdego rodzaju impulsu i obliczyłem czasy ich trwania. Operację powtórzyłem na kilku przebiegach aby mieć pewność, że nie popełniłem błędu. Następnie odczytałem kody każdego przycisku i zapisałem sobie wszystkie informacje o moim pilocie:

Częstotliwość modulacji: 36kHz
Ramka danych:

  • bit startu 1: 8ms LOW
  • bit startu 2: 4ms HIGH
  • osiem bitów systemu
  • bit przerwy: 4ms HIGH
  • osiem bitów komendy
  • koniec informacji: HIGH do otrzymania kolejnej ramki

Kodowanie bitów systemu i komendy:

  • sygnał low: 422us
  • sygnał high "0": 422us
  • sygnał high "1": 1.6ms

Między ósmym bitem danych, a przerwą lub końcem występuje jeszcze jeden sygnał low 422us. 

  • kod systemu: 11000011

Lista komend:

  • 0 - 11110000
  • 1 - 01001000
  • 2 - 01101000
  • 3 - 10011000
  • 4 - 00100000
  • 5 - 00110000
  • 6 - 00011010
  • 7 - 01110000
  • 8 - 10010000
  • 9 - 00111000
  • power - 00011000
  • mute - 01011000
  • prog - 01100000
  • audio - 11101000
  • sys - 01010000
  • lnb - 10111000
  • up - 11011000
  • down - 11001000
  • left - 01000000
  • right - 00111001
  • store - 11111000
  • next - 10101000
  • fav - 10001000
  • hv - 11010000
  • tone - 01111000
  • radio - 00000000
  • tvsat - 10100000
  • lock - 00101000

Dla pewności postanowiłem jeszcze sprawdzić przebiegi za pomocą prostego programu, napisanego w asemblerze, wykorzystującego USART do kontroli poprawności odczytywanych danych. Jego zadaniem jest odczytanie stanu pinu w przerwaniu timera, dodanie go do bufora odczytu, a po uzbieraniu ośmiu bitów wysłanie ich do PC.

Co ciekawe, wcześniej próbowałem sprawdzać pin w pętli, a nie w przerwaniu lub używać przerwania zewnętrznego, a nie timera. Okazywało się wtedy, że wartość przy zmianie przez jakiś czas oscyluje, powodując efekt podobny do drgania styków przy switchach, tylko oczywiście trwający o wiele krócej.

Na szczęście sprawdzanie w przerwaniu timera co 64us całkowicie wyeliminowało ten problem, a na odczycie z terminala wyniki są zgodne z oczekiwaniami. Oto odczyt z terminala w kodzie szesnastkowym dla jednej ramki danych:

Poszczególne fragmenty przebiegu z oscyloskopu można łatwo dopasować do odpowiadających im ciągów zer i jedynek na terminalu. Dzięki temu mam pewność, że mikrokontrolerowi uda się odczytać ramkę danych bez żadnych zakłóceń. Poniżej kod programu w asemblerze. Jeśli ktoś nie zna tego języka, to i tak nie powinien mieć problemu ze zrozumieniem dzięki komentarzom i dokumentacji Atmela:

Program dekodujący

Teraz kolej na napisanie pełnego kodu do dekodera pilota. Tutaj po raz kolejny wybrałem asemblera z kilku powodów. Po pierwsze, będzie to prosta aplikacja, wykorzystująca głównie operacje na rejestrach, a takie pisze się w asemblerze bardzo przyjemnie.

Po drugie, będę mógł dokładnie prześledzić działanie programu w debuggerze AVR Studio 4 i szybciej znaleźć ewentualne błędy. Ponadto, podczas pisania mogę ściągnąć niektóre fragmenty z noty aplikacyjnej Atmela, dotyczącej RC5. Pod spodem gotowy kod z opisem w komentarzach:

Po napisaniu części odczytujących kolejne fragmenty ramki, warto dopisać linijki zapalające diody, w celu sprawdzenia, czy wszystko robimy poprawnie.

Łatwiej debugować na bieżąco, niż później męczyć się z szukaniem błędów. Mój program przeszedł właśnie taki proces debugowania, co pozwoliło mi dość szybko uporać się z nim.

Program działa bez zarzutu, wykrywa wszystkie kody przycisków dokładnie tak, jak w opisanej wyżej specyfikacji. Ma on jednak pewne wady. Mimo korzystania z przerwań, dalej używane jest również odpytywanie w pętli. Poza tym trudno byłoby używać go jako funkcji w innym programie, jeżeli każde odczytanie przycisku zajmowałoby kilkadziesiąt milisekund, podczas których procesor nie może się zajmować niczym innym.

W większych projektach asembler jednak nie jest tak poręczny i przydałoby się również dysponować kodem w C. Dlatego właśnie napisałem bibliotekę danego pilota w tym języku. Mogę jej teraz z powodzeniem używać jako fragment większego projektu.

Biblioteka w C

Wykonuje ona wszystkie operacje w przerwaniu. Mimo że przerwanie wydaje się bardzo rozbudowane, składa się z wielu instrukcji warunkowych i tak naprawdę każda możliwa ścieżka wykonuje się dość szybko.

Przerwanie jest zorganizowane jako zbiór stanów, w których aktualnie może się znajdować układ. Za każdym razem są w nim sprawdzane warunki przejścia do innego stanu i jeśli zostaną spełnione, przy następnym przerwaniu układ znajdzie się w kolejnym stanie. Oczywiście nie ma najmniejszego problemu, żeby przeskalować program dla innych wartości oscylatora.

Podsumowanie

Jak widać, za pomocą prostych narzędzi i odrobiny wiedzy dotyczącej kodowania pilotów, udało mi się przystosować do własnych celów sygnał z nieznanego pilota.

Stosując podobne techniki można uporać się z każdym innym kodowaniem. Na zakończenie przeanalizujmy jeszcze przebieg z innego pilota do telewizora, jaki akurat miałem w domu. Nie będę już się w niego zagłębiać, ale proces dekodowania przebiegałby podobnie jak wyżej.

Na przebiegach widać wyraźnie część z kodem systemu, 20ms przerwy i kod komendy.

Każda z części zaczyna się dwoma sygnałami inicjalizującymi. Poza tym widzimy, że wszystkie przebiegi są tej samej długości, czyli mamy do czynienia z kodowaniem Manchester.

W kodzie systemu wszystkie bity mają tę samą wartość, natomiast w kodach komend dobrze widać, które bity mają inne wartości. Dekodując kod typu Manchester warto posiłkować się notą dotyczącą kodu RC5.

Innym sposobem jest odczytywanie połówek bitów, a następnie programowa zamiana ciągów 01 i 10 na odpowiednie wartości. Zostawiam to już jednak do samodzielnych eksperymentów.

asm, C, osycloskop, philips, pilot, przerwanie, rc5