Espduino i C.O. przez internet – podejście drugie

Wykorzystanie Espduino – „Arduino+WiFi” do kontroli centralnego ogrzewania – kotła na ekogroszek z obrotową retortą – Tekla Draco Duo, ze sterownikiem Recalart Economic Premium. Sam kocioł jest bardzo podobny do popularnych kotłów Klimosz (nawet produkowane są niedaleko).

Oczywiście cały ten system do życia niezbędny nie jest:) Jak jednak widać ogrzewanie domu węglem może dać człowiekowi mnóstwo możliwości i zabawy. Można sobie z nawiązką zrekompensować brak w dzieciństwie wymarzonego zestawu Lego Technics 🙂

Rok temu zrobiłem prosty system monitorowania kotła. Po roku działania tego połączenia Arduino i esp8266 postanowiłem zrobić coś prostszego i lepszego. Znalazłem w chińskim sklepie niezbyt znane urządzenie zwane Espduino firmy doit.am – jest to płytka identyczna pod względem wymiarów i rozmieszczenia pinów z Arduino, ale zawiera mikrokontroler Esp8266 esp13 zamiast ATmega328P. Na banggood.com kosztował 33zł .  Programuje się  w IDE Arduino, co dla mnie jest bardzo wygodne. No i oczywiście jest WiFi. Nawiasem mówiąc producent ma świetną nazwę – „doit.am” to dla nich skrót od „Shenzhen Doctors of Intelligence & Technology”. Niestety na swojej stronie nie chwalą się wyprodukowaniem tego układu.

Po podłączeniu i pierwszych próbach niestety tak różowo nie było. Od razu w oczy rzuca się inna kolejność PINów na płytce.  W sieci zupełny brak dokumentacji – znalazłem tylko  coś w rodzaju forum z informacjami (prawie puste) i schematem, który w sumie jest dość przydatny – można z niego wywnioskować, który PIN odpowiada któremu wejściu esp13. Trzeba się więc posiłkować dokumentacją dotyczącą samego esp8266-13. Same wejścia/wyjścia cyfrowe nie są aż tak uniwersalne, jak w Arduino. Niby wszystkie obsługują magistralę I2C czy OneWire, ale pierwsze próby z diodami pokazały, że nie wszystko jest takie oczywiste. Na przykład – co w sumie przydatne – GPIO16 jest powiązany z wbudowaną niebieską diodą LED. Stan niski powoduje włączenie, a wysoki wyłączenie diody. Na GPIO1 i 3 nie udało mi się odczytać temperatury.

Układ ma jednak dość dużo zalet, poza oczywistym faktem, że jest od razu WiFi i nie trzeba łączyć esp8266 z arduino:

  • jeden układ, zasilany przez USB lub przez „baryłkowe” wejście 6-12V
  • całość pracuje na 3,3V ale jest też wyjście 5V
  • łatwe programowanie w IDE Arduino, można pobrać skonfigurowane IDE z potrzebnymi bibliotekami
  • zawiera przykładowe programy – np. serwer WWW, serwer plików, OTA
  • OTA – łatwo można wgrywać oprogramowanie przez WiFi!
  • Cała obsługa WiFi jest bardzo prosta, wbudowana obsługa AP, STA i tryb hybrydowy.
  • Watchdog

Tak naprawdę obsługa WiFi odbywa się w tle – nie trzeba niczego robić poza nawiązaniem połączenia. Układ wykonuje operacje w tle, na przykład podczas przerw delay(). Jeśli wykonujemy jakąś pętlę zajmującą dużo czasu, wystarczy wprowadzić gdzieś funkcję yield(), która pozwala mikrokontrolerowi wykonać niezbędne operacje. W razie jakiejś nieprzewidzianej przerwy / zapętlenia wbudowany watchdog resetuje cały układ (co w Arduino nie było takie proste).

Tak więc zacząłem budowę od sprawy najbardziej oczywistej:

Odczyt temperatur

