,
06 Jun

(Boden-)Feuchtigkeit messen mit Arduino: Teil 2

Weiter geht’s mit dem Feuchtigkeitssensor und Arduino Uno. 🙂 Statt Grundgerüst gibt es heute die erweiterte Version – zuerst mit Prozentangaben, dann ergänzt um eine Mittelwertberechnung für höhere Genauigkeit. Tutorial Teil 2 von 2.

Bodenfeuchtigkeit messen mit einem Arduino Feuchtigkeitssensor bzw soil moisture sensor - erweiterte Version mit ein paar Features

 

 

Allgemein

Der Aufbau entspricht dem, der bereits im ersten Teil des Tutorials vorgestellt wurde: Arduino Uno (Amazon | eBay)* verkabelt mit YL-38 und YL-69 (Amazon | eBay)*.

An sich funktioniert der Code aus dem letzten Tutorial ja bereits. Wäre da nicht das etwas absurde Problem, dass statt der Feuchtigkeit eigentlich die Trockenheit angezeigt wird. Dem schaffen wir mit den Codebeispielen aus diesem Post Abhilfe, indem wir zunächst Feuchtigkeits-Prozentwerte ausgeben lassen. Danach erhöhen wir die Genauigkeit noch durch die Berechnung von Mittelwerten.

 

Feuchtigkeitssensor YL-38 mit Arduino Uno verbunden

Feuchtigkeitssensor YL-38 (und YL-69) mit Arduino Uno verbunden.

 

 

Bodenfeuchtesensor: Feuchtigkeit in Prozent angeben

Bislang gibt unser Bodenfeuchtigkeitssensor eher die Trockenheit als die Feuchtigkeit an: Je trockener die Zinken des Sensors sind, desto höher ist die Zahl. Dementsprechend müsste 1023 – die höchstmögliche Zahl – 0% Feuchtigkeit entsprechen und die niedrigste zu erreichende Zahl 100% Feuchtigkeit.

Damit sich das auch im seriellen Monitor niederschlägt, kann der folgende Code verwendet werden:

void setup() {
 Serial.begin(9600); // Serial-Port öffnen und auf 9600 Baud setzen
 pinMode (11, INPUT); // Pin 11 (digital) auf Input setzen
 pinMode (A0, INPUT); // Pin A0 (analog) auf Input setzen
 }

void loop() {
 int istTrocken = digitalRead(11); // Pin 11 auslesen -> in Variable istTrocken
 int feuchtigkeit = analogRead(A0); // Pin A0 auslesen -> in Variable feuchtigkeit
 int prozent = map(feuchtigkeit,230,1023,100,0); // ungefähre Prozentangabe durch Mapping
 
 Serial.print("Ist der Sensor trocken? "); // Kurzerklärung zum folgenden Wert
 if (istTrocken) // prüfen, ob istTrocken=1 (also true) ist ...
 { 
 Serial.println("Ja"); // ... wenn ja, dann "Ja" ausgeben ...
 }
 else // ... ansonsten ...
 { 
 Serial.println("Nein"); // ... "Nein" ausgeben
 }
 
 Serial.print("Gemessene Feuchtigkeit: "); // Kurzerklärung zum folgenden Wert
 Serial.println(feuchtigkeit); // Wert von "feuchtigkeit" ausgeben
 Serial.print("Feuchtigkeit in Prozent: "); //Kurzerklärung zum folgenden Wert
 Serial.println(prozent); // Wert von "prozent" ausgeben
 delay(1000); // 1 Sekunde warten
}

Wirklich neu ist, verglichen mit der Basisversion, nur die Verwendung von map und die Ausgabe der so ermittelten Prozentzahl (= Wert der Variablen prozent). Die Prozentzahl wird folgendermaßen per map ermittelt:

int prozent = map(feuchtigkeit,230,1023,100,0); // ungefähre Prozentangabe durch Mapping

Platt erklärt: map braucht neben der Variablen feuchtigkeit noch den niedrigsten Wert und den höchsten Wert, den feuchtigkeit haben kann; außerdem die ’neuen‘ Zahlen, denen diese Werte entsprechen sollen. Hier steht ein Wert von 230 für 100% und ein Wert von 1023 für 0% Feuchtigkeit. Alle Prozentzahlen dazwischen rechnet map aus und rundet diese. prozent ist eine Variable vom Typ Integer, also gibt es auch keine Nachkommastellen.

Die Ausgabe im Seriellen Monitor sieht jetzt so aus:

Feuchtigkeit mit Arduino-Sensor gemessen und in Prozent ausgegeben.

Feuchtigkeit mit Arduino-Sensor gemessen und in Prozent ausgegeben.

Natürlich ist eine Feuchtigkeit von 109%, wie sie im hier abgebildeten Beispiel auftritt, irgendwie komisch. Das liegt an der Schwelle von 230, die bei map angegeben wurde. Das Messsystem muss also kalibriert werden, um so genau wie möglich zu sein. Dafür benötigt ihr jetzt wieder das Glas Wasser: Sensor eintauchen und gucken, was der niedrigste regulär erzielbare Wert ist. Idealerweise könnte man nun aber auch einen richtig nassen und einen richtig trockenen Blumentopf verwenden.

Von Ausreißern abgesehen liegt bei mir der niedrigste Wert bei ungefähr 165. Das heißt, mein Code wäre jetzt

int prozent = map(feuchtigkeit,165,1023,100,0); // ungefähre Prozentangabe durch Mapping

