Componenti · 14 min di lettura

Sensore di livello dell'acqua Arduino: taratura, allarme, pompa

Sensore di livello dell'acqua con Arduino: taratura vuoto/metà/pieno, alimentazione da pin contro la corrosione, allarme con buzzer, pompa e codice ESP32/Pico.

Un sensore di livello dell'acqua è il modo più economico e semplice per capire con Arduino fin dove arriva l'acqua in un bicchiere, in un acquario, nel sottovaso di una pianta o in un piccolo serbatoio. Man mano che le piste conduttive scoperte della scheda finiscono sott'acqua, la tensione sulla sua uscita analogica sale; Arduino legge questa tensione con analogRead() e decide se il contenitore è «vuoto», «a metà» o «pieno». Si collega con tre fili, funziona con poche righe di codice ed è la base di molti progetti, dall'allarme di traboccamento al controllo automatico di una pompa.

In questa guida scoprirai cosa c'è dentro il modulo, perché la lettura non arriva mai a 1023, come fare la taratura vuoto/metà/pieno e come evitare la corrosione che consuma il sensore in poche settimane. Poi costruirai un allarme di traboccamento con buzzer e un controllo della pompa che riempie un serbatoio da solo, confronterai brevemente il sensore con un interruttore a galleggiante e con l'XKC-Y25 senza contatto e, infine, vedrai come fare lo stesso con l'ESP32 e il Raspberry Pi Pico.

Modulo sensore di livello dell'acqua per Arduino
Modulo sensore di livello dell'acqua: le piste conduttive intrecciate in basso vanno in acqua, i pin S, + e − in alto si collegano ad Arduino; l'elettronica deve restare sempre asciutta.

Che cos'è un sensore di livello dell'acqua e come funziona?

La parte inferiore del modulo ospita dieci piste conduttive che non si toccano e si incastrano come i denti di due pettini. Cinque sono piste di alimentazione collegate al +, le altre cinque sono piste di rilevamento che vanno alla base del transistor NPN S8050 sulla parte alta della scheda. Quando la scheda è asciutta tra le piste c'è solo aria, il transistor è spento e il pin S resta vicino a 0 V. Quando la scheda va in acqua, l'acqua fa da ponte tra le piste di alimentazione e quelle di rilevamento; una piccola corrente entra nella base, il transistor comincia a condurre e la tensione dell'uscita S, presa dall'emettitore, sale. Più l'acqua sale, più cresce la lunghezza di pista bagnata, più diminuisce la resistenza tra le piste e più aumenta la tensione di uscita.

Questo modo di funzionare ha tre conseguenze importanti. La prima è che il sensore non misura davvero l'acqua ma la sua conducibilità: i minerali disciolti nell'acqua del rubinetto alzano la lettura, mentre l'acqua pura (distillata) non dà quasi nulla. La seconda è che l'uscita proviene da un transistor in configurazione a inseguitore di emettitore, quindi la tensione non raggiunge mai quella di alimentazione; un sensore completamente bagnato e alimentato a 5 V di solito legge circa 500–650 su un Arduino Uno e non si avvicina mai a 1023. La terza è che la relazione non è lineare: il valore sale in fretta nei primi millimetri e poi sempre più lentamente. Per questo il sensore non è un righello con precisione al millimetro, ma un indicatore pratico che distingue in modo affidabile pochi livelli.

CaratteristicaValore
Tensione di funzionamento3,3–5 V DC
Corrente di funzionamentoMeno di 20 mA (massima quando è completamente bagnato)
UscitaTensione analogica (pin S), aumenta al salire dell'acqua
Area di rilevamentoCirca 40 × 16 mm, cioè al massimo circa 4 cm di altezza d'acqua
Dimensioni della schedaCirca 62 × 20 mm
Temperatura di funzionamento10–30 °C (dato del produttore)
PinS (segnale), + (VCC), − (GND)

Collegamento del sensore di livello dell'acqua: Arduino Uno, ESP32 e Pico

Pin del sensoreArduino UnoESP32Raspberry Pi Pico
S (segnale)A0GPIO 34 (ADC1)GP26 (ADC0)
+ (VCC)D7 (lo alimenta solo durante la misura)GPIO 25GP15
− (GND)GNDGNDGND
Non collegare il pin + del sensore ai 5V in modo permanente. Quando una corrente continua attraversa senza sosta le piste bagnate inizia l'elettrolisi: il rivestimento delle piste collegate al + si scioglie, le piste si anneriscono e in poche settimane le letture cominciano a spostarsi. Inoltre solo la parte bassa della scheda, quella con le piste conduttive, può andare in acqua; se si bagna la parte alta con il transistor, il LED e i pin, si crea un cortocircuito.

