6.0 Ausblick

Abb.: Platine mit dem ESP8266 oben rechts.

Der Wasserstand der Gießkanne muss manuell überprüft werden, um sicherzustellen, dass ausreichend Wasser für die Bewässerungsanlage vorhanden ist. Eine mögliche Verbesserung der Anlage wäre durch einen zusätzlichen Sensor, der den Wasserstand der Gießkanne misst und via App daran erinnert die Kanne aufzufüllen, denkbar. Da der ESP8266 nur über einen Analog-Eingang verfügt, ist entweder ein Multiplexer auf der Platine zu ergänzen oder sogar das ESP8266 mit einer anderen ESP-Version auszutauschen.

5.0 Fertigstellung

Abb.: Fertiges automatisierte Bewässerungsanlage einer Zimmerpflanze.

Je nach Art der Pflanze, können die Werte des Programms zur automatisierten Bewässerung angepasst werden. Die Software mit den Werten befindet sich auf dem ESP8266. Beispielsweise benötigen Kakteen im Vergleich zu anderen Zimmerpflanzen nicht viel Wasser. Auch die Zusammensetzung der Erde hat einen Einfluss auf die Messwerte des Sensors und damit auch auf die automatisierte Bewässerung. Wenn die Erde viel Torf enthält, kann sie das Wasser etwas länger speichern als staubige Erde.

4.3 Umsetzung der App

Eine zusätzliche Möglichkeit zur Kontrolle und zur externen Steuerung der Bewässerungsanlage, welche keinen Einfluss auf den automatisierten Bewässerungsablauf hat, soll eine App via MQTT bieten. Dazu sind hauptsächlich die definierten Topics zum Schreiben und Lesen des Brokers zu verwenden, die bereits in der Software des ESP8266 enthalten sind. Mit Hilfe von Flutter können Cross-Plattform-Apps, also Apps für die Betriebssysteme iOS und Android, in einer Programmierspache entwickelt werden. Diese Technolgie wird im Rahmen dieses Projekts verwendet.

Mit Flutter wurden drei Bildschirme implementiert, die es ermöglichen sich mit dem Broker zu verbinden, um anschließend die Kommunikation zwischen der Bewässerungsanlage und der App zu ermöglichen. Die Werte des Sensors werden vom ESP8266 in regelmäßigen Abständen an den Broker übermittelt, sodass die App diese mit Hilfe des richtigen Topics lesen und auf einem der drei Bildschirm als Wasserstand der Pflanze anzeigen kann, sobald die Bewässerungsanlage aktiviert und die App mit dem Broker verbunden ist.

Abb.: Drei Bildschirme der App ohne Verbindung zum Server. Im linken Bildschirm “Water Level” wird der Wasserstand der Pflanze angezeigt, sobald die App mit dem Broker verbunden wird und die Bewässerungsanlage aktiv ist.

Für die Verbindung zum Server müssen keine Einstellungen vorgenommen werden. Durch das betätigen des Connect-Buttons auf dem Bildschirm “Water Level”, kann der Nutzer die App mit dem Broker verbinden. Es ist ihm auch möglich die Kommunikation zwischen dem Broker auf dem Bildschirm “Messages” zu lesen und ggf. definierte Nachrichten an andere Topics des Brokers zu senden. Zusätzlich werden die verwendeten Topics zum Lesen und Schreiben im Bildschirm “Broker Settings” angezeigt. Dort ist es ebenfalls möglich die Kommunikation zwischen Broker und App aufzuheben.

Abb.: App im verbundenen Zustand.

Klicke hier, um die App für Android zu laden


4.2 Umsetzung des Programms

Zunächst wurde die fertiggestellte Hardware mit einem einfachen Blink-Programm bespielt, um zu sehen, ob Programme einwandfrei auf den ESP8266 übertragbar sind.

Als nächstes sollten die analogen Werte des Sensors auf einem seriellen Monitor angezeigt werden. Dazu musste das Blink-Programm, welches am Anfang genutzt wurde, modifiziert werden. Der passende PIN A0 des ESP8266 musste am Sensor angeschlossen und im Programm als analoger Input definiert werden.

