Arduino Uno R3
Ich habe diese Schaltung entwickelt, weil ich immer Probleme mit meinen Pflanzen hatte. Entweder die Samen haben nicht gekeimt oder die Pflanzen sind später eingegangen. Diese Schaltung ist dafür gedacht, dass man die Temperatur überwachen kann, damit die Samen besser keimen. Bei dieser Aufgabe hilft uns der Mikrocontroller Arduino Uno R3.
Temperatur und Luftfeuchtigkeit
Meine Chili-Samen benötigen ca. 20-30 ° C (weniger geht auch, aber dauert wesentlich länger) und eine Luftfeuchtigkeit von 60-80 %.
Benötigte Bauteile
- Arduino-Mikrocontroller
- Usb-Kabel für Arduino
- 9 LED’s (2 x rot, 2 x gelb, 5 x grün)
- 9 Widerstände 330 Ohm
- 13 Jumper-Kabel bzw. Schaltdraht
- DHT11 Modul (Sensor für Temperatur und Luftfeuchtigkeit)
Was soll die Schaltung können?
Der Sensor befindet sich im Topf der Pflanze und darüber ist Frischhaltefolie. Der Arduino misst die Spannung vom Sensor. Intern wird der Spannungswert in einen Temperatur- und Luftfeuchtigkeitswert umgewandelt. Darüber brauchen wir uns keine Gedanken machen. Das übernehmen Bibliotheken, die wir nur in unseren Code einbinden brauchen. Ebenfalls gibt es vorgefertigten Code für die Anzeige auf dem Seriellen Monitor von Arduino. Man muss also nicht das Rad neu erfinden. Es reicht, wenn wir den Code nach unseren Bedürfnissen anpassen. Ich werde später in den Paxisbeispielen genauer auf Begrifflichkeiten eingehen.
Schaltplan
Nächster Schritt
Nun haben wir alles was wir brauchen, bis auf den Programmcode. Bevor wir mit dem beginnen, klären wir noch was das Programm können soll. Wir haben also unsere Temperaturwerte und die müssen jetzt verarbeitet werden. Mit einem vorgefertigten Code kann ich mir die Werte von dem Arduino auf dem Seriellen Monitor anzeigen lassen. Den findet man, wenn die Arduinio-Software installiert wurde, unter dem Reiter Werkzeuge–>Serieller Monitor. Der erlaubt uns die Daten zu sehen, die der Arduino per USB an den Rechner schickt. Das ganze könnte dann so aussehen (die Ausgabe habe ich nach meinen Bedürfnissen angepasst).
Im Grunde genommen wäre man jetzt schon fertig. Der Nachteil ist, man muss den PC ständig laufen lassen. Um das zu vermeiden, kommen die 9 LED’s ins Spiel. Diese werde uns die Temperatur in denen von uns festgelegten Bereichen zeigen. Es soll immer nur eine LED leuchten. Jede einzelne steht für einen Bereich. Meine Festlegung lautet:
- LED 15 ° C und alles was darunter liegt
- LED 16-17 ° C
- LED 18-19 ° C
- LED 20 ° C
- LED 21 ° C
- LED 22 ° C
- LED 23 ° C
- LED 24-29 ° C
- LED 30 ° C und alles was darüber liegt
Damit haben wir alle möglichen Temperaturen abgedeckt. Die Bereiche könnt ihr natürlich nach euren Belieben ändern, indem ihr den Programmcode anpasst.
Kurze Zusammenfassung zum Ablauf
- Eingabe: Der Arduino bekommt die Temperaturwerte
- Verarbeitung: Anhand der Werte wird entschieden, was passieren soll (z. B. welche LED leuchten soll)
- Ausgabe: in unserem Fall es leuchtet die ausgewählte LED
Der Programmcode
//Bibliotheken einbinden
#include <SimpleDHT.h>
//Variabel
int pinDHT11 = 2;
SimpleDHT11 dht11;
// von mir bestimmte Variabeln
int zaehler = 0; //zaehlt die durchlaeufe
//variablen für die Lampen
int red15 = 4;
int yellow16_17 = 5;
int yellow18_19 = 6;
int green20 = 7;
int green21 = 8;
int green22 = 9;
int green23 = 10;
int green24_29 = 11;
int red30 = 12;
void setup() {
Serial.begin(9600); //serielle Datenübertragung
//Lampen werden als Ausgaenge festgelegt
pinMode(red15, OUTPUT);
pinMode(yellow16_17, OUTPUT);
pinMode(yellow18_19, OUTPUT);
pinMode(green20, OUTPUT);
pinMode(green21, OUTPUT);
pinMode(green22, OUTPUT);
pinMode(green23, OUTPUT);
pinMode(green24_29, OUTPUT);
pinMode(red30, OUTPUT);
}
void loop() {
// Messwerte
byte temperature = 0;
byte humidity = 0;
byte data[40] = {0};
byte temperature15 = 0; //2. Temperatur Variable
zaehler++; //zaehlt jeden Durchlauf
if (dht11.read(pinDHT11, &temperature, &humidity, data)) {
Serial.print(„Read DHT11 failed“);
return;
}
temperature15=temperature+temperature*0.15; //ausgelesene Temperatur wird um 15 % erhöht
//Entscheidung, welche Lampe leuchten wird
if (temperature15 <= 15)
{
digitalWrite(red15, HIGH);
digitalWrite(yellow16_17, LOW);
digitalWrite(yellow18_19, LOW);
digitalWrite(green20, LOW);
digitalWrite(green21, LOW);
digitalWrite(green22, LOW);
digitalWrite(green23, LOW);
digitalWrite(green24_29, LOW);
digitalWrite(red30, LOW);
}
else if (temperature15 >= 16 && temperature15 <= 17)
{
digitalWrite(red15, LOW);
digitalWrite(yellow16_17, HIGH);
digitalWrite(yellow18_19, LOW);
digitalWrite(green20, LOW);
digitalWrite(green21, LOW);
digitalWrite(green22, LOW);
digitalWrite(green23, LOW);
digitalWrite(green24_29, LOW);
digitalWrite(red30, LOW);
}
else if (temperature15 >= 18 && temperature15 <= 19)
{
digitalWrite(red15, LOW);
digitalWrite(yellow16_17, LOW);
digitalWrite(yellow18_19, HIGH);
digitalWrite(green20, LOW);
digitalWrite(green21, LOW);
digitalWrite(green22, LOW);
digitalWrite(green23, LOW);
digitalWrite(green24_29, LOW);
digitalWrite(red30, LOW);
}
else if (temperature15 == 20)
{
digitalWrite(red15, LOW);
digitalWrite(yellow16_17, LOW);
digitalWrite(yellow18_19, LOW);
digitalWrite(green20, HIGH);
digitalWrite(green21, LOW);
digitalWrite(green22, LOW);
digitalWrite(green23, LOW);
digitalWrite(green24_29, LOW);
digitalWrite(red30, LOW);
}
else if (temperature15 == 21)
{
digitalWrite(red15, LOW);
digitalWrite(yellow16_17, LOW);
digitalWrite(yellow18_19, LOW);
digitalWrite(green20, LOW);
digitalWrite(green21, HIGH);
digitalWrite(green22, LOW);
digitalWrite(green23, LOW);
digitalWrite(green24_29, LOW);
digitalWrite(red30, LOW);
}
else if (temperature15 == 22)
{
digitalWrite(red15, LOW);
digitalWrite(yellow16_17, LOW);
digitalWrite(yellow18_19, LOW);
digitalWrite(green20, LOW);
digitalWrite(green21, LOW);
digitalWrite(green22, HIGH);
digitalWrite(green23, LOW);
digitalWrite(green24_29, LOW);
digitalWrite(red30, LOW);
}
else if (temperature15 == 23)
{
digitalWrite(red15, LOW);
digitalWrite(yellow16_17, LOW);
digitalWrite(yellow18_19, LOW);
digitalWrite(green20, LOW);
digitalWrite(green21, LOW);
digitalWrite(green22, LOW);
digitalWrite(green23, HIGH);
digitalWrite(green24_29, LOW);
digitalWrite(red30, LOW);
}
else if (temperature15 >= 24 && temperature15 <= 29)
{
digitalWrite(red15, LOW);
digitalWrite(yellow16_17, LOW);
digitalWrite(yellow18_19, LOW);
digitalWrite(green20, LOW);
digitalWrite(green21, LOW);
digitalWrite(green22, LOW);
digitalWrite(green23, LOW);
digitalWrite(green24_29, HIGH);
digitalWrite(red30, LOW);
}
else if (temperature15 >= 30)
{
digitalWrite(red15, LOW);
digitalWrite(yellow16_17, LOW);
digitalWrite(yellow18_19, LOW);
digitalWrite(green20, LOW);
digitalWrite(green21, LOW);
digitalWrite(green22, LOW);
digitalWrite(green23, LOW);
digitalWrite(green24_29, LOW);
digitalWrite(red30, HIGH);
}
//Ausgabetext auf dem seriellen Monitor (nur erforderlich fuer genaue Ausgabe Temperatur und Luftfeuchtigkeit)
Serial.println(„******* vorbei mit Langeweile *******“);
Serial.print(„Messung „); Serial.println(zaehler); //am Tag maximal 8640 Messungen
Serial.print(„Die Temperatur betraegt: „); Serial.print(temperature15); Serial.println(“ *C, „);
Serial.print(„Die Luftfeuchtigkeit betraegt: „); Serial.print((int)humidity); Serial.println(“ %“);
delay(10000);
}
Erklärung zum Programmcode
Es sieht auf den ersten Blick sehr viel aus, aber wenn mal die Zeilen überfliegt, erkennt man schnell die Wiederholung. Es ändern sich oftmals nur wenige Werte.
Bibliotheken
In der zweiten Zeile „#include “ wird eine Bibliothek eingebunden. Bibliotheken sind Programmcode. Oftmals werden gewisse Programmzeilen auch in anderen Programmen benötigt. In unserem Fall übernimmt die Bibliothek die Aufgabe den Messwert vom Sensor, in einen Temperaturwert umzuwandeln. Das erleichtert uns die Arbeit. So brauchen wir in unserem Code den Temperaturwert nur abfragen. Die Bibliothken müssen runtergeladen und bei der Arduino Software hinzugefügt werden. Das Ganze unter Sketch/Bibliothek einbinden/.zip-Bibliothek hinzufügen. Hier gibt es die <SimpleDHT.h>.
Variablen
Danach werden Variablen festgelegt. Die sorgen dafür, dass wir Werte speichern und später wieder aufrufen können. z. B. die Zeile „int zaehler = 0;“. Genauso wird unserer Temperaturwert in einer Variabel gespeichert. Es gibt noch wesentlich mehr zum Thema Variablen und Datentypen, aber das würde den Rahmen sprengen. Diese Seite kann ich zum Nachlesen empfehlen.
Eingänge und Ausgänge definieren
Im void setup Teil werden z. B. die Baudrate für die serielle Datenübertragung festgelegt. In unserem Fall 9600. Beim seriellen Monitor kann man ebenfalls die Baudrate einstellen. Die muss mit der im Code festgelegten Rate übereinstimmen. Mit der pinMode-Funktion kann man bestimmen, ob ein Port als Eingang oder Ausgang definiert wird. In unserem Fall brauchen wir nur Ausgänge (OUTPUT), da die Lampe leuchten soll. Bei Eingängen fragt man etwas ab, z. B. ob ein Schalter gerade auf an oder aus steht.
Void loop
Hier beginnt unsere Schleife. Nachdem der Code in der {-Klammer abgearbeitet wurde, geht es wieder am Anfang des loop-Teils los. Es beginnt immer wieder von vorn und wird abgearbeitet. Die englischen Variablen sind von dem vorgefertigten Code und diese habe ich so übernommen. Ich musste nur eine kleine Anpassung vornehmen. Dazu später mehr.
zaehler++; steht für meinen Zähler, der sich jeden Durchlauf um 1 erhöht. In der Ausgabe ist es dann die Anzahl der Messvorgänge.
Falls ein Fehler vorliegt, gibt das die folgende If-Anweisung aus.
Mein Sensor hat eine Toleranz +-2 ° C. Bei der Überprüfung musste ich feststellen, dass die Abweichung bei mir etwas größer ist und habe den Wert angepasst. In meinem vorkommenden Temperaturbereich sind das etwa 15 %, die zu wenig angezeigt werden. Daher nehme ich den erhaltenen Messwert und addiere davon 15 % nochmal drauf. Es ist nicht genau, aber es nähert sich in meinem Fall besser an. Das Ganze passiert hier: „temperature15=temperature+temperature*0.15;“. auf der rechten Seite wird alles zusammengerechnet und auf der linken Seite in der Variabel gespeichert.
Entscheidung welche Lampe leuchtet
Jetzt kommt eine Menge Code. Aber keine Sorge hier erkennt man schnell ein Schema. Es ist lediglich eine Copy-Paste Geschichte. Man muss danach bloß die richtigen Werte ändern.
if (temperature15 <= 15)
{
digitalWrite(red15, HIGH);
digitalWrite(yellow16_17, LOW);
digitalWrite(yellow18_19, LOW);
digitalWrite(green20, LOW);
digitalWrite(green21, LOW);
digitalWrite(green22, LOW);
digitalWrite(green23, LOW);
digitalWrite(green24_29, LOW);
digitalWrite(red30, LOW);
}
In diesem Ausschnitt findet eine Fallunterscheidung statt. Es wird nur der {}-Block ausgeführt, wenn die Bedingung in den () richtig ist. Im Wortlaut: Wenn die Temperatur kleiner gleich 15 ist, dann soll Lampe15 leuchten und alle anderen sollen aus bleiben. Angekommen der Wert wäre über 15, dann würde der {} übersprungen werden und es geht nach der } weiter. In unserem Fall findet die nächste Abfrage statt. Bloß diesmal wird gefragt, ob die Temperatur zwischen 16 und 17 liegt. Wenn ja Lampe16_17 geht an, alle anderen bleiben aus. Wenn nein wird der {}-Teil wieder übersprungen und es geht zur nächsten Abfrage. Und so geht das weiter für alle Lampen, bis man jeden Bereich abgedeckt hat.
Beispiel für Fallunterscheidung
Man kann sich das Ganze so vorstellen. Wenn es heute regnet, bleibe ich in der Wohnung. Wenn es nicht regnet, dann sehe ich weiter, was ich mache. Beim programmieren bedeutet das, ich gehe im Code weiter. Wichtig ist dabei die Temperaturbereiche klar abzugrenzen, damit immer nur eine LED leuchtet.
Schlussteil
Hier ist die Ausgabe für den seriellen Monitor. Den Serial.print-Abschnitt kann man auch weglassen, wenn man nur die LED’s als Anzeige haben möchte.
delay(10000); hier findet eine Pause statt. Die Zeit wird in ms angegeben. Also 10000 ms sind 10 s. Bei mir wird alle 10 s eine Messung durchgeführt.
Dann viel Spaß beim ausprobieren. Hinterlasst mir doch mal einen Kommentar, ob es bei euch funktioniert hat.
Dann noch einen schönen Tag:)