Come azionare un led ad una determinata ora?

ciao a tutti stavo giochicchiando con un modulo rtc, e mi chiedevo ma come faccio a far accendere un led ad una determinata ora ogni giorno???
questo è il codice e dopo tutta la sfilza di print stavo provando a fare un if(); ma non riesco a farci entrare il programma dentro

#include "RTClib.h"


RTC_DS1307 rtc;

void setup () {

  
  Serial.begin(9600);

  
  while (!Serial) {
  
  }

  rtc.begin();

  if (!rtc.isrunning()) {
    Serial.println("Setto data e ora corrente:");
    Serial.println(F(__DATE__));
    Serial.println(F(__TIME__));
    
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

}

void loop () {

  /*
    Il metodo now() restituisce un oggetto di tipo DateTime
    che grazie ai suoi metodi restituisce le varie parti
    della data/ora.
  */
  DateTime adesso = rtc.now();

  Serial.println("Data e ora corrente: ");
  Serial.print(prefixaZero(adesso.day()));
  Serial.print("/");
  Serial.print(prefixaZero(adesso.month()));
  Serial.print("/");
  Serial.print(adesso.year());
  Serial.print(" ");
  Serial.print(prefixaZero(adesso.hour()));
  Serial.print(":");
  Serial.print(prefixaZero(adesso.minute()));
  Serial.print(":");
  Serial.print(prefixaZero(adesso.second()));
  Serial.println(" ");
  Serial.println("- - - - - - - - - - -");

  if (adesso.minute() == "15:57:00"){
    Serial.println("WOOOOO");
  }
  delay(1000);
}

/*
  Ho creato una funzione per aggiungere lo zero iniziale
  a tutti i numeri inferiori di 10 perché mi piacciono di più

  ATTENZIONE:
  Naturalmente questa funzione restituisce una stringa e non
  un numero, quindi se dovete effettuare operazioni matematiche
  usate il valore originale.

  Questa potrebbe essere comoda per stampare valori sul display per esempio
*/
String prefixaZero(uint8_t numero) {
  if (numero < 10) {
    return "0" + String(numero);
  }
  return String(numero);
  
}

si ho preso uno sketch già fatto su internet :grin:

Ciao,

adesso.minute() non restituisce una Stringa ma un intero, quindi non è una comparazione congruente nei tipi!

Comunque in genere quando si lavora con i tempi sui micro, è preferibile se non deve interagirci l'utente usare il formato UNIX TIME che conta i secondi dal 01/01/1970 in modo che esso sia sempre crescente e non hai problemi nel controllare le fasce orarie esempio "dalle 15:00:15 alle 18:30:22".

Come si lavora qundi:

const uint32_t SECS_PER_HOUR = 3600;
const uint32_t SECS_PER_MINUTE = 60;

DateTime time = rtc.now();
uint32_t unixtime = time.unixtime();
uint32_t midnight = unixtime - (time.hour() * SECS_PER_HOUR);


byte oraOn = 15;
byte minutiOn = 57;
byte secondiOn = 18;
uint32_t timeOn = (oraOn * SECS_PER_HOUR) + (minutiOn * SECS_PER_MINUTE) +  secondiOn;

byte oraOff = 18;
byte minutiOff = 22;
byte secondiOf = 22;
uint32_t timeOff = (oraOff * SECS_PER_HOUR) + (minutiOff * SECS_PER_MINUTE) +  secondiOff;

if(unixtime == midnight + timeOn ){
  Serial.println("wooo");
}

Questo codice non ho la possibilità di provarlo ma dovrebbe almeno darti un'idea di quello che dico...

Spero di essere stato chiaro, in caso resto a disposizione.

Alan

Inoltre:

  • le vigolatte "A" per un solo carattere puoi vantaggiosamente sostituirle con 'A' (un carattere anziché una stringa);
  • per anteporre gli zeri basta scrivere una funzione così:
scrive_numero (uint8_t numero)
{
if (numero<10) {Serial.print(' ');}
Serial.print (numero);
}

Scusami ma non ho ben capito come funziona, cioè penso mi sia chiara la sintassi del codice ma
Non mi funziona🤔


#include <RTClib.h>

RTC_DS1307 rtc;
const uint32_t SECS_PER_HOUR = 3600;
const uint32_t SECS_PER_MINUTE = 60;

DateTime time = rtc.now();
uint32_t unixtime = time.unixtime();
uint32_t midnight = unixtime - (time.hour() * SECS_PER_HOUR);
int timeOn= 0;
int timeOff= 0;

//lcd 
#include <LiquidCrystal.h>
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

void setup() {
  lcd.begin(16, 2);
  Serial.begin(9600);

  lcd.print("hello, world22!");
  byte oraOn = 00;
  byte minutiOn = 12;
  byte secondiOn = 18;
  uint32_t timeOn = (oraOn * SECS_PER_HOUR) + (minutiOn * SECS_PER_MINUTE) +  secondiOn;

  byte oraOff = 00;
  byte minutiOff = 12;
  byte secondiOff = 22;
  uint32_t timeOff = (oraOff * SECS_PER_HOUR) + (minutiOff * SECS_PER_MINUTE) +  secondiOff;
  //Serial.print("timeOn");

  } 

void loop() {
  Serial.print("ciao2");
  lcd.setCursor(0, 1);
  lcd.print("test");
  /*
  if(unixtime == midnight + timeOn ){
    lcd.setCursor(0,1);
    lcd.print("hello");
  }
    */
  delay(500);

}

La cosa strana che non mi stampa nulla anche nel monitor seriale…. E nemmeno sull’lcd

Invece questo sketch funziona


//ora lcd

#include "RTClib.h"
RTC_DS1307 rtc;

#include <LiquidCrystal.h>
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);


