piątek, 25 listopada 2016

BLYNK w (prawie) każdym mikroprocesorze

Mikroprocesorowe klocki LEGO czyli BLYNK<4>ALL

Dwa poprzednie posty zainspirowały tenże. Więc trochę logiki

Założenie
Jeśli mikroprocesor posiada > 8 kB pamięci programu i jakikolwiek interface szeregowy (serial, I2C itp)
Teza
 To dodając najmniejszy i najtańszy ESP8266 - ESP-01 można  nim sterować za pomocą aplikacji BLYNK
Dowód
W zasadzie zawarty jest w dwu poprzednich postach :)

Omówienie problemu

1. W wielu uruchamianych systemach mikropocesorowych do komunikacji z procesorem w konfigurowaniu, normalnym działaniu lub w celach testowych niezbędne jest  zastosowanie jakiegoś wyświetlacza (najczęściej LCD) i jakiś klawiszy czy klawiatury. Możemy to zastąpić lub uzupełnić o nowe funkcjonalności dodając do systemu odpowiednio zaprogramowany układ ESP-01  i komunikować się z systemem mikroprocesorowym poprzez telefon/tablet z IOS lub Androidem. Uzyskujemy nieporównanie bardziej uniwersalną, wszechstronną,  tanią a przede wszystkim zdalną możliwość komunikacji sterowania i nadzoru stworzonym przez nas systemem. Możemy więc zdalnie zmieniać konfigurację, wartości początkowe, i inne dane zmieniające zdalnie działanie systemu. Możemy odczytać online  informacje o dowolnych zmiennych, portach, komórkach pamięci czy rejestrach w systemie.
Oczywiście możemy udostępnić część  tych funkcji użytkownikowi końcowemu jeśli jest to niezbędne w normalnej pracy urządzenia. Ponadto w ramach systemu BLYNK  nasz system może wysyłać nam lub użytkownikowi alerty, informacje czy jakiekolwiek dane na telefon, email, facebook,zbiorczej bazy danych  czy gdzie sobie ustalimy.

To tylko początek możliwości jakie dostajemy dokładając do własnego systemu mikroprocesorowego niewielką (2,5x1,6 cm) i śmiesznie tanią (ok 1,5 $ z dostawą do domu) płytkę ESP z wgraną biblioteką BLYNK i z zainstalowaną w telefonie/tablecie darmową (lub za niewielką opłatą dla dużych projektów) aplikacją BLYNK. I to wszytko co potrzeba by skomunikować dowolny nasz projekt z projektantem lub użytkownikiem (przy czym liczba osób równolegle przyłączonych do systemu jest nieograniczona!)

Jak to wygląda w praktyce?

Na przykład do takiej płyty na etapie projektowania dodajemy nasz ESP (w dolnym lewym rogu)

I zamiast (albo obok) komunikować się z systemem za pomocą wyświetlacza LCD i przycisków na płycie możemy to zrobić tak samo albo i lepiej telefonem/tabletem z każdego dowolnego miejsca na świecie - podkreślmy - za 1,5$ :). Mamy wiec dzięki takiemu rozwiązaniu w telefonie wirtualne przyciski. potencjometry, klawiaturę, wyświetlacze ledy wskaźniki  itd itd a nawet terminal!.




Jak to wygląda programowo
W programie naszego systemu mikroprocesorowego dodajemy 3-4kB bibliotekę (mam zamiar zmniejszyć ją do 1-2KB) będącą protokołem komunikacyjnym z ESP-01. Poprzez wywołanie odpowiednich funkcji z biblioteki przekazywane są  polecenia, ustawienia i dane wysyłane z aplikacji w telefonie/tablecie lub wysyłane dane  (bity,bajty, liczby formatu int, stringi ) do aplikacji. Z jakim widgetem połączymy te dane to już nasza fantazja. Możliwości są nieograniczone. A mamy do dyspozycji 128 virtualnych pinów do deklaracji różnych zmiennych. A i to nie wszystko bo dołączony do aplikacji pełnowymiarowy terminal pozwala wprowadzać i wyświetlać nieograniczoną ilość danych.

Struktura systemu BLYNK<4>ALL

