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 139
Display informazioni
​multi schermo

🚀 Introduzione
​

Vuoi mostrare molte informazioni su un piccolo display OLED senza riempire troppo la schermata? 📟📋

In questo progetto realizzerai un display multi schermo con Arduino, capace di organizzare i dati del sistema in pagine separate.

Tramite due pulsanti potrai passare alla schermata successiva o precedente. Arduino potrà inoltre cambiare pagina automaticamente dopo alcuni secondi.

Le schermate mostreranno:
  • data e ora;
  • temperatura e umidità;
  • luminosità ambientale;
  • stato generale del sistema.
​
👉 Questa struttura è ideale per centraline, stazioni ambientali, pannelli domotici e dispositivi con molte informazioni.

🎯 Cosa realizzerai
​

Con Arduino creerai un sistema che:
  • ⏰ mostra data e ora;
  • 🌡️ misura la temperatura;
  • 💧 misura l’umidità;
  • 💡 rileva la luminosità;
  • 📟 organizza i dati in quattro schermate;
  • ➡️ passa alla pagina successiva;
  • ⬅️ ritorna alla pagina precedente;
  • 🔄 cambia schermata automaticamente;
  • ⏸️ sospende temporaneamente il cambio automatico dopo una pressione;
  • ⚠️ segnala eventuali errori del sensore.

🧰 Materiale necessario
​
  • 1x Arduino UNO;
  • 1x display OLED 0,96 pollici I2C SSD1306;
  • 1x sensore DHT22;
  • 1x resistenza da 10 kΩ, se utilizzi il DHT22 senza modulo;
  • 1x fotoresistenza LDR;
  • 1x resistenza da 10 kΩ;
  • 1x modulo RTC DS3231;
  • 1x batteria CR2032;
  • 2x pulsanti;
  • cavetti jumper;
  • breadboard;
  • cavo USB.
​
I pulsanti utilizzano le resistenze interne INPUT_PULLUP di Arduino e non richiedono resistenze esterne.

🛒 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:
  • Adafruit SSD1306;
  • Adafruit GFX Library;
  • DHT sensor library;
  • Adafruit Unified Sensor;
  • RTClib.
​
La libreria Wire è già inclusa nell’Arduino IDE.
🔌 Schema di collegamento

Display OLED SSD1306
  • VCC → 5V;
  • GND → GND;
  • SDA → A4;
  • SCL → A5.
L’indirizzo I2C utilizzato nel codice è 0x3C.

Modulo RTC DS3231
  • VCC → 5V;
  • GND → GND;
  • SDA → A4;
  • SCL → A5.
Il display OLED e il modulo RTC condividono i pin I2C.

Sensore DHT22
Se utilizzi un modulo già assemblato:
  • VCC → 5V;
  • GND → GND;
  • DATA → pin digitale 2.
Se utilizzi il sensore senza modulo, collega una resistenza da 10 kΩ tra DATA e 5V.

Fotoresistenza LDR
Realizza un partitore di tensione:
  • un terminale della fotoresistenza → 5V;
  • terminale opposto → A0;
  • resistenza da 10 kΩ tra A0 e GND.

Pulsante AVANTI
  • un terminale → pin digitale 3;
  • terminale opposto → GND.

Pulsante INDIETRO
  • un terminale → pin digitale 4;
  • terminale opposto → GND.
Con INPUT_PULLUP, un pulsante premuto viene letto come LOW.
Foto

💻 Codice Arduino
​

Il programma utilizza quattro schermate:
  1. data e ora;
  2. temperatura e umidità;
  3. luminosità;
  4. stato del sistema.
​
I pulsanti permettono di spostarsi manualmente tra le pagine.
Se non vengono premuti pulsanti, Arduino cambia automaticamente schermata ogni cinque secondi.
​/*
  ============================================================
  Progetto 139 - Display informazioni multi schermo
  Mostra ora, ambiente, luminosita e stato del sistema
  ============================================================
*/

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

