ESP8266 tika – taka

Ide vrijeme tika-tak a koliko kasni?

Nemojte propustiti

E Ink avanture s Inky pHAT-om

E Ink (AKA E Paper, electronic paper) već je neko vrijeme s nama, a mogli ste se sresti s tom tehnologijom ako (još...

Raspberry Pi Story

Raspberry Pi maleni je SBC (single board computer) razvijen od Raspberry Pi Foundation kako bi pomogao u edukaciji osnova računarstva. Međutim, vrlo brzo pokazalo...

Spajanje više tipkala na jedan pin

Mnogi su nas nakon članka o izborniku s LCD shieldom pitali kako spojiti tipkala da rade na takav način. Jedan od načina...

I2C LCD

Sada je vrijeme da se pozabavimo jednim od osnovnih koraka u našim projektima a to je prikazivanje poruka na LCD ekranu. Danas...

Izrada izbornika na LCD štitu

Nakon što smo se upoznali sa shield koji ima LCD ekran i tipkovnicu. Ako još niste možete to učiniti ovdje. Vrijeme je...

Datum i vrijeme oduvijek su bili bitni, a ako imate projekt koji prikuplja podatke, prilično je bitno zabilježiti i trenutak u kojem je neki podatak prikupljen. U nastavku slijedi kratki prikaz kako doći do točnog datuma i vremena (a onda ga i sačuvati), korištenjem pločice bazirane na ESP8266 – u ovom slučaju to je Croduino NOVA iz e-radionice.

Kako je ESP8266 po prirodi stvari povezan na internet, logično je podatak o točnom vremenu dohvatiti s nekog NTPservera. Uz malo guglanja može se pronaći nekoliko Arduino biblioteka koje mogu obaviti posao, za ovaj primjer korištena je Time biblioteka Paula Stoffregena.

Početak

- oglas-

Za početak, u projekt je potrebno uključiti standardnu ESP8266 biblioteku iz koje koristimo ESP8266WiFi, WiFiUdp i Ticker, a TimeLib dolazi u prije navedenoj Time biblioteci. Za podatak o točnom vremenu ne koristi se neki konkretni server, nego europski NTP pool koji bi se trebao pobrinuti za to da nam dodjeli geografski najbliži NTP server. Vremenska zona, tj. njena ‘ljetna’ varijanta je hardkodirana, pošto NTP vraća UTC vrijeme, za domaću zadaću pokušajte taj problem riješiti na pametniji način 😉

// Time keeping using Time library for Arduino - https://github.com/PaulStoffregen/Time

#include <TimeLib.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <Ticker.h>

const char ssid[] = "*********";  //  your network SSID (name)
const char pass[] = "*********";  // your network password

static const char ntpServerName[] = "0.europe.pool.ntp.org";
//const int timeZone = 1;     // Central European Time
const int timeZone = 2;     // Central European Summer Time

WiFiUDP udp; 
unsigned int udpPort = 8888;

Ticker timer;
const float tick = 1.0; // in seconds, how long to wait for the next time display

Treba napomenuti i da koristimo UDP protokol za komunikaciju s NTP serverom i jednostavni interni timer kako bi dobili prikaz vremena u zadanom razmaku (u primjeru je to jedna sekunda, ali lako se može promijeniti u neki drugi interval, npr. minutu). Također, ako se pojave problemi s dohvaćanjem NTP servera iz navedenog poola, moguće je promijeniti u npr. “1.europe.pool.ntp.org” ili “hr.pool.ntp.org”. Ajmo dalje…

Setup i loop

void setup()
{
  Serial.begin(115200);
  Serial.print("Connecting WiFi");
  WiFi.begin(ssid, pass);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("Starting UDP");
  udp.begin(udpPort);
  Serial.print("Local port: ");
  Serial.println(udp.localPort());
  Serial.println("waiting for sync");
  setSyncProvider(getNtpTime);
  setSyncInterval(86400); // in seconds, 86400 = 24 hours

  timer.attach(tick, &showDateTime); //start timer
}

void loop()
{
// nothing to do here :-)
}

U setup funkciji započinje serijska komunikacija sa računalom i pokušavamo uspostaviti vezu s NTP serverom (nadamo se uspješno) i našem timeru zakačimo interval i adresu funkcije koju poziva kada taj interval prođe:

void showDateTime()
{
  char datetime[20];
  sprintf(datetime, "%02d:%02d:%02d %02d.%02d.%04d.", 
          hour(), minute(), second(), day(), month(), year());
  Serial.println(datetime);
}

Ova funkcija formatira i šalje vrijeme i datum računalu, koje u Arduino IDE-u možemo vidjeti u Serial Monitoru (Ctrl+Shift+M). Lijepo je vidjeti da void loop() ne radi ništa 🙂

NTP

Kako bi sve funkcioniralo fali nam još samo dio koda koji zna pročitati ono što nam je NTP server poslao putem UDP protokola:

const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets

time_t getNtpTime()
{
  IPAddress ntpServerIP; // NTP server's ip address

  while (udp.parsePacket() > 0) ; // discard any previously received packets
  Serial.println("Transmit NTP Request");
  // get a random server from the pool
  WiFi.hostByName(ntpServerName, ntpServerIP);
  Serial.print(ntpServerName);
  Serial.print(": ");
  Serial.println(ntpServerIP);
  sendNTPpacket(ntpServerIP);
  uint32_t beginWait = millis();
  while (millis() - beginWait < 1500) {
    int size = udp.parsePacket();
    if (size >= NTP_PACKET_SIZE) {
      Serial.println("Receive NTP Response");
      udp.read(packetBuffer, NTP_PACKET_SIZE);  // read packet into the buffer
      unsigned long secsSince1900;
      // convert four bytes starting at location 40 to a long integer
      secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
      secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
      secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
      secsSince1900 |= (unsigned long)packetBuffer[43];
      return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
    }
  }
  Serial.println("No NTP Response :-(");
  return 0; // return 0 if unable to get the time
}

// send an NTP request to the time server at the given address
void sendNTPpacket(IPAddress &address)
{
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12] = 49;
  packetBuffer[13] = 0x4E;
  packetBuffer[14] = 49;
  packetBuffer[15] = 52;
  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:
  udp.beginPacket(address, 123); //NTP requests are to port 123
  udp.write(packetBuffer, NTP_PACKET_SIZE);
  udp.endPacket();
}

