Bauteile · 12 Min. Lesezeit

Wasserstandssensor am Arduino: Kalibrierung, Alarm und Pumpe

Wasserstandssensor am Arduino: Kalibrierung leer/halb/voll, Versorgung über einen Pin gegen Korrosion, Überlaufalarm mit Summer, Pumpe und ESP32/Pico-Code.

Ein Wasserstandssensor ist mit dem Arduino der günstigste und einfachste Weg, um zu erkennen, wie hoch das Wasser in einem Glas, einem Aquarium, einem Blumentopf-Untersetzer oder einem kleinen Tank steht. Je weiter die offenen Leiterbahnen auf der Platine ins Wasser eintauchen, desto höher steigt die Spannung am Analogausgang; der Arduino liest diese Spannung mit analogRead() und entscheidet, ob der Behälter „leer“, „halb voll“ oder „voll“ ist. Der Sensor wird mit drei Kabeln angeschlossen, läuft mit wenigen Zeilen Code und ist die Grundlage vieler Projekte, vom Überlaufalarm bis zur automatischen Pumpensteuerung.

In dieser Anleitung erfährst du, was im Modul steckt, warum der Messwert nie 1023 erreicht, wie du die Kalibrierung für leer, halb und voll machst und wie du die Korrosion verhinderst, die den Sensor sonst in wenigen Wochen zerfrisst. Danach baust du einen Überlaufalarm mit Summer und eine Pumpensteuerung, die einen Tank selbstständig nachfüllt, vergleichst den Sensor kurz mit einem Schwimmerschalter und dem berührungslosen XKC-Y25 und siehst zum Schluss, wie du dasselbe mit dem ESP32 und dem Raspberry Pi Pico umsetzt.

Wasserstandssensor-Modul für Arduino
Wasserstandssensor-Modul: Die ineinandergreifenden Leiterbahnen unten tauchen ins Wasser, die Pins S, + und − oben werden mit dem Arduino verbunden; die Elektronik muss immer trocken bleiben.

Was ist ein Wasserstandssensor und wie funktioniert er?

Im unteren Teil des Moduls liegen zehn Leiterbahnen, die sich nicht berühren und wie die Zähne zweier Kämme ineinandergreifen. Fünf davon sind Versorgungsbahnen, die an + hängen, die anderen fünf sind Messbahnen, die zur Basis des NPN-Transistors S8050 oben auf der Platine führen. Ist die Platine trocken, befindet sich zwischen den Bahnen nur Luft, der Transistor sperrt und der S-Pin liegt nahe 0 V. Taucht die Platine ins Wasser, überbrückt das Wasser Versorgungs- und Messbahnen; ein kleiner Strom fließt in die Basis, der Transistor beginnt zu leiten und die Spannung am S-Ausgang, der am Emitter abgegriffen wird, steigt. Je höher das Wasser steht, desto länger ist der benetzte Teil der Bahnen, desto kleiner wird der Widerstand zwischen ihnen und desto größer die Ausgangsspannung.

Diese Funktionsweise hat drei wichtige Folgen. Erstens misst der Sensor eigentlich nicht das Wasser, sondern seine Leitfähigkeit: Die gelösten Mineralien im Leitungswasser treiben den Messwert nach oben, reines (destilliertes) Wasser liefert dagegen fast nichts. Zweitens kommt der Ausgang von einem Transistor in Kollektorschaltung (Emitterfolger), deshalb erreicht die Spannung nie die Versorgungsspannung; ein komplett nasser Sensor an 5 V liefert am Arduino Uno meist etwa 500–650 und kommt nie in die Nähe von 1023. Drittens ist der Zusammenhang nicht linear: Der Wert steigt auf den ersten Millimetern schnell und dann immer langsamer. Dieser Sensor ist also kein Lineal mit Millimetergenauigkeit, sondern eine praktische Anzeige, die einige Stufen zuverlässig unterscheidet.

EigenschaftWert
Betriebsspannung3,3–5 V DC
StromaufnahmeUnter 20 mA (am höchsten, wenn er ganz nass ist)
AusgangAnaloge Spannung (S-Pin), steigt mit dem Wasserstand
MessflächeEtwa 40 × 16 mm, also höchstens etwa 4 cm Wasserhöhe
PlatinengrößeEtwa 62 × 20 mm
Betriebstemperatur10–30 °C (Herstellerangabe)
PinsS (Signal), + (VCC), − (GND)

