accendi relè da modulo RTC, richiesta semplice

Ciao a tutti, ho bisogno di una casetta molto semplice pr voi, difficile per me :slight_smile:
Questo è lo sketch che riporta su un display a doppia riga il tempo e la data attuale, ma senza nessuna azione.

#include <Wire.h>
#include <RTClib.h>
#include <LiquidCrystal.h>
char buffer1[20];
char buffer2[20];
RTC_DS1307 RTC;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int setpin = 6;
boolean statepin = 0;
void setup () {
  pinMode (6, INPUT);
  digitalWrite (6, HIGH);
  Wire.begin();
  RTC.begin();
  lcd.begin(16, 2);
  if (! RTC.isrunning()) {
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }
}
void loop () {
  statepin = digitalRead (setpin);
  if (statepin == LOW)
  {
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }
  DateTime now = RTC.now();
  sprintf(buffer1,  "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
  lcd.setCursor(0,0);
  lcd.print( buffer1 );
  sprintf(buffer2,  "%02d/%02d/%d", now.day(), now.month(), now.year());
  lcd.setCursor(0,1);
  lcd.print( buffer2 );
  delay(1000);

Leggendo su un commento, ho trovato questo, una istruzione che fa accendere un relè alle ore 10 usando la sintassi ">10", ma non credo sia corretta perché se accendo arduino e solo le 11, il relè si accende, mentre credo basterebbe usare la sintassi "=10"

 if(now.hour()>10) digitalWrite (1, HIGH)

Il mio problema è comparare un' orario come 10:22:33 utilizzando anche i minuti e i secondi.
se volessi accendere un relè alle ore 10:22:33, come si fa?
credo bisogna realizzare un if che fa la comparazione del' ora, minuti e secondi tipo:
se ora è uguale a 10 e se minuti è uguale a 22 e se secondi è uguale a 33... digitalWrite (1, HIGH)
Ma non so come scriverla, potete aiutarmi??
Grazie comunque

Ogni volta che si debbono fare comparazioni o manipolazioni di Date/ore è conveniente usare la loro rappresentazione in formato "Unix Time" e, quasi tutte le librerie (credo anche la RTClib ... guarda al suo interno, nel .cpp) hanno a loro interno le funzioni per la conversione da e verso detto formato.

Il grande vantaggio è che in questo modo una data/ora diventa semplicemente ... UN NUMERO intero (unsigned long) e come tale facilmente manipolabile.

Se devi lavorare solo con il tempo e non con la data, puoi addirittura scriverti tu la semplice trasformazione ... basta che consideri che ogni ora è 3600 secondi, ogni minuto è 60 secondi e ogni secondo è ... un secondo :smiley:

In questo modo, il tuo IF dovrà semplicemente comparare un numero (unsigned long) con un altro. Nel tuo caso, ad esempio, le 11:22:33 sono rappresentate da (11 x 3600) + (22 x 60) + 33 = 40953.

Guglielmo

Ciao Guglielmo, sempre gentilissimo e disponibilissimo :slight_smile:
Sono molto abile a gestire unità di tempo con il Software che utilizzo per realizzare programmi legati alle mie interfacce. La comparazione è molto semplice, realizzo un contatore o variabile e faccio la comparazione tra due valori, come mi hai suggerito tu per arduino. Immaginavo si potesse fare anche con quello, ma ho ancora alcune di programmazione in c++ :frowning:
se ho ben capito:
devo dichiarare una variabile unsigned long es: "realtime" che ha al suo interno la somma in secondi delle tre variabili: (ore+minuti+secondi) e poi fare una semplice comparazione con quella variabile appena creata...è corretto?
quindi, basta scrivere

if(realtime()=40953) digitalWrite (1, HIGH);
è scritta correttamente?
Grazie ancora per il tuo aiuto.

... si, il concetto è semplice, invece di lavorare in ore (che sono 24 ogni giorno), in minuti (che sono 60 ogni ora), ed in secondi ... è molto più semplice contare il tempo, nell'arco della giornata, sempre in secondi :slight_smile:

Parti da mezzanotte che vale 0 secondi ed arrivi alle 23:59:59 che valgono 86399.

Se tu, ad esempio, hai comunque l'RTC che ti da ore, minuti e secondi ... ti fai una funzioncina del tipo :

unsigned long tempoInSecondi(byte hh, byte mm, byte ss) {
  return (unsigned long)( (unsigned long) hh * 3600 + (unsigned long) mm * 60 + (unsigned long) ss );
}

... nota che, per ovvie ragioni di risparmio di spazio, le ore, i minuti ed i secondi, li puoi memorizzare in singoli byte, mentre per fare le operazioni ed avere il risultato con la precisione voluta, nella funzione utilizzi l'operatore di "cast" per indicare che il tutto ti serve in formato unsigned long.

Guglielmo

quella formula non fa altro che inserire nella variabile "tempoInSecondi" i risultato in forma numerica del tempo attuale e quà tutto chiaro.
Ora devo capire come prendere i minuti,secondi e l'ora dal modulo rtc, ma nello sketch non trovo i tre elementi separati. trovo questo:
DateTime now = RTC.now();

Mi sembra di capire che fa tutto la libreria.
Ho preso questo sketch perchè mi serviva visualizzare su un display l' ora esatta e una cosetta molto interessante che vorrei implementare.
L' istruzione che mi hai scritto è valida per lo sketch che ho postato ad inizio post? io penso di no visto che, al contrario di alcuni sketch, non si hanno i tre valori temporali (ore,min,sec) è esatto?
Sto cercando di capire la tua istruzione non in quanto alla sua logica, ma dalla sua interpretazione:

La prima parte sarebbe in questo modo:
unsigned long tempoInSecondi(byte 11, byte 22, byte 33)

La seconda parte dentro parentesi graffa non fa altro che moltiplicare per dare come unico risultato il tempo in secondi.

{
return (unsigned long)( (unsigned long) 11 * 3600 + (unsigned long) 22 * 60 + (unsigned long) 33);
}

Il valore di 86399 è dentro la variabile "tempoInSecondi" ?

Mi manca di capire come prendere i tre valori tempo dal mio sketch... :confused:

Sarà per caso questa?

sprintf(buffer1,  "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
  lcd.setCursor(0,0);
  lcd.print( buffer1 );
  sprintf(buffer2,  "%02d/%02d/%d", now.day(), now.month(), now.year());

Se fosse cosi, quello che mi hai scritto tu potrebbe essere questo:

unsigned long tempoInSecondi(now.hour, now.minute, now.second) {
  return (unsigned long)( (unsigned long) hour * 3600 + (unsigned long) minute * 60 + (unsigned long) second );
}

Ecco che mi arriva il badile in testa :frowning: :frowning:

Di librerie RTC ce ne sono svariate ... metti un link esatto a quella che stai usando almeno si possono leggere i sorgenti e capire cosa da.

La funzioncina che ti ho scritto ti serve per avere indietro, dati hh, mm, e ss il valore in secondi, quindi ... NON ci devi mettere dei valori tu fissi dentro, ma la devi chiamare assegnandola ad una variabile di tipo unsigned long ... che sarà poi quella che confronterai con il valore che tu avrai calcolato.

Sempre prendendo il tuo esempio, le ore 11:22:33 corrispondono, come abbiamo visto a 40953, quindi, ricavate dalla libreria che stai usando le tre componenti non dovrai fare altro che ...

...
byte miaHH, miaMM, miaSS;
unsigned long mieiSecondi;
...
...
miaHH  = now.hour();
miaMM  = now.minute();
miaSS  = now.second();
mieiSecondi = tempoInSecondi(miaHH, miaMM, miaSS);
...
...
if (mieiSecondi == 40953) {
 ... è il momento di fare quello che devo fare
}
...
...

... piuttosto semplice :slight_smile:

Guglielmo

... ovviamente, senza usare delle variabili di appoggio temporanee, complicando un po' la leggibilità del codice, si potrebbe rendere il tutto in una forma compatta :

...

if ( tempoInSecondi(now.hour(), now.minute(), now.second()) == 40953) {
  ...
  <<<<fai quello che devi fare>>>>
  ...
}
...
...
unsigned long tempoInSecondi(byte hh, byte mm, byte ss) {
return (unsigned long)( (unsigned long) hh * 3600 + (unsigned long) mm * 60 + (unsigned long) ss );
}
...
...

Guglielmo

... ho comunque l'impressione che tu abbia ... lacune piuttosto serie di linguaggio C ... ::slight_smile:

Mi permetto quindi di suggerire un attento studio di QUESTO testo e puoi scaricarti QUESTO libro (... tranquillo, è un sito legale, purché per esclusivo uso PERSONALE).

Guglielmo

Grazie Guglielmo, ti spiego brevemente il problema delle mie lacune.
Non ho mai studiato programmazione e non ho neanche le minime basi, certamente ho letto tanti manuali di arduino, ma non è possibile avere una certa indipendenza, specialmente per fare cose un po piu complesse se non si dedica tante ore di studio. Ho iniziato a programmare con MMF2 che credo sia anche più difficile sotto alcuni aspetti: (trovi pochi tutorial e tutti in inglese e non usa un linguaggio standard), ma con tanta pazienza e studio sono arrivato ad un livello molto avanzato tanto che alcuni dei miei Software molti programmatori esperti mi chiedono come ho fatto. Quando mi serve una cosa che richiama arduino, faccio un po di ricerca e cerco aiuto. Non devo accendere un led, quello lo so fare :slight_smile:
le cose semplici le so fare, ma non essendo una cosa che faccio tutti i giorni, con il tempo mi dimentico anche quelle piu semplici e devo cominciare da capo ogni volta. Porto avanti troppi progetti e non posso dedicarmi allo studio del C++anche se vorrei tanto muovermi come te e come tanti altri sul forum.
ritornando a noi, ho visto i due esempi, uno che utilizza le variabili di appoggio per semplificare le istruzioni di comparazione valori e una che invece rende il codice più complesso. le variabili di appoggio le preferisco anche perchè le chiami come vuoi e ti rendono il tutto più leggibile.
purtroppo non posso fare prove, sono fuori sede per lavoro e non ho con me il modulo rtc.
grazie Guglielmo dei file che leggerò sicuramente, ho già iniziato e sono alla pagina 32 ma come tutte le cose, se non hai qualcuno che ti accompagna o che ti spiega a voce, impieghi molto più tempo a capire. La programmazione è difficile se non si hanno basi e se si vuole fare tutto da soli...sarebbe come imparare la conoscenza delle equazioni nella matematica non sapendo fare una semplice addizione... :confused:

edstarink:
... ho già iniziato e sono alla pagina 32 ma come tutte le cose, se non hai qualcuno che ti accompagna o che ti spiega a voce, impieghi molto più tempo a capire. La programmazione è difficile se non si hanno basi e se si vuole fare tutto da soli...sarebbe come imparare la conoscenza delle equazioni nella matematica non sapendo fare una semplice addizione... :confused:

... con calma e con pazienza, provando le varie cose su Arduino (... con piccolissimi programmini con cui verifichi ciò che studi, un argomento alla volta), vedrai che prenderai confidenza con il linguaggio :wink:

Guglielmo

MI permetto di aggiungere che per lavorare sulle ore si può creare un numero unico senza trasformarlo in secondi ore e minuti. Se si moltiplicano ore X 10000 e minuti X 100. Necessario però usare i numeri long
Quindi le 9:43:23 => 910000+43100+23=> 94323 cifra unica facilmente confrontabile.
con questo "metodo" è più semplice scrivere i numeri di un intervallo, esempio se orario è maggiore delle 10:30:00

unsigned long tempo=hh*10000UL+mm*100+ss;
if  tempo>103000UL  // 10:30:00

Logicamente non è detto che il metodo sia utile in tutti i casi. E impiega più memoria (long invece di int)

ciao, ma non è la stessa cosa? io solitamente ricavo da un valore come 10:22:33, un solo numero espresso in secondi o centesimi o millesimi, dipende dal' applicazione.
cosi facendo, se devo attivare un relè alle 03:00:00 del mattino, avendo come conversione in secondi un valore di "(60x60)x3=10800 secondi, posso facilmente fare la comparazione.
naturalmente è una risoluzione che non mi serve per questa applicazione, ho bisogno solo di fare una comparazione in termini di minuti quindi prendendo questo come esempio: 03:00 quindi, 60x3= 180

naturalmente la comparazione la faccio sempre utilizzando "=" e non "<" ">" perché voglio che l' eccitazione del relè avvenga solo in quel preciso momento per questioni di sicurezza.

Ho provato a dichiarare tre variabili di appoggio, ma mi da errore e questo è la parte di codice che ho copiato e messa nello sketh. Tengo a precisare che lo sketch è funzionante.

byte miaHH, miaMM, miaSS;
unsigned long mieiSecondi;

miaHH  = now.hour();
miaMM  = now.minute();
miaSS  = now.second();

Dice che "now"non è stata dichiarata...
Ho dichiarato le tre variabili miaHH,miaMM ecc, ma non riconosce now.hour()
Ma now.hour(); per esempio non è una variabile dove vengono inserite le ore attuali e via dicendo? perché mi dice che non sono dichiarate?
Non ci sto più capendo niente :o

... quelli dovrebbero essere metodi della libreria RTC che stai usando (... e della quale ancora non ci hai dato il link).

Prima di poterli usare devi inizializzare la libreria istanziando il suo costruttore ...

Guglielmo

e aggiungere prima

 DateTime now = rtc.now();

Ops...scusami gugliemo, mi sono dimenticato.
Ho pro lo sketch da Daniele alberti, che sicuramente farà parte di questo forum :slight_smile:
ecco il link

per semplificare la ricerca, ecco il link diretto della libreria
Link alla libreria

DateTime now = rtc.now();

Serve per aggiornare l' ora durante la compilazione dello sketch?
rtc.now è l' ora ricavata dal modulo e immessa nella variabile DatetTime now ad inizio programma?

edstarink:

DateTime now = rtc.now();

rtc.now è l' ora ricavata dal modulo e immessa nella variabile DatetTime now ad inizio programma?

edstarink ... veramente, lo dico per te ... dedica qualche ora a studiare ALMENO le BASI del C/C++ (... dai link che ti ho già passato) ::slight_smile:

DateTime è una CLASSE è la trovi definita subito all'inizio di RTClib.h ... apri i sorgenti e passa del tempo a studiarli ... altrimenti applichi delle cose di cui non segui assolutamente il funzionamento ... :confused:

Guglielmo

Ciao Guglielmo, ho preso seriamente il tuo consiglio, sto studiando da ieri sera.
Sono in trasferta e ho tutto il tempo. Adesso ho chiare molte cose, mi sono studiato diverse guide e sto avendo già una certa indipendenza, la programmazione la conosco, solo che ho difficoltà nello scrivere in C++ quello che normalmente realizzo con altri Software. è inutile che studio solo quello che mi serve anche perché il mio progetto domotica utilizza arduino 2560 per la gestione di tutta la parte sensoristica e la mia nuova interfaccia da 96 ingressi sfruttando gli shift register quindi, devo avere una certa indipendenza :slight_smile: . Grazie come sempre, anche se non ho risolto il problema, ma grazie al tuo suggerimento ci arriverò da solo. :slight_smile:

edstarink:
... Grazie come sempre, anche se non ho risolto il problema, ma grazie al tuo suggerimento ci arriverò da solo. :slight_smile:

... che, almeno per ciò che mi riguarda, è lo spirito di questo forum ... ovvero "far crescere" le persone, consigliandogli cosa studiare e non fornendogli la "pappa fatta" con cui poi, alla prossima difficoltà ... sarebbero da capo a dodici ! :wink:

Ovvio che se poi non riesci a risolvere ed hai bisogno di aiuto ... siamo qui :slight_smile:

Guglielmo

Parole sante :slight_smile:
sto studiano i cicli if, else, while e ho già realizzato diverse istruzioni con tanti if annidati inserendo mano a mano altri cicli come i for, gli switch case e tutto il resto. In fondo è semplice, per me l' unica difficoltà è come scriverli visto che conosco la logica di programmazione visto che non per vantarmi, ho realizzato un Software per la domotica con struttura ladder dove il cliente si disegna la casa inserendo grafiche ed animazioni quindi, me la cavicchio. Comunque è molto bello il C++, peccato che alla mia età, anche se sono ancora giovane e non più giovanissimo, le difficoltà nel' imparare sono alte. Famiglia, lavoro, altri progetti ecc.
Per studiare arduino, ho dovuto abbandonare gli aggiornamenti del mio Software...qualcuno si lamenterà, ma non sarà tempo perso. :slight_smile: :slight_smile:
Grazie Guglielmo.