In diesem Tutorial möchte ich einen Mikrocontroller mit einem verbauten OLED Display vorstellen. Der Mikrocontroller ist ein NodeMCU mit einem ESP8266 Wi-Fi Chip.
Einen NodeMCU habe ich bereits im Tutorial NodeMCU – “Einer für (fast) Alles!” vorgestellt und möchte hier nun auf den betrieb mit dem OLED Display eingehen.
Der Microcontroller wurde mir vom Onlineshop Makershop.de für ein Review zur Verfügung gestellt.
Bezug
Den Mikrocontroller kannst du auf ebay.de* im Shop von Makershop.de für 14,45 € erwerben (Versandkosten fallen nicht an).
Hinweis von mir: Die mit einem Sternchen (*) markierten Links sind Affiliate-Links. Wenn du über diese Links einkaufst, erhalte ich eine kleine Provision, die dazu beiträgt, diesen Blog zu unterstützen. Der Preis für dich bleibt dabei unverändert. Vielen Dank für deine Unterstützung!
Technische Daten des NodeMCU mit OLED Display
NodeMCU
- 12 digitale Pins
- 1 analoger Eingang
- Micro-USB Buchse
- Eingangsspannung 4,75V bis 12V
- Abmaße 6,2 cm x 2,7 cm
OLED Display
- Abmaße 0,96 Zoll (2,7 cm x 1,5 cm)
Besonderheiten
Der NodeMCU mit OLED Display ist breiter als der NodeMCU.
Wenn der Mikrocontroller auf ein Steckbrett verbaut wird, so kann man nur eine Pinreihe verwenden.
Auf dem NodeMCU mit OLED Display ist bereits ein Sketch installiert, welcher auf dem Display einige Funktionen zeigt.
Quellcode
In den nachfolgenden Beispielen möchte ich aufzeigen wie das Display des Mikrocontrollers betrieben wird.
Installation der benötigten Bibliothek
Für den Betrieb des Displays wird eine Bibliothek benötigt, diese kann man bequem über die Arduino IDE installieren. Dazu wird über das Hauptmenü der Eintrag “Sketch” (1) -> “Bibliothek einbinden” (2) -> “Bibliotheken verwalten …” (3) navigiert.
Es sollte sich nun nach einer kurzen Ladezeit der Boardverwalter öffnen. In diesem Dialog suchen wir zunächst nach dem Eintrag “SSD1306” (1) danach wird der Eintrag “ESP8266 and ESP32 Oled Driver for SSD1306 ….”(2) ausgewählt. Nun noch die Schaltfläche “Installieren” (3) betätigen. Nachdem die Installation erfolgreich war, kann der Dialog mit der Schaltfläche “Schließen” (4) geschlossen werden.
Wie üblich bringt auch diese Bibliothek einige Beispiele mit, welche nach einer kleinen Konfiguration lauffähig sind.
SDA & SCL
Das Display ist über die digitalen Pins D1 – SDA & D2 – SCL angeschlossen, dieses muss in den Beispielen geändert / angepasst werden. Dann sind diese jedoch lauffähig.
Hello World!
Als Erstes ein Klassiker “Hello World!”. Für die Darstellung von Text kann man zwischen 3 Schriftgrößen wählen.
Für unser “Hello World!” reicht die Schriftgröße 16 völlig aus.
#include <Wire.h> //Bibliothek für die Arduino IDE <= 1.6.5 #include "SSD1306Wire.h" //Display Bibliothek #include "OLEDDisplayUi.h" //Display Bibliothek //Initialisieren des Displays //D1 - SDA //D2 - SCL SSD1306Wire display(0x3c, D1, D2); //Initialisieren des Objektes für die Oberfläche des Displays. //Es lassen sich mehrere Frames damit erzeugen welche in einem //definierten Interval angezeigt werden. OLEDDisplayUi ui ( &display ); //Funktion zum anzeigen des Textes "Hello World!" auf dem Display. void helloFrame(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { display->setTextAlignment(TEXT_ALIGN_LEFT); display->setFont(ArialMT_Plain_16); display->drawString(0, 0, "Hello World!"); } //Array mit den Frames für das Display. //Jeder Eintrag in diesem Array repräsentiert eine Darstellung //des Displays. FrameCallback frames[] = { helloFrame}; //Anzahl der maximalen Frames welche angezeigt werden sollen. const int frameCount = 1; void setup() { //Setzen der Bildwiederholungsfrequenz ui.setTargetFPS(60); //Setzen der Frames sowie die Anzahl der Frames. ui.setFrames(frames, frameCount); //Initialisieren der Oberfläche. ui.init(); //Bildschirm drehen, ansonsten ist die Darstellung auf dem Kopf. display.flipScreenVertically(); } void loop() { int remainingTimeBudget = ui.update(); }
Textausgabe auf dem OLED Display
Einfache Grafiken
Auf dem OLED Display können einfache Grafiken angezeigt werden. In dem Sketch, welcher ab Werk auf dem NodeMCU installiert wurde ist das Wifi Zeichen zu sehen.
Wollen wir uns also nun mal ansehen wie eine Grafik auf dem Display erzeugt werden kann.
X BitMap Image
Die Bilder, welche auf dem Display angezeigt werden können, müssen im X Bitmap Format vorliegen.
Auf Wikipedia ist ein kleiner Beitrag zum X Bitmap Format zu finden:
X BitMap (XBM) ist ein Format für die Darstellung von monochromen Rastergrafiken, hauptsächlich Cursors und Icons. Das XBM-Dateiformat wurde 1989 durch XPM für X11 ersetzt. Die Grafiken bestehen aus reinen Textdateien; sie können mit einem einfachen Texteditor bearbeitet und direkt in C-Quellcode eingebunden werden.
Seite „X BitMap“. In: Wikipedia, Die freie Enzyklopädie. Bearbeitungsstand: 21. November 2017, 09:08 UTC. URL: https://de.wikipedia.org/w/index.php?title=X_BitMap&oldid=171218654 (Abgerufen: 17. August 2018, 10:06 UTC)
Umandeln von PNG nach XBM
Um ein Bild in das XBM Format umzuwandeln, muss man nicht unbedingt spezielle Software erwerben, man kann dieses bequem online mit dem Tool https://www.online-utility.org/image/convert/to/XBM erledigt. Hier lädt man das gewünschte Bild hoch und kann die XBM Datei herunterladen.
Ich habe mein Logo im Format 48×48 Pixel hochgeladen und eine Datei mit folgendem Inhalt heruntergeladen:
#define 1534500608686_width 48 #define 1534500608686_height 48 static char 1534500608686_bits[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xBE, 0xEF, 0xFB, 0xFE, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x03, 0x00, 0x00, 0x00, 0xC0, 0xA3, 0x3B, 0x8D, 0xA3, 0x69, 0x8E, 0x21, 0x19, 0xCE, 0xB6, 0x6D, 0xC3, 0x73, 0x8B, 0xD9, 0x90, 0x1D, 0xC2, 0x63, 0x1B, 0xCB, 0xB5, 0x1D, 0xC2, 0x03, 0x00, 0x20, 0x80, 0x01, 0xC0, 0x03, 0x00, 0x78, 0xF4, 0x01, 0xC0, 0x03, 0x00, 0x3C, 0x01, 0x02, 0x80, 0x01, 0x00, 0x9E, 0xC2, 0x01, 0xC0, 0x03, 0x00, 0x67, 0xF5, 0x01, 0xC0, 0x03, 0x80, 0x97, 0xFE, 0x03, 0x40, 0x03, 0xC0, 0x6D, 0x7D, 0x06, 0xC0, 0x03, 0xF0, 0xD6, 0xFD, 0x0E, 0xC0, 0x03, 0xF0, 0x5F, 0xBE, 0x39, 0xC0, 0x01, 0xFC, 0x7F, 0xFF, 0x36, 0xC0, 0x03, 0xEC, 0xBF, 0x5F, 0x63, 0xC0, 0x03, 0xFE, 0xDF, 0x7F, 0xDB, 0xC0, 0x03, 0xFF, 0xFF, 0xEF, 0xBD, 0x81, 0x03, 0xFF, 0xEF, 0xDF, 0x9B, 0xC1, 0x83, 0xFF, 0x7F, 0xF7, 0xFF, 0xC3, 0x01, 0xFF, 0xEF, 0xFF, 0xFF, 0xC3, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0x03, 0xFF, 0x77, 0xFF, 0xFF, 0xC1, 0x03, 0xFE, 0xF7, 0xFF, 0xFF, 0x80, 0x03, 0xF8, 0xFF, 0xFF, 0x7F, 0xC0, 0x03, 0xF8, 0xFF, 0xFF, 0x3F, 0xC0, 0x01, 0xF0, 0xFE, 0xFF, 0x1F, 0xC0, 0x03, 0xF0, 0xFE, 0xFF, 0x0F, 0xC0, 0x03, 0x00, 0xFF, 0xFF, 0x0F, 0xC0, 0x03, 0x80, 0xFB, 0xFF, 0x03, 0xC0, 0x03, 0xC0, 0xFD, 0xFF, 0x01, 0x40, 0x03, 0xC0, 0xFD, 0xFF, 0x00, 0xC0, 0x01, 0x40, 0xF8, 0x77, 0x00, 0xC0, 0x63, 0x00, 0xFC, 0x2F, 0x00, 0xC0, 0x43, 0x06, 0x1C, 0x0D, 0x00, 0x40, 0x63, 0x06, 0xDC, 0xCD, 0x6E, 0xC6, 0x63, 0xC6, 0xCD, 0x4C, 0x6C, 0xC6, 0x63, 0x06, 0xCC, 0xEC, 0x6E, 0xCE, 0x21, 0x04, 0x24, 0x88, 0xC2, 0x4E, 0x03, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x03, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x7F, 0xDF, 0xF7, 0xFD, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, };
Quellcode
Ich musste den Datentyp für das Bild von “static char ” in “const uint8_t” ändern.
Ansonsten habe ich mich am Beispiel orientiert.
#include <Wire.h> //Bibliothek für die Arduino IDE <= 1.6.5 #include "SSD1306Wire.h" //Display Bibliothek #include "OLEDDisplayUi.h" //Display Bibliothek //Initialisieren des Displays //D1 - SDA //D2 - SCL SSD1306Wire display(0x3c, D1, D2); //Initialisieren des Objektes für die Oberfläche des Displays. //Es lassen sich mehrere Frames damit erzeugen welche in einem //definierten Interval angezeigt werden. OLEDDisplayUi ui ( &display ); #define img_Width 48 #define img_Height 48 const uint8_t image[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xBE, 0xEF, 0xFB, 0xFE, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x03, 0x00, 0x00, 0x00, 0xC0, 0xA3, 0x3B, 0x8D, 0xA3, 0x69, 0x8E, 0x21, 0x19, 0xCE, 0xB6, 0x6D, 0xC3, 0x73, 0x8B, 0xD9, 0x90, 0x1D, 0xC2, 0x63, 0x1B, 0xCB, 0xB5, 0x1D, 0xC2, 0x03, 0x00, 0x20, 0x80, 0x01, 0xC0, 0x03, 0x00, 0x78, 0xF4, 0x01, 0xC0, 0x03, 0x00, 0x3C, 0x01, 0x02, 0x80, 0x01, 0x00, 0x9E, 0xC2, 0x01, 0xC0, 0x03, 0x00, 0x67, 0xF5, 0x01, 0xC0, 0x03, 0x80, 0x97, 0xFE, 0x03, 0x40, 0x03, 0xC0, 0x6D, 0x7D, 0x06, 0xC0, 0x03, 0xF0, 0xD6, 0xFD, 0x0E, 0xC0, 0x03, 0xF0, 0x5F, 0xBE, 0x39, 0xC0, 0x01, 0xFC, 0x7F, 0xFF, 0x36, 0xC0, 0x03, 0xEC, 0xBF, 0x5F, 0x63, 0xC0, 0x03, 0xFE, 0xDF, 0x7F, 0xDB, 0xC0, 0x03, 0xFF, 0xFF, 0xEF, 0xBD, 0x81, 0x03, 0xFF, 0xEF, 0xDF, 0x9B, 0xC1, 0x83, 0xFF, 0x7F, 0xF7, 0xFF, 0xC3, 0x01, 0xFF, 0xEF, 0xFF, 0xFF, 0xC3, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0x03, 0xFF, 0x77, 0xFF, 0xFF, 0xC1, 0x03, 0xFE, 0xF7, 0xFF, 0xFF, 0x80, 0x03, 0xF8, 0xFF, 0xFF, 0x7F, 0xC0, 0x03, 0xF8, 0xFF, 0xFF, 0x3F, 0xC0, 0x01, 0xF0, 0xFE, 0xFF, 0x1F, 0xC0, 0x03, 0xF0, 0xFE, 0xFF, 0x0F, 0xC0, 0x03, 0x00, 0xFF, 0xFF, 0x0F, 0xC0, 0x03, 0x80, 0xFB, 0xFF, 0x03, 0xC0, 0x03, 0xC0, 0xFD, 0xFF, 0x01, 0x40, 0x03, 0xC0, 0xFD, 0xFF, 0x00, 0xC0, 0x01, 0x40, 0xF8, 0x77, 0x00, 0xC0, 0x63, 0x00, 0xFC, 0x2F, 0x00, 0xC0, 0x43, 0x06, 0x1C, 0x0D, 0x00, 0x40, 0x63, 0x06, 0xDC, 0xCD, 0x6E, 0xC6, 0x63, 0xC6, 0xCD, 0x4C, 0x6C, 0xC6, 0x63, 0x06, 0xCC, 0xEC, 0x6E, 0xCE, 0x21, 0x04, 0x24, 0x88, 0xC2, 0x4E, 0x03, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x03, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x7F, 0xDF, 0xF7, 0xFD, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, }; //Funktion zum anzeigen eines Logos auf dem Display. void imageFrame(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { display->drawXbm(x + 34, y + 14, img_Width, img_Height, image); } //Array mit den Frames für das Display. //Jeder Eintrag in diesem Array repräsentiert eine Darstellung //des Displays. FrameCallback frames[] = { imageFrame}; //Anzahl der maximalen Frames welche angezeigt werden sollen. //Wenn der Wert 0 ist dann wird nur das erste Frame angezeigt und //die Seitenanzeige im Display entfällt. const int frameCount = 0; void setup() { //Setzen der Bildwiederholungsfrequenz ui.setTargetFPS(60); //Setzen der Frames sowie die Anzahl der Frames. ui.setFrames(frames, frameCount); //Initialisieren der Oberfläche. ui.init(); //Bildschirm drehen, ansonsten ist die Darstellung auf dem Kopf. display.flipScreenVertically(); } void loop() { int remainingTimeBudget = ui.update(); }
Ausgabe des Bildes auf dem OLED Display
Das Logo wird relativ gut dargestellt, jedoch wird deutlich das bei einem weniger aufwändigen Bild das Display seine stärken zeigen kann.
Hallo,
habe mir gerade deinen Blog durchgelesen. Schöne Anleitung. Habe es versucht mit meinen Beiden hier liegenden Kontrollern nachzuvollziehen. Die Biliotheken sind unter Arduino installiert. Die Version ohne LED funktioniert wunderbar, ich kann aber das Teil mit dem OLED nicht ansprechen, weil der Port unter MAC OS nicht gefunden wird. Wird ein zusätzlicher Treiber benötigt?
Grüße
Steve
Hallo,
danke für deinen Kommentar.
Mit Mac OS habe ich keine Erfahrung, jedoch ist es bei den Chinaklones nicht unüblich das ein Treiber installiert werden muss. Schaue doch mal im “Gerätemanager” ob dort ein Gerät angezeigt wird welches nicht installiert werden konnte.
Unter Win7 musste ich einmal einen Treiber für den CH370 Chip installieren.
Gruß,
Stefan Draeger
Hallo,
bei mir wird kein ssd1306 gefunden.Arduino ide 1.8.15
MfG
Hi,
ich habe in der neuen Version Ardiono IDE 1.8.15 (installiert aus dem Microsoft Store) die Adafruit Bibliothek SSD1306 gefunden.
(siehe hier https://ibb.co/kh0DfQh)
Gruß,
Stefan
hallo herr draeger, ihre oben angeführten beispiele haben mich neugierig gemacht und so hab ich mir einen esp8266 mit oled display gekauft. leider musste ich feststellen, das beide sketche, so wie sie auf dieser seite angegeben sind, sich ohne probleme und fehlermeldungen aufspielen lassen, aber rein gar nichts im display angezeigt wird.
schließt man ein oled 0.96 extern über d1 und d2 an funktioniert alles einwandfrei.
nach mehrstundiger suche und ausprobieren bin ich dann auf den fehler gestoßen. es hat leider so lange gedauert, weil ich noch neu auf diesem gebiet bin.
wenn man das fest instalierte display nutzen möchte muss man sda —>>d6 und scl —>>d5 schalten und die zeile ssd1306 wire display (0x3c, d1,d2) in (0x3c,d6,d5) ändern und schon funktioniert es wie gewünscht.
ich würde sie bitten das zu ändern, da gerade anfänger wie ich schnell die lust verlieren und manchmal einfach nicht die zeit zur recherche haben.
es hat spass gemacht mich dem problem zu stellen und am ende ist das positive ergebnis sehr zufriedenstellend.
ich freue mich auf weitere ideen von ihnen
mfg m. jacke
Hallo Mirko,
ich habe das gerade ausprobiert und der Code der Seite funktioniert bei mir, ggf. gibt es wohl mehrere Varianten von dem Mikrocontroller.
Welchen hast du denn genau?
Gemäß des Pinouts ist beim ESP8266 SDA & SCL an den Pins GPIO5, GPIO6 (D1 & D2).
Gruß, Stefan
Hallo Stefan,
der Controller von Ideaspark und hat außer der Bezeichnung Bezeichnung ESP8266MOD steht leider nichts auf dem Chip. In der Arduino IDE läuft er auch nur unter NOTEMCU 1.0.
Wie gesagt ich beschäftige erst seit einem halben Jahr mit der Materie und bekomme vieles nur durch vergleichen und ausprobieren zum laufen.
Über D1 u. D2 habe ich nur ein externes OLED 0.96 zum laufen gebracht.
Wünsche noch einen schönen Abend.
MfG Mirko
Hi,
habe mir den Mikrocontroller mal bestellt, schaue mir das genauer an was da so ist.
(Lieferung erfolgt zwischen 11.Sep und 18.Sep)
Gruß, Stefan
Die Pins bei einigen 8266 entsprechen nicht ihrer Beschriftung:
D5 = GPIO14 = 14
D6 = GPIO12 = 12
SSD1306Wire display(0x3c, 14, 12);
Hi,
es gibt hier verschiedene Mikrocontroller mit unterschiedlichen Pinouts.
Man muss quasi immer genau checken, welchen Mikrocontroller man vor sich hat.
Gruß, Stefan