Componentes · 14 min de leitura

Sensor de nível de água com Arduino: calibração, alarme de transbordamento e bomba

Como usar um sensor de nível de água com Arduino: calibração vazio/metade/cheio, alimentação pelo pino contra corrosão, alarme de transbordamento com buzzer, controle de bomba, código para ESP32/Pico.

Um sensor de nível de água é o jeito mais barato e fácil de detectar com um Arduino a altura da água em um copo, um aquário, um pratinho de vaso ou um pequeno reservatório. À medida que as trilhas condutoras expostas da placa ficam embaixo d’água, a tensão na saída analógica sobe; o Arduino lê essa tensão com analogRead() e decide se a água está “vazio”, “metade” ou “cheio”. Ele se liga com três fios, funciona com poucas linhas de código e é o ponto de partida de muitos projetos, de alarmes de transbordamento a controle automático de bomba.

Neste guia você vai aprender o que há dentro do módulo, por que a leitura nunca chega a 1023, como fazer uma calibração vazio/metade/cheio e como evitar a corrosão que come o sensor em poucas semanas. Depois você vai montar um alarme de transbordamento com buzzer e um controle de bomba que enche um reservatório sozinho, comparar rapidamente o sensor com uma chave boia e com o XKC-Y25 sem contato e, por fim, ver como fazer o mesmo trabalho com o ESP32 e o Raspberry Pi Pico.

Módulo sensor de nível de água para Arduino
Módulo sensor de nível de água: as trilhas condutoras intercaladas na parte de baixo vão na água, enquanto os pinos S, + e − no topo se ligam ao Arduino; a eletrônica deve ficar sempre seca.

O que é um sensor de nível de água e como ele funciona?

A parte de baixo do módulo tem dez trilhas condutoras que não se tocam e se encaixam como os dentes de dois pentes. Cinco delas são trilhas de alimentação ligadas ao + da fonte; as outras cinco são trilhas de detecção que vão até a base do transistor NPN S8050 no topo da placa. Quando a placa está seca, só há ar entre as trilhas, o transistor fica cortado e o pino S fica perto de 0 V. Quando a placa entra na água, a água faz a ponte entre as trilhas de alimentação e as de detecção; uma pequena corrente entra na base do transistor, ele começa a conduzir e a tensão na saída S, tirada do emissor, sobe. Quanto mais alta a água, maior o comprimento molhado das trilhas, menor a resistência entre elas e maior a tensão de saída.

Esse jeito de funcionar tem três consequências importantes. Primeiro, o sensor na verdade não mede a água, e sim a condutividade da água: os minerais dissolvidos na água da torneira aumentam a leitura, enquanto a água pura (destilada) quase não dá nada. Segundo, como a saída vem de um transistor funcionando como seguidor de emissor, a tensão nunca chega à da alimentação; um sensor totalmente molhado alimentado com 5 V costuma ler em torno de 500–650 em um Arduino Uno e nunca chega perto de 1023. Terceiro, a relação não é linear: o valor sobe rápido nos primeiros milímetros e depois vai desacelerando cada vez mais. Por isso este sensor não é uma régua com precisão de milímetros, e sim um indicador prático que distingue com confiança alguns níveis.

CaracterísticaValor
Tensão de operação3,3–5 V DC
Corrente de operaçãoMenos de 20 mA (máxima quando totalmente molhado)
SaídaTensão analógica (pino S), sobe quando a água sobe
Área de detecçãoCerca de 40 × 16 mm, ou seja, no máximo uns 4 cm de altura de água
Tamanho da placaCerca de 62 × 20 mm
Temperatura de operação10–30 °C (valor do fabricante)
PinosS (sinal), + (VCC), − (GND)

Ligação do sensor de nível de água: Arduino Uno, ESP32 e Pico

Pino do sensorArduino UnoESP32Raspberry Pi Pico
S (sinal)A0GPIO 34 (ADC1)GP26 (ADC0)
+ (VCC)D7 (alimenta só durante a medição)GPIO 25GP15
− (GND)GNDGNDGND
Não ligue o pino + do sensor permanentemente no 5V. Quando uma corrente contínua passa o tempo todo pelas trilhas molhadas, começa a eletrólise: o revestimento das trilhas ligadas ao + se dissolve, as trilhas escurecem e, em poucas semanas, as leituras começam a variar. Além disso, só a parte de baixo da placa, com as trilhas condutoras, pode ir na água; se a parte de cima, com o transistor, o LED e os pinos, molhar, você tem um curto-circuito.