Wasserstandssensor anschließen: Arduino Uno, ESP32 und Pico

Sensor-PinArduino UnoESP32Raspberry Pi Pico
S (Signal)A0GPIO 34 (ADC1)GP26 (ADC0)
+ (VCC)D7 (versorgt ihn nur beim Messen)GPIO 25GP15
− (GND)GNDGNDGND
Schließe den +-Pin des Sensors nicht dauerhaft an 5V an. Fließt ständig Gleichstrom durch die nassen Bahnen, setzt Elektrolyse ein: Die Beschichtung der an + hängenden Bahnen löst sich auf, die Bahnen werden dunkel und nach wenigen Wochen beginnen die Messwerte zu wandern. Außerdem darf nur der untere Teil der Platine mit den Leiterbahnen ins Wasser; wird der obere Teil mit Transistor, LED und Pins nass, entsteht ein Kurzschluss.

Am einfachsten verhinderst du Korrosion, indem du den Sensor wie in der Tabelle über einen Digitalpin versorgst: Der Code setzt den Pin kurz vor der Messung auf HIGH, wartet 10 ms, liest den Wert und setzt den Pin wieder auf LOW. Bei einer Messung pro Sekunde stehen die Bahnen nur 1 Prozent der Zeit unter Spannung, was den Verschleiß grob um den Faktor hundert verlangsamt. Ganz nass zieht das Modul höchstens etwa 20 mA. Für einen Pin des Arduino Uno werden 20 mA empfohlen, absolut zulässig sind 40 mA, und der Pin ist nur wenige Millisekunden eingeschaltet, daher ist diese Schaltung sicher; auch die Pins des ESP32 liefern diesen Strom problemlos. Die Pins des Pico arbeiten dagegen standardmäßig mit einer geringeren Treiberstärke, deshalb sinkt die Pinspannung etwas, wenn der Sensor ganz nass ist, und die Messwerte werden kleiner. Solange du mit derselben Verdrahtung kalibrierst, ist das kein Problem; willst du stabilere Werte, kannst du das + des Sensors mit einem kleinen PNP-Transistor wie dem BC557 schalten: Der Emitter kommt an den 3V3-Pin des Boards, der Kollektor an das + des Sensors und die Basis über einen 1-kΩ-Widerstand an den GPIO-Pin; der Sensor ist dann eingeschaltet, wenn der Pin LOW ist. Einen passenden Transistor findest du mit dem Transistor-Tool.

Schritt für Schritt: die erste Messung mit dem Arduino

  1. Verbinde den S-Pin des Sensors mit A0, den +-Pin mit D7 und den −-Pin mit GND. Halte die Platine senkrecht, die Leiterbahnen zeigen nach unten.
  2. Öffne den folgenden Code in der Arduino IDE, wähle Arduino Uno als Board und den richtigen Port aus und lade ihn hoch.
  3. Öffne den Seriellen Monitor und stelle 9600 Baud ein. Prüfe, dass der Wert bei trockenem Sensor nahe 0 liegt.
  4. Tauche den Sensor langsam in ein Glas Wasser: zuerst nur die Spitze, dann bis zur Hälfte, dann bis zur Linie, an der die Leiterbahnen enden. Warte bei jedem Schritt ein paar Sekunden und notiere den Wert.
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}

Die Funktion readSensor() lässt den Sensor pro Messung nur etwa 11 ms eingeschaltet. Die 10 ms Wartezeit sorgen dafür, dass sich Transistor und Wasser zwischen den Bahnen auf einen stabilen Wert einpendeln; danach glättet der Mittelwert aus 8 Messungen die kleinen Schwankungen einzelner Werte. Auf dem Uno dauert jedes analogRead() etwa 0,1 ms, 8 Messungen brauchen also weniger als 1 ms. Wenn du das Wasser umrührst oder das Glas bewegst, springen die Werte im Seriellen Monitor; das ist normal, denn die bewegte Oberfläche ändert ständig die benetzte Länge der Bahnen.

Leer, halb, voll: So kalibrierst du den Sensor