// Dimensioni e indirizzo del display OLED
#define LARGHEZZA_DISPLAY 128
#define ALTEZZA_DISPLAY 64
#define RESET_OLED -1
#define INDIRIZZO_OLED 0x3C

// Configurazione del sensore DHT22
#define PIN_DHT 2
#define TIPO_DHT DHT22

// Collegamenti dei pulsanti e della fotoresistenza
#define PIN_AVANTI 3
#define PIN_INDIETRO 4
#define PIN_LUCE A0

// Numero totale delle schermate
const byte NUMERO_SCHERMATE = 4;

// Intervallo tra due letture del DHT22
const unsigned long INTERVALLO_LETTURA = 2000;

// Durata di visualizzazione automatica di ogni pagina
const unsigned long INTERVALLO_SCHERMATA = 5000;

// Tempo antirimbalzo dei pulsanti
const unsigned long TEMPO_DEBOUNCE = 180;

// Numero di campioni usati per filtrare la luce
const byte NUMERO_CAMPIONI_LUCE = 20;

// Oggetti utilizzati per display, DHT22 e RTC
Adafruit_SSD1306 display(
  LARGHEZZA_DISPLAY,
  ALTEZZA_DISPLAY,
  &Wire,
  RESET_OLED
);

DHT dht(PIN_DHT, TIPO_DHT);
RTC_DS3231 rtc;

// Nomi abbreviati dei giorni della settimana
const char* giorniSettimana[7] = {
  "DOM",
  "LUN",
  "MAR",
  "MER",
  "GIO",
  "VEN",
  "SAB"
};

// Valori ambientali correnti
float temperatura = 0.0;
float umidita = 0.0;
float temperaturaPercepita = 0.0;
int luminositaPercentuale = 0;

// Stato dei componenti
bool sensoreDhtValido = false;
bool rtcDisponibile = false;

// Pagina attualmente visualizzata
byte schermataAttuale = 0;

// Variabili temporali utilizzate dal programma
unsigned long ultimaLettura = 0;
unsigned long ultimoCambioSchermata = 0;
unsigned long ultimaPressione = 0;

// Indica quando il display deve essere ridisegnato
bool aggiornamentoDisplayRichiesto = true;

void setup() {
  // I pulsanti sono collegati tra pin e GND
  // e utilizzano le resistenze interne di Arduino
  pinMode(PIN_AVANTI, INPUT_PULLUP);
  pinMode(PIN_INDIETRO, INPUT_PULLUP);

  // Avvia il sensore DHT22 e il bus I2C
  dht.begin();
  Wire.begin();

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

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

  // Mostra una breve schermata iniziale
  mostraAvvio();

  // Controlla la presenza del modulo RTC
  rtcDisponibile = rtc.begin();

  if (!rtcDisponibile) {
    mostraErroreRtc();

    while (true) {
    }
  }

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

  // Esegue subito una prima lettura dei sensori
  leggiSensori();
  mostraSchermata();

  // Memorizza i tempi iniziali
  ultimaLettura = millis();
  ultimoCambioSchermata = millis();
  aggiornamentoDisplayRichiesto = false;
}

void loop() {
  // Controlla i due pulsanti di navigazione
  gestisciPulsanti();

  // Legge periodicamente i sensori
  if (millis() - ultimaLettura >= INTERVALLO_LETTURA) {
    ultimaLettura = millis();

    leggiSensori();
    aggiornamentoDisplayRichiesto = true;
  }

  // Cambia automaticamente schermata
  // quando è trascorso l'intervallo impostato
  if (millis() - ultimoCambioSchermata >=
      INTERVALLO_SCHERMATA) {
    ultimoCambioSchermata = millis();

    schermataSuccessiva();
    aggiornamentoDisplayRichiesto = true;
  }

  // Ridisegna il display soltanto quando necessario
  if (aggiornamentoDisplayRichiesto) {
    mostraSchermata();
    aggiornamentoDisplayRichiesto = false;
  }
}

