Gleich vorweg, eine richtige Wetterstation ist der in diesem Beitrag beschriebene Aufbau natürlich nicht. Dazu fehlen vor allem die Sensoren für Windrichtung und Windgeschwindigkeit, die im Eigenbau relativ schwer zu realisieren und zu eichen sind.
Aber trotzdem kann man mit einfachen Mitteln einige Grunddaten sammeln und online bereitstellen. Ich verwende hier derzeit – trotz aller Mängel – den Internet-of-Things Dienst thingspeak.com.
Meine Wetterstation soll eigentlich ein Datensammler für ein Hochbeet im Garten werden und wurde deswegen um einen Sensor zur Messung der Bodenfeuchtigkeit erweitert. Folgende Sensoren sind derzeit enthalten:
DHT11 – Temperatur und Luftfeuchtigkeit (Tutorial)
Digitaler, vorkalibrierter Sensor. Benötigt am Arduino nur 1 Pin zum Auslesen der Daten.
MPL3115A2 – Luftdruck und Temperatur
I²C-Sensor, misst die Temperatur genauer als der DHT11
TSL45315 – Lux / Lichteinfall (Tutorial)
I²C-Sensor, misst die Lichtmenge pro Fläche (Lux)
Seed Studio Feuchtigkeitssensor – Bodenfeuchtigkeit
Analoger Sensor, gibt einen mit der Feuchtigkeit des Mediums steigenden Wert an einem Analogpin zurück
Zusätzlich habe ich noch einen Arduino Uno R3 und ein Arduino Ethernet Shield zur Datenübertragung verwendet.
Hier werden die Bauteile noch einmal vorgestellt:
Die aktuelle Version des Arduino Sketch ist noch sehr einfach. Der Sketch macht alle 2 Minuten eine Messung und überträgt diese an einen bei thingspeak.com eingerichteten Channel zur Erfassung und Anzeige der Messdaten. Der Channel ist hier öffentlich abrufbar. Falls sich jemand über die Daten wundert: Der Aufbau steht die meiste Zeit im der Werkstatt im Keller – deswegen ist es auch an sonnigen Tagen eher kalt und dunkel.
Sollte der Channel gerade nicht mit Daten beschickt werden, hier ein Screenshot.
Der Anschluss der Sensoren an den Arduino ist nicht schwierig. Die Datenleitung des DHT11 habe ich mit Pin 8 verbunden. Die beiden I²C-Sensoren hängen an den I²C-Pins des Arduino (beim Arduino Uno R3 sind das A4 und A5). Achtung nur beim MPL3115A4-Sensor, da gehören laut Datenblatt zwei Widerstände I²C-Pins. Der Sensor für die Bodenfeuchtigkeit kommt an einen Analogpin.
Den grundlegenden Aufbau der Schaltung findet ihr in diesem Video:
Und die aktuelle Version des Arduino-Sketches mit etwas Dokumentation gibt es am Ende des Beitrags:
Für die beiden I²C-Sensoren, den DHT11 und das Ethernet-Shield werden passende Libraries benötigt, die hier zu finden sind:
DHT11
https://github.com/adafruit/DHT-sensor-library
MPL3115A2
https://github.com/sparkfun/MPL3115A2_Breakout (da gibt’s auch einen Hookup-Guide etc.)
TSL45315
https://github.com/adidax/Makerblog_TSL45315 (noch sehr rudimentär, aber bei mir funktioniert’s)
Die restlichen Libraries (Wire, SPI, Ethernet etc.) sind bei der Arduino IDE dabei.
Und hier der Sketch in der aktuellen Version. Keine Angst, der Programmcode ist hauptsächlich wegen der Testausgaben über die serielle Schnittstelle so lang:
/* Makerblog.at Wetterstation DHT11 fuer Temperatur und Luftfeuchtigkeit TSL45315 Lux Sensor fuer Helligkeit MPL3115A2 Barometer fuer Luftdruck und Temperatur Moisture Sensor fuer Bodenfeuchte Ethernet Board zur Datenuebertragung I2C Pins auf den einzelnen Arduino Boards: Board I2C/TWI Pins SDA, SCL ---------------------------- Uno, Ethernet A4, A5 Mega 20, 21 Leonardo 2, 3 Due 20, 21 Datenleitung DHT11: Pin 8 Feuchtesensor: Analogpin A1 */ // Die Libraries zur Ansteuerung aller Sensoren einbinden #include <Wire.h> #include <Makerblog_TSL45315.h> #include <MPL3115A2.h> #include <dht11.h> #include <SPI.h> #include <Ethernet.h> byte mac[] = { 0xD4, 0x28, 0xB2, 0xFF, 0xA0, 0xA1 }; // Must be unique on local network // ThingSpeak Settings - dazu ist ein kostenloser Account bei Thingspeak noetig char thingSpeakAddress[] = "api.thingspeak.com"; String writeAPIKey = "OCOJGIZW03EVREJC"; const unsigned long updateThingSpeakInterval = (unsigned long)120*1000; // Time interval in milliseconds to update ThingSpeak (number of seconds * 1000 = interval) // Variable Setup unsigned long lastConnectionTime = 0; boolean lastConnected = false; int failedCounter = 0; // Initialize Arduino Ethernet Client EthernetClient client; Makerblog_TSL45315 luxsensor = Makerblog_TSL45315(TSL45315_TIME_M4); MPL3115A2 myPressure; uint32_t lux; char pastring[10]; char tmpstring[10]; float pressure; float temperature; int ipress; int itemp; int soil; dht11 DHT11; #define DHT11PIN 8 // Der TSL45315 hat werkseitig die I2C ID 0x29 #define TSL45315_I2C_ADDR (0x29) void setup() { Serial.begin(9600); Serial.println("Initialization:"); Serial.print("TSL45315: "); Serial.println(luxsensor.begin()); Serial.println("MPL3115A2"); myPressure.begin(); // Get sensor online myPressure.setModeBarometer(); // Measure pressure in Pascals from 20 to 110 kPa myPressure.setOversampleRate(7); // Set Oversample to the recommended 128 myPressure.enableEventFlags(); // Enable all three pressure and temp event flags // DHT11 needs no setup // Moisture sensor needs no setup // Start Ethernet on Arduino startEthernet(); } void loop() { int chk = DHT11.read(DHT11PIN); Serial.print("Read sensor: "); switch (chk) { case DHTLIB_OK: Serial.println("OK"); break; case DHTLIB_ERROR_CHECKSUM: Serial.println("Checksum error"); break; case DHTLIB_ERROR_TIMEOUT: Serial.println("Time out error"); break; default: Serial.println("Unknown error"); break; } lux = luxsensor.readLux(); Serial.print("Lux: "); Serial.println(lux, DEC); pressure = myPressure.readPressure(); float pressure = myPressure.readPressure(); Serial.print("Pressure(Pa): "); Serial.println(pressure, 2); temperature = myPressure.readTemp(); Serial.print("Temperature1: "); Serial.print(temperature, 2); Serial.println(" (MPL3115A2)"); Serial.print("Temperature2: "); Serial.print((float)DHT11.temperature, 2); Serial.println(" (DHT11)"); Serial.print("Humidity (%): "); Serial.println((float)DHT11.humidity, 2); soil = analogRead(A1); Serial.print("Soil moisture: "); Serial.println(soil); Serial.println("------------------------------------"); // Print Update Response to Serial Monitor while (client.available()) { char c = client.read(); Serial.print(c); } // Disconnect from ThingSpeak if (!client.connected() && lastConnected) { Serial.println("...disconnected"); Serial.println(); client.stop(); } Serial.print("Millis: "); Serial.println(millis()); Serial.print("lastConnectionTime: "); Serial.println(lastConnectionTime); Serial.print("Diff: "); Serial.println(millis() - lastConnectionTime); Serial.print("Interval: "); Serial.println(updateThingSpeakInterval); // Update ThingSpeak - schauen ob 120 Sekunden vergangen sind, wenn ja dann Thingspeak updaten if(!client.connected() && (millis() - lastConnectionTime > updateThingSpeakInterval)) { Serial.println("UPDATE!"); // Ohne das Leerzeichen am Ende hat es bei mir nicht funktioniert updateThingSpeak("field1="+(String)temperature+"&field2="+(String)DHT11.temperature+"&field3="+(String)lux+"&field4="+(String)pressure+"&field5="+(String)DHT11.humidity+"&field6="+(String)soil+" "); } // Check if Arduino Ethernet needs to be restarted if (failedCounter > 3 ) {startEthernet();} lastConnected = client.connected(); delay(10000); } void updateThingSpeak(String tsData) { if (client.connect(thingSpeakAddress, 80)) { client.print("POST /update HTTP/1.1\n"); client.print("Host: api.thingspeak.com\n"); client.print("Connection: close\n"); client.print("X-THINGSPEAKAPIKEY: "+writeAPIKey+"\n"); client.print("Content-Type: application/x-www-form-urlencoded\n"); client.print("Content-Length: "); client.print(tsData.length()); client.print("\n\n"); Serial.println(tsData); client.print(tsData); lastConnectionTime = millis(); if (client.connected()) { Serial.println("Connecting to ThingSpeak..."); Serial.println(); failedCounter = 0; } else { failedCounter++; Serial.println("Connection to ThingSpeak failed ("+String(failedCounter, DEC)+")"); Serial.println(); } } else { failedCounter++; Serial.println("Connection to ThingSpeak Failed ("+String(failedCounter, DEC)+")"); Serial.println(); lastConnectionTime = millis(); } } void startEthernet() { client.stop(); Serial.println("Connecting Arduino to network..."); Serial.println(); delay(1000); // Connect to network amd obtain an IP address using DHCP if (Ethernet.begin(mac) == 0) { Serial.println("DHCP Failed, reset Arduino to try again"); Serial.println(); } else { Serial.println("Arduino connected to network using DHCP"); Serial.println(); } delay(1000); } |
Hej
Tolles Projekt. Ich bin gerade dabei mir eine Gewächshaussteuerung zusammenzu stoppeln
Dabei sollen 2 Arduinos (UNO + Mega 2560 R3 ATmega2560-16AU CH340G) mit einem Raspberry PI 3B zum Einsatz kommen, dazu etliche Sensoren.
Mal sehen ob ich es ans Laufen bekomme
Gruss aus Schweden
Jörg
Warum wird ein resistiver Bodenfeuchtesensor verwendet?
Die vergammeln recht gerne.
Nehmt doch einen kapazitiven, wie hier:
https://wwwvs.cs.hs-rm.de/vs-wiki/index.php/Internet_der_Dinge_WS2015/SmartPlant#Messmethode_2:_Kapazitiv