Big Sister is Watching You – Die totale Überwachung einer Stevia-Pflanze

Stevia-Pflanze mit Arduino und Sensoren

Nun ist es soweit: Seit ein paar Minuten steht meine Stevia-Pflanze unter totaler Überwachung, mit Unterstützung von Arduino natürlich. Und das 24 Stunden lang oder länger. Das ist gewissermassen mein erstes echtes Projekt, das nicht mehr unter “Mit Arduino herumspielen” läuft. Allerdings musste ich erst etwas umdisponieren. Ursprünglich wollte ich ja auf meinem Balkon für meine Blumen Werte wie Temperatur, Feuchtigkeit, Bodenfeuchtigkeit und Licht messen.

Dabei war das Fernziel, den Arduino autonom zu betreiben. Das bedingt aber auch die Verwendung einer Real Time Clock (RTC) und eines SD-Card-Moduls (die teurere WiFi-Variante oder Funk-Variante wollte ich mir sparen). Mit etwas Herumknobeln brachte ich sogar SD-Card und RTC zum Laufen, aber die Initialisierung der Zeit auf dem 1302-Chip wollte nie so richtig klappen. Zwar lief die RTC-Komponente, aber eigentlich nie mit der aktuellen Zeit. Und irgendwann beim Herumprobieren habe ich dann das RTC-Modul vermutlich zerstört. Auf jeden Fall erhalte ich seit geraumer Zeit nur noch 1.1.2000 zurück.

Da man ein RTC-Modul nicht gleich um die Ecke kaufen kann, war ich gezwungen umzudisponieren. Mein Netbook ist ohnehin schlecht ausgelastet, und im Moment ist nicht die Jahreszeit für Freiluftmessungen. Es lag also nahe, die Daten nicht direkt im Arduino zu verarbeiten, sondern im Netbook, wo ich sie komfortabel mit Datum und Uhrzeit versehen kann. Da die Einbindung von COM-Ports in Java nicht ganz einfach ist, und ich schon öfter Webanwendungen in CSharp geschrieben habe, lag es nahe, dafür Visual Studio Express 2012 und CSharp zu verwenden.

Seit dieser Einleitung ist fast ein Monat vergangen. Erst jetzt habe ich mich aufgerafft, den Artikel fertig zu schreiben. Dafür gibt im Abschnitt Demo aber eine Datenreihe über diesen Zeitraum zu sehen.

Projektziel

In diesem Projekt misst man mit mehreren Sensoren für Pflanzen relevante Umgebungswerte wie Temperatur, Luftfeuchtigkeit, Bodenfeuchtigkeit und Helligkeit. Die Daten werden via serielle Schnittstelle an einen Computer gesendet, der sie mit einer CSharp-Konsolenapplikation entgegennimmt, mit Datum und Uhrzeit versieht und in eine CSV-Datei speichert.

Als Versuchspflanze bot sich meine Stevia an. Sie ist nicht frosthart, so dass ich sie im Spätherbst vom Balkon in die Wohnung übersiedeln muss, was ihr meist mangels Licht nicht sonderlich gut bekommt. Sie hängt an einem Blumat-Pfropfen, so dass ich dabei auch gleich überprüfen kann, wie gut diese Bewässerungsart funktioniert.

Komponenten

Die Komponenten für dieses Projekt stammen abgesehen vom Lichtsensor nicht aus meinem Arduino-Experimentierkit, sondern ich habe sie mir speziell für diesen Zweck gekauft.

Elektronische Komponenten

  • 1 Arduino UNO R3
  • 1 Steckbrett
  • ganz viele Jumperkabel M/M und M/F
  • 1 kombinierter Feuchtigkeits- und Temperatursensor: DHT11; Achtung mein Sensor weist nur 3 Pins auf und hat eine etwas andere Pin-Belegung als im Datenblatt
  • 1 Sensor für die Bodenfeuchtigkeit: SKU:SEN0114
  • 1 Lichtsensor aus Kit, vermutlich Excelitas Tech LDR VT90N2 oder VT935G
  • 1 Widerstand 10kOhm
  • 1 Netbook, Notebook oder sonstiger Computer mit installiertem .NET-Framework und Entwicklungsumgebung Visual Express Studio 2012 oder älterer Version
  • 1 USB-Kabel zur Verbindung von Netbook und Arduino

