Go Down

Topic: Creazione temporizzatore con RTC DS1307 - aiuto codice (Read 7060 times) previous topic - next topic

Ivan_Isk

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.
Code: [Select]

// 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
HELLO WORLD!

uwefed

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+ minuti*60 +ore*60*60
e poi
Code: [Select]
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

Ivan_Isk

Ciao, grazie per la risposta!
E se invece facessi così dovrebbe funzionare?
Code: [Select]

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

:smiley-roll-sweat: :smiley-roll-sweat: :smiley-roll-sweat: :smiley-roll-sweat:
HELLO WORLD!

uwefed

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

Code: [Select]
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

Ivan_Isk

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
HELLO WORLD!

leo72

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.

Ivan_Isk

Ottima spiegazione, grazie.
Ho testato il seguente codice, ma sono presenti degli errori...
Code: [Select]
// 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  :smiley-eek:

A presto,
Ivan
HELLO WORLD!

leo72

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

Ecco cosa ottengo io:
Code: [Select]
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;

Ivan_Isk

Ciao, ho scritto che mi restituisce degli errori ma ho dimenticato di scrivere quali sono. Eccoli:
Code: [Select]
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'
HELLO WORLD!

PaoloP

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 =

Ivan_Isk

Grazie per la risposta,
Ho corretto il codice nel seguente modo e viene caricato correttamente:
Code: [Select]
// 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
HELLO WORLD!

PaoloP

Code: [Select]
#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.

leo72



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

leo72


Ivan_Isk

Ops, grazie per la pazienza  :)
Ho provato lo sketch, ma... :smiley-sad-blue: 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
HELLO WORLD!

Go Up