Nachdem der Sensor analoge Werte übermittelte, war es für die Funktionsweise der Bewässerungsanlage zu berücksichtigen, dass bestimmte Schwellenwerte dem Programm vorgegeben werden müssen, sodass das Programm erkennen kann, ob die Pflanze Wasser benötigt oder nicht.
Es wurden vier verschiedene Modi definiert, die je nach Schwellenwert aktiviert werden.

  if(sensorValue>0 && sensorValue<340){
      ledOff();
      msg = "Sensor is full WET";
      msg_id = 1;
  } else if(sensorValue>=340 && sensorValue<=530) {
      ledOff();
      msg = "Sensor is wet";
      msg_id = 2;
  } else if(sensorValue>530 && sensorValue<1023) {
      ledOn();
      msg = "Sensor is DRY ";
      msg_id = 3;
      //pump();
  } else {
      ledOff();
      msg = "Unexpected sensor value ";
      msg_id = 4;
  }

Anschließend wurde die Pumpe angeschlossen und in einem separaten Programm angesteuert. Nachdem die Funktionsweise der Pumpe und die Schwellenwerte des Sensors bekannt war, sollte nun das Programm von zuvor erweitert werden. Jedes Mal, wenn der Sensor meldet, dass die Pflanze trocken ist, sollte die Pumpe für 2 Sekunden angehen.

void pump(){
  // Turn pump on for 2000s
  int pumpPeriode = 2000;
  if(minDelayOfPump < millis() - timeStamp1){
    startingProcedure();
    pumpOn();
    delay(pumpPeriode);
    pumpOff();
    timeStamp1 = millis();
  }
}

Damit die Erde der Pflanze das Wasser aufnehmen kann, wird gemessen wann die Pumpe das letzte Mal aktiviert wurde. Erst wenn eine bestimmte Pause vergangen ist, darf die Pumpe wieder aktiviert werden. Somit kann das Programm nach einer bestimmten Zeit entscheiden, ob die Wassermenge ausreicht oder nicht. Falls die Wassermenge nicht ausreicht, wird die Pumpe wieder aktiviert. Dieser Ablauf wiederholt sich solange, bis die Erde der Pflanze ausreichend Wasser aufgenommen hat.

Nun sollten die Werte des Sensors zusätzlich via MQTT übertragen werden können. Dazu sollte wieder ein separates Programm genutzt werden, um den Broker, den Port und das Topic testen zu können. Anschließend wurde die MQTT-Funktionalität mit in das vorherige Programm mit aufgenommen.

Durch kleinere Programme ließen sich die Funktionen separat testen, bevor zu einem größeren Programm zusammengefügt wurden. Dies hat mögliche Fehlerquellen seit dem Anfang der Umsetzung des Quellcodes ausschließen können.

Abb.: Flussdiagramm zur Darstellung der Funktionsweise des Programms auf dem ESP8266.

Das Programm wurde noch um eine weitere Funktion erweitert, sodass es auch möglich ist die Pumpe via MQTT zu aktivieren.

/**
 * 
 *    brief: read values from water-sensor and send via WiFi to an application
 *    date: 05.07.2019
 *    project: CvO/Informatik/DDI3_µC
*/
//#include <WiFi.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

/********************************************************/
// Update these with values suitable for your network.

const char* ssid = "HIER DER NETZWERK NAME";
const char* password = "HIER DAS PASSWORT DES NETZWERKS";
/********************************************************/

const char* mqtt_server = "broker";
const char* mqttTopicPlant = "topic1";
const char* mqttTopicValues = "topic2";
const int port = 1883;
/********************************************************/
char* msg = ""; // msg to the broker
int msg_id = 0;
int msg_id_temp = 0;
int MOTOR = 14;
unsigned long timeStamp1 = 0, timeStamp2 = 0,  minDelayOfPump = 20000;

WiFiClient espClient;
PubSubClient client(espClient);

/********************************************************/
/* SETUP  */ 
/********************************************************/
void setup() {
  pinMode(BUILTIN_LED, OUTPUT);     // Initialize the BUILTIN_LED pin as an output
  pinMode(MOTOR, OUTPUT);
  pinMode(A0, INPUT);
  Serial.begin(115200);             // initialize serial communication at 115200 bits per second
  startingProcedure();              // blinking BuildIn_LED as starting procedure
  
  setup_wifi();
  client.setServer(mqtt_server, port);
  client.setCallback(callback);
  
  timeStamp1 = millis();
  timeStamp2 = millis();
}

/********************************************************/
/* MAIN LOOP  */ 
/********************************************************/
// the loop routine runs over and over again forever:
void loop() {
  
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  // read the input on analog pin 0:
  int sensorValue = analogRead(A0);

  sensorStates(sensorValue);

  delay(1000);
}
/********************************************************/

/********************************************************/
/* PROCESS  */ 
/********************************************************/

