Problema interfacciamento Arduino / RTC

Ciao a tutti, sono Francesco e sono nuovo nel forum, avrei bisogno di qualche dritta da voi più esperti…

Da un po di tempo ho un Arduino 2009 e sto cercando piano piano di iniziare a sfruttare le mille potenzialità che mi può offrire, mi sono “bloccato” su un piccolo progetto magari per molti di voi banale…una semplice “sveglia”.

Stavo cercando di capire il funzionamento di un RTC DS1307 e ho provato a scrivere un semplice programma che mi fa accende un led ad una certa ora…ma non riesco in nessun modo utilzzando il modulo RTC, ho usato diverse librerie ma con lo stesso risultato, l’unico modo con cui sono riuscito ad accenderlo è con il contatore di Arduino, ma io vorrei utilizzare l’RTC in modo che funzioni anche se viene a mancare la corrente senza dover ogni volta impostare l’ora a mano.

Questo è lo sketch in questione, la base è l’esempio della libreria TimeAlarms, dove sbaglio?

#include <Time.h>
#include <TimeAlarms.h>
#include "RTClib.h"
#include <Wire.h>

RTC_Millis rtc;

int led = 9;

void setup()
{
  Serial.begin(9600);
  pinMode(led, OUTPUT);
  rtc.begin(DateTime(__DATE__, __TIME__));
  // create the alarms 
  Alarm.alarmRepeat(7, 10, 0, MorningAlarm);  
  Alarm.alarmRepeat(7, 11, 0, StopAlarm); 
  
  
}

void  loop(){  
  DateTime now = rtc.now();
  
  Serial.print(now.year(), DEC);
  Serial.print('/');
  Serial.print(now.month(), DEC);
  Serial.print('/');
  Serial.print(now.day(), DEC);
  Serial.print(' ');
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.print(now.second(), DEC);
  Serial.println();
  
  delay(1000);

  
}

void MorningAlarm(){
  Serial.println("Alarm: - turn lights on"); 
  digitalWrite(led, HIGH);  
}

void StopAlarm(){
  Serial.println("Alarm: - turn lights off");
  digitalWrite(led, LOW);
}

questo invece è lo sketch di partenza con il quale funziona impostando l’ora a mano…

#include <Time.h>
#include <TimeAlarms.h>

void setup()
{
  Serial.begin(9600);
  setTime(8,29,0,1,1,11); // set time to Saturday 8:29:00am Jan 1 2011
  // create the alarms 
  Alarm.alarmRepeat(8,30,0, MorningAlarm);  // 8:30am every day
  Alarm.alarmRepeat(17,45,0,EveningAlarm);  // 5:45pm every day 
  Alarm.alarmRepeat(dowSaturday,8,30,30,WeeklyAlarm);  // 8:30:30 every Saturday 

 
  Alarm.timerRepeat(15, Repeats);            // timer for every 15 seconds    
  Alarm.timerOnce(10, OnceOnly);             // called once after 10 seconds 
}

void  loop(){  
  digitalClockDisplay();
  Alarm.delay(1000); // wait one second between clock display
}

// functions to be called when an alarm triggers:
void MorningAlarm(){
  Serial.println("Alarm: - turn lights off");    
}

void EveningAlarm(){
  Serial.println("Alarm: - turn lights on");           
}

void WeeklyAlarm(){
  Serial.println("Alarm: - its Monday Morning");      
}

void ExplicitAlarm(){
  Serial.println("Alarm: - this triggers only at the given date and time");       
}

void Repeats(){
  Serial.println("15 second timer");         
}

void OnceOnly(){
  Serial.println("This timer only triggers once");  
}

void digitalClockDisplay()
{
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.println(); 
}

void printDigits(int digits)
{
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

Grazie in anticipo

Di solito la Wire si include prima della libreria che la utilizza.

Questo è sbagliato

rtc.begin(DateTime(__DATE__, __TIME__));

il codice più corretto è

 if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(__DATE__, __TIME__));
  }

Guarda gli esempi allegati alla libreria.
Una versione recente della lib la trovi qui --> GitHub - adafruit/RTClib: A fork of Jeelab's fantastic RTC library

Grazie per la risposta, ma la libreria che mi hai indicato tu è quella che sto usando, ma il problema non è impostare l'ora, quella è ok, il mio problema secondo me è legato alla parte dove bisogna impostare l'orario di allarme

Alarm.alarmRepeat(23, 42, 0, MorningAlarm);  
  Alarm.alarmRepeat(23, 42, 30, StopAlarm);
