Das zwanzigste Türchen

Heute geht es um MQTT (Message Queuing Telemetry Transport), ein im Bereich Smarthome sehr häufig verwendetes Protokoll. Wir wollen den Envy aus dem heutigen Angebot mit diesem Protokoll ausstatten, um ihn einfach mit Smarthome-Systemen verbinden zu können. Eine solche Verbindung werden wir ebenfalls kennenlernen. Wir werden den Envy mit der im Smarthome Buch beschriebenen Smarthome Zentrale verbinden.

Eine MQTT Nachricht besteht aus einem sogenannten Thema und den zugehörigen Daten. Das Thema ist ähnlich wie ein Verzeichnispfad hierarchisch aufgebaut. Die einzelnen Ebenen werden durch Schrägstriche getrennt. Wildcards können verwendet werden. Wie MQTT im Detail funktioniert, wird im Kapitel 6 des Smarthome-Buchs beschrieben.

Die Daten werden als Objekt im JSON (Java Script Object Notation) Format dargestellt. Der Vorteil dieses Formats liegt darin, dass alle Daten als lesbare Strings übertragen werden. Messwerte und Einheiten werden als Eigenschaften eines Objekts dargestellt. Für den Envy werden wir folgende Eigenschaften definieren.

  • sensor Name des Sensors (konfigurierbar)
  • t Temperaturwert vom SHT30
  • tu Einheit der Temperatur „°C“ oder „°F“ (konfigurierbar)
  • h Luftfeuchtigkeit vom SHT30
  • hu Einheit für die Luftfeuchtigkeit fix „%“
  • g Gaskonzentration vom MQ2
  • gu Einheit für die Gaskonzentration fix „ppm“

Wie in der Liste erwähnt, soll der Name des Sensors und die gewünschte Temperatureinheit konfigurierbar sein. Weiters sollte auch die Art des Gases, das untersucht werden soll, konfiguriert werden können. Damit sich der Envy mit dem WLAN und dann mit dem MQTT-Broker verbinden kann, brauchen wir Zugangsdaten fürs WLAN, die Adresse des Brokers, Zugangsdaten zum Broker, das MQTT Thema und die Wiederholrate für die Messung (z.B. eine Messung/Minute). Alle diese Werte sollen auch konfiguriert werden können.

Da der Envy keine Eingabe- und Anzeigeelemente besitzt, kann die Konfiguration über im Programm hart kodierte Konstanten oder eleganter über Browser erfolgen. Für die Konfiguration über Browser gibt es die Bibliothek WebConfig, die ein frei konfigurierbares Webformular über einen Webserver bereitstellen kann. Auch diese Bibliothek wird im Smarthome Buch ab Seite 168 beschrieben.

Da ohne Konfiguration eine Anmeldung am WLAN nicht möglich ist, werden wir in diesem Fall zuerst einen Accesspoint starten, der über die Adresse 168.178.4.1 die Konfigurations-Webseite liefert. Dort können wir dann die Zugangsdaten eingeben und den Envy neu starten. Wenn der Envy eine Konfiguration hat und sich im WLAN anmelden kann, wird kein Accesspoint gestartet. Der Zugriff auf die Konfigurationsseite ist dann über die Adresse möglich, die der Envy bei der Anmeldung am WLAN erhält.

Da diese Vorgangsweise immer dann angewendet werden kann, wenn ein ESP8266 Messwerte über MQTT zu Verfügung stellen soll, wurde, im Zusammenhang mit dem Smarthome Buch, eine Bibliothek entwickelt, die eine include-Datei zur Verfügung stellt, die all die oben beschriebenen Aufgaben übernimmt. Die Bibliothek ist im Material zum Buch enthalten, kann aber auch von GitHub heruntergeladen werden. Auch die Funktion dieser Hilfsdatei ist im Buch ab Seite 176 beschrieben.

Damit kommen wir nun zu unserem Sketch für den Envy. Folgende Bibliotheken müssen installiert werden.

  • ClosedCube_SHT31D.h für den SHT30 aus der Arduino Bibliotheksverwaltung
  • MQUnifiedsensor.h für den Gassensor aus der Arduino Bibliotheksverwaltung
  • ESP8266_MQTT_Conf.h aus ZIP File von GitHub
  • ArduinoJson.h für das JSON Format aus der Arduino Bibliotheksverwaltung
  • PubSubClient.h für das MQTT Protokoll aus der Arduino Bibliotheksverwaltung