Übernimm die Schwellwerte aus Code im Internet nicht einfach; jeder Sensor, jedes Wasser und jede Versorgungsspannung liefert andere Werte. Kalibriere in dem Behälter, in dem der Sensor wirklich eingesetzt wird, und mit demselben Wasser: Aquariumwasser fürs Aquarium, gedüngtes Wasser für einen Bewässerungstank mit Dünger. Zeichne mit einem Stift Linien bei 0, 10, 20, 30 und 40 mm auf den Sensor, tauche die Platine bis zu jeder Linie ein, warte 3–4 Sekunden, bis sich der Wert eingependelt hat, und notiere die Zahl aus dem Seriellen Monitor. Die Tabelle zeigt typische Bereiche für Leitungswasser und 5 V; schreib deine eigenen Werte daneben.

StufeEintauchtiefeTypischer Uno-Wert (5 V, Leitungswasser)
Leer0 mm (trocken)0–20
NiedrigEtwa 5–10 mm250–400
HalbEtwa 20 mm400–480
VollEtwa 40 mm (Linie, an der die Bahnen enden)480–650

Auffällig ist, wie schnell die Werte im ersten Zentimeter steigen und wie eng sie danach beieinanderliegen: Zwischen 0 und 10 mm können mehrere Hundert Einheiten liegen, zwischen 20 und 40 mm nur noch ein paar Dutzend. Statt mit map() eine einzige Gerade zu ziehen, liefert deshalb die stückweise lineare Interpolation, die zwischen je zwei Messpunkten ein eigenes Verhältnis verwendet, ein viel genaueres Ergebnis. Der folgende Code speichert deine fünf Messpunkte in zwei Arrays, rechnet den Rohwert in Millimeter um und gibt die Stufe mit Namen aus. Du musst nur deine eigenen Messwerte aufsteigend in das Array RAW eintragen.

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}
Nimmst du den Sensor aus dem Wasser, fällt der Wert nicht sofort auf 0; der dünne Wasserfilm und die Tropfen zwischen den Bahnen halten den Messwert eine Weile deutlich über null. Leg die Schwelle für „leer“ deshalb etwas über 0 und verwende für Ein/Aus-Entscheidungen wie einen Alarm zwei getrennte Schwellen: eine zum Einschalten und eine zum Ausschalten. Dieses Verfahren heißt Hysterese und verhindert, dass ein Relais oder Summer im Sekundentakt an- und ausgeht, während der Pegel genau um die Schwelle schwankt.

Überlaufalarm mit Summer

Eine der nützlichsten Aufgaben eines Wasserstandssensors ist die Warnung vor Überlauf: Unter der Waschmaschine oder der Therme, im Untersetzer, in der Kondensatwanne einer Klimaanlage oder am Rand eines Eimers, der sich füllt, löst der Sensor den Alarm aus, sobald das Wasser seine Spitze berührt. Dafür reicht schon die Stufe „niedrig“ aus der Kalibriertabelle. Der folgende Code nutzt einen aktiven Summer und die eingebaute LED des Uno; überschreitet der Wert ALARM_ON, piept der Summer im Viertelsekundentakt, fällt er unter ALARM_OFF, wird er still. Weil für das Timing millis() statt delay() verwendet wird, blockieren sich Messung und Summer nicht gegenseitig. Mehr zu Summer-Typen findest du unter Was ist ein Buzzer?, zum Prinzip von millis() unter millis() und 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}

Pumpensteuerung: einen Tank selbstständig nachfüllen

Die zweite klassische Anwendung ist das automatische Nachfüllen, das den Pegel in einem Bereich hält. Vielleicht willst du verdunstetes Wasser im Aquarium aus einem Vorratseimer ergänzen, den Wassernapf deines Haustiers voll halten oder einen Gewächshaustank speisen. Die Logik ist einfach: Fällt der Pegel unter START_BELOW, läuft die Pumpe, erreicht er STOP_ABOVE, stoppt sie. Der Abstand zwischen diesen beiden Schwellen ist die Hysterese, die ständiges Ein- und Ausschalten der Pumpe verhindert. Denk daran, dass der Sensor nur etwa 4 cm Messfläche hat; befestige die Platine in einer Höhe, bei der der Wasserbereich, den du halten willst, innerhalb dieser 4 cm liegt.

6-V-Mini-Tauchpumpe für Wasser
3–6-V-Mini-Tauchpumpe: Sie arbeitet unter Wasser, zieht etwa 100–250 mA und wird deshalb über ein Relais oder einen MOSFET angesteuert, nicht direkt über einen Arduino-Pin.