Um die verbliebenen Ausreißer auszubügeln, kann man z.B. per if-Verzweigung alles über 100% abschneiden („falls Wert größer als 100 ist, den Wert einfach auf 100 setzen“). Oder ad nauseam nachkalibrieren. Oder mit der Berechnung eines Mittelwerts genauere Ergebnisse erzeugen (und auf Besserung hoffen ;-)).

 

 

Mittelwerte für die Feuchtigkeitsmessung berechnen

In dieser Version wird zehnmal gemessen, die Summe aller Messwerte gebildet – und diese Summe dann durch zehn geteilt, um einen Mittelwert zu berechnen.

void setup() {
 Serial.begin(9600); // Serial-Port öffnen und auf 9600 Baud setzen
 pinMode (11, INPUT); // Pin 11 (digital) auf Input setzen
 pinMode (A0, INPUT); // Pin A0 (analog) auf Input setzen
 }

void loop() {
 int istTrocken = digitalRead(11); // Pin 11 auslesen -> in Variable istTrocken

 int mittelwert = mittelwertBerechnen(); // Methode mittelwertBerechnen() aufrufen, Resultat in Variable mittelwert
 
 Serial.print("Ist der Sensor trocken? "); // Kurzerklärung zum folgenden Wert
 if (istTrocken) // prüfen, ob istTrocken=1 (also true) ist ...
 { 
  Serial.println("Ja"); // ... wenn ja, dann "Ja" ausgeben ...
 }
 else // ... ansonsten ...
 { 
  Serial.println("Nein"); // ... "Nein" ausgeben
 }
 
 Serial.print("Gemessene Feuchtigkeit (Mittelwert): "); // Kurzerklärung zum folgenden Wert
 Serial.println(mittelwert); // Mittelwert ausgeben
 Serial.print("In Prozent: "); // Kurzerklärung zum folgenden Wert
 Serial.println(map(mittelwert,165,1023,100,0)); // Prozentwert aus Mittelwert berechnen und ausgeben

}

int mittelwertBerechnen(){
 int ergebnis = 0; // Variable ergebnis
 for (int i = 0; i < 10; i++){ // solange i kleiner als 10 ist, i um 1 erhöhen, dann ...
  ergebnis = ergebnis + analogRead(A0); // ergebnis um den an A0 ausgelesenen Wert erhöhen
  delay(1000); // 1 Sekunde warten
 }
 ergebnis = ergebnis / 10; // ergebnis durch 10 teilen
 return ergebnis; // ergebnis zurückgeben
}

Dazu wird mit

int mittelwert = mittelwertBerechnen();

die Methode mittelwertBerechnen() aufgerufen und das Ergebnis in der Variablen mittelwert gespeichert. Die darauf folgenden Ausgaben von gemessener Feuchtigkeit und Prozentzahl (also auch das mapping) verwenden jeweils den Mittelwert.

Die Methode mittelwertBerechnen() an sich sieht so aus:

int mittelwertBerechnen(){
 int ergebnis = 0; // Variable ergebnis
 for (int i = 0; i < 10; i++){ // solange i kleiner als 10 ist, i um 1 erhöhen, dann ...
 ergebnis = ergebnis + analogRead(A0); // ergebnis um den an A0 ausgelesenen Wert erhöhen
 delay(1000); // 1 Sekunde warten
 }
 ergebnis = ergebnis / 10; // ergebnis durch 10 teilen
 return ergebnis; // ergebnis zurückgeben
}

Der Wert von ergebnis wird zunächst auf 0 gesetzt. Dann wird eine for-Schleife ausgeführt: solange die (bei 0 beginnende) Zählervariable i kleiner als 10 ist, wird i zunächst erhöht und dann der Code in der Schleife aufgerufen. Das heißt, die Schleife läuft zehnmal durch.

ergebnis = ergebnis + analogRead(A0); // ergebnis um den an A0 ausgelesenen Wert erhöhen delay(1000); // 1 Sekunde warten

Bei jedem Durchlauf wird die Variable ergebnis auf den bisherigen Wert von ergebnis plus den jeweils aktuell am Sensor (A0) ausgelesenen Feuchtigkeitswert gesetzt. Danach folgt eine Wartezeit von 1 Sekunde.

ergebnis = ergebnis / 10; // ergebnis durch 10 teilen
return ergebnis; // ergebnis zurückgeben

Nachdem die Schleife zehnmal durchlaufen wurde, wird ergebnis durch 10 geteilt, um den Mittelwert zu berechnen. Dieser wird dann zurückgegeben. Für genauere Ergebnisse oder Langzeitmessungen können Zähler i und die Wartezeit verändert werden. Wichtig: Nicht vergessen, dann auch die Division anzupassen. Ansonsten ist der Mittelwert entweder viel zu groß oder viel zu klein. 😉

Im Haupt-Loop wird die Variable mittelwert dann überall dort verwendet, wo im vorangegangenen Beispiel die Variable feuchtigkeit stand, also z.B. für die Ausgabe der Gesamtfeuchtigkeit und die Berechnung und Ausgabe der Prozentzahl im seriellen Monitor. Auch hier können/sollten Prozentwerte über 100% noch gekappt oder die für map verwendeten Werte angepasst werden.

 

Serieller Monitor: Mittelwerte der Feuchtigkeitsmessung

Serieller Monitor: Mittelwerte der Feuchtigkeitsmessung

Ansonsten ist die erweiterte Arduino-Feuchtigkeitsmessung mit Mittelwert und Prozentangabe jetzt fertig! 🙂