Tak jak wcześniej, zamierzam odczytywać temperatury za pomocą cyfrowych czujników Dallas DS18B20 na szynie OneWire. Jeden taki czujnik to koszt ok 4zł. Żeby było łatwiej, zastosowałem zasilanie parasite – zamiast trzech przewodów wystarczają dwa (GND i sygnał, zasilanie przewodem sygnałowym z rezystorem pullup).

  • Jeden czujnik wyprowadziłem na zewnątrz domu (ładnie widać dobowe zmiany temperatur),
  • drugi na wyjściu gorącej wody z kotła (jest to prawie równoważne z temperaturą samego kotła)
  • trzeci monitoruje temperaturę wody płynącej do kaloryferów (za zaworem 4D)

Po zbudowaniu pierwszego prostego układu odczytującego temperatury z OneWire – DS18B20 napotkałem na pierwszy problem. Wcześniej wszystko ładnie pracowało na napięciu 5V, ale teraz, na 3,3V wystąpił problem z odczytem temperatur.  Czujniki podłączałem za pomocą dwóch przewodów – na przewodzie sygnału dałem zalecany rezystor pullup 4,7kΩ. Na Arduino wszystko działało, a tu nie chce. Czujnik pokazywał, że w pokoju jest 60-80 stopni C. Po podłączeniu drugiego było nawet gorzej, a przecież DS18B20 powinien działać z 3V. Obniżyłem opór do ~2kΩ – temperatura prawidłowa. Ale po podłączeniu drugiego czujnika – znowu to samo. Obniżam rezystancję i znowu dobrze. Przy trzech czujnikach właściwe temperatury pokazywały się dopiero przy rezystorze 600Ω.  Znalazłem w sieci pewne obejście tego problemu – trzeba po prostu ustawić PIN jako wyjście i dać stan wysoki
digitalWrite(pinOneWire, HIGH);
pinMode(pinOneWire, OUTPUT);

Teraz wszystko działa poprawnie, nawet na długich kablach, przy rezystorze 4,7kΩ. Czy zrobiłem to dobrze – nie wiem, ale nie jestem sam:)

Pomiar ilości spalanego węgla

Druga rzecz, którą w moim piwnicznym IoT chciałem, to pomiar ilości spalanego węgla. Na ogół spalanie wynosi 1-2 worki na dobę, oczywiście zależnie od temperatury zewnętrznej,  ale chciałbym dokładniej wiedzieć, ile węgla potrzeba i jak to zmienia się w zależności od ustawień i jakości paliwa. Postanowiłem więc mierzyć czas podawania węgla.

W przypadku mojego kotła silnik podaje węgiel przez 5-7 sekund, zależnie od trybu sterownika. Po każdym podaniu następuje przerwa 20-30 sekund (ustalona przeze mnie w zależności od rodzaju węgla). Jeśli temperatura kotła będzie odpowiednia, następuje dłuższa przerwa, nawet do 30 minut (czas podtrzymania – żeby nie wygasło).

Do kabla zasilającego silnik podłączyłem równolegle starą ładowarkę telefonu. Jest to dość znany i bezpieczny sposób na odczytywanie stanu linii 230V. Ładowarka daje napięcie 5V, więc budowałem prosty dzielnik napięcia oparty na dwóch rezystorach (15kΩ i 10kΩ), dzięki czemu uzyskuję napięcie 3V. Zakładam, że ładowarka USB nie poda zbyt wysokiego napięcia więc taki dzielnik napięcia powinien wystarczyć.

Odczytuję stan (wysoki – silnik podaje węgiel) za pomocą wejścia GPIO:
pinMode ( pin_silnik, INPUT); //ustawienia odczytu silnika podajnika
digitalWrite(pin_silnik, LOW);

Dodatkowo dałem rezystor pulldown – nie bardzo potrafię znaleźć, które wejścia w Espduino mają rezystory pullup lub pulldown, bo na pewno nie wszystkie.

 

Pojawił się jednak kolejny problem tzw. drgań styków. Po włączeniu podajnika ładowarka czasem daje prąd z przerwami (ułamki sekund). W tym celu użyłem biblioteki Bounce2, która nawiasem mówiąc bardzo upraszcza cały program. W setup():

