niedziela, 31 lipca 2016

Bezprzewodowy miernik wilgotności gleby z odczytem w telefonie - cz.2

Watchdog dla ESP8266

 

Czujnik wilgotności testuje się w warunkach polowych. Nie dając wiary w szczelność chińskiej lampki uzupełniłem ją o własny pokrowiec bryzgoszczelny. IP64 jak mniemam.


Godzinowy wykres z okresu tygodnia zarejestrowany przez History Graph przedstawia się następująco

Opadające gwałtownie zbocza wykresu to moment podlewania. To w zasadzie wykres oporności gruntu a nie jego wilgotności stąd podlanie powoduje spadek mierzonego sondą napięcia.


Wadą ESP jest posiadanie tylko jednego portu ADC. Nie można w tym samym czasie mierzyć napięcia zewnętrznego i napięcia zasilania układu. To spory problem przy zasilaniu akumulatorowym, kiedy nie można określić czasu koniecznego doładowania. Postanowiłem testować układ do momentu zaprzestania transmisji. Zastosowany tani akumulatorek 14500 nie ma żadnych wewnętrznych zabezpieczeń. Tym samym mam dużą szansę, że będzie to jego jednorazowe zadanie lub w sposób istotny utraci on swoje parametry. Trzeba poszukać prostych możliwości pomiaru większej ilości napięć za pomocą jednego wejścia ADC modułu ESP.

Tworząc program dla czujnika wilgotności udało się przetestować kilka nowych zagadnień z funkcjonalności ESP i BLYNKa.



1. Zastąpienie  BLYNK_READ(V11) procedurą transmitBLYNK() okresowo wysyłającą dane do serwera BLYNK komendą Blynk.virtualWrite(V12, str);. Jest to mało eleganckie w stosunku do poprzedniego automatycznego pobierania danych przez aplikację ale inaczej dane potrzebne w History Graph nie są zapisywane na serwerze w czasie gdy aplikacja w telefonie nie jest aktywna.

2. Wysyłanie powiadomień o zdarzeniach na telefon.
To bardzo wdzięczna funkcja odciążająca od bieżącego śledzenia co dzieje się w aplikacji. Szkoda tylko, że mocno ograniczona do 1 powiadomienia /minutę. Ale i tak ładnie się to prezentuje na ekranie telefonu







3. Po wielokroć gruntownym przestudiowaniu forum BLYNKa udało mi się trafić na propozycję kodu nie wstrzymującego wykonywania programu przy braku połączenia z siecią lub braku połączenia z BLYNK tu>>>>>>>>> 

Zmodyfikowałem nieco te procedury i w efekcie zrobiłem sobie procedurę WifiBlynk() pozwalającą na przejście procedur nawiązywania połączenia z siecią i z serwerem BLYNK w przypadku braku jednego lub drugiego połączenia. Procedurę uzupełnia fragment w pętli głównej - linie 203-217 - pozwalające na dopisanie procedur działania programu w przypadku braku połączenia. Procedury działają rewelacyjnie. Bardzo szybko logują do sieci i BLYNK a przypadku braku połączenia przekazują sterowanie programem do pętli głównej. Przy powrocie połączenia komunikacja podnosi się prawie natychmiast. Zastosuję to w dotychczasowych projektach szczególnie w projekcie POMPA, który może a nawet powinien działać autonomicznie nawet przy braku komunikacji z siecią.

4. Watchdog dla ESP. to chyba najważniejszy z nowych elementów programowych. Zaproponowany tutaj>>>>> kod programowego wd ESP działa bez problemu. Nie jestem w stanie wyjaśnić potrzeby użycia poszczególnych komend w programie przepisałem je więc CTR+C CTR+V i zadziałało od razu. Najważniejsze, że jak do tej pory nie ma żadnych konfliktów w zasobach biblioteki  <Ticker.h> z  biblioteką BLYNK. Z opisu wynika że ten watchdog działa na trzech poziomach:  sprzętowym wd, programowym wd SDK i w programowej pętli programu i pokrywa większość teoretycznych możliwości zawieszenia się procesora i programu.

5. Procedura uśpienia ESP, o której już pisałem
Komendą   ESP.deepSleep(y * x * 1000 * 1000); uruchamiamy uśpienie procesora na y*x sekund.
Należy tylko pamiętać o zwarciu RST z GPIO16 (a więc do zastosowania w ESP-07 i 12) i o ewentualnym wyłączeniu na stałe LED modułu ESP sygnalizującego podanie zasilania (zwiększa pobór prądu w stanie deepsleep o około 0,6mA) . U mnie został on  brutalnie przewiercony

uffff....................cdn 

poniedziałek, 25 lipca 2016

Bezprzewodowy miernik wilgotności gleby z odczytem w telefonie

ESP8266 w działaniu - czyli projekt z bateryjką