void MorningAlarm(){
  Serial.println("Alarm: - turn lights on"); 
  digitalWrite(led, HIGH);  
}

void StopAlarm(){
  Serial.println("Alarm: - turn lights off");
  digitalWrite(led, LOW);
}

ma forse mi sbaglio e il problema è dovuto all'RTC...non so... :roll_eyes: :astonished:

Devi scrivere del codice in cui tu fai un confronto tra l'orario corrente e l'orario dell'allarme e se ore, minuti e secondi combaciano, allora esegui l'operazione.

Il problema è un pò più complesso di così, se cerchi sul forum l'argomento è stato trattato diverse volte (esecuzione di azioni a determinati orari)

Devi scrivere del codice in cui tu fai un confronto tra l'orario corrente e l'orario dell'allarme e se ore, minuti e secondi combaciano, allora esegui l'operazione.

Ho provato anche questa strada, ma mi da errore forse perchè la libreria non supporta la funzione, appena riesco posto lo sketck...

Il problema è un pò più complesso di così, se cerchi sul forum l'argomento è stato trattato diverse volte (esecuzione di azioni a determinati orari)

Già fatto mille ricerche ma non ho trovato nulla che potesse fare al mio caso...magari non ho cercato bene :fearful: :stuck_out_tongue:

Appena riesco posto lo skteck che ho provato...

Le versioni aggiornate delle librerie le trovi qui
--> Time Library, Timekeeping and Time/Date Manipulation on Teensy
--> TimeAlarms Library, Run Functions At Specific Times
--> GitHub - adafruit/RTClib: A fork of Jeelab's fantastic RTC library

Quello che vuoi fare tu è gestire gli allarmi tramite RTC, però la Time su cui si basa la TimeAlarms ha un suo contatore interno.
Quindo dovresti all'avvio controllare se l'RTC è attivo.
Se è attivo sincronizzate il contatore di Time con l'RTC, se non è attivo, impostare l'orario nell'RTC e poi sincronizzarlo col contatore di Time.
Periodicamente devi ricontrollare la sincronizzazione.
Guarda l'esempio "File > Examples > Time > TimeRTCSet." (la lib richiesta dall'esempio la trovi qui --> DS1307RTC Library, For Accessing Real Time Clock (RTC) Chips)

Quindo dovresti all'avvio controllare se l'RTC è attivo.
Se è attivo sincronizzate il contatore di Time con l'RTC, se non è attivo, impostare l'orario nell'RTC e poi sincronizzarlo col contatore di Time.

Ok chiaro adesso il funzionamento della libreria Time, ma domanda da 1000 punti:
Come faccio a sincronizzarlo con l'RTC??? :astonished: :astonished: :astonished:

La parte di sketch che fa ciò per caso è questa?

setSyncProvider(RTC.get);   // the function to get the time from the RTC
  if (timeStatus() != timeSet) 
     Serial.println("Unable to sync with the RTC");
  else
     Serial.println("RTC has set the system time");

Io sto gia usando l’RTC con arduino Mega ed ho un programmino che mi abbassa la temperatura della stufa a pellet ad una determinata ora del giorno per poi rialzarmela ad un’altra ora del giorno e “viaggia” alla grande.
E’ su 1307 quindi in I2C.
Non usa la libreria “time” ma solo quella di comunicazione “wire” perche me lo sono praticamente fatto in casa.
Te lo invio se riesci a tirarci fuori qualcosa di utile.

Spero che leo non si arrabbi ma non ho ancora imparato ad allegare gli sketch in modo corretto.
Scusate :blush: :blush: :blush:

#include <Wire.h> 

long Sensore = 0;
int TemperaturaKelvin = 0;
int TemperaturaCelsius = 0;
int analogPin=A1;
int Pin1=6;
int Pin2=7;
int thresholdA = 0;
int thresholdB = 0;
int thresholdC = 0;
int minutiC = 0;
int oraC = 0;
int Orario_per_crono = 0;


