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 135
​Display errori sistema

🚀 Introduzione
​

Vuoi fare in modo che Arduino riconosca automaticamente un problema e mostri un messaggio chiaro sul display? ⚠️📟
In questo progetto realizzerai un sistema di diagnostica con display OLED, capace di controllare diversi ingressi e segnalare eventuali anomalie.
​
Arduino verificherà:
  • funzionamento del sensore DHT22;
  • temperatura troppo elevata;
  • luminosità troppo bassa;
  • stato di un sensore porta;
  • tensione di alimentazione simulata.
Ogni problema sarà associato a un codice di errore, proprio come avviene nelle centraline e nei dispositivi elettronici reali.
​
👉 Il progetto insegna a distinguere tra un semplice valore fuori soglia e un vero errore di sistema.

🎯 Cosa realizzerai
​

Con Arduino creerai un sistema che:
  • 🌡️ controlla temperatura e umidità;
  • 💡 misura la luminosità ambientale;
  • 🚪 rileva lo stato di una porta;
  • 🔋 controlla una tensione simulata;
  • ⚠️ assegna un codice a ogni errore;
  • 📟 mostra l’anomalia sul display OLED;
  • 🔁 alterna più errori contemporaneamente;
  • ✅ mostra una schermata normale quando tutto funziona;
  • 🔘 permette di scorrere manualmente gli errori;
  • ⏱️ utilizza millis() senza bloccare Arduino.

🧰 Materiale necessario
​
  • 1x Arduino UNO;
  • 1x display OLED 0,96 pollici I2C SSD1306;
  • 1x sensore DHT22;
  • 1x resistenza da 10 kΩ, se utilizzi il sensore senza modulo;
  • 1x fotoresistenza LDR;
  • 1x resistenza da 10 kΩ per il partitore della fotoresistenza;
  • 1x sensore magnetico reed switch;
  • 1x potenziometro da 10 kΩ;
  • 1x pulsante;
  • cavetti jumper;
  • breadboard;
  • cavo USB.
​
Il potenziometro simula la tensione di alimentazione del sistema.
🛒 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.
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.

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.

Potenziometro
  • terminale laterale → 5V;
  • terminale laterale opposto → GND;
  • terminale centrale → A1.
Ruotando il potenziometro puoi simulare una tensione di alimentazione compresa tra 0V e 5V.

Reed switch
  • un terminale → pin digitale 3;
  • terminale opposto → GND.
Il codice utilizza INPUT_PULLUP.
Con il magnete vicino, il contatto viene normalmente letto come LOW.

Pulsante
  • un terminale → pin digitale 4;
  • terminale opposto → GND.
Il pulsante permette di passare manualmente all’errore successivo.
Foto

💻 Codice Arduino
​

Il programma controlla cinque possibili anomalie:
  • E01 → sensore DHT22 non disponibile;
  • E02 → temperatura troppo elevata;
  • E03 → luminosità troppo bassa;
  • E04 → porta aperta;
  • E05 → tensione simulata troppo bassa.

Quando non sono presenti errori, il display mostra:
SISTEMA OK
​
Se invece sono presenti più anomalie, Arduino le alterna automaticamente.
​/*
  ============================================================
  Progetto 135 - Display errori di sistema
  Controlla sensori e mostra codici di errore su display OLED
  ============================================================
*/

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHT.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 degli altri componenti
#define PIN_PORTA 3
#define PIN_PULSANTE 4
#define PIN_LUCE A0
#define PIN_TENSIONE A1

// Soglie utilizzate per generare gli errori
const float SOGLIA_TEMPERATURA = 30.0;
const int SOGLIA_LUMINOSITA = 20;
const float SOGLIA_TENSIONE = 3.5;

// Intervalli temporali
const unsigned long INTERVALLO_LETTURA = 2000;
const unsigned long INTERVALLO_CAMBIO_ERRORE = 3000;
const unsigned long TEMPO_DEBOUNCE = 180;

// Numero massimo di errori gestiti
const byte NUMERO_ERRORI = 5;

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

DHT dht(PIN_DHT, TIPO_DHT);

// Tipi di errore disponibili
enum CodiceErrore {
  ERRORE_DHT,
  ERRORE_TEMPERATURA,
  ERRORE_LUMINOSITA,
  ERRORE_PORTA,
  ERRORE_TENSIONE
};

