sobota, 11 marca 2017

"Inteligentny" dom na Raspberry PI

Jakiś czas temu opisywałem moje rozwiązanie automatyki domowej oparte na arduino i Raspberry PI
Polegało to mniej więcej na tym, że wszystkie przekaźniki którymi chciałem sterować, przełączniki z których odbierałem sygnały oraz czujniki temperatury z których korzystałem, podłączone były do arduino mega z ethernet shieldem. Za przechowywanie stanów poszczególnych urządzeń odpowiadało arduino. Na Raspberry PI zainstalowany miałem serwer MQTT. Arduino wysyłało wszystkie sygnały do MQTT skąd pobierał je sobie OpenHAB i udostępniał je użytkownikowi poprzez GUI web'owe lub aplikację mobilną. Dodatkowo OpenHab mógł przesyłać zdalne polecenia użytkownika do MQTT skąd odbierało je arduino i aktualizowało stan urządzeń domowych.

Rozwiązanie to miało jedną podstawową zaletę: działało :)
W trakcie użytkowania pojawiło się jednak kilka problemów o których już wspominałem w poprzednich postach. Były to między innymi:


  • skomplikowana architektura - w przypadku problemów było sporo miejsc do weryfikacji. 
  • problemy przy zanikach energii - w przypadku arduino z ethernet shield'em pojawiają się problemy z poprawnym wznowieniem pracy po zaniku energii. System potrafił zawieszać się przy starcie i konieczne było ręczne odłączenie od zasilania i ponowne uruchomienie. Czasami kilkukrotne. W internecie pojawiają się opisy takich przypadków. Niektórzy doradzają wrzucenie dodatkowego kondensatora pomiędzy PIN reset i GND (o ile dobrze pamiętam :) ), ale w moim przypadku niewiele to pomogło
  • samoczynne załączanie/wyłączanie urządzeń przy skokach napięcia. Tutaj przyczyny nie udało mi się namierzyć. Próbowałem podpinać urządzenia do dodatkowych stabilizatorów, ale nic to nie dało. Nie było to jakoś mocno uciążliwe, bo zdarzało się stosunkowo rzadko, ale jednak była to dość spora rysa na stabilności całego rozwiązania
  • niewygodne podłączanie urządzeń do arduino - podłączanie czujników i przekaźników bezpośrednio do PIN'ów arduino w przypadku "produkcyjnego" rozwiązania to generalnie bardzo słabe rozwiązanie. Co prawda rzadko po podłączeniu czegokolwiek się dotyka, ale arduino miałem w szafie razem z innymi urządzeniami do których co jakiś czas zaglądam i o rozpięcie czegoś było bardzo łatwo. Dorobiłem sobie co prawda dodatkową płytkę ze złączami śrubowymi do których wpiąłem urządzenia, ale i tak nie było to rozwiązanie komfortowe
  • problematyczne wprowadzanie zmian do systemu - dodanie nowego czujnika oprócz podpięcia sprzętu wymagało zmian w kodzie arduino, przenoszenia laptopa do garażu gdzie był hardware, podpinania po USB do arduino, programowania układu, testowania i w przypadku błędu powtarzania wszystkiego kilkukrotnie - niefajne :)
Po ponad dwóch latach korzystania z takiego systemu zacząłem zastanawiać się jak uprościć całą architekturę tak aby większość z powyższych problemów wyeliminować. Podświadomie czułem, że w tej sytuacji arduino jest zupełnie zbędne, że do wszystkiego w zupełności powinno wystarczyć Raspberry PI. Problemem jest jednak ograniczona liczba PIN'ów GPIO. 

W poprzednim wpisie Raspberry PI i dodatkowe piny GPIO na kilku układach mcp23017 oraz przełącznik na tranzystorze opisałem w jaki sposób można te problemy obejść. Pozostało jedynie zaprojektowanie odpowiedniego układu który spełniał będzie wszystkie moje wymagania, zapewniał elastyczność i możliwość dalszej rozbudowy, oraz płytki na której możliwe będzie wygodne  podpinanie urządzeń do Raspberry. Zdefiniowałem następujące wymagania:
  1. 16 cyfrowych wejść (obsługa do 16-tu przełączników)
  2. 16 cyfrowych wyjść (obsługa 16-tu urządzeń na zasadzie włącz/wyłącz)
  3. obsługa magistrali One Wire
  4. obsługa LIRC (sterowanie pilotem na podczerwień)
  5. łatwe i trwałe połączenie z Raspberry PI
  6. łatwe i trwałe podłączanie urządzeń i czujników
  7. dostęp do pozostałych PIN'ów GPIO
  8. możliwość obsługi urządzeń zasilanych różnym napięciem