Il modo più semplice per evitare la corrosione è alimentare il sensore da un pin digitale, come vedi nella tabella: il codice porta il pin a HIGH subito prima della misura, attende 10 ms, legge il valore e riporta il pin a LOW. In un sistema che misura una volta al secondo le piste restano sotto tensione solo l'1 per cento del tempo, e l'usura rallenta di circa cento volte. Completamente bagnato, il modulo assorbe al massimo una ventina di mA. Il limite consigliato per un pin di Arduino Uno è 20 mA e quello assoluto 40 mA, e il pin resta acceso solo pochi millisecondi, quindi questo collegamento è sicuro; anche i pin dell'ESP32 forniscono questa corrente senza problemi. I pin del Pico, invece, lavorano di default con una corrente di uscita più bassa, perciò con il sensore completamente bagnato la tensione del pin cala un po' e le letture si riducono. Finché fai la taratura con lo stesso collegamento non è un problema; se vuoi valori più stabili puoi commutare il + del sensore con un piccolo transistor PNP come il BC557: l'emettitore va al pin 3V3 della scheda, il collettore al + del sensore e la base al pin GPIO tramite una resistenza da 1 kΩ; in questo caso il sensore si accende quando il pin è LOW. Per scegliere il transistor giusto dai un'occhiata allo strumento transistor.

Passo dopo passo: la prima lettura con Arduino

  1. Collega il pin S del sensore ad A0, il pin + a D7 e il pin − a GND. Tieni la scheda in verticale, con le piste rivolte verso il basso.
  2. Apri il codice qui sotto nell'Arduino IDE, scegli Arduino Uno come scheda e la porta corretta e caricalo.
  3. Apri il Monitor seriale e impostalo a 9600 baud. Verifica che con il sensore asciutto il valore sia vicino a 0.
  4. Immergi lentamente il sensore in un bicchiere d'acqua: prima solo la punta, poi fino a metà, poi fino alla linea dove finiscono le piste. A ogni passo attendi qualche secondo e annota il valore.
C++ (Arduino IDE)
1const int SENSOR_PIN = A0;   // S → A0
2const int POWER_PIN = 7;     // + → D7 (yalnızca ölçerken besle / power only while measuring)
3
4int readSensor() {
5  digitalWrite(POWER_PIN, HIGH);        // sensörü aç / power the sensor
6  delay(10);                            // değerin oturmasını bekle / let the reading settle
7  long sum = 0;
8  for (int i = 0; i < 8; i++) {         // 8 ölçümün ortalaması / average of 8 readings
9    sum += analogRead(SENSOR_PIN);
10  }
11  digitalWrite(POWER_PIN, LOW);         // sensörü kapat / power off
12  return sum / 8;
13}
14
15void setup() {
16  pinMode(POWER_PIN, OUTPUT);
17  digitalWrite(POWER_PIN, LOW);         // kapalı başla / start powered off
18  Serial.begin(9600);
19}
20
21void loop() {
22  int raw = readSensor();
23  Serial.print("Ham deger / Raw value: ");
24  Serial.println(raw);
25  delay(1000);                          // saniyede bir ölç / measure once a second
26}

La funzione readSensor() tiene acceso il sensore solo per circa 11 ms a ogni misura. L'attesa di 10 ms permette al transistor e all'acqua tra le piste di assestarsi su un valore stabile; poi la media di 8 letture smussa le piccole oscillazioni dei singoli campioni. Sull'Uno ogni analogRead() richiede circa 0,1 ms, quindi 8 letture durano meno di 1 ms. Se mescoli l'acqua o muovi il bicchiere vedrai i valori ballare nel Monitor seriale; è normale, perché la superficie in movimento cambia di continuo la lunghezza bagnata delle piste.

Vuoto, metà, pieno: come tarare il sensore

Non usare così come sono le soglie dei codici trovati online: ogni sensore, ogni tipo d'acqua e ogni tensione di alimentazione danno valori diversi. Esegui la taratura nel contenitore dove il sensore verrà davvero usato e con la stessa acqua: acqua dell'acquario per l'acquario, acqua con fertilizzante per un serbatoio di irrigazione fertilizzato. Traccia con un pennarello delle linee a 0, 10, 20, 30 e 40 mm sul sensore, immergi la scheda fino a ogni linea, aspetta 3–4 secondi che il valore si stabilizzi e annota il numero del Monitor seriale. La tabella mostra intervalli tipici per l'acqua del rubinetto e 5 V; scrivi accanto i tuoi valori.

LivelloProfondità di immersioneValore tipico su Uno (5 V, acqua del rubinetto)
Vuoto0 mm (asciutto)0–20
BassoCirca 5–10 mm250–400
MetàCirca 20 mm400–480
PienoCirca 40 mm (linea dove finiscono le piste)480–650

Ciò che salta all'occhio nella tabella è quanto rapidamente i valori salgono nel primo centimetro e quanto poi si comprimono: tra 0 e 10 mm ci possono essere alcune centinaia di unità di differenza, ma tra 20 e 40 mm solo qualche decina. Per questo, invece di tracciare un'unica retta con map(), l'interpolazione lineare a tratti, che usa un rapporto diverso tra ogni coppia di punti misurati, dà un risultato molto più preciso. Il codice seguente conserva i cinque punti che hai misurato in due array, converte il valore grezzo in millimetri e scrive il livello con il suo nome. Ti basta inserire le tue letture nell'array RAW in ordine crescente.