Nichtelektronische Komponenten

  • eine Stevia oder irgendeine andere Pflanze, die in der Erde wächst (ich würde mal vermuten, dass der Feuchtigkeitssensor mit Hydrokultur nicht wirklich gut funktioniert)

Bestückungsplan

Zur Zeit sind drei Sensoren in der Schaltung verbaut (Details siehe Komponentenliste):

  • Sensor für Bodenfeuchtigkeit, als schwarzes Mystery-Teil dargestellt
  • Photowiderstand als Lichtsensor unten links
  • Feuchtigkeits- und Temperatursensor, blaues Kästchen rechts

Arduino mit Sensoren für Pflanzen: Bodenfeuchtigkeit, Temperatur, Feuchtigkeit, Licht

Code

Der Code umfasst bei diesem Projekt nicht nur den Arduino- sondern natürlich auf den mit Visual Studio Express 2012 erstellten CSharp-Code, der die Daten aus der Schnittstelle entgegennimmt.

Arduino

Der Code für den DHT11 stammt von DFRobot.

//Dieses Programm macht nur mit der zughörigen CSharp-Anwendung Sinn!
//CSharp liest Daten, gibt das Datum dazu
//und hängt die Daten einer CSV-Datei an

//generelle Einstellungen
char tab = 9;
unsigned long myDelay = 10000;
int val = 0; //eingelesener Wert aus serieller Schnittstelle
//Type ist nötig, weil Multiplikation mit 1000 zu integer führt
unsigned long faktor = 1000;

//Eingabe des Delays in Sekunden
char incoming[5] = {};

//Lichtsensor
int lightPin = 1;

#define dht11_pin 14 //Analog port 0 on Arduino Uno