O jeito mais fácil de evitar a corrosão é alimentar o sensor por um pino digital, como mostra a tabela: o código coloca o pino em HIGH logo antes da medição, espera 10 ms, lê o valor e coloca o pino em LOW de novo. Em um sistema que mede uma vez por segundo, as trilhas ficam energizadas só 1 por cento do tempo, o que desacelera o desgaste em cerca de cem vezes. Totalmente molhado, o módulo puxa no máximo uns 20 mA. O limite recomendado para um pino do Arduino Uno é 20 mA e o máximo absoluto é 40 mA, e o pino fica ligado só por alguns milissegundos, então essa ligação é segura; os pinos do ESP32 também fornecem essa corrente com folga. Já os pinos do Pico funcionam com uma configuração padrão de capacidade de corrente mais baixa, então, quando o sensor está totalmente molhado, a tensão do pino cai um pouco e as leituras ficam menores. Desde que você calibre com a mesma ligação, isso não é problema; se quiser valores mais estáveis, pode chavear o + do sensor com um pequeno transistor PNP como o BC557: o emissor vai no pino 3V3 da placa, o coletor no + do sensor e a base no pino GPIO por um resistor de 1 kΩ, e o sensor liga quando o pino está em LOW. Para escolher um transistor adequado, dê uma olhada na ferramenta de transistores.

Passo a passo: a sua primeira leitura com Arduino

  1. Ligue o pino S do sensor ao A0, o pino + ao D7 e o pino − ao GND. Segure a placa em pé, com as trilhas para baixo.
  2. Abra o código abaixo na Arduino IDE, selecione Arduino Uno como placa, escolha a porta certa e faça o upload.
  3. Abra o Monitor Serial e ajuste para 9600 baud. Confira se o valor fica perto de 0 com o sensor seco.
  4. Mergulhe o sensor devagar em um copo d’água: primeiro só a ponta, depois até a metade e depois até a linha onde as trilhas terminam. Em cada passo, espere alguns segundos e anote o valor.
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}

A função readSensor() mantém o sensor ligado só por cerca de 11 ms por medição. A espera de 10 ms deixa o transistor e a água entre as trilhas se estabilizarem em um valor estável; depois, a média de 8 leituras suaviza as pequenas oscilações de cada amostra. No Uno, cada analogRead() leva cerca de 0,1 ms, então 8 leituras levam menos de 1 ms. Quando você mexe a água ou balança o copo, os valores pulam no Monitor Serial; isso é normal, porque a superfície em movimento muda o tempo todo o comprimento molhado das trilhas.

Vazio, metade, cheio: como calibrar

Não use do jeito que estão os limites de códigos que você encontra na internet; cada sensor, cada tipo de água e cada tensão de alimentação dá valores diferentes. Calibre no recipiente em que o sensor vai ser usado de verdade e com a mesma água: água do aquário para um aquário, água com adubo para um reservatório de irrigação com adubo. Marque linhas em 0, 10, 20, 30 e 40 mm no sensor com uma caneta, mergulhe a placa até cada linha, espere 3–4 segundos para o valor se estabilizar e anote o número do Monitor Serial. A tabela abaixo mostra faixas típicas para água da torneira e alimentação de 5 V; anote os seus valores ao lado.

NívelProfundidade de imersãoValor típico no Uno (5 V, água da torneira)
Vazio0 mm (seco)0–20
BaixoCerca de 5–10 mm250–400
MetadeCerca de 20 mm400–480
CheioCerca de 40 mm (linha onde as trilhas terminam)480–650

O que chama atenção na tabela é como os valores sobem rápido no primeiro centímetro e depois se amontoam: pode haver uma diferença de várias centenas de unidades entre 0 e 10 mm, mas só algumas dezenas entre 20 e 40 mm. Por isso, em vez de traçar uma única reta com map(), a interpolação linear por partes, que usa uma razão separada entre cada par de pontos medidos, dá um resultado bem mais preciso. O código abaixo guarda em dois arrays os cinco pontos que você mediu, converte o valor bruto em milímetros e mostra o nome do nível. Você só precisa escrever as suas leituras no array RAW, em ordem 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 você tira o sensor da água, o valor não cai para 0 na hora; a película fina de água e as gotas que ficam entre as trilhas mantêm a leitura bem acima de zero por um tempo. Então deixe o limite de “vazio” um pouco acima de 0 e, para decisões de ligar/desligar como um alarme, use dois limites separados: um para ligar e outro para desligar. Esse método se chama histerese e impede que um relé ou um buzzer fique ligando e desligando a cada segundo enquanto o nível oscila bem em cima do limite.

