smarthome-tricks.de

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:

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>

const char* ssid = "WIFI-SSID";
const char* password = "WIFI-PWD";
const char* mqtt_server = "MQTT-BROKER-IP (ioBroker)";

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 &amp;amp;amp;amp;gt; 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 &amp;amp;amp;amp;gt; 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 ?

Die mobile Version verlassen