C++ (Arduino IDE)
1const int SENSOR_PIN = A0;
2const int POWER_PIN = 7;
3
4// Kendi kalibrasyon ölçümlerin / your own calibration readings
5const int N = 5;
6const int RAW[N] = {0, 330, 440, 490, 520};   // ham değer, küçükten büyüğe / raw value, ascending
7const int MM[N]  = {0, 10, 20, 30, 40};       // batma derinliği (mm) / immersion depth (mm)
8
9int readSensor() {
10  digitalWrite(POWER_PIN, HIGH);
11  delay(10);
12  long sum = 0;
13  for (int i = 0; i < 8; i++) sum += analogRead(SENSOR_PIN);
14  digitalWrite(POWER_PIN, LOW);
15  return sum / 8;
16}
17
18int rawToMm(int raw) {
19  if (raw <= RAW[0]) return MM[0];
20  for (int i = 1; i < N; i++) {
21    if (raw <= RAW[i]) {                      // iki nokta arasında oran kur / interpolate between two points
22      return map(raw, RAW[i - 1], RAW[i], MM[i - 1], MM[i]);
23    }
24  }
25  return MM[N - 1];                           // en üst noktanın üstü / above the top point
26}
27
28const char* levelName(int mm) {
29  if (mm < 3)  return "Bos / Empty";
30  if (mm < 15) return "Az / Low";
31  if (mm < 30) return "Yarim / Half";
32  return "Dolu / Full";
33}
34
35void setup() {
36  pinMode(POWER_PIN, OUTPUT);
37  digitalWrite(POWER_PIN, LOW);
38  Serial.begin(9600);
39}
40
41void loop() {
42  int raw = readSensor();
43  int mm = rawToMm(raw);
44  Serial.print(raw);
45  Serial.print(" -> ");
46  Serial.print(mm);
47  Serial.print(" mm, ");
48  Serial.println(levelName(mm));
49  delay(1000);
50}
Quando togli il sensore dall'acqua il valore non scende subito a 0: il sottile velo d'acqua e le gocce rimaste tra le piste tengono la lettura chiaramente sopra lo zero per un po'. Perciò tieni la soglia di «vuoto» un po' sopra lo 0 e, per decisioni di accensione e spegnimento come un allarme, usa due soglie distinte: una per attivare e una per disattivare. Questo metodo si chiama isteresi ed evita che un relè o un buzzer si accenda e si spenga ogni secondo mentre il livello oscilla proprio intorno alla soglia.

Allarme di traboccamento con buzzer

Uno dei compiti più utili di un sensore di livello dell'acqua è avvisarti di un traboccamento: messo sotto la lavatrice o la caldaia, in un sottovaso, nella vaschetta della condensa del condizionatore o sul bordo di un secchio che si sta riempiendo, il sensore fa partire l'allarme appena l'acqua ne tocca la punta. Per questo basta perfino il livello «basso» della tabella di taratura. Il codice qui sotto usa un buzzer attivo e il LED integrato dell'Uno; quando il valore supera ALARM_ON il buzzer suona ogni quarto di secondo, quando scende sotto ALARM_OFF tace. Poiché per i tempi si usa millis() invece di delay(), la misura e il buzzer non si bloccano a vicenda. Per i tipi di buzzer leggi Che cos'è un buzzer?, per il principio di millis() millis() e delay().

C++ (Arduino IDE)
1const int SENSOR_PIN = A0;   // S → A0
2const int POWER_PIN = 7;     // + → D7
3const int BUZZER_PIN = 8;    // aktif buzzer + ucu / active buzzer +
4const int LED_PIN = 13;      // Uno'nun dahili LED'i / Uno's built-in LED
5
6const int ALARM_ON = 200;    // bu değer ve üstü taşma / at or above: overflow (kendin ölç / measure yours)
7const int ALARM_OFF = 100;   // bunun altına inince alarm biter / alarm clears below this
8
9bool alarmActive = false;
10bool buzzerOn = false;
11unsigned long lastRead = 0;
12unsigned long lastBeep = 0;
13
14int readSensor() {
15  digitalWrite(POWER_PIN, HIGH);
16  delay(10);
17  long sum = 0;
18  for (int i = 0; i < 8; i++) sum += analogRead(SENSOR_PIN);
19  digitalWrite(POWER_PIN, LOW);
20  return sum / 8;
21}
22
23void setup() {
24  pinMode(POWER_PIN, OUTPUT);
25  pinMode(BUZZER_PIN, OUTPUT);
26  pinMode(LED_PIN, OUTPUT);
27  digitalWrite(POWER_PIN, LOW);
28  Serial.begin(9600);
29}
30
31void loop() {
32  unsigned long now = millis();
33
34  if (now - lastRead >= 1000) {                       // saniyede bir ölç / measure once a second
35    lastRead = now;
36    int level = readSensor();
37    if (!alarmActive && level >= ALARM_ON) alarmActive = true;    // taşma başladı / overflow started
38    if (alarmActive && level < ALARM_OFF) alarmActive = false;    // su çekildi / water receded
39    Serial.print("Seviye / Level: ");
40    Serial.println(level);
41  }
42
43  if (alarmActive) {
44    if (now - lastBeep >= 250) {                      // 250 ms öt, 250 ms sus / 250 ms on, 250 ms off
45      lastBeep = now;
46      buzzerOn = !buzzerOn;
47      digitalWrite(BUZZER_PIN, buzzerOn ? HIGH : LOW);
48    }
49  } else if (buzzerOn) {
50    buzzerOn = false;
51    digitalWrite(BUZZER_PIN, LOW);
52  }
53  digitalWrite(LED_PIN, alarmActive ? HIGH : LOW);
54}