Wrysowałem tu jedynie część rozwiązania znajdującą się w systemie mikroprocesorowym. Pozostała część przynależna do aplikacji BLYNK (serwer, telefon z aplikacją)   pozostają niezmienione how-blynk-works.
Dowolny mikroprocesor z zainstalowanym  naszym oprogramowaniem coś tam sobie steruje, mierzy czy błyska ledem na porcie. Dodatkowy niewielki kod ma za zadanie sformatować/zdekodować ramkę danych i wysłać/odebrać ją poprzez jakieś łącze szeregowe. Dla ułatwienia całość obsługi komunikacji BLYNK działa w poolingu z poziomu pętli głównej nie ma więc niebezpieczeństwa zablokowania normalnej pracy mikrokontrolera. Co więcej brak połączenia z ESP czy dalej z WiFi lub BLYNK nie ma większego znaczenia dla poprawnej pracy całego naszego systemu - ot przez jakiś czas nasz układ pracuje w trybie autonomicznym.  
Ramka danych jest najprostszą z możliwych.

Vxx:yyyy/r/n
V   - znak początku transmisji i znacznik rodzaju komendy (litery V, S, I, N, F, O itd.)
xx  - nr vPin lub nr komendy
:     - separator
yyy - dane w postaci integer lub string
/r/n  - znacznik końca ramki zamieniany przy odbiorze na znacznik końca stringu /0

Do wysłania jej funkcją Serial.printnl() skłania łatwość śledzenia transmisji i możliwość korzystania z gotowych procedur Arduino.
I to wszytko co potrzeba by skomunikować nasz procesorek ze światem zewnętrznym i skorzystać z dobrodziejstw gotowej aplikacji do zarządzania.
Klocki LEGO to genialny pomysł.

To zaczyna być naprawdę interesujące .......  więc niecierpliwie czekam na cd ...

piątek, 18 listopada 2016

BLYNK z 8051/2 PIC18 68HC908, HCS08 MSP430 - to już możliwe

BLYNK i ESP8622 w natarciu szerokim frontem


Małe ćwiczenie z programowania ESP8266 i NANO dało niespodziewany efekt - możliwość uruchomienia BLYNKa z każdym praktycznie dowolnym mikrokontrolerem. Jedyny warunek to możliwość wpisania do niego kodu do komunikacji z ESP na którym zainstalowany jest BLYNK. I natychmiast  większość opcji oferowanych przez BLYNK jest w zasięgu ręki a nawet obu rąk.
Poniższy program działa w oparciu o transmisję szeregową RS232 ale nie ma żadnych przeszkód by szybko przekonwertować to na np I2C czy SPI. Serial wybrałem tylko z lenistwa - łatwo go podejrzeć dowolnym terminalem by zobaczyć co w rzeczywistości jest transmitowane na łączach z ESP. Co prawda transmisja serialem ma swoje wady ale jest najprostsza do ogarnięcia.

Na dziś mogę zapisywać dane z i do większości BLINKowych widgetów - wszystkich, które do tej pory używałem. Ponadto udało się zaimplementować możliwość zmiany parametrów widgetów - color, label - co jak dla mnie wyczerpuje na razie potrzeby związane z wizualizacją działań w stosowanych mikrokontrolerach. Do czasu kiedy każdy procesor (lub większość) będzie wyposażony w sprzętowe WiFi połączenie z ESP8266 wydaje się na razie najsensowniejszym rozwiązaniem "usieciowienia" naszego procesora. I najtańszym!

To w miarę finalna (powiedzmy ver 0.1.1) oprogramowania dla ESP i komplementarna część, którą należy wgrać w drugi dowolny mikrokontroler. Kod pisany jest pod Arduino IDE i niektóre z funkcji trzeba pewnie przerobić dla konkretnego typu procesora i standardu języka C.

Kod dla ĘSP-01



Kod "wtyczki" BLYNK dla mikroprocesora



To oprogramowanie pisane i testowane jest pod kątem 32 wirtualnych pinów dostępnych w podstawowej wersji BLYNK ale bez widocznych problemów obsługuje wszystkie 128 vPiny.

Zarezerwowane są następujące vPiny:
- nr 0  > dla vLED. Ledy można dodawać też na wszystkie pozostałe wolne vPiny ale pin nr 0 jest tylko do vLED.
- nr 29 > terminal. Widget terminala jest na sztywno ustawiony na tym vPinie.
- nr 30 i 31 > są zarezerwowane dla ESP (vLED i terminal) na potrzeby testowe

A poza tym wszystko jest do dyspozycji programisty.
 Można przesyłać dane typu Intiger komendą BlynkvirtualWrite_int (nrvPin, data) i tupu String BlynkvirtualWrite_str(nrvPin, str). Dane bitowe czy bajtowe przesyła się jako int. Nie implementowałem przesyłania float bo za dużo z tym zabawy w stosunku do korzyści. Do wyświetlania wystarczy sformatować string a do innych operacji przesunąć przecinek by dostać liczbę całkowitą. Może w przyszłości zaimplementuję Double z liczbami ułamkowymi. Na razie to musi wystarczyć.
