ESP8266 OLED Display für ioBroker über MQTT

In diesem Artikel beschreibe ich das OLED Display Projekt, mit dem Informationen von ioBroker angezeigt werden können.

Das Display soll über das MQTT-Protokoll Informationen aus ioBroker Datenpunkten (Objekte) anzeigen können. Angesteuert werden soll das Display von einem ESP8266 über WLAN. Die wichtigste Anforderung an das Projekt war die Trennung zwischen Logik-und Präsentationsschicht. Die komplette Logik soll später in ioBroker abgebildet werden können. Der ESP8266 abonniert die entsprechenden MQTT-Topics und zeigt diese auf dem OLED-Display an. Bevor wir nun mit dem Aufbau der Hardware beginnen können, hier die Liste der benötigten Komponenten:


1. Aufbau der Hardware

Im nächsten Schritt kümmern wir uns um den Aufbau des ESP8266 mit dem OLED-Display und beginnen mit der Programmierung. Zunächst verkabeln wir den ESP8266 mit dem OLED Display nach folgender Pin-Belegung:

OLED-DisplayESP8266
GNDGND
VCC3V3
SCLD1
SDAD2


2. Programmierung der Software für den ESP8266

Nach dem wir nun den ESP8266 mit dem Display verbunden haben beginnen wir mit der Einrichtung der Arduino IDE für unser Projekt sowie mit der Programmierung der Software für den ESP8266. Im ersten Schritt müssen wir noch folgende Libraries installieren, welche für die Kommunikation mit dem Display benötigt werden:

  • Adafruit GFX Library
  • Adafruit SSD1306

 

Sketch-Code für die Programmierung des ESP8266:


#include <SPI.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

// Update these with values suitable for your network.
const char* ssid = "WIFI_SSID";
const char* password = "WIFI_KEY";
const char* mqtt_server = "IP_ADRESS_MQTT_SERVER";

String _DisplayLine1 = "";
String _DisplayLine2 = "";
String _DisplayLine3 = "";
String _DisplayLine4 = "";

#define OLED_RESET 0
Adafruit_SSD1306 display(OLED_RESET);

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;

void setup_wifi() {

delay(10);
// We start by connecting to a WiFi network
Serial.println();
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 callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");

if ( strcmp( topic, "display_line1" ) == 0 )
{
_DisplayLine1 = "";
for (int i = 0; i < length; i++) { _DisplayLine1 += (char)payload[i]; }
}

if ( strcmp( topic, "display_line2" ) == 0 )
{
_DisplayLine2 = "";
for (int i = 0; i < length; i++) { _DisplayLine2 += (char)payload[i]; }
}

if ( strcmp( topic, "display_line3" ) == 0 )
{
_DisplayLine3 = "";
for (int i = 0; i < length; i++) { _DisplayLine3 += (char)payload[i]; }
}

if ( strcmp( topic, "display_line4" ) == 0 )
{
_DisplayLine4 = "";
for (int i = 0; i < length; i++) { _DisplayLine4 += (char)payload[i]; }
}

UpdateDisplay();
}

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 (client.connect(clientId.c_str())) {
Serial.println("connected");

client.subscribe("display_line1");
client.subscribe("display_line2");
client.subscribe("display_line3");
client.subscribe("display_line4");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}

void UpdateDisplay()
{
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(2);

display.setCursor(1,0);
display.print(_DisplayLine1.c_str());
display.setCursor(1,16);
display.print(_DisplayLine2.c_str());
display.setCursor(1,32);
display.print(_DisplayLine3.c_str());
display.setCursor(1,48);
display.print(_DisplayLine4.c_str());
display.display();
}

void setup() {
Serial.begin(115200);

setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);

display.begin( SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(2);
display.display();
}

void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
}

 

3. Vorbereitungen in ioBroker

Im ersten Schritt legen wir uns 4 Datenpunkte „display_line1 … display_line4“ in ioBroker an. Die Inhalte (Zeichenfolgen) der Datenpunkte werden später auf dem Display angezeigt. Zur Initialisierung können wir diese Datenpunkte bereits mit den Zeichenfolgen „Zeile 1“ bis „Zeile 4“ befüllen.

 

4. Erstellung der ioBroker Display-Logik