Controllo della pompa: riempire un serbatoio da solo

La seconda applicazione classica è il rabbocco automatico che mantiene il livello entro una fascia. Magari vuoi reintegrare l'acqua che evapora da un acquario prendendola da un secchio di riserva, tenere pieno l'abbeveratoio del tuo animale o alimentare il serbatoio di una serra. La logica è semplice: quando il livello scende sotto START_BELOW la pompa parte, quando raggiunge STOP_ABOVE si ferma. Lo spazio tra queste due soglie è l'isteresi che impedisce alla pompa di accendersi e spegnersi di continuo. Ricorda che il sensore ha un'area di rilevamento di soli 4 cm circa; fissa la scheda a un'altezza in cui la fascia d'acqua che vuoi mantenere cada all'interno di quei 4 cm.

Mini pompa ad immersione da 6 V
Mini pompa ad immersione 3–6 V: funziona sott'acqua e assorbe circa 100–250 mA, quindi si comanda tramite un relè o un MOSFET, non direttamente da un pin di Arduino.

La pompa assorbe molta più corrente di quella che un pin di Arduino può fornire: comandala quindi con un modulo relè oppure con un MOSFET a livello logico e un diodo di ricircolo, alimentala con una fonte separata e collega insieme le GND delle due alimentazioni. Trovi i dettagli in Che cos'è un modulo relè?, come usare un MOSFET e la mini pompa per acqua. La parte più importante del codice è una misura di sicurezza: se la pompa funziona per tutto il tempo MAX_RUN_MS e il livello non raggiunge ancora l'obiettivo, il sistema blocca la pompa e ti avvisa con brevi bip. Forse il tubo si è sfilato, il secchio di riserva è vuoto o il sensore si è spostato; senza questo blocco la pompa potrebbe girare a secco per ore o allagare tutto.

C++ (Arduino IDE)
1const int SENSOR_PIN = A0;
2const int POWER_PIN = 7;
3const int PUMP_PIN = 8;                 // röle IN / relay IN
4const int BUZZER_PIN = 9;               // aktif buzzer / active buzzer
5const bool RELAY_ACTIVE_LOW = true;     // çoğu röle modülü LOW ile çeker / most relay modules switch on LOW
6
7const int START_BELOW = 300;            // bunun altında doldur / start filling below this (kendin ölç / measure yours)
8const int STOP_ABOVE = 480;             // bu değerde dur / stop at this value
9const unsigned long MAX_RUN_MS = 30000; // en uzun çalışma 30 sn / max run time 30 s
10
11bool pumpOn = false;
12bool fault = false;
13unsigned long pumpStart = 0;
14
15int readSensor() {
16  digitalWrite(POWER_PIN, HIGH);
17  delay(10);
18  long sum = 0;
19  for (int i = 0; i < 8; i++) sum += analogRead(SENSOR_PIN);
20  digitalWrite(POWER_PIN, LOW);
21  return sum / 8;
22}
23
24void setPump(bool on) {
25  pumpOn = on;
26  bool pinHigh = RELAY_ACTIVE_LOW ? !on : on;
27  digitalWrite(PUMP_PIN, pinHigh ? HIGH : LOW);
28}
29
30void setup() {
31  setPump(false);              // pin çıkış olmadan önce kapalı konuma al / set off before the pin becomes an output
32  pinMode(PUMP_PIN, OUTPUT);
33  pinMode(POWER_PIN, OUTPUT);
34  pinMode(BUZZER_PIN, OUTPUT);
35  digitalWrite(POWER_PIN, LOW);
36  Serial.begin(9600);
37}
38
39void loop() {
40  if (fault) {                 // arıza: pompa kilitli, kesik kesik öt / fault: pump locked out, beep
41    digitalWrite(BUZZER_PIN, HIGH);
42    delay(200);
43    digitalWrite(BUZZER_PIN, LOW);
44    delay(1800);
45    return;                    // yeniden başlatmak için reset / press reset to restart
46  }
47
48  int level = readSensor();
49
50  if (!pumpOn && level < START_BELOW) {
51    setPump(true);             // seviye düştü, doldur / level low, start filling
52    pumpStart = millis();
53  } else if (pumpOn && level >= STOP_ABOVE) {
54    setPump(false);            // istenen seviyeye ulaşıldı / target level reached
55  } else if (pumpOn && millis() - pumpStart > MAX_RUN_MS) {
56    setPump(false);            // süre doldu, seviye yükselmedi / timed out, level did not rise
57    fault = true;
58  }
59
60  Serial.print("Seviye / Level: ");
61  Serial.print(level);
62  Serial.println(pumpOn ? "  pompa / pump ON" : "  pompa / pump OFF");
63  delay(500);
64}
Acqua ed elettricità nello stesso progetto: posiziona Arduino, relè e alimentatore sopra e lontano dai contenitori d'acqua e isola le giunzioni con guaina termorestringente o colla a caldo. Se userai una pompa o un'elettrovalvola a 230 V, fai eseguire il collegamento alla rete da una persona qualificata e lavora su un circuito protetto da un interruttore differenziale (salvavita). Le piccole pompe ad immersione si surriscaldano e si guastano in fretta se girano a secco; mettere anche un interruttore a galleggiante nel secchio di riserva è un buon secondo livello di sicurezza.

