ESP8266ESP8266 - SmartHome ProjekteioBroker Status-Display

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>

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 ?

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.

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

  • Pingback: StatusDisplay ESP8266 ePaper |

  • Thomas

    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
  • Thomas

    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
    • Matthias Korte

      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
  • Thomas

    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
    • Matthias Korte

      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
  • Thomas

    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
    • Hallo,
      konntest du es lösen? Bei mir werden leider auch nur 2 Zeilen angezeigt.

      Antwort
  • Fischer

    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
    • Matthias Korte

      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
  • Andreas

    Moin moin.
    Hab da mal ne Frage.
    Ich habe einen Wemos D1 Mini, ein OLED Display (SH1106) und einen fertigen ioBroker mit mqtt.
    Auf dem ioBroker läuft ein Blockly Script, das 4 MQTT Datenpunkte regelmässig updatet. Nicht mit Zahlen, sondern mit kurzem Text.
    Ich würde gerne einfach diese 4 Datenpunkte untereinander auf dem Display ausgeben. Diese 4 Zeilen sollte sich natürlich aktualisieren, sobald der Datenpunkt im MQTT Broker aktualisiert wird.
    Mit espEasy klappt es teilweise, denn leider kann es nur Zahlen ausgeben.
    Wäre das mit deinem Sketch und Script auch für Text möglich?
    Vielen Dank schonmal.

    Grüße
    Andreas

    Antwort
  • Andre

    4 Zeilen Fix.

    #define SCREEN_WIDTH 128 // OLED display width, in pixels
    #define SCREEN_HEIGHT 64 // OLED display height, in pixels

    #define OLED_RESET 0
    Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
    //Adafruit_SSD1306 display(OLED_RESET);

    Antwort
  • Alveran

    Hallo,
    ist es möglich Benutzername und Kennwort bei der MQTT Verbindung mit zu übergeben?

    Antwort
    • tom

      das würde mich auch brennend interessieren.

      Antwort
      • Matthias Korte

        Hallo,

        klar, das geht ganz einfach:

        In Zeile 22 des Skechtes, den Code wie folgt erweitern:

        PubSubClient client(espClient,"DeinUserName","DeinPasswort");

        Antwort
        • Benny

          no matching function for call to ‚PubSubClient::PubSubClient(WiFiClient&, const char [13], const char [13])‘

          Was mach ich falsch?

          Antwort
  • Gerhard

    Hallo ich habe das Problem das ich immer nur 2 Zeilen von iobroker im adurino einlesen kann
    client.subscribe(„display_line1“);
    client.subscribe(„display_line2“);
    client.subscribe(„display_line3“);
    client.subscribe(„display_line4“);
    Wenn ich z.b Zeile 1 und 2 auskommentiere kann ich 3 in d 4 einlesen

    Schoene Gruesse von Gerhard

    Antwort
  • Gerhard

    Ich nochmal,

    was mache ich falsch?

    Es werden immer nur zwei Zeilen eingelesen

    15:32:18.292 -> Attempting MQTT connection…connected
    15:32:22.737 -> Message arrived [display_line1]
    Message arrived [display_line2]
    Attempting MQTT connection…connected
    15:33:27.876 -> Message arrived [display_line1]
    Message arrived [display_line2]
    Attempting MQTT connection…connected
    15:34:33.205 -> Message arrived [display_line1] usw.

    Schöne Grüße Gerhard

    Antwort
  • Hallo,

    Super-Projekt, aber ich bekomme es irgendwie nicht hin.

    Wenn ich Deine Anleitung 1 zu 1 befolge, zeigt das OLED komische Pixel und die MCU startet immer wieder neu.
    Jetzt habe ich mal den Code von Andre (s.o.) eingefügt, dann startet er normal, sagt auch, dass er die MQTT Zeilen empfangen hat, aber das Display bleibt komplett schwarz (Objekte im IO-Broker befüllt)

    Habe eine NodeMCU 3.3, Pinout müsste das gleiche sein?!

    Vielen Dank für einen Tipp
    LG Thilo

    Antwort
  • AtomicIX

    Klasse Projekt. Vielen Dank dafür.
    Ich habe dazu aber noch Fragen.
    Kann ich einen 2ten WLAN Zugang eintragen? Wenn ja, wie?
    Kann man dss anpassen, dss es auch mit dem Sonoff Adapter geht, ohne den direkten Mqtt Server?
    Ich würde gern Temperatur Werte von meinen Zigbee Wetter Sensoren anzeigen lassen. Gibt es für so einen Fall auch eine Vorlage?

    Vielen Dank Gruß Christian

    Antwort
  • Werner

    Hallo Matthias,
    wahrscheinlich liegt es an irgendeiner Einstellung meines Browser oder Rechner. Aber irgendwie wird Dein Script hier ziemlich verstümmelt angezeigt:

    #include &lt;SPI.h&gt;
    #include &lt;Wire.h&gt;
    #include &lt;Adafruit_SSD1306.h&gt;
    #include &lt;Adafruit_GFX.h&gt;
    #include &lt;ESP8266WiFi.h&gt;
    #include &lt;PubSubClient.h&gt;

    und weiter unten:
    if ( strcmp( topic, „display_line1“ ) == 0 )
    {
    _DisplayLine1 = „“;
    for (int i = 0; i &lt; length; i++) { _DisplayLine1 += (char)payload[i]; }
    }

    if ( strcmp( topic, „display_line2“ ) == 0 )
    {
    _DisplayLine2 = „“;
    for (int i = 0; i &lt; length; i++) { _DisplayLine2 += (char)payload[i]; }
    }

    if ( strcmp( topic, „display_line3“ ) == 0 )
    {
    _DisplayLine3 = „“;
    for (int i = 0; i &lt; length; i++) { _DisplayLine3 += (char)payload[i]; }
    }

    if ( strcmp( topic, „display_line4“ ) == 0 )
    {
    _DisplayLine4 = „“;
    for (int i = 0; i &lt; length; i++) { _DisplayLine4 += (char)payload[i]; }
    }

    Antwort
    • Matthias Korte

      Hallo Werner,

      sorry für das Problem. Nein, durch eine Software-Aktualisierung wurde der Code falsch dargestellt. Jetzt passt es wieder 🙂

      LG Matthias

      Antwort
  • Kai Ny

    Hallo. Leider ist das in diesem Beitrag aufgeführte OLED-Display nicht mehr verfügbar. Ich habe deshalb das 1,3 Zoll OLED Display von AZDelivery. Dieses wird jedoch über einen SH1106 Chip gesteuert, anders wie das o.g. Display über den SSD1306.
    Was muss im Sketch angepasst werden, damit das OLED-Display korrekt angesteuert wird?
    Vielen Dank.

    Antwort
    • Matthias Korte

      Moin,
      der Link führt zum Display, laut Amazon sind auch noch genügend vorrätig? Das neue Display habe ich noch nicht hier, von Daher kann ich Dir hier noch nicht viel sagen.
      Du kannst Dir aber mal folgendes Repo auf GitHub ansehen:

      https://github.com/rene-mt/esp8266-oled-sh1106

      LG Matthias

      Antwort
      • Kai Ny

        Hallo Matthias,

        danke für Deine Antwort.
        Ich habe mir das von Dir verwendete Display gekauft (war wieder lieferbar). Alles genau nach Anleitung gemacht. Leider werden mir auf dem Display nur ein paar Pixel angezeigt, ansonsten nichts. MQTT läuft, Script läuft und Datenpunkte werden befüllt.
        Hättest Du eine idee, was ich ggf. falsch mache? Muss ich im Sketch noch was anpassen?

        Danke im Voraus für die Antwort.

        VG Kai

        Antwort
        • Karsten G.

          Hey. Habe gleiche Probleme! Gibts es eine Lösung ? Oder eine Idee? LG, Karsten

          Antwort
  • Dirk

    Hey Matthias,
    Besten Dank für dein tolles Beispiel und die klasse Erklärung. Ich möchte gern bestimmte Topics zB Kueche/Lueften auf das Oled ausgeben. Dabei verwende ich Node Red. Die Daten bekomme ich schon über den Seriel Monitor angezeigt. Aber – Wie muss ich hier den String gestalten, damit diese Ausgabe auch auf dem Oled erscheint?
    Bespiel:
    Luefte!
    Schimmelbildung

    Beste Grüße Dirk

    Antwort
    • Dirk

      Wie erfolgt dieser Schritt?
      „Dein Kommentar muss noch freigeschaltet werden.“

      Antwort
    • Matthias Korte

      Hallo Dirk,

      im Sketch über die beiden folgenden Zeilen:


      display.setCursor(1,0);
      display.print(_DisplayLine1.c_str());
      display.setCursor(1,16);
      display.print(_DisplayLine2.c_str());

      Hier kannst Du mit der Position 1 die X-Koordinate und mit der Position 16 die Y-Koordinate angeben. Dann einfach die beiden Variablen mit deinen entsprechenden Zeichenketten füllen.

      LG Matthias

      Antwort
      • Dirk

        Hi Matthies,
        Besten Dank für Deine Antwort.
        Ich habe das Problem, das ich nicht weiß wie ich die Ausgabe von MQTT als String auf das Display bekomme.
        Ich habe hier mal den Code angehangen:
        Lieben Dank für Deine Unterstützung….
        Gruß Dirk

        #include
        #include

        #include
        #include
        #include

        #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
        #define SCREEN_WIDTH 128 // OLED display width, in pixels
        #define SCREEN_HEIGHT 64 // OLED display height, in pixels
        Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

        const char* SSID = „ssid“;
        const char* PSK = „password“;
        const char* MQTT_BROKER = „ip adresse“;

        String msg = „“;

        WiFiClient espClient;
        PubSubClient client(espClient);

        void setup() {
        Serial.begin(115200);
        setup_wifi();
        client.setServer(MQTT_BROKER, 1883);
        client.setCallback(callback);

        // Display
        display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // I2C address = 0x3C
        delay(1000);
        display.clearDisplay();
        display.display();
        display.setTextSize(1); // Schriftgröße 1-6
        display.setTextColor(WHITE); // WHITE = volle Farbe; BLACK = keine Farbe
        display.setCursor(5, 14); // (x, y) oben links (0,0) unten rechts (63,127)
        display.setFont(&FreeSansBold9pt7b);
        display.print(„Küche“);
        display.drawLine(0, 34, 127, 18, WHITE);
        display.setCursor(33, 55);
        display.print(„Lüftungsanzeige“);
        display.display();
        delay(7000);
        display.clearDisplay();
        display.display();

        }

        void setup_wifi() {
        WiFi.begin(SSID, PSK);

        while (WiFi.status() != WL_CONNECTED) {
        delay(100);
        }

        Serial.println(WiFi.localIP());
        }

        //Display
        void updateDisplay() {
        display.clearDisplay();
        display.setTextSize(1); // Schriftgröße 1-6
        display.setTextColor(WHITE); // WHITE = volle Farbe; BLACK = keine Farbe
        display.setCursor(5, 14); // (x, y) oben links (0,0) unten rechts (63,127)
        display.setFont(&FreeSansBold9pt7b);
        display.print(„Lüften ?“);
        display.drawLine(0, 18, 127, 18, WHITE);
        display.setCursor(33, 51);
        display.print(msg);
        display.display();
        }

        void loop() {
        if (!client.connected()) {
        while (!client.connected()) {
        client.connect(„ESP8266Client“);
        client.subscribe(„Klima/Kueche/#“);
        delay(100);
        }
        }
        client.loop();
        }
        void callback(char* topic, byte* payload, unsigned int length) {
        String msg;
        for (byte i = 0; i < length; i++) {
        char tmp = char(payload[i]);
        msg += tmp;
        }
        Serial.print(msg);
        updateDisplay();
        }

        Antwort
  • Dirk

    Hey Matthias,
    ich möchte das Problem noch etwaseinfachet formulieren:
    Mit diesem Programmschnipsel kann ich das msg am Serial Monitor anzeigen. Wie bekomme ich es auf das OKED?
    }
    void callback(char* topic, byte* payload, unsigned int length) {
    String msg;
    for (byte i = 0; i < length; i++) {
    char tmp = char(payload[i]);
    msg += tmp;
    }
    Serial.println(msg);
    }

    Antwort
    • Matthias Korte

      Hallo Dirk,

      mit den entsprechenden Methoden an der Klasse Adafruit_SSD1306. Im Beispiel von mir rufe ich dazu die UpdateDisplay() Methode auf um dann das Display zu setzen.

      LG Matthias

      Antwort
  • Dirk

    Hi Matthias,
    bitte um Entschuldigung ich raffe es noch nicht 😢
    Wenn ich in meinem Beispiel:

    String msg;
    for (byte i = 0; i < length; i++) {
    char tmp = char(payload[i]);
    msg += tmp;
    }
    Serial.println(msg);

    Hier den String msg auf das Display anzeigen möchte wie kann man das machen?
    Im Serielmonitor wird es angezeigt.
    Besten Dank für Deine Geduld
    Gruß Dirk

    Antwort
    • Matthias Korte

      Hallo Dirk,

      alles gut, wir bekommen das schon hin 😉

      Schau mal bitte in meinem Beispiel-Code ab Zeile 54. Hier werden die Zeichenfolgen über MQTT in die jeweiligen Variablen geschrieben (callbacks). Soweit ist das klar, denke ich. Du hast die Ausgaben ja auch schon in der Serial-Ausgabe.

      Dann wird die Methode UpdateDisplay() aufgerufen. Hier wird dann das Display initialisiert (geleert, Farbe und Schriftgröße gesetzt) und dann letztendlich die Strings über die Methode setCursor und print an die definierte Koordinate des Displays geschrieben. Abschließend muss noch die Display() Methode zur Aktualisierung aufgerufen werden.

      LG Matthias

      Antwort
      • Dirk

        Hi Matthias,
        anbei habe ich folgendes im Setup Tei:

        //Display
        void updateDisplay() {
        display.clearDisplay();
        display.setTextSize(1); // Schriftgröße 1-6
        display.setTextColor(WHITE); // WHITE = volle Farbe; BLACK = keine Farbe
        display.setCursor(5, 14); // (x, y) oben links (0,0) unten rechts (63,127)
        display.setFont(&FreeSansBold9pt7b);
        display.print(„Lüften ?“);
        display.drawLine(0, 18, 127, 18, WHITE);
        display.setCursor(33, 51);
        display.print(msg);
        display.display();
        }

        Und im Loop Teil wird

        updateDisplay()

        aufgerufen.
        Der Text erscheint und die Linie auch aber nicht der Inhalt von msg.
        😢
        Wir nähern uns wahrscheinlich…..
        VG Dirk

        Antwort
        • Matthias Korte

          Hallo Dirk,

          schön von Dir zu lesen. Bitte poste mal den kompletten Code, sieht irgendwo komisch.

          LG Matthias

          Antwort
          • Dirk

            Hi Matthias,
            anbei der aktuelle Code meiner Versuche msg auf dem OLED anzuzeigen.
            Besten Dank und VG Dirk

            #include
            #include

            #include
            #include
            #include

            #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
            #define SCREEN_WIDTH 128 // OLED display width, in pixels
            #define SCREEN_HEIGHT 64 // OLED display height, in pixels
            Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

            const char* SSID = „id“;
            const char* PSK = „per“;
            const char* MQTT_BROKER = „ip“;

            String msg = „“;

            WiFiClient espClient;
            PubSubClient client(espClient);

            void setup() {
            Serial.begin(115200);
            setup_wifi();
            client.setServer(MQTT_BROKER, 1883);
            client.setCallback(callback);

            // Display
            display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // I2C address = 0x3C
            delay(1000);
            display.clearDisplay();
            display.display();
            display.setTextSize(1); // Schriftgröße 1-6
            display.setTextColor(WHITE); // WHITE = volle Farbe; BLACK = keine Farbe
            display.setCursor(5, 14); // (x, y) oben links (0,0) unten rechts (63,127)
            display.setFont(&FreeSansBold9pt7b);
            display.print(„Küche“);
            display.drawLine(0, 34, 127, 18, WHITE);
            display.setCursor(33, 55);
            display.print(„Lüftungsanzeige“);
            display.display();
            delay(7000);
            display.clearDisplay();
            display.display();

            }

            void setup_wifi() {
            WiFi.begin(SSID, PSK);

            while (WiFi.status() != WL_CONNECTED) {
            delay(100);
            }

            Serial.println(WiFi.localIP());
            }

            //Display
            void updateDisplay() {
            display.clearDisplay();
            display.setTextSize(1); // Schriftgröße 1-6
            display.setTextColor(WHITE); // WHITE = volle Farbe; BLACK = keine Farbe
            display.setCursor(5, 14); // (x, y) oben links (0,0) unten rechts (63,127)
            display.setFont(&FreeSansBold9pt7b);
            display.print(„Lüften ?“);
            display.drawLine(0, 18, 127, 18, WHITE);
            display.setCursor(33, 51);
            display.println(msg);
            display.drawRect(79, 37, 3, 3, WHITE); // Das ° Symbol
            display.print(“ C“);
            display.display();
            }

            void loop() {
            if (!client.connected()) {
            while (!client.connected()) {
            client.connect(„ESP8266Client“);
            client.subscribe(„Klima/Kueche/#“);
            delay(100);
            }
            }
            client.loop();
            }
            void callback(char* topic, byte* payload, unsigned int length) {
            String msg;
            for (byte i = 0; i < length; i++) {
            char tmp = char(payload[i]);
            msg += tmp;
            }
            Serial.println(msg);
            updateDisplay();
            }

          • Dirk

            Hi Matthias,
            ich habe nochmal am Code gefeilt, leider funktioniert die Anzeige „Lüften“ und die Ausgabe auf den SerielMonitor. Aber das was man an SerielMonitor angezeigt bekommt sieht man nicht am OLED. Beste Grüße Dirk

            #include
            #include
            #include
            #include

            #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
            #define SCREEN_WIDTH 128 // OLED display Breite, in pixels
            #define SCREEN_HEIGHT 64 // OLED display Höhe, in pixels
            Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

            const char* SSID = „ssid“;
            const char* PSK = „psw“;
            const char* MQTT_BROKER = „ip“;

            WiFiClient espClient;
            PubSubClient client(espClient);

            String msg = „“;
            //float msg = 0.0;

            // ###########################################

            void setup() {
            Serial.begin(115200);
            setup_wifi();
            client.setServer(MQTT_BROKER, 1883);
            client.setCallback(callback);

            display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // I2C address = 0x3C
            delay(1000);
            display.clearDisplay();
            display.setTextSize(2);
            display.setTextColor(WHITE);
            display.setCursor(0, 0);
            display.print(„Lueften?“);
            display.setCursor(0,30);
            display.println(msg);
            display.display();
            }

            void setup_wifi() {
            WiFi.begin(SSID, PSK);
            while (WiFi.status() != WL_CONNECTED) {
            delay(100);
            }

            Serial.println(WiFi.localIP());
            }

            void updateDisplay(){
            display.setTextSize(2);
            display.setTextColor(WHITE);
            display.setCursor(0,30);
            display.println(msg);
            display.display();
            }

            // ##########################################

            void loop() {
            if (!client.connected()) {
            while (!client.connected()) {
            client.connect(„Klima“);
            client.subscribe(„Klima/Kueche/Schimmel“);
            delay(100);
            }
            }

            client.loop();
            }

            void callback(char* topic, byte* payload, unsigned int length) {
            String msg;
            for (byte i = 0; i < length; i++) {
            char tmp = char(payload[i]);
            msg += tmp;
            }

            Serial.println(msg);
            updateDisplay();
            }

  • Dirk

    Hi Matthis und Mitlesende,
    anbei nun der funktionierende Code:
    Man muss nur noch das entsorgende Topic und die Zugangsdaten ändern und dann passe alles.

    #include
    #include

    #include
    #include
    #include

    #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
    #define SCREEN_WIDTH 128 // OLED display width, in pixels
    #define SCREEN_HEIGHT 64 // OLED display height, in pixels
    Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

    const char* SSID = „ssid“;
    const char* PSK = „psw“;
    const char* MQTT_BROKER = „ip“;

    String msg;

    WiFiClient espClient;
    PubSubClient client(espClient);

    void setup() {
    Serial.begin(115200);
    setup_wifi();
    client.setServer(MQTT_BROKER, 1883);
    client.setCallback(callback);

    // Display
    display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // I2C address = 0x3C
    delay(1000);
    display.clearDisplay();
    display.display();
    display.setTextSize(1); // Schriftgröße 1-6
    display.setTextColor(WHITE); // WHITE = volle Farbe; BLACK = keine Farbe
    display.setCursor(5, 14); // (x, y) oben links (0,0) unten rechts (63,127)
    display.setFont(&FreeSansBold9pt7b);
    display.print(„Kueche“);
    display.drawLine(0, 34, 127, 18, WHITE);
    display.setCursor(33, 55);
    display.print(„Lueften“);
    display.display();
    delay(7000);
    display.clearDisplay();
    display.display();

    }

    void setup_wifi() {
    WiFi.begin(SSID, PSK);

    while (WiFi.status() != WL_CONNECTED) {
    delay(100);
    }

    Serial.println(WiFi.localIP());
    }

    //Display
    void updateDisplay() {
    display.clearDisplay();
    display.setTextSize(1); // Schriftgröße 1-6
    display.setTextColor(WHITE); // WHITE = volle Farbe; BLACK = keine Farbe
    display.setCursor(5, 14); // (x, y) oben links (0,0) unten rechts (63,127)
    display.setFont(&FreeSansBold9pt7b);
    display.print(„Lueften ?“);
    display.drawLine(0, 18, 127, 18, WHITE);
    display.setCursor(33, 51);
    display.println(msg);
    display.display();
    }

    void loop() {
    if (!client.connected()) {
    while (!client.connected()) {
    client.connect(„Sudhaus“);
    client.subscribe(„Sudhaus/kesseltemp“);
    delay(100);
    }
    }
    client.loop();
    }
    void callback(char* topic, byte* payload, unsigned int length) {

    // Die Variable leeren
    msg = „“;

    for (byte i = 0; i < length; i++) {
    char tmp = char(payload[i]);

    // Wird in die Globale-Variable `msg` geschrieben.
    msg += tmp;
    }

    Serial.println(msg);
    updateDisplay();
    }

    Antwort
    • Matthias Korte

      Moin Dirk,

      super, ich kam leider noch nicht dazu, an was lag es denn jetzt letztendlich?

      LG Matthias

      Antwort
      • Dirk

        Hi, am Ende lag es an Syntax der Variablen msg. VG Dirk

        1. bei den Settings
        String msg

        2.hier in der callback msg =„“;

        }
        void callback(char* topic, byte* payload, unsigned int length) {
        // Die Variable leeren
        msg = „“;
        for (byte i = 0; i < length; i++) {
        char tmp = char(payload[i]);
        // Wird in die Globale-Variable `msg` geschrieben.
        msg += tmp;
        }

        Antwort
  • Dennis Steinhuebel

    Hallo Matthias,
    habe das selbe Problem wie Thilo vom 9.Juni 2020.
    Habe exakt die Komponenten aus deiner Anleitung. Wenn ich deinen Code 1 zu 1 verwende, dann zeigt das Display komische Pixel und die MCU startet immer wieder neu. Dabei bleibt die MQTT Instanz im ioBoker Gelb.
    Lasse ich das Display weg starte die MCU normal und die Instanz wird Grün. Steuere ich ein Objekt aus dem Script dann wird das Objekt in der MQTT Instanz auch geändert. Es tut also alles so wie es soll, nur halt ohne Display.

    Setze ich den Fix von Andre vom 10.November 2019 ein kann ich das Display dran lassen und die MCU läuft normal und macht nicht ständig Neustarts und die MQTT Instanz bleibt auch Grün.
    Leider zeigt das Display zu keinem Zeitpunkt etwas an und bleibt schwarz.

    Was passt da nicht?

    So sieht aktuell mein Code aus:

    #include
    #include
    #include
    #include
    #include
    #include

    const char* ssid = „XXXXXXXXXXXXXX“;
    const char* password = „XXXXXXXXXXXXXXXXXXXX“;
    const char* mqtt_server = „192.XXX.XXX.XX“;

    String _DisplayLine1 = „“;
    String _DisplayLine2 = „“;
    String _DisplayLine3 = „“;
    String _DisplayLine4 = „“;

    // #define OLED_RESET -1
    // Adafruit_SSD1306 display(OLED_RESET);

    #define SCREEN_WIDTH 128 // OLED display width, in pixels
    #define SCREEN_HEIGHT 64 // OLED display height, in pixels

    #define OLED_RESET 0
    Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, 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_Katzen.display_line1");
    client.subscribe("Display_Katzen.display_line2");
    client.subscribe("Display_Katzen.display_line3");
    client.subscribe("Display_Katzen.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();
    }

    Antwort

Schreibe einen Kommentar zu Dirk Antworten abbrechen

Deine E-Mail-Adresse wird nicht veröffentlicht.