PROGETTI ARDUINO

  • HOME
  • 200 Progetti
  • Progetti e Tutorial
  • Reti
    • Impara le reti
    • internet fibra
    • wifi mesh
    • modem router
    • diagnostica reti
    • ethernet lan
    • sicurezza configurazione
  • Elettronica
  • Recensioni
  • Manuale
  • Contatti
  • HOME
  • 200 Progetti
  • Progetti e Tutorial
  • Reti
    • Impara le reti
    • internet fibra
    • wifi mesh
    • modem router
    • diagnostica reti
    • ethernet lan
    • sicurezza configurazione
  • Elettronica
  • Recensioni
  • Manuale
  • Contatti

Progetto 126
Orologio digitale con
​RTC DS3231

🚀 Introduzione

Vuoi realizzare un orologio digitale preciso che continui a mantenere data e ora anche quando Arduino viene spento? ⏰

In questo progetto utilizzerai il modulo RTC DS3231, un orologio in tempo reale dotato di batteria tampone.

Arduino leggerà ore, minuti, secondi e data dal modulo RTC, visualizzando tutte le informazioni su un display OLED.
​
👉 Il DS3231 è molto più preciso rispetto al semplice conteggio del tempo con millis() ed è ideale per sveglie, timer, centraline e automazioni programmate.

🎯 Cosa realizzerai
​

Con Arduino creerai un sistema che:
  • ⏰ mostra ore, minuti e secondi
  • 📅 visualizza giorno, mese e anno
  • 📆 indica il giorno della settimana
  • 📟 utilizza un display OLED SSD1306
  • 🔋 mantiene l’ora anche quando Arduino è spento
  • ⚠️ controlla se il modulo RTC ha perso l’alimentazione
  • 🔄 aggiorna automaticamente la schermata
  • 🕒 permette di impostare data e ora dal codice

🧰 Materiale necessario
​
  • 1x Arduino UNO
  • 1x modulo RTC DS3231
  • 1x batteria CR2032 per il modulo RTC
  • 1x display OLED 0,96 pollici I2C SSD1306
  • cavetti jumper
  • breadboard
  • cavo USB
Il display OLED e il modulo DS3231 utilizzano entrambi la comunicazione I2C e possono quindi condividere i pin SDA e SCL.
🛒 Non hai ancora i componenti?

Molti dei progetti presenti su progettiarduino.com utilizzano componenti elettronici di base come LED, resistenze, sensori e breadboard.
Se stai iniziando con Arduino, il modo più semplice è utilizzare un kit completo per principianti, che include quasi tutti i componenti necessari per realizzare molti dei progetti presenti sul sito.

👉 Kit Arduino consigliato:
ℹ️ Link di affiliazione Amazon: in qualità di Affiliato Amazon ricevo un guadagno dagli acquisti idonei, senza alcun costo aggiuntivo per te.
https://amzn.to/4b3dxjW

📘 Vuoi imparare Arduino passo dopo passo?
Se vuoi approfondire e realizzare progetti più completi, puoi dare un'occhiata anche ai miei libri dedicati ad Arduino.
All'interno troverai spiegazioni semplici, schemi chiari e molti progetti pratici pensati per chi parte da zero.

👉 Scopri i miei libri su Arduino:
ℹ️ Link di affiliazione Amazon: in qualità di Affiliato Amazon ricevo un guadagno dagli acquisti idonei, senza alcun costo aggiuntivo per te.
https://amzn.to/4rfzjXE
​
📚 Librerie necessarie
​

Per realizzare il progetto devi installare:
  • RTClib
  • Adafruit SSD1306
  • Adafruit GFX Library
​
Per installarle:
  1. apri Arduino IDE;
  2. vai su Sketch → Include Library → Manage Libraries;
  3. cerca RTClib;
  4. installa la libreria sviluppata da Adafruit;
  5. cerca Adafruit SSD1306;
  6. installa la libreria;
  7. installa anche Adafruit GFX Library se non è già presente.
La libreria Wire, utilizzata per la comunicazione I2C, è già inclusa nell’Arduino IDE.

🔌 Schema di collegamento

