Codice.txt (2.9 KB)
Output.txt (2.8 KB)
Un saluto a tutti, mi sono presentato ed ora mi accingo a fare il mio primo post nel forum.
Sto facendo parti di codice che poi userò per un progetto più ampio (se mai riuscirò a realizzarlo).
Ho postato poco sopra il codice che utilizzo e che formalmente non ha errori insieme all'output ottenuto.
Non capisco perchè lo stesso codice che interroga lo stesso server possa dare date "random".
Qualcuno che ha più esperienza di me mi può aiutare a capire?
Ciao e grazie
Americo
Per facilitare il lavoro a tutti, ma specie a quelli che leggono da smatphone, codice e testi vanno, nei limiti del possibile, inseriti direttamente nel post racchiudendoli nei tag CODE (ovvero, dopo averlo inserito, seleziona la parte di codice e premi l'icona <code/> nella barra degli strumenti per contrassegnarla come codice). Grazie,
Guglielmo
OK.....Scusate
Questo è il codice:
/*
* Tiene aggiornata l'ora su arduino Mega
*/
#include <NTPClient.h>
#include <WiFiEsp.h>
#include "WiFiEspUdp.h"
#include <RTClib.h>
WiFiEspServer server(80);
WiFiEspUDP ntpUDP;
NTPClient timeClient(ntpUDP, "it.pool.ntp.org", 3600);
RTC_DS3231 rtc;
unsigned long ISTANTE = 0; //Fissa un punto nel tempo con millis()
unsigned long Old_ISTANTE = 0; //Vecchio valore di millis()
String DataFormattata; //Data restituita dall'NTP Client (2023-10-03T12:03:25K)
uint32_t EpochTime; //Secondi trascorsi dal 01/01/1970
String Giorno, Mese, Anno, Ora, Minuto, Secondo; //Variabili divise
int status = WL_IDLE_STATUS; // Stato iniziale della WiFi
void setup() {
Serial.begin(115200);delay(10); // Iniziallizza la serriale per comunicazione co PC
Serial2.begin(115200);delay(10); // Iniziallizza la serriale del WiFi Esp-01
//Inizializza il modulo RTC
Serial.println("Inizializzo modulo RTC");
if(!rtc.begin()){
Serial.println("Errore Modulo rtc");
return;
}
delay(50);
Serial.println("Modulo RTC Avviato");
//Si collega alla WiFi
Serial.println("Inizio Avvio WiFi");
WiFi.init(&Serial2);
if (WiFi.status() == WL_NO_SHIELD)
{
Serial.println("Non Ho trovato la scheda WiFi !!");
while (true);
}
while (WiFi.begin("SSID_WiFi", "PWD_WiFi") != WL_CONNECTED){;} //Aspetta fino a che la WiFi non è connessa
server.begin();
Serial.println("WiFi Attiva");
}
void Ottieni_Data_Web() // Ottiene la data dal server NTP ed aggiorna l'RTC
{
timeClient.begin();
delay(500);
while(!timeClient.update()){timeClient.forceUpdate();}
DataFormattata = timeClient.getFormattedDate(); //2023-10-03T12:03:25Z
EpochTime = timeClient.getEpochTime();
timeClient.end();
Giorno = DataFormattata.substring(8, 10);
Mese = DataFormattata.substring(5, 7);
Anno = DataFormattata.substring(0, 4);
Ora = DataFormattata.substring(11, 13);
Minuto = DataFormattata.substring(14, 16);
Secondo = DataFormattata.substring(17, 19);
Serial.println("Data Formattata: " + String(DataFormattata));
Serial.println("EpochTime: " + String(EpochTime));
rtc.adjust(DateTime(EpochTime));
delay(500);
DateTime Adesso = rtc.now();
// Stampa i valori ottenuti
printDateTime(Adesso);
Serial.println("Giorno: " + Giorno);
Serial.println("Mese: " + Mese);
Serial.println("Anno: " + Anno);
Serial.println("Ora: " + Ora);
Serial.println("Minuto: " + Minuto);
Serial.println("Secondo: " + Secondo);
Serial.println("");
Serial.println("");
}
void printDateTime(DateTime dt)
{
char dateBuffer[] = "DD/MM/YYYY ";
char timeBuffer[] = "hh:mm:ss ";
Serial.print(dt.toString(dateBuffer));
Serial.println(dt.toString(timeBuffer));
}
void loop() {
ISTANTE = millis();
if (ISTANTE > Old_ISTANTE + 30000)
{
Ottieni_Data_Web();
Old_ISTANTE = millis();
}
}
E questo è l'Output:
16:35:11.055 -> Inizializzo modulo RTC
16:35:11.102 -> Modulo RTC Avviato
16:35:11.102 -> Inizio Avvio WiFi
16:35:11.102 -> [WiFiEsp] Initializing ESP module
16:35:14.516 -> [WiFiEsp] Initilization successful - 2.0.0
16:35:21.559 -> [WiFiEsp] Connected to XXXXXXXX
16:35:21.559 -> [WiFiEsp] Server started on port 80
16:35:21.559 -> WiFi Attiva
16:35:44.667 -> [WiFiEsp] TIMEOUT: 7
16:35:44.667 -> Data Formattata: 1977-08-15T10:18:56Z
16:35:44.667 -> EpochTime: 240488336
16:35:45.182 -> 20/09/2013 16:47:12
16:35:45.182 -> Giorno: 15
16:35:45.182 -> Mese: 08
16:35:45.182 -> Anno: 1977
16:35:45.182 -> Ora: 10
16:35:45.182 -> Minuto: 18
16:35:45.182 -> Secondo: 56
16:35:45.182 ->
16:35:45.182 ->
16:36:15.702 -> Data Formattata: 1977-08-15T10:19:29Z
16:36:15.702 -> EpochTime: 240488369
16:36:16.217 -> 20/09/2013 16:47:45
16:36:16.217 -> Giorno: 15
16:36:16.217 -> Mese: 08
16:36:16.217 -> Anno: 1977
16:36:16.217 -> Ora: 10
16:36:16.217 -> Minuto: 19
16:36:16.217 -> Secondo: 29
16:36:16.217 ->
16:36:16.217 ->
16:36:49.823 -> [WiFiEsp] TIMEOUT: 3
16:36:49.823 -> Data Formattata: 1975-04-30T14:17:07Z
16:36:49.823 -> EpochTime: 168099427
16:36:50.340 -> 05/06/2011 20:45:23
16:36:50.340 -> Giorno: 30
16:36:50.340 -> Mese: 04
16:36:50.340 -> Anno: 1975
16:36:50.340 -> Ora: 14
16:36:50.340 -> Minuto: 17
16:36:50.340 -> Secondo: 07
16:36:50.340 ->
16:36:50.340 ->
16:37:20.865 -> Data Formattata: 1975-04-30T14:17:40Z
16:37:20.865 -> EpochTime: 168099460
16:37:21.379 -> 05/06/2011 20:45:56
16:37:21.379 -> Giorno: 30
16:37:21.379 -> Mese: 04
16:37:21.379 -> Anno: 1975
16:37:21.379 -> Ora: 14
16:37:21.379 -> Minuto: 17
16:37:21.379 -> Secondo: 40
16:37:21.379 ->
16:37:21.379 ->
16:37:55.031 -> [WiFiEsp] TIMEOUT: 16
16:37:55.031 -> Data Formattata: 2036-02-07T07:28:16Z
16:37:55.031 -> EpochTime: 2085982096
16:37:55.544 -> 07/02/2036 07:28:16
16:37:55.544 -> Giorno: 07
16:37:55.544 -> Mese: 02
16:37:55.544 -> Anno: 2036
16:37:55.544 -> Ora: 07
16:37:55.544 -> Minuto: 28
16:37:55.544 -> Secondo: 16
16:37:55.544 ->
16:37:55.544 ->
16:38:26.075 -> Data Formattata: 2036-02-07T07:28:49Z
16:38:26.075 -> EpochTime: 2085982129
16:38:26.590 -> 07/02/2036 07:28:49
16:38:26.590 -> Giorno: 07
16:38:26.590 -> Mese: 02
16:38:26.590 -> Anno: 2036
16:38:26.590 -> Ora: 07
16:38:26.590 -> Minuto: 28
16:38:26.590 -> Secondo: 49
16:38:26.590 ->
16:38:26.590 ->
16:38:57.180 -> Data Formattata: 2023-03-19T16:38:56Z
16:38:57.180 -> EpochTime: 1679243936
16:38:57.692 -> 19/03/2023 16:38:56
16:38:57.692 -> Giorno: 19
16:38:57.692 -> Mese: 03
16:38:57.692 -> Anno: 2023
16:38:57.692 -> Ora: 16
16:38:57.692 -> Minuto: 38
16:38:57.692 -> Secondo: 56
16:38:57.692 ->
16:38:57.692 ->
Perché questa riga?
Ho dato un'occhiata agli esempi della libreria in questione e non viene mai usato un simile approccio.
Questo è riportato nel keywords.txt della libreria:
#######################################
# Datatypes (KEYWORD1)
#######################################
NTPClient KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
begin KEYWORD2
end KEYWORD2
update KEYWORD2
forceUpdate KEYWORD2
isTimeSet KEYWORD2
getDay KEYWORD2
getHours KEYWORD2
getMinutes KEYWORD2
getSeconds KEYWORD2
getFormattedTime KEYWORD2
getEpochTime KEYWORD2
setTimeOffset KEYWORD2
setUpdateInterval KEYWORD2
setPoolServerName KEYWORD2
In teoria se ci sono problemi di aggiornamento, con quell'istruzione avremo la certezza di avere dal server i dati aggiornati. Questo almeno quello che ho capito leggendo con quel poco di inglese che conosco.
Ho comunque provato anche solo con " timeClient.update(); " ma l'output rimane sempre con date randomiche...... ma non sempre.
Allora a questo punto probabilmente è la libreria che fa casini (nel repository c'è anche qualche issue aperta) e in effetti nell'output che hai messo mi pare di notare che il tempo è sballato sempre quando c'è un timeout.
Magari non è ottimizzata per lavorare in sincronia con la libreria WiFiEsp
Ad ogni modo l'utilizzo della libreria NTPClient secondo me è del tutto ridondante.
Nella libreria WiFiEsp c'è già incluso un esempio che mostra come prelevare l'epoch time da un server NTP senza ulteriori dipendenze.
Innanzitutto grazie per la dritta........ immaginavo potesse essere qualche passaggio tra le due librerie.
Ho dato uno sguardo sommario al codice dell'esempio che hai postato.
Avevo già provato quella strada ma poi mi sono perso........
Stasera provo di nuovo poi ti dico.
Io farei cosi:
- una funzione che interroga il server NTP e ritorna un unsigned long (epoch time) quando ha successo, 0 in caso di timeout
- quando è necessario impostare l'ora del modulo RTC chiami la funzione e se la risposta è positiva, fai quel che devi con il modulo.
Prendendo il codice paro paro dall'esempio di cui sopra:
void sendNTPpacket(char *ntpSrv)
{
//.... uguale a quello che già c'è
}
unsigned long getNTPTime(unsigned long timeout) {
sendNTPpacket(timeServer); // send an NTP packet to a time server
// wait for a reply for UDP_TIMEOUT miliseconds
unsigned long startMs = millis();
while (!Udp.available()){
if (millis() - startMs > timeout) {
Serial.println("Error: UDP timeout");
return 0;
}
Serial.println(Udp.parsePacket());
if (Udp.parsePacket()) {
// We've received a packet, read the data from it into the buffer
Udp.read(packetBuffer, NTP_PACKET_SIZE);
// the timestamp starts at byte 40 of the received packet and is four bytes,
// or two words, long. First, esxtract the two words:
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord;
// now convert NTP time into everyday time:
// Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
const unsigned long seventyYears = 2208988800UL;
// subtract seventy years:
unsigned long epoch = secsSince1900 - seventyYears;
return epoch;
}
}
}
// Quando necessario:
.....
unsigned long EpochTime = getNTPTime(UDP_TIMEOUT);
if (EpochTime > 0) {
Serial.print("EpochTime: ");
Serial.println(EpochTime)
rtc.adjust(DateTime(EpochTime));
delay(500);
DateTime Adesso = rtc.now();
// Stampa i valori ottenuti
printDateTime(Adesso);
}
....
Grazie cotestatnt, è stata una svolta!
L'esempio funziona alla grande. Ho solo aggiunto la correzione dell'ora locale, il codice per il modulo RTC e la conversione di DateTime in String (chce non è così immediata ed intuitiva).
Posto di seguito il mio codice funzionante e commentato se può essere utile a qualcuno.
Se ravvisate delle imprecisioni fatemi sapere.
/*
WiFiEsp example: UdpNTPClient
Modificato da Americo il 21/03/2023 per Arduino Mega2560
Aggiungendo il modulo RTC, gestione fuso orario e conversione di DateTime in Sting
N.B.: in Italia "time.nist.gov" dà dei problemi di comunicazione mandando
la richiesta UDP in timeout.
Meglio utilizzare "it.pool.ntp.org"
Get the time from a Network Time Protocol (NTP) time server.
Demonstrates use of UDP to send and receive data packets
For more on NTP time servers and the messages needed to communicate with them,
see http://en.wikipedia.org/wiki/Network_Time_Protocol
NOTE: The serial buffer size must be larger than 36 + packet size
In this example we use an UDP packet of 48 bytes so the buffer must be
at least 36+48=84 bytes that exceeds the default buffer size (64).
You must modify the serial buffer size to 128
For HardwareSerial modify _SS_MAX_RX_BUFF in
Arduino\hardware\arduino\avr\cores\arduino\SoftwareSerial.h
For SoftwareSerial modify _SS_MAX_RX_BUFF in
Arduino\hardware\arduino\avr\libraries\SoftwareSerial\SoftwareSerial.h
*/
#include "WiFiEsp.h" //Libreria per la comunicazione con l'ESP8266 (tramite comandi AT)
#include "WiFiEspUdp.h" //Libreria per protocollo UDP con il web
#include <RTClib.h> //Libreria per la gestione del modulo RTC
RTC_DS3231 rtc; //Crea un oggetto per il real time clock
WiFiEspUDP Udp; //Apre l'istanza per il server UDP
char ssid[] = "XXXXXX"; // Il nome della vostra rete WiFi
char pass[] = "123456"; //La password della vostra rete WiFi
int status = WL_IDLE_STATUS; // Stato della Wifi
char timeServer[] = "it.pool.ntp.org"; //NTP server "it.pool.ntp.org" , "time.nist.gov"
unsigned int localPort = 2390; //Porta locale per ricevere i pacchetti UDP dal Web
const int NTP_PACKET_SIZE = 48; // NTP timestamp is in the first 48 bytes of the message
const int UDP_TIMEOUT = 2000; // timeout in miliseconds to wait for an UDP packet to arrive
byte packetBuffer[NTP_PACKET_SIZE]; // buffer to hold incoming and outgoing packets
unsigned long ISTANTE = 0; //Fissa un punto nel tempo con millis()
unsigned long Old_ISTANTE = 0; //Vecchio valore di millis()
int Local_Ora = 1; //differenza di ora da UTC time
void setup()
{
Serial.begin(115200); //Inizializza serial monitor
//Inizializza la seriale per ESP8266
//(abbassare a 9600 se si usa SoftwareSerial)
//Modificare in Serial1 se la vostra scheda ha una sola seriale
Serial2.begin(115200);
WiFi.init(&Serial2); // Iniziallizza la comunicazione WiFi
//Inizializza il modulo RTC
Serial.println("Inizializzo modulo RTC");
if(!rtc.begin()){
Serial.println("Errore Modulo rtc");
return;
}
delay(50);
Serial.println("Modulo RTC Avviato");
// check for the presence of the shield
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue
while (true);
}
// attempt to connect to WiFi network
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass); //Connect to WPA/WPA2 network
}
Serial.println("You're connected to the network");
Udp.begin(localPort); // you're connected now, so print out the data
}
void Ottieni_Data_Web() // Ottiene la data dal server NTP ed aggiorna l'RTC
{
sendNTPpacket(timeServer); // send an NTP packet to a time server
unsigned long startMs = millis(); // wait for a reply for UDP_TIMEOUT miliseconds
while (!Udp.available() && (millis() - startMs) < UDP_TIMEOUT) {}
Serial.println(Udp.parsePacket());
if (Udp.parsePacket())
{
Serial.println("packet received");
Udp.read(packetBuffer, NTP_PACKET_SIZE); // We've received a packet, read the data from it into the buffer
// the timestamp starts at byte 40 of the received packet and is four bytes, or two words, long. First, esxtract the two words
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
// combine the four bytes (two words) into a long integer this is NTP time (seconds since Jan 1 1900)
unsigned long secsSince1900 = highWord << 16 | lowWord;
Serial.print("Seconds since Jan 1 1900 = ");
secsSince1900 = secsSince1900 + (Local_Ora * 3600);
Serial.println(secsSince1900);
Serial.print("Unix time = "); // now convert NTP time into everyday time
const unsigned long seventyYears = 2208988800UL; // Unix time starts on Jan 1 1970. In seconds, that's 2208988800
unsigned long epoch = secsSince1900 - seventyYears; // subtract seventy years
Serial.println(epoch); // print Unix time:
rtc.adjust(DateTime(epoch));
delay(500);
DateTime Adesso = rtc.now();
// print the hour, minute and second:
Serial.print("The UTC time is "); // UTC is the time at Greenwich Meridian (GMT)
Serial.print((epoch % 86400L) / 3600); // print the hour (86400 equals secs per day)
Serial.print(':');
if (((epoch % 3600) / 60) < 10)
{
Serial.print('0');// In the first 10 minutes of each hour, we'll want a leading '0'
}
Serial.print((epoch % 3600) / 60); // print the minute (3600 equals secs per minute)
Serial.print(':');
if ((epoch % 60) < 10)
{
Serial.print('0'); // In the first 10 seconds of each minute, we'll want a leading '0'
}
Serial.println(epoch % 60); // Secondi dal 01/01/1970
Serial.print("Data salvata nell'RTC = " + Converti_Time_To_String(Adesso));
}
}
void sendNTPpacket(char *ntpSrv) // send an NTP request to the time server at the given address
{
memset(packetBuffer, 0, NTP_PACKET_SIZE); // set all bytes in the buffer to 0
// 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(ntpSrv, 123); //NTP requests are to port 123
Udp.write(packetBuffer, NTP_PACKET_SIZE);
Udp.endPacket();
}
String Converti_Time_To_String(DateTime dt) //Converte una variabile DateTime in String
{
char buffer [25] = "";
sprintf(buffer, "%04d/%02d/%02d, %02d:%02d:%02d", dt.year(), dt.month(), dt.day(), dt.hour(), dt.minute(), dt.second());
String datetime = buffer;
return datetime;
}
void loop()
{
ISTANTE = millis();
if (ISTANTE > Old_ISTANTE + 10000)
{
Ottieni_Data_Web();
Old_ISTANTE = millis();
}
}
La discussione può essere indicata dagli amministratori come risolta.
Ciao a tutti e alla prossima
Americo
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.