Librerie time.h e Time Lib.h: intervallo di aggiornamento

Ciao a tutti

Tempo fa ho realizzato un orologio NTP a matrici di LED. Funziona, ma il LED blu dell'ESP8266 lampeggia continuamente e una radio AM, avvicinata, fa "toc-toc-toc" con periodo di un secondo.
Ho letto che i server NTP possono bannare chi legge l'orario continuamente, più spesso di una volta ogni 64 secondi o qualcosa del genere. L'intervallo di lettura dell'NTP dovrebbe essere di default ogni 10 minuti. Ho anche inserito setSyncInterval (600); ma non ho notato differenze.

Avevo usato la libreria time.h. Non riuscendo a trovarla fra quelle presenti con il gestore delle librerie, pur venendo il programma compilato e caricato senza problemi, ho installato la TimeLib.h, che forse è solo la versione nuova della stessa, ma nulla è cambiato.

Qualcuno mi sa dire come stanno esattamente le cose?

Grazie
Gianluca

#include <ESP8266WiFi.h> // URL aggiuntivo per il gestore schede: http://arduino.esp8266.com/stable/package_esp8266com_index.json
#include <SPI.h> // Mi sembra che funzioni anche senza...
#include <Adafruit_GFX.h> // Usato da Max72xxPanel
#include <Max72xxPanel.h> // Installare da zip: https://github.com/markruys/arduino-Max72xxPanel
// #include <time.h>
#include <TimeLib.h>

void scrive_orario()
{
time_t now = time(nullptr); // Facendo now variabile globale, perdeva il fuso orario.
if (now!=t_prec)
  {
  t_prec=now;
  matrix.fillScreen(LOW);
  String time = String(ctime(&now));
  time.trim();
  time.substring(11,19).toCharArray(time_value, 10);
  if(time_value[7]!=sec_prec) {t_prec=millis(); digitalWrite(D0, HIGH); sec_prec=time_value[7];/*GP16O|=1;*/} // Porta a livello alto la porta GPIO16 (D0).
  // Visualizza lo '0' iniziale prima delle ore 9.00:
  matrix.drawChar(P,0,    time_value[0], HIGH,LOW,1); // 
(...)
  }
}

