Nicht jeder besitzt einen grünen Daumen. Deshalb müssen Pflanzen aber nicht zwangsläufig vergammeln. Mit einem Arduino Microcontroller Board, einem Ethernet Shield, ein paar Sensoren und einem Sketch baut man sich eine effektive Pflanzenüberwachung zusammen, die per E-Mail warnt, wenn der Pflanze etwas fehlt.
Vorgeschichte
Vor ein paar Jahren hatte ich mir den Parrot Flower Power gekauft, um Vitaldaten einer meiner Lieblingspflanzen zu erhalten und sie vor einem frühen Tod zu schützen. Der Flower Power gab jedoch nach rund eineinhalb Jahren den Geist auf: Der Bodenfeuchtigkeitssensor war defekt. Außerdem arbeitet der Flower Power mit dem Nahbereichsfunk Bluetooth. Um Infos zum Zustand der Pflanze auf einem Smartphone zu erhalten, muss sich das Mobiltelefon in der Nähe des Flower Power befinden. Eine Fernüberwachung ist nicht möglich. Ein neuer Flower Power kam für mich deshalb nicht in Frage. Glücklicherweise konnte ich ihn zurückschicken und bekam von Amazon den Kaufpreis erstattet.
Das Geld investierte ich in einen Arduino Mega 2560, ein Ethernet Shield und Sensoren für Luft- und Bodentemperatur, Luft- und Bodenfeuchtigkeit sowie Helligkeit, um ein eigenes Pflanzenüberwachungssystem mit dem Namen „Strauchie-Bot“ zu bauen. Strauchie-Bot soll sicherstellen, dass sich die Pflanze per E-Mail meldet, sobald sie keine optimalen Bedingungen mehr hat und beispielsweise Wasser oder mehr Licht benötigt. Außerdem soll morgens und abends eine Zusammenfassung zum Status mit aktuellen Messwerten gesendet werden.
Basis und austauschbare Sensoreinheit
Kernstück des Strauchie-Bots ist ein Arduino Mega mit ATmega 2560 Microcontroller. Diese erweiterte Variante des Arduino Uno verfügt mit 54 digitalen und 16 analogen Ein-und Ausgängen über deutlich mehr In- und Output-Ports als das kleine Schwestermodell. Wichtiger ist jedoch der üppigere, 256 KB große Flash-Speicher für Programme und Variablen. Der größere Programmspeicher kann deutlich umfangreichere Sketches aufnehmen. Zum Vergleich: Der Arduino Uno verfügt lediglich über 32 KB Speicher. Der größere Speicher ist notwendig, da die Abfrage und Auswertung der sensorischen Daten, die textliche Aufbereitung sowie das Mailen den Sketch stark aufblähen und reichlich Variablen benötigt werden.
Zum Herstellen einer Internet-Verbindung, benötigt man ein Ethernet Shield. Möchte man lieber eine drahtlose WLAN-Verbindung ins Internet herstellen, dann muss man sich ein Wi-Fi Shield anschaffen. Das ist allerdings etwa sechsmal so teurer. Alternativ greift man auf ein preiswertes WLAN-Modul wie beispielsweise ein ESP8266 zurück. Im Projekt kommt ein ein Ethernet Shield zum Einsatz, das über den SPI-Bus kommuniziert und die entsprechenden Anschlüsse blockiert. Die übrigen Sensoren und Komponenten benutzen analoge und digitale Ports sowie den I2C-Bus. Der serielle I2C-Datenbus kann mit mehreren Slaves gleichzeitig kommunizieren. Doch dazu später mehr.
Arduino Mega und Ethernet Shield verschwinden in einem Kunststoffgehäuse mit Aussparungen für den Netzteilanschluss, Ethernet-Port und die USB-Buchse zum Programmieren. Zum Anschluss der Sensoreinheit dient eine 12-polige SUB-D-Buchse, die intern mit den passenden Ports des Arduinos verdrahtet ist. So kann die komplette Sensoreinheit sehr einfach angeschlossen und ausgetauscht werden, ohne umständlich Rumlöten zu müssen.
Insgesamt habe ich zwei Sensoreinheiten gebaut. Sie sind jeweils in einem kleinen Kunststoffgehäuse untergebracht und unterscheiden sich durch ihre LED-Statusanzeige und den Bodenfeuchtigkeitssensor. Das 12-adrige abgeschirmte Kabel ist mit einer Zugentlastung mit Knickschutz aus dem Gehäuse geführt, um Kabelbruch zu vermeiden.
LED-Ampel-Anzeige
In der ersten Sensoreinheit kommen drei LEDs in Ampelform als Statusanzeige zum Einsatz. Sie signalisieren, ob die Pflanzenbedingungen optimal sind (Grün), sich im kritischen Bereich befinden (Gelb) oder mindestens ein Parameter von den Minimalanforderungen für die Pflanze abweicht (Rot). Die zweite Sensoreinheit enthält eine einzelne RGB-LED, die je nach Zustand die entsprechende Farbe annimmt. Das bietet mehrere Vorteile: Denn die RGB-LED kann mehrere Farben darstellen und so weitere Zustände beispielsweise beim Hochfahren des Sensors oder bei einem Fehler der Internet-Verbindung anzeigen. Außerdem ist die einzelne LED weit oben im Gehäuse untergebracht und damit bei Blumentöpfen mit hohem Rand gut erkennbar. Im Gegensatz dazu sind die LEDs bei der Ampelform untereinander angeordnet, sodass die untere grüne LED unter Umständen schlechter zu sehen ist.
Zu beachten ist, dass die drei LEDs mit verschiedenen Spannungen arbeiten. Zum direkten Anschluss an den Arduino Mega, dessen digitale Ausgänge +5 Volt liefern, benötigt man entsprechende Vorwiderstände. Das gilt auch für die drei Farbkanäle der RGB-LED. Die Datenblätter der LEDs geben Auskunft über die Arbeitsspannung und Stromaufnahme, sodass man die Widerstandswerte einfach berechnen kann. Der Anschluss der RGB-LED erfolgt über drei Anoden an je einem digitalen PWM-Ausgang und über eine gemeinsame Kathode an Masse. Durch Pulsweitenmodulation wird dem jeweiligen RGB-Kanal ein Helligkeitswert zugewiesen, um die gewünschte Farbmischung zu erzielen.
Bodenfeuchtigkeit und -temperatur
Die erste Sensoreinheit besitzt einen einfachen Bodenfeuchtigkeitssensor, der im Wesentlichen aus einer Forke mit zwei Elektroden besteht, die man in die Erde steckt. Solche fertigen Sensoren kosten nur wenig mehr als zwei Euro. An ihnen ist eine Spannung angelegt, die je nach Wassergehalt im Boden höher oder niedriger ausfällt. Der Arduino Mega wertet die Spannung über einen analogen Eingang aus. Im Sketch wird die Spannung in einen prozentualen Bodenfeuchtigkeitswert überführt. Diese Art Feuchtigkeitssensor hat aber einen Haken: Die Spannung zwischen den beiden Elektroden führt im Boden zur Elektrolyse, sodass sich die Metallbeschichtung zersetzt und mit der Zeit zu fehlerhaften Messwerten führt.
Um das zu vermeiden, steckt in der verbesserten zweiten Sensoreinheit ein kapazitiv arbeitender Bodenfeuchtigkeitssensor mit ATtiny441 Mikroprozessor. Solche kapazitiven Sensoren sind schon für knapp neun Euro erhältlich. Andere Alternativen, wie beispielsweise die Bodenfeuchtigkeit über die Verdunstungsfeuchtigkeit mit einem preiswerten Luftfeuchtesensor in einem Röhrchen zu messen, lohnen deshalb nicht.
Der kapazitiv arbeitende Sensor besitzt ebenfalls Mess-Elektroden und muss in den Boden gesteckt werden. Er arbeitet allerdings berührungslos und die mit Lack überzogenen Elektroden kommen nicht in Kontakt mit der umgebenden Erde. Zur Elektrolyse kommt es deshalb nicht, die Elektroden bleiben unbeschädigt und der Sensor liefert verlässliche Daten und hält länger.
Das Prinzip der kapazitiven Bodenfeuchtigkeitsmessung basiert auf der Veränderung der Dielektrizitätszahl in Abhängigkeit des leitenden Materials, das die Elektroden umgibt. Dabei spielt in die Karten, dass die Dielektrizitätszahl von Wasser im Vergleich zu trockener Erde mit 80 zu 3,9 deutlich höher ausfällt. Der Feuchtigkeitsgehalt kann deshalb recht genau bestimmt werden. Die Kapazitätsänderung misst ein Oszillator. Die Frequenz des Oszillators gibt Kapazitätsänderungen fein abgestuft wieder, optimal also für eine genaue Bestimmung der Bodenfeuchtigkeit.
Das Auslesen der Daten mit dem Arduino erfolgt über den I2C-Bus des Bodenfeuchte-Sensors. Zum Anschluss an den Arduino werden lediglich vier Leitungen benötigt: +5 Volt, Masse, SDA und SCL. Für den Arduino-Sketch benötigt man die Funktionsbibliothek I2CSensor_Std, die einfache Funktionen enthält, um Bodenfeuchtigkeit in Prozent und zusätzlich die Bodentemperatur in Grad Celsius zu bestimmen, denn der verwendete Sensor enthält zusätzlich ein Temperaturmessmodul. Ein THT-Widerstand als Thermistor misst knapp unterhalb der Bodenoberfläche die Temperatur.
Um möglichst genaue Werte zu erhalten, muss man beide Module gegebenenfalls kalibrieren. Das sollte mit einem geeichten Bodenfeuchtigkeitsmessgerät und einem Thermometer geschehen. Im Projekt war die Abweichung allerdings so gering, dass keine Anpassung notwendig war. Ansonsten muss man im Sketch entsprechende Differenzfaktoren einbauen.
Luftfeuchtigkeit und -temperatur
Die Lufttemperatur und Luftfeuchtigkeit spielen für das Wohlfühlklima einer Pflanze eine entscheidende Rolle. Beide lassen sich sehr einfach mit dem Sensor DHT22/AM2302 erfassen, der schon für weniger als drei Euro zu haben ist. Um ihn korrekt auslesen zu können, ist nur noch ein 10 k Widerstand nötig. Für den Arduino existiert mit der Funktionsbibliothek Arduino DHT eine einfache Option zum Auslesen der Sensordaten. Die werden seriell über eine Datenleitung an einen digitalen Port des Arduino übertragen. Der DHT22/AM2302 arbeitet neben einer Spannung von 3,3 auch mit der im gesamten Projekt genutzten Spannung von 5 Volt. Die Toleranz beträgt bei der Luftfeuchtigkeit etwa +/- 2 %, bei der Temperatur muss man mit einer Abweichung von +/- 0,5 °C rechnen. Zum Kalibrieren benutzt man entsprechende Messgeräte und baut passende Differenzfaktoren im Sketch ein.
Helligkeit
Zur Helligkeitsmessung setzt man einen Fotowiderstand mit 50 kΩ zusammen mit einem etwa gleich großen Widerstand in einer Spannungsteiler-Schaltung ein. Die daran abfallende Spannung ändert sich je nach Lichteinfall. Die Spannungsänderung wird über einen analogen Eingang (A1) des Arduino Mega abgefragt. Die Kalibrierung des Sensors erfolgt mit einem Lux-Meter. Die analogen Werte müssen dabei umgerechnet werden, um halbwegs genaue Ergebnisse in Lux zu erhalten. Die Helligkeit wertet Strauchie-Bot für einen kompletten Tag-Nacht Zyklus über 24 Stunden aus. So kann festgestellt werden, ob die Pflanze im Tagesdurchschnitt genügend Licht bekommen hat.
Ermittlung der Messwerte und Abstimmung auf die Pflanze
Um die genaue Uhrzeit für ein regelmäßiges Abfragen der Messwerte zu erhalten, besitzt Strauchie-Bot ein RTC-Modul DS3231 mit Pufferbatterie, das über die Funktionsbibliothek DS323RTC angesprochen wird. Die Uhr geht allerdings recht ungenau, sodass täglich ein Abgleich über das Internet mit einem Zeit-Server über die Funktionsbibliothek TimeLib erfolgt. Das DS3231 hängt ebenfalls am I2C-Bus. Damit es zu keinen Kollisionen mit den Daten des Bodenfeuchtigkeitssensors am gleichen Bus kommt, müssen beide Module unterschiedlich adressiert sein. Die ebenfalls notwendigen Pull-Up-Widerstände bringen Uhrenmodul und Bodenfeuchtigkeitssensor bereits mit.
Der Arduino-Sketch fragt im 15-Minuten-Takt die Messwerte ab und vergleicht sie mit den minimalen und maximalen Wohlfühlwerten der Pflanze. Im Sketch sind sie als Konstanten für Boden- und Lufttemperatur, Boden- und Luftfeuchtigkeit sowie Helligkeit als Referenz hinterlegt. Befinden sich die Messerwerte außerhalb dieser Wohlfühlwerte, dann ändert sich die LED-Anzeige. Außerdem wird ein passender Text zusammengestellt, der einen Hinweis auf die Abweichung und die notwendige Aktion wie beispielsweise Gießen enthält. Zusätzlich sind alle Messwerte aufgelistet. Morgens und abends erstellt Strauchie-Bot automatisch eine Zusammenfassung mit dem aktuellen Pflanzenstatus.
E-Mail-Benachrichtigungen via SMTP2GO
Die Pflanze soll mitteilen können, wenn ihr etwas fehlt. Das funktioniert am einfachsten per Push-E-Mail an ein Mobiltelefon. Damit das klappt, ist Strauchie-Bot über ein Ethernet-Shield mit dem Internet verbunden. Das Shield benutzt den SPI-Bus (MOSI (51), MISO (50) und SCK (52)) zur seriellen Kommunikation mit dem Arduino, blockiert ansonsten aber keine weiteren Anschlüsse.
Um möglichst einfach und ohne große Ressourcen E-Mails versenden zu können, kommt der SMTP-Dienst SMTP2GO zum Einsatz. Der Dienst ist in der Basisvariante kostenfrei. Bis zu 25 E-Mails pro Stunde und 1000 E-Mails pro Monat können damit versendet werden. Das reicht problemlos für Strauchie-Bot aus. Ausfälle gab es im Betrieb keine. Im Schnitt versendet Strauchie-Bot nicht mehr als vier E-Mails pro Tag.
Im Sketch müssen lediglich die verschlüsselten Zugangsdaten zum Dienst und die Empfänger- und Absender-E-Mail-Adresse angeben werden. Die Verschlüsselung der Zugangsdaten erfolgt über Base64 Encode. E-Mail-Betreff und -Inhalt generiert Strauchie-Bot selbst aus den Messergebnissen und den ermittelten Bedürfnissen der Pflanze.
Arduino-Sketch
Den Sketch überträgt man mit der Arduino-Software via USB auf den Arduino Mega 2560. Der Sketch ist noch nicht final und wird ständig verbessert. Wer mitarbeiten möchte, ist herzlich dazu eingeladen, ihn zu optimieren.
#include "Ethernet.h" #include "EthernetUdp.h" #include "Wire.h" #include "DHT.h" #include "I2CSensor_std.h" #include "DS3232RTC.h" #include "time.h" #include "TimeLib.h" #include "SPI.h" const byte ledrot=7; const byte ledgruen=5; const byte ledblau=6; const byte aus=0; const byte rot=1; const byte gelb=2; const byte gruen=3; const byte blau=4; const byte rotanteil=150; const byte gruenanteil=5; const byte blauanteil=100; const byte dunkel=0; const byte luftfeuchtigkeit_temperatur=8; const float luftfeuchtigkeit_min=55; const float luftfeuchtigkeit_max=90; const float temperatur_min=16; const float temperatur_max=28; const float helligkeit_min=800; // 1000 Lux const float helligkeit_max=1020; // 2700 Lux const float bodenfeuchtigkeit_min=15; const float bodenfeuchtigkeit_max=48; const float bodentemperatur_min=10; const float bodentemperatur_max=40; const int NTP_PACKET_SIZE = 48; const unsigned int MAX_INPUT = 32; boolean start_ok=false; boolean helligkeitproblem=false; boolean luftfeuchteproblem=false; boolean temperaturproblem=false; boolean bodenfeuchteproblem=false; boolean bodentemperaturproblem=false; boolean tageszusammenfassung_abgeschickt=false; boolean tweet_abgeschickt=false; boolean messung_erfolgt=false; boolean erster_helligkeitsdurchlauf=false; boolean SetAlarm=false; byte letztertag=0; byte mac[]={0xDE,0xAD,0xBE,0xEF,0xFE,0xED}; byte packetBuffer[NTP_PACKET_SIZE]; int port=2525; int timeZone=1; int helligkeitszaehler=0; uint16_t CapacitanceHigh; uint16_t CapacitanceLow; float durchschnittshelligkeit=0; float helligkeitsmesswert=0; float helligkeitsarray[96]={0}; float gesamthelligkeit=0; float durchschnitt=0; char server[]="mail.smtp2go.com"; EthernetUDP Udp; I2CSensor sensor (0x71); unsigned int localPort = 8888; IPAddress timeServer(132,163,4,101); IPAddress ip(192,168,178,47); IPAddress gateway(192,168,178,1); IPAddress subnet(255,255,255,0); DHT dht; EthernetClient client; void setup() { Wire.begin(); Serial.begin(9600); sensor.begin(); pinMode(ledrot,OUTPUT); pinMode(ledgruen,OUTPUT); pinMode(ledblau,OUTPUT); pinMode(4,OUTPUT); digitalWrite(4,HIGH); Ethernet.begin(mac,ip,gateway,gateway,subnet); dht.setup(luftfeuchtigkeit_temperatur); setSyncProvider(RTC.get); if (Ethernet.begin(mac) == 0) { while (1) { led_schalten(blau); Serial.println("Fehler beim Konfigurieren des Ethernet über DHCP!"); delay(10000); } } Udp.begin(localPort); } boolean zeitsync_notwendig(byte aktuellertag) { if (aktuellertag!=letztertag) { letztertag=aktuellertag; return(true); } else { return(false); } } boolean sommerzeit(int s_jahr, byte s_monat, byte s_tag, byte s_stunde, byte s_zeitzone) { if (s_monat<3 || s_monat>10) return false; if (s_monat>3 && s_monat<10) return true; if (s_monat==3 && (s_stunde + 24 * s_tag)>=(1+s_zeitzone+24*(31-(5*s_jahr/4+4) % 7)) || s_monat==10 && (s_stunde+24*s_tag)<(1+s_zeitzone+24*(31-(5*s_jahr/4+1) % 7))) { return true; } else { return false; } } void led_schalten(byte farbe) { switch(farbe) { case 0: analogWrite(ledrot,dunkel); analogWrite(ledgruen,dunkel); analogWrite(ledblau,dunkel); break; case 1: analogWrite(ledrot,rotanteil); analogWrite(ledgruen,dunkel); analogWrite(ledblau,dunkel); break; case 2: analogWrite(ledrot,rotanteil); analogWrite(ledgruen,gruenanteil); analogWrite(ledblau,dunkel); break; case 3: analogWrite(ledrot,dunkel); analogWrite(ledgruen,gruenanteil); analogWrite(ledblau,dunkel); break; case 4: analogWrite(ledrot,dunkel); analogWrite(ledgruen,dunkel); analogWrite(ledblau,blauanteil); break; } } void zeit_setzen(time_t ntpzeit) { setTime(ntpzeit); RTC.set(now()); } time_t getNtpTime() { while (Udp.parsePacket() > 0); sendNTPpacket(timeServer); uint32_t beginWait = millis(); while (millis() - beginWait < 1500) { int size = Udp.parsePacket(); if (size >= NTP_PACKET_SIZE) { Udp.read(packetBuffer, NTP_PACKET_SIZE); unsigned long secsSince1900; secsSince1900 = (unsigned long)packetBuffer[40] << 24; secsSince1900 |= (unsigned long)packetBuffer[41] << 16; secsSince1900 |= (unsigned long)packetBuffer[42] << 8; secsSince1900 |= (unsigned long)packetBuffer[43]; return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR; } } return 0; } void sendNTPpacket(IPAddress &address) { memset(packetBuffer, 0, NTP_PACKET_SIZE); packetBuffer[0] = 0b11100011; packetBuffer[1] = 0; packetBuffer[2] = 6; packetBuffer[3] = 0xEC; packetBuffer[12] = 49; packetBuffer[13] = 0x4E; packetBuffer[14] = 49; packetBuffer[15] = 52; Udp.beginPacket(address, 123); Udp.write(packetBuffer, NTP_PACKET_SIZE); Udp.endPacket(); } boolean isValidNumber(String str) { for (byte i = 0; i < str.length(); i++) { if (isDigit(str.charAt(i))) return true; } return false; } void handleReceivedMessage(const char *msg) { if (strcmp(msg, "setAlarm") == 0) { SetAlarm = true; Serial.println("Bitte einen Wert zwischen 0 und 100 eingeben."); } else if (SetAlarm) { if (isValidNumber(msg)) { if ( (atoi(msg) >= 0) && (atoi(msg) <= 100) ) { Serial.print("Alarm setzen "); Serial.println(atoi(msg), DEC); if (sensor.setAlarmOn(atoi(msg))) Serial.println("... Fertig!"); else Serial.println("... Fehler!"); } else { if (atoi(msg) < 0) Serial.println("Fehler! Wert muss größer oder gleich Null sein!"); if (atoi(msg) > 100) Serial.println("Fehler! Wert muss kleiner oder gleich 100 sein!"); } } else { Serial.println("Fehler! Kein gültiger Wert!"); } SetAlarm = false; } else if (strcmp(msg, "getAlarm") == 0) { Serial.println("Get Alarm"); Serial.print(sensor.getAlarmOn(), DEC); Serial.println(" %"); } else if (strcmp(msg, "setL") == 0) { Serial.println("Set Low"); sensor.setCalibrateLow(); } else if (strcmp(msg, "setH") == 0) { Serial.println("Set High"); sensor.setCalibrateHigh(); } else if (strcmp(msg, "reset") == 0) { Serial.println("Reset Sensor"); sensor.restart(); } else Serial.println("Fehler! Befehl nicht gefunden!"); Serial.println(); } void HandleIncomingByte (const byte inByte) { static char input_line [MAX_INPUT]; static unsigned int input_pos = 0; switch (inByte) { case '\n': input_line [input_pos] = 0; handleReceivedMessage (input_line); input_pos = 0; break; case '\r': break; default: if (input_pos < (MAX_INPUT - 1)) input_line [input_pos++] = inByte; break; } } float helligkeit() { byte i; durchschnittshelligkeit=0; helligkeitsmesswert=0; for(i=1; i<10; i++) { delay(300); helligkeitsmesswert=analogRead(A1); if (helligkeitsmesswert<0) { helligkeitsmesswert=0; } durchschnittshelligkeit=durchschnittshelligkeit+helligkeitsmesswert; } return(durchschnittshelligkeit/10); } float durchschnittsluminanz(float aktuellehelligkeit) { byte i; gesamthelligkeit=0; durchschnitt=0; if (helligkeitszaehler<96) { helligkeitszaehler++; helligkeitsarray[helligkeitszaehler]=aktuellehelligkeit; for(i=1; i<96; i++) { gesamthelligkeit=gesamthelligkeit+helligkeitsarray[i]; } if (!erster_helligkeitsdurchlauf) { durchschnitt=gesamthelligkeit/helligkeitszaehler; } else { durchschnitt=gesamthelligkeit/96; } } else { if (helligkeitszaehler==96) { helligkeitszaehler=1; gesamthelligkeit=0; durchschnitt=0; helligkeitsarray[helligkeitszaehler]=aktuellehelligkeit; for(i=1; i<96; i++) { gesamthelligkeit=gesamthelligkeit+helligkeitsarray[i]; } durchschnitt=gesamthelligkeit/96; erster_helligkeitsdurchlauf=true; } } return(durchschnitt); } float luftfeuchtigkeit() { byte i; float durchschnittsluftfeuchtigkeit=0; for(i=1; i<10; i++) { delay(dht.getMinimumSamplingPeriod()); durchschnittsluftfeuchtigkeit=durchschnittsluftfeuchtigkeit+dht.getHumidity(); } return(durchschnittsluftfeuchtigkeit/10); } float temperatur() { byte i; float durchschnittstemperatur=0; for(i=1; i<10; i++) { delay(dht.getMinimumSamplingPeriod()); durchschnittstemperatur=durchschnittstemperatur+(dht.getTemperature()+2); } return(durchschnittstemperatur/10); } float bodenfeuchtigkeit() { byte i; int durchschnittsbodenfeuchtigkeit=0; for(i=1; i<10; i++) { while (Serial.available () > 0) { HandleIncomingByte (Serial.read ()); } durchschnittsbodenfeuchtigkeit=durchschnittsbodenfeuchtigkeit+sensor.getCapacitanceProz(); if (i<10) { delay(1000); } } return(durchschnittsbodenfeuchtigkeit/10); } float bodentemperatur() { byte i; float durchschnittsbodentemperatur=0; for(i=1; i<10; i++) { while (Serial.available () > 0) { HandleIncomingByte (Serial.read ()); } durchschnittsbodentemperatur=durchschnittsbodentemperatur+(sensor.getTemperature() / (float)10); if (i<10) { delay(1000); } } return(durchschnittsbodentemperatur/10); } boolean startsensorcheck() { boolean check_luftfeuchtigkeit_temperatur=false; boolean check_helligkeit=false; boolean check_bodenfeuchtigkeit=false; boolean check_bodentemperatur=true; boolean check_rtc=false; led_schalten(rot); if(timeStatus() != timeSet) check_rtc=false; else check_rtc=true; delay (2000); led_schalten(gelb); if (analogRead(A1) >= 0) { check_helligkeit=true; } else { check_helligkeit=false; } if (isnan(dht.getHumidity()) || isnan(dht.getHumidity())) { check_luftfeuchtigkeit_temperatur=false; } else { check_luftfeuchtigkeit_temperatur=true; } if (sensor.getCapacitanceProz() >= 0) { check_bodenfeuchtigkeit=true; } else { check_bodenfeuchtigkeit=false; } if (sensor.getTemperature() / (float)10 >= 0) { check_bodentemperatur=true; } else { check_bodentemperatur=false; } delay (2000); if ((check_helligkeit) && (check_luftfeuchtigkeit_temperatur) && (check_bodenfeuchtigkeit) && (check_bodentemperatur) && (check_rtc)) { led_schalten(gruen); return(true); } else { led_schalten(rot); return(false); } } byte email_senden(char Betreff[],char Nachricht[]) { byte thisByte = 0; byte respCode; if (client.connect(server,port) == 1) { Serial.println(F("Verbindung zum E-Mail-Server hergestellt!")); } else { Serial.println(F("Verbindung zum E-Mail-Server fehlgeschlagen!")); return 0; } if(!eRcv()) return 0; client.println("EHLO xxx.xxx.xxx.xx"); // Lokale IP des Ethernet Shield if(!eRcv()) return 0; client.println("auth login"); if(!eRcv()) return 0; client.println("XXXXX"); // Kodierter SMTP2GO-Zugang if(!eRcv()) return 0; client.println("XXXXX"); // Kodierter SMTP2GO-Zugang if(!eRcv()) return 0; client.println("MAIL From: <strauchie@domain.de>"); if(!eRcv()) return 0; client.println("RCPT To: <empfaenger@domain.de>"); if(!eRcv()) return 0; client.println("DATA"); if(!eRcv()) return 0; client.println("To: Vorname Nachname <empfaenger@domain.de>"); client.println("From: Strauchie <strauchie@domain.de>"); client.println(Betreff); client.println(Nachricht); client.println("."); if(!eRcv()) return 0; client.println("QUIT"); if(!eRcv()) return 0; client.stop(); return 1; } byte eRcv() { byte respCode; byte thisByte; int loopCount = 0; while (!client.available()) { delay(1); loopCount++; if(loopCount > 10000) { client.stop(); return 0; } } respCode = client.peek(); while (client.available()) { thisByte = client.read(); } if (respCode >= '4') { efail(); return 0; } return 1; } void efail() { byte thisByte = 0; int loopCount = 0; client.println(F("QUIT")); while (!client.available()) { delay(1); loopCount++; if (loopCount > 10000) { client.stop(); return; } } while (client.available()) { thisByte = client.read(); } client.stop(); } void warnblinken() { led_schalten(rot); delay(500); led_schalten(aus); delay(500); } boolean tageszusammenfassung_senden(byte tageszusammenfassungsstunde) { if ((tageszusammenfassungsstunde==10) || (tageszusammenfassungsstunde==18)) { if (!tageszusammenfassung_abgeschickt) { tageszusammenfassung_abgeschickt=true; return(true); } else { return(false); } } else { tageszusammenfassung_abgeschickt=false; return(false); } } boolean messung_starten(byte messungminute) { if ((messungminute==5) || (messungminute==20) || (messungminute==35) || (messungminute==50)) { if (!messung_erfolgt) { messung_erfolgt=true; return(true); } else { return(false); } } else { messung_erfolgt=false; return(false); } } void auswertung(byte n_tag, byte n_monat, int n_jahr, byte n_stunde, byte n_minute, byte n_sekunde, float n_helligkeit, float n_luftfeuchtigkeit, float n_temperatur, float n_bodenfeuchtigkeit, float n_bodentemperatur) { char speicher[5]=""; char emailwarnungbetreff[50]=""; char emailwarnungbetreffhelligkeit[50]=""; char emailwarnungbetreffluftfeuchte[50]=""; char emailwarnungbetrefftemperatur[50]=""; char emailwarnungbetreffbodenfeuchte[50]=""; char emailwarnungbetreffbodentemperatur[50]=""; char tageszusammenfassungbetreff[50]=""; char emailwarnung[180]=""; char emailwarnunghelligkeit[180]=""; char emailwarnungluftfeuchte[180]=""; char emailwarnungtemperatur[180]=""; char emailwarnungbodenfeuchte[180]=""; char emailwarnungbodentemperatur[180]=""; char tageszusammenfassung[180]=""; if ((n_helligkeit <= helligkeit_min) && (!helligkeitproblem)) { strcat(emailwarnungbetreffhelligkeit,"Subject: Strauchie: Helligkeit zu niedrig\r\n"); dtostrf(n_helligkeit,4,1,speicher); strcat(emailwarnunghelligkeit,"Die Helligkeit ist zu niedrig: "); strcat(emailwarnunghelligkeit,speicher); strcat(emailwarnunghelligkeit," Lux."); helligkeitproblem=true; } else { if ((n_helligkeit >= helligkeit_max) && (!helligkeitproblem)) { strcat(emailwarnungbetreffhelligkeit,"Subject: Strauchie: Helligkeit zu hoch\r\n"); dtostrf(n_helligkeit,4,1,speicher); strcat(emailwarnunghelligkeit,"Die Helligkeit ist zu hoch: "); strcat(emailwarnunghelligkeit,speicher); strcat(emailwarnunghelligkeit," Lux."); helligkeitproblem=true; } else { if ((n_helligkeit > helligkeit_min) && (n_helligkeit < helligkeit_max) && (helligkeitproblem)) { strcat(emailwarnungbetreffhelligkeit,"Subject: Strauchie: Helligkeit wieder ok\r\n"); dtostrf(n_helligkeit,4,1,speicher); strcat(emailwarnunghelligkeit,"Die Helligkeit ist wieder im Normalbereich und liegt bei "); strcat(emailwarnunghelligkeit,speicher); strcat(emailwarnunghelligkeit," Lux."); helligkeitproblem=false; } } } if ((n_luftfeuchtigkeit <= luftfeuchtigkeit_min) && (!luftfeuchteproblem)) { strcat(emailwarnungbetreffluftfeuchte,"Subject: Strauchie: Luftfeuchte zu niedrig\r\n"); dtostrf(n_luftfeuchtigkeit,4,1,speicher); strcat(emailwarnungluftfeuchte,"Die Luftfeuchtigkeit ist zu niedrig: "); strcat(emailwarnungluftfeuchte,speicher); strcat(emailwarnungluftfeuchte," %."); luftfeuchteproblem=true; } else { if ((n_luftfeuchtigkeit >= luftfeuchtigkeit_max) && (!luftfeuchteproblem)) { strcat(emailwarnungbetreffluftfeuchte,"Subject: Strauchie: Luftfeuchte zu hoch\r\n"); dtostrf(n_luftfeuchtigkeit,4,1,speicher); strcat(emailwarnungluftfeuchte,"Die Luftfeuchtigkeit ist zu hoch: "); strcat(emailwarnungluftfeuchte,speicher); strcat(emailwarnungluftfeuchte," %."); luftfeuchteproblem=true; } else { if ((n_luftfeuchtigkeit > luftfeuchtigkeit_min) && (n_luftfeuchtigkeit < luftfeuchtigkeit_max) && (luftfeuchteproblem)) { strcat(emailwarnungbetreffluftfeuchte,"Subject: Strauchie: Luftfeuchte wieder ok\r\n"); dtostrf(n_luftfeuchtigkeit,4,1,speicher); strcat(emailwarnungluftfeuchte,"Die Luftfeuchtigkeit ist wieder im Normalbereich und liegt bei "); strcat(emailwarnungluftfeuchte,speicher); strcat(emailwarnungluftfeuchte," %."); luftfeuchteproblem=false; } } } if ((n_temperatur <= temperatur_min) && (!temperaturproblem)) { strcat(emailwarnungbetrefftemperatur,"Subject: Strauchie: Temperatur zu niedrig\r\n"); dtostrf(n_temperatur,4,1,speicher); strcat(emailwarnungtemperatur,"Die Temperatur ist zu niedrig: "); strcat(emailwarnungtemperatur,speicher); strcat(emailwarnungtemperatur," °C."); temperaturproblem=true; } else { if ((n_temperatur >= temperatur_max) && (!temperaturproblem)) { strcat(emailwarnungbetrefftemperatur,"Subject: Strauchie: Temperatur zu hoch\r\n"); dtostrf(n_temperatur,4,1,speicher); strcat(emailwarnungtemperatur,"Die Temperatur ist zu hoch: "); strcat(emailwarnungtemperatur,speicher); strcat(emailwarnungtemperatur," °C."); temperaturproblem=true; } else { if ((n_temperatur > temperatur_min) && (n_temperatur < temperatur_max) && (temperaturproblem)) { strcat(emailwarnungbetrefftemperatur,"Subject: Strauchie: Temperatur wieder ok\r\n"); dtostrf(n_temperatur,4,1,speicher); strcat (emailwarnungtemperatur,"Die Temperatur ist wieder im Normalbereich und liegt bei "); strcat(emailwarnungtemperatur,speicher); strcat(emailwarnungtemperatur," °C."); temperaturproblem=false; } } } if ((n_bodenfeuchtigkeit <= bodenfeuchtigkeit_min) && (!bodenfeuchteproblem)) { strcat(emailwarnungbetreffbodenfeuchte,"Subject: Strauchie: Bodenfeuchte zu niedrig\r\n"); dtostrf(n_bodenfeuchtigkeit,4,1,speicher); strcat(emailwarnungbodenfeuchte,"Die Bodenfeuchtigkeit ist zu niedrig: "); strcat(emailwarnungbodenfeuchte,speicher); strcat(emailwarnungbodenfeuchte," %."); bodenfeuchteproblem=true; } else { if ((n_bodenfeuchtigkeit >= bodenfeuchtigkeit_max) && (!bodenfeuchteproblem)) { strcat(emailwarnungbetreffbodenfeuchte,"Subject: Strauchie: Bodenfeuchte zu hoch\r\n"); dtostrf(n_bodenfeuchtigkeit,4,1,speicher); strcat(emailwarnungbodenfeuchte,"Die Bodenfeuchtigkeit ist zu hoch: "); strcat(emailwarnungbodenfeuchte,speicher); strcat(emailwarnungbodenfeuchte," %."); bodenfeuchteproblem=true; } else { if ((n_bodenfeuchtigkeit > bodenfeuchtigkeit_min) && (n_bodenfeuchtigkeit < bodenfeuchtigkeit_max) && (bodenfeuchteproblem)) { strcat(emailwarnungbetreffbodenfeuchte,"Subject: Strauchie: Bodenfeuchte wieder ok\r\n"); dtostrf(n_bodenfeuchtigkeit,4,1,speicher); strcat(emailwarnungbodenfeuchte,"Die Bodenfeuchtigkeit ist wieder im Normalbereich und liegt bei "); strcat(emailwarnungbodenfeuchte,speicher); strcat(emailwarnungbodenfeuchte," %."); bodenfeuchteproblem=false; } } } if ((n_bodentemperatur <= bodentemperatur_min) && (!bodentemperaturproblem)) { strcat(emailwarnungbetreffbodentemperatur,"Subject: Strauchie: Bodentemperatur zu niedrig\r\n"); dtostrf(n_bodentemperatur,4,1,speicher); strcat(emailwarnungbodentemperatur,"Die Bodentemperatur ist zu niedrig: "); strcat(emailwarnungbodentemperatur,speicher); strcat(emailwarnungbodentemperatur," °C."); bodentemperaturproblem=true; } else { if ((n_bodentemperatur >= bodentemperatur_max) && (!bodentemperaturproblem)) { strcat(emailwarnungbetreffbodentemperatur,"Subject: Strauchie: Bodentemperatur zu hoch\r\n"); dtostrf(n_bodentemperatur,4,1,speicher); strcat(emailwarnungbodentemperatur,"Die Bodentemperatur ist zu hoch: "); strcat(emailwarnungbodentemperatur,speicher); strcat(emailwarnungbodentemperatur," °C."); bodentemperaturproblem=true; } else { if ((n_bodentemperatur > bodentemperatur_min) && (n_bodentemperatur < bodentemperatur_max) && (bodentemperaturproblem)) { strcat(emailwarnungbetreffbodentemperatur,"Subject: Strauchie: Bodentemperatur wieder ok\r\n"); dtostrf(n_bodentemperatur,4,1,speicher); strcat(emailwarnungbodentemperatur,"Die Bodentemperatur ist wieder im Normalbereich und liegt bei "); strcat(emailwarnungbodentemperatur,speicher); strcat(emailwarnungbodentemperatur," °C."); bodentemperaturproblem=false; } } } if ((helligkeitproblem) || (luftfeuchteproblem) || (temperaturproblem) || (bodenfeuchteproblem) || (bodentemperaturproblem)) { led_schalten(rot); } if ((!helligkeitproblem) && (!luftfeuchteproblem) && (!temperaturproblem) && (!bodenfeuchteproblem) && (!bodentemperaturproblem)) { if ((((n_helligkeit > helligkeit_min) && (n_helligkeit < helligkeit_min * 1.05)) || ((n_helligkeit > helligkeit_max * 0.95) && (n_helligkeit < helligkeit_max))) || (((n_luftfeuchtigkeit > luftfeuchtigkeit_min) && (n_luftfeuchtigkeit < luftfeuchtigkeit_min * 1.05)) || ((n_luftfeuchtigkeit > luftfeuchtigkeit_max * 0.95) && (n_luftfeuchtigkeit < luftfeuchtigkeit_max))) || (((n_temperatur > temperatur_min) && (n_temperatur < temperatur_min * 1.05)) || ((n_temperatur > temperatur_max * 0.95) && (n_temperatur < temperatur_max))) || (((n_bodenfeuchtigkeit > bodenfeuchtigkeit_min) && (n_bodenfeuchtigkeit < bodenfeuchtigkeit_min * 1.05)) || ((n_bodenfeuchtigkeit > bodenfeuchtigkeit_max * 0.95) && (n_bodenfeuchtigkeit < bodenfeuchtigkeit_max)) || ((n_bodentemperatur > bodentemperatur_min) && (n_bodentemperatur < bodentemperatur_min * 1.05)) || ((n_bodentemperatur > bodentemperatur_max * 0.95) && (n_bodentemperatur < bodentemperatur_max)))) { led_schalten(gelb); } else { led_schalten(gruen); } } if ((strlen(emailwarnungbetreffhelligkeit)>0) && (strlen(emailwarnungbetreffluftfeuchte)==0) && (strlen(emailwarnungbetrefftemperatur)==0) && (strlen(emailwarnungbetreffbodenfeuchte)==0) && (strlen(emailwarnungbetreffbodentemperatur)==0)) { if (email_senden(emailwarnungbetreffhelligkeit,emailwarnunghelligkeit)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)==0) && (strlen(emailwarnungbetreffluftfeuchte)>0) && (strlen(emailwarnungbetrefftemperatur)==0) && (strlen(emailwarnungbetreffbodenfeuchte)==0) && (strlen(emailwarnungbetreffbodentemperatur)==0)) { if (email_senden(emailwarnungbetreffluftfeuchte,emailwarnungluftfeuchte)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)==0) && (strlen(emailwarnungbetreffluftfeuchte)==0) && (strlen(emailwarnungbetrefftemperatur)>0) && (strlen(emailwarnungbetreffbodenfeuchte)==0) && (strlen(emailwarnungbetreffbodentemperatur)==0)) { if (email_senden(emailwarnungbetrefftemperatur,emailwarnungtemperatur)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)==0) && (strlen(emailwarnungbetreffluftfeuchte)==0) && (strlen(emailwarnungbetrefftemperatur)==0) && (strlen(emailwarnungbetreffbodenfeuchte)>0) && (strlen(emailwarnungbetreffbodentemperatur)==0)) { if (email_senden(emailwarnungbetreffbodenfeuchte,emailwarnungbodenfeuchte)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)==0) && (strlen(emailwarnungbetreffluftfeuchte)==0) && (strlen(emailwarnungbetrefftemperatur)==0) && (strlen(emailwarnungbetreffbodenfeuchte)==0) && (strlen(emailwarnungbetreffbodentemperatur)>0)) { if (email_senden(emailwarnungbetreffbodentemperatur,emailwarnungbodentemperatur)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)>0) && (strlen(emailwarnungbetreffluftfeuchte)>0) && (strlen(emailwarnungbetrefftemperatur)==0) && (strlen(emailwarnungbetreffbodenfeuchte)==0) && (strlen(emailwarnungbetreffbodentemperatur)==0)) { strcat(emailwarnungbetreff,"Subject: Strauchie: Helligkeit und Luftfeuchte schlecht\r\n"); strcat(emailwarnung,emailwarnunghelligkeit); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungluftfeuchte); if (email_senden(emailwarnungbetreff,emailwarnung)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)>0) && (strlen(emailwarnungbetreffluftfeuchte)==0) && (strlen(emailwarnungbetrefftemperatur)>0) && (strlen(emailwarnungbetreffbodenfeuchte)==0) && (strlen(emailwarnungbetreffbodentemperatur)==0)) { strcat(emailwarnungbetreff,"Subject: Strauchie: Helligkeit und Temperatur schlecht\r\n"); strcat(emailwarnung,emailwarnunghelligkeit); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungtemperatur); if (email_senden(emailwarnungbetreff,emailwarnung)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)>0) && (strlen(emailwarnungbetreffluftfeuchte)==0) && (strlen(emailwarnungbetrefftemperatur)==0) && (strlen(emailwarnungbetreffbodenfeuchte)>0) && (strlen(emailwarnungbetreffbodentemperatur)==0)) { strcat(emailwarnungbetreff,"Subject: Strauchie: Helligkeit und Bodenfeuchte schlecht\r\n"); strcat(emailwarnung,emailwarnunghelligkeit); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodenfeuchte); if (email_senden(emailwarnungbetreff,emailwarnung)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)>0) && (strlen(emailwarnungbetreffluftfeuchte)==0) && (strlen(emailwarnungbetrefftemperatur)==0) && (strlen(emailwarnungbetreffbodenfeuchte)==0) && (strlen(emailwarnungbetreffbodentemperatur)>0)) { strcat(emailwarnungbetreff,"Subject: Strauchie: Helligkeit und Bodentemperatur schlecht\r\n"); strcat(emailwarnung,emailwarnunghelligkeit); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodentemperatur); if (email_senden(emailwarnungbetreff,emailwarnung)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)>0) && (strlen(emailwarnungbetreffluftfeuchte)>0) && (strlen(emailwarnungbetrefftemperatur)>0) && (strlen(emailwarnungbetreffbodenfeuchte)==0) && (strlen(emailwarnungbetreffbodentemperatur)==0)) { strcat(emailwarnungbetreff,"Subject: Strauchie: Helligkeit, Luftfeuchte und Temperatur schlecht\r\n"); strcat(emailwarnung,emailwarnunghelligkeit); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungluftfeuchte); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungtemperatur); if (email_senden(emailwarnungbetreff,emailwarnung)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)>0) && (strlen(emailwarnungbetreffluftfeuchte)>0) && (strlen(emailwarnungbetrefftemperatur)==0) && (strlen(emailwarnungbetreffbodenfeuchte)>0) && (strlen(emailwarnungbetreffbodentemperatur)==0)) { strcat(emailwarnungbetreff,"Subject: Strauchie: Helligkeit, Luftfeuchte und Bodenfeuchte schlecht\r\n"); strcat(emailwarnung,emailwarnunghelligkeit); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungluftfeuchte); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodenfeuchte); if (email_senden(emailwarnungbetreff,emailwarnung)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)>0) && (strlen(emailwarnungbetreffluftfeuchte)>0) && (strlen(emailwarnungbetrefftemperatur)==0) && (strlen(emailwarnungbetreffbodenfeuchte)==0) && (strlen(emailwarnungbetreffbodentemperatur)>0)) { strcat(emailwarnungbetreff,"Subject: Strauchie: Helligkeit, Luftfeuchte und Bodentemperatur schlecht\r\n"); strcat(emailwarnung,emailwarnunghelligkeit); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungluftfeuchte); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodenfeuchte); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodentemperatur); if (email_senden(emailwarnungbetreff,emailwarnung)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)>0) && (strlen(emailwarnungbetreffluftfeuchte)>0) && (strlen(emailwarnungbetrefftemperatur)>0) && (strlen(emailwarnungbetreffbodenfeuchte)>0) && (strlen(emailwarnungbetreffbodentemperatur)==0)) { strcat(emailwarnungbetreff,"Subject: Strauchie: Helligkeit, Luftfeuchte, Temperatur und Bodenfeuchte schlecht\r\n"); strcat(emailwarnung,emailwarnunghelligkeit); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungluftfeuchte); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungtemperatur); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodenfeuchte); if (email_senden(emailwarnungbetreff,emailwarnung)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)==0) && (strlen(emailwarnungbetreffluftfeuchte)>0) && (strlen(emailwarnungbetrefftemperatur)>0) && (strlen(emailwarnungbetreffbodenfeuchte)==0) && (strlen(emailwarnungbetreffbodentemperatur)==0)) { strcat(emailwarnungbetreff,"Subject: Strauchie: Luftfeuchte und Temperatur schlecht\r\n"); strcat(emailwarnung,emailwarnungluftfeuchte); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungtemperatur); if (email_senden(emailwarnungbetreff,emailwarnung)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)==0) && (strlen(emailwarnungbetreffluftfeuchte)>0) && (strlen(emailwarnungbetrefftemperatur)==0) && (strlen(emailwarnungbetreffbodenfeuchte)>0) && (strlen(emailwarnungbetreffbodentemperatur)==0)) { strcat(emailwarnungbetreff,"Subject: Strauchie: Luftfeuchte und Bodenfeuchte schlecht\r\n"); strcat(emailwarnung,emailwarnungluftfeuchte); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodenfeuchte); if (email_senden(emailwarnungbetreff,emailwarnung)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)==0) && (strlen(emailwarnungbetreffluftfeuchte)>0) && (strlen(emailwarnungbetrefftemperatur)>0) && (strlen(emailwarnungbetreffbodenfeuchte)>0) && (strlen(emailwarnungbetreffbodentemperatur)==0)) { strcat(emailwarnungbetreff,"Subject: Strauchie: Luftfeuchte, Temperatur und Bodenfeuchte schlecht\r\n"); strcat(emailwarnung,emailwarnungluftfeuchte); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungtemperatur); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodenfeuchte); if (email_senden(emailwarnungbetreff,emailwarnung)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)==0) && (strlen(emailwarnungbetreffluftfeuchte)==0) && (strlen(emailwarnungbetrefftemperatur)>0) && (strlen(emailwarnungbetreffbodenfeuchte)>0) && (strlen(emailwarnungbetreffbodentemperatur)==0)) { strcat(emailwarnungbetreff,"Subject: Strauchie: Temperatur und Bodenfeuchte schlecht\r\n"); strcat(emailwarnung,emailwarnungtemperatur); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodenfeuchte); if (email_senden(emailwarnungbetreff,emailwarnung)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)==0) && (strlen(emailwarnungbetreffluftfeuchte)==0) && (strlen(emailwarnungbetrefftemperatur)==0) && (strlen(emailwarnungbetreffbodenfeuchte)>0) && (strlen(emailwarnungbetreffbodentemperatur)>0)) { strcat(emailwarnungbetreff,"Subject: Strauchie: Bodenfeuchte und Bodentemperatur schlecht\r\n"); strcat(emailwarnung,emailwarnungbodenfeuchte); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodentemperatur); if (email_senden(emailwarnungbetreff,emailwarnung)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)==0) && (strlen(emailwarnungbetreffluftfeuchte)==0) && (strlen(emailwarnungbetrefftemperatur)>0) && (strlen(emailwarnungbetreffbodenfeuchte)==0) && (strlen(emailwarnungbetreffbodentemperatur)>0)) { strcat(emailwarnungbetreff,"Subject: Strauchie: Temperatur und Bodentemperatur schlecht\r\n"); strcat(emailwarnung,emailwarnungtemperatur); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodentemperatur); if (email_senden(emailwarnungbetreff,emailwarnung)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)==0) && (strlen(emailwarnungbetreffluftfeuchte)==0) && (strlen(emailwarnungbetrefftemperatur)>0) && (strlen(emailwarnungbetreffbodenfeuchte)>0) && (strlen(emailwarnungbetreffbodentemperatur)>0)) { strcat(emailwarnungbetreff,"Subject: Strauchie: Temperatur, Bodenfeuchte und Bodentemperatur schlecht\r\n"); strcat(emailwarnung,emailwarnungtemperatur); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodenfeuchte); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodentemperatur); if (email_senden(emailwarnungbetreff,emailwarnung)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)==0) && (strlen(emailwarnungbetreffluftfeuchte)>0) && (strlen(emailwarnungbetrefftemperatur)==0) && (strlen(emailwarnungbetreffbodenfeuchte)==0) && (strlen(emailwarnungbetreffbodentemperatur)>0)) { strcat(emailwarnungbetreff,"Subject: Strauchie: Luftfeuchte und Bodentemperatur schlecht\r\n"); strcat(emailwarnung,emailwarnungluftfeuchte); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodentemperatur); if (email_senden(emailwarnungbetreff,emailwarnung)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)==0) && (strlen(emailwarnungbetreffluftfeuchte)>0) && (strlen(emailwarnungbetrefftemperatur)==0) && (strlen(emailwarnungbetreffbodenfeuchte)>0) && (strlen(emailwarnungbetreffbodentemperatur)>0)) { strcat(emailwarnungbetreff,"Subject: Strauchie: Luftfeuchte, Bodenfeuchte und Bodentemperatur schlecht\r\n"); strcat(emailwarnung,emailwarnungluftfeuchte); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodenfeuchte); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodentemperatur); if (email_senden(emailwarnungbetreff,emailwarnung)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)==0) && (strlen(emailwarnungbetreffluftfeuchte)>0) && (strlen(emailwarnungbetrefftemperatur)>0) && (strlen(emailwarnungbetreffbodenfeuchte)==0) && (strlen(emailwarnungbetreffbodentemperatur)>0)) { strcat(emailwarnungbetreff,"Subject: Strauchie: Luftfeuchte, Temperatur und Bodentemperatur schlecht\r\n"); strcat(emailwarnung,emailwarnungluftfeuchte); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungtemperatur); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodentemperatur); if (email_senden(emailwarnungbetreff,emailwarnung)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)==0) && (strlen(emailwarnungbetreffluftfeuchte)>0) && (strlen(emailwarnungbetrefftemperatur)>0) && (strlen(emailwarnungbetreffbodenfeuchte)>0) && (strlen(emailwarnungbetreffbodentemperatur)>0)) { strcat(emailwarnungbetreff,"Subject: Strauchie: Luftfeuchte, Temperatur, Bodenfeuchte und Bodentemperatur schlecht\r\n"); strcat(emailwarnung,emailwarnungluftfeuchte); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungtemperatur); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodenfeuchte); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodentemperatur); if (email_senden(emailwarnungbetreff,emailwarnung)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)>0) && (strlen(emailwarnungbetreffluftfeuchte)==0) && (strlen(emailwarnungbetrefftemperatur)==0) && (strlen(emailwarnungbetreffbodenfeuchte)>0) && (strlen(emailwarnungbetreffbodentemperatur)>0)) { strcat(emailwarnungbetreff,"Subject: Strauchie: Helligkeit, Bodenfeuchte und Bodentemperatur schlecht\r\n"); strcat(emailwarnung,emailwarnunghelligkeit); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodenfeuchte); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodentemperatur); if (email_senden(emailwarnungbetreff,emailwarnung)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)>0) && (strlen(emailwarnungbetreffluftfeuchte)==0) && (strlen(emailwarnungbetrefftemperatur)>0) && (strlen(emailwarnungbetreffbodenfeuchte)>0) && (strlen(emailwarnungbetreffbodentemperatur)==0)) { strcat(emailwarnungbetreff,"Subject: Strauchie: Helligkeit, Temperatur und Bodenfeuchte schlecht\r\n"); strcat(emailwarnung,emailwarnunghelligkeit); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungtemperatur); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodenfeuchte); if (email_senden(emailwarnungbetreff,emailwarnung)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)>0) && (strlen(emailwarnungbetreffluftfeuchte)==0) && (strlen(emailwarnungbetrefftemperatur)>0) && (strlen(emailwarnungbetreffbodenfeuchte)>0) && (strlen(emailwarnungbetreffbodentemperatur)>0)) { strcat(emailwarnungbetreff,"Subject: Strauchie: Helligkeit, Temperatur, Bodenfeuchte und Bodentemperatur schlecht\r\n"); strcat(emailwarnung,emailwarnunghelligkeit); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungtemperatur); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodenfeuchte); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodentemperatur); if (email_senden(emailwarnungbetreff,emailwarnung)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)>0) && (strlen(emailwarnungbetreffluftfeuchte)>0) && (strlen(emailwarnungbetrefftemperatur)==0) && (strlen(emailwarnungbetreffbodenfeuchte)>0) && (strlen(emailwarnungbetreffbodentemperatur)>0)) { strcat(emailwarnungbetreff,"Subject: Strauchie: Helligkeit, Luftfeuchte, Bodenfeuchte und Bodentemperatur schlecht\r\n"); strcat(emailwarnung,emailwarnunghelligkeit); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungluftfeuchte); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodenfeuchte); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodentemperatur); if (email_senden(emailwarnungbetreff,emailwarnung)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)>0) && (strlen(emailwarnungbetreffluftfeuchte)>0) && (strlen(emailwarnungbetrefftemperatur)>0) && (strlen(emailwarnungbetreffbodenfeuchte)==0) && (strlen(emailwarnungbetreffbodentemperatur)>0)) { strcat(emailwarnungbetreff,"Subject: Strauchie: Helligkeit, Luftfeuchte, Temperatur und Bodentemperatur schlecht\r\n"); strcat(emailwarnung,emailwarnunghelligkeit); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungtemperatur); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodenfeuchte); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodentemperatur); if (email_senden(emailwarnungbetreff,emailwarnung)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if ((strlen(emailwarnungbetreffhelligkeit)>0) && (strlen(emailwarnungbetreffluftfeuchte)>0) && (strlen(emailwarnungbetrefftemperatur)>0) && (strlen(emailwarnungbetreffbodenfeuchte)>0) && (strlen(emailwarnungbetreffbodentemperatur)>0)) { strcat(emailwarnungbetreff,"Subject: Strauchie: Helligkeit, Luftfeuchte, Temperatur, Bodenfeuchte und Bodentemperatur schlecht\r\n"); strcat(emailwarnung,emailwarnunghelligkeit); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungluftfeuchte); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungtemperatur); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodenfeuchte); strcat(emailwarnung," "); strcat(emailwarnung,emailwarnungbodentemperatur); if (email_senden(emailwarnungbetreff,emailwarnung)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } if (tageszusammenfassung_senden(n_stunde)) { char tageszusammenfassungbetreff[50]="Subject: Strauchie: Tageszusammenfassung\r\n"; char tageszusammenfassung[180]=""; if ((!helligkeitproblem) && (!luftfeuchteproblem) && (!temperaturproblem) && (!bodenfeuchteproblem) && (!bodentemperaturproblem)) { strcat(tageszusammenfassung,"Mir geht es prima: Es ist mit "); dtostrf(n_helligkeit,4,1,speicher); strcat(tageszusammenfassung,speicher); strcat(tageszusammenfassung," Lux schön hell. Die Luftfeuchtigkeit beträgt "); dtostrf(n_luftfeuchtigkeit,4,1,speicher); strcat(tageszusammenfassung,speicher); strcat(tageszusammenfassung," %. Die Temperatur liegt bei angenehmen "); dtostrf(n_temperatur,4,1,speicher); strcat(tageszusammenfassung,speicher); strcat(tageszusammenfassung," °C. Ich habe mit "); dtostrf(n_bodenfeuchtigkeit,4,0,speicher); strcat(tageszusammenfassung,speicher); strcat(tageszusammenfassung," % Bodenfeuchtigkeit genügend Wasser. "); strcat(tageszusammenfassung,"Die Bodentemperatur ist mit "); dtostrf(n_bodentemperatur,4,1,speicher); strcat(tageszusammenfassung,speicher); strcat(tageszusammenfassung," °C optimal."); } else { strcat(tageszusammenfassung,"Mir geht es nicht so gut: "); dtostrf(n_helligkeit,4,1,speicher); if (helligkeitproblem) { if (n_helligkeit<helligkeit_min) { strcat(tageszusammenfassung,"Die Helligkeit ist mit "); strcat(tageszusammenfassung,speicher); strcat(tageszusammenfassung," Lux zu gering. "); } else { if (n_helligkeit>helligkeit_max) { strcat(tageszusammenfassung,"Die Helligkeit ist mit "); strcat(tageszusammenfassung,speicher); strcat(tageszusammenfassung," Lux zu hoch. "); } } } dtostrf(n_luftfeuchtigkeit,4,1,speicher); if (luftfeuchteproblem) { if (n_luftfeuchtigkeit<luftfeuchtigkeit_min) { strcat(tageszusammenfassung,"Die Luftfeuchtigkeit ist mit "); strcat(tageszusammenfassung,speicher); strcat(tageszusammenfassung," % zu niedrig. "); } else { if (n_helligkeit>helligkeit_max) { strcat(tageszusammenfassung,"Die Luftfeuchtigkeit ist mit "); strcat(tageszusammenfassung,speicher); strcat(tageszusammenfassung," % zu hoch. "); } } } dtostrf(n_temperatur,4,1,speicher); if (temperaturproblem) { if (n_temperatur<temperatur_min) { strcat(tageszusammenfassung,"Die Temperatur beträgt lediglich "); strcat(tageszusammenfassung,speicher); strcat(tageszusammenfassung," °C. "); } else { if (n_temperatur>temperatur_max) { strcat(tageszusammenfassung,"Die Temperatur ist mit "); strcat(tageszusammenfassung,speicher); strcat(tageszusammenfassung," °C zu hoch. "); } } } dtostrf(n_bodenfeuchtigkeit,4,0,speicher); if (bodenfeuchteproblem) { if (n_bodenfeuchtigkeit<bodenfeuchtigkeit_min) { strcat(tageszusammenfassung,"Der Boden ist mit nur "); strcat(tageszusammenfassung,speicher); strcat(tageszusammenfassung," % Feuchtigkeit zu trocken."); } else { if (n_bodenfeuchtigkeit>bodenfeuchtigkeit_max) { strcat(tageszusammenfassung,"Der Boden ist mit "); strcat(tageszusammenfassung,speicher); strcat(tageszusammenfassung," % zu nass."); } } } dtostrf(n_bodentemperatur,4,1,speicher); if (bodentemperaturproblem) { if (n_bodentemperatur<bodentemperatur_min) { strcat(tageszusammenfassung,"Die Bodentemperatur ist mit nur "); strcat(tageszusammenfassung,speicher); strcat(tageszusammenfassung," °C zu kalt."); } else { if (n_bodenfeuchtigkeit>bodenfeuchtigkeit_max) { strcat(tageszusammenfassung,"Die Bodentemperatur ist mit "); strcat(tageszusammenfassung,speicher); strcat(tageszusammenfassung," °C zu hoch."); } } } } if (email_senden(tageszusammenfassungbetreff,tageszusammenfassung)) Serial.println(F("E-Mail erfolgreich versendet!")); else Serial.println(F("E-Mail-Versand fehlgeschlagen!")); } } void loop() { if (!start_ok) { if (startsensorcheck()) { start_ok=true; } else { start_ok=false; } } if (start_ok) { if (zeitsync_notwendig(day())) { if (sommerzeit(year(),month(),day(),hour(),1)) { timeZone=2; } else { timeZone=1; } zeit_setzen(getNtpTime()); } delay(5000); if (messung_starten(minute())) { auswertung(day(),month(),year(),hour(),minute(),second(),durchschnittsluminanz(helligkeit()),luftfeuchtigkeit(),temperatur(),bodenfeuchtigkeit(), bodentemperatur()); } } else { warnblinken(); } }
Bauteilliste Strauchie-Bot
Bauteile für Strauchie-Bot gibt es günstig im China-Handel wie beispielsweise MiniIn the Box. Aber Vorsicht: Überschreitet die Bestellung 22 Euro, dann sind Einfuhrumsatzsteuer und Zollgebühren fällig.
- 1 x Arduino Mega 2560
- 1 x Arduino Ethernet Shield
- 1 x RTC-Modul DS3231
- 1 x RGB-LED 5 mm
- 1 x DHT22/AM2302
- 1 x I2C FT-Sensor
- 1 x Fotowiderstand 50 kΩ
- 1 x Widerstand 49,9 kΩ
- 1 x Widerstand 10 kΩ
- 2 x Widerstand 200 Ω
- 1 x Widerstand 100 Ω
- 1 x Gehäuse für Basis
- 1 x Gehäuse für Sensoreinheit
- 1 x SUB-D Stecker 12-polig
- 1 x SUB-D Buchse 12-polig
- 1 x Zugentlastung
- 1 x Kabel 12-polig
- Kabel, Steckerleisten, Schrumpfschlauch, Platinenhalter, Heißkleber
Fazit und Ausblick auf weitere Funktionen
Strauchie-Bot überwacht bereits seit mehr als einem Jahr fehlerfrei meinen selbst gezogenen Ficus, der durch die kontinuierliche Überwachung optimale Bedingungen für sein Wachstum erhält. Die Kosten halten sich mit etwa 50 Euro in Grenzen. Zwei Erweiterungen sind in Arbeit: So soll die Pflanze zukünftig je nach Zustand, Tageszeit und andere Umstände selbst auf lustige Weise twittern. Das funktioniert bereits im Ansatz, hat aber noch deutliches Verbesserungspotenzial.
Die zweite Erweiterung betrifft das Gießen. Es ist zwar hilfreich, dass Strauchie-Bot darauf hinweist, dass die Pflanze gegossen werden muss, aber wenn man den Hinweis beispielsweise im Urlaub erhält und nicht zu Hause ist, kann man doch nichts machen. Deshalb ist eine automatische Bewässerungsfunktion im Aufbau. Dabei steht im Vordergrund, dass die Pflanze optimal mit Wasser versorgt wird, ohne dabei die Wohnung zu überschwemmen.
Das ist genau das Richtige für mich! Aber ich brauche davon mindestens 6 Stück.
Hallo,
erstmal danke für dieses geile Bastelprojekt. Wie zuverlässig läuft das Teil denn? Muss man den Arduino öfter neu starten?
Gruß
Enzo
Hi Enzo,
Neustarts sind nicht notwendig. Bei mir lief Strauchie-Bot mehrere Monate ohne Unterbrechung fehlerfrei. Starte ihn nur neu, wenn ich etwas am Sketch geändert habe.
Viele Grüße
Oliver
Das dann nur noch mit einer automatischen Gießanlage verbinden. Das wäre perfekt.
Richtig geiles projekt und für den preis super funktionen, wenn man das jetzt noch mit wlan statt mit einem ethernetshield wäre wäre es perfekt ^^
ich werde mich mal denke ich demnächst damit befassen und schau ob man das ganze auch mit wlan ohne weiteres implementiert bekommt, ich denke ich werde dann dazu ein update posten. muss nur schauen wann 🙂
Hallo Tommy,
mit einem ESP32 und ein paar kleinen Anpassungen am Sketch sollte das klappen. Bin gespannt auf dein Projekt!
Viele Grüße
Oliver
Cool,
letztes Jahr hatte ich genau diesen Sensor bei meiner automatischen Bewesserungsanlage. Nur ich kam mit dem Sensor nicht klar. Danke für den Quellcode, werde diesen mal implementieren und hoffe, dass es dieses Jahr keine vertrocknen Pflanzen gibt.
Gruß Jörg
Klasse Projekt! Werde ich bald auf jeden Fall nachbauen und auch an einer automatischen Bewässerung arbeiten.
Eine interessante Erweiterung wäre sicherlich noch den PH Wert zu überwachen.
Hallo Oliver,
bist Du an diesem Projekt noch dran, oder ist das für Dich schon erledigt. Ich meine gelesen zu haben das du dies noch noch weiter entwickeln möchtest. Leider habe ich mit dem Sketch ein Problem.
Mit freundlichen Grüßen
Knut
Hallo Knut,
der Sketch ist die letzte Version. Es könnte sein, dass der E-Mail-Versand in der Form nicht mehr klappt. Da gibt es aber Alternativen. Mittlerweile habe ich die Entwicklung eingestellt. Tut mir Leid, dass keine Updates mehr kommen.
Viele Grüße
Oliver