Hackair Sensor Station
Posted by quark007 | Posted in Uncategorized | Posted on 13-08-2020-05-2008
0
Mich hat das Konzept von HackAIR schon lange fasziniert, ich kam jedoch nie dazu es wirklich in Betrieb zu nehmen. Jetzt hat sich die Zeit ergeben und einige dabei zu umschiffende Probleme möchte ich euch gerne mitgeben.
In der Zwischenzeit ist das Projekt hackAIR ausgelaufen. Über die Platform https://opensensemap.org können die Daten aus den hackAIR Sensoren weiterhin abgeliefert werden. Der Code enthält diese option bereits.
Meine Einkaufsliste sieht wie folgt aus:
- Wemos D1 mini
- Nova SDS011 Sensor
- DHT22 Shield
BHM1750 Brightness sensor (geplant zur Steuerung von Rolläden über OpenHab)Regensensor (geplant zur Steuerung des Mähroboters über OpenHab)
Zunächst sollte erstmal alles so laufen wie es das HackAir Projekt vorsah. Die Aufbauanleitung und der Code (ich habe den hackAIR advanced Code verwendet) findet sich auf der Hackair Homepage.
Problem1: DHT22-Shield liefert keine Werte
Ich hatte zunächst nur den WEMOS D1 mini und das DHT22-Shield gelötet und verbunden (entsprechend der Anleitung auf der hackAIR webseite). Doch nach uploaden des Projekts konnte nie ein Wert für Luftfeuchte und Temperatur ermittelt werden. Ich ging zunächst von einem Hardware defekt aus, doch da die Dispute-Phase über Aliexpress schon vorbei war, hat mich der Ergeiz gepackt es doch nochmal genauer zu untersuchen.
Über ein Breadboard mit verschiedenen Pin-Anschlüssen hat sich rausgestellt, dass das DHT22 Shield es nicht mag, sowohl über 3,3V als auch über 5V versorgt zu werden.
Lösung: ich habe den 5V Pin einfach abgezwickt und der DHT22 lief. (erstmal, siehe Problem4)
Problem2: Nova SDS011 schläft ein, wacht aber nicht mehr auf
Im hackAIR code steht lediglich die Codezeile:
sensor.turnOn();
Nach einigem Lesen auf mehreren Seiten stellte sich heraus, dass es dem Sensor angeblich genügen würde irgend ein Commando zu bekommen um wieder aufzuwachen.
Nach etwas weiterem Lesen bin ich über diesen Post gestolpert, der etwas anderes behauptet: es ist doch eine konkrete Byte-Folge notwendig, um den Sensor aufzuwecken.
Also habe ich die hackair.cpp in den libraries entsprechend angepasst. Die turnOn(); Funktion sah dann für mich so aus:
void hackAIR::turnOn() {
static const byte WAKECMD[19] = {
0xAA, // head
0xB4, // command id
0x06, // data byte 1
0x01, // data byte 2 (set mode)
0x01, // data byte 3 (wake up)
0x00, // data byte 4
0x00, // data byte 5
0x00, // data byte 6
0x00, // data byte 7
0x00, // data byte 8
0x00, // data byte 9
0x00, // data byte 10
0x00, // data byte 11
0x00, // data byte 12
0x00, // data byte 13
0xFF, // data byte 14 (device id byte 1)
0xFF, // data byte 15 (device id byte 2)
0x06, // checksum
0xAB // tail
};
// SDS011 uses the built-in power saving function
if (_sensorType == SENSOR_SDS011) {
// Send anything to wake up the sensor
//_serial.write(0x01);
for (uint8_t i = 0; i < 19; i++) {
_serial.write(WAKECMD[i]);
}
delay(2000);
} else {
#ifndef ESP8266
digitalWrite(A2, HIGH);
#endif
}
}
Das Projekt neu kompiliert und hochgeladen und siehe da, der SDS011 ist wirklich wieder aufgewacht.
Problem3: Übertragen der Daten per MQTT an OpenHAB
Ein großteil meiner Datensammlung läuft über einen MQTT-Broker (Temperatur und Feuchte Sensoren in jedem Zimmer ; Steuerung des Mähroboters über die LandroidBridge …..). Also sollten auch diese Daten im Smarthome verfügbar sein.
Zunächst war ich der Annahme ich könnte die AdafruitMQTT-Libraries verwenden. Nach viel Rumprobieren hat sich das aber als Fehler herausgestellt. ich habe es nicht geschafft eine Verbindung zu einem normalen Mosquitto Server aufzunehmen. (Offensichtlich ist die Adafruit-Implementierung etwas anders).
Aus meinem Projekt mit den Zimmer-Sensoren habe ich mir Struktur des MQTT-Clients (PubSubClient) übernommen. In auszügen sieht das dann wie folgt aus:
#include <PubSubClient.h> // MQTT CLIENT FOR OPENHAB
// MQTT
#define MQTT_ENABLE "1" // set this to 1 to enable MQTT
#define MQTT_BROKER "192.168.178.XX" // MQTT Broker IP
#define MQTT_USER "openhab" // MQTT user
#define MQTT_PASS "openhab" // MQTT password
[...]
// Create a Wifi client for MQTT connection
WiFiClient espClient; //Only for MQTT
PubSubClient MQTTclient(espClient);
void setup() {
// MQTT Initialisation
MQTTclient.setServer(MQTT_BROKER, 1883);
[....]
}
void loop() {
[...]
//DHT READ
float env_temp = dht.readTemperature();
float env_hum = dht.readHumidity();
// Send error message if DHT22 values could not be read
if(isnan(env_hum) || isnan(env_temp)){
Serial.print("Temp: ");
Serial.print(env_temp);
Serial.print(" | Hum: ");
Serial.println(env_hum);
MQTTreconnect();
MQTTclient.publish("tele/hackair/state", "ERROR Temp/Hum");
}
[...]
if (MQTT_ENABLE == "1") {
if (!MQTTclient.connected()) {
MQTTreconnect();
}
String dataMQTT = "{\"data\":{\"PM25\":\""; // PM25 ist eingfacher über openhab abzurufen als PM2.5
dataMQTT += data.pm25;
dataMQTT += "\",\"PM10\":\"";
dataMQTT += data.pm10;
dataMQTT += "\",\"temp\":\"";
dataMQTT += env_temp;
dataMQTT += "\",\"hum\":\"";
dataMQTT += env_hum;
// dataMQTT += "\",\"rain_d\":\""; //noch nicht implementiert
// dataMQTT += env_rain_d; //noch nicht implementiert
// dataMQTT += "\",\"rain_a\":\""; //noch nicht implementiert
// dataMQTT += env_rain_a; //noch nicht implementiert
// dataMQTT += "\",\"lux\":\""; //noch nicht implementiert
// dataMQTT += env_lux; //noch nicht implementiert
dataMQTT += "\"},\"battery\":\"";
dataMQTT += vdd;
dataMQTT += "\",\"tamper\":\"";
dataMQTT += "0";
dataMQTT += "\",\"error\":\"";
dataMQTT += data.error;
dataMQTT += "\"}";
if (MQTTclient.publish("tele/hackair/SENSOR", (char*) dataMQTT.c_str()) && DEBUG == "1") {
Serial.print("MQTT Publish successful: ");
Serial.println(dataMQTT);
} else if (DEBUG == "1") {
Serial.print("MQTT Publish failed");
Serial.println(MQTTclient.state());
}
}
[...]
// define functions
void MQTTreconnect() {
// Loop until we're reconnected
while (!MQTTclient.connected()) {
Serial.print("Attempting MQTT connection...");
// Create a random client ID
String clientId = "Hackair-";
clientId += String(random(0xffff), HEX);
// Attempt to connect
if (MQTTclient.connect(clientId.c_str(), MQTT_USER, MQTT_PASS)) {
Serial.println(" connected");
MQTTclient.publish("tele/hackair/LWT", "Online", false); //ohne hat er die Verbindung nicht behalten.
} else {
Serial.print("failed, rc=");
Serial.print(MQTTclient.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
MQTTclient.loop();
}
Mit ein wenig Konfiguration in openHAB sieht das Ergebnis dann wie folgt aus:
Problem4: Instabiler Neustart des Wemos D1 mini
Beim Neustart des Wemos D1 mini kommt es wiederholt (schon fast regelmäßig) vor, dass entweder die Ausgabe über die Serielle Schnittstelle nicht funktioniert oder aber das Auslesen der DHT22 Messwerte. Diese liefern dann nur nan zurück und somit ist eine Feuchtigkeits-Korrektur der Partikelmessung nicht mehr möglich.
Nach einem Upload eines Sketches auf den ESP funktioniert die Serielle Ausgabe ohne Neustart, jedoch der DHT22 nicht.
Nach dem ersten hard reset (Strom trennen und wieder verbinden) geht fast immer die Serielle Schnittstelle nicht.
Nach einem weiteren hard reset geht ab und an das Auslesen der DHT-Werte schief. Egal wie oft die Reset-Taste am ESP gedrückt wird.
Eine Lösung für das DHT22 Problem konnte ich hier finden: https://blog.zs64.net/2018/02/fixing-the-wemos-d1-mini-dht22-shield/
Es hat sich gezeigt, dass der D4-Port, den das DHT22 Shield verwendet, auch für die LED-Steuerung verwendet wird. Beim Start kann es also dazu kommen dass sich Sensor-Initialisieren und LED-Steuern in die Quere kommen.
Übers Breadboard mit umlegen auf den D3-Pin läuft es nun stabil wie nie!!! Damit hatte ich dann auch deutlich weniger Probleme mit einer nicht funktionierenden Seriellen Verbindung.
Edit: beim Programmieren eines weiteren DHT22 Shields kam ich wieder nicht weiter. Sowohl das umlegen des D-Pins, als auch der Spannungsversorgungs-hack hat nicht geholfen. Nach viel googlen bin ich dem Problem auf den Grund gekommen: die DHT-Library funktioniert mit meinen DHT22 nur bis Version 1.2.0. Mit allen neueren geht es nicht (hier der Bug-Eintrag dazu).
Gehäuse
Damit alles schön verpackt in den Außenbereich kann, habe ich nach einem Gehäuse gesucht. Auf thingivers.com bin ich bei der “Dust Sensor Box” fündig geworden.
Auf meinem Ender3 habe ich das ganze aus weißem PLA mit 15% Infill gedruckt (195°C Düse und 48°C Druckbett Temperatur).
Da das Projekt aber für einen Nodemcu v2 amica vorgesehen ist, habe ich den Wemos D1 mit dem DHT22 Shield einfach reingelegt. Durch die relativ geringe Höhe und den leicht abstehenden DHT22 Sensor klemmt das ganze eigentlich ganz gut.
Montiert wurde die Box anschließend unter den selbstgebauten Hochbeeten (an der Querverbindung zur Stabilisierung des Mörtelwannenbodens).
Datenübertragung an opensensemap und luftdaten.info
Zusätzlich zu dem bereits unterstützten opensensemap.org wollte ich auch luftdaten.info mit einbinden. Dazu gibt es schon ein Script. Das habe ich als Vorlage verwendet, um den Code von hackair entsprechend anzupassen.
Es hat sich bei mir noch ein anderes Problem gezeigt: auch auf opensensemap konnten die Daten nicht hochgeladen werden. Nach viel herumprobieren und optimieren des Codes bin ich zu der im Code befindlichen Lösung gekommen.
TODO
Hier gibt es noch eine Info, wenn das Uploaden des Sketchs fehlschlägt (bei meinen neuen WEMOS D1 mini war das fast immer der Fall): https://github.com/esp8266/Arduino/issues/2604#issuecomment-294970016
Es kommt bei mir öfter vor, dass HackAIR an irgend einem Punkt hängen bleibt. Er macht dann nicht weiter und liefert auch keine Werte. Ich habe die Vermutung, dass es in der SDS011 ein Problem gibt. Die Serielle Schnittstelle so lange angeschlossen zu lassen, schaffe ich nicht (hackAIR hängt unter einem Hochbeet auf der Terasse). Daher habeich mich damit abgefunden und über openHAB eine Regel erstellt, die den Strom 20 Sekunden trennt und danach wieder anschaltet.