Stringi nie są niczym ograniczone poza buforem obu procesorów. Dla pewności wstawiłem ograniczenie do 50 bajtów na jednym stringu.
Dla obsługi vLED jest osobna funkcja BlynkvirtualWrite_led(nrvPin, data). "Data" to jasność świecenia vLED - 0 wygaszony 255 max świecenia.
Zmiany parametrów widgetów to głównie zmiana koloru  BlynkvirtualWrite_col(nrvPin, str)
gdzie str musi być zgodna z formatką koloru tj. #FFFFFF. F to dowolna cyfra w HEX.
Osobna funkcja BlynkvirtualWrite_ON(nrvPin, str) i OFF jest przeznaczona dla zmiany etykiet przycisków w stanie ON i OFF. Na razie nie implementowałem zmiany etykiet innych widgetów - nigdy z tego nie korzystałem i sądzę że to zbędny widget-gadżet.

Najwięcej problemów pojawiło się w najłatwiejszym obszarze - komunikacji szeregowej. Funkcja printnl() dodaje na końcu przesyłanego łańcucha znaki CR i NL a nie dodaje znaku końca stringa /0 o czym zapomniałem a czego nie było widać w standardowym terminalu Arduino IDE. Dopiero program RealTerm   pozwolił podejrzeć co naprawdę transmituje się pomiędzy serialami obu procesorów. Gorąco go polecam bo jest naprawdę świetny.

  
 Dzięki niemu w standardowej procedurze odbioru stringa z seriala dodałem zamianę znacznik końca wydruku /r na koniec stringa /0. I wszystko zaczęło działać. No może prawie wszystko. Okazuje się że transmisja po serialu nie jest taka bezbłędna jak sądziłem - pojawiają się tam czasem jakieś dziwne znaki (przesłuchy ? utrata części znaków przy dużej ilości przesyłanych danych?) które mogą zakłócić poprawność odbieranych danych. Temat został wyprostowany poprzez wstępną analizę formatu odbieranej ramki - ale temat jest niewątpliwie do dalszej analizy. Na razie działa bez większych zakłóceń.
Co ważne obserwowany wcześniej w klasycznym układzie NANO<>ESP8266 efekt "zatykania" się transmisji do APP BLYNK szczególnie przy częstej zmianie parametrów widgetów - tu praktycznie nie występuje. Wszystko przechodzi gładko.

Najpiękniejsza jest objętość kodu w NANO potrzebna do obsługi BLYNK znajdującego się w ESP-01 - 4 kB (13 % pamięci). I to bez żadnej optymalizacji rozrzutnego przecież Arduino IDE.
 Czysty blink BLYNK to prawie 18 kB (60% pamięci). To otwiera całkiem nowe możliwości zastosowania BLYNKa dla procesorów z 16 a nawet 8 kB pamięci programu! ATtiny i BLYNK - oczywiście możliwe choć oczywiście bez sensu.

Jeszcze ciekawszym pomysłem wydaje się stworzenie miniaturowego (wielkości ESP-01) systemu kontrolno-testującego dla dowolnego projektu mikroprocesorowego. Obecnie dla tego celu trzeba stosować rozbudowane wyświetlacze LCD i klawiaturki które umożliwiają "wgląd" do wnętrza programu, ustawienia parametrów,odczytu zarejestrowanych błędów czy uruchomienia testów kontrolnych.  To wszytko można zrobić teraz z klawiatury telefonu a co najważniejsze - z drugiego końca świata. Dla systemów prototypowych po prostu bajka!!! Trzeba na tym pomyśleć bo wydaje się to ogromne rozwojową ścieżką dla zastosowań BLYNKa.


Tyle na razie z frontu walki nad "dziwną" implementacją BLYNKa  cd jak mniemam nastąpi ......


 

piątek, 11 listopada 2016

ESP 8266 <> Arduinno NANO - zmiana miejsca instalacji BLYNK

Duży może więcej

 

