Problema reale Timing

Aggiorna la pagina :)

Mi piace

Bene, ora resta solo da vedere cosa succede se 'tOraStart' sono le 22 e 'tOraStop'sono le 2 di mattina :smiling_imp:

Uffa! Contiamo anche giorno, mese e anno e risolviamo il problema fino alla fine dei secoli! :slight_smile:
Ah… Dobbiamo trovare come farlo funzionare in Paradiso, perché lì non c’è il tempo!

unsigned long tOraCorrente = annoCorrente*100000000 +meseCorrente*1000000 +giornoCorrente*10000+oraCorrente*60+minutiCorrenti;
unsigned long tOraStart = annoStart*100000000 +meseStart*1000000 +giornoStart*10000+oraStart*60+minutiStart;
unsigned long tOraStop = annoStop*100000000 +meseStop*1000000 +giornoStop*10000+oraStop*60+minutiStop;
byte acceso=0;
...
if (tOraCorrente>=tOraStart && tOraCorrente<tOraStop) 
  {
  if (acceso==0) { ON(); acceso=1; }
  }
else if (acceso==1)
{ OFF(); acceso=0; }

Claudio_FF: Bene, ora resta solo da vedere cosa succede se 'tOraStart' sono le 22 e 'tOraStop'sono le 2 di mattina :smiling_imp:

cambiamo fuso orario Scherzi a parte, se si vuole una pianificazione ciclica che sopravviva alla perdita di alimentazione rimettendosi a posto da sola al riavvio, si avrà sempre il problema dello overflow, che sia il passaggio da mezzanotte su 24 ore, passaggio da domenica su settimana, o San Silvestro all'anno Serve evitarlo cambiando lo offset

È come millis… solo che bisogna fare i calcoli in modulo 1440:

  • Calcolare intervallo ‘DT’ tra ora finale e ora iniziale
  • Calcolare intervallo ‘DA’ tra ora finale e ora attuale
  • Se DA <= DT e DA > 0: acceso else: spento
int dt = tOraStop - tOraStart;
if(dt < 0) dt += 1440;

int da = tOraStop - tOraCorrente;
if(da < 0) da += 1440;

if(da <= dt  &&  da > 0) { if(!acceso) { ON();  acceso = true; } }
else if(acceso)          { OFF();  acceso = false; }

EDIT: corretto errore da <= dt

fabpolli:
Sarebbe stato meglio allegare il codice intero ma conunque credo che una variabile di stato salvata in EEPROM potrebbe fare al caso tuo.
Es.

if (lampadinaAccesa &&oraCorrente >= oraStop && minutiCorrenti >= minutiStop)

{
 spengoLampadina();
 lampadinaAccesa = true;
 salvataggioInEEPROMStato(lampadinaAccesa);
}
if (!lampadinaAccesa && oraCorrente >= oraStart && minutiCorrenti >= minutiStart)
{
 accendoLampadina();
 lampadinaAccesa = true;
 salvataggioInEEPROMStato(lampadinaAccesa);
}



INel setup leggi dalla EEPROM lo stato in cui era la lampadina
Senza vedere il codice la soluzione potrebbe non essere comuque adatta al tuo caso, prova e/o allega il codcie in capo di problemi

Questa purtroppo di sicuro non funziona… gia provato a lungo, come scritto sopra…
(raga ma questi 15 mesi da dove gli avete tirati fuori???)

cambiamo fuso orario
Scherzi a parte, se si vuole una pianificazione ciclica che sopravviva alla perdita di alimentazione rimettendosi a posto da sola al riavvio, si avrà sempre il problema dello overflow, che sia il passaggio da mezzanotte su 24 ore, passaggio da domenica su settimana, o San Silvestro all’anno
Serve evitarlo cambiando lo offset

mmmmm non ho capito niente :smiley:

È come millis… solo che bisogna fare i calcoli in modulo 1440:

Calcolare intervallo ‘DT’ tra ora finale e ora iniziale
Calcolare intervallo ‘DA’ tra ora finale e ora attuale
Se DA <= DT acceso else spento

Claudio_FF cosa intendi?

Raga il calcolo che dovrebbe fare e' solo giornaliero... il fuso orario lo aggiorneranno loro quando sara' il momento... questa schedina deve accendere e spegnere "la luce" ogni giorno all'ora preimpostata (che gli viene inviata da seriale tramite Nextion display)... non vi posto tutto il codice solo perche' e' immenso... poi se volete ve lo mando tranquillamente... Sto facendo una serra automatizzata enorme.

matt-korban:
Claudio_FF cosa intendi?

Oggi è una giornata strana, sarà perché ho deciso di farmi crescere il pizzetto o perché ho ordinato una stampante 3D?

In che senso cosa intendo?

Dataman ha fornito la soluzione più semplice al post #5 (non serve memorizzare niente da nessuna parte, semplicemente si controlla se l’ora attuale è all’interno dell’intervallo acceso oppure no).

L’unico inconveniente è che non funziona se l’ora di spegnimento è dopo la mezzanotte mentre l’ora di accensione è prima di mezzanotte.

La mia aggiunta è il calcolo + codice di esempio che corregge quell’unica mancanza nel codice del post #5 ( i calcoli sono fatti con un tempo in minuti che va da 0 a 1439 come da post #5).

Ancora più semplice:

if(oraStop<oraStart) oraStop+=24; // Vuol dire che è del giorno dopo.
unsigned int tOraCorrente = oraCorrente*60+minutiCorrenti;
unsigned int tOraStart = oraStart*60+minutiStart;
unsigned int tOraStop = oraStop*60+minutiStop;
byte acceso=0;
...
if (tOraCorrente>=tOraStart && tOraCorrente<tOraStop)
  {
  if (acceso==0) { ON(); acceso=1; }
  }
else if (acceso==1)
{ OFF(); acceso=0; }

Datman: Ancora più semplice:

E come tutte le cose troppo belle per... la parte destra della condizione risulterebbe sempre vera, mentre quella sinistra dopo mezzanotte diventerebbe sempre falsa ;)

matt-korban: Questa purtroppo di sicuro non funziona... gia provato a lungo, come scritto sopra... (raga ma questi 15 mesi da dove gli avete tirati fuori???)

Ho sbagliato io, sono solo 3

Claudio, ho solo aggiunto la prima riga...

Datman & Claudio...

Sta funzionando... ho preso il consiglio di datman, con l'aggiunta dt/da di Claudio, e per ora sta funzionando meglio di come lo avevo fatto io... Va provato bene, vi aggiornero'...

Per ora ho notato che in linea di massima va bene, giusto qualche fesseria... - Spegne sempre un minuto dopo il minuto impostato (se deve spegnere alle 22:10, spegne alle 22:11) - Nel momento in cui passa la mezzanotte fa un piccolo ON-OFF-ON (ho impostato come ON le 23:58 e come OFF 00:02, quindi era ON, e nel momento del passaggio a 00:00, ha fatto un OFF-ON, poi tutto regolare)

Dovendo installare il sistema in una grossa serra di Canapa (esatto, proprio lei, quella legale pero!) devo essere sicuro che funzioni alla grande... Se volete vi passo il programma, ma e' bello grosso, e creato per essere comandato da un Nextion Display. Il sistema completo e' composto da 4 plc Controllino slave, connessi via modbus RS485 ad un plc master collegato al display.

Un minuto dopo??? Strano… La condizione di accensione è:

if (tOraCorrente>=tOraStart && tOraCorrente<tOraStop)

a meno che tu abbia scritto && tOraCorrente<=tOraStop
o che il loop() faccia solo 1 giro al minuto…