// Array che contiene gli errori attualmente attivi
CodiceErrore erroriAttivi[NUMERO_ERRORI];

// Numero di errori presenti
byte numeroErroriAttivi = 0;

// Errore attualmente visualizzato
byte indiceErroreVisualizzato = 0;

// Valori letti dai sensori
float temperatura = 0.0;
int luminositaPercentuale = 0;
float tensione = 0.0;

// Stati del sistema
bool sensoreDhtValido = false;
bool portaAperta = false;

// Variabili temporali utilizzate da millis()
unsigned long ultimaLettura = 0;
unsigned long ultimoCambioErrore = 0;
unsigned long ultimaPressione = 0;

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

void setup() {
  // Il reed switch e il pulsante sono collegati a GND
  // e utilizzano le resistenze interne di Arduino
  pinMode(PIN_PORTA, INPUT_PULLUP);
  pinMode(PIN_PULSANTE, INPUT_PULLUP);

  // Avvia il sensore DHT22
  dht.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();

  // Esegue subito una prima lettura
  leggiSensori();
  aggiornaElencoErrori();
  mostraSchermata();

  ultimaLettura = millis();
  ultimoCambioErrore = millis();
  aggiornamentoDisplayRichiesto = false;
}

void loop() {
  // Controlla il pulsante per lo scorrimento manuale
  gestisciPulsante();

  // Controlla continuamente lo stato della porta
  bool nuovoStatoPorta =
    digitalRead(PIN_PORTA) == HIGH;

  if (nuovoStatoPorta != portaAperta) {
    portaAperta = nuovoStatoPorta;

    aggiornaElencoErrori();
    aggiornamentoDisplayRichiesto = true;
  }

  // Legge periodicamente tutti gli altri sensori
  if (millis() - ultimaLettura >= INTERVALLO_LETTURA) {
    ultimaLettura = millis();

    leggiSensori();
    aggiornaElencoErrori();

    aggiornamentoDisplayRichiesto = true;
  }

  // Se sono presenti più errori,
  // passa automaticamente al successivo
  if (numeroErroriAttivi > 1 &&
      millis() - ultimoCambioErrore >=
      INTERVALLO_CAMBIO_ERRORE) {
    ultimoCambioErrore = millis();

    passaErroreSuccessivo();
    aggiornamentoDisplayRichiesto = true;
  }

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

void leggiSensori() {
  // Legge la temperatura dal DHT22
  float nuovaTemperatura = dht.readTemperature();

  // Se la lettura non è valida,
  // segnala un errore di comunicazione
  if (isnan(nuovaTemperatura)) {
    sensoreDhtValido = false;
  } else {
    sensoreDhtValido = true;
    temperatura = nuovaTemperatura;
  }

  // Legge il partitore formato da LDR
  // e resistenza da 10 kΩ
  int valoreLuce = analogRead(PIN_LUCE);

  // Converte la lettura in percentuale
  luminositaPercentuale = map(
    valoreLuce,
    0,
    1023,
    0,
    100
  );

  luminositaPercentuale = constrain(
    luminositaPercentuale,
    0,
    100
  );

  // Legge il potenziometro che simula
  // la tensione di alimentazione
  int valoreTensione = analogRead(PIN_TENSIONE);

  // Converte il valore analogico in volt
  tensione =
    valoreTensione * (5.0 / 1023.0);
}

void aggiornaElencoErrori() {
  // Ricostruisce completamente l'elenco
  // degli errori presenti nel sistema
  numeroErroriAttivi = 0;

  // E01: il sensore DHT22 non risponde
  if (!sensoreDhtValido) {
    aggiungiErrore(ERRORE_DHT);
  }

  // E02: la temperatura supera la soglia
  if (sensoreDhtValido &&
      temperatura >= SOGLIA_TEMPERATURA) {
    aggiungiErrore(ERRORE_TEMPERATURA);
  }

  // E03: la luminosità è troppo bassa
  if (luminositaPercentuale <=
      SOGLIA_LUMINOSITA) {
    aggiungiErrore(ERRORE_LUMINOSITA);
  }

  // E04: il reed switch segnala porta aperta
  if (portaAperta) {
    aggiungiErrore(ERRORE_PORTA);
  }

  // E05: la tensione simulata è troppo bassa
  if (tensione <= SOGLIA_TENSIONE) {
    aggiungiErrore(ERRORE_TENSIONE);
  }

  // Mantiene l'indice nei limiti
  if (numeroErroriAttivi == 0) {
    indiceErroreVisualizzato = 0;
  } else if (
    indiceErroreVisualizzato >= numeroErroriAttivi
  ) {
    indiceErroreVisualizzato = 0;
  }
}

void aggiungiErrore(CodiceErrore errore) {
  // Aggiunge il codice all'array
  // soltanto se esiste ancora spazio
  if (numeroErroriAttivi < NUMERO_ERRORI) {
    erroriAttivi[numeroErroriAttivi] = errore;
    numeroErroriAttivi++;
  }
}

void gestisciPulsante() {
  // Con INPUT_PULLUP il pulsante premuto
  // viene letto come livello LOW
  if (digitalRead(PIN_PULSANTE) == LOW &&
      millis() - ultimaPressione >=
      TEMPO_DEBOUNCE) {
    ultimaPressione = millis();

    // Scorre gli errori soltanto
    // quando almeno uno è presente
    if (numeroErroriAttivi > 0) {
      passaErroreSuccessivo();

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

void passaErroreSuccessivo() {
  // Se non ci sono errori, non esegue nulla
  if (numeroErroriAttivi == 0) {
    return;
  }

  indiceErroreVisualizzato++;

  // Dopo l'ultimo errore torna al primo
  if (indiceErroreVisualizzato >=
      numeroErroriAttivi) {
    indiceErroreVisualizzato = 0;
  }
}

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

  // Se sono presenti errori,
  // mostra la schermata diagnostica
  if (numeroErroriAttivi > 0) {
    mostraErroreAttivo();
  } else {
    mostraSistemaOk();
  }

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

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

  // Titolo e stato generale
  display.setCursor(0, 0);
  display.print("DIAGNOSTICA");

  display.setCursor(79, 0);
  display.print("SISTEMA OK");

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

  // Temperatura corrente
  display.setCursor(0, 16);
  display.print("Temp: ");

  if (sensoreDhtValido) {
    display.print(temperatura, 1);
    display.print((char)247);
    display.print("C");
  } else {
    display.print("ERR");
  }

  // Luminosità corrente
  display.setCursor(0, 28);
  display.print("Luce: ");
  display.print(luminositaPercentuale);
  display.print("%");

  // Tensione simulata
  display.setCursor(0, 40);
  display.print("Tensione: ");
  display.print(tensione, 2);
  display.print("V");

  // Stato della porta
  display.setCursor(0, 52);
  display.print("Porta: ");

  if (portaAperta) {
    display.print("APERTA");
  } else {
    display.print("CHIUSA");
  }
}

void mostraErroreAttivo() {
  // Recupera il codice da visualizzare
  CodiceErrore errore =
    erroriAttivi[indiceErroreVisualizzato];

  // Disegna un bordo attorno al messaggio
  display.drawRect(
    0,
    0,
    128,
    64,
    SSD1306_WHITE
  );

  display.setTextSize(1);

  // Mostra la posizione nell'elenco
  display.setCursor(4, 4);
  display.print("Errore ");
  display.print(indiceErroreVisualizzato + 1);
  display.print("/");
  display.print(numeroErroriAttivi);

  // Mostra codice, titolo e descrizione
  switch (errore) {
    case ERRORE_DHT:
      mostraMessaggioErrore(
        "E01",
        "ERRORE DHT22",
        "Controlla sensore"
      );
      break;

    case ERRORE_TEMPERATURA:
      mostraMessaggioErrore(
        "E02",
        "TEMP. ELEVATA",
        "Raffredda ambiente"
      );
      break;

    case ERRORE_LUMINOSITA:
      mostraMessaggioErrore(
        "E03",
        "LUCE BASSA",
        "Controlla ambiente"
      );
      break;

    case ERRORE_PORTA:
      mostraMessaggioErrore(
        "E04",
        "PORTA APERTA",
        "Chiudi ingresso"
      );
      break;

    case ERRORE_TENSIONE:
      mostraMessaggioErrore(
        "E05",
        "TENSIONE BASSA",
        "Controlla aliment."
      );
      break;
  }

  display.setCursor(13, 54);
  display.print("Premi: prossimo");
}

void mostraMessaggioErrore(
  const char* codice,
  const char* titolo,
  const char* descrizione
) {
  // Mostra il codice con caratteri grandi
  display.setTextSize(2);
  display.setCursor(46, 15);
  display.print(codice);

  // Mostra titolo e descrizione
  display.setTextSize(1);
  centraTesto(titolo, 36);
  centraTesto(descrizione, 46);
}

void centraTesto(
  const char* testo,
  int coordinataY
) {
  int16_t x1;
  int16_t y1;
  uint16_t larghezza;
  uint16_t altezza;

  // Calcola la dimensione della scritta
  display.getTextBounds(
    testo,
    0,
    coordinataY,
    &x1,
    &y1,
    &larghezza,
    &altezza
  );

  // Calcola la posizione necessaria
  // per centrare il testo orizzontalmente
  int coordinataX =
    (LARGHEZZA_DISPLAY - larghezza) / 2;

  display.setCursor(
    coordinataX,
    coordinataY
  );

  display.print(testo);
}

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

  display.setCursor(16, 15);
  display.print("Diagnostica sistema");

  display.setCursor(23, 31);
  display.print("Display errori");

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

  display.display();

  delay(1800);
}

⚙️ Come funziona

Arduino legge periodicamente tutti i sensori.
Ogni valore viene confrontato con una soglia.

Le soglie iniziali sono:
  • temperatura massima: 30 °C;
  • luminosità minima: 20%;
  • tensione minima: 3,5V.
​
Lo stato della porta viene invece letto direttamente dal reed switch.
Quando una condizione è fuori dai limiti, il relativo errore viene aggiunto all’elenco delle anomalie attive.

⚠️ Codici di errore
​

Ogni errore possiede:
  • un codice;
  • un titolo;
  • una breve descrizione.
​
Per esempio:
E02
TEMPERATURA ALTA
​
Controlla ambiente
Questa organizzazione rende il sistema più facile da diagnosticare.
👉 In un progetto reale, i codici potrebbero essere riportati anche in un manuale tecnico.

🔋 Controllo della tensione simulata
​

Il potenziometro genera un valore analogico compreso tra 0 e 1023.

Arduino lo converte in una tensione:
tensione = valoreAnalogico * (5.0 / 1023.0);

​Quando il valore scende sotto 3,5V, viene attivato l’errore:
E05 - TENSIONE BASSA
​
👉 Per misurare una batteria reale con tensione superiore a 5V è necessario utilizzare un partitore correttamente dimensionato.

🌡️ Errore e soglia non sono la stessa cosa
​

Il progetto distingue due situazioni:
  • sensore non disponibile;
  • valore valido ma fuori soglia.
Se il DHT22 non risponde, viene mostrato E01.
​
Se invece il sensore funziona ma misura una temperatura troppo alta, viene mostrato E02.
Questa distinzione è importante nei sistemi di diagnostica reali.

🧠 Perché è un progetto importante
​

Con questo progetto impari a:
  • creare un sistema di diagnostica;
  • assegnare codici agli errori;
  • controllare più sensori;
  • distinguere guasti e valori fuori soglia;
  • gestire più anomalie contemporaneamente;
  • utilizzare array di errori;
  • alternare messaggi sul display;
  • misurare una tensione analogica;
  • costruire una schermata di stato;
  • organizzare il codice in funzioni.
​
👉 Questa tecnica è utile per centraline, impianti domotici, robot, sistemi di sicurezza e automazioni industriali.

🔄 Varianti possibili
​

Vuoi migliorare il progetto?
  • 🔊 aggiungi un buzzer di errore;
  • 🚨 assegna priorità differenti agli allarmi;
  • 💾 salva gli errori nella EEPROM;
  • ⏰ registra data e ora con RTC DS3231;
  • 📋 crea uno storico degli ultimi eventi;
  • 🔘 aggiungi un pulsante per confermare gli errori;
  • 💡 collega LED di stato differenti;
  • 📶 invia gli errori tramite Wi-Fi;
  • 🗃️ salva gli eventi su microSD;
  • ⚡ controlla automaticamente un relè;
  • 🔒 aggiungi un errore per accesso non autorizzato;
  • 🏠 integra il sistema in una centralina domotica.

Foto
Foto

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