Display OLED SSD1306
  • VCC → 5V
  • GND → GND
  • SDA → A4
  • SCL → A5
L’indirizzo I2C utilizzato dal display OLED è normalmente 0x3C.

Modulo RTC DS3231
  • VCC → 5V
  • GND → GND
  • SDA → A4
  • SCL → A5
Il display OLED e il modulo RTC vengono collegati agli stessi pin A4 e A5.
​
Questo è possibile perché i dispositivi I2C utilizzano indirizzi differenti:
  • display OLED: 0x3C;
  • modulo DS3231: 0x68.

Batteria tampone
Inserisci una batteria CR2032 nel portabatteria del modulo DS3231, rispettando la polarità indicata
La batteria alimenta soltanto l’orologio interno quando Arduino viene spento.
👉 Senza batteria tampone, il modulo potrebbe perdere data e ora quando viene scollegata l’alimentazione principale.
Foto

💻 Codice Arduino
​

Il programma inizializza il display OLED e il modulo DS3231.
Successivamente legge dal modulo:
  • ora;
  • minuti;
  • secondi;
  • giorno;
  • mese;
  • anno;
  • giorno della settimana.
​
Le informazioni vengono visualizzate su tre aree del display:
  • giorno della settimana nella parte superiore;
  • ora in formato grande al centro;
  • data nella parte inferiore.
​/*
  ============================================================
  Progetto 126 - Orologio digitale con RTC DS3231
  Visualizza ora, data e giorno della settimana su display OLED
  ============================================================
*/

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <RTClib.h>

// Dimensioni del display OLED
#define LARGHEZZA_DISPLAY 128
#define ALTEZZA_DISPLAY 64
#define RESET_OLED -1

// Indirizzo I2C tipico del display SSD1306
#define INDIRIZZO_OLED 0x3C

// Oggetto utilizzato per controllare il display OLED
Adafruit_SSD1306 display(
  LARGHEZZA_DISPLAY,
  ALTEZZA_DISPLAY,
  &Wire,
  RESET_OLED
);

// Oggetto utilizzato per comunicare con il modulo DS3231
RTC_DS3231 rtc;

// Nomi italiani dei giorni della settimana.
// La funzione dayOfTheWeek() restituisce:
// 0 = domenica, 1 = lunedì, fino a 6 = sabato.
const char* giorniSettimana[7] = {
  "Domenica",
  "Lunedi",
  "Martedi",
  "Mercoledi",
  "Giovedi",
  "Venerdi",
  "Sabato"
};

// Memorizza l'ultimo secondo mostrato.
// In questo modo il display viene aggiornato solo quando serve.
int ultimoSecondoVisualizzato = -1;

// Indica se il modulo RTC è stato rilevato correttamente
bool rtcDisponibile = false;

void setup() {
  // Avvia la comunicazione I2C
  Wire.begin();

  // Inizializza il display OLED
  if (!display.begin(
        SSD1306_SWITCHCAPVCC,
        INDIRIZZO_OLED
      )) {
    // Se il display non viene rilevato,
    // il programma rimane bloccato in questo ciclo.
    while (true) {
    }
  }

  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);
  display.setTextWrap(false);

  // Mostra una breve schermata iniziale
  mostraAvvio();

  // Prova a inizializzare il modulo RTC DS3231
  rtcDisponibile = rtc.begin();

  // Se il modulo non viene rilevato,
  // mostra un messaggio di errore e blocca il programma.
  if (!rtcDisponibile) {
    mostraErroreRtc();

    while (true) {
    }
  }

  // Se il DS3231 ha perso l'alimentazione,
  // imposta automaticamente data e ora di compilazione.
  if (rtc.lostPower()) {
    rtc.adjust(
      DateTime(
        F(__DATE__),
        F(__TIME__)
      )
    );

    mostraImpostazioneOra();
  }
}

void loop() {
  // Legge data e ora correnti dal DS3231
  DateTime adesso = rtc.now();

  // Aggiorna la schermata soltanto quando cambia il secondo.
  // Questo evita di ridisegnare inutilmente il display
  // centinaia di volte al secondo.
  if (adesso.second() != ultimoSecondoVisualizzato) {
    ultimoSecondoVisualizzato = adesso.second();
    mostraOrologio(adesso);
  }
}