void setup() {
  // put your setup code here, to run once:
  lcd.begin(16, 2);

  while (!Serial) {
  
  }

  rtc.begin();
/*
  if (!rtc.isrunning()) {
    Serial.println("Setto data e ora corrente:");
    Serial.println(F(__DATE__));
    Serial.println(F(__TIME__));
  }
  */
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}

void loop() {
  // put your main code here, to run repeatedly:
  DateTime adesso = rtc.now();
  lcd.setCursor(0, 0);
  lcd.print(prefixaZero(adesso.day()));
  lcd.print("/");
  lcd.print(prefixaZero(adesso.month()));
  lcd.print("/");
  lcd.print(adesso.year());
  lcd.print(" ");
  lcd.setCursor(0, 1);
  lcd.print(prefixaZero(adesso.hour()));
  lcd.print(":");
  lcd.print(prefixaZero(adesso.minute()));
  lcd.print(":");
  lcd.print(prefixaZero(adesso.second()));
 
}
String prefixaZero(uint8_t numero) {
  if (numero < 10) {
    return "0" + String(numero);
  }
  return String(numero);
}

Se invece dovessi interagirci, nel senso cambiare ora di accensione???

La differenza sembra solo in queste righe. Che board usi ? Quel pezzo di solito si usa su Arduino Leonardo.
Inoltre il secondo, che dici funziona, cosa vedi su Serial Monitor ? Perché manca Serial.begin

Uso un’ arduino uno ma dovrò usarlo poi con un mega… che cosa fa quel pezzo di codice?

Si hai ragione scusa… ieri sera ho fatto prove, il secondo mi funziona sull’lcd invece il primo ne sul lcd e nemmeno sul serial monitor

Ciao,
prima di tutto mi correggo su una piccola cosa:
al posto di

const uint32_t SECS_PER_HOUR = 3600;
const uint32_t SECS_PER_MINUTE = 60;

mettici

#define SECS_PER_HOUR 3600UL
#define SECS_PER_MINUTE 60UL

poi,

