Sondaggi

Quale scheda Arduino usi maggiormente?

View Results

Loading ... Loading ...

Usare il modulo RTC DS1307 con Arduino

Cosa devi sapere per usare un real time clock DS1307

Considero molto utile avere un dispositivo che permetta di tenere traccia del tempo e della data, poiché in molti progetti, come quelli della domotica, richiedono un sistema per recuperare queste informazioni. Avere un circuito che mi garantisca, anche in mancanza di alimentazione, un riferimento temporale sicuro è fondamentale.

DS1307 real time clock RTC pin function

Tipicamente, l’integrato che viene utilizzato maggiormente, in campo hobbistico, è il DS1307. Le sue caratteristiche tecniche sono le seguenti

 Caratteristiche  conteggio in secondi, minuti, ore, giorno della settimana, giorno del mese, mese, anno.
 Interfaccia  bus I2C
 RAM  56 byte aggiuntivi di memoria utente
 Altre uscite  Possibilità di generare un onda quadra di 1Hz, 4096KHz, 8192KHz, 32768KHz

ha un costo contenuto, circa 2.5€, è disponibile sia in package  THT(Through-Hole Technology) sia in SMD, in versioni con standard industriali (temperature di esercizio da -40 a +85 °C).

Anche utilizzarlo è risultato semplice, vista la possibilità di colloquiare tramite bus I2C. Una volta realizzato il circuito seguente, scriviamo alcun istruzioni per settare i registri del DS1307 in modo da impostare la data e l’ora.

schema DS1307

La struttura di questi registri è la seguente:

Struttura registri DS 1307

mentre le istruzioni le trovate di seguito

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

void setup()
{
  //inizializzo la libreria
  Wire.begin();

  //attivo la comunicazione con il DS1307
  //l'indirizzo dell'RTC è 0x68
  Wire.beginTransmission(0x68);
  //il primo byte stabilisce il registro
  //iniziale da scivere
  Wire.write((byte)0x00);
  //specifico il tempo 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()
{
  delay(100);
}

Per poter recuperare le informazioni è sufficiente eseguire una lettura in sequenza dei primi 7 byte, partendo dall’indirizzo 0×00

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

void setup()
{
  //inizializzo la seriale
  Serial.begin(9600);

  //inizializzo la libreria
  Wire.begin();

  //attivo la comunicazione con il DS1307
  //l'indirizzo dell'RTC è 0x68
  Wire.beginTransmission(0x68);
  //il primo byte stabilisce il registro
  //iniziale da scivere
  Wire.write((byte)0x00);
  //specifico il tempo 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()
{
  //inizzializza 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);
  //regupero 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("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();

  delay(1000);
}

La batteria tampone, tipicamente una CR2032, garantisce un back-up di circa 6 mesi.

Delocalizzare la gestione dell’orario su un chip esterno permette di concentrare le risorse dell’Arduino su altri processi e allo stesso tempo di impiegare in modo veloce e semplice il bus I2C per recuperare le informazioni di tempo e data.

Realizzare automatismi basati sul DS1307 è risultato molto economico e semplice, vi invito quindi ad acquistare direttamente il chip piuttosto che i kit già assemblati che attualmente si aggirano tra gli 8€ e i 15€.

11 risposte a Usare il modulo RTC DS1307 con Arduino

  • Dove mi rifornisco io il DS1307 costa ben 6€!!! dove lo trovi a 2,5 €?
    Ciao

  • Puoi trovare il DS1307 sul sito tme.eu, è molto fornito e i prezzi mi sembrano abbordabili anche considerando le spese di spedizione.

    Ciao

  • Ciao,
    sapresti dirmi dove posso trovare il quarzo a 32768 KHz

    Grazie tante e complimenti per l’articolo.

  • Ciao Marco,
    il tuo tool e semplice e funzionale, complimenti..
    Vorrei chiederti 2 spiegazioni che non mi sono chiare….

    1) Vorrei sapere se e possibile cambiare i pin A5 ed A4 utilizzando i pin A3 ed A2 oppure della mega2560 usare i pin 20/21 digitali che corrispondono alla SDA ed SCL, non ho trovato dove li assegni.

    2) mi chiedevo come fai a programmare i minuti l’ora e quant’altro dato che non capisco come fai a metterli in ordine. Ho provato in fase di inserimento a commentare alcune righe ma non riesco a trovare come tu gli dici di scrivere dei dati nello specifico..

    p.s. mi funziona tutto e solo un chiarimento…

    Grazie ciao Max

    • Ciao Max
      grazie per i complimenti!
      i pin A5 ed A4 sono collegati al modulo I2C interno all’Atmega328, quindi la libreria wire utilizza direttamente questo modulo, non puoi usarla con altri pin.
      Per usare altri pin puoi provare ad impiegare la libreria softi2c, personalmente non l’ho mai usata e non so dirti come si comporta.
      L’ordine è stabilito dalla successione delle istruzioni Write, definisci per primo l’indirizzo di partenza e ad ogni Write ottieni uno ‘spostamento’ all’indirizzo successivo.

      Grazie a te
      ciao

  • Azz… dimenticavo..

    cosa significa

      Wire.write((byte)0×80 | 0×10); //3° byte ORE da 0×00 a 0×24

    il numero 80 per cosa sta??

    ri-grazie..

    • Il numero 0×80 serve da maschera (http://en.wikipedia.org/wiki/Mask_%28computing%29). Se controlli la figura della struttura interna della memoria dell’rtc, vedrai che all’indirizzo dove setti l’ora, puoi settare anche altri parametri. In pratica il 0×80 setta questi parametri metre l’altro numero dopo il simbolo or (|) setta l’orario.

      Spero di essere stato chiaro

      saluti
      Marco

      • Ok tutto chiaro…
        grazie per la risposta, andrò a cercare gli altri parametri solo per curiosità …

        Ciao Max

  • Ciao Marco, un grazie per avermi dato la possibilità di apprendere Arduino velocemente e complimenti per le spiegazioni sempre chiare. Veniamo alla domanda. Sto implementando un codice che permette di regolare l’ora e la data del DS1307 via Web. Sto impazzendo per convertire un numero intero decimale in numero esadecimale. Per assegnare per esempio una nuova ora e minuti devo inserire i valori nei rispettivi:
    Wire.write((byte)0×10); //2° byte MINUTI da 0×00 a 0×59
    Wire.write((byte)0×80 | 0×10); //3° byte ORE da 0×00 a 0×24

    dove al posto di 0×10(min) e 0×10(ore) devo associargli le mie variabili. Non riesco proprio a farlo.
    Ma più semplicemente esiste un modo per convertire un numero decimale intero in esadecimale.

    Un saluto e grazie.

  • Aggiungo questo commento per essere più chiaro. Nel tuo codice tu imposti l’ora e la data del Ds1307 inviando i valori in esadecimale. Io vorrei settare i valori in decimale ed inviarli in esadecimale, ma non riesco proprio a convertire in decimale in esadecimale.

    Ciao.