byte read_dht11_dat() {
  byte i = 0;
  byte result=0;
  for(i=0; i< 8; i++) {     while (!digitalRead(dht11_pin));     delayMicroseconds(30);     if (digitalRead(dht11_pin) != 0 )       bitSet(result, 7-i);     while (digitalRead(dht11_pin));   }   return result; }       void setup(){   pinMode(dht11_pin, OUTPUT);   digitalWrite(dht11_pin, HIGH);   Serial.begin(9600); }        void loop(){   //Delay ändern   int j = 0;   //über die serielle Schnittstelle kann man das Intervall für die    //Datenerfassung bestimmen   if (Serial.available() > 0) {
    //sonst bleiben die 0 erhalten 60 -> 600
    memset(incoming, 0, sizeof(incoming));
    while (Serial.available() > 0 && j < sizeof(incoming) - 1) {
      incoming[j] = Serial.read();
      j++;
      delay(3);
    }

    //array of char in int wandeln
    val = atoi(incoming);
    myDelay = faktor * val;

    Serial.print("neues Delay ");
    Serial.print(val);
    Serial.println(" Sekunden");
  }

  //Daten für Temperatur- und Feuchtigkeitssensor auslesen
  byte dht11_dat[5];
  byte dht11_in;
  byte i;// start condition

  digitalWrite(dht11_pin, LOW);
  delay(18);
  digitalWrite(dht11_pin, HIGH);
  delayMicroseconds(1);
  pinMode(dht11_pin, INPUT);
  delayMicroseconds(40);

  if (digitalRead(dht11_pin)) {
    Serial.println("!Temperatursensor dht11 startet nicht");
    delay(1000);
    return;
  }
  delayMicroseconds(80);
  if (!digitalRead(dht11_pin)) {
     Serial.println("!Temperatursensor dht11 startet immer noch nicht");
    return;
  }

  delayMicroseconds(80);
  for (i=0; i<5; i++)  {
    dht11_dat[i] = read_dht11_dat();
  }

  pinMode(dht11_pin, OUTPUT);
  digitalWrite(dht11_pin, HIGH);
  byte dht11_check_sum = dht11_dat[0]+dht11_dat[2];// check check_sum
  if(dht11_dat[4]!= dht11_check_sum) {
    Serial.println("!DHT11 Checksummen-Error");
  }

  //Daten an die serielle Schnittstelle ausgeben

  //*********************************************
  //Feuchtigkeit und Temperatur

  //Feuchtigkeit
  Serial.print(dht11_dat[0], DEC);
  Serial.print("%");
  Serial.print(tab);
  //Temperatur
  Serial.print(dht11_dat[2], DEC);
  Serial.print(tab);

  //*********************************************
  //Bodenfeuchtigkeit
  //bei 5V 0 an Luft, 800 im Wasser
  //bei 3.3V bis ca 485
  float soilHumidity = analogRead(2);
  soilHumidity = constrain(map(soilHumidity, 0, 800, 0, 100), 0, 100);
  Serial.print(soilHumidity);
  Serial.print("%");
  Serial.print(tab);

  //*********************************************
  //Licht
  //Wert von ca. 0 bis 1023
  //Gesteckt 5 V - 1. Bein - 2. Bein 10 KOhm Widerstand
  //und Arduino-Pin - Ausgang Widerstand GND
  float lightLevel = analogRead(lightPin);
  //Mittel aus 3 Messungen
  delay(10);
  lightLevel = lightLevel + analogRead(lightPin);
  delay(10);
  lightLevel = lightLevel + analogRead(lightPin);
  lightLevel = map(lightLevel/3, 0, 1023, 0, 100);
  Serial.print(lightLevel);
  Serial.print("%");
  Serial.print(tab);

  //*********************************************
  //Bodenfeuchtigkeit Eigenbau
  //bei 5V 0 an Luft, 800 im Wasser
  //bei 3.3V bis ca 485
  float soilHumidity2 = analogRead(3);
  Serial.print(soilHumidity2);

  //Zeilenende
  Serial.println("");

  delay(myDelay-500); //nächster Durchgang
}

CSharp

Das CSharp-Programm ist ein reines Konsolenprogramm, das allerdings endlos läuft.

using System;
using System.IO;
using System.IO.Ports;
using System.Configuration;
using System.Collections.Specialized;
using ArduinoReadFromSerial.Properties;

namespace test {
  class Program {

    static void Main(string[] args) {
      Settings settings = new Settings();
      SerialPort port = new SerialPort(settings.port, 9600);
      port.Open();
      port.WriteLine(settings.delayInSek.ToString());
      String filePathAndName = settings.exportpfad;
      String ext = ".csv";
      String filedate = String.Format("{0:yyyyMMdd_HHmmss}", DateTime.Now);
      String fileAll = filePathAndName + "_" + filedate + ext;
      TextWriter tw = new StreamWriter(fileAll, false);
      Console.WriteLine(fileAll);
      String tab = char.ConvertFromUtf32(9);
      String header = "Datum" + tab + "Luftfeuchtigkeit in Prozent" + tab
          + "Temperatur in Grad Celsius" + tab + "Bodenfeuchtigkeit" + tab
          + "Licht in Prozent" + tab + "Bodenfeuchtigkeit Eigenbau";
      Console.WriteLine(header);
      tw.WriteLine(header);
      // close the stream
      tw.Close();

      while (true) {
        tw = new StreamWriter(fileAll, true);
        String myVar = port.ReadLine();
        //Warnhinweise beginnen mit ! -> nicht in Datei schreiben
        if (!myVar.StartsWith("!")) {
          //Hier noch Datum und Zeit vorne dran hängen
          DateTime now = DateTime.Now;
          myVar = String.Format("{0:dd.MM.yyyy HH:mm:ss}", now) + tab + myVar;
          tw.Write(myVar);
          tw.Close();
        }
        Console.WriteLine(myVar);
      }
    }
  }
}