Sensore di livello dell'acqua, interruttore a galleggiante e XKC-Y25 a confronto

CaratteristicaSensore di livello dell'acqua (piste conduttive)Interruttore a galleggianteXKC-Y25 (senza contatto)
Principio di rilevamentoConducibilità dell'acquaMagnete galleggiante e contatto reedVariazione di capacità dietro la parete del contenitore
UscitaAnalogica (pochi livelli)Contatto aperto o chiusoDigitale (liquido presente o no)
Campo di misuraCirca 0–4 cmUn punto (altezza di montaggio)Un punto (altezza di montaggio)
Contatto con l'acquaSì, piste in acquaSì, corpo in acquaNo, si incolla all'esterno del contenitore
CorrosioneSì; alimentarlo da un pin è indispensabilePraticamente nessunaNessuna
Alimentazione3,3–5 VNon serve (contatto passivo)5–24 V, circa 5 mA
Ideale perEsperimenti, allarmi di traboccamento, piccoli contenitoriSerbatoi fissi, protezione della pompaSerbatoi chiusi in plastica o vetro, liquidi corrosivi
PrezzoIl più economicoEconomicoPiù caro degli altri

Un interruttore a galleggiante è formato da uno stelo con un contatto reed all'interno e da un galleggiante con magnete che scorre lungo di esso. Quando l'acqua sale, il galleggiante si solleva, il magnete arriva all'altezza del contatto reed e il contatto si chiude o si apre. Montando il galleggiante capovolto sullo stelo puoi passare da normalmente aperto (NO) a normalmente chiuso (NC). Per collegarlo ad Arduino basta portare un filo a un pin digitale e l'altro a GND e impostare il pin come INPUT_PULLUP; non soffrendo dell'usura da elettrolisi, dura molto di più nelle installazioni fisse. I contatti dei modelli piccoli sono in genere limitati a circa 0,5 A e 10 W, quindi comanda la pompa tramite un relè e non direttamente. Per capire come funziona un contatto reed leggi l'articolo Interruttore reed.

Interruttore a galleggiante come sensore di livello dell'acqua
Interruttore a galleggiante: il galleggiante magnetico sale con l'acqua e apre o chiude il contatto reed nello stelo.
C++ (Arduino IDE)
1const int FLOAT_PIN = 2;    // bir kablo D2'ye, diğeri GND'ye / one wire to D2, the other to GND
2
3void setup() {
4  pinMode(FLOAT_PIN, INPUT_PULLUP);   // dahili pull-up direnci / internal pull-up resistor
5  Serial.begin(9600);
6}
7
8void loop() {
9  // Kontak kapalıyken pin LOW okunur / the pin reads LOW when the contact is closed
10  if (digitalRead(FLOAT_PIN) == LOW) {
11    Serial.println("Kontak kapali / Contact closed");
12  } else {
13    Serial.println("Kontak acik / Contact open");
14  }
15  delay(500);
16}

L'XKC-Y25, invece, è un sensore capacitivo che non tocca mai l'acqua: si incolla all'esterno di un serbatoio di plastica o di vetro e rileva se dietro la parete c'è del liquido. Secondo il produttore funziona a 5–24 V, assorbe circa 5 mA, rileva attraverso pareti non metalliche spesse fino a 13 mm e risponde in circa 500 ms. Il livello alto della sua uscita è pari alla tensione di alimentazione, quindi se colleghi a un ESP32 o a un Pico un XKC-Y25 alimentato a 5 V devi usare un partitore di tensione (lo strumento partitore di tensione calcola le resistenze giuste). Spieghiamo in dettaglio la regolazione della sensibilità e i modelli con uscite diverse nell'articolo sensore di livello senza contatto XKC-Y25.

Sensore di livello liquidi senza contatto XKC-Y25
XKC-Y25: sensore capacitivo incollato all'esterno del serbatoio; non toccando mai l'acqua, non si corrode.

Controllare il livello dell'acqua dal telefono con l'ESP32

