RTC DS1307, maledetto ladro...

Ragazzi, sto litigando con un un DS1307, proprio non riesco a scoprire dove sto sbagliando. Premetto che non ho acquistato il modulo pronto all’uso ma i singoli componenti. Il collegamento del DS1307 credo sia corretto, ho usato due resistenze da 1K, il quarzo da 32,768 Mhz e la batteria da 3V per mantenere l’orario come illustrato in molti schemi in rete. Ho notato che i secondi non corrispondono alla realtà perchè ogni tanto salta un secondo (1,2,3,4,6,7,… ). Ho ridotto all’osso lo script in questione, potete illuminarmi perchè si frega i secondi? Lo script è molto elementare, ogni secondo il display lcd mostra l’orario restituito dal RTC e invia tramite seriale i secondi:

#include <WProgram.h>
#include <Wire.h>
#include <DS1307.h>
#include <LiquidCrystal.h>

LiquidCrystal lcd(2, 3, 4, 5, 6, 7, 8);
int rtc[7];

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

RTC.stop();
RTC.set(DS1307_SEC,44); //set the seconds
RTC.set(DS1307_MIN,23); //set the minutes
RTC.set(DS1307_HR,12); //set the hours
RTC.set(DS1307_DOW,4); //set the day of the week
RTC.set(DS1307_DATE,5); //set the date
RTC.set(DS1307_MTH,3); //set the month
RTC.set(DS1307_YR,9); //set the year
RTC.start();
}

void loop()
{
orologio();
Serial.print("Secondi = ");
Serial.println(rtc[0]);
delay(1000);
}

void orologio()
{
RTC.get(rtc,true);
lcd.setCursor(0,0);
lcd.print(rtc[2]); // ore
lcd.print(":");
lcd.print(rtc[1]); // minuti
lcd.print(":");
lcd.print(rtc[0]); // secondi
}

Dov’è l’errore, manca qualche componente oppure è un problema legato allo script?

Secondo me non devi usare il delay. Invia il comando solo quando il valore RTC(secondi) è cambiato rispetto al ciclo precedente

SE RTC(secondi)attuale DIVERSO da RTC(secondi)precedente ALLORA Invia il valore alla seriale

RTC(secondi)precedente = RTC(secondi)attuale

Scusa se non te l'ho scritto sotto forma di codice ma l'ho buttato giù così al volo ... Se non ti è chiaro lo buttiamo giù insieme il codice

e ovvio che si mangia i secondi perche oltre al delay di 1 secondo devi contare il tempo di esecuzione del codice e ogni tanto ti fa perdere una lettura quindi come dice ambrogio devi toglierlo e controllare il cambiamento o tipo mettere come delay 100 millisecondi in modo che ti passi sempre il valore esatto con un errore massimo del 10%.

c

Ciao Ambrogio, grazie per la tua disponibilità. Da quello che ho capito mi consigli di rimuovere il delay suppongo con la funzione millis(); . Sto costruendo un timer crepuscolare, lo script originale dal quale ho estrapolato l’esempio usa i valori restituiti dal DS1307 per controllare l’accensione e lo spegnimento di alcune lampade a led in PWM per ottenere l’effetto crepuscolare. In pratica quando l’ora dell’RTC è uguale a quella impostata dall’utente, ogni secondo faccio partire un contatore che incrementa di 1 il valore di una variabile (ecco perchè avevo usato il delay); questa variabile servirà poi per calcolarmi il valore PWM da trasmettere all’uscita. A questo punto se tolgo il delay poi il contatore quando parte come faccio a farlo aumentare di 1 soltanto dopo un secondo?

No no, non ti serve nemmeno il millis !

dovrebbe essere una cosa del genere:

if (rtc[0] != secondi_precedenti) //se per esempio “secondi” vale 5 e nel ciclo precedente valeva 4
{
Serial.print("Secondi = "); //invia il comando alla seriale
Serial.println(rtc[0]);
}
secondi_precedenti = rtc[0]; // aggiorno la variabile, quindi al prox ciclo varrà 5 e non esegue il contenuto dell’IF fino a quando rtc[0] varrà 6 … e così via.

Ora provo... intanto grazie per l'aiuto. A pensarci la soluzione era piuttosto semplice, si vede che sono ancora agli inizi.