Die Pumpe zieht viel mehr Strom, als ein Arduino-Pin liefern kann. Steuere sie deshalb über ein Relaismodul oder einen Logic-Level-MOSFET mit Freilaufdiode an, versorge die Pumpe aus einem eigenen Netzteil und verbinde die GNDs beider Quellen. Details findest du unter Was ist ein Relaismodul?, MOSFET am Arduino und Mini-Wasserpumpe. Der wichtigste Teil des Codes ist eine Sicherheitsfunktion: Läuft die Pumpe die ganze Zeit MAX_RUN_MS, ohne dass der Pegel den Zielwert erreicht, sperrt das System die Pumpe und warnt dich mit kurzen Pieptönen. Vielleicht ist der Schlauch herausgerutscht, der Vorratseimer leer oder der Sensor verrutscht; ohne diese Sperre könnte die Pumpe stundenlang trocken laufen oder alles unter Wasser setzen.

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}
Wasser und Strom im selben Projekt: Platziere Arduino, Relais und Netzteil oberhalb und abseits der Wasserbehälter und isoliere Kabelverbindungen mit Schrumpfschlauch oder Heißkleber. Wenn du eine Pumpe oder ein Magnetventil für Netzspannung verwenden willst, lass den Netzanschluss von einer Elektrofachkraft machen und arbeite an einem Stromkreis mit FI-Schutzschalter. Kleine Tauchpumpen überhitzen und gehen schnell kaputt, wenn sie trocken laufen; ein zusätzlicher Schwimmerschalter im Vorratseimer ist eine gute zweite Sicherheitsstufe.

Wasserstandssensor, Schwimmerschalter und XKC-Y25 im Vergleich

EigenschaftWasserstandssensor (Leiterbahnen)SchwimmerschalterXKC-Y25 (berührungslos)
MessprinzipLeitfähigkeit des WassersSchwimmender Magnet und ReedkontaktKapazitätsänderung hinter der Behälterwand
AusgangAnalog (einige Stufen)Offener oder geschlossener KontaktDigital (Flüssigkeit vorhanden oder nicht)
MessbereichEtwa 0–4 cmEin Punkt (Einbauhöhe)Ein Punkt (Einbauhöhe)
Kontakt mit WasserJa, Bahnen im WasserJa, Körper im WasserNein, klebt außen am Behälter
KorrosionJa; Versorgung über einen Pin ist PflichtPraktisch keineKeine
Versorgung3,3–5 VNicht nötig (passiver Kontakt)5–24 V, etwa 5 mA
Am besten fürExperimente, Überlaufalarm, kleine BehälterFeste Tanks, PumpenschutzGeschlossene Kunststoff- oder Glastanks, aggressive Flüssigkeiten
PreisAm günstigstenGünstigTeurer als die anderen

Ein Schwimmerschalter besteht aus einem Rohr mit einem Reedkontakt im Inneren und einem Schwimmer mit Magnet, der daran entlanggleitet. Steigt das Wasser, hebt sich der Schwimmer, der Magnet kommt auf Höhe des Reedkontakts und der Kontakt schließt oder öffnet. Steckst du den Schwimmer umgedreht auf das Rohr, wechselst du zwischen Schließer (NO) und Öffner (NC). Für den Arduino verbindest du ein Kabel mit einem Digitalpin, das andere mit GND, und setzt den Pin auf INPUT_PULLUP; da keine Elektrolyse auftritt, hält er in festen Installationen viel länger. Die Kontakte kleiner Modelle sind meist auf etwa 0,5 A und 10 W begrenzt, schalte die Pumpe daher über ein Relais und nicht direkt. Wie ein Reedkontakt funktioniert, erklärt der Beitrag Reedschalter.

Schwimmerschalter als Wasserstandssensor
Schwimmerschalter: Der magnetische Schwimmer steigt mit dem Wasser und öffnet oder schließt den Reedkontakt im Rohr.
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}

Der XKC-Y25 ist dagegen ein kapazitiver Sensor, der das Wasser nie berührt: Du klebst ihn außen an einen Kunststoff- oder Glasbehälter, und er erkennt, ob sich hinter der Wand Flüssigkeit befindet. Laut Hersteller arbeitet er mit 5–24 V, zieht etwa 5 mA, erkennt Flüssigkeit durch nichtmetallische Wände bis 13 mm Dicke und reagiert in etwa 500 ms. Der High-Pegel seines Ausgangs entspricht der Versorgungsspannung; schließt du einen mit 5 V versorgten XKC-Y25 an einen ESP32 oder Pico an, brauchst du daher einen Spannungsteiler (das Spannungsteiler-Tool berechnet die passenden Widerstände). Die Empfindlichkeitseinstellung und die Modelle mit anderen Ausgängen beschreiben wir ausführlich im Beitrag berührungsloser Füllstandssensor XKC-Y25.