in poche parole cerco di spiegartelo:
calcoli l'ora corrente in UNIX time nella variabile unixtime, e ci sottrai sempre in UNIX il valore dell'ora in secondi, il valore dei minuti in secondi e i secondi correnti (mi sono dimenticato io di metterli nell'esempio) con
midnight = unixtime - (time.hour() * SECS_PER_HOUR) - (time.minute() * SECS_PER_MINUTE) - time.seconds()
poi calcoli il momento di accensione e/o di spegnimento che sarebbero in sostanza i secondi dalla mezzanotte del giorno corrente, in modo che sia sempre un valore crescente e quindi relazionabile ad altri valori:

byte oraOn = 15;
byte minutiOn = 57;
byte secondiOn = 18;
uint32_t timeOn = (oraOn * SECS_PER_HOUR) + (minutiOn * SECS_PER_MINUTE) +  secondiOn;

byte oraOff = 18;
byte minutiOff = 22;
byte secondiOff = 22;
uint32_t timeOff = (oraOff * SECS_PER_HOUR) + (minutiOff * SECS_PER_MINUTE) +  secondiOff;
//notare che timeOn e timeOff sono in UNIX, mentre oraOn, minutiOn, .... , sono in formato H24

ora se al valore midnight ci sommi uno dei due valori appena calcolati (time = midnight + timeOn) ottieni il valore che l'UNIX time deve assumere per essere esattamente in quel dato istante assoluto nel tempo; il che vuol dire che due valori uguali sono univoci ed equivalgono ad una data precisa al secondo!

Ricapitolando il tuo programma completo dovrebbe essere una cosa del genere:

#include <RTClib.h>

#define SECS_PER_HOUR 3600UL
#define SECS_PER_MINUTE 60UL


RTC_DS1307 rtc;

//Variabili per il controllo dell'ora
DateTime time;
uint32_t unixtime = 0;
uint32_t midnight = 0;
int timeOn= 0;
int timeOff= 0;

//lcd 
#include <LiquidCrystal.h>
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

void setup() {
  lcd.begin(16, 2);
  Serial.begin(9600);

  lcd.print("hello, world22!");
  byte oraOn = 00;
  byte minutiOn = 12;
  byte secondiOn = 18;
  uint32_t timeOn = (oraOn * SECS_PER_HOUR) + (minutiOn * SECS_PER_MINUTE) +  secondiOn;

  byte oraOff = 00;
  byte minutiOff = 12;
  byte secondiOff = 22;
  uint32_t timeOff = (oraOff * SECS_PER_HOUR) + (minutiOff * SECS_PER_MINUTE) +  secondiOff;
  //Serial.print("timeOn");

  } 

void loop() {
  time = rtc.now();
  unixtime = time.unixtime();
  midnight = unixtime - (time.hour() * SECS_PER_HOUR);

  Serial.print("ciao2");
  lcd.setCursor(0, 1);
  lcd.print("test");
  
  
  if(unixtime == midnight + timeOn ){
    lcd.setCursor(0,1);
    lcd.print("hello");
  }
  if(unixtime == midnight + timeOff ){
    lcd.clear();
    lcd.setCursor(0,1);
    lcd.print("OFF");
  }

 //delay(500); QUESTO SE FAI CONTROLLO DI TEMPI TI POTREBBE IMPEDIRE DI ENTRARE NELLA CONDIZIONE CHE ESEGUE QUELLO CHE VUOI, PERCIO' USI I TIMER NON BLOCCANTI VEDI ESEMPIO SUCCESSIVO!!!!!!!

}

Questo invece è l'esempio con i timer non bloccanti:

#include <RTClib.h>

#define SECS_PER_HOUR 3600UL
#define SECS_PER_MINUTE 60UL


RTC_DS1307 rtc;

//Variabili per il controllo dell'ora
DateTime time;
uint32_t unixtime = 0;
uint32_t midnight = 0;
int timeOn= 0;
int timeOff= 0;
//Timer non bloccante 
uint32_t t0 = 0;

//lcd 
#include <LiquidCrystal.h>
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

void setup() {
  lcd.begin(16, 2);
  Serial.begin(9600);

  lcd.print("hello, world22!");
  byte oraOn = 00;
  byte minutiOn = 12;
  byte secondiOn = 18;
  uint32_t timeOn = (oraOn * SECS_PER_HOUR) + (minutiOn * SECS_PER_MINUTE) +  secondiOn;

  byte oraOff = 00;
  byte minutiOff = 12;
  byte secondiOff = 22;
  uint32_t timeOff = (oraOff * SECS_PER_HOUR) + (minutiOff * SECS_PER_MINUTE) +  secondiOff;
  //Serial.print("timeOn");

  } 

void loop() {
  time = rtc.now();
  unixtime = time.unixtime();
  midnight = unixtime - (time.hour() * SECS_PER_HOUR);

  Serial.print("ciao2");
  lcd.setCursor(0, 1);
  lcd.print("test");
  
  const uint32_t pausa = 500; //500 ms di pausa

  while (millis() - t0 < pausa){
    t0 = millis();
    if(unixtime == midnight + timeOn ){
      lcd.setCursor(0,1);
      lcd.print("hello");
    }
    if(unixtime == midnight + timeOff ){
      lcd.clear();
      lcd.setCursor(0,1);
      lcd.print("OFF");
    }
  }
}

Ecco, anche in questo caso spero di essere stato chiaro e se non fosse così sono a disposizione!!!
Alan

Eccomi allora, ho provato il tuo ultimo sketch allora se riesci a modificarlo cosi chi lo leggerà in futuro non avrà problemi, mi spiego meglio queste due righe solo scritte male

perché mi dava errore ed ho capito che vanno scritte cosi:

#define SECS_PER_HOUR (3600UL)
#define SECS_PER_HOUR (3600UL)

aparte questo invece, non funziona nel senso parte che non capisco come mai ma non mi apre sto cavolo di monitor seriale(poco mi frega però era per capire che stava succedendo), poi mi impazzisce LCD


C’è una riga bianca che va su e giù e basta :thinking:

Scusa ancora, mio errore di battitura, non ci va il ; alla fine (edito i post comunque),

Per il monitor seriale non ho idee, mentre per il display, hai provato a regolare il contrasto?

Si se carico un altro sketch funziona alla grande

allora ragazzi io non ci sto capendo più un nulla ..... perché ora mi segna sempre questo......
Schermata 2021-12-11 alle 17.04.29
@alanmasutti @gpb01 vi taggo perché sto davvero SCLERANDO scusatemi

... per favore usaimo un linguaggio più consono ... ho corretto io.

Guglielmo

scusa e che sto veramente diventando matto :crazy_face:

non capisco perché non mi aggiorna l'ora con quella di compilazione

Hai nel codice questa riga?

rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

... perché fa esattamente quello.

Guglielmo

Perché stai sovrascrivendo continuamente il testo sul display.
Hai due opzioni:

  • Aggiorni ogni tot millisecondi in modo da minimizzare lo sfarfallio
  • Aggiorni solo quando i dati sono cambiati (scelta preferibile)

@cotestatnt ok ma adesso come faccio a ripristinare l'orario corretto??

Come ti ha già scritto Guglielmo.