Arduino Gewächshaus-Steuerung: Sensoren, Bewässerung und Code
Smartes Gewächshaus mit Arduino: DHT22, Bodenfeuchte und LDR messen, Lüfter, Heizung, Pumpe und LEDs per Relais und MOSFET schalten, mit Hysterese und Code.
Eine Arduino Gewächshaus-Steuerung ist ein Automatisierungssystem, bei dem ein Arduino oder ESP32 Lufttemperatur, Luftfeuchtigkeit, Bodenfeuchte und Licht im Gewächshaus misst und Lüfter, Heizung, Wasserpumpe und Pflanzenlampen selbstständig schaltet. Das smarte Gewächshaus mit Arduino gehört zu den beliebtesten Themen für Schulprojekte, Wettbewerbe wie Jugend forscht und den Technikunterricht, weil man das Ergebnis sieht: Trocknet die Erde aus, startet die Pumpe; wird es drinnen warm, dreht sich der Lüfter; abends gehen die LEDs an. Und zwischen einem Modellgewächshaus aus einer Aufbewahrungsbox und einem echten Mini-Gewächshaus auf dem Balkon gibt es bei Schaltung und Code fast keinen Unterschied.
In dieser Anleitung beginnen wir damit, was Pflanzen überhaupt brauchen. Danach bauen wir Schritt für Schritt das Modellgewächshaus: Teileliste und ungefähre Kosten, die Verdrahtung der Sensoren (DHT22, kapazitiver Bodenfeuchtesensor, LDR) und der Aktoren (Lüfter, Heizung, Pumpe und LEDs über Relais und MOSFET), Stromversorgung und Pin-Tabelle. Dann erklären wir die Logik aus Schwellwert und Hysterese, die verhindert, dass die Relais ständig klicken, den kompletten Arduino-Code ohne delay() und das 16x2-LCD. In den letzten Abschnitten findest du die Überwachung per Handy mit dem ESP32, eine MicroPython-Version für den Raspberry Pi Pico, Tipps für Schul- und Wettbewerbspräsentationen und typische Fehler.





Wie funktioniert ein smartes Gewächshaus?
Jedes smarte Gewächshaus arbeitet mit derselben Schleife aus vier Schritten: messen, entscheiden, handeln, anzeigen. Die Sensoren messen die Umgebung: Wie warm ist es drinnen, wie feucht ist die Luft, ist die Erde trocken, reicht das Licht? Der Arduino vergleicht diese Werte mit deinen Regeln: „Steigt die Temperatur über 30 °C, Lüfter an“, „Fällt die Bodenfeuchte unter 35 %, gießen“. Die Aktoren setzen die Entscheidung um: Relais schalten Lüfter, Heizung und Pumpe, ein MOSFET regelt die Helligkeit des LED-Streifens. Zum Schluss zeigen LCD und Handy dir den aktuellen Zustand des Gewächshauses. Die Klimacomputer in echten Erwerbsgewächshäusern arbeiten genau mit dieser Schleife, nur mit mehr Sensoren und größeren Motoren.
| Was wird gemessen? | Sensor | Aktor | Regel (Beispiel) |
|---|---|---|---|
| Lufttemperatur | DHT22 | Lüfter und Heizung | Lüfter läuft ab 30 °C, Heizung schaltet bei 16 °C ein |
| Relative Luftfeuchtigkeit | DHT22 | Lüfter | Lüfter an bei 85 %, aus bei 75 % |
| Bodenfeuchte | Kapazitiver Bodenfeuchtesensor | Mini-Tauchpumpe | Gießt unter 35 % in Stößen von 3 Sekunden |
| Licht | LDR | LED-Streifen (MOSFET) | Bei Dunkelheit leuchten die LEDs höchstens 4 Stunden |
| Wasser im Tank | Schwimmerschalter | Pumpensperre | Ist der Tank leer, läuft die Pumpe nie |
Was brauchen Pflanzen? Zielwerte für Temperatur, Feuchte und Licht
Bevor du Regeln schreibst, musst du wissen, worauf du hinarbeitest. Die meisten Pflanzen wollen tagsüber und nachts unterschiedliche Temperaturen; eine leichte Abkühlung in der Nacht hilft der Pflanze, sich zu erholen. Bleibt die Luftfeuchtigkeit lange über 85 %, kondensiert Wasser auf den Blättern, und Pilzkrankheiten wie Schimmel und Falscher Mehltau breiten sich schnell aus. Deshalb läuft der Lüfter im Gewächshaus nicht nur zum Kühlen, sondern auch, um Feuchtigkeit abzuführen. Beim Licht wollen die meisten Gemüsejungpflanzen 14–16 Stunden pro Tag, brauchen aber auch eine Dunkelphase von mindestens 6–8 Stunden; LEDs die ganze Nacht brennen zu lassen schadet mehr, als es nützt. Die Werte unten sind ein guter Ausgangspunkt; passe sie an das an, was du anbaust.
| Pflanze | Tag | Nacht | Rel. Luftfeuchte | Hinweis |
|---|---|---|---|---|
| Tomate | 21–27 °C | 15–18 °C | 60–75 % | Über 32 °C können Blüten abfallen |
| Paprika | 21–29 °C | 16–20 °C | 60–75 % | Kälteempfindlicher als Tomaten |
| Salat und Spinat | 15–20 °C | 10–15 °C | 60–70 % | Schießt bei Hitze und langen Tagen früh |
| Erdbeere | 18–24 °C | 10–13 °C | 60–75 % | Bei hoher Feuchte steigt das Risiko für Grauschimmel |
| Jungpflanzen und Keimung | 20–25 °C | 18–20 °C | 70–85 % | Die Bodentemperatur ist wichtiger als die Lufttemperatur |
Das Modellgewächshaus bauen
Das einfachste und günstigste Gehäuse ist eine durchsichtige Kunststoff-Aufbewahrungsbox mit Deckel: Eine Box mit 40–60 Litern reicht für zwei oder drei Töpfe, ist wasserdicht und lässt sich mit dem Cuttermesser oder einer erhitzten Spitze leicht bohren. Für einen realistischeren Look baust du ein Gerüst aus Holzleisten und verkleidest es mit 2–3 mm starken Acrylglas- oder PETG-Platten; ein Gewächshaus mit Satteldach macht bei der Präsentation viel mehr her. Etwa 50×35×40 cm sind eine gute Startgröße. Egal welches Gehäuse du wählst: Deckel oder eine Seitenwand müssen sich öffnen lassen, denn du wirst hineingreifen, um zu gießen, den Sensor zu versetzen und Kabel zu ordnen.
- Elektronik außen: Im Gewächshaus ist es feucht, morgens kondensiert Wasser an den Wänden. Setz Arduino, Relaismodul und Netzteil in eine eigene Box außerhalb des Gewächshauses; drinnen bleiben nur Sensoren, Lüfter, Heizung, Pumpenschlauch und LEDs.
- Lüftung: Warme Luft steigt nach oben, also montierst du den Lüfter im oberen Teil einer der Schmalseiten so, dass er Luft nach außen bläst. In den unteren Teil der gegenüberliegenden Wand schneidest du eine Zuluftöffnung in Lüftergröße und klebst Fliegengitter darüber; so strömt frische Luft unten herein und warme, feuchte Luft oben hinaus.
- Heizung: Montiere die Heizung nah am Boden auf einer Aluminiumplatte oder einer Keramikfliese, mindestens 5 cm von den Kunststoffwänden und den Pflanzen entfernt. Die warme Luft steigt auf und zirkuliert durch das ganze Gewächshaus.
- LED-Beleuchtung: Kleb den LED-Streifen innen an den Deckel, 15–30 cm über die Pflanzen. Auf einem dünnen Aluminiumprofil gibt der Streifen seine Wärme besser ab, und der Kleber löst sich mit der Zeit nicht.
- Sensoren: Setz den DHT22 auf Pflanzenhöhe an eine Stelle ohne direkte Sonne und ohne direktes LED-Licht. Den Bodenfeuchtesensor steckst du in den Wurzelbereich, weg vom Topfrand. Der LDR darf die LEDs nicht sehen: Platziere ihn außerhalb des Gewächshauses auf dem Dach, Richtung Himmel.
- Wassertank: Ein Behälter mit 1–2 Litern reicht für Pumpe und Schwimmerschalter. Stell Untersetzer unter die Töpfe; überschüssiges Wasser sammelt sich dort, statt den Boden der Box zu fluten.
Teileliste und Kosten
| Teil | Anzahl | Aufgabe | Preisniveau |
|---|---|---|---|
| Arduino Uno R3 oder ESP32 DevKit | 1 | Gehirn des Gewächshauses | Mittel |
| DHT22 (AM2302) Temperatur- und Feuchtemodul | 1 | Lufttemperatur und Luftfeuchte | Niedrig |
| Kapazitiver Bodenfeuchtesensor (v1.2) | 1 (einer pro Topf) | Bodenfeuchte | Niedrig |
| LDR (GL5528) und 10-kΩ-Widerstand | 1 + 1 | Umgebungslicht | Sehr niedrig |
| Schwimmerschalter für den Wasserstand | 1 | Sperrt die Pumpe bei leerem Tank | Niedrig |
| 4-Kanal-Relaismodul 5 V (mit Optokoppler und JD-VCC) | 1 | Lüfter, Heizung und Pumpe | Niedrig |
| Logic-Level-N-Kanal-MOSFET (IRLZ44N), Widerstände 220 Ω und 100 kΩ | 1 Satz | Helligkeit des LED-Streifens (PWM) | Sehr niedrig |
| Mini-Tauchpumpe 3–6 V und 1 m Silikonschlauch | 1 | Bewässerung | Niedrig |
| 12-V-PC-Lüfter 80 mm | 1–2 | Lüftung und Entfeuchtung | Niedrig |
| 12-V-PTC-Heizelement (10–30 W) und Thermosicherung | 1 + 1 | Heizen | Niedrig |
| 12-V-LED-Streifen (Pflanzenlicht oder kaltweiß), ca. 1 m | 1 | Zusatzbeleuchtung | Niedrig |
| I2C-LCD 16x2 | 1 | Statusanzeige | Niedrig – mittel |
| Netzteil 12 V 5 A und Step-down-Wandler LM2596 | 1 + 1 | Stromversorgung | Mittel |
| Diode 1N5819 oder 1N4007, Kondensator 470 µF, Schraubklemmen, Jumperkabel | – | Schutz und Verbindungen | Sehr niedrig |
| Durchsichtige Box mit Deckel oder Acrylglasplatten, Töpfe, Untersetzer | – | Gewächshausgehäuse | Mittel |
Die Preise schwanken je nach Händler stark, deshalb hier ein grobes Budget statt genauer Zahlen. Ohne Board kostet die Basisversion (DHT22, Bodenfeuchtesensor, LDR, 2-Kanal-Relais, Pumpe und 5-V-Lüfter) meist etwa 25–40 €. Die Vollversion mit Heizung, LED-Streifen, LCD, 12-V-Netzteil, LM2596, Schwimmerschalter und Gehäuse liegt meist bei 70–120 €; den Großteil machen Board, Netzteil, Display und Gehäuse aus. Hast du ein Arduino-Starterkit, sind Board, Steckbrett, Kabel, LDR, Widerstände und oft auch das LCD schon vorhanden. Bei knappem Budget verschiebst du Heizung und LEDs auf eine zweite Ausbaustufe; Bewässerung und Lüftung allein sind schon ein sinnvolles, funktionierendes Projekt.
Sensoren: DHT22, Bodenfeuchtesensor und LDR
Für das Gewächshaus empfehlen wir den DHT22 (AM2302). Er ist etwas teurer als der DHT11, misst aber die Temperatur von −40 bis 80 °C auf ±0,5 °C und die Luftfeuchtigkeit über 0–100 % auf etwa ±2 %; der DHT11 ist nur zwischen 0 und 50 °C auf ±2 °C genau und erkennt keine Feuchte über 90 %. Da ein Gewächshaus morgens über 90 % Luftfeuchte und im Winter Minusgrade erreichen kann, passt der DHT22 viel besser. Der Sensor liefert höchstens alle 2 Sekunden einen Messwert, deshalb liest der Code ihn alle 2,5 Sekunden. Scheinen Sonne oder LEDs direkt auf den Sensor, erwärmt sich sein Gehäuse und er zeigt einige Grad mehr als die Luft; eine weiße, gelochte Abdeckung als Schatten verhindert das. Verdrahtung und Bibliothek findest du im Artikel DHT11 und DHT22 Temperatur- und Feuchtesensor.