Auf dem Display sollen in meinem Beispiel 4 Zeilen angezeigt werden. Das Display soll folgenden Aufbau bekommen:

System: <STATUS>
Device: <STATUS>
Status: <STATUS>
Water: <YES>

Dabei soll im Systemstatus OK angezeigt werden, wenn keine Warnung oder Systemmeldung seitens den HomeMatic Aktoren vorliegt. In der zweiten Zeile möchte ich anzeigen ob noch ein Gerät (Device) eingeschaltet ist. Der Status gibt an, ob noch Fenster oder Türen geöffnet sind. In der letzten Zeile steht der Status des Bewässerungsbedarfs. Der Outdoorsensor misst hier die Bodenfeuchtigkeit und soll ab einem vorher definierten Grenzwert die Anzeige „Water“ auf YES stellen.

Nach dem wir nun die Logik der Anzeige definiert haben, beginnen wir mit der Implementierung des entsprechenden Scripts. Im ersten Schritt lege mich nun ein neues JavaScript an. Der Script-Code der Steuerung wird nun folgendermaßen definiert:

 

on({id: "hm-rpc.0.XXX.1.STATE", change: "ne"}, 
function (obj) { UpdateDisplayStatus(); });

on({id: "hm-rpc.0.XXX.1.STATE", change: "ne"}, 
function (obj) { UpdateDisplayStatus(); });

on({id: "hm-rpc.0.XXX.1.STATE", change: "ne"}, 
function (obj) { UpdateDisplayStatus(); });

on({id: "hm-rpc.0.XXX.1.STATE", change: "ne"}, 
function (obj) { UpdateDisplayStatus(); });

on({id: "hm-rpc.0.XXX.1.STATE", change: "ne"}, 
function (obj) { UpdateDisplayStatus(); });

function UpdateDisplayStatus()
{
    // Display Line 1
    var SystemStatusText = "OK";
    if ( getState("hm-rega.0.maintenance").val > 0 ) {
        SystemStatusText = "ER";
    }
    
    // Display Line 2
    var StatusDeviceText = "OFF";
    var StatusDevice_TV = getState("hm-rpc.0.XXX.1.STATE").val;
    var StatusDevice_Licht_Flur = getState("hm-rpc.0.XXX.1.STATE").val;
    var StatusDevice_Licht_Esszimmer = getState("hm-rpc.0.XXX.1.STATE").val;
    if ( StatusDevice_Licht_Flur === true || 
         StatusDevice_Licht_Esszimmer === true || 
         StatusDevice_TV === true ) { 
        StatusDeviceText = " ON";
    }
    
    // Display Line 3
    var StateText = "OK";
    var StateHaustuer = getState("hm-rpc.0.XXX.1.STATE").val;
    var StateTerassentuer = getState("hm-rpc.0.XXX.1.STATE").val;
    if ( StateHaustuer === true || StateTerassentuer === true) {
        StateText = "ER";
    }
    
    // Display Line 4
    var WaterState = "NO";
    if ( getState("mqtt.0.outdoor1_Bodenfeuchtigkeit").val > 700 ) {
        WaterState = "YES";
    }    
    
    // Save display lines
    setState('mqtt.0.display_line1', "System:"  + SystemStatusText );
    setState('mqtt.0.display_line2', "Device:"  + StatusDeviceText );
    setState('mqtt.0.display_line3', "Status: " + StateText );        
    setState('mqtt.0.display_line4', "Water: " + WaterState );
}

Die Basis der Logik-Steuerung stellt die Funktion UpdateDisplayStatus() dar. Diese Funktion ermittelt alle Werte für die Anzeige und schreibt diese im letzten Schritt in die entsprechenden Datenpunke des MQTT-Adapters. Somit werden die neuen Display-Werte an den ESP8266 publiziert. Für das Update des Displays wird die UpdateDisplayStatus() Methode nach einem Update der STATE Datenpunkte der jeweiligen Geräte aufgerufen.

Nach diesem Schema könnt Ihr natürlich auch eine eigene Logik definieren, welche zur Anzeige von Werten dargestellt werden soll.

Ich hoffe euch gefällt dieser Artikel. Über Kommentare unterhalb des Artikels oder per E-Mail freue ich mich wie immer 🙂

