💧 Arduino • Livello acqua • LCD I2C

Sensore livello acqua con Arduino e display LCD I2C

Misuriamo il livello dell’acqua, lo trasformiamo in una percentuale e lo visualizziamo su un display LCD, con quattro LED che indicano le diverse fasce di riempimento.

DifficoltàIntermedia
IngressoA0 analogico
DisplayLCD 16×2 I2C o parallelo
In poche parole: Arduino legge il sensore di livello su A0, limita la lettura tra due valori calibrati, la converte in 0–100% con map() e aggiorna display e LED.

Cosa imparerai

  • come leggere un sensore di livello acqua analogico;
  • come calibrare minimo e massimo;
  • come convertire la lettura in percentuale;
  • come usare un LCD 16×2 con interfaccia I2C;
  • come usare in alternativa un LCD 16×2 parallelo;
  • come creare indicazioni di livello con più LED.

Il sensore e il display I2C

Sensore livello acqua per Arduino

Sensore di livello acqua utilizzato nel progetto .

Display LCD I2C per Arduino

Display LCD 16×2 con interfaccia I2C.

Il progetto propone due versioni: una con display I2C, che riduce il numero di collegamenti verso Arduino, e una con il classico LCD 16×2 parallelo.

Materiale necessario

🔌 Arduino Uno
💧 Sensore livello acqua
📟 Display LCD 16×2 I2C
💡 4 LED
〰️ 4 resistenze da 220 Ω
🧩 Breadboard e cavetti

🧰 Kit Arduino consigliato

Molti progetti del sito utilizzano display, LED, resistenze, sensori e breadboard. Un kit completo può essere comodo per iniziare.

👉 Guarda il kit Arduino consigliato

Link di affiliazione Amazon: in qualità di Affiliato Amazon ricevo un guadagno dagli acquisti idonei, senza alcun costo aggiuntivo per te.

📘 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.

Schema con display I2C

Schema Arduino sensore livello acqua con display I2C

Schema I2C. Nel sito questa immagine era visualizzata a circa 700 px.

Schema con display 16×2 parallelo

Schema Arduino sensore livello acqua con LCD 16x2

Versione con display parallelo. Nel sito era visualizzata a circa 750 px.

Calibrazione del sensore

Nel progetto vengono usati due valori sperimentali:

ParametroValore Significato
valoremin500Valore con recipiente vuoto
valoremax700Valore con recipiente pieno
Questi valori non sono universali: devi misurare il minimo e il massimo del tuo sensore nel contenitore reale e sostituire 500 e 700 con i valori ottenuti.

Codice Arduino – versione I2C

Nota sulla libreria: il progetto usa newliquidcrystal_1.3.4 e un costruttore esteso di LiquidCrystal_I2C. Oggi esistono più librerie con lo stesso nome ma API differenti. Se il costruttore non compila, verifica quale libreria hai installato invece di cancellare alla cieca le librerie presenti nell’IDE.
Sensore livello acqua + LCD I2C
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// Costruttore usato nella libreria NewLiquidCrystal.
// Se la tua libreria usa una sintassi diversa, consulta
// la documentazione della versione installata.
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

// Pin analogico del sensore
const int sensorePin = A0;

// LED di livello
const int ledAlto = 9;
const int ledMedioAlto = 10;
const int ledMedioBasso = 11;
const int ledBasso = 12;

// Valori ottenuti sperimentalmente
// nel progetto .
const int valoreMin = 500;
const int valoreMax = 700;

void setup() {

 // Monitor Seriale per il debug
 Serial.begin(9600);

 // Inizializza LCD 16x2
 lcd.begin(16, 2);

 // Piccolo effetto di avvio della retroilluminazione
 for (int i = 0; i < 3; i++) {
 lcd.backlight();
 delay(250);
 lcd.noBacklight();
 delay(250);
 }

 lcd.backlight();

 // Configura i quattro LED
 pinMode(ledAlto, OUTPUT);
 pinMode(ledMedioAlto, OUTPUT);
 pinMode(ledMedioBasso, OUTPUT);
 pinMode(ledBasso, OUTPUT);

 // Il LED rosso di livello basso resta sempre acceso
 // come indicatore della fascia minima.
 digitalWrite(ledBasso, HIGH);
}

void loop() {

 // Legge il valore grezzo del sensore
 int valoreRaw = analogRead(sensorePin);

 // Mostra la lettura sul Monitor Seriale
 Serial.print("Lettura grezza: ");
 Serial.print(valoreRaw);

 // Limita la lettura all'intervallo calibrato
 valoreRaw = constrain(valoreRaw, valoreMin, valoreMax);

 // Converte 500...700 in 0...100%
 int livello = map(valoreRaw, valoreMin, valoreMax, 0, 100);

 Serial.print(" - Livello: ");
 Serial.print(livello);
 Serial.println("%");

 // Aggiorna il display
 lcd.clear();
 lcd.setCursor(0, 0);
 lcd.print("Livello: ");
 lcd.print(livello);
 lcd.print("%");

 // Spegne preventivamente i tre LED superiori
 digitalWrite(ledMedioBasso, LOW);
 digitalWrite(ledMedioAlto, LOW);
 digitalWrite(ledAlto, LOW);

 // Accende progressivamente i LED
 if (livello > 20) {
 digitalWrite(ledMedioBasso, HIGH);
 }

 if (livello > 50) {
 digitalWrite(ledMedioAlto, HIGH);
 }

 if (livello > 80) {
 digitalWrite(ledAlto, HIGH);
 }

 // Nuova misura ogni secondo
 delay(1000);
}