Nimm für die Bodenfeuchte einen kapazitiven Sensor. Bei billigen resistiven Sensoren (YL-69, FC-28) berühren zwei Metallzinken direkt die Erde; werden sie dauerhaft versorgt, korrodieren sie durch Elektrolyse innerhalb weniger Wochen. Für ein System, das monatelang laufen soll, taugen sie nicht. Beim kapazitiven Sensor ist die Elektrode beschichtet, kein Metall berührt die Erde. Sein Ausgang ist analog und sinkt, je nasser die Erde wird: Am Uno liefert ein Sensor an der Luft etwa 500–600, in Wasser getaucht etwa 250–300. Diese Zahlen sind bei jedem Sensor anders. Lies deshalb vor dem Hochladen des Hauptprogramms die Werte deines Sensors an der Luft und im Wasser im seriellen Monitor ab und trag sie in die Konstanten SOIL_DRY_RAW und SOIL_WET_RAW ein. Der Code rechnet die beiden Werte mit map() in 0–100 % um. Mehr dazu im Artikel Bodenfeuchtesensor.
Für das Licht reicht der LDR (GL5528) aus deinem Set. Schließ den LDR mit einem 10-kΩ-Widerstand als Spannungsteiler an: 5V → LDR → A1 → 10 kΩ → GND. Mehr Licht senkt den Widerstand des LDR, der Wert an A1 steigt; auch diesen Wert rechnet der Code in 0–100 % um, anhand zweier Zahlen, die du im Dunkeln und in der Sonne misst. Ein LDR ist kein präzises Luxmeter, beantwortet aber zuverlässig die Frage „Ist es dunkel geworden, bewölkt oder sonnig?“. Für genauere Lichtmessung kannst du auf einen I2C-Lichtsensor wie den BH1750 umsteigen. Für die Berechnung des Teilers nutzt du das Werkzeug Spannungsteiler, Details stehen im Artikel LDR-Lichtsensor.
Aktoren: Relais oder MOSFET?
Ein Arduino-Pin liefert nur etwa 20 mA, Lüfter, Heizung, Pumpe und LED-Streifen ziehen dagegen Hunderte Milliampere oder sogar mehrere Ampere. Deshalb wird jede Last über ein Relais oder einen MOSFET geschaltet. Ein Relais ist ein mechanischer Schalter: Es schaltet eine Last in einem völlig getrennten Stromkreis ein und aus, egal ob Wechsel- oder Gleichstrom. Es kann aber nur ein und aus, klickt bei jedem Wechsel, und seine Kontakte haben eine begrenzte Lebensdauer. Ein MOSFET ist ein lautloser elektronischer Schalter; er funktioniert nur mit Gleichstromlasten, kann aber Hunderte Male pro Sekunde schalten und damit per PWM Helligkeit und Drehzahl regeln. In diesem Projekt nutzen wir ein 4-Kanal-Relaismodul für Heizung, Lüfter und Pumpe und einen MOSFET für die Helligkeit des LED-Streifens.
| Last | Typischer Wert | Treiber | Warum? |
|---|---|---|---|
| 12-V-PTC-Heizelement | 10–30 W, etwa 1–2,5 A | Relais (IN2) | Hoher Strom, nur Ein/Aus nötig |
| 12-V-Lüfter 80 mm | 0,1–0,2 A | Relais (IN1) oder MOSFET | Relais ist einfach; mit MOSFET geht auch PWM-Drehzahlregelung |
| Mini-Tauchpumpe 3–6 V | 0,1–0,25 A, beim Anlauf mehr | Relais (IN3) oder MOSFET mit Diode | Läuft in kurzen Stößen; Motorstörungen müssen entkoppelt werden |
| 12-V-LED-Streifen (5050, 60 LEDs/m) | Etwa 1,2 A pro Meter | Logic-Level-MOSFET | PWM-Helligkeitsregelung und lautloser Betrieb |

