NodeMcu NTP Óra 8×8-as led mátrixszal

Jelenleg Magyarországon UTC + 1 a téli időszámítás és UTC + 2 a nyári. Ezt másképp hívják CET-nek és CEST-nek is.

Az Európai Bizottság 2018. szeptember 12-én elfogadott javaslata szerint az óraátállítás 2019-ben megszűnt volna. Az eredeti elképzelés szerint a tagállamoknak 2019 elejéig kellett volna jelezni, melyik időzónába szeretnének tartozni, de ez a határidő szűkösnek bizonyult, 2019 márciusában 2021-re tették át a döntés évét, addig kell a tagállamoknak eldönteniük, hogy melyik időzóna lenne számukra az előnyösebb vagy elfogadottabb.

Előreláthatólag legközelebb 2019. október 27-én hajnali 3-kor állítjuk vissza az órát hajnali kettőre.

Átállási dátumok 2021-ig

2020. március 29. 2 h október 25. 3 h
2021. március 28. 2 h október 31. 3 h

Forrás: Wiki

Amennyiben szeretnénk a dátumot is kiíratni, akkor módosítsuk a könyvtárunkat az alábbi függvényekkel:

Első körben módosítsuk a NTPclient.ccp-t. Adjuk hozzá a következő függvényeket.

String NTPClient::getFullFormattedTime()
{
   time_t rawtime = this->getEpochTime();
   struct tm * ti;
   ti = localtime (&rawtime);

   uint16_t year = ti->tm_year + 1900;
   String yearStr = String(year);

   uint8_t month = ti->tm_mon + 1;
   String monthStr = month < 10 ? "0" + String(month) : String(month);

   uint8_t day = ti->tm_mday;
   String dayStr = day < 10 ? "0" + String(day) : String(day);

   uint8_t hours = ti->tm_hour;
   String hoursStr = hours < 10 ? "0" + String(hours) : String(hours);

   uint8_t minutes = ti->tm_min;
   String minuteStr = minutes < 10 ? "0" + String(minutes) : String(minutes);

   uint8_t seconds = ti->tm_sec;
   String secondStr = seconds < 10 ? "0" + String(seconds) : String(seconds);

   return yearStr + "." + monthStr + "." + dayStr + " " +
          hoursStr + ":" + minuteStr + ":" + secondStr;
}

int NTPClient::getYear() {
  time_t rawtime = this->getEpochTime();
  struct tm * ti;
  ti = localtime (&rawtime);
  int year = ti->tm_year + 1900;

  return year;
}

int NTPClient::getMonth() {
  time_t rawtime = this->getEpochTime();
  struct tm * ti;
  ti = localtime (&rawtime);
  int month = (ti->tm_mon + 1) < 10 ? 0 + (ti->tm_mon + 1) : (ti->tm_mon + 1);

  return month;
}

int NTPClient::getDayNow() {
  time_t rawtime = this->getEpochTime();
  struct tm * ti;
  ti = localtime (&rawtime);
  int daynow = (ti->tm_mday) < 10 ? 0 + (ti->tm_mday) : (ti->tm_mday);

  return daynow;
}

Másodjára módosítsuk az NTPclient.h nevű fájlunkat, ahol regisztráljuk úgymond az utólag létrehozott függvényeket.  Az alábbi szöveget a “void end();” elé szúrjuk be.

/** Hozzáadott funkció: Dátum plusz idő*/
    String getFullFormattedTime();
/** Hozzáadott funkció: Év + Hónap + Nap*/
    int getYear();
    int getMonth();
    int getDayNow();

Ezután már rendelkezünk azokkal a függvényekkel, amikkel akár a dátumot is ki tudjuk íratni a kijelzőre. (Én ezeket nem fogom alkalmazni a példakódban.)

A kis kitérő után térjünk vissza az eredeti problémához, a megadott napokon át kell állni a téli vagy a nyári időszámításra. Ezt megtehetjük, úgy is, hogy beszerzünk valami timezone könyvtárat és abból dolgozunk, vagy megírjuk magunknak erre a kódot. Én a könnyebbik utat választottam, megírtam a kódot. Abból az alap feltevésből indultam ki, hogy most egyenlőre csak 5 db fix időpontunk van, amikor még órát állítunk át, és utána nem tudjuk, hogy hogyan folytatjuk. Ezért én előre definiáltam ezt az 5 időpontot, és ehhez viszonyítva jelenítem meg az időt UTC+2-ben vagy UTC+1-ben.

