Ciao a tutti, vorrei effettuare una serra domotica, con l'obbiettivo di effettuare l'irrigazione all'alba. Il dispositivo che ho preso in esame è l'esp32 e data la sua funzionalità avevo pensato di prelevare la data e l'orario tramite NTP. Ho studiato il funzionamento tramite il seguente codice che ho trovato in rete:
Come al solito, il mio consiglio quando si fanno operazioni con "il tempo" è di lavorare usando il formato unix time (rappresentato come offset in secondi rispetto alla mezzanotte del 1º gennaio 1970).
In questo modo per identificare in modo univoco un preciso istante è sufficiente una sola variabile unsigned long
Per conoscere con precisione a che ora è alba o tramonto, so che esistono dei siti web che espongono delle API oppure potresti definire due array di unsigned long (uno per alba e uno per tramonto).
A quel punto basta confrontare lo unix time attuale con quello dell'array (o restituito dal sito web) e con un semplice confronto booleano sai quando devi fare quel che devi.
Ciao grazie per la risposta, per quanto riguarda il metodo unix time ho preferito non utilizzarlo perché è un po' scomodo il settaggio dell'ora reale e l'utilizzo di variabili unsigned long occupano spazio inutilmente. Comunque ho risolto il problema, non conoscevo la libreria NTPClient.h che offre la possibilità di ottenere i dati temporali , in NTP, con variabili short o int
Se usi un server NTP che c'è da settare? L'ora corretta la prendi dal server.
L'ESP32 inoltre ha già ampio supporto a livello di core per sincronizzare il tempo con un server NTP, non sono necessarie altre dipendenze esterne.
E comunque per quanto riguarda le librerie, TUTTE quelle che hanno a che fare con il tempo (NTP, RTC etc etc) usano sotto il cofano il formato unix time (detto anche epoch time) per poi esporre diversi metodi per "estrapolare" giorni, mesi, ore, minuti etc etc in formato "human readable".
Per come la vedo io, rappresentare il tempo secondo questo formato, ha senso solo quando si deve interagire con un utente (tempo sul display e/o monitor seriale, inserimento di date etc etc).
Ma per "farci i conti" o confrontare intervalli è solo un'inutile complicazione del codice e spreco di risorse della MCU.
Se ho due minuti più tardi trasformo gli spezzoni di codice messi qua e la in uno sketch completo, magari includendo la libreria per calcolare ora di alba e tramonto (ce ne sono diverse nel library manager).
@ale195 ecco lo sketch!
Spero possa essere un buon punto di partenza per il tuo progetto.
La libreria inclusa non è molto precisa (ce n'è un'altra che da risultati più vicini a quelli reali, ma bisogna metterci le mani per compilare con ESP32)
Ad esempio per oggi 09 Giugno 2021 mi da i seguenti risultati per Roma centro. Alba: 05:22; Tramonto: 20:44
quando dovrebbero essere in realtà Alba: 05:35; Tramonto: 20:44
Sbaglia di qualche minuto l'ora dell'alba come vedi, ma credo che sia del tutto trascurabile per la tua applicazione.
#include <WiFi.h>
#include <time.h>
const char* ssid = "xxxxxxx";
const char* password = "xxxxxxxxx";
// Libreria per il calcolo di alba e tramonto (la trovi nel gestore librerie)
#include <sunset.h>
/* Coordinate di Roma */
#define LATITUDE 41.8954F
#define LONGITUDE 12.5080F
#define DST_OFFSET 1
// Definizione del timezone
// Central EST Europe + 1, intervallo ora legale
#define MYTZ "CET-1CEST,M3.5.0,M10.5.0/3"
struct tm tInfo; // Struct che contiene le informazioni "human readable" relative al tempo
SunSet sun; // Istanza della libreria per il calcolo alba/tramonto
int sunrise; // Minuti dalla mezzanotte (cfr. documentazione libreria)
int sunset; // Minuti dalla mezzanotte (cfr. documentazione libreria)
int prevDay = -1; // Variabile di controllo per aggiornare la libreria quando cambia il giorno
uint32_t unixTime; // Variabile per il valore del tempo attuale (aggiornato ogni secondo)
uint32_t startOfDay; // Variabile per il momento "unix time" che corrisponde all'inizio del giorno attuale
void setup(){
Serial.begin(115200);
sun.setPosition(LATITUDE, LONGITUDE, DST_OFFSET);
// Connect to Wi-Fi
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected.");
// Init and get the time
configTzTime(MYTZ, "time.google.com", "time.windows.com", "pool.ntp.org");
checkNewDay();
//disconnect WiFi as it's no longer needed
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
}
void loop(){
static uint32_t checkTime;
if(millis() - checkTime > 9999) {
checkTime = millis();
checkNewDay();
}
getLocalTime(&tInfo); // Aggiorno la struct tInfo
unixTime = mktime(&tInfo); // Tempo attuale in formato unix time
// Se vuoi provare il funzionamento senza aspettare l'alba o il tramonto
// sovrascrivi le variabili sunrise e sunset con dei valori "comodi" ORE + MINUTI
sunrise = 15 * 3600 + 14 * 60; // 15:14
sunset = 15 * 3600 + 15 * 60; // 15:15
// Controlliamo se è l'alba o il tramonto
if (unixTime == (startOfDay + sunrise) ) {
Serial.println("E' l'alba");
// *****************************************************
// N.B. Questo blocco rimane attivo per un secondo intero
delay(200); // Evitiamo di stampare decine di volte il messaggio
// *****************************************************
}
if (unixTime == (startOfDay + sunset)) {
Serial.println("E' il tramonto");
// *****************************************************
// N.B. Questo blocco rimane attivo per un secondo intero
delay(200); // Evitiamo di stampare decine di volte il messaggio
// *****************************************************
}
}
void checkNewDay(){
getLocalTime(&tInfo); // Aggiorno la struct tInfo
unixTime = mktime(&tInfo); // Tempo attuale in formato unix time
// Calcolo l'ora di alba e tramonto solo quando cambia il giorno corrente
if( tInfo.tm_mday != prevDay) {
prevDay = tInfo.tm_mday;
startOfDay = unixTime - tInfo.tm_hour*3600UL - tInfo.tm_min*60UL - tInfo.tm_sec;
Serial.printf("Inizio del giorno (unix time): %d\n", startOfDay);
// Aggiorniamo la libreria con la data attuale
sun.setCurrentDate(tInfo.tm_year, tInfo.tm_mon, tInfo.tm_mday);
// Se c'è l'ora legale l'offset è di 2 ore
if(tInfo.tm_isdst) {
sun.setTZOffset(DST_OFFSET + 1);
}
else {
sun.setTZOffset(DST_OFFSET);
}
sunrise = sun.calcCivilSunrise();
sunset = sun.calcCivilSunset();
Serial.printf("Alba: %02d:%02d; Tramonto: %02d:%02d\n", sunrise/60, sunrise%60, sunset/60, sunset%60);
sunrise = sunrise*60; // Abbiamo bisogno del numero dei secondi per confrontare con unixTime
sunset = sunset*60; // Abbiamo bisogno del numero dei secondi per confrontare con unixTime
}
// Stampa sul monitor seriale ora e data corrente
// Per la scelta del "format specifier", fai riferimento qui:
// https://www.cplusplus.com/reference/ctime/strftime/
Serial.println(&tInfo, "%A, %B %d %Y %H:%M:%S");
}