Je nach Schlauchhöhe fördert eine Mini-Tauchpumpe etwa 1–1,5 Liter pro Minute; ein Stoß von 3 Sekunden bringt also 50–75 ml Wasser in den Topf. Deshalb lassen wir die Pumpe nicht durchlaufen, „bis die Erde nass ist“, sondern in kurzen Stößen: 3 Sekunden gießen, 60 Sekunden warten, bis das Wasser eingezogen ist, dann neu messen. Würde der Sensor erneut gelesen, bevor das Wasser bei ihm ankommt, wirkte die Erde noch trocken und die Pumpe liefe, bis der Topf überläuft. Läuft die Pumpe trocken, wird sie heiß und ist nach wenigen Minuten defekt; der Schwimmerschalter im Tank sperrt die Pumpe, sobald das Wasser alle ist. Jedes Mal, wenn der Motor stoppt, erzeugt seine Spule eine Spannungsspitze in Gegenrichtung; eine in Sperrrichtung parallel zur Pumpe geschaltete Diode (Freilaufdiode 1N5819 oder 1N4007, Ring zur Plusseite) schützt Relaiskontakt und Arduino vor dieser Störung. Pumpenauswahl und Ansteuerung erklärt der Artikel Mini-Wasserpumpe.
Zum Heizen nimmst du ein 12-V-PTC-Heizelement. Bei PTC-Keramikelementen (positiver Temperaturkoeffizient) steigt der Widerstand mit der Temperatur, deshalb begrenzt sich ihre Oberflächentemperatur selbst auf einen festen Wert; das ist viel sicherer als ein offen glühender Heizdraht. In einem Kunststoffgehäuse wählst du ein Niedertemperaturmodell, dessen Oberfläche bei etwa 80 °C begrenzt wird. Ein 24-W-Heizelement zieht nach P = U × I bei 12 V 2 A; in den ersten Sekunden im kalten Zustand etwas mehr. Für das Licht kannst du einen rot-blauen Pflanzen-LED-Streifen oder einen kaltweißen LED-Streifen nehmen; Pflanzen nutzen für die Fotosynthese vor allem rotes (etwa 660 nm) und blaues Licht (etwa 450 nm). Steuere den Streifen mit einem Logic-Level-MOSFET wie dem IRLZ44N: Das Gate hängt über 220 Ω an D9 und über 100 kΩ an GND; Plus des Streifens an 12 V, Minus an den Drain des MOSFET, Source an GND. Standard-MOSFET-Module wie das IRF520 schalten bei 5 V Gatespannung nicht voll durch und werden bei Lasten von mehreren Ampere heiß; Details im Artikel MOSFET am Arduino. Strom und Leistung berechnest du mit dem Werkzeug Ohmsches Gesetz.
Stromversorgung: 12-V- und 5-V-Schiene
Die häufigsten Probleme in smarten Gewächshäusern („Der Arduino startet neu, wenn die Pumpe läuft“, „Auf dem LCD erscheinen seltsame Zeichen“) kommen von der Stromversorgung. Am saubersten ist es, aus einem einzigen 12-V-5-A-Netzteil zwei Schienen abzuleiten. Die 12-V-Schiene versorgt Heizung, Lüfter und LED-Streifen direkt und geht außerdem an die DC-Buchse des Arduino Uno. Dieselben 12 V speisen einen auf 5 V eingestellten LM2596-Step-down-Wandler; Relaisspulen, Pumpe und LCD hängen an dieser 5-V-Schiene. Ziehst du am Relaismodul den JD-VCC-Jumper, kommt der Spulenstrom komplett aus dem LM2596, und die Arduino-Seite lässt nur die LEDs der Optokoppler leuchten. Die Sensoren (DHT22, Bodenfeuchtesensor und LDR-Teiler) versorgst du dagegen vom eigenen 5V-Pin des Arduino: analogRead() misst relativ zu den 5 V des Boards, deshalb bleiben die Messwerte stabil, wenn die analogen Sensoren an derselben Spannung hängen. Verbinde unbedingt die GNDs von Netzteil, LM2596 und Arduino miteinander.
| Last | Schiene | Strom ca. |
|---|---|---|
| PTC-Heizung (24 W) | 12 V | 2 A (im kalten Zustand anfangs mehr) |
| LED-Streifen (1 m) | 12 V | 1–1,2 A |
| Zwei 80-mm-Lüfter | 12 V | 0,2–0,4 A |
| Arduino Uno und Sensoren (über die DC-Buchse) | 12 V | Etwa 0,06–0,08 A |
| LM2596-Eingang (bei 1 A auf der 5-V-Seite) | 12 V | Etwa 0,5 A |
| Relaismodul (drei Relais angezogen) | 5 V | 0,2–0,25 A |
| Mini-Tauchpumpe | 5 V | 0,1–0,25 A (beim Anlauf mehr) |
| I2C-LCD (Hintergrundbeleuchtung an) | 5 V | 20–30 mA |
Selbst wenn alles gleichzeitig läuft, liegt der Gesamtstrom bei etwa 4–4,5 A; ein Netzteil mit 12 V 5 A (60 W) lässt genug Reserve. In der Praxis laufen Heizung und Temperaturlüfter nie gleichzeitig, weil zwischen ihren Schwellen eine große Lücke liegt. Bevor du den LM2596 an die Schaltung anschließt, misst du seinen Ausgang mit dem Multimeter und stellst ihn mit dem Trimmpoti auf 5,0 V ein; im Auslieferungszustand kann er fast die vollen 12 V durchlassen. Den Arduino kannst du beim Hochladen per USB und im Betrieb über die DC-Buchse versorgen; beides gleichzeitig ist für den Uno kein Problem. Mehr dazu in der Anleitung Arduino Stromversorgung.
Verdrahtung und Pin-Tabelle
Die Tabelle unten zeigt die Pins, die die drei Programme dieser Anleitung nutzen. Am Uno haben wir den MOSFET für den LED-Streifen an D9 gehängt, weil dieser Pin PWM kann; am Uno gibt es PWM nur an D3, D5, D6, D9, D10 und D11. Schwimmerschalter und Relais brauchen kein PWM. Da das LCD nur den I2C-Bus (A4 und A5) nutzt, belegt es kaum Pins; am Uno bleiben A2, A3 und einige digitale Pins für einen zweiten Bodensensor oder einen Taster frei. Am ESP32 hängen die analogen Sensoren an ADC1-Pins (GPIO 34 und 35), die auch bei eingeschaltetem WLAN funktionieren. Die Pinbelegung deines Boards siehst du im Werkzeug Pinout.
| Verbindung | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| DHT22 DATA | D2 | GPIO 4 | GP15 |
| Schwimmerschalter (anderes Ende an GND) | D3 | GPIO 13 | GP14 |
| Relais IN3: Pumpe | D4 | GPIO 25 | GP18 |
| Relais IN1: Lüfter | D7 | GPIO 26 | GP16 |
| Relais IN2: Heizung | D8 | GPIO 27 | GP17 |
| MOSFET-Gate (über 220 Ω): LED | D9 | GPIO 18 | GP19 |
| Bodenfeuchtesensor AOUT | A0 | GPIO 34 | GP26 |
| Mittelpunkt des LDR-Teilers | A1 | GPIO 35 (Teiler an 3V3) | GP27 (Teiler an 3V3) |
| I2C-LCD SDA / SCL | A4 / A5 | GPIO 21 / 22 | GP4 / GP5 |
| Sensorversorgung | 5V | 3V3 | 3V3 |
Schwellwert und Hysterese: Warum klappern Relais?
Stell dir vor, du steuerst den Lüfter mit einer einzigen Schwelle: „Über 30 °C an, sonst aus“. Pendelt die Temperatur zwischen 29,9 und 30,1 °C (durch Sensorrauschen passiert das ständig), schaltet das Relais bei jeder Messung ein und aus. Relaiskontakte und Lüftermotor verschleißen, und bei der Heizung werden Leitungen und Netzteil bei jedem Einschalten unnötig belastet. Die Lösung heißt Hysterese: Du verwendest zwei getrennte Schwellen zum Ein- und Ausschalten. Der Lüfter startet bei 30 °C, stoppt aber erst, wenn die Temperatur auf 27 °C gefallen ist. In der 3 Grad breiten Totzone dazwischen behält das System seinen letzten Zustand. Raumthermostate von Heizungen und Kühlschränke funktionieren nach demselben Prinzip.
| Steuerung | Schaltet ein | Schaltet aus | Totzone |
|---|---|---|---|
| Lüfter (Temperatur) | ≥ 30 °C | ≤ 27 °C | 3 °C |
| Lüfter (Luftfeuchte) | ≥ 85 % | ≤ 75 % | 10 % |
| Heizung | ≤ 16 °C | ≥ 19 °C | 3 °C |
| Bewässerung | Boden ≤ 35 % | Boden ≥ 50 % | 15 % |
| LED-Beleuchtung | Licht ≤ 25 % | Licht ≥ 35 % oder nach 4 Stunden | 10 % |
Die Breite der Totzone ist ein Kompromiss: Ist sie zu schmal, schaltet das Relais weiterhin oft; ist sie zu breit, entfernt sich die Temperatur zu weit vom Ziel. 2–3 °C bei der Temperatur, 8–10 % bei der Luftfeuchte und 10–15 % bei der Bodenfeuchte sind ein guter Anfang. Zwischen 19 °C, wo die Heizung abschaltet, und 30 °C, wo der Lüfter startet, haben wir außerdem eine große Lücke gelassen, damit Heizung und Temperaturlüfter nie gegeneinander arbeiten. Im Code steckt die Hysterese in einer kleinen Funktion hysteresis(), damit du sie nicht für jede Steuerung neu schreiben musst: Ist die Einschaltschwelle größer als die Ausschaltschwelle, heißt das „beim Steigen einschalten“ (Lüfter); ist sie kleiner, „beim Fallen einschalten“ (Heizung, Bewässerung, LEDs). Willst du Ausreißer in den Sensordaten zusätzlich glätten, wirf einen Blick in den Artikel Sensordaten filtern.
Code-Aufbau: messen, entscheiden, handeln, anzeigen
Die wichtigste Regel im Gewächshaus-Code lautet: Keine Aufgabe wartet auf eine andere. Würdest du nach der Pumpe mit delay(60000) eine Minute warten, liefe in dieser Zeit weder der Lüfter, noch würde das Display aktualisiert. Deshalb besteht der Code aus kleinen Funktionen, die die Zeit mit millis() messen und jeweils für genau eine Aufgabe zuständig sind; loop() ruft sie tausende Male pro Sekunde nacheinander auf, und jede Funktion tut nur etwas, wenn ihre Zeit gekommen ist. Die Bewässerung ist ein kleiner Zustandsautomat mit drei Zuständen: warten (IDLE), gießen (PUMPING) und einziehen lassen (SOAKING). Alle Einstellungen stehen als Konstanten oben im Code, sodass du zum Ändern einer Schwelle nicht im Code suchen musst. Die Idee dahinter erklären die Artikel millis() und delay() und Zustandsautomat mit Arduino. Außerdem enthält der Code diese Schutzfunktionen:
- Sicherer Start: Der Wert für „aus“ wird auf die Relaispins geschrieben, bevor pinMode() aufgerufen wird; so ziehen die Relais beim Booten des Arduino nicht einmal kurz an.
- Sensorausfall: Lässt sich der DHT22 dreimal hintereinander nicht lesen, wechselt der Code in einen sicheren Zustand: Er schaltet die Heizung aus, lässt den Lüfter laufen und zeigt auf dem LCD „Sensor hatasi“ (Sensorfehler). Ein System, das die Temperatur nicht kennt, darf die Heizung nie eingeschaltet lassen.
- Tankschutz: Meldet der Schwimmerschalter einen leeren Tank, startet die Pumpe gar nicht erst, und eine laufende Pumpe stoppt sofort.
- Überlaufschutz: Erreicht die Bodenfeuchte in einem Gießzyklus trotz sechs Stößen keine 50 %, ist vielleicht der Sensor aus der Erde gerutscht oder der Schlauch abgegangen; der Code stoppt die Bewässerung und zeigt „Sulama hatasi“ (Bewässerungsfehler). Sobald die Erde wieder nass ist, verschwindet die Warnung von selbst.
- Datenaufzeichnung: Alle 10 Sekunden schreibt der Code die Messwerte als kommagetrennte Zeile (CSV) in den seriellen Monitor; diese Zeilen kannst du kopieren und in Excel Diagramme daraus zeichnen.
Aufbau und Test Schritt für Schritt
- Gehäuse vorbereiten: Löcher für Lüfter, Zuluft, Schlauch und Kabel schneiden und die Elektronikbox außerhalb des Gewächshauses platzieren.
- Stromschienen aufbauen: das 12-V-Netzteil an eine Schraubklemme anschließen, den LM2596 mit dem Multimeter auf 5,0 V einstellen und alle GNDs verbinden.
- Das I2C-LCD anschließen und einen Text ausgeben. Zeigt das Display nichts, probiere den Scanner-Sketch und das Kontrastpoti aus dem Artikel I2C-LCD.
- Die Sensoren einzeln hinzufügen und im seriellen Monitor testen: die Werte des DHT22, den Rohwert des Bodensensors an der Luft und im Wasser sowie den Wert des LDR im Dunkeln und in der Sonne notieren.
- Die Relais zuerst ohne Last testen und dabei auf ihre LEDs und das Klicken achten. Danach Lüfter, Pumpe (Tank gefüllt) und zuletzt die Heizung anschließen.
- Den LED-Streifen über den MOSFET anschließen und den analogWrite()-Wert ändern, um zu sehen, wie sich die Helligkeit ändert.
- Das Hauptprogramm hochladen, die notierten Kalibrierwerte in die Konstanten eintragen und das System einige Stunden unter Aufsicht laufen lassen: Wird falsch gegossen, klickt ein Relais ständig oder wird ein Bauteil zu heiß?
Kompletter Code für den Arduino Uno
Zum Kompilieren installierst du über den Bibliotheksverwalter die DHT sensor library von Adafruit (mit ihrer Abhängigkeit Adafruit Unified Sensor) und die Bibliothek LiquidCrystal I2C von Frank de Brabander; Wire ist in der Arduino IDE schon enthalten. Die Adresse des LCD ist meist 0x27, bei manchen Modulen 0x3F. Trag vor dem Hochladen deine gemessenen Kalibrierwerte in die Konstanten SOIL_DRY_RAW, SOIL_WET_RAW, LDR_DARK_RAW und LDR_BRIGHT_RAW ein. Öffnet dein Schwimmerschalter bei Wasser, statt zu schließen, setzt du TANK_OK auf HIGH; ist dein Relaismodul active HIGH, tauschst du die Werte von RELAY_ON und RELAY_OFF.
1#include <Wire.h>
2#include <LiquidCrystal_I2C.h>
3#include <DHT.h>
4
5// Pinler / Pins
6const byte DHT_PIN = 2, FLOAT_PIN = 3, PUMP_RELAY = 4, FAN_RELAY = 7, HEATER_RELAY = 8;
7const byte LED_PIN = 9; // MOSFET gate (PWM)
8const byte SOIL_PIN = A0, LDR_PIN = A1;
9
10// Kalibrasyon: kendi ölçümlerini yaz / Calibration: write your own readings
11const int SOIL_DRY_RAW = 520, SOIL_WET_RAW = 260; // havada ve suda / in air and in water
12const int LDR_DARK_RAW = 60, LDR_BRIGHT_RAW = 900; // karanlık ve güneş / dark and sunlight
13
14// Eşikler (açma, kapama) / Thresholds (on, off)
15const float FAN_ON_C = 30, FAN_OFF_C = 27; // sıcaklıkta fan / fan on heat
16const float HUM_ON = 85, HUM_OFF = 75; // nemde fan / fan on humidity
17const float HEAT_ON_C = 16, HEAT_OFF_C = 19; // ısıtıcı / heater
18const float SOIL_DRY = 35, SOIL_OK = 50; // sulama başla, dur / start, stop watering
19const float DARK_ON = 25, DARK_OFF = 35; // ışık % / light %
20
21// Zamanlar / Timing
22const unsigned long READ_MS = 2500; // DHT22: en az 2 sn / at least 2 s
23const unsigned long PUMP_MS = 3000; // tek sulama darbesi / one watering pulse
24const unsigned long SOAK_MS = 60000; // suyun yayılması / let the water soak in
25const byte MAX_PULSES = 6; // fazlası arıza / more means a fault
26const unsigned long EXTRA_LIGHT_MS = 4UL * 3600000UL; // günü 4 saat uzat / extend the day by 4 h
27const byte LED_LEVEL = 200; // LED parlaklığı 0-255 / LED brightness 0-255
28const byte RELAY_ON = LOW, RELAY_OFF = HIGH; // aktif LOW röle / active-LOW relay
29const byte TANK_OK = LOW; // şamandıra suyla kapanır / float closes with water
30
31DHT dht(DHT_PIN, DHT22);
32LiquidCrystal_I2C lcd(0x27, 16, 2);
33
34float tempC = NAN, hum = NAN, soil = 0, light = 0;
35byte dhtErrors = 0, pulses = 0, page = 0;
36bool fanByTemp = false, fanByHum = false, fanOn = false, heaterOn = false;
37bool needWater = false, pumpFault = false, isDark = false, ledOn = false, tankOk = true;
38unsigned long lastRead = 0, lastLcd = 0, lastLog = 0, pumpAt = 0, darkSince = 0;
39
40enum PumpState { IDLE, PUMPING, SOAKING };
41PumpState pumpState = IDLE;
42
43// onAt > offAt: yükselince aç (fan) / turn on when rising (fan)
44// onAt < offAt: düşünce aç (ısıtıcı) / turn on when falling (heater)
45bool hysteresis(bool state, float value, float onAt, float offAt) {
46 if (onAt > offAt) {
47 if (value >= onAt) return true;
48 if (value <= offAt) return false;
49 } else {
50 if (value <= onAt) return true;
51 if (value >= offAt) return false;
52 }
53 return state; // ölü bölgede durumu koru / keep state in the dead band
54}
55
56void setRelay(byte pin, bool on) {
57 digitalWrite(pin, on ? RELAY_ON : RELAY_OFF);
58}
59
60float readPercent(byte pin, int raw0, int raw100) {
61 long sum = 0;
62 for (byte i = 0; i < 10; i++) sum += analogRead(pin); // 10 ölçüm ortalaması / average of 10
63 long pct = map(sum / 10, raw0, raw100, 0, 100);
64 return constrain(pct, 0, 100);
65}
66
67void setup() {
68 Serial.begin(9600);
69 setRelay(PUMP_RELAY, false); pinMode(PUMP_RELAY, OUTPUT); // açılışta kapalı / off at boot
70 setRelay(FAN_RELAY, false); pinMode(FAN_RELAY, OUTPUT);
71 setRelay(HEATER_RELAY, false); pinMode(HEATER_RELAY, OUTPUT);
72 pinMode(LED_PIN, OUTPUT);
73 pinMode(FLOAT_PIN, INPUT_PULLUP);
74 dht.begin();
75 lcd.init();
76 lcd.backlight();
77 lcd.print(F("BlueGrays Sera"));
78 Serial.println(F("sn,sicaklik,nem,toprak,isik,fan,isitici,pompa,led")); // CSV başlığı / CSV header
79 delay(2000); // DHT22 açılış süresi / DHT22 start-up time
80 readSensors();
81 lastRead = millis();
82}
83
84void loop() {
85 unsigned long now = millis();
86 if (now - lastRead >= READ_MS) {
87 lastRead = now;
88 readSensors();
89 }
90 controlClimate();
91 controlLight(now);
92 controlPump(now);
93 updateLcd(now);
94 logCsv(now);
95}
96
97// 1) Ölç / Measure
98void readSensors() {
99 float t = dht.readTemperature();
100 float h = dht.readHumidity();
101 if (isnan(t) || isnan(h)) {
102 if (dhtErrors < 255) dhtErrors++; // okuma hatası / read error
103 } else {
104 tempC = t;
105 hum = h;
106 dhtErrors = 0;
107 }
108 soil = readPercent(SOIL_PIN, SOIL_DRY_RAW, SOIL_WET_RAW);
109 light = readPercent(LDR_PIN, LDR_DARK_RAW, LDR_BRIGHT_RAW);
110 tankOk = digitalRead(FLOAT_PIN) == TANK_OK;
111}
112
113// 2) Fan ve ısıtıcı / Fan and heater
114void controlClimate() {
115 if (dhtErrors >= 3) { // sensör yok: güvenli durum / no sensor: safe state
116 heaterOn = false;
117 fanByTemp = true;
118 } else {
119 fanByTemp = hysteresis(fanByTemp, tempC, FAN_ON_C, FAN_OFF_C);
120 fanByHum = hysteresis(fanByHum, hum, HUM_ON, HUM_OFF);
121 heaterOn = hysteresis(heaterOn, tempC, HEAT_ON_C, HEAT_OFF_C);
122 }
123 fanOn = fanByTemp || fanByHum;
124 setRelay(FAN_RELAY, fanOn);
125 setRelay(HEATER_RELAY, heaterOn);
126}
127
128// 3) LED aydınlatma / LED grow light
129void controlLight(unsigned long now) {
130 bool wasDark = isDark;
131 isDark = hysteresis(isDark, light, DARK_ON, DARK_OFF);
132 if (isDark && !wasDark) darkSince = now; // akşam oldu / dusk detected
133 ledOn = isDark && (now - darkSince < EXTRA_LIGHT_MS);
134 analogWrite(LED_PIN, ledOn ? LED_LEVEL : 0);
135}
136
137// 4) Sulama: darbe + bekleme / Watering: pulse + soak
138void controlPump(unsigned long now) {
139 needWater = hysteresis(needWater, soil, SOIL_DRY, SOIL_OK);
140 if (!needWater) {
141 pulses = 0;
142 pumpFault = false; // toprak ıslandı / soil is wet again
143 }
144 switch (pumpState) {
145 case IDLE:
146 if (needWater && tankOk && !pumpFault) {
147 if (pulses >= MAX_PULSES) {
148 pumpFault = true; // nem yükselmiyor / moisture is not rising
149 } else {
150 pumpState = PUMPING;
151 pumpAt = now;
152 pulses++;
153 }
154 }
155 break;
156 case PUMPING:
157 if (now - pumpAt >= PUMP_MS || !tankOk) {
158 pumpState = SOAKING;
159 pumpAt = now;
160 }
161 break;
162 case SOAKING:
163 if (now - pumpAt >= SOAK_MS) pumpState = IDLE;
164 break;
165 }
166 setRelay(PUMP_RELAY, pumpState == PUMPING);
167}
168
169// 5) LCD: üç sayfa / three pages
170void updateLcd(unsigned long now) {
171 if (now - lastLcd < 3000) return;
172 lastLcd = now;
173 page = (page + 1) % 3;
174 lcd.clear();
175 if (page == 0) {
176 lcd.print(F("Sicaklik: "));
177 if (isnan(tempC)) lcd.print(F("--")); else lcd.print(tempC, 1);
178 lcd.print('C');
179 lcd.setCursor(0, 1);
180 lcd.print(F("Hava nemi: %"));
181 if (isnan(hum)) lcd.print(F("--")); else lcd.print(hum, 0);
182 } else if (page == 1) {
183 lcd.print(F("Toprak: %"));
184 lcd.print(soil, 0);
185 lcd.setCursor(0, 1);
186 lcd.print(F("Isik: %"));
187 lcd.print(light, 0);
188 } else {
189 lcd.print(F("F:")); lcd.print(fanOn);
190 lcd.print(F(" I:")); lcd.print(heaterOn);
191 lcd.print(F(" P:")); lcd.print(pumpState == PUMPING);
192 lcd.print(F(" L:")); lcd.print(ledOn);
193 lcd.setCursor(0, 1);
194 if (dhtErrors >= 3) lcd.print(F("Sensor hatasi"));
195 else if (!tankOk) lcd.print(F("Depo bos!"));
196 else if (pumpFault) lcd.print(F("Sulama hatasi"));
197 else lcd.print(F("Sistem normal"));
198 }
199}
200
201// 6) Seri port CSV kaydı / Serial CSV log
202void logCsv(unsigned long now) {
203 if (now - lastLog < 10000) return;
204 lastLog = now;
205 Serial.print(now / 1000); Serial.print(',');
206 Serial.print(tempC, 1); Serial.print(',');
207 Serial.print(hum, 0); Serial.print(',');
208 Serial.print(soil, 0); Serial.print(',');
209 Serial.print(light, 0); Serial.print(',');
210 Serial.print(fanOn); Serial.print(',');
211 Serial.print(heaterOn); Serial.print(',');
212 Serial.print(pumpState == PUMPING); Serial.print(',');
213 Serial.println(ledOn);
214}| Funktion | Aufgabe | Wie oft? |
|---|---|---|
| readSensors() | Liest DHT22, Bodenfeuchte, LDR und Schwimmerschalter; rechnet Analogwerte aus dem Mittel von 10 Messungen in 0–100 % um | Alle 2,5 Sekunden |
| controlClimate() | Schaltet den Lüfter mit Temperatur- oder Feuchte-Hysterese und die Heizung mit Temperatur-Hysterese; bei Sensorausfall sicherer Zustand | In jedem Durchlauf |
| controlLight() | Schaltet die LEDs bei Dunkelheit per PWM ein und nach höchstens 4 Stunden aus | In jedem Durchlauf |
| controlPump() | Bewässerungsautomat: 3 s gießen, 60 s warten, neu messen; mit Tank- und Überlaufschutz | In jedem Durchlauf |
| updateLcd() | Wechselt zwischen drei Seiten: Luftwerte, Bodenfeuchte und Licht, Gerätezustände | Alle 3 Sekunden |
| logCsv() | Schreibt Messwerte und Zustände als CSV-Zeile in den seriellen Monitor | Alle 10 Sekunden |
Auf der ersten LCD-Seite stehen Temperatur und Luftfeuchte, auf der zweiten Bodenfeuchte und Lichtwert, auf der dritten die Zustände der Geräte: „F:1 I:0 P:0 L:1“ heißt, der Lüfter läuft, Heizung (I = ısıtıcı) und Pumpe sind aus und die LEDs leuchten. Die untere Zeile zeigt eine der Meldungen „Sistem normal“ (alles in Ordnung), „Depo bos!“ (Tank leer), „Sulama hatasi“ (Bewässerungsfehler) oder „Sensor hatasi“ (Sensorfehler); diese Texte kannst du im Code leicht übersetzen. Kompiliert belegt der Code etwa 31 % des Programmspeichers und 25 % des RAM des Uno; es bleibt also viel Platz für einen zweiten Bodensensor, einen Summer oder ein RTC-Uhrmodul. Weil der Uno keine echte Uhr hat, lautet die LED-Regel „nach der Dämmerung höchstens 4 Stunden“; so lassen sich kurze Wintertage gut verlängern. Sollen die LEDs jeden Tag zu festen Uhrzeiten leuchten, ergänze ein RTC-Modul oder wechsle zur ESP32-Version unten.
Mit dem ESP32 per Handy überwachen und gießen