Amennyiben már tudjuk, hogy milyen időszámítási módot fogunk alkalmazni fixen, már csak annyit kell a kódon változtatni, hogy UTC + 1-re vagy pedig UTC + 2-re állítjuk az NTP offset-et.

NTPClient timeClient(ntpUDP, "hu.pool.ntp.org", 7200, 60000);

A “hu.pool.ntp.org” utáni paraméter megváltoztatása 3600-ra eredményezi az UTC + 1-es számítást. A 7200-ra állítás pedig az UTC + 2-es számítási módot deklarálja.

Viszont itt még nem tartunk, szóval térjünk vissza az átállítási időpontokhoz. Amikor itt jártam, elgondolkoztam azon, hogy melyik megoldást válasszam? Deklaráljam az átállítási dátumokat “év, hónap, nap, óra, perc, másodperc” formában, vagy használjam a “getEpochTime()” függvényt, ami a UNIX időt adja vissza longint-ben. A Vagy megoldás érvényesült ebben az estben is. 

De mi is az a Unix Idő?

A Unix-idő vagy POSIX idő a számítástechnikában a UTC szerinti 1970. január 1. éjfél óta eltelt másodpercek száma, a szökőmásodperceket nem számolva. A Unix-szerű operációs rendszerek mellett számos más alkalmazásban is használják. A Unix-idő, bár sokan tévesen annak hiszik, valójában nem lineáris reprezentációja az időnek, és nem valódi reprezentációja a UTC-nak, mert a szökőmásodperceket nem lehet vele megadni.

— Forrás —

Az átálláshoz szükséges időpontokat a szemléltetés és az átláhatóság kedvéért így deklaráltam.

long firstokt = ((86400*365*49)+(300*86400)+(11*86400)+(2*3600));   // 2019. október 27.  3:00 UTC + 1
long secondmarch = ((86400*365*50)+(91*86400)+(12*86400)+(1*3600)); // 2020. március 31.  2:00 UTC + 2
long secondokt = ((86400*365*50)+(299*86400)+(12*86400)+(2*3600));  // 2020. október 25.  3:00 UTC + 1
long thirdmarch = ((86400*365*51)+(87*86400)+(12*86400)+(1*3600));  // 2021. március 28.  2:00 UTC + 2
long thirdokt = ((86400*365*51)+(304*86400)+(12*86400)+(2*3600));   // 2021. október 31.  3:00 UTC + 1

Ez a dolog összefüggésében így értelmezendő: 1970 óra eltelt évek + az adott év eltelt napjai + 1970 óta eltelt szökőévek száma + az óraátállítás időpontja. Szerencsére a 2000-es évet mint szökőévet is be kellett számolni, mert 400-al osztható. Így ezen sem kellett pluszba gondolkozni.

Lássuk a kódot teljes kódot:

#include <MD_MAX72xx.h>
#include <SPI.h>
#include <NTPClient.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

const char *ssid     = "Arpanet";
const char *password = "MH86Helezd";
char timeprint[20]="";
String timenow;

// Óraátállítás időpontok 

long firstokt = ((86400*365*49)+(300*86400)+(11*86400)+(2*3600));           // 2019. október 27.  3:00 UTC + 1
long secondmarch = ((86400*365*50)+(91*86400)+(12*86400)+(1*3600));         // 2020. március 31.  2:00 UTC + 2
long secondokt = ((86400*365*50)+(299*86400)+(12*86400)+(2*3600));          // 2020. október 25.  3:00 UTC + 1
long thirdmarch = ((86400*365*51)+(87*86400)+(12*86400)+(1*3600));          // 2021. március 28.  2:00 UTC + 2
long thirdokt = ((86400*365*51)+(304*86400)+(12*86400)+(2*3600));           // 2021. október 31.  3:00 UTC + 1

long eltelt; 
int daynow; String nap;
int monthnow; String honap;
int yearnow; String ev;
int hoursnow; String ora;
int hours_summer; String hour;
int minutesnow; String perc;
int secondsnow; String mperc;

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

#define  DEBUG  0
#if  DEBUG
#define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }
#define PRINTS(x) Serial.print(F(x))
#define PRINTD(x) Serial.println(x, DEC)
#else
#define PRINT(s, x)
#define PRINTS(x)
#define PRINTD(x)
#endif
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 8
#define CLK_PIN   D5 //  SCK
#define DATA_PIN  D7 //  MOSI
#define CS_PIN    D8 //  SS

MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
#define  DELAYTIME  200  // millisecundum