Czas coś popełnić z samodzielnie działającym ESP8266. W poczekalni jest pomysł na małą automatykę ogrodową - coś co odciąży od obowiązku doglądania i podlewania donic i pojemników z warzywami w ogrodzie. Skrzyń z warzywami jest trochę a nawet chwilowy niedobór wody odbija się znacząco na kondycji roślin  i plonach. Trzeba więc zatrudnić dobrego dżinna by robił to za mnie.

Pierwszy krok to czujnik wilgotności. Wymagania
- komunikacja bezprzewodowa
- zasilanie bateryjne
- prosty
- ładny
Padło więc na ESP8266. Postaram się go zmieścić w małej ładnej standardowej ogrodowej lampce solarnej. Np takiej (6,50 PLN)
Sonda wilgotności będzie w szpikulcu, akumulator w nóżce a elektronika w kopule. Byłoby pięknie gdyby jeszcze udało się wykorzystać panel solarny do doładowywania akumulatora - ale to już extra dodatek. Na razie trzeba uruchomić moduł podstawowy.
Akumulatorek 18650 lub 14500 w zależności od tego co wejdzie do rurki. Mam więc do dyspozycji 1000do 2000 mAh na zasilanie układu. ESP potrzebuje 70-100 mA w czasie pracy i 10-100uA w stanie deep sleep. Mogę więc zakładać około 10 - 20 godzin ciągłej pracy. Restart systemu w raz z pomiarem zajmuje 10 - 20 sek po czym ponownie można uśpić procesor. Załóżmy więc pracę przez 2 min dziennie (6 pomiarów) co teoretycznie powinno pozwolić na pracę układu przez  około 300 - 600 dni. Tak naprawdę układ będzie pracował nie więcej niż 120-150 dni więc zasilania powinno starczyć na cały sezon.

Schemat maksymalnie prosty widoczny jest na zdjęciu


ESP-07 przygotowany do pracy z usypianiem (zwarte GPIO 16 i RST poprzez zworkę rozwieraną w trakcie programowania). Dodane są niezbędne polaryzacje i wejścia/wyjścia do programowania modułu wlutowanego na płytkę.  Rx na wejściu ma dzielnik dla dopasowani poziomów napięć z konwerterem USB/RS232.  Wejście sondy podane jest równolegle do rezystora 20 k (w rzeczywistości wstawiłem tam 39 kom). Wyżej potencjometr 100kom do kalibracji zakresu pomiarowego (ostatecznie trafił tam opornik 81kom). Te dwa oporniki stanowią jednocześnie dzielnik zapewniający na wejściu ADC poziom napięcia nie wyższy niż 1,1 V - ADC mierzy napięcia z zakresu 0-1V. Zasilanie całości z akumulatorka Li-Ion 3,7 V poprzez diodę obniżającą napięcie do poziomu 3,5 - 3 V w zależności od stanu naładowania akku.
ESP8266 wlutowałem na pająka dzięki czemu nie musiałem stosować płytki przejściowej. Układ ESP-07 ma dodatkową zaletę - możliwość przyłączenia anteny zewnętrznej co może się przydać w pracy polowej. Oporniki zmieściły się pod układem a po bokach ESP wlutowane są złącza szpilkowe do szybkiego łączenia z sondą i zasilaniem oraz niezbędne piny w procesie programowania procesora.

  • Test pierwszy -  pomiar napięcia - pozytywny 
procedura identyczna jak w Arduino  analogRead (A0) działa bez problemów pamiętając, że napięcie wej to 0-1 V. Dokładność zaskakująco duża przy napięciach bliskich 1 V "przeskakuje" tylko ostatni bit co oznacza że mamy rozdzielczość 9 bitów (zakładałem 8)
  • Test drugi BLYN z widget GRAPH i HISTORY GRAPH
Do odczytu danych przesyłanych cyklicznie ale w długich odstępach czasu przyda się widget HISTORY GRAF. Ale tego co zaobserwowałem jego wskazania są prawdziwe jedynie w chwili połączenia telefonu z mikroprocesorem (via serwer). Po wyłączeniu ekranu w danych powstaje czarna dziura. Powinno być inaczej - i telefon i procesor powinny pobierać aktualne dane z serwera nawet gdy urządzenie na przeciwległym końcu jest nieaktywne. O ile synchronizacja danych z BLYNK serwera w procesorze może ( i powinna) być dokonana komendą  Blynk.syncAll(); 
po której wszystkie zmienne i porty powiązane z widgetami w telefonie aktualizują swoje wartości. W drugą stronę coś  jednak szwankuje i wyświetlane wartości nie zawsze odpowiadają temu co powinno znajdować się na serwerze BLYNKa wcześniej przesłane z procesora