Nachdem all diese Bibliotheken installiert wurden, kann der Sketch kompiliert werden.

#include "ESP8266_MQTT_Conf.h" //Includedatei enthält alles für WiFi, Konfiguration und MQTT
#include <Wire.h> //Notwendig für SHT30
#include "ClosedCube_SHT31D.h" //Bibliothek für SHT30
#include <MQUnifiedsensor.h> //Bibliothek für Gassensor

//Parameter für den Gassensor
/************************Hardware Related Macros************************************/
#define Board ("ESP8266")
#define Pin (A0) //Analog input
/***********************Software Related Macros************************************/
#define Type ("MQ-2") //MQ2
#define Voltage_Resolution (3.3)
#define ADC_Bit_Resolution (10) // For arduino UNO/MEGA/NANO
#define RatioMQ2CleanAir (9.83) //RS / R0 = 9.83 ppm


//Spezifische Einträge für das Konfigurationsformular
String param = "["
  "{"
  "'name':'thema',"
  "'label':'MQTT Thema Temp.',"
  "'type':"+String(INPUTTEXT)+","
  "'default':'envy'"
  "},"
  "{"
  "'name':'sensor',"
  "'label':'Name des Sensors',"
  "'type':"+String(INPUTTEXT)+","
  "'default':'SHT30'"
  "},"
  "{"
  "'name':'typ',"
  "'label':'Welches Gas?',"
  "'type':"+String(INPUTSELECT)+","
  "'default':'1',"
  "'options':["
  "{'v':0,'l':'Wasserstoff'},"
  "{'v':1,'l':'LPG'},"
  "{'v':2,'l':'Kohlenmonoxyd'},"
  "{'v':3,'l':'Alkohol'},"
  "{'v':4,'l':'Propan'}"
  "]},"
  "{"
  "'name':'fahrenheit',"
  "'label':'Fahrenheit',"
  "'type':"+String(INPUTCHECKBOX)+","
  "'default':'0'"
  "}"
  "]";


//SHT Sensor Instanz
ClosedCube_SHT31D sht;
//MQ2 Sensor Instanz
MQUnifiedsensor MQ2(Board, Voltage_Resolution, ADC_Bit_Resolution, Pin, Type);

//Einstellwerte für verschiedene Gase
const float gase[5][2] {
  {987.99,-2.162}, //Wasserstoff
  {574.25,-2.222}, //LPG
  {36974,-3.109}, //Kohlenmonoxyd
  {3616.1,-2.675}, //Alkohol
  {658.71,-2.168} //Propan
  };

//Daten an den MQTT Broker senden
void publishData() {
  //Daten von SHT30 lesen die hohe Wiederholbarkeit verringert das Rauschen.
  //Der Parameter 50 gibt den Timeout an
  SHT31D result = sht.readTempAndHumidityPolling(SHT3XD_REPEATABILITY_HIGH, 50);
  //Messwerte in Variable übernehmen
  float humidity = result.rh;
  float temperature = result.t;
  String unit = "°C";
  temperature = temperature - 6; //Korrektur wegen Erwärmung durch Gassensor und Controller.
  //Falls Fahrenheit gewählt wurde, die Temperatur umrechnen
  if (conf.getBool("fahrenheit")) {
    temperature= temperature * 1.8 +32;
    unit="°F";
  }
  //Messwerte vom Gassensor
  MQ2.update(); // Update die Spannung am Analogeingang wird gemessen
  float gas=MQ2.readSensor(); //Die Gaskonzentration in ppm ermitteln
  char buffer[1000]; //Buffer für die JSON Zeichenkette
  //Der temporäre Speicher für das JSON Dokument wird angelegt
  //Wir reservieren 500 Zeichen
  StaticJsonDocument<500> doc;
  //Das JSON Objekt wird mit Daten befüllt
  doc["sensor"]=conf.getValue("sensor"); //Name des Sensors
  doc["t"]=temperature; //Temperatur
  doc["tu"]=unit; //Einheit
  doc["h"]=humidity; //Feuchte
  doc["hu"]="%";
  doc["g"]=gas; //Gaskonzentration
  doc["gu"]="ppm";
  //Aus dem Objekt wird die JSON Zeichenkette im Buffer gebildet
  uint16_t n = serializeJson(doc, buffer);
  //Kontrollausgabe
  Serial.println(buffer);
  //Der Messwert wird mit dem Thema an den Broker gesendet
  if (!client.publish(conf.getValue("thema"), buffer, n)) {
    Serial.print("Fehler beim Senden an MQTT Server = ");
    Serial.println(client.state());
  }
  Serial.printf("Temperatur = %f %s Feuchtigkeit = %f %%   Gaskonzentration = %f       ppm\n",temperature,unit.c_str(),humidity,gas);
}