Zadanie było dość czasochłonne, ale myślę że założony efekt udało mi się osiągnąć. Zrobiłem schemat i projekt w Eagle, zdecydowałem jednak że nie będę sam trawił płytki. Zamówiłem w jednej z firm oferujących taką usługę. Takie oto płytki otrzymałem:




To pierwszy prototyp, jak widać jeszcze nie do końca polutowany. 
Płytka zaprojektowana jest pod 40-pinowe złącze GPIO dostępne od Raspberry Pi 2.
W tym przypadku podłączenie jest bardzo wygodne i trwałe - za pośrednictwem 40-żyłowej taśmy wpinanej do Raspberry i do płytki.
Nic nie stoi jednak na przeszkodzie żeby podłączyć ją do starszej wersji RPI gdzie złącze było 26-cio pinowe. W tym przypadku jednak podłączenie musi być inne - na przykład przewodami female-female:


Podłączenie jest proste, ponieważ złącze na płytce odpowiada  portowi GPIO w Raspberry.

Płytka zawiera wszystkie elementy o których pisałem  w wymaganiach:

Teraz kilka słów wyjaśnienia i opis działania.
Płytkę należy podłączyć do portu GPIO Raspberry PI. Oprócz tego, należy podłączyć dodatkowe źródło zasilania DC. Zdecydowałem się na takie rozwiązanie ponieważ RPI ma zbyt małą wydajność prądową aby obsłużyć 16 urządzeń zewnętrznych które mogą mieć różne wymagania. Jak widać na zdjęciu na płytce mamy 16 tranzystorów. Wszystkie wyjścia zaprojektowane są jako klucze tranzystorowe. Układy MCP23017 załączają poszczególne tranzystory podając zewnętrzne zasilanie na poszczególne wyjścia. Z tego wynika bardzo ciekawa cecha - w zależności od tego jakie napięcie podamy jako zewnętrzne źródło zasilania, takie urządzenia będziemy mogli podpinać do wyjść. Przykładowo, podpinając płytkę do +5V będziemy mogli sterować przekaźnikami które wymagają 5V, podpinając płytkę do +12V będziemy na wyjścia mogli podpinać urządzenia 12-voltowe, na przykład taśmy LED. Jest tutaj jednak ograniczenie - wszystkie wyjścia muszą działać na tym samym napięciu. Kolejna cecha płytki pozwala jednak obejść to ograniczenie. Jak widać na płytce jest dodatkowe wyjście GPIO do którego teoretycznie można podpiąć drugą  taką samą płytkę. Wtedy jedną płytkę podpinamy do +5V a drugą do +12V. Mamy wtedy 16 wyjść +5V i 16 wyjść +12V. I tak dalej.... Do drugiej możemy podpiąć trzecią, do trzeciej czwartą :). Na każdej płytce trzeba jedynie za pomocą zworek zmienić adresowanie układów MCP23017. Ograniczeniem jest jedynie liczba adresów - 3 bity, czyli możemy obsłużyć 7 układów MCP - z czwartej płytki musielibyśmy wyjąć jeden układ MCP - są w podstawkach, więc nie ma problemu. Nie testowałem jeszcze takiego rozwiązania - nie mam tylu płytek :), ale teoria mówi że takie rozwiązanie powinno działać. Pozostało mi jeszcze do zbadania ograniczenie prądowe wszystkich podpiętych urządzeń - to jeszcze przede mną. Ze wstępnych obliczeń wynika, że do 2A powinno działać bez ryzyka przegrzania - to jeszcze będę badał.

Kolejna uwaga - na wyjścia można podpinać jedynie urządzenia które da się załączyć za pośrednictwem dwóch przewodów (plus i minus). Pozwala to na przykład załączać przekaźniki, ale tylko jednokanałowe. Mają one 3 piny. Podpinamy  minus do minusa, a plus z płytki jednocześnie do plusa i sygnału na przekaźniku. Dla mnie takie rozwiązanie jest wystarczające. Steruję jednokanałowymi przekaźnikami ukrytymi w puszkach ściennych. Sterowanie wielokanałowymi modułami przekaźnikowymi może być problematyczne, ponieważ mają one wspólne zasilanie dla wszystkich kanałów. Nad rozwiązaniem tego ograniczenia być może jeszcze popracuję, ale na razie nie widzę jakiejś większej potrzeby.