Poczytałem jeszcze raz dokumentację i forum i sprawa się wyjaśniła. Stosowana przez mnie procedura pobierania danych przez BLYNK z procesora - BLYNK.Read(vPin) -  jest wywoływana JEDYNIE gdy aplikacja w telefonie jest aktywna (patrzymy na nią). Po zamknięciu okna funkcje nie jest nieaktywna. Trzeba użyć cyklicznego wywołania funkcji Blynk.wirtualWrite(vPin,wartość).
Każde wywołane tej procedury zapisuje dane w serwerze BLYNK skąd telefon może je już sobie pobrać przy otwarciu aplikacji. Rzeczywiście wszystko działa 


 To trzydniowy zapis danych "na sucho"wysyłanych co godzinę z czujnika wilgotności. Wykres opada z wartości 1019 do 1000 razem ze spadkiem napięcia zasilania rozładowującego się akumulatorka (o ok 2%). Będzie to miało jakiś wpływ na pomiary - napięcie na akumulatorze będzie zmieniać się od 4,2 V do 3,7 V a więc ponad 10%. Trzeba będzie uwzględnić ten fakt w przyszłych konstrukcjach.

Ostatecznie czujnik wilgotności trafił do nieco większej obudowy - lampki solarnej za 9 PLN. Akumulatorek Li-Ion 14500 o wymiarach AA zmieścił się na siłę w miejscu akumulatorka AAA a cała elektronika poszła do klosza. Na razie musi tak zostać. Dla pewności połączenia dołączyłem zewnętrzną antenkę i całość przybrało postać kompaktowego urządzenia

 
   Solar z lampki wisi na razie w powietrzu. W następnej wersji może uda się go zmusić do podładowywania akumulatorka.

No to teraz do ogrodu na małą próbę ognia

I zapewnie cdn ...........  

niedziela, 17 lipca 2016

ESP8266 na poważnie cz. 3

Aaa kotki dwa - czyli jak skutecznie uśpić ESP-12

Dziś spróbujemy wprowadzić nasz moduł w stan uśpienia. Do wyboru jest kilka modów ograniczenia prądu pobieranego przez procesor. tu>>>>>>>>>



Mode
Min
Typical
Max
Units
802.11b, CCK 1Mbps, POUT=+19.5dBm

215

mA
802.11b, CCK 11Mbps, POUT=+18.5dBm

197

mA
802.11g, OFDM 54Mbps, POUT=+16dBm

145

mA
802.11n, MCS7, POUT =+14dBm

135

mA
802.11b, packet size of 1024 bytes, -80dBm

60

mA
802.11b, packet size of 1024 bytes, -70dBm

60

mA
802.11b, packet size of 1024 bytes, -65dBm

62

mA
Standby

0.9

uA
Deep sleep

10

mA
Saving mode DTIM 1

1.2

mA
Saving mode DTIM 3

0.86

mA
Shutdown

0.5

uA


Najlepiej opisany i najprostszy do wdrożenia jest "deep sleep".
W tym celu należy:
  1. Zewrzeć piny RST i GPIO 16
  2. Wywołać procedurę >>> ESP.deepSleep(10* 1000 * 1000); <<< w nawiasie przykładowe wprowadzenie w stan uśpienia na 10sek (1 = 1 us)
  3. warto po tej procedurze dodać delay(100)
  4. czekać
  5. po 10 sek procesor się samo-resetuje (pin 16 jest ustawiany na 0)
  6. ot i wszystko - działa 
  7. jeśli w miejsce czasu wstawimy 0 to moduł nie wybudzi się timerem ale będzie musiał być wzbudzony przez zewnętrzny RST 
Wyłączeniu podlega głównie transmisja WiFi i coś tam jeszcze ale bez szału.
W moim układzie w tym stanie pobór prądu spadł z 70 do 12 mA.  Niby 6 x  mniej ale 12mA to o rząd za dużo by zasilić to wszystko z bateryjki.
A jeszcze do tego należy rozewrzeć RST i GPIO 16 podczas programowania modułu.
Ponadto okazało się że moduł jest bardzo wrażliwy na przyłączenia na GPIO 15. Miałem na ten pin podane wyjście z odbiornika 433MHz. Wszystko ładnie pracuje do momentu wyłączenia napięcia. Po ponownym załączeniu moduł się wiesza - trzeba go ręcznie zresetować poprzez RST.  Odłączenie odbiornika i pozostawienie tego pinu w stanie pull-down przywraca prawidłowe działanie ESP.
W literaturze stanowczo zalecają omijanie szerokim łukiem pinów 0, 2 i 15 do wykorzystania we własnych aplikacjach. Jeśli dodamy do tego piny 6-11 zarezerwowane dla komunikacji wewnętrznej z pamięcią to okazuje się że na 16 pinów ESP tak naprawdę swobodnie możemy dysponować tylko GPIO 4,5,12,13,14. Pięć portów na 16 + ewentualnie dwa (Tx Rx) jeśli dobrze pokombinujemy i jeden analogowy. Hmm niewiele tego jest.
Stąd wniosek, kupowanie bardziej rozbudowanych w piny modułów ESP nie ma żadnego sensu (np ESP-12) lepiej już kupić ESP-07 z porządniejszą antenką na płytce i możliwością przyłączenia dodatkowej zewnętrznej. Pewnie dlatego pojawiła się wersja ESP-14 z dodatkowym 8-bitowym STM8S udostępniająca 22 piny i 5 wejść analogowych. Ale prawdę powiedziawszy wolę już układ ESP z Arduino ze względu na mnogość sprawdzonych bibliotek.