Der Uno hat kein WLAN. Willst du den Zustand des Gewächshauses auf dem Handy sehen und aus der Ferne gießen, tauschst du das Gehirn gegen einen ESP32. Der folgende Code überträgt dieselbe Steuerlogik auf den ESP32 und startet einen kleinen Webserver. Ist dein Handy im selben WLAN und öffnest du im Browser die IP-Adresse aus dem seriellen Monitor, siehst du Temperatur, Luftfeuchte, Bodenfeuchte, Licht, den Tankzustand und ob jedes Gerät an oder aus ist; die Seite lädt sich alle 10 Sekunden neu. Der Knopf Water now (Jetzt gießen) lässt die Pumpe einmal 3 Sekunden laufen, wenn Wasser im Tank ist. Beim Start holt sich der ESP32 die Uhrzeit aus dem Internet (NTP); dadurch leuchten die LEDs nur zwischen 06:00 und 20:00 Uhr und nur bei Dunkelheit, und nachts ruhen die Pflanzen.
1#include <WiFi.h>
2#include <WebServer.h>
3#include <DHT.h>
4#include <time.h>
5
6const char* ssid = "AgAdi"; // Wi-Fi adın / your Wi-Fi name
7const char* password = "Sifre123"; // Wi-Fi şifren / your Wi-Fi password
8
9// Pinler / Pins
10const int DHT_PIN = 4, FLOAT_PIN = 13, PUMP_RELAY = 25, FAN_RELAY = 26, HEATER_RELAY = 27;
11const int LED_PIN = 18; // MOSFET gate (PWM)
12const int SOIL_PIN = 34, LDR_PIN = 35; // ADC1: Wi-Fi açıkken çalışır / works with Wi-Fi on
13
14// Kalibrasyon (0-4095): kendin ölç / Calibration (0-4095): measure your own
15const int SOIL_DRY_RAW = 2800, SOIL_WET_RAW = 1200;
16const int LDR_DARK_RAW = 200, LDR_BRIGHT_RAW = 3800;
17
18// Eşikler (açma, kapama) / Thresholds (on, off)
19const float FAN_ON_C = 30, FAN_OFF_C = 27, HUM_ON = 85, HUM_OFF = 75;
20const float HEAT_ON_C = 16, HEAT_OFF_C = 19, SOIL_DRY = 35, SOIL_OK = 50;
21const float DARK_ON = 25, DARK_OFF = 35;
22const int LIGHT_FROM = 6, LIGHT_TO = 20; // LED yalnız 06:00-20:00 / LEDs only 06:00-20:00
23
24const unsigned long READ_MS = 2500, PUMP_MS = 3000, SOAK_MS = 60000;
25const unsigned long EXTRA_LIGHT_MS = 4UL * 3600000UL; // saat yoksa yedek kural / fallback without a clock
26const int MAX_PULSES = 6, LED_LEVEL = 200;
27const int RELAY_ON = LOW, RELAY_OFF = HIGH; // aktif LOW röle / active-LOW relay
28const int TANK_OK = LOW; // şamandıra suyla kapanır / float closes with water
29
30DHT dht(DHT_PIN, DHT22);
31WebServer server(80);
32
33float tempC = NAN, hum = NAN, soil = 0, light = 0;
34int dhtErrors = 0, pulses = 0;
35bool fanByTemp = false, fanByHum = false, fanOn = false, heaterOn = false;
36bool needWater = false, pumpFault = false, isDark = false, ledOn = false, tankOk = true;
37unsigned long lastRead = 0, pumpAt = 0, darkSince = 0;
38
39enum PumpState { IDLE, PUMPING, SOAKING };
40PumpState pumpState = IDLE;
41
42bool hysteresis(bool state, float value, float onAt, float offAt) {
43 if (onAt > offAt) { // yükselince aç / turn on when rising
44 if (value >= onAt) return true;
45 if (value <= offAt) return false;
46 } else { // düşünce aç / turn on when falling
47 if (value <= onAt) return true;
48 if (value >= offAt) return false;
49 }
50 return state;
51}
52
53void setRelay(int pin, bool on) {
54 digitalWrite(pin, on ? RELAY_ON : RELAY_OFF);
55}
56
57float readPercent(int pin, int raw0, int raw100) {
58 long sum = 0;
59 for (int i = 0; i < 16; i++) sum += analogRead(pin); // 16 ölçüm ortalaması / average of 16
60 long pct = map(sum / 16, raw0, raw100, 0, 100);
61 return constrain(pct, 0, 100);
62}
63
64int hourNow() {
65 struct tm t;
66 if (!getLocalTime(&t, 0)) return -1; // saat henüz yok / time not set yet
67 return t.tm_hour;
68}
69
70void readSensors() {
71 float t = dht.readTemperature();
72 float h = dht.readHumidity();
73 if (isnan(t) || isnan(h)) {
74 dhtErrors++;
75 } else {
76 tempC = t;
77 hum = h;
78 dhtErrors = 0;
79 }
80 soil = readPercent(SOIL_PIN, SOIL_DRY_RAW, SOIL_WET_RAW);
81 light = readPercent(LDR_PIN, LDR_DARK_RAW, LDR_BRIGHT_RAW);
82 tankOk = digitalRead(FLOAT_PIN) == TANK_OK;
83}
84
85void controlClimate() {
86 if (dhtErrors >= 3) { // sensör yok: güvenli durum / no sensor: safe state
87 heaterOn = false;
88 fanByTemp = true;
89 } else {
90 fanByTemp = hysteresis(fanByTemp, tempC, FAN_ON_C, FAN_OFF_C);
91 fanByHum = hysteresis(fanByHum, hum, HUM_ON, HUM_OFF);
92 heaterOn = hysteresis(heaterOn, tempC, HEAT_ON_C, HEAT_OFF_C);
93 }
94 fanOn = fanByTemp || fanByHum;
95 setRelay(FAN_RELAY, fanOn);
96 setRelay(HEATER_RELAY, heaterOn);
97}
98
99void controlLight(unsigned long now) {
100 bool wasDark = isDark;
101 isDark = hysteresis(isDark, light, DARK_ON, DARK_OFF);
102 if (isDark && !wasDark) darkSince = now;
103 int h = hourNow();
104 if (h >= 0) ledOn = isDark && h >= LIGHT_FROM && h < LIGHT_TO; // saat kuralı / clock rule
105 else ledOn = isDark && (now - darkSince < EXTRA_LIGHT_MS); // yedek kural / fallback rule
106 analogWrite(LED_PIN, ledOn ? LED_LEVEL : 0);
107}
108
109void controlPump(unsigned long now) {
110 needWater = hysteresis(needWater, soil, SOIL_DRY, SOIL_OK);
111 if (!needWater) {
112 pulses = 0;
113 pumpFault = false;
114 }
115 if (pumpState == IDLE && needWater && tankOk && !pumpFault) {
116 if (pulses >= MAX_PULSES) {
117 pumpFault = true; // nem yükselmiyor / moisture is not rising
118 } else {
119 pumpState = PUMPING;
120 pumpAt = now;
121 pulses++;
122 }
123 } else if (pumpState == PUMPING && (now - pumpAt >= PUMP_MS || !tankOk)) {
124 pumpState = SOAKING;
125 pumpAt = now;
126 } else if (pumpState == SOAKING && now - pumpAt >= SOAK_MS) {
127 pumpState = IDLE;
128 }
129 setRelay(PUMP_RELAY, pumpState == PUMPING);
130}
131
132String row(const char* name, const String& value) {
133 return String("<tr><td>") + name + "</td><td><b>" + value + "</b></td></tr>";
134}
135
136String onOff(bool on) {
137 return on ? "ON" : "OFF";
138}
139
140void handleRoot() {
141 String html = "<!DOCTYPE html><html><head><meta charset='utf-8'>"
142 "<meta name='viewport' content='width=device-width,initial-scale=1'>"
143 "<meta http-equiv='refresh' content='10'><title>BlueGrays Sera</title>"
144 "<style>body{font-family:sans-serif;max-width:420px;margin:auto;padding:12px}"
145 "td{padding:8px;border-bottom:1px solid #ddd}"
146 "a{display:block;margin-top:16px;padding:16px;border-radius:10px;background:#2e7d32;"
147 "color:#fff;text-align:center;text-decoration:none;font-size:18px}</style>"
148 "</head><body><h2>BlueGrays Sera</h2><table>";
149 html += row("Sıcaklık / Temperature", String(tempC, 1) + " °C");
150 html += row("Hava nemi / Humidity", "%" + String(hum, 0));
151 html += row("Toprak nemi / Soil", "%" + String(soil, 0));
152 html += row("Işık / Light", "%" + String(light, 0));
153 html += row("Fan", onOff(fanOn));
154 html += row("Isıtıcı / Heater", onOff(heaterOn));
155 html += row("Pompa / Pump", onOff(pumpState == PUMPING));
156 html += row("LED", onOff(ledOn));
157 html += row("Depo / Tank", tankOk ? "OK" : "BOŞ / EMPTY");
158 if (pumpFault) html += row("Uyarı / Warning", "Sulama hatası / Watering fault");
159 html += "</table><a href='/water'>Şimdi sula / Water now</a></body></html>";
160 server.send(200, "text/html", html);
161}
162
163void handleWater() { // elle tek darbe / one manual pulse
164 if (pumpState == IDLE && tankOk) {
165 pumpState = PUMPING;
166 pumpAt = millis();
167 }
168 server.sendHeader("Location", "/");
169 server.send(303);
170}
171
172void setup() {
173 Serial.begin(115200);
174 setRelay(PUMP_RELAY, false); pinMode(PUMP_RELAY, OUTPUT);
175 setRelay(FAN_RELAY, false); pinMode(FAN_RELAY, OUTPUT);
176 setRelay(HEATER_RELAY, false); pinMode(HEATER_RELAY, OUTPUT);
177 pinMode(LED_PIN, OUTPUT);
178 pinMode(FLOAT_PIN, INPUT_PULLUP);
179 dht.begin();
180 WiFi.begin(ssid, password);
181 while (WiFi.status() != WL_CONNECTED) {
182 delay(500);
183 Serial.print('.');
184 }
185 Serial.println();
186 Serial.println(WiFi.localIP()); // bu adresi telefonda aç / open this address on your phone
187 configTime(3 * 3600, 0, "pool.ntp.org"); // Türkiye UTC+3; kendi saat dilimini yaz / set your own time zone
188 server.on("/", handleRoot);
189 server.on("/water", handleWater);
190 server.begin();
191 readSensors();
192 lastRead = millis();
193}
194
195void loop() {
196 server.handleClient();
197 unsigned long now = millis();
198 if (now - lastRead >= READ_MS) {
199 lastRead = now;
200 readSensors();
201 }
202 controlClimate();
203 controlLight(now);
204 controlPump(now);
205}Gegenüber dem Uno-Code ändert sich Folgendes: Der ADC des ESP32 hat 12 Bit und liefert Werte von 0 bis 4095, deshalb musst du neu kalibrieren; da die Sensoren an 3V3 hängen, sind auch die Rohwerte anders. Die Zeitzone wird in der Zeile configTime() eingestellt; wir haben 3 × 3600 Sekunden für die Türkei (UTC+3) eingetragen. In Deutschland ersetzt du die Zeile durch configTzTime("CET-1CEST,M3.5.0,M10.5.0/3", "pool.ntp.org"), das berücksichtigt auch die Sommerzeit. Gibt es kein Internet oder ist die Uhrzeit noch nicht geholt, fällt die LED-Regel auf die Uno-Regel „höchstens 4 Stunden“ zurück. Die Seite hat kein Passwort, also könnte jeder in deinem Heimnetz die Pumpe starten; ein einfaches Passwort mit der Funktion authenticate() der WebServer-Bibliothek ist eine gute Gewohnheit. Willst du auch am ESP32 ein LCD, übernimmst du die Funktion updateLcd() unverändert aus dem Uno-Code; SDA ist GPIO 21, SCL ist GPIO 22.
| Methode | Zugriff von unterwegs | Schwierigkeit | Am besten für |
|---|---|---|---|
| ESP32-Webserver (der Code dieser Anleitung) | Nein, nur im selben Netz | Mittel | Schulpräsentation, Vorführung ohne Internet |
| Blynk IoT | Ja | Leicht | Fertige Anzeigen, Diagramme und Benachrichtigungen |
| Telegram-Bot | Ja | Mittel | Warnungen wie „Tank leer“ und „Temperatur zu hoch“ |
| Google Tabellen | Ja | Mittel | Datenaufzeichnung über Wochen und Diagramme |
| MQTT und Home Assistant | Ja, mit Einrichtung | Fortgeschritten | Echte Haus- und Gartenautomation |
Für eine Schulpräsentation ist der ESP32-Webserver die sicherste Wahl: Er hängt von keinem Cloud-Dienst ab und läuft auch ohne Internet im Saal mit seinem eigenen Netz. Willst du auch von unterwegs nachsehen, ist Blynk IoT mit fertigen Anzeigen und Diagrammen der einfachste Weg. Für eine Nachricht aufs Handy, wenn der Tank leer ist oder die Temperatur gefährlich wird, lies die Anleitung ESP32 Telegram-Bot; um für deinen Bericht wochenlang Daten zu sammeln, ESP32 mit Google Tabellen; und um das Gewächshaus an eine echte Hausautomation anzubinden, MQTT und Home Assistant.
MicroPython-Version für den Raspberry Pi Pico
Dasselbe Gewächshaus kannst du auch mit einem Raspberry Pi Pico in MicroPython steuern. In der MicroPython-Firmware des Pico ist ein DHT-Treiber schon enthalten, du musst keine zusätzlichen Dateien kopieren. Analoge Eingänge sind nur GP26, GP27 und GP28, und read_u16() liefert Werte von 0 bis 65535; miss deine Kalibrierwerte entsprechend. Weil der Pico mit 3,3 V arbeitet, versorgst du die Sensoren aus 3V3 und das Relaismodul aus VBUS (den 5 V vom USB) oder aus der LM2596-Schiene. Der folgende Code enthält alle Regeln für Lüfter, Heizung, LEDs und Bewässerung und gibt die Werte in der Shell von Thonny aus. Speicherst du die Datei als main.py auf dem Pico, läuft das Board auch ohne Computer. Nutzt du den Pico W mit WLAN, kannst du die Methode aus dem Artikel Pico W Webserver ergänzen, um die Werte per Handy zu verfolgen.
1from machine import Pin, ADC, PWM
2import dht
3import time
4
5sensor = dht.DHT22(Pin(15)) # GP15: DHT22 DATA
6soil_adc = ADC(26) # GP26: toprak nem AOUT / soil moisture AOUT
7ldr_adc = ADC(27) # GP27: LDR bölücü (3V3) / LDR divider (3V3)
8tank = Pin(14, Pin.IN, Pin.PULL_UP) # şamandıra: suyla 0 / float switch: 0 with water
9fan = Pin(16, Pin.OUT, value=1) # aktif LOW röleler kapalı başlar / active-LOW relays start off
10heater = Pin(17, Pin.OUT, value=1)
11pump = Pin(18, Pin.OUT, value=1)
12led = PWM(Pin(19)) # MOSFET gate
13led.freq(1000)
14
15SOIL_DRY_RAW, SOIL_WET_RAW = 50000, 22000 # kendin ölç / measure your own
16LDR_DARK_RAW, LDR_BRIGHT_RAW = 2000, 60000
17EXTRA_LIGHT_MS = 4 * 3600 * 1000 # günü 4 saat uzat / extend the day by 4 h
18
19
20def percent(adc, raw0, raw100):
21 raw = sum(adc.read_u16() for _ in range(10)) // 10
22 pct = (raw - raw0) * 100 // (raw100 - raw0)
23 return max(0, min(100, pct))
24
25
26def hysteresis(state, value, on_at, off_at):
27 if on_at > off_at: # yükselince aç / turn on when rising
28 if value >= on_at:
29 return True
30 if value <= off_at:
31 return False
32 else: # düşünce aç / turn on when falling
33 if value <= on_at:
34 return True
35 if value >= off_at:
36 return False
37 return state # ölü bölge / dead band
38
39
40def relay(pin, on):
41 pin.value(0 if on else 1)
42
43
44t = h = None
45errors = pulses = 0
46fan_t = fan_h = heat_on = need_water = dark = led_on = False
47pump_state, pump_at, dark_since = "idle", 0, 0
48soil = light = 0
49tank_ok = True
50time.sleep(2) # DHT22 açılış süresi / DHT22 start-up time
51last_read = time.ticks_add(time.ticks_ms(), -2500)
52
53while True:
54 now = time.ticks_ms()
55 if time.ticks_diff(now, last_read) >= 2500: # 2,5 sn'de bir ölç / measure every 2.5 s
56 last_read = now
57 try:
58 sensor.measure()
59 t, h = sensor.temperature(), sensor.humidity()
60 errors = 0
61 except OSError:
62 errors += 1 # okuma hatası / read error
63 soil = percent(soil_adc, SOIL_DRY_RAW, SOIL_WET_RAW)
64 light = percent(ldr_adc, LDR_DARK_RAW, LDR_BRIGHT_RAW)
65 tank_ok = tank.value() == 0
66
67 if errors >= 3 or t is None: # güvenli durum / safe state
68 heat_on, fan_t = False, True
69 else:
70 fan_t = hysteresis(fan_t, t, 30, 27)
71 fan_h = hysteresis(fan_h, h, 85, 75)
72 heat_on = hysteresis(heat_on, t, 16, 19)
73 relay(fan, fan_t or fan_h)
74 relay(heater, heat_on)
75
76 was_dark = dark
77 dark = hysteresis(dark, light, 25, 35)
78 if dark and not was_dark:
79 dark_since = now # akşam oldu / dusk detected
80 led_on = dark and time.ticks_diff(now, dark_since) < EXTRA_LIGHT_MS
81 led.duty_u16(50000 if led_on else 0)
82
83 need_water = hysteresis(need_water, soil, 35, 50)
84 if not need_water:
85 pulses = 0
86 print("T", t, "N", h, "Toprak", soil, "Isik", light, "Pompa", pump_state,
87 "Depo OK" if tank_ok else "Depo BOS", "HATA" if pulses >= 6 else "")
88
89 # Sulama: 3 sn darbe, 60 sn bekleme / Watering: 3 s pulse, 60 s soak
90 if pump_state == "idle" and need_water and tank_ok and pulses < 6:
91 pump_state, pump_at = "pump", now
92 pulses += 1
93 elif pump_state == "pump" and (time.ticks_diff(now, pump_at) >= 3000 or not tank_ok):
94 pump_state, pump_at = "soak", now
95 elif pump_state == "soak" and time.ticks_diff(now, pump_at) >= 60000:
96 pump_state = "idle"
97 relay(pump, pump_state == "pump")
98 time.sleep_ms(100)Tipps für Schulprojekt und Wettbewerb
Smarte Gewächshäuser sind so beliebt, dass Jurys Dutzende ähnlicher Modelle sehen. Herausstechen wirst du nicht nur mit einem System, das funktioniert, sondern indem du eine Frage mit Messungen beantwortest. Bei einer Schulausstellung müssen Ziel, Methode und erwartetes Ergebnis klar sein; Forschungswettbewerbe wie Jugend forscht erwarten ein Vergleichsexperiment mit Daten. Eine gute Forschungsfrage für dieses Gewächshaus lautet: „Wie viel Wasser spart eine Bewässerung nach Bodenfeuchte im Vergleich zum Gießen jeden Tag zur gleichen Uhrzeit, und wie wirkt sich das auf das Pflanzenwachstum aus?“
- Zwei Gruppen bilden: Teil Jungpflanzen derselben Art und Größe in zwei Gruppen. Die eine gießt das Sensorsystem, die andere gießt du jeden Tag von Hand mit einer festen Menge; Licht und Temperatur sind für beide Gruppen gleich.
- Messen und aufzeichnen: Führ eine Tabelle mit der wöchentlichen Wassermenge (am Tank gemessen, in ml), der Pflanzenhöhe (cm) und der Zahl der Blätter. Die CSV-Ausgabe des Codes oder ein Protokoll in Google Tabellen liefert dir das Temperatur- und Feuchtediagramm gleich mit.
- Blockschaltbild zeichnen: Links die Sensoren, in der Mitte der Arduino, rechts die Aktoren; beschrifte die Pfeile mit Regelsätzen („Boden < 35 % → Pumpe“). Die Jury liest deinen Code nicht, aber an dieses Bild erinnert sie sich.
- Hysterese erklären: Zwei Diagramme, die zeigen, wie oft ein Lüfter mit einer Schwelle und einer mit Hysterese pro Stunde schaltet, zeigen der Jury die technische Seite deines Projekts am besten.
- Ablauf für die Live-Vorführung schreiben: Wärm den DHT22 in der Hand an, damit der Lüfter startet, steck den Bodensensor in einen trockenen Topf, um die Pumpenstöße zu zeigen, und deck den LDR mit der Hand ab, damit die LEDs angehen. Jede Vorführung sollte 10–20 Sekunden dauern.
- Bezug zum echten Leben herstellen: Sprich über echte Probleme wie Wasser- und Energieverbrauch in Gewächshäusern, Pilzkrankheiten durch zu hohe Luftfeuchte und die Arbeitsbelastung von Gärtnereien; zeig mit Zahlen, auf welches davon dein System antwortet.
- Plan B vorbereiten: Film das funktionierende System; nimm Ersatzkabel, eine Ersatzpumpe und ein Netzteil mit; schreib Kalibrierwerte und WLAN-Daten auf einen Zettel.
- Auf Jury-Fragen vorbereiten: Leg dir kurze Antworten zurecht auf „Was passiert, wenn ein Sensor ausfällt?“, „Was passiert bei Stromausfall mit den Pflanzen?“ und „Wie würdest du das auf ein echtes Gewächshaus übertragen?“. Der sichere Zustand und der Überlaufschutz im Code sind die besten Antworten darauf.
Häufige Fehler und Lösungen
| Symptom | Mögliche Ursache | Lösung |
|---|---|---|
| Der Arduino startet neu oder das LCD zeigt Unsinn, wenn die Pumpe läuft | Pumpe und Relais hängen am 5V-Pin des Arduino, Motorstörungen | Pumpe und Relaisspulen aus dem LM2596 versorgen, GNDs verbinden, Freilaufdiode und 470 µF an der Pumpe |
| Die Relais klicken ständig | Nur eine Schwelle oder verrauschte Messwerte | Getrennte Ein- und Ausschaltschwellen (Hysterese) nutzen und Analogwerte mitteln |
| Nach dem Abschalten der Pumpe fließt weiter Wasser | Saugheber-Effekt: Das Schlauchende liegt unter dem Wasserstand im Tank | Tank tiefer stellen oder oben in den Schlauch ein kleines Luftloch stechen |
| Bodenfeuchte immer 0 % oder immer 100 % | Falsche Kalibrierwerte oder AOUT am falschen Pin | Rohwert des Sensors an der Luft und im Wasser messen und in die Konstanten eintragen |
| Die LEDs blinken an und aus | Der LDR sieht das Licht der LEDs | LDR außerhalb des Gewächshauses mit Blick zum Himmel montieren |
| Der DHT22 liefert nan | Falscher Pin, kein Pull-up-Widerstand oder öfter als alle 2 Sekunden gelesen | Pin prüfen, ein Modul verwenden oder 10 kΩ zwischen DATA und VCC setzen |
| Die Temperatur ist zu hoch | Sonne oder LED-Licht scheint direkt auf den Sensor | Mit einer weißen, gelochten Abdeckung beschatten und weg von der Heizung setzen |
| Wassertropfen und Schimmel an den Wänden | Luftfeuchte zu hoch, Lüftung zu schwach | Feuchteschwelle senken, Zuluftöffnung vergrößern, weniger gießen |
| Am ESP32 spinnt der Bodenwert, sobald WLAN startet | Der Sensor hängt an einem ADC2-Pin | Auf einen ADC1-Pin zwischen GPIO 32 und 39 umstecken |
| Mit ESP32 fällt das Relais nie ab | 3,3-V-HIGH schaltet ein Active-LOW-Modul für 5 V nicht aus | JD-VCC trennen oder ein Relaismodul mit 3,3-V-Ansteuerung verwenden |
Ein smartes Gewächshaus vereint Sensoren auslesen, Kalibrieren, Entscheiden mit Hysterese, Relais und MOSFETs ansteuern, Stromversorgung planen und kabellose Überwachung in einem einzigen Projekt, und am Ende wächst etwas wirklich Lebendiges: eine Pflanze. Fang mit Bewässerung und Lüftung an, teste jedes Teil einzeln und ergänze dann Heizung, LEDs und Handy. In der BlueGrays-App findest du Schritt-für-Schritt-Projekte mit Schaltplänen und Code zur Temperatur- und Feuchtemessung mit dem DHT11, zur Lichtmessung mit einem LDR, eine smarte Bewässerungsstation und einen Temperaturlogger mit DHT22.
Häufige Fragen
Was braucht man für ein Arduino-Gewächshaus?
Für ein einfaches smartes Gewächshaus reichen ein Arduino Uno oder ESP32, ein DHT22 für Temperatur und Luftfeuchte, ein kapazitiver Bodenfeuchtesensor, ein LDR mit 10-kΩ-Widerstand, ein Relaismodul, eine Mini-Tauchpumpe und ein Lüfter. In der Vollversion kommen ein 12-V-PTC-Heizelement, ein über MOSFET gesteuerter LED-Streifen, ein I2C-LCD, ein Schwimmerschalter, ein 12-V-5-A-Netzteil und ein LM2596 dazu. Als Gehäuse ist eine durchsichtige Aufbewahrungsbox mit Deckel die einfachste und günstigste Lösung.
Wie funktioniert ein smartes Gewächshaus?
Ein smartes Gewächshaus arbeitet in der Schleife messen, entscheiden, handeln, anzeigen. Sensoren messen Temperatur, Luftfeuchte, Bodenfeuchte und Licht; der Arduino vergleicht die Werte mit Schwellen und schaltet Lüfter, Heizung, Pumpe und LEDs über Relais oder einen MOSFET. Die Ergebnisse erscheinen auf einem LCD und mit einem ESP32 auch auf dem Handy.
DHT11 oder DHT22 fürs Gewächshaus?
Nimm den DHT22. Der DHT11 ist nur zwischen 0 und 50 °C auf ±2 °C genau und erkennt keine Luftfeuchte über 90 %, im Gewächshaus kann die Feuchte morgens aber über 90 % steigen und die Temperatur im Winter unter null fallen. Der DHT22 misst von −40 bis 80 °C auf ±0,5 °C und die Feuchte auf etwa ±2 %, und sein Code ist fast identisch mit dem des DHT11.
Was kostet ein Arduino-Gewächshaus?
Die Preise hängen vom Händler ab, aber ohne Board kostet die Basisversion (DHT22, Bodenfeuchtesensor, LDR, Relais, Pumpe und Lüfter) meist etwa 25–40 €. Die Vollversion mit Heizung, LED-Streifen, LCD, 12-V-Netzteil und Gehäuse liegt bei etwa 70–120 €. Hast du schon ein Arduino-Starterkit, sinken die Kosten deutlich.
Wie überwache ich mein Gewächshaus per Handy?
Am einfachsten tauschst du das Gehirn gegen einen ESP32 und betreibst einen Webserver; im Browser deines Handys im selben WLAN siehst du die Werte und startest die Pumpe. Für den Zugriff von unterwegs eignet sich Blynk IoT, für Warnmeldungen ein Telegram-Bot und für die Langzeitaufzeichnung Google Tabellen.
Wie präsentiere ich ein smartes Gewächshaus bei Jugend forscht?
Zeig nicht nur ein funktionierendes Modell, sondern stell eine messbare Forschungsfrage; miss zum Beispiel mit zwei Pflanzengruppen über mehrere Wochen, wie viel Wasser sensorgesteuertes Gießen gegenüber zeitgesteuertem spart. Präsentiere Wasserverbrauch, Pflanzenhöhe und Temperatur- und Feuchteverläufe in Tabellen und Diagrammen, erkläre das System mit einem Blockschaltbild und bereite einen kurzen Ablauf für die Live-Vorführung vor.
Projekte, die du danach bauen kannst
Alle Projekte ansehen
Temperatur und Luftfeuchtigkeit mit DHT11
Wie warm ist dein Zimmer, und ist die Luft feucht oder trocken? Der DHT11-Sensor misst Temperatur und Luftfeuchtigkeit, und der Arduino schreibt die Werte auf ein zweizeiliges LCD und aktualisiert sie

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

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.

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