Berührungsloser Füllstandssensor XKC-Y25
XKC-Y25: kapazitiver Sensor, der außen auf den Tank geklebt wird; er berührt das Wasser nie und korrodiert deshalb nicht.

Wasserstand mit dem ESP32 auf dem Handy überwachen

Mit dem ESP32 bringst du den Messwert per WLAN auf dein Handy. Verbinde den S-Pin des Sensors unbedingt mit einem ADC1-Pin (GPIO 32–39); ADC2-Pins lassen sich bei aktivem WLAN nicht auslesen. Der ADC des ESP32 hat 12 Bit, die Werte liegen also zwischen 0 und 4095, und weil der Sensor mit 3,3 V versorgt wird, sind die Zahlen nicht mit denen des Uno vergleichbar; du musst neu kalibrieren. Der ADC des ESP32 ist nahe 0 V und nahe dem oberen Ende nicht ganz linear, doch da es hier nicht auf die absolute Spannung, sondern nur auf den Unterschied zwischen den Stufen ankommt, stört das nicht. Der folgende Code misst alle zwei Sekunden und stellt eine kleine Webseite bereit, die sich alle fünf Sekunden selbst aktualisiert und die du im selben Netzwerk mit dem Handy aufrufen kannst.

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}

Ersetze vor dem Hochladen WIFI_SSID und WIFI_PASS durch deine eigenen WLAN-Daten; der ESP32 verbindet sich nur mit 2,4-GHz-Netzen. Öffnest du den Seriellen Monitor mit 115200 Baud, gibst du die angezeigte Adresse einfach im Browser deines Handys ein. Möchtest du eine Benachrichtigung aufs Handy, wenn der Pegel „voll“ ist, kannst du denselben Messwert mit der Methode aus dem Beitrag ESP32-Telegram-Bot in eine Nachricht verwandeln.

Überlaufalarm mit Raspberry Pi Pico und MicroPython

Beim Raspberry Pi Pico dienen die Pins GP26, GP27 und GP28 für analoge Messungen. Die MicroPython-Funktion read_u16() skaliert die 12-Bit-Messung des Pico auf den Bereich 0–65535, deine Schwellwerte sind also viel größere Zahlen als beim Uno. Der folgende Code versorgt den Sensor über GP15, liest den S-Ausgang an GP26 und warnt mit drei kurzen Pieptönen eines aktiven Summers an GP14 vor Überlauf. Lege die Schwellen wie beim ersten Sketch anhand deiner eigenen Messungen fest.

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)

Projektideen mit dem Wasserstandssensor

  • Überlaufwarnung für den Untersetzer: Ein Summer, der sich meldet, wenn sich nach dem Gießen Wasser im Untersetzer sammelt; zusammen mit einem Bodenfeuchtesensor entsteht ein komplettes Bewässerungssystem.
  • Automatisches Nachfüllen im Aquarium: Ein zeitbegrenztes System, das verdunstetes Wasser mit einer Minipumpe aus einem Vorratseimer ersetzt.
  • Wassernapf fürs Haustier: Ein Erinnerer, der eine LED einschaltet oder per ESP32 eine Nachricht aufs Handy schickt, wenn der Napf fast leer ist.
  • Wassermelder: Ein Leckalarm mit flach auf den Boden gelegtem Sensor unter der Waschmaschine, der Therme oder im Keller.
  • Intelligenter Gewächshaustank: Ein Schutz, der den Pegel des Bewässerungstanks überwacht und die Pumpe sperrt, wenn er leer ist; lässt sich leicht in das smarte Gewächshausprojekt einbauen.
  • Regentonnen-Anzeige: Ein Display, das den Pegel als leer, halb oder voll auf einem I2C-LCD-Display zeigt; mit einem Regensensor erkennst du zusätzlich, wann der Regen einsetzt.

Häufige Fehler und Lösungen