Alarme de transbordamento com buzzer

Um dos usos mais úteis de um sensor de nível de água é avisar de um transbordamento: colocado embaixo da máquina de lavar ou do aquecedor, em um pratinho de vaso, na bandeja de dreno do ar-condicionado ou na borda de um balde que está enchendo, o sensor dispara o alarme assim que a água toca a ponta dele. Até o nível “baixo” da tabela de calibração basta para isso. O código abaixo usa um buzzer ativo e o LED integrado do Uno; quando o valor passa de ALARM_ON, o buzzer apita a cada quarto de segundo e, quando o valor cai abaixo de ALARM_OFF, ele se cala. Como usa millis() em vez de delay() para a temporização, a medição e o buzzer não travam um ao outro. Para os tipos de buzzer, veja O que é um buzzer? e, para a ideia do millis(), veja 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}

Controle de bomba: enchendo um reservatório sozinho

A segunda aplicação clássica é o reabastecimento automático que mantém o nível dentro de uma faixa. Você pode querer repor a água que evapora de um aquário a partir de um balde reserva, manter cheio o pote de água do seu pet ou abastecer o reservatório de uma estufa. A lógica é simples: quando o nível cai abaixo de START_BELOW, a bomba liga e, quando chega a STOP_ABOVE, ela para. A distância entre esses dois limites é a histerese que impede a bomba de ficar ligando e desligando sem parar. Lembre que o sensor tem uma área de detecção de só cerca de 4 cm; monte a placa em uma altura em que a faixa de água que você quer manter fique dentro desses 4 cm.

Minibomba de água submersível de 6 V
Minibomba submersível de 3–6 V: funciona embaixo d’água e puxa cerca de 100–250 mA, por isso é acionada por um relé ou um MOSFET, e não direto por um pino do Arduino.

A bomba puxa muito mais corrente do que um pino do Arduino consegue fornecer, então acione-a com um módulo relé ou com um MOSFET de nível lógico e um diodo de roda livre, alimente a bomba com uma fonte separada e ligue juntos os GNDs das duas fontes. Para os detalhes, veja O que é um módulo relé?, como usar um MOSFET e a minibomba de água. A parte mais importante do código é uma medida de segurança: se a bomba funcionar durante todo o período MAX_RUN_MS e o nível ainda não tiver chegado ao alvo, o sistema bloqueia a bomba e avisa você com bipes curtos. A mangueira pode ter escapado, o balde reserva pode estar vazio ou o sensor pode ter saído do lugar; sem esse bloqueio, a bomba poderia funcionar a seco por horas ou alagar tudo.

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}
Água e eletricidade no mesmo projeto: coloque o Arduino, o relé e a fonte acima e longe dos recipientes de água e isole as emendas dos fios com espaguete termorretrátil ou cola quente. Se for usar uma bomba ou uma válvula solenoide que funciona na tensão da rede elétrica, peça a um profissional qualificado que faça a ligação na rede e trabalhe em um circuito protegido por um dispositivo DR (diferencial residual). Minibombas submersíveis esquentam e queimam rápido se funcionarem a seco; colocar também uma chave boia no balde reserva é uma boa segunda camada de proteção.

Sensor de nível de água vs. chave boia vs. XKC-Y25

CaracterísticaSensor de nível de água (trilhas condutoras)Chave boiaXKC-Y25 (sem contato)
Método de detecçãoCondutividade da águaÍmã flutuante e contato reedVariação de capacitância atrás da parede do recipiente
SaídaAnalógica (alguns níveis)Contato aberto ou fechadoDigital (há líquido ou não)
Faixa de mediçãoCerca de 0–4 cmUm ponto (altura de montagem)Um ponto (altura de montagem)
Contato com a águaSim, trilhas na águaSim, corpo na águaNão, fica colado do lado de fora do recipiente
CorrosãoSim; alimentar pelo pino é obrigatórioPraticamente nenhumaNenhuma
Alimentação3,3–5 VNão precisa (contato passivo)5–24 V, cerca de 5 mA
Melhor paraExperimentos, alarmes de transbordamento, recipientes pequenosReservatórios permanentes, proteção de bombaReservatórios fechados de plástico ou vidro, líquidos corrosivos
PreçoO mais baratoBaratoMais caro que os outros