Con l'ESP32 puoi portare la misura sul telefono tramite Wi-Fi. Collega sempre il pin S del sensore a un pin dell'ADC1 (GPIO 32–39); i pin dell'ADC2 non si possono leggere con il Wi-Fi attivo. L'ADC dell'ESP32 è a 12 bit, quindi i valori vanno da 0 a 4095, e poiché il sensore è alimentato a 3,3 V i numeri non sono confrontabili con quelli dell'Uno: dovrai ripetere la taratura. L'ADC dell'ESP32 non è del tutto lineare vicino a 0 V e vicino al fondo scala, ma dato che qui conta la differenza tra i livelli e non la tensione assoluta, non è un problema. Il codice seguente misura ogni due secondi e offre una piccola pagina web che si aggiorna da sola ogni cinque secondi e che puoi aprire dal telefono sulla stessa rete.

C++ (Arduino IDE)
1#include <WiFi.h>
2#include <WebServer.h>
3
4const char* WIFI_SSID = "WIFI_ADIN";      // ağ adın / your network name
5const char* WIFI_PASS = "WIFI_SIFREN";    // ağ şifren / your network password
6
7const int SENSOR_PIN = 34;   // S → GPIO 34 (ADC1, Wi-Fi ile çalışır / works with Wi-Fi)
8const int POWER_PIN = 25;    // + → GPIO 25
9const int HALF = 1500;       // yarım eşiği / half threshold (kendin ölç / measure yours)
10const int FULL = 2000;       // dolu eşiği / full threshold (kendin ölç / measure yours)
11
12WebServer server(80);
13int lastRaw = 0;
14unsigned long lastRead = 0;
15
16int readSensor() {
17  digitalWrite(POWER_PIN, HIGH);
18  delay(10);
19  long sum = 0;
20  for (int i = 0; i < 16; i++) sum += analogRead(SENSOR_PIN);   // 0–4095
21  digitalWrite(POWER_PIN, LOW);
22  return sum / 16;
23}
24
25const char* levelName(int raw) {
26  if (raw < 100) return "Bos / Empty";
27  if (raw < HALF) return "Az / Low";
28  if (raw < FULL) return "Yarim / Half";
29  return "Dolu / Full";
30}
31
32void handleRoot() {
33  String html = "<!DOCTYPE html><html><head><meta charset='utf-8'>"
34                "<meta name='viewport' content='width=device-width'>"
35                "<meta http-equiv='refresh' content='5'></head><body>"
36                "<h1>Su seviyesi / Water level</h1><h2>";
37  html += levelName(lastRaw);
38  html += "</h2><p>Ham deger / Raw: ";
39  html += lastRaw;
40  html += "</p></body></html>";
41  server.send(200, "text/html", html);
42}
43
44void setup() {
45  Serial.begin(115200);
46  pinMode(POWER_PIN, OUTPUT);
47  digitalWrite(POWER_PIN, LOW);
48  WiFi.begin(WIFI_SSID, WIFI_PASS);
49  while (WiFi.status() != WL_CONNECTED) {   // bağlanana kadar bekle / wait until connected
50    delay(500);
51    Serial.print(".");
52  }
53  Serial.println();
54  Serial.print("Adres / Address: http://");
55  Serial.println(WiFi.localIP());
56  server.on("/", handleRoot);
57  server.begin();
58}
59
60void loop() {
61  server.handleClient();
62  if (millis() - lastRead >= 2000) {        // 2 sn'de bir ölç / measure every 2 s
63    lastRead = millis();
64    lastRaw = readSensor();
65  }
66}

Prima di caricare il codice sostituisci WIFI_SSID e WIFI_PASS con i dati della tua rete; l'ESP32 si collega solo a reti a 2,4 GHz. Aprendo il Monitor seriale a 115200 baud, ti basta digitare l'indirizzo che compare nel browser del telefono. Se vuoi ricevere una notifica sul telefono quando il livello è «pieno», puoi trasformare la stessa lettura in un messaggio con il metodo dell'articolo bot Telegram con ESP32.

Allarme di traboccamento con Raspberry Pi Pico e MicroPython

Sul Raspberry Pi Pico per le letture analogiche si usano i pin GP26, GP27 e GP28. La funzione read_u16() di MicroPython riporta la misura a 12 bit del Pico nell'intervallo 0–65535, quindi le tue soglie saranno numeri molto più grandi che sull'Uno. Il codice qui sotto alimenta il sensore da GP15, legge l'uscita S su GP26 e segnala il traboccamento con tre brevi bip di un buzzer attivo collegato a GP14. Come nel primo sketch, fissa le soglie in base alle tue misure.