void leggiSensori() {
  // Legge temperatura e umidità dal DHT22
  float nuovaTemperatura = dht.readTemperature();
  float nuovaUmidita = dht.readHumidity();

  // Aggiorna i dati soltanto quando
  // entrambe le letture sono valide
  if (!isnan(nuovaTemperatura) &&
      !isnan(nuovaUmidita)) {
    temperatura = nuovaTemperatura;
    umidita = nuovaUmidita;

    // Calcola la temperatura percepita in Celsius
    temperaturaPercepita = dht.computeHeatIndex(
      temperatura,
      umidita,
      false
    );

    sensoreDhtValido = true;
  } else {
    // Conserva gli ultimi valori corretti
    // ma segnala l'errore del sensore
    sensoreDhtValido = false;
  }

  // Legge la luminosità applicando
  // una media di più campioni
  luminositaPercentuale = leggiLuminosita();
}

int leggiLuminosita() {
  unsigned long somma = 0;

  // Esegue più letture per ridurre
  // oscillazioni e rumore analogico
  for (byte i = 0; i < NUMERO_CAMPIONI_LUCE; i++) {
    somma += analogRead(PIN_LUCE);
    delayMicroseconds(200);
  }

  int valoreMedio =
    somma / NUMERO_CAMPIONI_LUCE;

  // Converte la lettura in percentuale
  int percentuale = map(
    valoreMedio,
    0,
    1023,
    0,
    100
  );

  return constrain(
    percentuale,
    0,
    100
  );
}

void gestisciPulsanti() {
  // Accetta una nuova pressione soltanto
  // dopo il tempo necessario all'antirimbalzo
  if (millis() - ultimaPressione < TEMPO_DEBOUNCE) {
    return;
  }

  // Pulsante per la schermata successiva
  if (digitalRead(PIN_AVANTI) == LOW) {
    ultimaPressione = millis();

    schermataSuccessiva();

    // Fa ripartire il conteggio automatico
    ultimoCambioSchermata = millis();
    aggiornamentoDisplayRichiesto = true;
    return;
  }

  // Pulsante per la schermata precedente
  if (digitalRead(PIN_INDIETRO) == LOW) {
    ultimaPressione = millis();

    schermataPrecedente();

    ultimoCambioSchermata = millis();
    aggiornamentoDisplayRichiesto = true;
  }
}

void schermataSuccessiva() {
  // Passa alla pagina seguente
  schermataAttuale++;

  // Dopo l'ultima pagina torna alla prima
  if (schermataAttuale >= NUMERO_SCHERMATE) {
    schermataAttuale = 0;
  }
}

void schermataPrecedente() {
  // Dalla prima pagina passa direttamente all'ultima
  if (schermataAttuale == 0) {
    schermataAttuale = NUMERO_SCHERMATE - 1;
  } else {
    schermataAttuale--;
  }
}

void mostraSchermata() {
  // Pulisce completamente il display
  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);

  // Seleziona la funzione relativa alla pagina attiva
  switch (schermataAttuale) {
    case 0:
      mostraDataOra();
      break;

    case 1:
      mostraAmbiente();
      break;

    case 2:
      mostraLuminosita();
      break;

    case 3:
      mostraStatoSistema();
      break;
  }

  // Invia al display tutti gli elementi disegnati
  display.display();
}

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

  display.setTextSize(1);

  // Titolo e numero della pagina
  display.setCursor(0, 0);
  display.print("DATA E ORA");

  display.setCursor(105, 0);
  display.print("1/4");

  display.drawLine(
    0,
    10,
    127,
    10,
    SSD1306_WHITE
  );

  // Mostra il giorno della settimana
  display.setCursor(50, 15);
  display.print(
    giorniSettimana[adesso.dayOfTheWeek()]
  );

  // Mostra l'ora con caratteri grandi
  display.setTextSize(2);
  display.setCursor(16, 27);

  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, 54);

  stampaDueCifre(adesso.day());
  display.print("/");
  stampaDueCifre(adesso.month());
  display.print("/");
  display.print(adesso.year());
}