void setup()
{
//ESP.wdtDisable();  // Disabilita il watchdog software.
//hw_wdt_disable();  // Disabilita il watchdog hardware.
pinMode(D0, OUTPUT); // 1Hz.
pinMode(sys_pin,INPUT_PULLUP); // Chiudere a massa durante il loop per leggere sysinfo.
pinMode(D6,INPUT_PULLUP); // Chiudere a massa in qualsiasi momento per capovolgere il display.
// Serial.begin(9600);
setSyncInterval(600); // 600 secondi.
se_capovolto(); // Imposta la disposizione delle matrici di LED leggendo lo stato dell'ampollina al mercurio.
(...)

void loop()
{
if(millis()-t_display>200)
  {
  t_display=millis();
  lum=map(analogRead(0),0,1023,0,15); matrix.setIntensity(lum); // Ogni 200ms legge il potenziometro (1023 con 3,3V).
  se_capovolto();
  }
scrive_orario();
(...)

Ancora non ho trovato una soluzione. Spesso, accendendo l'orologio, anziché indicare l'ora corrente, parte da 01:00:00 e va avanti. Potrebbe essere perché viene rifiutato da uno dei due server NTP che lo ha messo in blacklist?... No, non è per quello: se lascio uno solo dei due server, qualunque sia, qualche volta inizia con l'ora giusta e qualche altra no!
Allego il codice completo.

@cotestatnt e @steve-cr , ho visto una discussione in proposito in cui intervenivate. Potete aiutarmi?

Grazie!
Gianluca
Orologio_NTP_a_LED_v3.9g.zip (8.5 KB)

Non conosco bene la libreria TimeLib.h (e francamente con ESP8266 mi sembra anche abbastanza inutile), ma solitamente l'esp - una volta connesso al WiFi - ci mette qualche secondo per instaurare la connessione con il server e sincronizzare il system time.
Ti parte da 01:00:00 perché aggiunge l'ora del fuso orario italiano come offset, altrimenti partirebbe da 00:00:00

Io mi sono fatto una funzioncina che aspetta la sincronizzazione in modo bloccante con un timeout da inserire nel setup.

Ho fatto un esempio sul solito wokwi, anche se è lentissimo nel simulare l'ESP32 (va al 5-10% della velocità reale!! :persevere:)
Lo sketch ovviamente funziona anche su ESP8266.

wifi-NTP-time.ino - Wokwi Arduino and ESP32 Simulator


#include <NTPClient.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP); // 2nd parameter: difference in seconds between TIME ZONE 0

etc..
.etc..

      Serial.println ("Aggiornamento Ora Esatta da server NPT ");
      timeClient.update();
delay (1000);
    Hours = (timeClient.getHours());
    Minutes = (timeClient.getMinutes());
    Serial.print (Hours);  Serial.print (":");  Serial.println(Minutes);

Succede anche a me che, quando accendo il Wemos o premo reset, le ore e minuti sono a ZERO.
E il mio sistema e il mio programma sono diversi dal tuo.
Ciò mi conferma che il problema è il collegamento con il server NTP.
Ho messo un semplice delay e penso di aver risolto il problema, ma potrei fare anche due chiamate al timeClientUpdate ().

Facci sapere.

In realtà bastà fare un qualche cosa così ...

time_t now;
...
...
   while ( now < EPOCH_1_1_2019 ) {
      now = time ( nullptr );
      delay ( 500 );
      Serial.print ( "*" );
   }
...
...

così aspetti che l tempo sia un orari valido.

Guglielmo

Grazie anche a te, Guglielmo. Infatti mi sono reso conto che faccio solo un controllo di connessione, ma non che venga letto l'orario. Insieme al

while (WiFi.status()!=WL_CONNECTED)

devo verificare che l'anno sia diverso dal 1970.

Con:

while(year()<2020) {now = time(nullptr);}

ottengo l'errore:
exit status 1
assignment of function 'time_t now()'

Ma addirittura:
now = time(nullptr);

exit status 1
assignment of function 'time_t now()'

Nel programma che trovai e ho adottato per il mio orologio veniva dichiarata una variabile time_t now, che è una variabile locale che va a sovrapporsi a quella già definita nella libreria!

Probabilmente la libreria definisce una funzione now().
Prova a cambiare nome alla variabile.

Ho anche provato come hai detto tu, Guglielmo, ma mi da lo stesso problema!

while (WiFi.status()!=WL_CONNECTED);
delay(1000);
while(now<EPOCH_1_1_2019) {now = time(nullptr);}

Confermo...

Time/TimeLib.h at master · PaulStoffregen/Time (github.com)

//GLOBALE:
time_t adesso=0;


while (WiFi.status()!=WL_CONNECTED);
delay(1000);
while(adesso<EPOCH_1_1_2019) {adesso = time(nullptr);}

exit status 1
'EPOCH_1_1_2019' was not declared in this scope

Come esce "adesso"?

Non mi è assolutamente chiaro il funzionamento della libreria! :frowning:

Guarda, io nel mio programma per ESP8266 ho le seguenti include:

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <Wire.h>
#include <time.h>
#include "timezone.h"

la Wire.h mi serve per degli oggetti I2C :wink:

Ti allego timezone.h: timezone.h.zip (550 Bytes)

Guglielmo

Io, non capendo se e dove era installata la time.h, ho installato e usato la timeLib.b, che supporta anche setSyncInterval(600); . Non ho capito se quella libreria è una nuova versione della time.h...

Adesso uso nuovamente time.h, ma non digerisce il confronto

if (adesso<EPOCH_1_1_2019)

Di che tipo è EPOCH? E' una macro? Evidentemente non ce l'ho definita!
adesso l'ho dichiarata time_t... La dichiaro int32_t e la confronto con 3600000 (1000 ore)?

La time.h fa parte delle librerie di BASE del 'C', come <stdio.h>, <string.h>, ecc. ecc. quindi devi SOLO includerla.

Ti serve anche la timezone.h che ti ho allegato che serve per le varie costanti e le varie time zone.

Guglielmo

... anche se QUESTA è quella per AVR, puoi fare comunque riferimento a questa documentazione o cercare la documentazione più completa su internet.

Guglielmo

Il calcolo del fuso è già presente, senza usare timezone.h. Come sempre, il programma che presi come base sarà stato un impiastro di chissà quanta roba appiccicata insieme... :frowning:
Comunque così funziona:

while(adesso<3600000) {adesso = time(nullptr);}

Non fallisce un colpo! :slight_smile:

Resta da capire se legge il server ogni secondo e se i server NTP bannano in caso di letture troppo frequenti.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.