MicroPython
1from machine import ADC, Pin
2import time
3
4sensor = ADC(26)                    # GP26 (ADC0) → S
5power = Pin(15, Pin.OUT, value=0)   # GP15 → sensör + / sensor +
6buzzer = Pin(14, Pin.OUT, value=0)  # GP14 → aktif buzzer / active buzzer
7
8ALARM_ON = 20000    # bu değer ve üstü taşma / at or above: overflow (kendin ölç / measure yours)
9ALARM_OFF = 10000   # bunun altında alarm biter / alarm clears below this
10
11def read_level(samples=8):
12    power.value(1)
13    time.sleep_ms(10)               # değerin oturmasını bekle / let the reading settle
14    total = 0
15    for _ in range(samples):
16        total += sensor.read_u16()  # 0–65535
17    power.value(0)
18    return total // samples
19
20alarm = False
21while True:
22    level = read_level()
23    if not alarm and level >= ALARM_ON:
24        alarm = True
25    elif alarm and level < ALARM_OFF:
26        alarm = False
27    print("Seviye / Level:", level, "ALARM" if alarm else "")
28    if alarm:
29        for _ in range(3):          # üç kısa bip / three short beeps
30            buzzer.value(1)
31            time.sleep_ms(150)
32            buzzer.value(0)
33            time.sleep_ms(150)
34    else:
35        time.sleep(1)

Idee di progetto con un sensore di livello dell'acqua

  • Avviso di traboccamento del sottovaso: Un buzzer che suona quando dopo l'irrigazione si accumula acqua nel sottovaso; abbinato a un sensore di umidità del terreno diventa un impianto di irrigazione completo.
  • Rabbocco automatico dell'acquario: Un sistema di riempimento a tempo limitato che reintegra con una mini pompa l'acqua evaporata prendendola da un secchio di riserva.
  • Ciotola dell'acqua per animali: Un promemoria che accende un LED o invia una notifica al telefono tramite l'ESP32 quando l'acqua sta finendo.
  • Rilevatore di allagamento: Un allarme perdite con il sensore appoggiato in orizzontale sul pavimento sotto la lavatrice, vicino alla caldaia o in cantina.
  • Serbatoio intelligente per la serra: Una protezione che controlla il livello del serbatoio di irrigazione e blocca la pompa quando si svuota; si aggiunge facilmente al progetto di serra intelligente.
  • Indicatore per il bidone dell'acqua piovana: Un pannello che mostra il livello come vuoto, metà o pieno su un display LCD I2C; puoi aggiungere anche un sensore di pioggia per capire quando inizia a piovere.

Errori comuni e soluzioni

SintomoCausa probabileSoluzione
Il valore è sempre 0, anche in acquaIl pin + non è alimentato (POWER_PIN non va mai a HIGH) oppure S è sul pin sbagliatoControlla le righe con pinMode e digitalWrite e che S sia su un pin analogico
Il valore salta a caso anche da asciuttoIl pin S è scollegato oppure manca la GNDControlla tutti e tre i fili; la GND deve essere in comune
Non arriva mai a 1023, nemmeno del tutto immersoÈ normale; l'uscita viene da un inseguitore di emettitoreImposta le soglie in base al valore più alto che hai misurato tu
Nell'acqua pura non si legge nullaL'acqua distillata o depurata conduce pochissimoCon quest'acqua usa un XKC-Y25 o un interruttore a galleggiante
I valori calano o si spostano nel giro di qualche settimanaElettrolisi e depositi sulle pisteAlimenta il sensore da un pin, pulisci le piste con uno spazzolino morbido e, se serve, sostituisci il sensore
Pompa o buzzer si accendono e spengono di continuo sulla sogliaC'è una sola soglia; la superficie in movimento fa oscillare il valoreUsa due soglie distinte per accensione e spegnimento (isteresi) e fai la media delle letture
Sull'ESP32 il valore non si legge più quando si collega il Wi-FiIl sensore è su un pin dell'ADC2Sposta S su un pin dell'ADC1 tra GPIO 32 e 39
Per allungare la vita del sensore mettilo in verticale nell'acqua, immergi solo la parte con le piste e copri l'elettronica in alto con colla a caldo o vernice trasparente; non ricoprire però le piste, altrimenti non potranno più misurare la conducibilità. In un'installazione fissa che resterà in acqua per mesi, la soluzione più robusta è usare questo sensore per il prototipo e passare, nel sistema definitivo, a un interruttore a galleggiante o a un sensore senza contatto.

Il sensore di livello dell'acqua insegna letture analogiche, taratura, isteresi e problemi reali come la corrosione con un solo modulo economico. Se devi misurare centimetro per centimetro il livello di un grande serbatoio, puoi passare a una soluzione a ultrasuoni come il sensore di distanza HC-SR04. Nell'app BlueGrays trovi la stazione di irrigazione intelligente e progetti di allarme con buzzer, con schemi e codice passo dopo passo, e puoi aggiungervi facilmente il sensore di livello dell'acqua.

Domande frequenti

Come funziona un sensore di livello dell'acqua?

Quando le piste conduttive intrecciate della scheda finiscono in acqua, l'acqua le collega e una corrente scorre verso la base del transistor S8050 del modulo. Più il transistor conduce, più sale la tensione sul pin S; Arduino legge questa tensione con analogRead() per capire fin dove arriva l'acqua.

Perché il mio sensore di livello dell'acqua si corrode?