void scrollText(char *p)
{
  uint8_t charWidth;
  uint8_t cBuf[10];  // Karakterek száma

  PRINTS("\nScrolling text");
  mx.clear();
  while (*p != '\0')
  {
    charWidth = mx.getChar(*p++, sizeof(cBuf) / sizeof(cBuf[0]), cBuf);
    for (uint8_t i=0; i<=charWidth; i++)	
    {
      mx.transform(MD_MAX72XX::TSL);
      if (i < charWidth)
        mx.setColumn(0, cBuf[i]);
      delay(DELAYTIME);
    }
  }
}

void setup()
{
 Serial.begin(115200);
  WiFi.begin(ssid, password);
  if ( WiFi.status() != WL_CONNECTED ) 
  {
    delay ( 500 );
    Serial.print ("\nNo Wifi");
  }
  timeClient.begin();
  mx.begin();

#if  DEBUG
  Serial.begin(115200);
#endif
}

void loop()
{
timeClient.update();
daynow = timeClient.getDayNow();
monthnow = timeClient.getMonth();
yearnow = timeClient.getYear();
hoursnow = timeClient.getHours();
hours_summer = timeClient.getHours()+1;
minutesnow = timeClient.getMinutes();
secondsnow = timeClient.getSeconds();
eltelt = timeClient.getEpochTime();

mperc = String (secondsnow);
perc = String(minutesnow);
ora = String(hours_summer);
hour = String(hoursnow);
ev = String (yearnow);
honap = String (monthnow);
nap = String (daynow);

if (eltelt <= firstokt)
{
if (hours_summer<10) { ora = "0"+ora; }
if (minutesnow<10) { perc = "0"+perc; }
if (secondsnow<10) { mperc = "0"+mperc;}
timenow = (ora+":"+perc+":"+mperc);
timenow.toCharArray(timeprint, 20);
}
else if ((eltelt >= firstokt) && (eltelt <= secondmarch))
{
if (hoursnow<10) { hour = "0"+hour; }
if (minutesnow<10) { perc = "0"+perc; }
if (secondsnow<10) { mperc = "0"+mperc;}
timenow = (hour+":"+perc+":"+mperc);
timenow.toCharArray(timeprint, 20);
}
else if ((eltelt >= secondmarch) && (eltelt <= secondokt))
{
if (hours_summer<10) { ora = "0"+ora; }
if (minutesnow<10) { perc = "0"+perc; }
if (secondsnow<10) { mperc = "0"+mperc;}
timenow = (ora+":"+perc+":"+mperc);
timenow.toCharArray(timeprint, 20);
}
else if ((eltelt >= secondokt) && (eltelt <= thirdmarch))  
{
if (hoursnow<10) { hour = "0"+hour; }
if (minutesnow<10) { perc = "0"+perc; }
if (secondsnow<10) { mperc = "0"+mperc;}
timenow = (hour+":"+perc+":"+mperc);
timenow.toCharArray(timeprint, 20);
}
else if ((eltelt >= thirdmarch) && (eltelt  <= thirdokt))  
{
if (hours_summer<10) { ora = "0"+ora; }
if (minutesnow<10) { perc = "0"+perc; }
if (secondsnow<10) { mperc = "0"+mperc;}
timenow = (ora+":"+perc+":"+mperc);
timenow.toCharArray(timeprint, 20);
}
else if (eltelt >= thirdokt)  
{
if (hoursnow<10) { hour = "0"+hour; }
if (minutesnow<10) { perc = "0"+perc; }
if (secondsnow<10) { mperc = "0"+mperc;}
timenow = (hour+":"+perc+":"+mperc);
timenow.toCharArray(timeprint, 20);
}
//-----------------------------------------------------------------------------------------------//
#if 1
if ( WiFi.status() != WL_CONNECTED )
{
scrollText("No Wifi");
WiFi.begin(ssid, password);
}
else
{
  scrollText(timeprint);
  Serial.println("\nWinter time: "+timeClient.getFormattedTime());
  Serial.println("Winte time: " + timeClient.getFullFormattedTime());
  Serial.println("Winter time: " + ev +"."+honap+"."+nap+" "+hour+":"+perc);
  Serial.println("Summer time: " + ev +"."+honap+"."+nap+" "+ora+":"+perc);
  delay(100); 
}
#endif
}

És lássuk a cuccot működés közben.

A bedobozolásra egyenlőre még nem volt időm, de ami késik nem múlik. Miután elkészültem, készítek egy utánlövést, a dolgoról. Ha észrevételed van akkor írj e-mailt nekem, vagy írj a komment szekcióba.

(Statisztika: 317 megtekintés)

Vélemény, hozzászólás?

Az email címet nem tesszük közzé.