void setup() {
  Serial.begin(74880); //Damit auch Bootmeldungen des ESP8266 angezeigt werden
  //I2C Bus starten
  Wire.begin();
  //Start des SHT30
  sht.begin(0x44);
  //Seriennummer des SHT30 anzeigen
  Serial.print("Serial #");
  Serial.println(sht.readSerialNumber());
  //Die Setupfunktion in der Include Datei aufrufen
  //WLAN und Konfiguration werden vorbereitet
  //Verbindung zum MQTT Broker wird hergestellt
  //Der Parameter param enthält zusätzliche Formulareinträge
  //für das Konfigurationsformular, true bedeutet dass wir einen
  //Sensor haben
  ESP_MQTT_setup(param,true);
  //Callbackfunktion zum Senden der Daten registrieren
  onPublish = publishData;
  //Das Regressionsmodell für die Gaskonzentration wird gewählt
  MQ2.setRegressionMethod(1); //_PPM = a*ratio^b
  int gas = conf.getInt("typ");
  //Die Parameter für das in der Konfiguration gewählte
  //Gas werden gesetzt
  MQ2.setA(gase[gas][0]); MQ2.setB(gase[gas][1]);
  //Gas Sensor Bibliothek initialisieren
  MQ2.init();
  //Gassensor kalibrieren
  Serial.print("Calibrating please wait.");
  float calcR0 = 0;
  for(int i = 1; i<=10; i ++)
  {
    MQ2.update(); // Update data, the arduino will be read the voltage on the analog pin
    calcR0 += MQ2.calibrate(RatioMQ2CleanAir);
    Serial.print(".");
  }
  MQ2.setR0(calcR0/10);
  Serial.println(" done!.");

  if(isinf(calcR0)) {Serial.println("Warning: Conection issue founded, R0 is infite (Open circuit detected) please check your wiring and supply"); while(1);}
  if(calcR0 == 0){Serial.println("Warning: Conection issue founded, R0 is zero (Analog pin with short circuit to ground) please check your wiring and supply"); while(1);}
}

void loop() {
  //Schleifenfunktion der eingebundenen Hilfsdatei aufrufen
  //Sorgt dafür, dass die Messwerte in regelmäßigen
  //Zeitabständen ermittelt und an den Broker gesendet werden
  ESP_MQTT_loop();
}

Download Sketch

Die Compiler Warnung, dass eine Bibliothek eventuell mit dem Board nicht kompatibel ist, kann ignoriert werden.

Da sehr viele Funktionen in der include-Datei umgesetzt werden, bleibt der Code überschaubar. Wichtigste Funktion ist die Callback-Funktion publishData(), die immer dann aufgerufen wird, wenn neue Daten der Sensoren an den Broker übertragen werden sollen. In der Setup Funktion werden die Sensoren vorbereitet und dann das Setup der include-Datei aufgerufen. In der Hauptschleife wird nur die Loop-Funktion der include-Datei aufgerufen.  Gleich am Anfang wird die String-Konstante param definiert, die die Formular-Beschreibung der für den Envy speziellen Konfigurationen enthält.

Nun können wir den Sketch zum Envy hochladen. Dazu müssen wir einen FDTI-Adapter verwenden, bei dem wir GND, TX und RX mit den gleichen Pins am Envy verbinden.

 