void mostraAvvio() {
  // Pulisce completamente il display
  display.clearDisplay();
  display.setTextSize(1);

  display.setCursor(22, 17);
  display.println("Orologio digitale");

  display.setCursor(31, 33);
  display.println("RTC DS3231");

  display.setCursor(28, 49);
  display.println("Progetto 126");

  // Invia al display gli elementi appena disegnati
  display.display();

  delay(1800);
}

void mostraOrologio(const DateTime& adesso) {
  // Cancella la schermata precedente
  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);

  // Recupera il giorno della settimana
  byte indiceGiorno = adesso.dayOfTheWeek();

  // Mostra il nome del giorno nella parte superiore
  display.setTextSize(1);
  centraTesto(
    giorniSettimana[indiceGiorno],
    2,
    1
  );

  // Disegna una linea sotto il giorno della settimana
  display.drawLine(
    0,
    12,
    127,
    12,
    SSD1306_WHITE
  );

  // Mostra ore, minuti e secondi con caratteri grandi
  display.setTextSize(2);
  display.setCursor(16, 21);

  stampaDueCifre(adesso.hour());
  display.print(":");

  stampaDueCifre(adesso.minute());
  display.print(":");

  stampaDueCifre(adesso.second());

  // Mostra la data nella parte inferiore
  display.setTextSize(1);
  display.setCursor(35, 51);

  stampaDueCifre(adesso.day());
  display.print("/");

  stampaDueCifre(adesso.month());
  display.print("/");

  display.print(adesso.year());

  // Rende visibile la nuova schermata
  display.display();
}

void stampaDueCifre(int valore) {
  // Aggiunge uno zero davanti ai numeri inferiori a 10.
  // Per esempio, 7 viene visualizzato come 07.
  if (valore < 10) {
    display.print("0");
  }

  display.print(valore);
}

void centraTesto(
  const char* testo,
  int coordinataY,
  byte dimensione
) {
  // Imposta la dimensione utilizzata per calcolare il testo
  display.setTextSize(dimensione);

  int16_t x1;
  int16_t y1;
  uint16_t larghezzaTesto;
  uint16_t altezzaTesto;

  // Calcola lo spazio occupato dalla scritta
  display.getTextBounds(
    testo,
    0,
    coordinataY,
    &x1,
    &y1,
    &larghezzaTesto,
    &altezzaTesto
  );

  // Calcola la posizione orizzontale necessaria
  // per centrare il testo sul display
  int coordinataX =
    (LARGHEZZA_DISPLAY - larghezzaTesto) / 2;

  display.setCursor(
    coordinataX,
    coordinataY
  );

  display.print(testo);
}

void mostraErroreRtc() {
  // Mostra un messaggio quando il DS3231
  // non viene rilevato sul bus I2C.
  display.clearDisplay();
  display.setTextSize(1);

  display.setCursor(20, 15);
  display.println("ERRORE RTC");

  display.setCursor(9, 31);
  display.println("DS3231 non rilevato");

  display.setCursor(15, 47);
  display.println("Controlla i cavi");

  display.display();
}

void mostraImpostazioneOra() {
  // Avvisa che data e ora sono state impostate
  // usando il momento di compilazione del programma.
  display.clearDisplay();
  display.setTextSize(1);

  display.setCursor(18, 15);
  display.println("Ora impostata");

  display.setCursor(10, 31);
  display.println("Data di compilazione");

  display.setCursor(14, 47);
  display.println("Batteria: controlla");

  display.display();

  delay(2000);
}

⚙️ Come funziona

Il modulo DS3231 contiene un circuito dedicato al conteggio del tempo.
A differenza di Arduino, non dipende dal ciclo principale del programma e continua a funzionare grazie alla batteria tampone.
​
La seguente istruzione legge la data e l’ora correnti:
DateTime adesso = rtc.now();
​
Dall’oggetto adesso è possibile ottenere ogni informazione:
adesso.hour();
adesso.minute();
adesso.second();
adesso.day();
adesso.month();
adesso.year();