Und so sehen die produzierten Daten aus:

Datum	Luftfeuchtigkeit in Prozent	Temperatur in Grad Celsius	Bodenfeuchtigkeit	Licht in Prozent	Bodenfeuchtigkeit Eigenbau
25.11.2012 23:16:00	37%	25	100.00%	73.00%	1019.00
25.11.2012 23:17:00	37%	25	100.00%	72.00%	1023.00
25.11.2012 23:18:00	37%	25	100.00%	73.00%	1022.00
25.11.2012 23:19:00	37%	25	100.00%	74.00%	1021.00
25.11.2012 23:20:00	37%	25	100.00%	73.00%	1021.00
25.11.2012 23:21:00	37%	25	100.00%	73.00%	1021.00
25.11.2012 23:22:00	37%	25	100.00%	73.00%	1021.00

Tipps zum CSharp-Projekt

Das Programm entwickelt habe ich auf meinem Notebook. Visual Studio Express auf meinem Netbook zu betreiben, würde mich ziemlich sicher auf die Palme bringen, weil das Kistchen zu wenig Ressourcen für den flüssigen Betrieb einer Entwicklungsumgebung hat. Also stand ich ganz rasch vor dem Problem, dass ich meine Konsolenapplikation konfigurierbar machen musste, so dass die Einstellungen für Dateipfad und seriellen Port aus einer änderbaren Konfigurationsdatei stammen. In einem Konsolenprojekt unter Visual Express Studio 2012 erstellt man diese, indem man im Projektmappen-Explorer Properties direkt unterhalb des Projektnamens doppelklickt. Unter “Einstellungen” habe ich die folgenden Werte erfasst:

  • exportpfad: C:\meinpfad\meinedatei (ohne Datei-Endung, da noch Datum und Uhrzeit angehängt wird)
  • port: COM9 (wechselt je nach Computer)
  • delayInSek: 60 (so kann man die Frequenz, mit der Daten gesammelt werden, individuell einstellen)

Um die Applikation auf anderen Rechner installieren zu können, geht man unter Erstellen – MeinProjekt veröffentlichen.

Da die Konsolen-Applikation in ein absolut obskures Verzeichnis installiert wird, und ich nicht jedesmal danach suchen wollte, um meine Einstellungen in der Config-Datei für das Netbook zu ändern, kam ich auf die Idee, die Konfigurationsdatei noch vor der Installation zu ändern, denn vom Installationsverzeichnis weiss ich genau, wo es liegt. Doch ich hatte die Rechnung ohne Microsoft gemacht: Die Installation wurde aus Sicherheitsgründen abgebrochen, weil der Hash-Code der von mir manipulierten Konfigurationsdatei nicht mehr mit jenem des Projektes übereinstimmte!

Properties in CSharp für konfigurierbare Einstellungen

Demo

Mit einer bestimmten Zahl an Sensoren wird die Schaltung ziemlich unübersichtlich.  Oben links sieht man Bodenfeuchtigkeitssensor, bzw. jener Teil davon, der nicht im Boden steckt. In der linken oberen Ecke des Steckbretts steht der Photosensor. Und das blaue Teil im unteren Teil des Steckbretts ist der kombinierte Feuchtigkeits- und Temperatursensor. Das orange Kabel führt zu einem nicht sichtbaren und auf dem Bestückungsplan nicht erwähnten selbst gebastelten Feuchtigkeitssensor: Ein Stück Styropor mit zwei verkabelten Nägeln. Am Arduino hängt übrigens auch schon die SD Card, auch wenn sie im Moment noch absolut funktionslos ist.

Arduino und Sensoren

Und wozu das Ganze? Am Schluss kann man die Daten aus der Textdatei in Excel holen und mit PivotTables auswerten oder als Diagramme darstellen. Für den Lichtverlauf sieht das folgendermassen aus:

Lichtverlauf im November und Dezember 2012

Comments are closed.