void mostraAmbiente() {
  display.setTextSize(1);

  // Titolo e numero della pagina
  display.setCursor(0, 0);
  display.print("DATI AMBIENTALI");

  display.setCursor(105, 0);
  display.print("2/4");

  display.drawLine(
    0,
    10,
    127,
    10,
    SSD1306_WHITE
  );

  // Se il sensore non è disponibile,
  // mostra un messaggio di errore
  if (!sensoreDhtValido) {
    display.setCursor(28, 24);
    display.print("ERRORE DHT22");

    display.setCursor(18, 41);
    display.print("Controlla sensore");
    return;
  }

  // Mostra temperatura e umidità
  display.setCursor(0, 17);
  display.print("Temperatura: ");
  display.print(temperatura, 1);
  display.print((char)247);
  display.print("C");

  display.setCursor(0, 31);
  display.print("Umidita:    ");
  display.print(umidita, 1);
  display.print("%");

  // Mostra la temperatura percepita
  display.setCursor(0, 45);
  display.print("Percepita:  ");
  display.print(temperaturaPercepita, 1);
  display.print((char)247);
  display.print("C");

  display.setCursor(0, 57);
  display.print(valutaComfort());
}

void mostraLuminosita() {
  display.setTextSize(1);

  display.setCursor(0, 0);
  display.print("LUMINOSITA");

  display.setCursor(105, 0);
  display.print("3/4");

  display.drawLine(
    0,
    10,
    127,
    10,
    SSD1306_WHITE
  );

  // Mostra la percentuale con caratteri grandi
  display.setTextSize(2);
  display.setCursor(43, 17);
  display.print(luminositaPercentuale);
  display.print("%");

  // Disegna una barra proporzionale alla luce
  display.drawRect(
    8,
    39,
    112,
    11,
    SSD1306_WHITE
  );

  int larghezzaBarra = map(
    luminositaPercentuale,
    0,
    100,
    0,
    108
  );

  display.fillRect(
    10,
    41,
    larghezzaBarra,
    7,
    SSD1306_WHITE
  );

  // Mostra una valutazione testuale
  display.setTextSize(1);
  display.setCursor(40, 55);
  display.print(testoLuminosita());
}

void mostraStatoSistema() {
  display.setTextSize(1);

  display.setCursor(0, 0);
  display.print("STATO SISTEMA");

  display.setCursor(105, 0);
  display.print("4/4");

  display.drawLine(
    0,
    10,
    127,
    10,
    SSD1306_WHITE
  );

  // Stato del sensore DHT22
  display.setCursor(0, 17);
  display.print("DHT22: ");

  if (sensoreDhtValido) {
    display.print("ONLINE");
  } else {
    display.print("ERRORE");
  }

  // Stato del modulo RTC
  display.setCursor(0, 30);
  display.print("RTC:   ");

  if (rtcDisponibile) {
    display.print("ONLINE");
  } else {
    display.print("ERRORE");
  }

  // Stato della fotoresistenza
  display.setCursor(0, 43);
  display.print("LDR:   ONLINE");

  // Stato del cambio automatico
  display.setCursor(0, 56);
  display.print("Cambio auto: 5 sec");
}

const char* valutaComfort() {
  // Valutazione ambientale indicativa
  if (umidita < 40.0) {
    return "Ambiente troppo secco";
  }

  if (umidita > 65.0) {
    return "Ambiente troppo umido";
  }

  if (temperatura < 18.0) {
    return "Temperatura bassa";
  }

  if (temperatura > 28.0) {
    return "Temperatura elevata";
  }

  return "Ambiente confortevole";
}

const char* testoLuminosita() {
  // Classifica il livello di illuminazione
  if (luminositaPercentuale < 25) {
    return "BUIO";
  }

  if (luminositaPercentuale > 75) {
    return "LUMINOSO";
  }

  return "NORMALE";
}

void stampaDueCifre(int valore) {
  // Aggiunge uno zero davanti ai valori inferiori a 10
  if (valore < 10) {
    display.print("0");
  }

  display.print(valore);
}