Ovaj dio koda preuzet je iz primjera koji se nalazi u sklopu Time biblioteke. Ukoliko imate problema s komunikacijom sa NTP serverom možete u liniji while (millis() - beginWait < 1500) povećati vrijednost s 1500 naviše, ali u tom slučaju riskirate da će se aktivirati ESP-ov watchdog pa ćete dobiti poruku Soft WDT reset i blokirani mikrokontroler. Nije niti to nepremostiva prepreka, kako se obraniti od ovog psa čuvara možete pročitati ovdje.

OK, a je’l drifta?

Naravno da drifta! Ova metoda nije posebno točna već prilikom dohvaćanja podataka s NTP servera, za povećanje točnosti trebalo bi koristiti više NTP servera i algoritam za sinkronizaciju. Ali, čak i bez toga, korišteni library gubi bitku s entropijom i počinje zaostajati:

2018-06-29 20:04:08.73:   20:04:08 29.06.2018.
.
.
.
.
2018-06-30 08:00:09.05:   08:00:07 30.06.2018.

U 12 sati naš timer zaostao je cca 0.3 s za satom računala na koje je bio spojen (u ovom slučaju više vjerujemo računalu :-)), a biblioteka je izgubila maksimalno 1 sekundu (rezultat je zaokružen na sekundu pa možemo samo nagađati koliki je točno zaostatak). U većini slučajeva ovo nije pretjerano bitno pa se sinkronizacija s NTP serverom ne mora izvoditi prečesto (što se niti ne smije), a za sprečavanje drifta potrebno je koristiti vanjski RTC modul s temperaturnom korekcijom, npr. Adafruit DS3231 precizni RTC. Ipak, za veliku većinu primjena nije bitna velika točnost, pa se ovaj primjer može bez puno razmišljanja iskoristiti u mnogim IoT projektima.

Prethodni članakBig Brother na ESP-32 način
Sljedeći članakRaspberry Pi Story

Možda vas zanima i ovo:

Komentiraj

Unesite svoj komentar!
Ovdje unesite svoje ime

Popularno

Uvjeti korištenja

Uvjeti korištenja seekretors.org stranice (u daljnjem tekstu: ove stranice) u vlasništvu su njenih osnivača Marka Miroslava Bače i Tomislava Preksavca (u daljnjem...

Enderova nova pamet

Enderu 3 teško je naći manu (naročito za cijenu po kojoj se prodaje), i ako bi nešto trebalo izdvojiti, to je sigurno njegov...

PYW – Vijak

Evo nas na prvoj stranici našeg putovanja, a s čime je bolje početi nego s dobrom vezom. Zato krenimo od vijčanog spoja.

Print Your world- uvod

Dobrodošli u novi serijal Print Your world ili kako bi mi rekli ekstrudiraj, ekstrudiraj. U ovom serijalu bavit ćemo...

Korekcija putanje glave 3D printera

Konkretno, u mom slučaju radi se o 3D printeru tipa delta, premda vjerujem da sličnih problema ima i kod modela s klasičnim...