Nurtuje mnie od jakiegoś czasu zagadnienie współpracy UNO/NANO z ESP8266. A dokładniej, czy słaby 8 bitowy mikrus procesorowy winien nadzorować działanie całego systemu i jeszcze sterować o wiele potężniejszym mikrokontrolerem ESP8266. Brak w tym logiki poza logiką historyczną - Arduino był pierwszy i to on obrastał w kolejne peryferia w tym odpowiedzialne za komunikację różnego rodzaju shieldy.  Ale od czasu gdy ESP wkupił się w łaski Arduino IDE i może być traktowany na równi z Atmelami utrzymywanie stanu rządzenia dużego przez małego wydaje się anachronizmem. Szczególnie, że zapełnienie 32 KB pamięci UNO/NANO dokonuje się błyskawicznie  przy wykorzystywaniu BLYNKa a 10 krotnie większa pamięć ESP8266 pozostaje praktycznie pusta.
Można oczywiście minimalizować kod  Atmegi. W wielu miejscach znajdziemy poradniki jak z kobyły Arduino IDE i gotowych bibliotek wrócić do czystego C i bezpośredniego sterowania rejestrami zmniejszając kod 10-20 krotnie przy standardowym programie blink. To oczywiście doskonały pomysł dla osób na poważnie (głównie zawodowo) chcących zająć się programowaniem mikrokontrolerów. Ale ja dziękuję. To jest dokładnie odwrotna logika niż ta, która legła u podstaw tego bloga. Bo oczywiście bez problemu zminimalizuję sterowanie portami ale biblioteki RCSwitch albo OneWire już nie. Że o BLYNKu nie wspomnę - a to są prawdziwe KOBYŁY pochłaniające gros zasobów malutkiej Atmegi. A nie mając zamiaru pisania własnych bibliotek nie pozostaje mi nic innego niż przeniesienie części kodu do większego procesora. W końcu mam dwa i niech się dzielą robotą.

Dobrym pytaniem jest czy w ogóle sprzęgać te dwa nierówne w klasach procesory jeśli większość programów da się już uruchomić na ESP. Moim zdaniem, dopóki chińczyk będzie oferował praktycznie 5 portów I/O i jeden analogowy to takie połączenie ma sens. Nawet jeśli za drzwiami czeka już kolejna mutacja  - ESP-32. Przyjazność, mnogość dobrze działających sprawdzonych bibliotek, potężne grono fanów i oczywiście cena jest gwarancją, że Atmele nie dadzą się łatwo zepchnąć do narożnika. Więc póki co postanowiłem pokombinować z odwróceniem logiki współpracy NANO <> ESP na ESP <> NANO z przesunięciem zadań rozdzielanych na oba procesory.

I tak ESP8266 chciałbym zrobić odpowiedzialnym za całość spraw komunikacyjnych z światem zewnętrznym na poziomie Internetu łącznie z pełną komunikacją z BLYNK. Atmel zaś robiłby to w tym czym jest najlepszy - w zarządzaniu peryferiami. Połączenie obu na poziomie sprzętowego seriala pozwoli na wykorzystanie wszystkich dotychczasowych moich płytek praktycznie bez zmian. Ba można poważnie pomyśleć nad fizycznym rozdzieleniem procesorów do różnych oddalonych lokalizacji  i wykorzystania do połączenia dowolnych łączy, po których bez problemu da się zaimplementować serial.

Zagadnienie jest frapujące choć wobec błyskawicznie zmieniającej się procesorowej rzeczywistości może stać się czysto akademickim zajęciem. Ale co tam .....

Najważniejszym problemem jest przyjęcie jakiegoś protokołu komunikacji, który z jednej strony nie zablokuje dzisiejszych funkcjonalności a z drugiej będzie na tyle szybki wydajny by nie odczuć różnicy w działaniu tak zmienionego duetu. Dobrze byłoby mieć jeszcze jakiś samo nakręcający się upside z takiej konfiguracji ale o tym będziemy myśleli potem. Na początek założę najprostszą komunikację szeregową typu nr_pin,dane. Przy tych odległościach problem zakłóceń praktycznie nie występuje.
Nic prostszego niż przesyłanie stringów pewnie nie wymyślę więc na początek ramka wyglądać będzie tak
Vxx:ww          xx - nr vPinu  ww - wartość    : separator
i tyle. Zakładam przesył danych jedno argumentowych - włączona funkcja SPLIT we właściwościach vPinow. Zobaczmy jak to zadziała. Dla jeszcze łatwiejszej obsługi na razie przyjmę następujący przydział vPinów
0 - 4  vLED
6 - 25 zmienne typu integer
25-31 zmienne typu string
Potem może pomyślimy nad uniwersalizacją przydziałów choć gdy do wykorzystania mam 128 vPinów rozbudowa i komplikacja kodu może nie mieć sensu.