debouncer.attach(pin_silnik); //użycie debouncera na pinie silnika
debouncer.interval(5); // maksymalny czas drgania styków

później, w pętli loop() wystarczyły dwie linie sprawdzenia stanu odczytu:

if (debouncer.rose()) podajnik_zalaczony(); // podajnik załączył się
if (debouncer.fell()) podajnik_wylaczony();// podajnik wyłączył się

Sumuję czas, w jakim silnik jest włączony oraz wyłączony (w celu wyliczenia zużycia węgla), a po każdym odczycie danych z zewnątrz resetuję te liczniki.

Na razie odczytuję w jednostkach „sekundy podawania” a na stronie internetowej mam wykres w postaci „sp/h” i „sp/dobę”, pozostaje kwestia pomiaru ile węgla mniej więcej jest podawane w ciągu sekundy i przeliczenie tych jednostek na kilogramy.

Po uruchomieniu całości pojawił się jeszcze jeden niespodziewany problem:

Ładowarka USB daje prąd jeszcze po wyłączeniu zasilania 230V. Na początku przez 2 sekundy, ale przy częstszym załączaniu się podajnika nawet przez 3s. Na razie skorygowałem to w programie (odejmuję 2 sekundy pracy i dokładam do przerwy), ale muszę sprawdzić, czy to tylko ta konkretna ładowarka.

Monitorowanie braku węgla w podajniku

Wcześniej planowałem pomiar ilości węgla w podajniku czujnikiem odległości. Stwierdziłem jednak, że nie ma to sensu, i tak co dzień / dwa zerkam do piwnicy, a w podajniku mieści się około 130kg. Po ubiegłorocznej obserwacji wykresów ustaliłem jednak coś innego. Kiedy braknie węgla, lub z jakiegoś innego powodu węgiel nie jest podawany, wszystko zachowuje się w łatwo przewidywalny sposób: sterownik próbuje podawać węgiel tak często jak się da, zawór 4D zamyka się (bo temperatura kotła nie rośnie), temperatura obiegu CO szybko spada.Temperatura kotła CO utrzymuje się jeszcze przez kilkadziesiąt minut, przez dłuższy czas nie spada – choć nie ma węgla nie ma węgla, to kocioł nie jest chłodzony powracającą wodą z kaloryferów. Sterownik kotła ma więc problem z ustaleniem, czy brakło węgla (lub wystąpił inny problem) i lampka „alarm” pojawia się dopiero po dłuższym czasie. Jest już wtedy za późno na ewentualne dosypanie i trzeba rozpalać na nowo. Jednak dzięki znajomości historii temperatur i częstotliwości podawania, mogę w bardzo prosty sposób przewidzieć takie wygasanie znacznie szybciej i ustawić wysyłanie powiadomienia na komórkę. To jednak rzecz, którą robię po stronie serwera odczytującego temperatury, a nie w Espduino.

Obniżenie temperatury kotła

Jak już pisałem poprzednio, mój sterownik Recalart Economic Premium posiada możliwość czasowego obniżenia temperatury. Temperatura w pokoju jest zbyt wysoka – zewnętrzny termostat (można go dokupić) zwiera styki, a wtedy sterownik kotła obniża temperaturę wody płynącej do kaloryferów.

W sumie to dość prosta sprawa, wystarczy za pomocą pinów spowodować zwarcie styku. Chciałem to zrobić za pomocą tranzystora – bo tranzystor akurat posiadam – nie wiem, czy to wyjdzie, muszę dopiero sprawdzić jakie jest napięcie na stykach i czy taki układ zadziała, czy nie obejdzie się bez kupna jakiegoś przekaźnika. Temat dopiero rozgryzam, ale zrobiłem już część programową z wyjściem na odpowiedni pin sterujący. Z diodą LED działa 🙂 Przez internet będę podawał czas w minutach, na jaki temperatura ma się obniżyć, dodatkowo bezprzewodowy termometr (oparty na „małym” esp8266) odczytuje temperaturę w pomieszczeniach, więc można zaprogramować automatyczne obniżenie.

Serwer WWW