Come funziona la percentuale

Prima di usare map(), la lettura viene limitata tra minimo e massimo. In questo modo un valore inferiore al minimo non genera percentuali negative e uno superiore al massimo non supera il 100%.

Esempio: con minimo 500 e massimo 700, una lettura di circa 600 viene convertita approssimativamente nel 50%.

Indicazione con quattro LED

LivelloIndicazione
0–20%Rosso
> 20%Rosso + giallo
> 50%Rosso + giallo + primo verde
> 80%Tutti i LED accesi

Versione con display 16×2 parallelo

La seconda versione della guida utilizza la libreria standard LiquidCrystal.h e collega il display con RS, Enable e quattro linee dati.

LCD parallelo: inizializzazione e logica principale
#include <LiquidCrystal.h>

// RS, EN, D4, D5, D6, D7
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

const int sensorePin = A0;

const int ledAlto = 9;
const int ledMedioAlto = 10;
const int ledMedioBasso = 11;
const int ledBasso = 12;

const int valoreMin = 500;
const int valoreMax = 700;

void setup() {

 Serial.begin(9600);

 lcd.begin(16, 2);

 pinMode(ledAlto, OUTPUT);
 pinMode(ledMedioAlto, OUTPUT);
 pinMode(ledMedioBasso, OUTPUT);
 pinMode(ledBasso, OUTPUT);

 digitalWrite(ledBasso, HIGH);
}

void loop() {

 int valoreRaw = analogRead(sensorePin);

 valoreRaw = constrain(valoreRaw, valoreMin, valoreMax);

 int livello = map(valoreRaw, valoreMin, valoreMax, 0, 100);

 Serial.print("Livello: ");
 Serial.print(livello);
 Serial.println("%");

 lcd.clear();
 lcd.setCursor(0, 0);
 lcd.print("Livello: ");
 lcd.print(livello);
 lcd.print("%");

 digitalWrite(ledMedioBasso, livello > 20 ? HIGH : LOW);
 digitalWrite(ledMedioAlto, livello > 50 ? HIGH : LOW);
 digitalWrite(ledAlto, livello > 80 ? HIGH : LOW);

 delay(1000);
}

I2C oppure collegamento parallelo?

I2CParallelo
Pochi filiPiù pin Arduino occupati
Serve una libreria compatibileLibreria LiquidCrystal standard
Indirizzo I2C da verificareNessun indirizzo I2C
Cablaggio più ordinatoOttimo per capire il funzionamento del display

Indirizzo I2C: perché 0x27 potrebbe non funzionare

Nel progetto viene usato l’indirizzo 0x27. Molti moduli usano questo indirizzo, ma non è garantito. Se il display resta vuoto, conviene eseguire uno sketch I2C Scanner e verificare l’indirizzo reale del modulo.

Immagini del progetto

Arduino sensore livello acqua risultato progetto
Arduino sensore livello acqua e display

Download

⬇️ Libreria newliquidcrystal_1.3.4.zip

⬇️ Sketch display I2C

⬇️ Sketch display 16×2

Debug rapido

  • controlla VCC e GND del sensore;
  • verifica che il segnale analogico arrivi ad A0;
  • osserva la lettura grezza nel Monitor Seriale;
  • calibra valoreMin e valoreMax sul tuo contenitore;
  • se il display I2C non mostra nulla, verifica indirizzo e libreria;
  • se il display parallelo è vuoto, controlla contrasto e cablaggio;
  • verifica la polarità dei LED e le resistenze da 220 Ω.

Varianti del progetto

  • aggiungere un buzzer quando il livello è troppo basso;
  • attivare una pompa tramite MOSFET o relè adatto;
  • usare un OLED al posto dell’LCD;
  • aggiungere un allarme di troppo pieno;
  • inviare il livello via Wi-Fi con ESP32;
  • registrare l’andamento del livello nel tempo.

Cosa devi ricordare

  • Il sensore viene letto su A0.
  • Minimo e massimo devono essere calibrati sperimentalmente.
  • map() trasforma la lettura in una scala 0–100%.
  • I LED indicano progressivamente le diverse fasce di livello.
  • La versione I2C riduce molto il numero di fili del display.
  • L’indirizzo 0x27 e la libreria I2C vanno verificati sul modulo reale.

Domande frequenti

Perché il display I2C non visualizza nulla?

Controlla alimentazione, contrasto, indirizzo I2C e compatibilità della libreria. 0x27 è comune ma non universale.

Posso usare valori diversi da 500 e 700?

Sì, e in genere dovresti farlo. Quei numeri appartengono alla calibrazione del progetto ; misura vuoto e pieno con il tuo sensore.

La percentuale è una misura precisa del volume?

Non necessariamente. È una percentuale ricavata dalla risposta del sensore. La relazione con il volume reale dipende da sensore, geometria del contenitore e calibrazione.

Posso comandare direttamente una pompa con Arduino?

No. Usa un MOSFET, un transistor o un modulo relè adatto alla corrente della pompa, con alimentazione e protezioni corrette.