Quando una corrente continua attraversa senza sosta le piste bagnate inizia l'elettrolisi e il rivestimento delle piste collegate al + si scioglie. Se alimenti il sensore da un pin digitale invece che dai 5V e lo accendi solo per pochi millisecondi a ogni lettura, l'usura rallenta moltissimo e il sensore dura mesi.

Il sensore di livello dell'acqua funziona con l'acqua distillata?

Quasi per niente. Poiché il sensore misura la conducibilità dell'acqua, l'acqua distillata o depurata, priva di minerali disciolti, dà letture molto basse. Per quest'acqua è meglio scegliere sensori che non dipendono dalla conducibilità, come l'XKC-Y25 senza contatto o un interruttore a galleggiante.

Perché il sensore di livello dell'acqua non arriva a 1023?

L'uscita S è presa dall'emettitore del transistor, quindi la tensione resta sotto quella di alimentazione, e la corrente di base è limitata dalla resistenza dell'acqua. Su un Arduino Uno a 5 V un sensore completamente bagnato di solito legge circa 500–650; imposta le soglie partendo da questo massimo.

Si può immergere completamente un sensore di livello dell'acqua?

No. Solo la parte bassa con le piste conduttive deve andare in acqua; se si bagna la parte alta con il transistor, il LED e i pin, si crea un cortocircuito e il sensore legge male o si guasta. Proteggere l'elettronica con colla a caldo o vernice ne allunga la vita.

Come si misura il livello di un grande serbatoio d'acqua?

Questo sensore copre solo circa 4 cm, quindi non è adatto ai grandi serbatoi. Per misurare il livello in modo continuo si usano sensori a ultrasuoni impermeabili come il JSN-SR04T montati sul coperchio del serbatoio; per controllare solo alcuni punti critici si mettono interruttori a galleggiante a diverse altezze.

Vedi tutti i progetti
Uso del cicalino
#13Principiante

Uso del cicalino

Ti sei mai chiesto come fa un campanello o un allarme a suonare? L'Arduino fa suonare un piccolo cicalino a intervalli brevi: bip, pausa, bip, pausa. Vedi come l'elettricità diventa suono e fai il pri

4.7(89)
161
Misurare l'intensità luminosa con LDR
#11Principiante

Misurare l'intensità luminosa con LDR

Vuoi vedere quanto è luminosa la tua stanza sotto forma di numero? L'LDR, un piccolo componente sensibile alla luce, misura la luce ambiente e l'Arduino scrive il valore sullo schermo del computer ogn

4.6(81)
139
Lettura dell'intensità luminosa con il modulo LDR ESP32
#113Principiante

Lettura dell'intensità luminosa con il modulo LDR ESP32

Monitoraggio in tempo reale sul Serial Monitor del valore grezzo dell'ADC del modulo LDR e della percentuale relativa di luce calcolata dai valori di riferimento al buio e alla luce. Questa percentuale non è una misurazione in lux. Spiega il principio di calibrazione del modulo. È consigliabile eseguirlo prima del Progetto 10, poiché serve a determinare il valore di soglia.

4.6(36)
55
Stazione di irrigazione intelligente
#83Avanzato
Premium

Stazione di irrigazione intelligente

Un giardiniere che annaffia le tue piante da solo, così non si seccano mentre sei in vacanza. Un sensore di umidità misura quanto è bagnata la terra; quando diventa secca, l'Arduino accende la pompa d

5.0(42)
57
Lettura di un sensore reed
#37Principiante

Lettura di un sensore reed

Ti sei mai chiesto come funziona l'interruttore magnetico degli allarmi per porte e finestre? Quando una calamita si avvicina al modulo relè reed, il minuscolo interruttore al suo interno si chiude; l

4.4(21)
27
Server web asincrono ESP32 (con indicazione dell'IP sul display LCD)
#129Avanzato

Server web asincrono ESP32 (con indicazione dell'IP sul display LCD)

In questo progetto trasformiamo l'ESP32 in un server web asincrono che potrete controllare dal vostro telefono o computer collegato alla stessa rete Wi-Fi. Grazie alla libreria ESPAsyncWebServer, il server è in grado di elaborare più richieste contemporaneamente (a differenza del classico WebServer.h, che si blocca su una singola richiesta).

4.8(16)
26
Sistema di Allarme Movimento ESP32 (PIR + Buzzer + LED + Telegram)
#145Avanzato
Premium

Sistema di Allarme Movimento ESP32 (PIR + Buzzer + LED + Telegram)

Un sistema di allarme di sicurezza intelligente che attiva buzzer e LED quando il sensore PIR rileva movimento, inviando contemporaneamente una notifica istantanea al proprietario tramite Telegram. Dispone di un tempo di attesa di 30 secondi per limitare la frequenza degli allarmi ripetuti; questo meccanismo non verifica la validità dei rilevamenti del sensore PIR né elimina le false attivazioni. Adatto a sicurezza domestica, monitoraggio di garage, magazzini o studi. Con l'ESP32-CAM è possibile

0.0(0)
9