Per lo spegnimento a mezzanotte è strano anche quello…
Che fa se carichi il mio blocco delle 17.42 (messaggio #16)?

Datman:
Un minuto dopo??? Strano… La condizione di accensione è:

Per il minuto in più è un mio errore del post #12, adesso corretto.

Per l’ OFF/ON di mezzanotte non saprei. Nell’esempio di Dataman mi era sfuggito che usava variabili unsigned per ‘tOraCorrente’, ‘tOraStart’, ‘tOraStop’. Ma vedo che anche calcolando senza segno la condizione rimane valida:

intervallo-orario.png

Claudio_FF:
Bene, ora resta solo da vedere cosa succede se ‘tOraStart’ sono le 22 e 'tOraStop’sono le 2 di mattina :smiling_imp:

Infatti nel post dove ho messo il primo codice di esempio l’ho scritto: “se hai un solo intervallo di accensione ON-OFF”… :wink:

Se è OFF-ON (es. una luce notturna) basta cambiare la condizione (ho anche rimosso la seconda if(), inutile):

if (tOraCorrente >= tOraStart || tOraCorrente < tOraStop) 
{ ON }
else
{ OFF }

Oppure per rendere tutto più flessibile (ossia indipendentemente se START<STOP o STOP<START):

if ( (tOraStop>tOraStart && (tOraCorrente >= tOraStart && tOraCorrente < tOraStop) ) ||
     (tOraStop<tOraStart && (tOraCorrente >= tOraStart || tOraCorrente < tOraStop)) )
{ ON }
else
{ OFF }

Scusate, ma che ce ne importa se l'ora di spegnimento è minore di quella di accensione?... Noi stiamo considerando solo ore e minuti, quindi c'è un minuto intero a disposizione e spero vivamente che il ciclo giri a una velocità superiore a uno al minuto! Perciò basta usare "uguale" e il problema non c'è più! :-)

Uhmm... Se manca la corrente?... Ma gli RTC hanno una sveglia interna... Non si potrebbe usare vantaggiosamente?

Datman:
Uhmm… Se manca la corrente?..

Eh già, la richiesta era proprio quella… :wink:

Ovviamente per evitare continue “riaccensioni” (o spegnimenti) quando è già accesa (o spenta) si usa un ulteriore test memorizzando lo stato corrente, come hai fatto tu “ampliando” il mio codice. :wink:

Anzi, non userei neanche una variabile, ma leggerei direttamente la porta. Una cosa del tipo (chiaramente il nome/numero della porta può variare, non avendo l’intero programma non so quale sia):

if ( (tOraStop>tOraStart && (tOraCorrente >= tOraStart && tOraCorrente < tOraStop) ) ||
     (tOraStop<tOraStart && (tOraCorrente >= tOraStart || tOraCorrente < tOraStop)) )
{ 
  // ON
  if ( digitalRead(LUCE) == LOW ) 
    digitalWrite(LUCE, HIGH);
}
else
{ 
  // OFF
  if ( digitalRead(LUCE) == HIGH ) 
    digitalWrite(LUCE, LOW);
 }

Ragazzi il discorso e', che questa scheda e' all'interno di una serra industriale... percio' non posso permettermi cagate...

Se manca la corrente per esempio, l'RTC continua ad andare per 2 settimane, nessun problema, ma il micro non esegue il controllo/paragone tra l'orario corrente e l'orario di accensione...

Ecco perche' non basta mettere un =, ma serve un >=, perche' se manca corrente nel momento in cui abbiamo raggiunto l'orario di accensione, il micro non accende nulla! Quando la corrente sara' tornata, dovra' verificare se abbiamo superato l'orario di accensione, e rimediare accendendo le luci...

Il comando di accensione, deve essere inviato una sola volta al cambio di stato, e inviato nuovamente in caso di blackout. Questo perche', non accende realmente una lampadina, ma invia tramite modbus un comando al PLC della relativa stanza che accendera' la luce... Se invia il telegramma 50 volte, perche' il loop gira a manetta, impalla il PLC slave.