Problema reale Timing

Ciao a tutti...

Sto affrontando un grosso problema con un programma che sto creando...

Principalmente e' un timer, e come modulo timing uso RV-2123-C2-TA-QC-020

Dovrebbe funzionare cosi:
Raggiunto un certo orario (ore e minuti) accendi una lampadina.
Raggiunto un altro certo orario (ore e minuti) spegni la lampadina.

Fino a qui tutto ok, molto banale...

Il problema nasce quando arduino, si spegne per un blackout per esempio... il modulo RTC continua a contare perche ha una batteria tampone, ma arduino non esegue il calcolo.
Risultato: abbiamo raggiunto l'orario di start o stop, ma l'operazione non e' stata eseguita.

Basterebbe aggiungere all'equazione:
if (oraCorrente >= oraStart && minutiCorrenti >= minutiStart) { ON }
if (oraCorrente >= oraStop && minutiCorrenti >= minutiStop) { OFF }

Peccato che cosi facendo entri in un loop senza fine ON OFF ON OFF...

Ragazzi le sto provando tutte, flag, salvataggi di stato in eeprom, variabili, altri void separati, switch case, altri if... e mi sono anche avvicinato tanto alla soluzione, ma qualcosa va sempre storta...

Qualche idea?

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

Manno
Deve solo riscrivere la condizione di accensione, ma sembra che 15 mesi a pensare allo stesso problema non siano bastati
Anche per gli ingannieri, il consiglio è sempre quello:
Scrivetevi il programma in Italiano, vedrete che se riuscite a scriverlo in Italiano riuscirete anche in ‘C’

Boh, a me sembra solo un problema di logica…

Se hai un solo intervallo di accensione ON-OFF come mi sembra di capire:

if (oraCorrente >= oraStart && minutiCorrenti >= minutiStart && (oraCorrente < oraStop || minutiCorrenti < minutiStop) )
{ ON }
else if (oraCorrente >= oraStop && minutiCorrenti >= minutiStop) 
{ OFF }

Se però accorpi l’orario in una sola variabile intera fai prima e ti impicci di meno con le condizioni, esempio:

unsigned int tOraCorrente = oraCorrente*60+minutiCorrenti;
unsigned int tOraStart = oraStart*60+minutiStart;
unsigned int tOraStop = oraStop*60+minutiStop;
...
if (tOraCorrente >= tOraStart && tOraCorrente < tOraStop) 
{ ON }
else if (tOraCorrente >= tOraStop )
{ OFF }

È un problema di logica, concordo con docdoc
Però se un problema così banale non si risolve in 15 mesi, a me non resta altro da dire
Comunque purtroppo la prima delle due soluzioni proposte da docdoc non è adatta:
A causa della valutazione a corto circuito sbaglierebbe se a lampada che dovrebbe essere accesa i minuti fossero "inferiori" alla loro soglia;serve infilarci dentro un po' di parentesi

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; }

Questa proprio no

Aggiorna la pagina :slight_smile:

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 :wink:

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...