2023-01-17

Zegar i kalendarz w ESP8266 czyli co to jest NTP i dlaczego w VIRTUINO


Szczęśliwi czasu nie liczą .... No to jestem szczęśliwym człowiekiem. Choć czasami muszę siebie i mój ulubiony ESP8266, unieszczęśliwiać. Niezbyt często ale jednak. 
Do unieszczęśliwiania wymyślono zegarek. Taki za złotówkę ale i za złotówkę z kilkoma zerami. Wszystkie robią to samo - liczą czas. A czas jak to czas - tyka wszystkich. Trudno ale niech robi to szybko, tanio i dokładnie. I o tym właśnie dzisiejszy wpis.




W dawnych mikroproceorowych czasach określanie czasu było sporym problemem. Czas tyka ciągle a już mikroprocesor niekoniecznie. Wymyślono więc zegar na rękę dla mikroprocesora, który tyka bez przerwy. Ma bateryjkę i rezonator kwarcowy by tykać szybko i dokładnie. Ale kosztuje i zabiera miejsce (szczególnie bateryjka). No i jak się okazało w praktyce wcale nie jest taki dokładny. 

Zmieniono więc ideę i od czasu wszechobecnego internetu za odmierzanie czasu odpowiada serwer (serwery) czasu. Wszystkie komputery, telefony a nawet zegarki z dostępem do internetu synchronizują swój wewnętrzny zegar z internetowym serwerem czasu.  I choć producenci zegarków dla mikrokomputerów wciąż rają nam zakup układów RTC to od chwili gdy nasz ESP  włączył się do międzygalaktycznej sieci możemy aktualny czas pobrać z serwera czasu NTP. Trzeba tylko dołączyć do naszego programu bibliotekę protokołu transmisji z takim serwerem  (to jest UDP) i jakąś bibliotekę potrafiącą obrobić dane przesyłane przez serwer na bardziej przyjazną postać typu godzina/minuta/sekunda.

Skąd taki temat? W moim domowym systemie automatyki dostawcą zegara był stale działający serwer BLYNKa. Specjalny widget umożliwiał podjęcie określonych działań przez ESP w określonym czasie. W VIRTUINO IoT jest podobny widget ale zakładam iż aplikacja będzie łączyła się mikromodułem sporadycznie więc w takiej konfiguracji jest on nieprzydatny. Potrzebuję innego sposobu określenia czasu w mikroprocesorze a jak wspomniałem wcześniej dołożenie dodatkowego modułu RTC nie wchodzi w grę. Pozostaje tylko połączyć nasz ESP do serwera NTP i stamtąd pobrać aktualny czas.

Dla Arduino polecana jest biblioteka NTPClient. Zobaczymy jak taki zegar współpracuje z oprogramowaniem VIRTUINO IoT.    

Na początek deklaracje dodatkowych bibliotek:

#include <ESP8266WiFi.h> // to już mamy w VIRTUINO
#include <NTPClient.h>
#include <WiFiUdp.h>

definiujemy klienta NTP

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org");

inicjalizujemy klienta w setup()

  timeClient.begin();
  // dopasowanie strefy czasowej
  // GMT +1 = 3600
  // GMT -1 = -3600
  timeClient.setTimeOffset(0);

i pobieramy z serwera NTP aktualne dane - gdzieś w naszym programie

  timeClient.update();

Teraz pozostaje już tylko odczytać aktualne ( w miarę) dane o czasie. W miarę gdyż nie należy zapominać o opóźnieniach wynikających z czasu łączenia się z serwerem i przetwarzania danych w ESP. Ale nie przekroczą one nigdy 1 sekundy co daje nam dokładność naszego zegara niedostępną dla większości układowych RTC. Z danych NTP odczytujemy aktualny czas i datę ale ja dla projektu potrzebuję czas i to z dokładnością do 1 minuty. Możemy odczytać czas w takim formacie

  String formattedTime = timeClient.getFormattedTime();
  Serial.print("Formatted Time: ");
  Serial.println(formattedTime);  

lub poszczególne jego elementy

  int currentHour = timeClient.getHours();
  Serial.print("Hour: ");
  Serial.println(currentHour);  

  int currentMinute = timeClient.getMinutes();
  Serial.print("Minutes: ");
  Serial.println(currentMinute); 
   
  int currentSecond = timeClient.getSeconds();
  Serial.print("Seconds: ");
  Serial.println(currentSecond);  

I w odpowiedzi widzimy piękny wydruk na monitorze

Formatted Time: 18:26:58

Hour: 18

Minutes: 26

Seconds: 58

Najważniejsze że biblioteka NTP i WebSocket nie przeszkadzają sobie za bardzo i wszystko śmiga bez zakłóceń.
A co z tym dalej zrobić podpowie nam już tylko ułańska fantazja i nasz ulubiony ciąg dalszy.

I chciałoby się powiedzieć .. i to by było na tyle.
Niestety nie. Z niejasnych mi jeszcze przyczyn biblioteka NTPClient przestaje odczytywać bieżący czas z serwera gdy w kodzie mam odblokowaną linię ustawiającą na stałe adres IP mojego ESP tj.

WiFi.config(ip, gateway, subnet);   

Sprawdziłem - nie ma to nic wspólnego z kodem Virtuino - ale problem jest. Może się zdarzyć, że po resecie modułu lub rutera, ruter przydzieli inny adres IP dla tego ESP i aplikacja nie będzie się mogła z nim połączyć. Można to łatwo obejść przywiązując w ruterze na stałe MAC adres ESP do danego adresu IP.  Na razie dodałem do kodu dwie linijki ułatwiające odnalezienie mojego ESP w ruterze

  String nazwa_ESP = String("ESP_pompa");
  WiFi.hostname(nazwa_ESP);  

Ale to jakaś dodatkowa czynność, której zawsze staram się unikać. Poszperam czy problem jest znany i czy jest na to jakieś rozwiązanie. A na razie to już naprawdę koniec.
 
SUPLEMENT

Rozwiązanie bez trudu można znaleźć w sieci . Trzeba tylko dodać adresy dwu DNS do konfiguracji WiFi  Uzupełniłem oryginalną konfigurację Virtuino o coś takiego

.............
  IPAddress subnet(255, 255, 255, 0);        // set subnet mask to match your network
  IPAddress ip4 = ipaddr_addr( "8.8.8.8" );//dns 1
  IPAddress ip5 = ipaddr_addr( "8.8.4.4" );//dns 2

  WiFi.mode(WIFI_STA);
  WiFi.config(ip, gateway, subnet, ip4, ip5);    // If you don't want to config IP manually disable this line
  WiFi.begin(ssid, password);
.....................

I odczyt czasu działa bezbłędnie. I niech tak zostanie





Brak komentarzy:

Prześlij komentarz