Kod dla NANO



Kod dla ESP8266


I o dziwo wszystko działa. Choć trochę trzeba było pododawać do płytki by można było równolegle programować i NANO i ESP-01. Co ważne instalacja portable Arduino IDE pozwala pracować równolegle na dwu aplikacjach i znakomicie przyspiesza implementację.



Z ciekawszych fragmentów kodu polecam funkcje związane ze zmienną  typu String. To dzięki nim analiza odbieranego kodu  jest prosta i przyjemna.

str.charAt(0) - zwraca znak z pozycji 0 stringu str
str.substring(1, str.indexOf(':')) - wycina kawałek stringa od znaku na pozycji  1 do znaku ":"
data = str.substring(str.indexOf(':') + 1) wycina kawałek stringa od znaku po ":" do końca
data2 = strdata2.toInt() - zamienia string na licznę typu int jeśli string zawiera cyfry

Jedyny problem był z funkcją  serialEvent()   Odbiera ona znaki ze sprzętowego seriala w przerwaniu - i działa bardzo ładnie ale tylko na NANO. Z jakiegoś powodu nie działa na ESP choć powinna bo serial ESP też działa na przerwaniach. Dodałem więc funkcje  myserialEvent(), która jest cyklicznie wywoływana w pętli LOOP. Trzeba będzie poszperać jak to zrobić elegancko na przerwaniu.

Opisany sposób instalacji BLYNK w ESP8266 i połączenie go serialem z procesorem NANO ma jeszcze jedną fajną cechę - można w ten sposób obsłużyć BLYNKiem każdy dowolny procesor posiadający port serial np całą rodzinę PICów, dla których nie została zaimplementowana biblioteka BLYNK.

A to już całkiem nowy i ciekawy temat ......

cdn .....

niedziela, 6 listopada 2016

Bezprzewodowy czujnik otwarcia / zamknięcia bramy garażu

O zawiązywaniu buta dżdżownicą

W ładnie działającym sterowaniu bramą garażu brakuje jednego elementu - czujnika otwarcia/ zamknięcia. To niezbędna rzecz jeśli chcemy sterować nią zdalnie. Pierwsze to względy bezpieczeństwa osób. Próba zdalnego zamknięcia bramy otwartej przez kogoś innego może zakończyć się  źle. Standardowa blokada zamykania gdy mechanizm wyczuje opór to za mało. A nie wszystkie bramy szczególnie garażowe mają fotokomórki.
Drugi powód bardziej oczywisty. Sterując z daleka nie mamy pewności czy mechanizm zareagował na komendę pilota. Nie raz zdarza się potrzeba ponownego naciśnięcia pilota by otworzyć bramę czy samochód. Po trzecie czasami dobrze wiedzieć, że ktoś otworzył bramę - ot taka informacja kontrolna np. w domowym systemie alarmowym.
A więc potrzeba czujnika jest . Oczywiście ma to być czujnik bezprzewodowy. I jak zawsze - niedrogi.
Pomysł nr 1
ESP z jakimkolwiek stykiem
Do tego celu wystarczy nawet ESP-01. Ale potrzebny jeszcze zasilacz, obudowa, jakiś styk i dociągnięcie zasilania do miejsca montażu - niby niewiele ale to wykonawczo spory projekt. Na razie na półkę

Pomysł nr 2
Kontaktronowa czujka otwarcia okna / drzwi
Wybór padł na radiowy czujnik otwarcia drzwi / okna od systemów alarmowych np taki. Aliexpress.com. 10 - 12 zł za czujnik z dostawą do domu nie wydaje się dużo.
Czujniki nadeszły - małe zgrabne po prostu ideał.
Tylko mają mały feler - działają w jedną stronę. Czujka wysyła kod jedynie przy rozwarciu magnesu (rozwarciu kontaktronu). Może uda się coś pogmerać w środku by działało w obie strony?



Schemat prosty (powyżej część odpowiedzialna z zwłokę czasową) cały czujnik zrobiony na układzie  EV1527. Niezły chip z możliwością nauki kodu.
Ze schematu wynika że cała idea działania to ładowanie  kondensatora przez dużą pojemność o stalej czasowej kilku sek. W tym czasie otwiera się Q6 a poprzez Q5 podawane jest napięcie na układ i generowany kod. Jest nieźle.
Przerobienie tego na czujnik zwierny zajęło chwilkę - przeniesienie kontaktronu do +VCC i dodanie rezystora 5-10 Mom do rozładowania pojemności. Schemat poniżej


