Jestem zwolennikiem łączności przewodowej tam gdzie to możliwe i uzasadnione. Dlatego, tam gdzie się da, stosuję skrętkę zamiast wifi. Natomiast chcąc zbudować budżetową instalację automatyki domowej w istniejącym budynku czasem warto rozważyć systemy radiowe, tym bardziej, że są sprawdzone i tanie. Tanie? Tak, bo nie mówię tu o bezprzewodowych systemach inteligentnego domu, tylko o popularnych sterownikach działających na częstotliwości 433,92MHz.
Dawno temu pisałem o zestawie gniazdek na pilota, które do tej pory z powodzeniem stosuję do sterowania świąteczną iluminacją. Od tego czasu wiele się zmieniło, a wśród radiowych elementów różnych producentów można znaleźć wiele ciekawych urządzeń. Wśród odbiorników, poza opisywanymi już wtykanymi „gniazdkami”, możemy znaleźć gniazdka pasujące w tradycyjne puszki, oprawki do żarówek, przekaźniki pasujące do puszek, sterowniki żaluzji czy nawet sygnalizatory akustyczne (z zestawów dzwonków bezprzewodowych). Natomiast nadajniki to już nie tylko proste piloty, ale także zwykłe przyciski ścienne, czujniki ruchu (do puszek i zewnętrzne) czy czujniki otwarcia drzwi.
Co więcej, nawet producenci tych urządzeń dostrzegli trendy i zaczęli oferować namiastkę „inteligentnych domów”. Wielu z nich oferuje sterowniki, które łączymy z siecią domową, czy to za pomocą ethernetu czy też wifi, aby z poziomu aplikacji w smartfonie móc sterować urządzeniami elektrycznymi bądź programować ich czasowe włączenia i wyłączenia. Mnie to bardzo cieszy, bo za umiarkowaną (mniej lub bardziej) cenę można zacząć budowę swojej instalacji automatyki domowej. Każde z rozwiązań ma jednak wady. Poza oczywistym uzależnieniem się od urządzeń jednego producenta, głównym grzechem projektantów jest założenie, że wszyscy chcą sterować urządzeniami za pośrednictwem smartfona. A przecież to bardzo niepraktyczne. Inteligentny dom musi być sterowany na podstawie stanów różnych czujników i wiele rzeczy ma działać bez udziału mieszkańców. Czy przykładowo ręczne sterowanie cyrkulacją ciepłej wody ma sens? Albo codzienne ręczne zapalanie światła przed domem po zmroku? Nie, to ma się dziać automatycznie – gdy ktoś potrzebuje ciepłej wody lub zależnie od godziny zachodu słońca, a może dopiero gdy ktoś otworzy drzwi lub goście zadzwonią domofonem.
Co więc powinni zrobić producenci systemów radiowych i sieciowych sterowników do nich? Udostępnić dokumentację protokołu, który pozwoliłby przekazywać polecenia i odczytywać stany czujników przez, istniejący już, system inteligentnego domu. Być może ten rynek nie jest jeszcze wystarczająco duży, ale przecież to teraz jest czas walki o zyskanie przewagi nad konkurentami, która może później procentować. A kto, jak nie osoby budujące swoje systemy, jest w stanie najlepiej wypromować wiodące rozwiązanie?
Sterownik IP do urządzeń na 433MHz
Oczywiście nie ma co czekać na producentów, skoro można działać samemu. Nic nie stoi na przeszkodzie, żeby zaprojektować urządzenie, który pozwoli sterować urządzeniami, niezależnie od producenta. Będzie ono się także bardzo łatwo integrować z systemem inteligentnego domu, ale także sterować przez smartfona (tak, to czasem też się przydaje). Projekt, tak jak w przypadku termometru wifi, będzie kompleksowy – od idei, przez projekt elektroniki, obudowę wydrukowaną na drukarce 3d, po oprogramowanie.
Sterownik będzie oparty o Arduino Pro Mini oraz moduł ethernetowy z układem w5100 (jak Ethernet Shield do Arduino, tylko mniejszy). Za nadawanie i odbiór sygnałów radiowych na 433,92MHz będą odpowiedzialne dwa proste i bardzo tanie układy – nadajnika (MX-FS-03V) i odbiornika (MX-05V).
Projekt elektroniki
Rozpocząć należy od zaprojektowania płytki drukowanej, choć połączenia są na tyle proste, że na płytce uniwersalnej czy w formie „pająka” także bez problemu dałoby się to zrealizować. W tym wypadku jednak przygotujemy płytkę, na której zamocowane będzie Arduino, moduły radiowe i układ zasilania. Taka płytka będzie stabilnie umieszczona w obudowie. Schemat elektryczny jest prosty.
Górna sekcja to zasilanie – gniazdo zasilacza, stabilizator 5V oraz potrzebne kondensatory. Po środku serce układu – Adruino Pro Mini. Złącza goldpin J5 i J6 będą mogły służyć do podłączenia do urządzenia fizycznych przycisków, jeżeli zajdzie kiedyś taka potrzeba. Na dole mamy złącza: J1, które wyprowadza piny do modułu ethernet, J3 odpowiada za nadajnik 433Mhz, a J4 – za odbiornik. Jak widać układ jest bardzo prosty. Przekłada się to na nieskomplikowaną płytkę drukowaną.
Elementów do lutowania nie ma zbyt wielu. Dodane są otwory do przykręcenia płytki, natomiast podpory pokrywki obudowy będą także trzymać płytkę na miejscu. Na pewno nie można zapomnieć o połączeniu pól masy. Można by tego uniknąć przygotowując płytkę dwustronną, ale taka jest tańsza.
Obudowa
Obudowę można zaprojektować w bezpłatnym programie OpenSCAD. Przypomina to bardzo programowanie, tylko w przestrzeni, więc pewnie będzie to bardzo odpowiadać programistom.
Obudowa ma miejsce na zaprojektowaną wcześniej płytkę PCB i moduł komunikacji Ethernet. W obudowie są otwory na gniazdo zasilania i port ethernet. W pokrywce dodatkowo będzie mała kratka wentylacyjna nad stabilizatorem napięcia. Projekt można przygotować do druku w Repetier Host.
Do wydruku tym razem użyłem filamentu PLA produkcji Devil Design. Dlaczego? Bo tym razem zależało mi, żeby obudowa nie była przezroczysta, a poza tym teraz opanowuję druk z tego surowca, posiłkując się lekurą forum. Ostatnio eksperymentuję z chłodzeniem wydruku, ale to temat na inny wpis. W każdym razie wydruk wyszedł odpowiedni.
Komunikacja i bezpieczeństwo
Temat komunikacji warto zacząć od łączności radiowej. Popularne systemy używają jednego z dwóch sposobów kodowania sygnału. Oba są „rozumiane” przez odbiornik, którego używamy przy wsparciu biblioteki dla Arduino. Od strony programistycznej komunikacja polega na wysłaniu lub odebraniu jakiejś liczby – ciągu bitów o określonej długości (zwykle 24 lub 32). Przy czym na naszym poziomie nie jest istotne w jaki sposób sygnał jest przekazywany i dekodowany, interesuje nas wyłącznie ta liczba, jej długość w bitach i informacja o użytym protokole. Dla włączanego urządzenia także istotna jest liczba, a właściwie dwie liczby – jedna włącza, druga wyłącza urządzenie.
Oczywiście osobnym tematem jest analiza tego, jakie liczby mogą być użyte to zaprogramowania danego urządzenia (bo część urządzeń można parować z pilotami, a część posiada kody/liczby przypisane na stałe). Natomiast ponieważ nie chcemy przywiązywać się do żadnego producenta, nie będziemy tego analizować (w razie czego takie informacje można znaleźć w Internecie). Założymy, że znamy kody, a raczej skupimy się na podsłuchiwaniu pilotów, co w zupełności wystarczy.
Gdy już jesteśmy przy podsłuchiwaniu, warto wspomnieć o bezpieczeństwie. Systemy ze stałymi kodami nie są odpowiednie do sterownia procesami, od których zależy bezpieczeństwo. Nie mam żadnych oporów, żeby użyć tego systemu do zapalenia gdzieś światła, może nawet podniesienia rolet, które i tak nie są antywłamaniowe, natomiast na pewno nie otwierałbym w ten sposób bramy garażowej – dlatego sterowniki bram używają zmiennych kodów.
Wiemy już, że same kody transmitowane w sposób umożliwiający podsłuchanie, co określa zakres użycia tej klasy tanich systemów bezprzewodowych, ale też definiuje nasze podejście do bezpieczeństwa od strony sieciowej. Ponieważ będziemy sterować urządzeniami przez IP, trzeba zastanowić się na wyborem protokołu. W moim odczuciu najbardziej adekwatne będzie użycie pakietów UDP (transmisji bezpołączeniowej), która ze swej natury jest podobna do sygnałów radiowych – będziemy wysyłali ciąg znaków, bez oczekiwania na potwierdzenie odbioru. Nie ma specjalnie sensu zabezpieczanie połączenia przez szyfrowanie, skoro dużo prościej niż dostać się do lokalnej sieci jest nadać, choćby z zewnątrz podsłuchany sygnał radiowy. Oczywiście w razie potrzeby można rozważać zabezpieczenia na różnym poziomie, choćby prostą weryfikację adresu IP nadawcy.
Przyjmijmy więc, że do komunikacji będziemy używać ciągów trzech liczb rozdzielonych kropkami. Pierwsza liczba będzie określała protokół (1 lub 2), kolejna długość liczby (zwykle 24 lub 32 bity), a ostatnia będzie już właściwym kodem (np. 2.24.5555). Nasze urządzenie po odebraniu sygnału radiowego powinno go dekodować i wysyłać pakiet UDP do serwera automatyki domowej. Z drugiej strony urządzenie po odebraniu pakietu, powinno wysłać odpowiedni pakiet w eter. Żeby jednak wykryć ewentualne nieautoryzowane wysłanie kodów przez sieć, po nadaniu kodu zostanie także wysłany pakiet do serwera.
Dzięki takiej konstrukcji będziemy mogli zarówno odczytywać stan nadajników (np. wciśnięcia przycisku na pilocie czy wykrycia ruchu przez czujnik), jak również sterować urządzeniami bez użycia pilota (np. zapalić światło przed domem czy w korytarzu).
Programowanie Arduino
Mamy już sprzęt, wiemy jak ma się komunikować, można więc przejść do stworzenia programu, który będzie realizował te funkcje. Do obsługi nadajnika i odbiornika użyjemy biblioteki RCSwitch, która zapewni kodowanie i dekodowanie sygnałów radiowych. Do obsługi modułu ethernetowego dołączamy standardową bibliotekę Arduino używaną do obsługi Ethernet Shield, która z kolei wymaga biblioteki SPI, bo tym interfejsem komunikują się oba układy. EthernetUdp odpowiada za transmisję datagramów (pakietów UDP). Na sztywno określimy adres serwera automatyki domowej (zmienna master) oraz oczywiście naszego urządzenia (zmiennna ip). Zmienne localPort i remPort określają, na jakich portach będzie odbywać się komunikacja.
#include <RCSwitch.h> #include <SPI.h> #include <Ethernet.h> #include <EthernetUdp.h> RCSwitch mySwitch = RCSwitch(); byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xF7, 0xAE }; IPAddress ip(192, 168, 1, 250); IPAddress master(192,168,1,2); unsigned int localPort = 8000; // local port to listen on unsigned int remPort = 8000; char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet, EthernetUDP Udp; void setup() { mySwitch.enableReceive(0); // interrupt 0 - pin 2 mySwitch.enableTransmit(3); // pin 3 Ethernet.begin(mac, ip); Udp.begin(localPort); } String str; char cstr[19]; void loop() { int mProtocol; int mSize; unsigned long mValue; int packetSize = Udp.parsePacket(); //przyszły jakieś dane przez sieć if (packetSize) { IPAddress remote = Udp.remoteIP(); if( remote[0]!=192 ) { //tu można dodać autoryzację po adresie źródłowym } Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE); //pobieramy wartości z ciągu znaków mProtocol=packetBuffer[0]-48; mSize=packetBuffer[3]-48+10*(packetBuffer[2]-48); mValue=String(packetBuffer).substring(5, packetSize).toInt(); // wyłaczamy odbieranie kodów, żeby nie odczytywać wysłaego przez siebie mySwitch.disableReceive(); // wysyłamy polecenie radiowo mySwitch.setProtocol(mProtocol); mySwitch.send(mValue, mSize); // włączamy odbieranie ponownie mySwitch.enableReceive(0); // odsyłamy potwierdzenie wysłania Udp.beginPacket(master, remPort); str = String("P:"+String(mProtocol)+"."+String(mSize)+"."+String(mValue)+"..."); for(int w=0; w<19; w++) cstr[w]=0; String(str).toCharArray(cstr,19); Udp.write(cstr, 19); Udp.endPacket(); } //przyszły jakieś dane radiowo if (mySwitch.available()) { int value = mySwitch.getReceivedValue(); if (value == 0) { //nieznane kodowanie/błędny odczyt; } else { str = String(String(mySwitch.getReceivedProtocol())+"."+mySwitch.getReceivedBitlength()+"."+ String(mySwitch.getReceivedValue())); for(int w=0; w<19; w++) cstr[w]=0; str.toCharArray(cstr,19); // wysyłamy pakiet udp Udp.beginPacket(master, remPort); Udp.write(cstr, 19); Udp.endPacket(); } mySwitch.resetAvailable(); } }
W funkcji setup inicjujemy odbiornik i nadajnik, moduł sieciowy oraz inicjujemy nasłuch na porcie udp. Funkcja loop, będąca główną pętlą podzielona jest na dwie części. W pierwszej sprawdzamy czy przyszedł jakiś pakiet udp i go obsługujemy (dzielimy na liczby, wysyłamy sygnał radiowo i odsyłamy pakiet udp do serwera). W drugiej odczytujemy dane radiowe, jeżeli się pojawiły i wysyłamy pakiet udp do serwera. Jak widać program jest bardzo prosty, a wszelkie wątpliwości powinny rozwiać komentarze w kodzie.
Testy
Skoro mamy już urządzenie, trzeba je przetestować. Zakładając, że serwerem inteligentnego domu jest jakieś urządzenie z Linuksem, najłatwiej użyć polecenia netcat (oczywiście nic nie stoi na przeszkodzie, żeby na początek był to zwykły komputer). Aby wypisać na ekranie wszystkie pakiety, które przychodzą na port 8000 należy wywołać polecenie:
netcat -ul 8000
Jeżeli wszystko działa poprawnie, a w kodzie podaliśmy jako adres serwera urządzenie, na którym wykonaliśmy powyższe polecenie, to wciskając przyciski pilota radiowego powinniśmy otrzymać informacje typu:
1.24.333101
Jest to odczytany kod pilota. W takim wypadku wysłanie takiego kodu przez udp do naszego urządzenia powinno być równoznaczne z wciśnięciem przycisku na pilocie. To także można zrobić używając polecenia netcat.
printf "2.24.333101" | netcat -u 192.168.50.25 8000
Na co urządzenie powinno też przesłać do serwera potwierdzenie nadania sygnału radiowego:
P:1.24.333101
Przy takich wynikach możemy uznać, że wszystko działa jak trzeba.
Zasięg
Dla systemów radiowych to kluczowe zagadnienie. Jak jest w tym przypadku? I dobrze i słabiej. Dobrze, bo nadajnik, nawet bez użycia anteny, ma zasięg pozwalający na sterowanie urządzeniami w całym domu. Słabiej, bo zasięg odbiornika nie zadowala mnie w pełni. Bez problemu mogę odczytać dowolne sygnały nadane w pomieszczeniu, w którym jest urządzenie, nie powinno być problemów z nadajnikami znajdującymi się za ścianą, ale o odczytaniu kodów nadanych z odległego zakątka domu można zapomnieć. Rozwiązaniem prawdopodobnie będzie użycie nieco (ale tylko nieco) droższego odbiornika, jeżeli ktoś ma taką potrzebę lub eksperymenty z zewnętrzną anteną. Ja na razie potrzebuję tylko nadawania, a odczytu jedynie do podsłuchania kodów pilotów, z czym nie ma żadnych problemów. Oczywiście inny odbiornik przetestuję gdy do mnie dotrze.
Co dalej?
W następnej kolejności trzeba użyć sterownika w praktyce i podłączyć go do istniejącego systemu inteligentnego domu. Przy następnej okazji opiszę praktyczną realizację sterowania włączaniem światła przed domem.
A nie wiesz jaki może być zasięg takiego pilota na otwartym terenie? Czy wszystkie piloty danego producenta wysyłają ten sam kod? I nie da się rozpoznać, który pilot nadał sygnał? Szukam jakiegoś rozwiązania, aby kilka osób mogło przesyłać prostą informację (liczby od 0 do 5) do elementu centralnego. Przy czym muszę wiedzieć kto co wysłał, a odległość może wynosić do 150 metrów w otwartym terenie. Czyli albo jakieś piloty, ale musiałyby mieć jakiś kod identyfikujący je. Albo prosty układ oparty na arduino + układ radiowy (np. HC-12).
Każdy producent podaje taki zasięg. W przypadku Conrad RSL jest to 70m. Natomiast, jak pisałem, dużo zależy od czułości odbiornika, która w tym przypadku nie jest szczególnie dobra.
Jeżeli chodzi o kody, to tak, każdy pilot nadaje inne kody i da się je odróżnić.
Dziękuję bardzo za informację. Czyli 70m jest przy dobrym odbiorniku? Czy dobrym odbiornikiem można ją zwiększyć?
Bo jeśli chodzi o zastosowanie, to problem mam następujący: Na naszych zawodach łucznictwa konnego mamy w jednej konkurencji kilka tarcz, pomiędzy którymi jedzie zawodnik, strzelając do każdej. Dotąd zapisywaliśmy wyniki na kartkach, ale chcielibyśmy je zbierać od razu. Dotąd myślałem o prostym urządzeniu: Arduino Mini Pro 3.3V + 3 AA (lub 186500) + HC12 + prosta klawiatura, aby wysłać wynik. Ale może tego typu nadajnik się nada, będzie prostszym i wygodniejszym rozwiązaniem? A HC12 zostaje mi tylko do mierzenia czasu (Arduino z fotokomórką i HC12 do wyliczenia czasu przejazdu). Bo różne kody pilotów pozwolą mi odróżnić sygnały dla poszczególnych tarcz.
Gdy czytam „zawody”, to wyczuwam, że musi być bardzo niezawodne i odporne na awarie systemu i wstrzykiwanie nieautoryzowanych wyników. Czyli według mnie wchodzi w grę komunikacja dwustronna i buforowanie wysyłania wyników w razie problemów. Może więc coś na ESP8266, które mają w otwartym terenie całkiem dobry zasięg. Do tego jakiś router z OpenWRT do zbierania wyników i do przekazywania do Internetu? ESP8266 są dość wymagające jeżeli chodzi o energię, ale zawody nie trwają przecież miesiąc, tylko raczej pojedyncze godziny?
To raczej takie nasze „podwórkowe”, przyjacielskie zawody – a nie żadne profesjonalne. Nie musi być jakoś bardo niezawodne i odporne na awarie – bo w razie czego mamy papierowe wersję wyników. No i nie należy się spodziewać jakichś prób oszustwa – nie na takich koleżeńskich zawodach.
Co do wyników to zakładałem, że komunikacja jednostronna powinna wysterczać ale jak się tak teraz nad tym zastanawiam, to może rzeczywiście lepiej dodać potwierdzenia… a może nawet backup wyników w EEPROM? Komunikację dwustronną mam między elementem centralnym a bramkami do mierzenia czasu – tam sobie zaimplementowałem mechanizm potwierdzeń i retransmisji. No i zastosowałam właśnie HC-12, jako prostsze do użycia niż WiFi, które wymagają routera, wcześniejszego połączenia, bardziej zaawansowanego protokołu. Cóż, będę musiał chyba jeszcze parę rzeczy przemyśleć. W każdym razie dzięki za pomoc 🙂
To jeszcze pytanie – a czemu nie smartfon?
Projekt obudowy można znaleźć pod adresem http://www.thingiverse.com/thing:1849422
Poprawiłem kod programu. Błąd powodował wysyłanie złego kodu, jeżeli był krótszy niż poprzednie.