Uma chave boia é formada por uma haste com um contato reed dentro e uma boia com ímã que desliza ao longo dela. Quando a água sobe, a boia sobe, o ímã se alinha com o contato reed e o contato fecha ou abre. Montando a boia de cabeça para baixo na haste, você alterna entre o comportamento normalmente aberto (NA) e normalmente fechado (NF). Para ligar ao Arduino, ligue um fio em um pino digital e o outro no GND e configure o pino como INPUT_PULLUP; como não há desgaste por eletrólise, ela dura muito mais em instalações permanentes. Os contatos dos modelos pequenos costumam ser limitados a cerca de 0,5 A e 10 W, então acione a bomba por um relé, e não diretamente. Para entender como funciona um contato reed, veja o artigo Chave reed.

Sensor de nível de água com chave boia
Chave boia: a boia magnética sobe com a água e abre ou fecha o contato reed dentro da haste.
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}

Já o XKC-Y25 é um sensor capacitivo que nunca toca na água: você o cola do lado de fora de um reservatório de plástico ou vidro e ele detecta se há líquido atrás da parede. Segundo o fabricante, funciona com 5–24 V, puxa cerca de 5 mA, detecta através de paredes não metálicas de até 13 mm de espessura e responde em cerca de 500 ms. O nível alto da saída é igual à tensão de alimentação, então, ao ligar um XKC-Y25 alimentado com 5 V a um ESP32 ou a um Pico, use um divisor de tensão (a ferramenta de divisor de tensão calcula os resistores certos). O ajuste de sensibilidade e os modelos com saídas diferentes estão explicados em detalhe no artigo sensor de nível sem contato XKC-Y25.

Sensor de nível de líquido sem contato XKC-Y25
XKC-Y25: um sensor capacitivo colado do lado de fora do reservatório; como nunca toca na água, nunca sofre corrosão.

Acompanhando o nível da água pelo celular com o ESP32

Com o ESP32 você leva a medição para o celular pelo Wi-Fi. Ligue sempre o pino S do sensor a um pino do ADC1 (GPIO 32–39); os pinos do ADC2 não podem ser lidos com o Wi-Fi ligado. O ADC do ESP32 é de 12 bits, então os valores vão de 0 a 4095 e, como o sensor é alimentado com 3,3 V, os números não podem ser comparados com os do Uno; você vai precisar calibrar de novo. O ADC do ESP32 não é totalmente linear perto de 0 V e perto do topo da faixa, mas, como aqui importa a diferença entre os níveis e não a tensão absoluta, isso não é problema. O código abaixo faz uma leitura a cada dois segundos e serve uma pequena página web que se atualiza sozinha a cada cinco segundos, que você pode abrir no celular conectado à mesma rede.

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}

Antes do upload, troque WIFI_SSID e WIFI_PASS pelos dados da sua rede; o ESP32 só se conecta a redes de 2,4 GHz. Quando abrir o Monitor Serial a 115200 baud, basta digitar no navegador do celular o endereço que aparece. Se quiser receber uma notificação no celular quando o nível estiver “cheio”, você pode transformar a mesma leitura em mensagem com o método do artigo bot do Telegram com ESP32.

Alarme de transbordamento com Raspberry Pi Pico e MicroPython

No Raspberry Pi Pico, os pinos GP26, GP27 e GP28 são usados para leituras analógicas. A função read_u16() do MicroPython converte a medição de 12 bits do Pico para a faixa de 0–65535, então os seus limites vão ser números bem maiores que no Uno. O código abaixo alimenta o sensor pelo GP15, lê a saída S no GP26 e dá um aviso de transbordamento com três bipes curtos de um buzzer ativo no GP14. Como no primeiro sketch, defina os limites a partir das suas próprias medições.

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)