Mam więc dwa ładne bezprzewodowe czujniki  jeden zwierny a drugi rozwierny wysyłające rożne kody. Da się to już zastosować do systemu bramy. Tylko ten montaż dwu osobnych czujników jakoś mi nie pasuje.
Niestety próba upchnięcia obu funkcji na jednej płytce wymaga zbyt dużej ilości przeróbek. Pozostaje wersja nr 2 - zróbmy z dwu czujników  jeden. Wspólne zasilanie, antenka, obudowa i dwie płytki = czujnik zwierno - rozwierny w komplecie.


 I upakujemy wszystko razem w jednej obudowie - miejsca jest dosyć. W górę dumnie sterczy jeszcze dodatkowy rezystor 3 Mom. Niestety nie mam nic miniaturowego w swoich zapasach więc do testów musi tak pozostać.



Magnes jest w odległości działania kontaktronu. Widać sporą rezerwę na ewentualne tolerancję montażu czujnika w docelowym miejscu.

A nagrodę  pozostała mi ekstra piękna antenka 433 MHz, obudowa i baterię na przyszłą wymianę . Co więcej obudowa idealnie pasuje do mojego modułu ESP-07 a więc miejsce na kolejne pomysły urządzeń już jest.



Teraz trzeba tylko zaimplementować czujnik w oprogramowaniu IoT ale to już następną razą.
I dla jasności - nie zadaję sobie pytania czy nie lepiej było kupić gotową czujkę bezprzewodową zwierno-rozwierną. Bo wtedy cały ten blog nie ma sensu :) 

Więc cdn niewątpliwie nastąpi.......

wtorek, 1 listopada 2016

O przewadze zmywarki nad ręcznym myciem garów - biblioteki cd ..

Biblioteka TIMERS.H z daleka i bliska

Jakiś czas temu dotknąłem pobieżnie tematu bibliotek tych genialnych narzędzi programisty I choć to podstawa całej filozofii klocków lego, o której opowiada ten blog to jednak wszystko jest jeszcze przede mną. Zdałem sobie sprawę z tego analizując moją najbardziej ulubioną bibliotekę Timers.h.

We wszystkich programach i tych uruchamianych na Arduino UNO/NANO i tych dla ESP8266 biblioteka Timers.h jest podstawowym zawiadowcą całym programem. Odpowiada zarówno za bezpieczeństwo systemu wymuszając resety ESP i samego Atmela (taki programowy watchdog) i obsługuje główne, zależne od czasu, procedury programu a w tym np. częstotliwość komunikacji z BLYNK.
Jest przy tym nieprawdopodobnie prosta, niezawodna i co ważne - nie wchodzi w konflikt z żadnymi elementami sprzętu czy programu. Po prosu ideał. Ale jak to jest w większością ideałów - dostrzega się to dopiero po czasie .....

Analizując wcześniejsze programy dostrzegam w ilu miejscach przegapiłem możliwość zastosowania tej biblioteki. Zamiast tego pracowicie dziergałem  pętle if....  if .... sprawdzające kolejne warunki liczników zdarzeń.

Świetny przykład  opisu i zastosowania tej biblioteki podał wojtekizk  (pewnie to jego biblioteka choć nie pisze o tym wprost :) ) w programie wytrawiarki. Mamy tu praktyczny przegląd możliwości zastosowania tej biblioteki dla obsługi różnorakich zdarzeń powiązanych z czasem.

Jest tylko jedno ale. Zabrakło tu opisu najważniejszej moim zdaniem funkcji tej biblioteki  - zaszytej wewnątrz funkcji setInterval . Działa podobnie jak funkcja updateInterval ale dodatkowo  zeruje licznik początkowy danego timera co ma kapitalne znaczenie dla nowych zastosowań tej biblioteki.

A biblioteka Timers.h potrafi naprawdę znacznie więcej niż to do czego ją wykorzystywałem do tej pory.

1.Obsługa cykliczna zdarzeń. Najbardziej oczywiste zastosowanie.

#include <Timers.h>
void setup(){
   akcja.attach(0, 1000, zrob_cos_co1sek);  // inicjalizacja procesu
}
 void loop(){
 akcja.process();  //pooling - cyklicznie wywołanie by sprawdzić czy już czas działać
}
void zrob_cos_co1sek() {
//wlasny podprogram do wykonania co 1 sek
}