SymptomMögliche UrsacheLösung
Der Wert ist immer 0, auch im WasserDer +-Pin wird nicht versorgt (POWER_PIN wird nie HIGH) oder S hängt am falschen PinPrüfe die Zeilen mit pinMode und digitalWrite und ob S an einem Analogpin hängt
Der Wert springt auch trocken zufällig herumDer S-Pin hängt in der Luft oder GND ist nicht verbundenPrüfe alle drei Kabel; GND muss gemeinsam sein
Er erreicht nie 1023, selbst ganz eingetauchtDas ist normal; der Ausgang kommt von einem EmitterfolgerLege die Schwellen anhand des höchsten selbst gemessenen Werts fest
In reinem Wasser kommt gar kein WertDestilliertes oder gefiltertes Wasser leitet kaumNimm für solches Wasser einen XKC-Y25 oder einen Schwimmerschalter
Die Werte sinken oder wandern über einige WochenElektrolyse und Ablagerungen auf den BahnenVersorge den Sensor über einen Pin, reinige die Bahnen mit einer weichen Bürste und ersetze den Sensor bei Bedarf
Pumpe oder Summer schalten an der Schwelle ständig hin und herEs gibt nur eine Schwelle; die bewegte Oberfläche lässt den Wert schwankenNutze zwei getrennte Schwellen zum Ein- und Ausschalten (Hysterese) und bilde Mittelwerte
Beim ESP32 lässt sich der Wert nach dem WLAN-Verbindungsaufbau nicht lesenDer Sensor hängt an einem ADC2-PinVerlege S auf einen ADC1-Pin zwischen GPIO 32 und 39
Damit der Sensor länger hält, setze ihn senkrecht ins Wasser, tauche nur den Teil mit den Bahnen ein und schütze die Elektronik oben mit Heißkleber oder Klarlack; die Bahnen selbst darfst du aber nicht beschichten, sonst können sie keine Leitfähigkeit mehr messen. Für eine feste Installation, die monatelang im Wasser bleibt, ist es am robustesten, diesen Sensor nur für den Prototyp zu verwenden und im fertigen System auf einen Schwimmerschalter oder einen berührungslosen Sensor umzusteigen.

Der Wasserstandssensor vermittelt analoge Messungen, Kalibrierung, Hysterese und echte Praxisprobleme wie Korrosion mit einem einzigen günstigen Modul. Musst du den Pegel eines großen Tanks zentimetergenau messen, kannst du auf eine Ultraschall-Lösung wie den HC-SR04-Abstandssensor umsteigen. In der BlueGrays-App findest du die smarte Bewässerungsstation und Alarmprojekte mit Summer, jeweils mit Schaltplan und Code Schritt für Schritt, und kannst den Wasserstandssensor ganz einfach in diese Projekte einbauen.

Häufige Fragen

Wie funktioniert ein Wasserstandssensor?

Tauchen die ineinandergreifenden Leiterbahnen der Platine ins Wasser, überbrückt das Wasser sie und es fließt Strom in die Basis des S8050-Transistors auf dem Modul. Je stärker der Transistor leitet, desto höher die Spannung am S-Pin; der Arduino liest diese Spannung mit analogRead() und erkennt so, wie hoch das Wasser steht.

Warum korrodiert mein Wasserstandssensor?

Fließt ständig Gleichstrom durch die nassen Bahnen, setzt Elektrolyse ein und die Beschichtung der an + hängenden Bahnen löst sich auf. Versorgst du den Sensor statt über 5V über einen Digitalpin und schaltest ihn nur für wenige Millisekunden pro Messung ein, verlangsamt sich der Verschleiß stark und der Sensor hält monatelang.

Funktioniert ein Wasserstandssensor in destilliertem Wasser?

Kaum. Da der Sensor die Leitfähigkeit misst, liefert destilliertes oder gefiltertes Wasser ohne gelöste Mineralien nur sehr kleine Werte. Für solches Wasser sind Sensoren, die nicht von der Leitfähigkeit abhängen, wie der berührungslose XKC-Y25 oder ein Schwimmerschalter, die bessere Wahl.

Warum erreicht der Wasserstandssensor nicht den Wert 1023?

Der S-Ausgang wird am Emitter des Transistors abgegriffen, deshalb bleibt die Spannung unter der Versorgungsspannung, und der Basisstrom wird durch den Widerstand des Wassers begrenzt. Am Arduino Uno mit 5 V liefert ein ganz nasser Sensor meist etwa 500–650; lege deine Schwellen anhand dieses Höchstwerts fest.

Darf man einen Wasserstandssensor komplett untertauchen?