​
Arduino aggiorna il display soltanto quando cambia il secondo visualizzato, evitando ridisegni inutili.

🕒 Impostazione iniziale di data e ora
​

Quando il DS3231 viene utilizzato per la prima volta, è necessario impostare l’orologio.

Il codice controlla se il modulo ha perso l’alimentazione:
​
if (rtc.lostPower()) {
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}

​
In questo caso, data e ora vengono impostate utilizzando il momento in cui il programma è stato compilato.
​
Le costanti:
  • __DATE__
  • __TIME__
sono generate automaticamente dall’Arduino IDE.
​
👉 Dopo la prima impostazione, il modulo continuerà a mantenere l’orario grazie alla batteria CR2032.

📅 Giorno della settimana

La funzione:
adesso.dayOfTheWeek();
restituisce un numero compreso tra 0 e 6.

Nel programma viene utilizzato un array per associare ogni numero al nome italiano del giorno:
const char* giorniSettimana[7] = {
"Domenica",
"Lunedi",
"Martedi",
"Mercoledi",
"Giovedi",
"Venerdi",
"Sabato"
};

In questo modo il display mostra direttamente il nome del giorno.

🔋 Perché utilizzare il DS3231
​

Arduino può misurare il tempo trascorso tramite millis(), ma questo sistema presenta alcuni limiti:
  • il conteggio riparte da zero quando Arduino viene spento;
  • non conosce data e ora reali;
  • può accumulare errori nel lungo periodo;
  • non gestisce automaticamente giorni, mesi e anni.
​
Il DS3231 è invece progettato appositamente per mantenere il tempo reale ed è dotato di compensazione della temperatura per migliorare la precisione.

⚠️ Problemi comuni
​

Il display non mostra nulla
Controlla:
  • alimentazione del display;
  • collegamenti SDA e SCL;
  • indirizzo I2C 0x3C;
  • installazione delle librerie.

Il modulo RTC non viene rilevato
Controlla:
  • collegamenti del DS3231;
  • alimentazione a 5V;
  • condivisione corretta dei pin I2C;
  • eventuali cavetti difettosi.

L’orario si azzera quando Arduino viene spento
Controlla che:
  • la batteria CR2032 sia presente;
  • la batteria sia inserita nel verso corretto;
  • la batteria non sia scarica.

L’orario è leggermente indietro rispetto al computer
La compilazione e il caricamento richiedono alcuni secondi.
Poiché __TIME__ contiene l’ora di compilazione, al primo avvio può esserci un piccolo ritardo.

🧠 Perché è un progetto importante
​

Con questo progetto impari a:
  • utilizzare un modulo RTC DS3231
  • mantenere data e ora senza alimentazione principale
  • collegare più dispositivi allo stesso bus I2C
  • utilizzare la libreria RTClib
  • leggere ore, minuti e secondi
  • gestire giorno, mese e anno
  • mostrare il giorno della settimana
  • formattare correttamente un orario
  • aggiornare il display soltanto quando necessario
👉 Il modulo RTC sarà fondamentale nei prossimi progetti dedicati a sveglie, timer settimanali e automazioni programmate.

🔄 Varianti possibili
​

Vuoi migliorare il progetto?
  • 🔘 aggiungi pulsanti per regolare data e ora
  • 🔔 collega un buzzer per creare una sveglia
  • 🌡️ mostra la temperatura interna del DS3231
  • 📊 alterna orologio e dati ambientali
  • 💡 regola automaticamente la luminosità del display
  • 🌙 crea una modalità notturna
  • ⏱️ aggiungi un cronometro
  • ⏳ inserisci un timer countdown
  • 💾 salva impostazioni e preferenze nella EEPROM
  • 📟 utilizza un display OLED più grande
  • 📶 sincronizza l’ora tramite Internet con ESP8266 o ESP32
Foto
Foto

© ProgettiArduino.com 2026 - Fancello Salvatore
​ Layout, immagini e testi sono di esclusiva proprietà di www.progettiarduino.com 
Privacy Policy