Wywołanie podprogramu zrob_cos następuje co 1 sek - np będzie to zmiana stanu leda na przeciwny, wyświetlenie wartości odczytanej z czujnika itd itd  Uzyskuję w ten sposób obsługę zdarzeń o częstotliwości dostosowanej do rzeczywistych potrzeb. Umieszczenie programu zrob_coś w pętli głównej  programu spowoduje, że wykonywał się on będzie  (niepotrzebnie) setki lub tysiące razy na sekundę.  Możemy go spowolnić  dodając nieśmiertelne delay(), ale zablokuje to możliwość wykonania innych pożytecznych rzeczy przez procesor. Timers.h rozwiąże ten problem za mnie - odczeka w tle 1  sek nie wstrzymując działania innych fragmentów kodu po czym w odpowiednim momencie uruchomi program zrob_coś.

2.Obsługa cykliczna zdarzeń z dynamiczną zmianą częstotliwości obsługi. To odmiana pkt. 1 pozwalająca na zmianę częstości wywołania programu zrob_cos w trakcie działania programy np. zwiększenia szybkości migania led jako sygnalizacja nowego stanu w procesorze.


#include <Timers.h>
void setup(){
   akcja.attach(0, 1000, zrob_cos);  // inicjalizacja procesu
}
 void loop(){
 akcja.process();  //pooling - cyklicznie wywołanie by sprawdzić czy już czas działać
if (zmiana stanu przycisku)  {
      if (zmiana z 0>1) akcja.updateInterval(0,500); else akcja.updateInterval(0, 1000); 
  }
 
}
void zrob_cos() {
//wlasny podprogram do wykonania cyklicznie
}


 Świetnie nadaje się np. jako wskaźnik błedu/błędów w działaniu programu z wykorzystaniem tylko jednego LEDa. Zaraz implementuję to w nowych programach do sterowania led_OK.

3. Zatrzymanie/ start cyklicznej obsługi zdarzeń. To w zasadzie pkt.2 z z ustawionym czasem obsługi = 0.

#include <Timers.h>
void setup(){
   akcja.attach(0, 1000, zrob_cos);  // inicjalizacja procesu
}
 void loop(){
 akcja.process();  //pooling - cyklicznie wywołanie by sprawdzić czy już czas działać
if (zmiana stanu przycisku)  {
      if (zmiana z 0>1) akcja.updateInterval(0,0); else akcja.updateInterval(0, 1000); 
  }
}
void zrob_cos(){
//wlasny podprogram do wykonania cyklicznie
}


 To świetna sprawa - np. uruchamiam wykonywanie większości procedur głównego programu dopiero po nawiązaniu połączenia z BLYNK ale pozostała część odpowiedzialna za reset ESP czy NANO działa nadal nieprzerwanie.

4 Praca monostabilna - jednokrotne odmierzanie zadanego odcinka czasu. To moim zdaniem jedno z ciekawszych możliwości zastosowań tej do bólu prostej biblioteki

#include <Timers.h>
void setup(){
   akcja.attach(0, 0, zrob_cos);  // inicjalizacja procesu
}
 void loop(){
 akcja.process();  //pooling - cyklicznie wywołanie by sprawdzić czy już czas działać
if (zmiana stanu przycisku z 0>1) akcja.setInterval(0,5000); // zrob cos za 5 sek
}
void zrob_cos()  {
akcja.updateInterval(0,0); //wyłącz timer 
//wlasny podprogram do wykonania jednokrotnie 
}

W momencie PZ następuje jakieś zdarzenie i uruchamiany jest timer na zadany odcinek czasu (koniecznie wywołaniem funkcji setInterval  bo wtedy mamy pewność, że timer odliczy dokładnie zadany odcinek czasu). Po jego upływie timer wywołuje procedurę zrob_cos, która wstrzymuje dalsze odliczanie timera i wykonuje zadany nasz program. Znakomicie nadaje się to do uruchamiania np. pompy obiegowej CO.