Nein. Nur der untere Teil mit den Leiterbahnen darf ins Wasser; wird der obere Teil mit Transistor, LED und Pins nass, entsteht ein Kurzschluss und der Sensor misst falsch oder geht kaputt. Wenn du die Elektronik mit Heißkleber oder Lack schützt, hält er länger.

Wie misst man den Füllstand eines großen Wassertanks?

Dieser Sensor deckt nur etwa 4 cm ab und eignet sich daher nicht für große Tanks. Für eine durchgehende Füllstandsmessung nutzt man wasserdichte Ultraschallsensoren wie den JSN-SR04T im Tankdeckel; sollen nur einige kritische Punkte überwacht werden, setzt man Schwimmerschalter in verschiedenen Höhen ein.

Alle Projekte ansehen
Verwendung des Summers
#13Anfänger

Verwendung des Summers

Hast du dich mal gefragt, wie eine Türklingel oder ein Alarm seinen Ton erzeugt? Der Arduino lässt einen kleinen Summer in kurzen Abständen piepen: piep, Pause, piep, Pause. Du siehst, wie Strom zu Kl

4.7(89)
161
Lichtstärke messen mit LDR
#11Anfänger

Lichtstärke messen mit LDR

Willst du sehen, wie hell dein Zimmer ist, und zwar als Zahl? Der LDR, ein kleines lichtempfindliches Bauteil, misst das Umgebungslicht, und der Arduino schreibt den Wert jede halbe Sekunde auf deinen

4.6(81)
139
Messung der Lichtintensität mit dem ESP32-LDR-Modul
#113Anfänger

Messung der Lichtintensität mit dem ESP32-LDR-Modul

Echtzeit-Anzeige des ADC-Rohwerts des LDR-Moduls und des anhand von Dunkel- und Hellreferenzwerten berechneten relativen Lichtwerts in Prozent im Serial Monitor. Dieser Prozentwert ist keine Lux-Messung. Vermittelt die Kalibrierungslogik des Moduls. Sollte idealerweise vor Projekt 10 durchgeführt werden, da es zur Festlegung des Schwellenwerts dient.

4.6(36)
55
Intelligente Bewässerungsstation
#83Fortgeschritten
Premium

Intelligente Bewässerungsstation

Ein Gärtner, der deine Pflanzen von selbst gießt, damit sie im Urlaub nicht vertrocknen. Ein Bodenfeuchtesensor misst, wie nass die Erde ist; wird sie trocken, lässt der Arduino die Wasserpumpe ein pa

5.0(42)
57
Reedschalter auslesen
#37Anfänger

Reedschalter auslesen

Hast du dich schon mal gefragt, wie der Magnetschalter in Tür- und Fensteralarmen funktioniert? Kommt ein Magnet in die Nähe des Reed-Relais-Moduls, schließt sich der winzige Schalter darin; der Ardui

4.4(21)
27
ESP32 Async-Webserver (mit IP-Anzeige auf dem LCD)
#129Fortgeschritten

ESP32 Async-Webserver (mit IP-Anzeige auf dem LCD)

In diesem Projekt verwandeln wir den ESP32 in einen asynchronen Webserver, den Sie über Ihr Smartphone oder Ihren Computer im selben WLAN-Netzwerk steuern können. Dank der ESPAsyncWebServer-Bibliothek kann der Server mehrere Anfragen gleichzeitig bearbeiten (im Gegensatz zum klassischen WebServer.h, der bei einer einzigen Anfrage blockiert). Sie können über den Browser die IP-Adresse des ESP32 öffnen und durch Drücken der ON/OFF-Schaltflächen (Routen /on und /off) die an GPIO 5 anges

4.8(16)
26
ESP32 Bewegungsalarmsystem (PIR + Buzzer + LED + Telegram)
#145Fortgeschritten
Premium

ESP32 Bewegungsalarmsystem (PIR + Buzzer + LED + Telegram)

Ein intelligentes Sicherheitsalarmsystem, das Buzzer und LED aktiviert, sobald der PIR-Sensor Bewegung erkennt, und gleichzeitig eine sofortige Benachrichtigung per Telegram an den Besitzer sendet. Ein 30-sekündiger Cooldown begrenzt die Häufigkeit wiederholter Alarme; dieser Mechanismus überprüft weder die Gültigkeit der PIR-Erkennungen noch verhindert er Fehlauslösungen. Geeignet für Heimsicherheit, Garagenüberwachung, Lagerräume oder Arbeitszimmer. Mit ESP32-CAM sind Foto-Benachrichtigungen m

0.0(0)
9