void sensorStates(int sensorValue){
  if(sensorValue>0 && sensorValue<340){
      ledOff();
      msg = "Sensor is full WET";
      msg_id = 1;
  } else if(sensorValue>=340 && sensorValue<=530) {
      ledOff();
      msg = "Sensor is wet";
      msg_id = 2;
  } else if(sensorValue>530 && sensorValue<1023) {
      ledOn();
      msg = "Sensor is DRY ";
      msg_id = 3;
      //pump();
  } else {
      ledOff();
      msg = "Unexpected sensor value ";
      msg_id = 4;
  }

  if(minDelayOfPump < millis() - timeStamp2){
    timeStamp2 = millis();
    statusCheckOfPlant(msg_id, sensorValue);
  }

  if(msg_id != msg_id_temp){
    msg_id_temp = msg_id;
    statusCheckOfPlant(msg_id, sensorValue);
  }
}

void statusCheckOfPlant(int msg_id, int sensorValue){
  sendDataToBroker(sensorValue);
  // DRY?
  if(msg_id == 3){
    //Turn pump on
    pump();
  }
}

void sendDataToBroker(int sensorValue){
    // Serial
    Serial.println(msg);
    Serial.println(sensorValue);
    // MQTT
    client.publish(mqttTopicPlant, msg);
    sendSensorValueViaMqtt(sensorValue);    
}

/********************************************************/
/* Pump  */ 
/********************************************************/
void pump(){
  // Turn pump on for 2000s
  int pumpPeriode = 2000;
  if(minDelayOfPump < millis() - timeStamp1){
    startingProcedure();
    pumpOn();
    delay(pumpPeriode);
    pumpOff();
    timeStamp1 = millis();
  }
}

void pumpOn(){
  ledOn();
  // pump on
  analogWrite(MOTOR, 512);
}

void pumpOff(){
  ledOff();
  // pump off
  analogWrite(MOTOR, 0);
     
}

/********************************************************/
/* LED  */ 
/********************************************************/
void ledOn(){
  digitalWrite(LED_BUILTIN, LOW);   // turn the LED on (HIGH is the voltage level)
  delay(250);
}

void ledOff(){
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(250);
}

// blinking procedure when device is switched on
void startingProcedure(){
  ledOn();
  ledOff();
  ledOn();
  ledOff();
}

/********************************************************/
/* MQTT  */ 
/********************************************************/

void setup_wifi() {

  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  randomSeed(micros());

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}


void callback(char* topic, byte* payload, unsigned int length) {
  char receivedPayload[length];
  /*Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");*/
  for (int i = 0; i < length; i++) {
    //Serial.print((char)payload[i]);
    receivedPayload[i] = (char) payload[i];
  }
  Serial.println();

  // Received Message
  int receivedMessage = atoi(receivedPayload);
  if(receivedMessage==1){
    Serial.print("MESSAGE: ");
    Serial.println(receivedMessage);
    pump();
  }
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str())) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("outTopic", "hello world");
      //client.publish(mqttTopicPlant, "hello world!");
      client.subscribe(mqttTopicPlant);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void sendSensorValueViaMqtt(int sensorValue){
    // Publish int (auch hier wieder char array)
    String pi_str = String(sensorValue);
    char pi_buff[pi_str.length()+1];
    pi_str.toCharArray(pi_buff, pi_str.length()+1);
    client.publish(mqttTopicValues, pi_buff);
}

4.1 Umsetzung der Hardware

Hauptsächlich steht bei der Umsetzung der Hardware die Fertigstellung der Platine mit den zugehörigen Bauteilen im Vordergrund. Die anderen Elemente, wie beispielsweise die Pumpe, werden lediglich miteinander verbunden.

Abb.: Bild der fertiggestellten Platine mit allen Bauteilen.

Der Hauptbestandteil ist der ESP8266, welcher die Prozesse für die automatische Bewässerung steuert. Auch die Kommunikation über WLan ist durch den ESP8266 gewährleistet.

Die Platine beinhaltet außerdem den Spannungsteiler, welcher 12V auf 3,3V regulieren kann. Dieser wird nach einer gewissen Zeit sehr warm und sollte daher nach Möglichkeit an eine zusätzliche Metallfläche angeschlossen werden.

Die Platine kann nach Fertigstellung in eine Kunststoffbox installiert werden, um diese vor Feuchtigkeit zu schützen. Auch die Anschlüsse vom Netzteil und der Pumpe können an der Platine angeschlossen werden.

Die Platine kann nach Fertigstellung

4.0 Umsetzung

