In diesem Artikel gehen wir einmal unter die Bastler 😉 Meiner KNX Installation fehlt es leider an einem Sensor zum messen der Luftfeuchtigkeit. Da ich mir das Nachrüsten sparen will und auch nicht einsehe für eine Netatmo Station ein kleines Vermögen auszugeben, habe ich mich auf die Suche nach Alternativen gemacht und mein Arduino Kit rausgekramt. Leider hat das Arduino Uno Board kein WLAN und ich müsste die Daten auf andere Weise ins Netzwerk und zu obenHAB übertragen. Die Lösung heißt NodeMCU ESP8266 – ein Mikrocontroller mit eingebautem WLAN Modul, der über die Arduino IDE programmiert werden kann. Als Temperatursensor kommt ein DHT22 zum Einsatz.
Vorbereitung
Zunächst einmal muss der NodeMCU per USB mit dem Computer verbunden und für die Programmierung vorbereitete werden. Wie das im einzelnen funktioniert werde ich an dieser Stelle ausklammern und verweise auf eine super Anleitung von OpenDataLab, die auch mir sehr geholfen hat. Sobald das erledigt ist, kann der Sensor an das Board angeschlossen werden. Um einen ersten schnellen (fliegenden) Aufbau zu bewerkstelligen, kann entweder eine Steckplatine genutzt werden, oder Female Jumper Kabel. Beides ist in der Artikelliste oben aufgeführt. Die Pins werden folgendermaßen miteinander verbunden:
Programmierung NodeMCU
Unser Ziel ist es die Daten des Sensors an openHAB zu übertragen. Die einfachste Methode hierfür ist der Weg über das HTTP Binding. Damit können wir beispielsweise JSON Dateien auslesen. Wie es der Zufall will kann der NodeMCU als Webserver fungieren und die Sensordaten in eine JSON Datei schreiben, die sich openHAB dann abholen kann.
Es gibt sicherlich noch elegantere Wege der Datenübertragung an openHAB wie beispielsweise das MQTT Protokoll. Das Thema ist allerdings etwas umfangreicher und wird an anderer Stelle noch genauer behandelt werden.
Bibliotheken herunterladen
Für dieses Projekt benötigen wir folgende Bibliotheken einige Bibliotheken, die, sofern noch nicht geschehen, installiert werden müssen. Das wird im Menü Sketch – Bibilothek einbinden – Bibliotheken verwalten. Es öffnet sich der Bibliotheksverwalter. Hier über die Suche die folgenden Bibliotheken suchen und installieren:
- ArduinoJson
- ESP8266WiFi
- ESP8366WebServer
- DHT
In unser neues Projekt wird jetzt folgender Code eingefügt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
#include <ArduinoJson.h> #include <ESP8266WiFi.h> #include <ESP8266WebServer.h> #include <DHT.h> #define DHTTYPE DHT22 #define DHTPIN 5 #define WLAN_SSID "xxxxxxx" #define WLAN_PASSWORD "12345678" DHT dht(DHTPIN, DHTTYPE, 22); ESP8266WebServer server(80); float temperature, humidity; int soil = analogRead(A0); float soil_percent; unsigned long previousMillis = 0; const long interval = 2000; void setup() { Serial.begin(115200); delay(10); dht.begin(); humidity = dht.readHumidity(); temperature = dht.readTemperature(); pinMode(soil, INPUT); Serial.println(); Serial.println(); Serial.print("Connecting to "); Serial.println(WLAN_SSID); WiFi.mode(WIFI_STA); WiFi.begin(WLAN_SSID, WLAN_PASSWORD); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); server.on("/dht22.json", [](){ unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= interval) { previousMillis = currentMillis; humidity = dht.readHumidity(); temperature = dht.readTemperature(); if (isnan(humidity) || isnan(temperature)) { Serial.println("Failed to read from DHT sensor!"); return; } Serial.println("Reporting " + String((int)temperature) + "C and " + String((int)humidity) + " % humidity"); } StaticJsonBuffer<500> jsonBuffer; JsonObject& root = jsonBuffer.createObject(); root["temperature"] = temperature; root["humidity"] = humidity; String jsonString; root.printTo(jsonString); Serial.println(jsonString); server.send(200, "application/json", jsonString); }); server.begin(); Serial.println("HTTP server started! Waiting for clients!"); } void loop() { server.handleClient(); } |
Die Werte für SSID und WLAN Passwort müssen natürlich durch die Zugangsdaten des eigenen WLAN zu Hause ersetzt werden. Wichtig: Der NodeMCU unterstützt nur das 2,4 GHz Band.
#define WLAN_SSID „xxxxxxx“
#define WLAN_PASSWORD „12345678“
Auf den Code selbst gehe ich an dieser Stelle nicht im Detail ein. Grob zusammengefasst macht der Code Folgendes:
- Webserver starten
- Sensor auslesen
- Sensorwerte in eine .json Datei schreiben
- .json Datei auf dem Webserver zur Verfügung stellen
- Serielle Ausgabe der Werte, um alles auf dem Computer verfolgen zu können, wenn der Node per USB verbunden ist.
In der Arduino IDE kann nun der serielle Monitor geöffnet werden, um zu sehen was der Node ausspuckt und ob der Sensor sinnvolle Werte liefert.
Jetzt kann der Code kompiliert und auf den NodeMCU übertragen werden. Um zu testen, ob es Fehler im Code gibt, kann man den Code mit Klick auf das Häkchen oben links überprüfen.
Wenn die Überprüfung keine Fehler ergibt, kann das der Code mit Klick auf den Pfeil nach rechts auf das Gerät übertragen werden. Nach Abschluss sollten im seriellen Monitor die Vorgänge zu sehen sein.
Der Node sollte jetzt auch schon mit dem Netzwerk verbunden sein. Im seriellen Monitor ist die IP Adresse des Node zu sehen. Diese kann aber auch über den Router identifiziert werden. Sobald du die IP Adresse hast, in meinem Fall 192.168.1.54 kannst du die JSON Ausgabe über den Browser aufrufen.
Dazu gibst du im Browser die Adresse http://192.168.1.56/dht22.json ein (die IP Adresse musst du durch die IP Adresse des Node in deinem Netzwerk ersetzen). Das Ergebnis sollte so aussehen:
Die Einträge soil und soil_percent können ignoriert werden. Hier habe ich mittels Analog Read die einen Sensor zur Messung der Bodenfeuchtigkeit meiner Zimmerpflanze gebaut. Hierzu in einem anderen Artikel mehr ;). Kleiner Tipp: Firefox kann in der neusten Version JSON gleich lesbar anzeigen, wie im folgenden Screenshot dargestellt.
Das war es schon in Sachen Sensor bauen und programmieren. Die Daten, die der Webserver als JSON Datei zur Verfügung stellt, kann beispielsweise durch openHAB mittels HTTP Binding ausgelesen werden.
Im Zusammenhang mit dem NoceMCU habe ich mir auch einen kleinen 3D Drucker angeschafft und die passenden Gehäuse für meine Bastelarbeiten zu drucken. Ergebnisse und Vorlagen werden in der
Hallo Patrick,
eine aktualisierung des Codes auf die aktuellen Librarys wäre Top 🙂
bekomme leider auch eine Fehlermeldung … würde das Setup gerne nutzen um ein paar Temp. Fühler im Haus zu verteilen.
Viele Grüße
André
Hi Patrick,
der Beitrag ist ja schon ein paar Tage alt, allerdings zweifelsohne richtig gut geschrieben.
Läuft bei mir, zumindest sendet der Server die Daten als JSON und ich kann auch im Browser alles „sehen“, also Temp und Luftfeuchte. Ich habe in Summe 5 ESPs laufen, das scheint mir die beste Lösung, da alle 5 völlig gleich konfiguriert sind, ich also nur die IP / MAC zum Unterscheiden brauche. Soweit so gut.
Wo ich jetzt noch einen Tip bzw eine Idee brauche ist bezüglich dem Einbinden ins OpenHAB2 … hier bin ich totaler Newbie und scheitere am HTTP Binding bzw. am Anlegen einer / der Items (Google hat mir auch nicht wirklich weitergeholfen)… Hast du ggf einen Tip, der mich in die richtige Richtung schubst? Wie „lese“ ich den JSON String korrekt aus bzw wie ist das HTTP Binding zu konfigurieren ..
Allerbesten Dank im Voraus
Dirk
Hallo Dirk,
vielen Dank für das Lob 🙂 Das ist ein guter Punkt. Ich werde eine Anleitung zur Integration in openHAB schreiben. Das sollte bis heute Abend, spätestens am Wochenende fertig sein.
Viele Grüße
Patrick
Hallo Patrick… coolio .. Danke schonmal im Voraus, aber bitte nicht hetzen. Ich bin noch am Gehäuse-Design 😉
Das Ganze soll per Raspi und 3,5″ Touchdisplay „nur“ die Fernbedienung bzw. TempAnzeige der meiner Heizung ersetzen, welche gerade einen „Hardware-Refresh“ erfahren hat … Dadurch wurde die bisherige LCD Anzeige mit ein paar Tasten und Schiebereglern überflüssig und hat eine häßliche kahle Stelle an der Wohnzimmerwand hinterlassen. Diese gilt es wieder mit einem sinnvollen Gadget zu füllen.
Wenn das dann alles funzt, nehme ich dann das volle OpenHAB (dann sicher mit MQTT) in Angriff … auf „ZukunftAtHome“ gibt’s ja mega-interessante Projekte und Ideen zum Thema.
Also nochmal : Besten Dank im Voraus.. schönstes WE wünsch‘ ich.
Dirk
Sodele, hiermit solltest du es in openHAB einbinden können 🙂 https://zukunftathome.de/json-datei-ueber-http-binding-mit-openhab-auslesen/
Hi Patrick,
mega! .. Wochenendbastelei …
Allerbesten Dank, nochmals!
Ich werde berichten, sobald ich Ergebnisse hab‘.
Btw. Neulich war ja Prime-Day… ich habe jetzt dann auch nen 3D Drucker 😉
VG und SWE
Dirk
Hi Patrick,
läuft! Super.. vielen Dank nochmal.
(hab zwar grade das Problem, dass nach ’nem RPI-Update das TonTec Display nicht mehr läuft, aber das bekomme ich per Image Backup sicher wieder hin.. ;))
Also Danke nochmals
VG, Dirk
super, das freut mich 🙂
Hallo Patrick,
beide Sketches finde ich für mich sehr hilfreich, Danke!
Im Belegungsplan vermisse ich zwischen der Datenleitung und dem 3,3V Anschluss einen 10k pull-up Widerstand.
Gruß Friedhelm
Hallo Patrick
Danke für deine interessante Erklärung, ganau das habe ich gesucht.
Leider dürfte es mittlerweile Änderungen in ArduinoJson gegeben haben (von Version 5 auf 6),
die sich auf dein Script auswirken. Ich bin aber leider nicht in der Lage das funktionstüchtig anzupassen.
Wäre super wenn du dir das ansehen könntest.
Die Fehlermeldung ist wie folgt:
error: StaticJsonBuffer is a class from ArduinoJson 5. Please see arduinojson.org/upgrade to learn how to upgrade your program to ArduinoJson version 6
StaticJsonBuffer jsonBuffer;
^
exit status 1
StaticJsonBuffer is a class from ArduinoJson 5. Please see arduinojson.org/upgrade to learn how to upgrade your program to ArduinoJson version 6
Danke 🙂
Hallo Erwin, es freut mich, dass du fündig geworden bist. Ich muss das Projekt mal rauskramen und schauen ob ich das hinbekomme. Zugegebenermaßen übertrage ich schon eine ganze Sensordaten nur noch per MQTT. Das hat sich – zumindest bei mir – als wesentlich stabiler herausgestellt. Wenn das für dich eine Option ist, kannst du dir diesen Artikel anschauen: https://zukunftathome.de/anwesenheitserkennung-per-ultraschallsensor/
Viele Grüße
Patrick
funktioniert bei mir so:
StaticJsonDocument root;
root[„temperature“] = temperature;
root[„humidity“] = humidity;
String jsonString;
serializeJson(root,jsonString);
Serial.println(jsonString);
server.send(200, „application/json“, jsonString);
Paste-fehler: Hinter StaticJsonDocument kommt natürlich noch die 500 in eckigen Klammern, wie im alten Source…
Hallo Zusammen!
Ich würde gerne diesen Sensor statt (https://www.aliexpress.com/item/32983350369.html?spm=2114.search0104.3.1.5f03235aQQZLAR&ws_ab_test=searchweb0_0%2Csearchweb201602_4_10065_10068_10547_319_317_10548_10696_10084_453_10083_454_10618_10304_10307_10820_10821_537_10302_536_10059_10884_10887_321_322_10103%2Csearchweb201603_53%2CppcSwitch_0&algo_expid=5ad8f251-2126-4b63-ac23-209e551a837c-0&algo_pvid=5ad8f251-2126-4b63-ac23-209e551a837c&transAbTest=ae803_3) statt den DHT-Sensor verwenden weil ich gerne mein Poolwasser damit messen möchte.
Könntest du den Code soweit anpassen, dass dieser Sensor statt den anderen Verwendet wird und die Temparatur alle 5 Minuten gesendet wird.
Dankeshön
LG Stefan
Hallo Stefan,
ich habe diesen Sensor selbst nicht in Verwendung. Allerdings gibt es einige schöne Anleitungen. Diese habe ich gefunden https://draeger-it.blog/arduino-lektion-48-temperatursensor-ds18b20/
Damit sollte es problemlos möglich sein, den Code oben anzupassen. Du musst temperature den Wert des Sensors zuweisen, also sensors.getTempFByIndex(i), dann solltest du große Teile des Codes weiterverwenden können.
Viele Grüße
Patrick
Super Projekt.
Duch deine anleitung habe ich endlich 2 meiner Fehler gefunden.
Den einen Verstehe ich nicht ganz. Warum ist der DHT an Pin D1 angeschlossen wir daber im Code als 5 bezeichnet.
Greetz
Max
Hallo Max,
freut mich, dass die Anleitung geholfen hat.
Die Pin Bezeichnung unterscheidet sich leider von der Nummer, die im Code zu verwenden ist. Hier findest du die Zuordnung der Pins:
https://i.pinimg.com/originals/b6/b2/5b/b6b25b8869fadd501e85406e3d247fe0.png
Viele Grüße
Ich habe das Programm versucht zu kompilieren, leider bekomme ich bei der Eingabe
StaticJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
root[„temperature“] = temperature;
root[„humidity“] = humidity;
String jsonString;
root.printTo(jsonString);
Serial.println(jsonString);
server.send(200, „application/json“, jsonString);
});
Fehlermeldungen für root, StaticJsonBuffer etc, dass die nicht deklariert wurden. Als was muss ich die deklarieren und wo?
Hallo Flo,
das hört sich seltsam an. Hast du die Json Bibliothek eingebunden? Das wäre
#include
Ansonsten definiere ich an dieser Stelle noch, dass es sich bei temperature und humidity um float Werte handelt
float temperature, humidity;
Du kannst mir auch gerne einmal deinen kompletten Code zukommen lassen, dann versuche ich ihn bei mir zum Laufen zu bekommen.
Hallo Patrick,
Danke. Ich habe eine beta-Version verwendet (halt die neueste Version ausgewählt). Die funktioniert dann noch nicht so richtig. Der Upload klappt schon mal.
Sensor läuft. Astrein!
Könntest du vielleicht noch ergänzend den Quellcode für den BMP085 Luftdrucksensor hinzufügen?
Schon mal vielen Dank im Voraus,
Flo
Hi Flo,
super! Das freut mich zu hören 🙂
Mit dem Sensor habe ich bisher noch nicht gearbeitet, steht aber auf meiner Liste. Sobald ich Neuigkeiten habe, gebe ich Bescheid.
Hallo!
Ich habe heute den Sonsor erhalten und habe versucht den NodeMCU zu Kompilieren.
Leider kommt folgende Fehlermeldung:
Arduino: 1.8.5 (Windows Store 1.8.10.0) (Windows 10), Board: „NodeMCU 1.0 (ESP-12E Module), 80 MHz, 4M (1M SPIFFS), v2 Lower Memory, Disabled, None, Only Sketch, 115200“
Build-Optionen wurden verändert, alles wird neu kompiliert
In file included from
\Arduino\libraries\DHT_sensor_library\DHT_U.cpp:22:0:
\Arduino\libraries\DHT_sensor_library\DHT_U.h:25:29: fatal error: Adafruit_Sensor.h: No such file or directory
#include
^
compilation terminated.
exit status 1
Fehler beim Kompilieren für das Board NodeMCU 1.0 (ESP-12E Module).
Wo ist der fehler?
LG Stefan
Hi Stefan,
es sieht so aus als wäre die Bibliothek nicht richtig installiert. Schau mal hier nach: https://forum.arduino.cc/index.php?topic=471001.0
Viele Grüße
Patrick
Hallo Patrick!
Könntest du in diesen Beispiel den Code erweitern, dass er die Daten auch ein einen MQTT Server sendet wir beim Ultraschallmesser?
LG Stefan
Klar! Anbei der Code:
#include
#include
#include
#define DHTTYPE DHT22
#define DHTPIN 5
DHT dht(DHTPIN, DHTTYPE, 22);
float temperature, humidity;
// Update these with values suitable for your network.
const char* ssid = "XXXXXXXXX";
const char* password = "123456789";
const char* mqtt_server = "192.168.1.1";
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;
void setup_wifi() {
delay(100);
// We start by connecting to a WiFi network
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 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 you MQTT broker has clientID,username and password
//please change following line to if (client.connect(clientId,userName,passWord))
if (client.connect(clientId.c_str()))
{
Serial.println("connected");
//once connected to MQTT broker, subscribe command if any
client.subscribe("OsoyooCommand");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 6 seconds before retrying
delay(6000);
}
}
} //end reconnect()
void setup() {
Serial.begin(115200);
Serial.setTimeout(2000);
// Wait for serial to initialize.
while(!Serial) { }
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);
dht.begin();
humidity = dht.readHumidity();
temperature = dht.readTemperature();
if (!client.connected()) {
reconnect();
}
}
void loop() {
dht.begin();
humidity = dht.readHumidity();
temperature = dht.readTemperature();
if (isnan(humidity) || isnan(temperature)) {
return;
}
if (!client.connected()) {
reconnect();
}
client.loop();
long now = millis();
// read DHT11 sensor every 6 seconds
if (now - lastMsg > 10000) {
lastMsg = now;
String msg = (String)humidity;
char messagehumidity[58];
msg.toCharArray(messagehumidity, 58);
Serial.println(messagehumidity);
//publish sensor data to MQTT broker
client.publish("Haus/EG/Essen/Sensor/Feuchtigkeit", messagehumidity);
String msg2 = (String)temperature;
char messagetemperature[58];
msg2.toCharArray(messagetemperature, 58);
Serial.println(messagetemperature);
//publish sensor data to MQTT broker
client.publish("Haus/EG/Essen/Sensor/Temperatur", messagetemperature);
}
}