Creazione temporizzatore con RTC DS1307 - aiuto codice

Buona sera a tutti,
sto creando un temporizzatore basato sul rtc ds1307 con Arduino, ma avrei bisogno di una mano per completare il codice.
In pratica, quello che non ricordo come si fà, è stabilire DA QUANDO A QUANDO dovrà essere eccitato il relè collegato.
Qualcuno potrebbe darmi una mano?
Ecco il codice che ho scritto fino ad ora, commentato.

// di seguito includo la libreria per la comunicazione su bus I2C
#include <Wire.h>

int start_h=00;
int start_m=00;
int end_h=00;
int end_m=00;
 
void setup()
{
    pinMode(2, OUTPUT);    // PIN DOVE E' COLLEGATO IL RELE'
    
  // inizializzo la comunicazione seriale
  Serial.begin(9600);
 
  //inizializzo la libreria
  Wire.begin();
 
  // adesso, inizializzo la comunicazione con il DS1307. 
  // L’indirizzo del DS1307 di default è 0x68
  Wire.beginTransmission(0x68);
  // il primo byte stabilisce il registro
  Wire.write((byte)0x00);
  // imposto l’orario e la data
  Wire.write((byte)0x00); // 1° byte SECONDI da 0x00 a 0x59
  Wire.write((byte)0x10); // 2° byte MINUTI da 0x00 a 0x59
  Wire.write((byte)0x80 | 0x10); // 3° byte ORE da 0x00 a 0x24
  Wire.write((byte)0x01); // 4° byte GIORNO della settimana da 0x01 a 0x07
  Wire.write((byte)0x21); // 5° byte GIORNO del mese da 0x00 a 0x31
  Wire.write((byte)0x03); // 6° byte MESE da 0x00 a 0x12
  Wire.write((byte)0x12); // 7° byte ANNO 0x00 a 0x99
  Wire.endTransmission();
}
 
void loop()
{
  // inizzializzo la trasmissione partendo dall'indirizzo 0x00
  Wire.beginTransmission(0x68);
  Wire.write((byte)0x00);
  Wire.endTransmission();
 
  // richiedo 7 byte dal dispositivo con indirizzo 0x68
  Wire.requestFrom(0x68, 7);
  // recupero i 7 byte relativi ai corrispondenti registri
  byte secondi = Wire.read();
  byte minuti = Wire.read();
  byte ora = Wire.read();
  byte giorno_sett = Wire.read();
  byte giorno_mese = Wire.read();
  byte mese = Wire.read();
  byte anno = Wire.read();
 
  Serial.print("Ora corrente: ");
  Serial.print(ora, HEX);
  Serial.print(":");
  Serial.print(minuti, HEX);
  Serial.print(":");
  Serial.println(secondi, HEX);
 
  Serial.print("Giorno della settimana: ");
  Serial.println(giorno_sett, HEX);
 
  Serial.print("Data corrente: ");
  Serial.print(giorno_mese, HEX);
  Serial.print("/");
  Serial.print(mese, HEX);
  Serial.print("/");
  Serial.println(anno, HEX);
  Serial.println();
   delay(1000);
   
   // QUI' IMPOSTO I PARAMETRI DI ACCENSIONE DEL RELE' --- COME FACCIO A IMPOSTARE - DA QUANDO A QUANDO- DOVRA' RESTARE ECCITATO?
   if((ora == start_h && minuti == start_m) &&){
   digitalWrite(2, HIGH);
    delay(5000);
   }
   else{
   digitalWrite(2, LOW);
    delay(5000);
   }
}

A presto,
Ivan

la cosa piú semplice é che cambi da H:M.S a Secondi della giornata. Cosí hai un unico numero che devi controllare e non 3 numeri.

Secondigiorno = secondi+ minuti60 +ore60*60
e poi

if (Secondigiorno >=28800 &&  Secondigiorno < 29100){
accendi relé;
reléacceso = 1;}
else 
if (reléacceso = 1){
 spegni relé;
 reléacceso = 0;}

Se non vuoi che si ripeta l' accensione/spegnimento del relé tutti i giorni devi aggiungere al calcolo del tempo trascorso anche la data.

Ciao Uwe

Ciao, grazie per la risposta!
E se invece facessi così dovrebbe funzionare?

if ((start_h >= 08 &&  start_m >= 00) && (ora< end_h &&  minuti < end_m)){
accendi relé;
reléacceso = 1;}
else 
if (reléacceso = 1){
 spegni relé;
 reléacceso = 0;}