Bei der Umsetzung wurde nach der Methode “Bottom Up” alles kleinschrittig und möglichst gekapselt umgesetzt. Zu Beginn wurde die Hardware und anschließend die Software fertiggestellt. Als Zusatz wurde noch eine eigene App für die automatische Bewässerungsanlage implementiert, welche keinen Einfluss auf den automatisierten Prozess der Bewässerungsanlage hat, sondern lediglich zur Kontrolle und zur zusätzlichen Steuerung dient.
Durch die kleinschrittige und transparente Umsetzung, konnten die einzelnen Hardware- und Software-Elemente getestet und ggf. angepasst und verbessert werden.

3.1.2 Beschreibung der Software

Die Software ist auf dem ESP8266 gespeichert, der sich wiederrum auf der Platine befindet. Diese kann mit Hilfe eines weiteren Computers und mit einer Entwicklungsumgebung (IDE), wie beispielsweise Arduino, erstellt werden. Bei einem vorgegeben Quellcode können ebenfalls Änderungen mit einer IDE vorgenommen werden.

3.1.2.1 Funktion des Programms

Abb.: Flussdiagramm zur Darstellung des Programms, welches auf den ESP8266 übertragen wird.

Zunächst wird eine WIFI-Verbindung aufgebaut. Dafür muss das Programm die nötigen Informationen erhalten. Dazu gehören Name des Router und das Passwort.
Sobald eine bestehende WIFI-Verbindung existiert, werden laufend Spannungswerte vom Sensor zum ESP8266 gesendet. Dabei sind dem Programm bestimmte Schwellenwerte vorgegeben, um zu entscheiden, ob die Pflanze Wasser benötigt oder nicht. Das Programm liest die Werte und entscheidet dann über die Bewässerung der Pflanze.
Wenn die Pflanze gegossen wurde, soll diese für mehrere Sekunden nicht gegossen werden können, damit die Erde der Pflanze das Wasser zunächst aufnehmen kann. Der Sensor erhält außerdem Zeit, um neue Werte zu messen und zu entscheiden, ob die Wassermenge ausreicht. Falls die Wassermenge nicht ausreicht, wird die Pumpe wieder aktiviert. Dieser Ablauf wiederholt sich solange, bis die Erde der Pflanze ausreichend Wasser aufgenommen hat.

Für die Übertragung der Sensorwerte und die Steuerung zur Bewässerung der Pflanze via App, müssen ein Broker, ein Port, ein WIFI-Netz und Topics zum Lesen und Schreiben im Programm des ESP8266 festgelegt werden.

Auch bei der Umsetzung der App müssen die festgelegten Topics des Brokers zum Lesen und Schreiben genutzt werden. Die App sollte erst dann umgesetzt werden, wenn sowohl die Hardware als auch die Software des ESP8266 einwandfrei funktioniert, um nicht weitere Probleme hinzuzufügen, da es ansonsten schwieriger wird, die Ursachen herauszufinden.

3.1.1 Beschreibung der Hardware

Abb.: Fertiggestellte Platine, welche für das Projekt genutzt werden kann.*

Die Hardware besteht aus den folgenden Komponenten:

  • 1x Pumpe
  • 1x Sensor**
  • 1x Platine (inkl. 1x ESP8266, 1x 12v –> 3,3V Spannungswandler)

Um die Platine vor Feuchtigkeit zu schützen, soll diese in einem Behälter installiert werden. Sowohl die Pumpe als auch die Platine sollen durch eine Installation auf einer Holzwand die nötige Stabilität erhalten, um keinen Bewegungsspielraum zu ermöglichen. Diese Holzwand kann neben der ausgewählten Zimmerpflanze aufgestellt werden. Die Kabel des Sensors und des Netzteils sind an der Platine angeschlossen. Auch die Pumpe ist an der Platine angeschlossen. Die Kontakte zur Platine wurden mit einer Heißklebepistole verdichtet, damit kein Wasser auf die Platine kommen kann. Die Pumpe ist an zwei Schläuchen angeschlossen. Der eine Schlauch saugt das Wasser aus dem Wasserbehälter und der andere pumpt das angesaugte Wasser zur Pflanze. Dazu muss der Schlauch, welcher zur Pflanze führt, gut befestigt werden, damit die Erde mit Wasser versorgt werden kann. Zur Befestigung des Schlauchs können Drahtstücke oder Kunststoffklammern genutzt werden, die in die Erde gesteckt werden. Auch eine Befestigung des Schlauchs am ausgewählten Wasserbehälter ist sinnvoll, da auch dieser durch das Ansaugen des Wassers seine Position wechseln könnte, sodass schließlich der Schlauch kein Wasser ansaugen kann.

Abb.: Einige Ausschnitte der Platinenschaltung.*