Ideias de projetos com sensor de nível de água

  • Aviso de transbordamento do pratinho do vaso: um buzzer que toca quando a água se acumula no pratinho depois da rega; junte com um sensor de umidade do solo e você tem um sistema de irrigação completo.
  • Reposição automática do aquário: um sistema de reabastecimento com limite de tempo que repõe a água evaporada a partir de um balde reserva com uma minibomba.
  • Pote de água do pet: um lembrete que acende um LED ou manda uma notificação para o celular pelo ESP32 quando o pote fica baixo.
  • Detector de vazamento de água: um alarme de vazamento com o sensor deitado no chão embaixo da máquina de lavar ou do aquecedor, ou no porão.
  • Reservatório de estufa inteligente: uma proteção que vigia o nível do reservatório de irrigação e bloqueia a bomba quando ele seca; ela se encaixa fácil no projeto de estufa inteligente.
  • Medidor de cisterna de chuva: um painel que mostra o nível como vazio, metade ou cheio em um display LCD I2C; você também pode acrescentar um sensor de chuva para registrar o momento em que a chuva começa.

Erros comuns e como corrigi-los

SintomaCausa provávelSolução
O valor é sempre 0, mesmo na águaO pino + não está sendo alimentado (POWER_PIN nunca vai para HIGH) ou o S está no pino erradoConfira as linhas de pinMode e digitalWrite e se o S está ligado a um pino analógico
O valor pula aleatoriamente mesmo secoO pino S está flutuando ou o GND não está ligadoConfira os três fios; o GND tem de ser comum
Nunca chega a 1023, mesmo totalmente submersoIsso é normal; a saída vem de um seguidor de emissorDefina os limites a partir do maior valor que você mesmo mediu
Nenhuma leitura em água puraÁgua destilada ou purificada tem condutividade muito baixaUse um XKC-Y25 ou uma chave boia com esse tipo de água
Os valores caem ou variam ao longo de algumas semanasEletrólise e depósitos nas trilhasAlimente o sensor por um pino, limpe as trilhas com uma escova macia e troque o sensor se for preciso
A bomba ou o buzzer fica ligando e desligando no limiteÉ usado um único limite; a superfície em movimento faz o valor oscilarUse dois limites separados para ligar e desligar (histerese) e tire a média das leituras
No ESP32, o valor não pode ser lido depois que o Wi-Fi conectaO sensor está em um pino do ADC2Passe o S para um pino do ADC1, entre GPIO 32 e 39
Para o sensor durar mais, coloque-o em pé na água, mergulhe só a parte com as trilhas e cubra a eletrônica do topo com cola quente ou verniz transparente; mas não cubra as trilhas, senão elas não conseguem medir a condutividade. Para uma instalação permanente que vai ficar meses na água, a solução mais robusta é usar este sensor no protótipo e trocar por uma chave boia ou um sensor sem contato no sistema final.

O sensor de nível de água ensina leitura analógica, calibração, histerese e problemas do mundo real, como a corrosão, com um único módulo barato. Se você precisa medir centímetro por centímetro o nível de um reservatório grande, pode partir para uma solução ultrassônica como o sensor de distância HC-SR04. No app BlueGrays você encontra a estação de irrigação inteligente e projetos de alarme com buzzer, com esquemas de circuito e código passo a passo, e pode acrescentar facilmente o sensor de nível de água a eles.

Perguntas frequentes

Como funciona um sensor de nível de água?

Quando as trilhas condutoras intercaladas da placa entram na água, a água faz a ponte entre elas e uma corrente entra na base do transistor S8050 da placa. Quanto mais o transistor conduz, maior a tensão no pino S; o Arduino lê essa tensão com analogRead() para saber a altura da água.

Por que o meu sensor de nível de água sofre corrosão?

Quando uma corrente contínua passa o tempo todo pelas trilhas molhadas, começa a eletrólise e o revestimento das trilhas ligadas ao + se dissolve. Se você alimentar o sensor por um pino digital em vez do 5V e ligá-lo só por alguns milissegundos a cada leitura, o desgaste desacelera muito e o sensor dura meses.

O sensor de nível de água funciona em água destilada?

Na prática, não. Como o sensor mede a condutividade da água, água destilada ou purificada, sem minerais dissolvidos, dá leituras muito baixas. Para esse tipo de água, sensores que não dependem da condutividade, como o XKC-Y25 sem contato ou uma chave boia, são a melhor escolha.