:cold_sweat: :cold_sweat: :cold_sweat: :cold_sweat:

secondo me non funziona perche devi controllare l' ora e minuti correnti e non i loro valori di accensione / spegnimento.

if ((ore  >= start_h &&  ninuti >= start_m ) && (ora< end_h &&  minuti < end_m)){

Cosí dovrebbe funzionare.
Si potrebbe fare un controllo dello stato del relé per non accenderlo a ogni ciclo del if come avevo previsto per il spegnimento.

Ciao Uwe

perfetto grazie!
Scusami ma potresti spiegarmi meglio
"
Si potrebbe fare un controllo dello stato del relé per non accenderlo a ogni ciclo del if come avevo previsto per il spegnimento.
"

A presto,
Ivan

Usi una var di stato. Esempio boolean releOn = false;
Quando la metti su true, sai che il relé è acceso e non occorre riaccenderlo. Quindi fai un altro test con if dopo il primo di controllo dell'orario. Ovviamente quando spengerai il relé la rimetterai a false, altrimenti non riuscirai più a riaccenderlo.

Ottima spiegazione, grazie.
Ho testato il seguente codice, ma sono presenti degli errori...

// di seguito includo la libreria per la comunicazione su bus I2C
#include <Wire.h>

int start_h=00;
int start_m=00;
int end_h=00;
int end_m=00;
 
void setup()
{
    pinMode(2, OUTPUT);    // PIN DOVE E' COLLEGATO IL RELE'
    
  // inizializzo la comunicazione seriale
  Serial.begin(9600);
 
  //inizializzo la libreria
  Wire.begin();
 
  // adesso, inizializzo la comunicazione con il DS1307. 
  // L’indirizzo del DS1307 di default è 0x68
  Wire.beginTransmission(0x68);
  // il primo byte stabilisce il registro
  Wire.write((byte)0x00);
  // imposto l’orario e la data
  Wire.write((byte)0x00); // 1° byte SECONDI da 0x00 a 0x59
  Wire.write((byte)0x10); // 2° byte MINUTI da 0x00 a 0x59
  Wire.write((byte)0x80 | 0x10); // 3° byte ORE da 0x00 a 0x24
  Wire.write((byte)0x01); // 4° byte GIORNO della settimana da 0x01 a 0x07
  Wire.write((byte)0x21); // 5° byte GIORNO del mese da 0x00 a 0x31
  Wire.write((byte)0x03); // 6° byte MESE da 0x00 a 0x12
  Wire.write((byte)0x12); // 7° byte ANNO 0x00 a 0x99
  Wire.endTransmission();
}
 
void loop()
{
  // inizzializzo la trasmissione partendo dall'indirizzo 0x00
  Wire.beginTransmission(0x68);
  Wire.write((byte)0x00);
  Wire.endTransmission();
 
  // richiedo 7 byte dal dispositivo con indirizzo 0x68
  Wire.requestFrom(0x68, 7);
  // recupero i 7 byte relativi ai corrispondenti registri
  byte secondi = Wire.read();
  byte minuti = Wire.read();
  byte ora = Wire.read();
  byte giorno_sett = Wire.read();
  byte giorno_mese = Wire.read();
  byte mese = Wire.read();
  byte anno = Wire.read();
 
  Serial.print("Ora corrente: ");
  Serial.print(ora, HEX);
  Serial.print(":");
  Serial.print(minuti, HEX);
  Serial.print(":");
  Serial.println(secondi, HEX);
 
  Serial.print("Giorno della settimana: ");
  Serial.println(giorno_sett, HEX);
 
  Serial.print("Data corrente: ");
  Serial.print(giorno_mese, HEX);
  Serial.print("/");
  Serial.print(mese, HEX);
  Serial.print("/");
  Serial.println(anno, HEX);
  Serial.println();
   delay(1000);
   
   // QUI' IMPOSTO I PARAMETRI DI ACCENSIONE DEL RELE' --- COME FACCIO A IMPOSTARE - DA QUANDO A QUANDO- DOVRA' RESTARE ECCITATO?
   if ((ore  >= start_h &&  ninuti >= start_m ) && (ora< end_h &&  minuti < end_m)){
     digitalWrite(2, HIGH);
     int releacceso = 1;
   }
   else 
if (releacceso = 1){
digitalWrite(2, LOW);
int reléacceso = 0;}
}

Cosa sbaglio :astonished:

A presto,
Ivan

Mi dici come fa a compilarti il programma, a te? Così, giusto per curiosità....

Ecco cosa ottengo io:

sketch_nov18a:80: error: stray ‘\’ in program
sketch_nov18a.ino: In function ‘void loop()’:
sketch_nov18a:73: error: ‘ore’ was not declared in this scope
sketch_nov18a:73: error: ‘ninuti’ was not declared in this scope
sketch_nov18a:78: error: ‘releacceso’ was not declared in this scope
sketch_nov18a:80: error: expected initializer before ‘u00e9acceso’

Hai usato var non dichiarate e poi ad un certo punto usi anche una lettera accentata: int reléacceso = 0;

Ciao, ho scritto che mi restituisce degli errori ma ho dimenticato di scrivere quali sono. Eccoli:

temporizzatore.ino:80:1: error: stray ‘\’ in program
temporizzatore.ino: In function ‘void loop()’:
temporizzatore.ino:73:9: error: ‘ore’ was not declared in this scope
temporizzatore.ino:73:29: error: ‘ninuti’ was not declared in this scope
temporizzatore.ino:78:5: error: ‘releacceso’ was not declared in this scope
temporizzatore.ino:80:9: error: expected initializer before ‘u00e9acceso’

Le variabili sono ora e non ore, minuti e non ninuti.
Per releacceso l'errore è più subdolo: è stato definito dentro ad un blocco, uscito dal blocco la variabile viene distrutta.
Il primo è l'ultimo errore sono dovuti alla presenza di caratteri invisibili o con codifiche particolari tipo reléacceso (c'è la e con l'accento)
Infine nell'IF ci vuole == e non =

Grazie per la risposta,
Ho corretto il codice nel seguente modo e viene caricato correttamente:

// di seguito includo la libreria per la comunicazione su bus I2C
#include <Wire.h>

int start_h=10;
int start_m=11;
int end_h=10;
int end_m=13;
int acceso=1;
 
void setup()
{
    pinMode(2, OUTPUT);    // PIN DOVE E' COLLEGATO IL RELE'
    
  // inizializzo la comunicazione seriale
  Serial.begin(9600);
 
  //inizializzo la libreria
  Wire.begin();
 
  // adesso, inizializzo la comunicazione con il DS1307. 
  // L’indirizzo del DS1307 di default è 0x68
  Wire.beginTransmission(0x68);
  // il primo byte stabilisce il registro
  Wire.write((byte)0x00);
  // imposto l’orario e la data
  Wire.write((byte)0x00); // 1° byte SECONDI da 0x00 a 0x59
  Wire.write((byte)0x10); // 2° byte MINUTI da 0x00 a 0x59
  Wire.write((byte)0x80 | 0x10); // 3° byte ORE da 0x00 a 0x24
  Wire.write((byte)0x01); // 4° byte GIORNO della settimana da 0x01 a 0x07
  Wire.write((byte)0x21); // 5° byte GIORNO del mese da 0x00 a 0x31
  Wire.write((byte)0x03); // 6° byte MESE da 0x00 a 0x12
  Wire.write((byte)0x12); // 7° byte ANNO 0x00 a 0x99
  Wire.endTransmission();
}
 
void loop()
{
  // inizzializzo la trasmissione partendo dall'indirizzo 0x00
  Wire.beginTransmission(0x68);
  Wire.write((byte)0x00);
  Wire.endTransmission();
 
  // richiedo 7 byte dal dispositivo con indirizzo 0x68
  Wire.requestFrom(0x68, 7);
  // recupero i 7 byte relativi ai corrispondenti registri
  byte secondi = Wire.read();
  byte minuti = Wire.read();
  byte ora = Wire.read();
  byte giorno_sett = Wire.read();
  byte giorno_mese = Wire.read();
  byte mese = Wire.read();
  byte anno = Wire.read();
 
  Serial.print("Ora corrente: ");
  Serial.print(ora, HEX);
  Serial.print(":");
  Serial.print(minuti, HEX);
  Serial.print(":");
  Serial.println(secondi, HEX);
 
  Serial.print("Giorno della settimana: ");
  Serial.println(giorno_sett, HEX);
 
  Serial.print("Data corrente: ");
  Serial.print(giorno_mese, HEX);
  Serial.print("/");
  Serial.print(mese, HEX);
  Serial.print("/");
  Serial.println(anno, HEX);
  Serial.println();
   delay(1000);
   
   // QUI' IMPOSTO I PARAMETRI DI ACCENSIONE DEL RELE' --- COME FACCIO A IMPOSTARE - DA QUANDO A QUANDO- DOVRA' RESTARE ECCITATO?
   if ((ora  >= start_h &&  minuti >= start_m ) && (ora< end_h &&  minuti < end_m)){
     digitalWrite(12, HIGH);
     int acceso = 1;
   }
   else 
if (acceso == 1){
digitalWrite(12, LOW);
int acceso = 0;}
}

Ma... non funziona...
L'orologio l'ho impostato alle 10:10
Il led collegato al pin12 dovrebbe accendersi alle 10:11 e spegnersi alle 10:13, ma non funziona.
Ho sbagliato qualcosa?

Grazie e a presto,
Ivan

#include <Wire.h>

#define PINRELE 12

int start_h = 10;
int start_m = 11;
int end_h = 10;
int end_m = 13;
bool acceso = true;

void setup()
{
	pinMode(PINRELE, OUTPUT);    // PIN DOVE E' COLLEGATO IL RELE'

	// inizializzo la comunicazione seriale
	Serial.begin(9600);

	//inizializzo la libreria
	Wire.begin();

	// adesso, inizializzo la comunicazione con il DS1307.
	// L’indirizzo del DS1307 di default è 0x68
	Wire.beginTransmission(0x68);
	// il primo byte stabilisce il registro
	Wire.write((byte)0x00);
	// imposto l’orario e la data
	Wire.write((byte)0x00); // 1° byte SECONDI da 0x00 a 0x59
	Wire.write((byte)0x10); // 2° byte MINUTI da 0x00 a 0x59
	Wire.write((byte)0x80 | 0x10); // 3° byte ORE da 0x00 a 0x24
	Wire.write((byte)0x01); // 4° byte GIORNO della settimana da 0x01 a 0x07
	Wire.write((byte)0x21); // 5° byte GIORNO del mese da 0x00 a 0x31
	Wire.write((byte)0x03); // 6° byte MESE da 0x00 a 0x12
	Wire.write((byte)0x12); // 7° byte ANNO 0x00 a 0x99
	Wire.endTransmission();
}

void loop()
{
	// inizzializzo la trasmissione partendo dall'indirizzo 0x00
	Wire.beginTransmission(0x68);
	Wire.write((byte)0x00);
	Wire.endTransmission();

	// richiedo 7 byte dal dispositivo con indirizzo 0x68
	Wire.requestFrom(0x68, 7);
	// recupero i 7 byte relativi ai corrispondenti registri
	byte secondi = Wire.read();
	byte minuti = Wire.read();
	byte ora = Wire.read();
	byte giorno_sett = Wire.read();
	byte giorno_mese = Wire.read();
	byte mese = Wire.read();
	byte anno = Wire.read();

	Serial.print("Ora corrente: ");
	Serial.print(ora, HEX);
	Serial.print(":");
	Serial.print(minuti, HEX);
	Serial.print(":");
	Serial.println(secondi, HEX);

	Serial.print("Giorno della settimana: ");
	Serial.println(giorno_sett, HEX);

	Serial.print("Data corrente: ");
	Serial.print(giorno_mese, HEX);
	Serial.print("/");
	Serial.print(mese, HEX);
	Serial.print("/");
	Serial.println(anno, HEX);
	Serial.println();

	// QUI' IMPOSTO I PARAMETRI DI ACCENSIONE DEL RELE' --- COME FACCIO A IMPOSTARE - DA QUANDO A QUANDO- DOVRA' RESTARE ECCITATO?
	if ((ora >= start_h &&  minuti >= start_m ) && (ora < end_h &&  minuti < end_m))
		acceso = true;
	else if (acceso == true)
		acceso = false;

	// Accende o spegne il relè
	if (acceso)
		digitalWrite(PINRELE, HIGH);
	else
		digitalWrite(PINRELE, LOW);

	delay(1000);
} // End Loop

Non sono sicuro se la variabile si possa definire bool oppure va definita boolean.

Ivan_Isk:

E sono gli stessi che ottenevo io.
Però se leggevi quei messaggi capivi già subito cosa c'era che non andava. Il compilatore è molto fiscale e ti segnala tutte le anomalie. Bastava leggere cosa segnalava e correggere quelle piccole cose. :wink:

@Paolo:
ci vuole "boolean"

Ops, grazie per la pazienza :slight_smile:
Ho provato lo sketch, ma... :disappointed_relieved: non ottengo il risultato sperato...
Il pin 12 non và in HIGH nonostante dovrebbe farlo...
Il codice mi sembra giusto, ma non funziona. Forse manca qualcosa?
Spero in una vostra illuminazione,
Ivan

Trasforma tutto in secondi.
E poi fai il confronto con questi. Come già ti aveva suggerito Uwe, è meglio per gestire gli orari

Si, ho letto il suo consiglio, ma se devo essere sincero l'ho ignorato in quanto non mi è molto chiaro come fare.
Dove e come devo inserire questo?

Secondigiorno = secondi+ minuti*60 +ore*60*60

Per questo invece non credo di avere problemi

if (Secondigiorno >=28800 &&  Secondigiorno < 29100){
accendi relé;
reléacceso = 1;}
else 
if (reléacceso = 1){
 spegni relé;
 reléacceso = 0;}

Ancora grazie,
Ivan

Buona sera a tutti, mi sono rimesso a lavorare sul codice e scritto in questo modo non ho problemi nella compilazione.
Spero che funzioni, anche se non ho ancora provato.
Avete altri consigli da darmi?

// di seguito includo la libreria per la comunicazione su bus I2C
#include <Wire.h>

int start_h=00;
int start_m=00;
int end_h=00;
int end_m=00;
int releacceso=0;
 
void setup()
{
    pinMode(2, OUTPUT);    // PIN DOVE E' COLLEGATO IL RELE'
    
  // inizializzo la comunicazione seriale
  Serial.begin(9600);
 
  //inizializzo la libreria
  Wire.begin();
 
  // adesso, inizializzo la comunicazione con il DS1307. 
  // L’indirizzo del DS1307 di default è 0x68
  Wire.beginTransmission(0x68);
  // il primo byte stabilisce il registro
  Wire.write((byte)0x00);
  // imposto l’orario e la data
  Wire.write((byte)0x00); // 1° byte SECONDI da 0x00 a 0x59
  Wire.write((byte)0x10); // 2° byte MINUTI da 0x00 a 0x59
  Wire.write((byte)0x80 | 0x10); // 3° byte ORE da 0x00 a 0x24
  Wire.write((byte)0x01); // 4° byte GIORNO della settimana da 0x01 a 0x07
  Wire.write((byte)0x21); // 5° byte GIORNO del mese da 0x00 a 0x31
  Wire.write((byte)0x03); // 6° byte MESE da 0x00 a 0x12
  Wire.write((byte)0x12); // 7° byte ANNO 0x00 a 0x99
  Wire.endTransmission();
}
 
void loop()
{
  // inizzializzo la trasmissione partendo dall'indirizzo 0x00
  Wire.beginTransmission(0x68);
  Wire.write((byte)0x00);
  Wire.endTransmission();
 
  // richiedo 7 byte dal dispositivo con indirizzo 0x68
  Wire.requestFrom(0x68, 7);
  // recupero i 7 byte relativi ai corrispondenti registri
  byte secondi = Wire.read();
  byte minuti = Wire.read();
  byte ora = Wire.read();
  byte giorno_sett = Wire.read();
  byte giorno_mese = Wire.read();
  byte mese = Wire.read();
  byte anno = Wire.read();
  int Secondigiorno = secondi+ minuti*60 +ora*60*60;
 
  Serial.print("Ora corrente: ");
  Serial.print(ora, HEX);
  Serial.print(":");
  Serial.print(minuti, HEX);
  Serial.print(":");
  Serial.println(secondi, HEX);
 
  Serial.print("Giorno della settimana: ");
  Serial.println(giorno_sett, HEX);
 
  Serial.print("Data corrente: ");
  Serial.print(giorno_mese, HEX);
  Serial.print("/");
  Serial.print(mese, HEX);
  Serial.print("/");
  Serial.println(anno, HEX);
  Serial.println();
   delay(1000);
   
   // QUI' IMPOSTO I PARAMETRI DI ACCENSIONE DEL RELE' --- COME FACCIO A IMPOSTARE - DA QUANDO A QUANDO- DOVRA' RESTARE ECCITATO?
   if (Secondigiorno >=28800 &&  Secondigiorno < 29100){
digitalWrite(2, HIGH);
    delay(1000);
releacceso = 1;
}
else 
if (releacceso = 1){
digitalWrite(2, LOW);
    delay(1000);
 releacceso = 0;}
   
   
}

A presto,
Ivan

Ivan,
per i confronti di date e ore ... dai un'occhiata a QUESTA vecchia discussione ... la funzione per il TimeStamp è sempre molto utile :wink:

Guglielmo

Attento che secondi giorno può avere come massimo 86399 mentre int ha 32767: non ci sta!
Usa long per la variabile secondigiorno.