Co ważne odcinek czasu na jaki uruchamiany  jest timer może być dowolnie zmieniamy podczas każdorazowego uruchamiania timera a także w trakcie odliczania .
W programie możemy zadecydować  o tym czy kolejny sygnał sterujący w czasie pracy timera  będzie uwzględniony czy nie w procesie odliczania odcinka czasu. Możemy także  sterować zachowaniem timera w zależności od tego czy do zmiany czasu w trakcie odliczania użyjemy funkcji  setInterval   czy też updateInterval . Tym samy dostajemy arcyciekawe możliwości zastosowania biblioteki Timers.h w pracy monostabilnej: 

  1. Praca monostabilna ze stałym czasem - gdy kolejny sygnał wzbudzający timer pojawiający się w trakcie odliczania nie przedłuża odcinku czasu
  2. Praca monostabilna z odświeżaniem czasu - gdy kolejny sygnał wzbudzający timer pojawiający się w trakcie odliczania  przedłuża odcinku czasu o kolejną tą samą wartość.
  3. Praca monostabilna ze zminą czasu - gdy kolejny sygnał wzbudzający timer pojawiający się w trakcie odliczania  przedłuża odliczany okres  nową wartość.
  4. Praca monostabilna ze zminą czasu 2 - gdy kolejny sygnał wzbudzający timer pojawiający się w trakcie odliczania  zmienia odliczany okres. Jeśli timer odliczył już czas nowo ustawianej wartości następuje natychmiastowe wywołanie funkcji zrob_co. Gdy odliczany odcinek czasu jest krótszy niż  nowa wartość, timer "dolicza czas do nowej wartości i wywołuje funkcję zrob_cos.
  5. Praca monostabilna z możliwością zatrzymania timera w trakcie odliczania 
  6. Itd .............

Jak na tak prostą bibliotekę ilość możliwych do wykorzystania opcji rozrasta się imponująco.

Biblioteka ta przypomina mi nieśmiertelny timer NE555 królujący od lat w rożnych aplikacjach częstotliwościowo/czasowych i dla którego wciąż pojawiają  się nowe ciekawe zastosowania.

Z pobieżnego tylko oglądu tej biblioteki widać już jak bardzo potrafi ona ułatwić i uprzyjemnić obsługę wszelkiej maści zdarzeń w tworzonych programach.

Oczywiście nie ma nic za darmo. Wykorzystanie tej biblioteki wiąże się z pewnymi ograniczeniami w programie. Jednak

Nasz program musi pozwolić na wywołanie funkcji akcja.process() w pętli loop na tyle często by nie "przegapić" momentu czasu w którym powinien być uruchomiany podprogram zrob_coś. Jeśli pozostała część programu wykonuje się np w ok 100 ms to wywołanie podprogramu może się w najgorszym razie opóźnić o te 100 ms . Ale dodanie w programie funkcji delay() o czasach rzędu sek lub dłużej całkowicie zaburza działanie tego mechanizmu. A więc stosowanie funkcji delay() lub procedur wstrzymujących obieg programu w pętli głównej jest niedopuszczalne - o ile chcemy mieć pewność, że nastąpi wywołanie procedury zrób_coś w przewidzianym przez nas czasie. Oczywiście taki sam skutek będzie miało wstrzymanie obiegu programu przez program zrob_coś.  
Generalna zasada przy pracy z obsługą typu pooling - często sprawdzać warunek czy działać a jeśli jest spełniony - szybko zrobić co ma się do zrobienia.Często na pierwszy rzut oka nie widać czy dana procedura nie wstrzymuje obiegu programu np w obsłudze czujników przetworników czy modułów komunikacji. Warto taką niesprawdzoną procedurę obsługi umieścić na próbę w pętli głównej i zobaczyć ile razy zostanie ona wywołana w czasie sek. Np.dla czujnika DS18B20 czas przetwarzania pomiaru dla rozdzielczości 12 bitów wynosi ok 750 ms. Jeśli procedura obsługi czujnika wstrzyma obieg programu do czasu uzyskania wyniku pomiaru możemy zablokować sobie cały program tym opóźnieniem. Biblioteka <DallasTemperature.h> pozwala wyłączyć to opóźnienie poprzez wywołanie   sensors.setWaitForConversion(false);
Podobna historia dotyczy przetworników A/C i modułów komunikacji. Wszędzie tam musimy sprawdzić czy nie następuje zawieszenie programu do czasu wykonania przez moduł działania.
W tym kontekście wielką niewiadomą jest BLYNK. W normalnej pracy nie widać w działaniu programu  znaczących opóźnień wynikających z obsługi biblioteki BLYNK.  Ale przy utracie łączności z serwerem lub utracie połączenia wifi cały nasz program się sypie. Opóźnienia wprowadzane przez BLYNK całkowicie dezorganizują pracę np. timera o czasie 1 sek i krótszym.

Ale pomimo tych (przyznajmy niewielkich) ograniczeń biblioteka Timers.h stała się nieodzownym elementem wszystkich moich programów.

Zobaczymy czy po odliczeniu kolejnego odcinka czasu wywoła procedurę ........ cdn();