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.
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 di livello acqua utilizzato nel progetto .
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
🧰 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 consigliatoLink 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 ArduinoLink 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 I2C. Nel sito questa immagine era visualizzata a circa 700 px.
Schema con display 16×2 parallelo
Versione con display parallelo. Nel sito era visualizzata a circa 750 px.
Calibrazione del sensore
Nel progetto vengono usati due valori sperimentali:
| Parametro | Valore | Significato |
|---|---|---|
valoremin | 500 | Valore con recipiente vuoto |
valoremax | 700 | Valore con recipiente pieno |
Codice Arduino – versione I2C
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.#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%.
Indicazione con quattro LED
| Livello | Indicazione |
|---|---|
| 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.
#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?
| I2C | Parallelo |
|---|---|
| Pochi fili | Più pin Arduino occupati |
| Serve una libreria compatibile | Libreria LiquidCrystal standard |
| Indirizzo I2C da verificare | Nessun indirizzo I2C |
| Cablaggio più ordinato | Ottimo 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
Download
⬇️ Libreria newliquidcrystal_1.3.4.zip
Debug rapido
- controlla VCC e GND del sensore;
- verifica che il segnale analogico arrivi ad A0;
- osserva la lettura grezza nel Monitor Seriale;
- calibra
valoreMinevaloreMaxsul 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.