void setup() {
  Serial.begin(9600);
  pinMode (Pin1, OUTPUT); //comando rele' stufa a pellets
  pinMode (Pin2, OUTPUT); //comando rele' caldaia a metano  
  
  Wire.begin(); //Inizializzo la libreria per l'RTC e per la comunicazione I2C 
  Wire.beginTransmission(0x68); //Attivo la comunicazione all'indirizzo 0x68 con l'RTC.
  // Scrivo il settaggio della data da cui l'RTC iniziera' il conteggio.
  Wire.write((byte)0x00);
  
  //Specifico il tempo e la data
  Wire.write((byte)0x00); //1° byte SECONDI da 0x00 a 0x59   
  Wire.write((byte)0x36); //2° byte MINUTI da 0x00 a 0x59   
  Wire.write((byte)0x80 | 0x15); //3° byte ORE da 0x00 a 0x24   
  Wire.write((byte)0x06); //4° byte GIORNO della settimana da 0x01 a 0x07 (Domenica=1,Lunedi=2,ecc)   
  Wire.write((byte)0x31); //5° byte GIORNO del mese da 0x00 a 0x31   
  Wire.write((byte)0x01); //6° byte MESE da 0x00 a 0x12   
  Wire.write((byte)0x14); //7° byte ANNO 0x00 a 0x99   
  Wire.endTransmission(); 
}

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

  Wire.requestFrom(0x68, 7); 
  //richiedo 7 byte dal dispositivo con indirizzo 0x68 (1 per i secondi,1 per i minuti,1 per le ore,ecc.
  byte secondi = Wire.read();  //recupero i 7 byte relativi ai corrispondenti registri  
  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(); 
  
  //Scrivo nel seriale data ed ora NB.i valori sono in esadecimale.
  
  Serial.print("Orario 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(); 
 
 // Converto le ore in numero decimale
   if (ora>=0&&ora<=9) //Per le ore da 00 a 09
   {oraC=ora;}
   else if (ora>=16&&ora<=25)//Per le ore da 10 a 19
   {oraC=ora-6;}
   else  //Per le ore da 20 a 23
   {oraC=ora-12;} 
  
  // Ricavo la frazione di ora per il cronotermostato
    if (minuti<=47) 
    {minutiC=0;}
    else 
    {minutiC=5;}
    
    Orario_per_crono=((10*oraC)+minutiC);
    
     /* Scrivo nel seriale l'orario con frazione di mezz'ora per la programmazione dei cronotermostati e dei settimanali
        da utilizzare per i vari controllori collegati alla rete I2C (riscaldamento,condizionamento,irrigazione,allarmi ecc)*/
  Serial.println ("Orario per cronotermostato"); 
  Serial.println (Orario_per_crono);
  Serial.println ();
  
  
  Sensore = analogRead(A1);  // rilevo il segnale del transistor di temperatura mandata impianto
  TemperaturaKelvin = Sensore *500/1023; // lo rapporto alla tensione della scala analogica
  TemperaturaCelsius = TemperaturaKelvin -273; // ricavo i valori in gradi centigradi
  
 
   while (TemperaturaCelsius < thresholdA) { 
   digitalWrite (Pin1,HIGH);  //accendo la stufa a pellets
   break;
 }
   while (TemperaturaCelsius < thresholdB) { 
   digitalWrite(Pin1, HIGH);
   digitalWrite(Pin2, HIGH); //accendo la caldaia a metano
   break;
 }
   while (TemperaturaCelsius > thresholdC) {
   digitalWrite (Pin1,LOW); // spengo la stufa a pellets
   digitalWrite (Pin2,LOW); // spengo la caldaia a metano
   break;
 }

  Serial.print ("Temperatura Rilevata");
  Serial.print (TemperaturaKelvin -273); //invio alla porta seriale la temperatura di mandata impianto
  Serial.println ("*C");
  Serial.println ();
  
  // Ricavo la programmazione oraria per il circuito di alimentazione del puffer
     
    if (Orario_per_crono>=70&&Orario_per_crono<=185)
    { 
      thresholdA = 35;
      thresholdB = 30;
      thresholdC = 45;
    }
    else
    { 
      thresholdA = 20;
      thresholdB = 15;
      thresholdC = 30;
    }
  // Scrivo sul seriale la temperatura di settaggio del circuito di alta
  Serial.println ("Temperature mandata impianto");
  Serial.print ("Temperatura accensione stufa pellet ");
  Serial.println(thresholdA);
  Serial.print ("Temperatura accensione caldaia a metano ");
  Serial.println(thresholdB);
  Serial.print ("Temperatura spegnimento ");
  Serial.println(thresholdC);
  
  delay(5000);
}

edit by mod: per favore includi il codice usando gli appositi tag

Grazie a tutti per i consigli…alla fine sono riuscito a farlo funzionare e sono andato avanti con lo sketch, sono riuscito anche a far funzionare diversi allarmi, anche se mi sono accorto che il limite massimo che gestisce sono 6 allarmi :fearful:

Vi posto lo sketch…se qualcuno vuole prendere spunto…come dicevo però non riesce a gestire più di 6 allarmi, quindi in questo sketch gli ultimi 2 allarmi non funzionano…se qualcuno trova una soluzione…io stavo pensando ad usare un delay, ma non so qual’è il tempo massimo che si può impostare…

#include <Wire.h>
#include <Time.h>
#include <TimeAlarms.h>
#include <DS1307RTC.h>
#include <LiquidCrystal.h>

#define DS1307_I2C_ADDRESS 0x68

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

int luce1 = 6;
int luce2 = 7;
int luce3 = 8;
int luce4 = 9;
int luce5 = 10;

void setup()
{
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  Serial.begin(9600);
  pinMode(luce1, OUTPUT);
  pinMode(luce2, OUTPUT);
  pinMode(luce3, OUTPUT);
  pinMode(luce4, OUTPUT);
  pinMode(luce5, OUTPUT);
  
  setSyncProvider(RTC.get);
  if(timeStatus()!= timeSet)
     Serial.println("Impossibile sincronizzare con RTC");
  else
     Serial.println("Ora sincronizzata con RTC"); 
  
  //Impostare orari degli allarmi
  Alarm.alarmRepeat(21, 27, 0, Prima);
  Alarm.alarmRepeat(21, 27, 10, Seconda);
  Alarm.alarmRepeat(21, 27, 20, Terza);
  Alarm.alarmRepeat(21, 27, 30, Quarta);
  Alarm.alarmRepeat(21, 27, 40, QuartaOff);
  Alarm.alarmRepeat(21, 27, 50, TerzaOff);
  Alarm.alarmRepeat(21, 28, 2, SecondaOff);
  Alarm.alarmRepeat(21, 28, 12, PrimaOff);
  
}

void loop()
{
  if(timeStatus() == timeSet){
     digitalClockDisplay();
	 lcdClockDisplay();
	 }
  Alarm.delay(1000);
}

void digitalClockDisplay(){
  
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(month());
  Serial.print(" ");
  Serial.print(year()); 
  Serial.println(); 
}

void printDigits(int digits){
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}


void lcdClockDisplay(){
  
  lcd.setCursor(0, 0);
  lcd.print(hour());
  lcdDigits(minute());
  lcdDigits(second());
  lcd.setCursor(0, 1);
  switch(weekday()){
  case 1:
    lcd.print("Dom");
    break;
  case 2:
    lcd.print("Lun");
    break;
  case 3:
    lcd.print("Mar");
    break;
  case 4:
    lcd.print("Mer");
    break;
  case 5:
    lcd.print("Gio");
    break;
  case 6:
    lcd.print("Ven");
    break;
  case 7:
    lcd.print("Sab");
    break;
  }
  
  lcd.print(" ");
  lcd.print(day());
  lcd.print('/');
  lcd.print(month());
  lcd.print('/');
  lcd.print(year()); 
  
}


void lcdDigits(int digital){
  lcd.print(":");
  if(digital < 10)
    lcd.print('0');
  lcd.print(digital);
}




// gestione strisce led:
void Prima(){
  Serial.println("Allarme 1 On"); 
  digitalWrite(luce1, HIGH);
  lcd.setCursor(10, 0);
}

void Seconda(){
  Serial.println("Allarme 2 On");
  digitalWrite(luce2, HIGH);  
  lcd.setCursor(10, 0);
}

void Terza(){
  Serial.println("Allarme 3 On"); 
  digitalWrite(luce3, HIGH);
  lcd.setCursor(10, 0);
}

void Quarta(){
  Serial.println("Allarme 4 On");
  digitalWrite(luce4, HIGH);  
  lcd.setCursor(10, 0);
}



void PrimaOff(){
  Serial.println("Allarme 1 Off"); 
  digitalWrite(luce1, LOW);
  lcd.setCursor(10, 0);
}

void SecondaOff(){
  Serial.println("Allarme 2 Off");
  digitalWrite(luce2, LOW);  
  lcd.setCursor(10, 0);
}

void TerzaOff(){
  Serial.println("Allarme 3 Off"); 
  digitalWrite(luce3, LOW);
  lcd.setCursor(10, 0);
}

void QuartaOff(){
  Serial.println("Allarme 4 Off");
  digitalWrite(luce4, LOW);  
  lcd.setCursor(10, 0);
}