void mostraAvvio() {
  display.clearDisplay();
  display.setTextSize(1);

  display.setCursor(12, 14);
  display.print("Display multi schermo");

  display.setCursor(21, 30);
  display.print("Pannello informazioni");

  display.setCursor(28, 47);
  display.print("Progetto 139");

  display.display();

  delay(1800);
}

void mostraErroreRtc() {
  display.clearDisplay();
  display.setTextSize(1);

  display.setCursor(27, 15);
  display.print("ERRORE RTC");

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

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

  display.display();
}

⚙️ Come funziona

Arduino legge temperatura, umidità e luminosità a intervalli regolari.
Il modulo DS3231 fornisce invece data e ora.

La variabile schermataAttuale indica quale pagina deve essere visualizzata.

Quando viene premuto il pulsante AVANTI, il numero della schermata aumenta.
​
Quando viene premuto INDIETRO, il numero diminuisce.

Dopo l’ultima pagina, il sistema ritorna automaticamente alla prima.

📟 Schermata data e ora
​

La prima schermata mostra:
  • giorno della settimana;
  • ora corrente;
  • giorno, mese e anno.
L’orario viene letto direttamente dal modulo RTC DS3231.
​
La batteria CR2032 permette al modulo di continuare a mantenere l’ora anche quando Arduino viene spento.

🌡️ Schermata ambientale
​

La seconda schermata mostra:
  • temperatura;
  • umidità;
  • temperatura percepita.
​
La temperatura percepita viene calcolata dalla libreria DHT utilizzando temperatura reale e umidità.
Se il sensore non risponde, sul display appare un messaggio di errore.

💡 Schermata luminosità
​

La fotoresistenza genera un valore analogico compreso tra 0 e 1023.

Il programma lo trasforma in una percentuale da 0 a 100.

Il display mostra:
  • percentuale numerica;
  • barra grafica;
  • valutazione dell’ambiente.
​
Gli stati disponibili sono:
  • BUIO;
  • NORMALE;
  • LUMINOSO.

🛠️ Schermata stato sistema
​

L’ultima pagina mostra lo stato dei componenti:
  • DHT22;
  • modulo RTC;
  • sensore luminosità;
  • cambio automatico delle schermate.
Questa pagina funziona come una piccola schermata diagnostica.

🔄 Cambio automatico

Se l’utente non preme alcun pulsante, Arduino cambia pagina ogni cinque secondi.

Dopo una pressione manuale, il timer automatico riparte da zero.

In questo modo la schermata selezionata rimane visibile per tutto l’intervallo previsto.
​
Puoi modificare la durata attraverso:
const unsigned long INTERVALLO_SCHERMATA = 5000;

🧠 Perché è un progetto importante

Con questo progetto impari a:
  • creare un’interfaccia multi schermo;
  • organizzare molte informazioni;
  • navigare con due pulsanti;
  • realizzare una navigazione circolare;
  • cambiare pagina automaticamente;
  • utilizzare più dispositivi I2C;
  • mostrare dati numerici e grafici;
  • creare una pagina diagnostica;
  • gestire più intervalli tramite millis();
  • strutturare un pannello informativo completo.
​
👉 Questa tecnica è molto utile quando il display è piccolo ma le informazioni da mostrare sono numerose.

🔄 Varianti possibili
​

Vuoi migliorare il progetto?
  • 🎛️ sostituisci i pulsanti con un encoder rotativo;
  • 📊 aggiungi grafici di temperatura e umidità;
  • 💾 salva le impostazioni nella EEPROM;
  • 🔔 aggiungi una schermata degli allarmi;
  • ⚡ mostra lo stato di più relè;
  • 🔋 aggiungi la tensione della batteria;
  • 🌬️ collega un sensore di qualità dell’aria;
  • 🚪 mostra lo stato di porte e finestre;
  • 📶 aggiungi una pagina dedicata al Wi-Fi;
  • 🗃️ mostra i dati registrati su microSD;
  • 📟 utilizza un display OLED da 1,3 pollici;
  • 🏠 trasforma il progetto in una dashboard domotica.

Foto
Foto

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