Tak więc ESP w roli samodzielnej pozostanie u mnie li tylko w niewielkich projektach i to raczej tam gdzie będę musiał stosować zasilanie bateryjne. Tylko te 12 mA...


Wracam więc do usypiania. 12 mA to stanowczo za dużo.
Ale Internetowa akademia mówi, że w stanie deep sleep mają być uA a nie mA. Szukam jeszcze raz danych.
Rzeczywiście. W tabelce zamieszczonej tutaj>>>
Mode Min Typ Max Unit
Transmit 802.11b, CCK 1Mbps, POUT=+19.5dBm
215
mA
Transmit 802.11b, CCK 11Mbps, POUT=+18.5dBm
197
mA
Transmit 802.11g, OFDM 54Mbps, POUT =+16dBm
145
mA
Transmit 802.11n, MCS7, POUT=+14dBm
135
mA
Receive 802.11b, packet length=1024 byte, -80dBm
60
mA
Receive 802.11g, packet length=1024 byte, -70dBm
60
mA
Receive 802.11n, packet length=1024 byte, -65dBm
62
mA
Standby
0.9
mA
Deep sleep
10
uA
Power save mode DTIM 1
1.2
mA
Power save mode DTIM 3
0.86
mA
Total shutdown
0.5
uA

Deep sleep to 10 uA a nie 10 mA. 1000x mniej! Ktoś łże.

Wracam do płytki i zasilam ją bezpośrednio z napięcia 3,3V
Stan pracy - 75 mA
Stan deep sleep - 470 uA
 No tak - miliampery brał przecież stabilizator 5/3,3V.
470uA - całkiem nieźle. Nie mam jak sprawdzić gdzie wycieka mi ta różnica pomiędzy 10 a 470 uA bo wymagało by to prucia pracowicie poskładanej płytki prototypowej. Na razie to bez znaczenia. Przy  takim poziomie poboru prądu praca z baterii nabiera sensu. Szczególnie że mam pewien pomysł.......

Całą procedurę usypinia można sobie skomplikować dodając dodatkowy parametr
ESP.deepSleep(uint32_t time_us, RFMode mode = RF_DEFAULT)

RF mode może przyjmować warości od 0-4

  •    RF_DEFAULT = 0,  //RF_CAL depends on init data from byte 108
  •      RF_CAL = 1,  //RF_CAL enabled causes large current drain after wake 170mA
  •      RF_NO_CAL = 2,  //RF_CAL disabled, small current drain after wake 75mA
  •      RF_DISABLED = 4  //RF disabled, smallest current drain after wake 15mA
  ale po co to stosować - to jeszcze nie wiem

Wejście analogowe

ESP-07, 08 i 12 mają dodatkowo wyprowadzony na zewnątrz płytki pin wejścia 10 bitowego przetwornika analogowo-cyfrowego. Szkoda że tylko jedno. Przetwornik czyta się standardowo


  
pomiar = analogRead(A0);

Wadą jest również zakres pomiarowy - 0 - 1 V co dla 10 bitów daje rozdzielczość 100uV .  A więc na poziomie szumów. Pewnie praktycznie do wykorzystania będzie 8 bitów.

Ale ESP ma jedną ciekawą właściwość związaną z wejściem ADC (czasami nie wiedzieć czemu nazywanym również TOUT)


 można nim pomierzyć napięcie zasilania  wewnątrz układu (na pinie 3 i 4)
W tym celu należy
  • wejście ADC ma wisieć w powietrzu nie podłączone
  • zadeklarować ADC_MODE(ADC_VCC)
  • w pętli głównej odczytać

float voltaje=0.00f;
voltaje = ESP.getVcc();
Serial.print(voltaje/1024.00f);
Serial.println(" V");

i powinno uzyskać się wynik w Voltach

Ale są jakieś dodatkowe warunki których nie bardzo rozumiem

  • The 107th byte in esp_init_data_default.bin(0~127byte) must be 0xFF
  • RF must be enabled (pewnie coś związane z wywołaniem funkcji DeepSleep)

więc cd niewątpliwie nastąpi.....