🚀 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:
👉 Questa struttura è ideale per centraline, stazioni ambientali, pannelli domotici e dispositivi con molte informazioni.
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:
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
I pulsanti utilizzano le resistenze interne INPUT_PULLUP di Arduino e non richiedono resistenze esterne.
- 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
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:
La libreria Wire è già inclusa nell’Arduino IDE.
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
Modulo RTC DS3231
Sensore DHT22
Se utilizzi un modulo già assemblato:
Fotoresistenza LDR
Realizza un partitore di tensione:
Pulsante AVANTI
Pulsante INDIETRO
Display OLED SSD1306
- VCC → 5V;
- GND → GND;
- SDA → A4;
- SCL → A5.
Modulo RTC DS3231
- VCC → 5V;
- GND → GND;
- SDA → A4;
- SCL → A5.
Sensore DHT22
Se utilizzi un modulo già assemblato:
- VCC → 5V;
- GND → GND;
- DATA → pin digitale 2.
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.
💻 Codice Arduino
Il programma utilizza quattro schermate:
I pulsanti permettono di spostarsi manualmente tra le pagine.
Se non vengono premuti pulsanti, Arduino cambia automaticamente schermata ogni cinque secondi.
Il programma utilizza quattro schermate:
- data e ora;
- temperatura e umidità;
- luminosità;
- 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();
}
============================================================
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.
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:
La batteria CR2032 permette al modulo di continuare a mantenere l’ora anche quando Arduino viene spento.
La prima schermata mostra:
- giorno della settimana;
- ora corrente;
- giorno, mese e anno.
La batteria CR2032 permette al modulo di continuare a mantenere l’ora anche quando Arduino viene spento.
🌡️ Schermata ambientale
La seconda schermata mostra:
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.
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:
Gli stati disponibili sono:
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:
L’ultima pagina mostra lo stato dei componenti:
- DHT22;
- modulo RTC;
- sensore luminosità;
- cambio automatico delle schermate.
🔄 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;
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:
👉 Questa tecnica è molto utile quando il display è piccolo ma le informazioni da mostrare sono numerose.
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?
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.