Es ist darauf zu achten, dass der Sensor, welcher den Wasserstand der Pflanze misst, nicht zu locker in der Erde sitzt. Wenn der Sensor zu locker in der Erde sitzt, kann der Sensor nicht den Wasseranteil der Erde messen, da sich Luft zwischen Erde und Sensor befindet.

Außerdem sollen die elektrischen Kontakte oberhalb des Sensors vor Wasser geschützt werden. Dazu können die Kontakte mit einer Heißklebepistole überklebt werden.


*Die dargestellte Platine wurde von Anatolij Fandrich entworfen.
**Sensor: Hygrometer

3.1 Schritte für die Umsetzung

Für die Umsetzung des Projekts ist eine grobe Unterteilung hilfreich, um kleine Hardware- und Software-Komponenten schnell und erfolgreich umsetzen zu können. Außerdem ermöglicht eine Unterteilung des Projekts eine bessere Testbarkeit, da die einzelnen Komponenten unabhängig voneinander getestet und ggf. verbessert werden können.

Empfehlenswert ist eine Definition oder eine übersichtliche Skizze des Projekts, um die Schritte zur Umsetzung effektiv vornehmen zu können.

Wie bereits beschrieben, beinhaltet das Projekt folgende Punkte:

  • Feuchtigkeitsmessung der Erde
  • Ein 12V-Netzteil zur Stromversorgung der Hardware (Platine und Pumpe)
  • Eine Pumpe, die Wasser aus einem Behälter, wie beispielsweise aus einer Gießkanne, an eine Pflanze pumpen kann.
  • Eine programmierbare Hardware zur automatisierten Steuerung der Bewässerung.
    • Die Hardware muss 12V in die Betriebsspannung von 3,3V umwandeln können, um nicht zwei unterschiedliche Netzteile für die Pumpe und die Hardware nutzen zu müssen.
    • Die Hardware muss mindestens einen AD-Konverter beinhalten, um die Werte des Feuchtigkeitssensors empfangen zu können.
    • Die Hardware muss WIFI-fähig sein, um drahtlos eine Internetverbindung aufbauen zu können, damit sich die Bewässerungsanlage mit einem externen Gerät via MQTT lesen und steuern lässt.
  • Zusätzlich wird ein Computer benötigt, um die Software zur automatisierten Bewässerung der Pflanze via USB auf die Hardware übertragen zu können.
  • Um drahtlos via Internetverbindung Werte vom Sensor lesen zu können, ist ein weiteres internetfähiges Gerät mit Anzeige notwendig. Dazu eignet sich ein Smartphone hervorragend.
  • Eine App soll es ermöglichen, Werte vom Sensor lesen zu können. Außerdem soll es möglich sein, die Pflanze via App zu gießen. Dies soll auch außerhalb der automatisierten Bewässerung ermöglicht werden.

Für die Umsetzung des Projekts ist eine Unterteilung in Hardware und Software sinnvoll. Die Hardware kann als erstes, unabhängig von der Software, entwickelt werden. Für die Software zur Steuerung der Hardware ist nach der Fertigstellung zu berücksichtigen, welche Anschlüsse für die Pumpe und für den Sensor zu verwenden sind.

Nach der Fertigstellung der Hardware und Software zur automatisierten Bewässerung, soll eine App fertiggestellt werden, die es ermöglicht Sensorwerte zu lesen und auch zu gießen. Dazu soll MQTT verwendet werden, sodass ein Broker und mindestens zwei Topics für die Umsetzung benötigt werden. Die Topics zum Lesen und Schreiben müssen sowohl in der Software für die Platine als auch in der Software für die App genutzt werden. Dies bedeutet, dass bei der Fertigstellung der Software für die Platine bereits MQTT, Broker, Topics, Ports und WIFI-Verbindung berücksichtigt werden müssen.


3.0 Planung des Projekts

Die Bewässerungsanlage besteht im Wesentlichen aus einem Sensor, einer Platine mit integriertem ESP8266, einer Wasserpumpe und einer vollen Gießkanne mit Wasser.
Sowohl der Sensor, welcher die Feuchtigkeit in der Erde misst, als auch die Pumpe sind an die Platine angeschlossen. Dabei werden gemessene Spannungswerte des Sensors kontinuierlich an den ESP8266 gesendet. Ein 12V-Netzteil versorgt die Platine sowie die Pumpe mit Energie. Der ESP8266 wird mit einem Router via WIFI verbunden, um via App mit der Bewässerungsanlage kommunizieren zu können. Für die Kommunikation zwischen der Bewässerungsanlage und der App wird MQTT verwendet.

Abb.: Skizze als Hilfestellung zur Umsetzung.*

*Senor: Hygrometer