Nachdem der Sketch hochgeladen wurde, kann das Programm gestartet werden. Da noch keine Konfiguration existiert, wird ein Accesspoint gestartet. Wir verbinden uns mit einem Smartphone mit diesem Accesspoint (es ist kein Passwort erforderlich) und rufen in einem Browser die Adresse http://192.168.4.1 auf. Es sollte nun die Konfigurationsseite angezeigt werden.

 

Nachdem die Konfiguration gespeichert und der Envy neu gestartet wurde, sendet er im konfigurierten Messintervall ein Datentelegramm an den MQTT-Broker. Die Abbildung zeigt die Nachrichten, die der Broker erhält.


Nachdem der Envy nun seine Messwerte als MQTT Nachrichten zur Verfügung stellt wollen wir die Messwerte in der Smarthome Zentrale am AZ-Touch anzeigen lassen. Wie ihr zur Smarthome Zentrale kommt und deren Bedienung, erfahrt ihr aus dem Smarthome Buch. Ich will hier nur eine passende Konfiguration zur Anzeige der Daten vom Envy zeigen. Eine funktionsfähige Smarthome Zentrale ist dafür erforderlich.


Wichtiger Hinweis!

Als das Buch fertiggestellt wurde, gab es das AZ-Touch MOD und das 2.8 Zoll Display noch nicht. Es sind daher kleine Änderungen an den SmarthomeZentrale_x.ino Sketches im Material zum Buch notwendig. Ausnahme der Sketch SmarthomeZentrale_8.ino im Ordner „Neu“, der bereits alle Änderungen für den AZ-Touch MOD mit 2.8 Zoll Display enthält. Welche Änderungen durchzuführen sind, wird in der Datei ReadMe.txt beschrieben.

In der Smarthome Zentrale fügen wir eine neue leere Seite an. Auf dieser Seite fügen wir drei Farbbalken Widgets mit einer Breite von 4 Einheiten und einer Höhe von 14 Einheiten hinzu. Die Abbildungen zeigen die eingestellten Werte:


Da die Grenzwerte nicht passen, werden wir die spezifischen Einstellungen der Widgets ebenfalls anpassen. Die Abbildungen zeigen die eingestellten Werte:


Die Display-Seite für den Envy sollte dann so aussehen:

 

 

Viel Spaß mit dem AZ-Envy.

Specials

5 Kommentare

Jan

Jan

Alles klar – vielen Dank für die Info – probiere die Beispiele mal aus…

Grüße, Jan

Bernd Albrecht

Bernd Albrecht

Die Frage bezieht sich auf den Sensor MQ-2, der auch separat im Sortiment von AZ-Delivery verkauft wird. Auf der Produktseite gibt es dazu weiterführende Dokumentation.
https://www.az-delivery.de/en/products/gas-sensor-modul?pos=1&_sid=d98f89d48&ss=r
Kurz und knapp: Der Sensor liefert (nur) einen analogen Wert, der ungefähr einer bestimmten Gaskonzentration entspricht. Der Messtechniker nennt so etwas „Schätzeisen“. Wenn Sie nur den analogen Wert messen ( analogRead(A0) ) und einen Schwellenwert für einen Alarm festlegen, dann wird auch bei Rauch dieser Alarm ausgelöst.
Erfahrungswert: Bei einem 10-bit ADC (max. Wert 1023) liegt der Wert für normales Raumklima bei 70 – 110. Wenn Sie den Schwellenwert dann auf 200 festlegen, wird Alarm ausgelöst, wenn ein Schnapsglas in der Nähe verschüttet wird oder der offene Kamin nicht richtig zieht.

Jan

Jan

Hallo,
wie kann ich mir den Rauch(Smoke) ausgeben lassen?
Ihr bietet nur die Gase an…

Danke,

Jan

Gerald Lechner

Gerald Lechner

Hallo Thomas,
Du hast nichts falsch gemacht. Beim Upload der Files auf GitHub ist etwas schief gelaufen und damit war das ZIP File bis auf die Readme Datei leer. Das ist jetzt behoben. Bitte nochmals runterladen.
Sorry Gerald

Thomas Ücok

Thomas Ücok

Hallo,

die ESP8266_MQTT_Conf.h befindet sich nicht in dem GITHub Download. Oder mache ich da etwas
falsch ?

Gruß

Thomas Ücok

Einen Kommentar hinterlassen

Alle Kommentare werden vor der Veröffentlichung moderiert