ESP32 DHT22 Temperatur und Luftfeuchtigkeit (mit LCD-Display)
Bei diesem Projekt werden die Umgebungstemperatur und die Luftfeuchtigkeit mit einem DHT22-Sensor gemessen und in Echtzeit auf einem 16x2 I2C-LCD angezeigt. Mithilfe der Adafruit-DHT-Bibliothek werden die Daten über das One-Wire-Protokoll vom Sensor ausgelesen. Dieses Projekt bildet die Grundlage für IoT-Wetterstationen, Smart-Home-Automatisierung oder Umgebungsüberwachungssysteme in Gewächshäusern. Die Kommunikation mit dem DHT22 erfolgt über den GPIO-4-Pin des ESP32.

ESP32 Temperatur-Datenlogger (DHT22 + DS1307 RTC + microSD + OLED)
Baue einen zeitgestempelten Temperaturlogger mit ESP32! Lese Temperatur/Feuchtigkeit vom DHT22 jede Minute, hole die aktuelle Zeit vom DS1307 RTC und protokolliere auf microSD-Karte als CSV. Das OLED zeigt live Temperatur (große Schrift), Luftfeuchtigkeit, Zeitstempel und Logzähler. Die /temp_log.csv-Datei auf der SD-Karte öffnet sich in Excel, Google Sheets oder Python pandas zur Analyse — perfekt für Gewächshausüberwachung, Raumtemperaturverfolgung, Laboraufzeichnung, Lebensmittellageru

ESP32 Intelligente Beleuchtung (PIR + LDR + Relais + OLED)
Verwandle deinen Flur, dein Badezimmer oder deine Speisekammer mit dem ESP32 in intelligente Beleuchtung! Mit einem PIR-Bewegungssensor, einem LDR-Lichtsensor und einem Relaismodul realisieren wir das klassische Szenario "Licht geht an, wenn im Dunkeln Bewegung erkannt wird" — bei Tageslicht bleibt das Licht trotz Bewegung aus, was tagsüber Energie spart. Das Licht bleibt 30 Sekunden lang an; bei anhaltender Bewegung wird der Timer zurückgesetzt und das Licht bleibt länger an. Das SSD1306 OLED-D
Weitere Artikel
BlueGrays-App
Diese Schaltung Schritt für Schritt auf dem Handy nachbauen
Schaltplan, Code und Teileliste auf einem Bildschirm. Über 200 Arduino-, ESP32- und Pico-Projekte zum Nachbauen.
Mit dem Handy scannen
Richte die Kamera auf den Code, dann öffnet sich der App-Store deines Handys.
oder im Store öffnen