Por que a leitura do sensor de nível de água não chega a 1023?

A saída S é tirada do emissor do transistor, então a tensão fica abaixo da alimentação, e a corrente de base é limitada pela resistência da água. Em um Arduino Uno com 5 V, um sensor totalmente molhado costuma ler em torno de 500–650, então defina os seus limites a partir desse máximo.

Um sensor de nível de água pode ficar totalmente submerso?

Não. Só a parte de baixo, com as trilhas condutoras, deve ir na água; se a parte de cima, com o transistor, o LED e os pinos, molhar, ela entra em curto e o sensor lê errado ou queima. Proteger a eletrônica com cola quente ou verniz faz ele durar mais.

Como medir o nível de um reservatório de água grande?

Este sensor só cobre uma faixa de cerca de 4 cm, então não serve para reservatórios grandes. Para medir o nível de forma contínua, usam-se sensores ultrassônicos à prova d’água, como o JSN-SR04T, montados na tampa do reservatório; para vigiar só alguns pontos críticos, colocam-se chaves boia em alturas diferentes.

Ver todos os projetos
Uso do buzzer
#13Iniciante

Uso do buzzer

Já se perguntou como uma campainha ou um alarme produz som? O Arduino faz um pequeno buzzer emitir bipes em intervalos curtos: bipe, pausa, bipe, pausa. Você vê como a eletricidade produz som e dá o p

4.7(89)
161
Medição da intensidade da luz com LDR
#11Iniciante

Medição da intensidade da luz com LDR

Quer ver a luminosidade do seu quarto em números? O LDR, um pequeno componente sensível à luz, mede a luz ambiente, e o Arduino exibe o valor na tela do computador a cada meio segundo. Cubra o sensor

4.6(81)
139
Leitura da intensidade da luz com módulo LDR e ESP32
#113Iniciante

Leitura da intensidade da luz com módulo LDR e ESP32

Acompanhe em tempo real no Monitor Serial o valor bruto do ADC do módulo LDR e a porcentagem relativa de luz calculada a partir de referências de escuridão e claridade. Essa porcentagem não é uma medida em lux. O projeto ensina a lógica de calibração do módulo. É ideal fazê-lo antes do projeto 10, pois ajuda a determinar o valor do limiar.

4.6(36)
55
Estação de irrigação inteligente
#83Avançado
Premium

Estação de irrigação inteligente

Um jardineiro que rega suas plantas sozinho para que elas não sequem enquanto você está de férias. Um sensor de umidade do solo mede o quanto a terra está úmida; quando ela seca, o Arduino aciona a bo

5.0(42)
57
Leitura de uma chave reed
#37Iniciante

Leitura de uma chave reed

Você já teve curiosidade sobre a chave magnética dos alarmes de portas e janelas? Quando um ímã se aproxima do módulo de relé reed, a pequena chave interna fecha; o Arduino faz a leitura uma vez por s

4.4(21)
27
Servidor web assíncrono com ESP32 (IP no LCD)
#129Avançado

Servidor web assíncrono com ESP32 (IP no LCD)

Neste projeto, transformamos o ESP32 em um servidor web assíncrono que você pode controlar pelo celular ou computador na mesma rede Wi-Fi. Com a biblioteca ESPAsyncWebServer, o servidor processa várias requisições ao mesmo tempo (ao contrário do WebServer.h tradicional, que bloqueia a execução ao processar uma requisição). Você poderá abrir o endereço IP do ESP32 no navegador e clicar nos botões ON/OFF (as rotas /on e /off) para ligar e desligar o LED conectado ao GPIO 5.

4.8(16)
26
Alarme de movimento com ESP32 (PIR + buzzer + LED + Telegram)
#145Avançado
Premium

Alarme de movimento com ESP32 (PIR + buzzer + LED + Telegram)

Um sistema de alarme de segurança inteligente que aciona o buzzer e o LED quando o sensor PIR detecta movimento e, ao mesmo tempo, envia uma notificação instantânea ao proprietário pelo Telegram. Inclui um intervalo de espera de 30 segundos para limitar a frequência dos alarmes repetidos; esse mecanismo não valida as detecções do PIR nem elimina disparos falsos. Pode ser usado na segurança de casas, no monitoramento de garagens, depósitos ou salas de trabalho.

0.0(0)
9