Matthias Korte

Hauptberuflich Software-Entwickler und seit einigen Jahren Smart-Home Fan. Angefangen hat alles mit einem RaspberryMatic und einer schaltbaren Steckdose. Mittlerweile habe ich einige Steckdosen, Sensoren, und Thermostate sowie ioBroker zur Visualisierung im Einsatz.

9 Gedanken zu „ESP8266 OLED Display für ioBroker über MQTT

  • Pingback:StatusDisplay ESP8266 ePaper |

  • 9. September 2018 um 20:18
    Permalink

    Hallo !
    Durch dich bin ich zum ESPEasy kommen und habe es nicht bereut. Das machst Du super.
    Beim Skecth von oben bekomme ich aber diese Meldung:
    exit status 1
    PubSubClient.h: No such file or directory
    Kannst Du mir helfen?
    Gruß
    Thomas

    Antwort
  • 9. September 2018 um 21:13
    Permalink

    Hallo Matthias,
    jetzt habe ich mein Problem mit PubSubclient behoben, war einfach,sorry für meinen Kommentar.
    Aber nach dem Upload des Sketchs für das Display blinkt die WLAN Lampe nur noch und ich empfange meinen Arduino nicht mehr…..

    Antwort
    • 10. September 2018 um 6:34
      Permalink

      Moin Thomas,
      kein Problem. Hast Du in die Setup-Methode bereits Ausgaben für die serielle Schnittstelle gemacht? Mit diesen Ausgaben siehst Du dann, wie weit das Programm läuft, und wo er evtl. hängen bleibt. Versuche das mal und geb mir nochmals Bescheid. Alternativ erneut flashen und nochmal probieren.

      Antwort
  • 14. September 2018 um 20:37
    Permalink

    Moin Matthias,
    mein Arduino freezed jetzt immer. Über die ser.Schnittstelle läuft dann auch nichts.
    Das Problem tritt immer dann auf, wenn ich den Sketch uploade.

    Ich habe die 2er Firmware.

    Antwort
    • 16. September 2018 um 7:14
      Permalink

      Moin,

      tritt das Problem schon während dem Upload auf? Wenn nein, versuche mal Code herauszunehmen (auskommentieren), so lange bis Du die Zeile ausfindig machen kannst, die den freeze verursacht.

      Antwort
  • 24. September 2018 um 13:48
    Permalink

    Hallo !
    Jetzt ist der Fehler raus. Ich hatte die IP im http-Format eingegeben. Mist.
    Nun gehts. Aber bei mir ist die Schrift so groß´, dass nur 2 Zeilen reinpassen. Woran kann das liegen?

    und wie machst Du das mit der generellen Erreichbarkeit des EspEASY? nach dem Start des Scripts von Dir, ist der Nodemcu nicht mehr erreichbar.
    Dadurch kann ich auch nicht die anderen POrts belegen,oder?

    Antwort
  • 19. November 2018 um 13:46
    Permalink

    Hi,
    Ich habe einen Sonoff Touch im Flur für die Statusabfrage verbaut .
    Im moment habe ich es so realisiert, dass wenn ich auf den Sonoff Touch drücke, dann eine Nachricht per Telegram auf das Handy kommt ob die Fenster auf sind.
    Alles mit iobroker am laufen.

    Jetzt die frage, könnte man auch so ein OLED Display über den Sonoff Touch anschließen und laufen lassen ?
    Bei Tastendruck auf den Sonoff Touch bekomme ich eine Info auf dem OLED Display ob z.b Fenster auf sind?

    Danke dir schonmal

    Antwort
    • 15. Dezember 2018 um 15:56
      Permalink

      Ja, das wäre über einen ESP8266, OLED-Display sowie MQTT auf jeden Fall möglich. Der Sonoff triggert einen Datenpunkt im ioBroker. Dadurch werden die Informationen gesammelt und über einen weiteren Datenpunkt an MQTT-weitergegeben. Der ESP8266 hat den Datenpunkt abonniert und zeigt dann die Informationen an. Sollte relativ easy möglich sein 🙂

      Antwort

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

* Die Checkbox für die Zustimmung zur Speicherung ist nach DSGVO zwingend.

Ich akzeptiere