Pozostaje kwestia odczytu zebranych danych. Tak jak wcześniej, zamiast regularnie wysyłać informacje, postanowiłem zrobić prosty serwer WWW. Espduino sczytuje wszystkie dane, a ich zebranie i wstawienie do bazy danych zostawiam urządzeniu zewnętrznemu. Postawiłem na serwer z dwoma, a właściwie trzema stronami WWW:

  • AdresIP/raw – pokazuje „czyste” dane w prostym formacie, jaki sobie wymyśliłem:
    nazwazmiennej;wartosczmiennej|nazwazmiennej;wartosczmiennej|... Po wczytaniu tej strony mój program zakłada, że dane zostały przekazane i kasuje je (tzn. czasy podawania)
  • AdresIP – pokazuje właściwie te same dane, ale w czytelniejszej postaci, do tego można bezpośrednio zmienić obniżenie temperatury.
  • AdresIP/update – w celu wykonania zdalnej aktualizacji OTA – w końcu nie trzeba biegać do piwnicy, żeby coś poprawić!

I to właściwie wszystko! Oczywiście moje urządzenie ma stały adres IP i port przekierowany na routerze dzięki czemu jest do niego dostęp z zewnątrz.

Samo uruchomienie WiFi jest banalne:

WiFi.mode(WIFI_STA);
Serial.begin ( 9600 );
WiFi.begin ( ssid, password );
while ( WiFi.status() != WL_CONNECTED ) {
delay ( 500 );
}

oraz obsługa adresów stron:

server.on ( "/raw", handleRoot ); //tylko zmienne
server.on ( "/", handleInfo ); // dane w czytelnej postaci
server.on ( "/wprowadzczas", handleWprowadzczas); //strona tylko do wprowadzania czasu podawania poprzez HTTP POST
server.onNotFound ( handle404 );

Obsługa takiego żądania to po prostu utworzenie odpowiedzi

String response;

W której zamieszczam kod html, który ma być wysłany. Później przekształcenie jej na char[] i wysłanie:

server.send ( 200, "text/html", charResponse );

Wysyłany w ten sposób ciąg znaków nie może być zbyt długi – esp8266 radzi sobie z tekstem do mniej więcej 2100 znaków, można to oczywiście obejść, ale w moim przypadku to wystarcza.

Obsługa OTA (Over-the-air-programming) – tu skorzystałem z prawie gotowej funkcji. Można wysyłać aktualizację prosto ze środowiska Arduino, ja wybrałem inną metodę, była dla mnie najprostsza, bez zabawy w konfigurację: w Arduino IDE wybieram kompilację do pliku bin i pod linuksem wykonuję polecenie:

curl -F "image=@firmware.bin" adresIP/update

Baza danych, frontend

Do zbierania danych wykorzystuję program napisany w PHP, umieszczony na zewnętrznym serwerze VPS (tak przy okazji posiadania tego serwera). Program odczytuje z powyższej strony zmienne i wpisuje je do bazy danych MySQL. W crontabie umieściłem wpis uruchamiający ten program co 2 minuty. Nie musiałem zmienić prawie niczego od zeszłorocznej wersji układu.

Dane wyświetlam na stronie internetowej (również  w PHP), do tego wykresy przy użyciu Google Chart API. Wygląda to dość czytelnie, można klikać na poszczególnych punktach i odczytywać wartości, a nawet powiększać.

Montaż

Cały układ jest oparty na Espduino, płytce stykowej, kabelkach, kilku rezystorach, diodzie LED i ładowarce USB. Właściwie jedyny koszt to Espduino. Wszystko to przymocowałem trytytkami do podstawki i zawiesiłem w piwnicy na ścianie – w razie zmian i udoskonaleń mogę to łatwo zdjąć lub nawet na miejscu coś poprawić.

Espduino+Arduino

 

Tak wygląda podgląd strony bezpośrednio z serwera na Espduino:
piec_infoMoja aktualna strona na VPS z wszystkimi informacjami – muszę jeszcze poprawić dodać parę funkcji:

co-info

A poniżej kod źródłowy na esp8266:

 

 

Napisz odpowiedź

Twój adres e-mail nie zostanie opublikowany.