Na płytce jest 16 wejść cyfrowych. Są to zwykłe 2-pinowe złącza. Zwarcie pinów powoduje podanie napięcia +5V na odpowiedni kanał układu MCP23017 i stamtąd możemy odczytać stan przycisku.

Dodatkowo na płytce umieściłem 3-PIN'owe złącze LIRC, do którego można bezpośrednio podpiąć odbiornik TSOP. Złącze podpięte jest do napięcia 3,3V z RPI więc działały będą jedynie układy TSOP obsługujące takie napięcie. Osobiście sprawdzałem na TSOP4836 i działa bez zarzutu.

Do płytki można wpiąć bezpośrednio 10 urządzeń OneWire. Każde wejście ma 3 PIN'y (+5V, GND, SIGNAL). Urządzenia wpinamy bezpośrednio, bez dodatkowego rezystora, który umieściłem już na płytce. 

To już chyba wszystkie funkcje płytki. U mnie płytka zastąpiła poprzednią konfigurację około miesiąc temu i jak dotąd działa bez zarzutu. Praktycznie wszystkie z wymienionych na początku wpisu wad zostały usunięte. 

No i największa zaleta - to w jaki sposób wykorzystamy płytkę, w czym napiszemy oprogramowanie zależy już tylko od nas. Można skorzystać z pythona, javy, c, czy nawet pisać skrypty w bash'u. Ogranicza nas praktycznie tylko wyobraźnia. Wszystko można wygodnie testować logując się na RPI po ssh i uruchamiając programy. Nie trzeba za każdym razem programować arduino :)

Ja postanowiłem że nadal pozostanę przy OpenHab uruchomionym na RPI.

Do OpenHab 1.x jest "binging" obsługujący układy MCP23017. Prawdopodobnie da się z niego skorzystać. Ja przy okazji zmiany architektury przesiadłem się również na OpenHab 2.0. 
Niestety binding nie działał, musiałem zatem napisać swój. Kod oczekuje na "code review". Jeśli go przejdzie prawdopodobnie znajdzie się w oficjalnym wydaniu OpenHab 2.1.

Niecierpliwi znajdą go tutaj:

Do obsługi czujników temperatury podpiętych do złącz OneWire również nie było binding'u. Tutaj również musiałem napisać swój. Również oczekuje na code review. 

Kod znajdziecie tutaj:
Konfiguracja OpenHab to już jednak temat na oddzielny wpis.
 
Podsumowując: 
 całe rozwiązanie zajęło mi mnóstwo czasu, począwszy od prototypu na płytce stykowej, poprzez schemat i projekt w eagle, lutowanie układu, pisanie oprogramowania, ale zdecydowanie było warto. Całość działa dużo stabilniej niż poprzednie rozwiązanie, a co najważniejsze jest dużo wygodniejsze i elastyczniejsze. Jestem w stanie sobie wyobrazić dużo więcej zastosowań takiej płytki niż tylko automatyka domowa. 
U mnie obecnie płytka obsługuje:

  • 7 przekaźników do sterowania oświetleniem lub gniazdkami
  • przełączniki do obsługi przekaźników
  • 7 czujników temperatury One Wire DS18B20
  • sterowanie przekaźnikami za pomocą pilota
  • do jednego wejścia podłączyłem zamiast przełącznika kontaktron i mam stały podgląd stanu bramy garażowej (zamknięta/otwarta)

Wszystko to na jednym Raspberry PI i opisywanej płytce :)

W trakcie prac przygotowałem trzy prototypy płytki. Jeden działa produkcyjnie, jeden mam do dalszych testów i jeden został "wolny". Jeśli ktoś będzie zainteresowany mogę go odsprzedać. 
Cena - 150 zł. Dość wysoka, ale wykorzystane części nie są tanie (głównie tranzystory i układy MCP), trawienie płytki też trochę kosztowało a i pracy włożyłem sporo. 
Chętnych proszę o kontakt na priv. Mogę wystawić aukcję na allegro.

Jeśli zainteresowanie będzie większe przygotuję jeszcze kilka takich płytek.

Z tego też powodu niestety nie zamieszczę na razie projektu w eagle. Natomiast nie ma tam żadnej wiedzy tajemnej i na podstawie mojego poprzedniego wpisu gdzie załączyłem diagram połączeń MCP, oraz ogólno dostępnej w internecie wiedzy, każdy zainteresowany powinien być w stanie takie rozwiązanie przygotować.