E-Paper Display am ESP32 und ESP8266 - [Teil1]

Einführung

In diesem Blogbeitrag möchte ich Ihnen als Alternative zu LCDs oder OLEDs die Möglichkeit zeigen, E-Paperdisplays an einem ESP32 bzw. ESP8266 zu betreiben. Ich werde Ihnen vorführen, wie man die 1,54-Zoll-Variante von Waveshare anschließt, wie man sie mit Hilfe der Arduino IDE und dafür zur Verfügung stehenden Bibliotheken programmiert. Auf die Vorzüge dieser Technik werde ich natürlich auch eingehen, ebenso wie auf die Nachteile. Los geht's.

Benötigte Hardware

Anzahl Bauteil Anmerkung
1 Mikrocontroller ESP32
1 1,54" E-Paper Display
1 PC mit Arduino IDE


Was ist E-Paper?

Viele von Ihnen kennen diese Technik aus den E-Book-Readern. Wie man es aus dem Namen ableiten kann, steht das E für "Elektronic". Man kann es sinngemäß mit "elektronisches Papier" übersetzen. Daher auch die Bezeichnung Electronic Paper Display (EPD). Ziel der Entwicklung war es, Bildschirme so aussehen zu lassen, als würde man auf bedrucktes Papier schauen. Dabei sind die anzeigenden Bildpunkte selbst nicht leuchtend, sondern reflektieren das Licht.

Einfach erklärt funktioniert das Ganze dadurch, dass kleine Mikrokapseln in einer Flüssigkeit schwimmen. Durch das Anlegen einer Spannung werden sie entweder an die sichtbare Oberfläche gebracht, oder in die Flüssigkeit, wo sie nicht sichtbar sind. Genauere Details dazu finden sie hier oder hier.

Vor- und Nachteile

Der wohl wichtigste Vorteil ist, dass das Bild auf dem Display sichtbar bleibt, auch wenn die Stromversorgung abgeschaltet ist. Es wird nur dann Energie benötigt, wenn die oben genannten Mikrokapseln positioniert werden sollen. Dadurch ist diese Technik sehr stromsparend und damit sehr interessant für Projekte mit schwacher Energiequelle oder um lange Akkulaufzeiten zu begünstigen.

Geringe Auflösung, lange Reaktionszeiten und kleine Bauformen sind hier als Nachteile zu nennen. Außerdem wird bei Dunkelheit eine separate Beleuchtung benötigt. Die Auswahl der Displaytechnik ist also stark vom Anwendungsfall abhängig.

Vorbereitung

Ich verwende ein E-Paper Display in schwarz/weiß von der Firma Waveshare mit einer Größe von 1,54 Zoll und einer Auflösung von 200 x 200 Pixeln. Es ist die Modulvariante mit SPI-Interface. Es ist auch als RAW-Panel erhältlich, außerdem in weiteren Größen, unterschiedlicher Auflösung und auch in anderen Farben. Die Verbindungskabel sind beigelegt und können direkt an das Interface mittels Stecker angeschlossen werden.

 

 

Der Anschluss an den ESP32 Mikrocontroller sieht folgendermaßen aus:

EPD Pins ESP32 GPIO
Busy 27
RST 33
DC 25
CS 26
CLK SCK = 18
DIN MOSI = 23
GND GND
3.3V 3.3V


SCK und MOSI sind durch den Mikrocontroller vorgegeben. Am ESP32 sind das Pin 18 für SCK und Pin 23 für MOSI.  Die Anschlüsse für Busy, RST, DC und CS können frei gewählt werden.

Hinweis: Es gibt ältere Modelle dieses Displays, die ausschließlich mit einer 3.3V Spannung versorgt werden dürfen. Dafür müssen dann ein Logiklevelkonverter und ein Stepdownconverter verwendet werden, wenn man z.B. den Arduino UNO verwendet. Die neuere Ausführung kann mit 3.3V und 5V Spannung versorgt werden. Genauere Informationen dazu findet man auf der Webseite des Herstellers.

 
 

Hinweis: Es gibt verschiedene Boards mit dem ESP 32 (siehe ESP32 – Das Multitalent).

Nutzen Sie in jedem Fall das Pinout Diagramm für Ihr Board.

Die Pinbelegung des ESP32 Node MCU aus dem AZ-Delivery Shop sieht wie folgt aus:

 

Bibliotheken

Öffnet man die Bibliotheksverwaltung in der Arduino IDE (STRG + UMSCH + I) und gibt in das Suchfeld "Waveshare" ein, werden als Suchergebnisse u.a. die EPD-Bibliothek von Asuki Kono und die GxEPD-Bibliotheken von Jean-Marc Zingg aufgelistet.

 

Auf der Githup-Seite von Jean-Marc Zingg wird empfohlen, die GxEPD2-Bibliothek zu verwenden. Wir installieren beide. GxEPD2 benötigt die Adafruit_GFX-Bibliothek. Normalerweise sollte die Arduino IDE während der Installation darauf hinweisen. Für die Verwendung der Bibliotheken ist ein Hardware-SPI-Interface notwendig.

Die Software

EPD-Bibliothek

Ich werde zuerst auf die EPD-Bibliothek eingehen. Wir öffnen das Beispielprogramm EPD1in54ShowRunningTime, dass wir nun unter Beispiele -> EPD in der Auswahl finden. Wir ändern die Zeilen 43 und 44:

// EPD1in54 epd; // default reset: 8, dc: 9, cs: 10, busy: 7
EPD1in54 epd(33, 25, 26, 27); // reset, dc, cs, busy

Damit nutzen wir nicht mehr die Standardpins, sondern unsere eigenen. Anschließend laden wir das Programm auf den ESP32 hoch.

Hinweis: Eventuell gibt es unter den Lesern jemanden, der jetzt zum ersten Mal einen ESP32 verwendet. Im Gegensatz zu dem Arduino Nano, Uno oder auch dem ESP8266 D1 Mini muss man den ESP32 mit der Boot-Taste in den Upload-Modus versetzen. Warten Sie bis im Infofenster nach dem Kompilieren "Connecting...." erscheint und halten dann die BOOT-Taste am ESP32 Mikrocontroller gedrückt.

 

Der Uploadprozess sollte dann beginnen und mit folgenden Zeilen enden:

Leaving...
Hard resetting via RTS pin...

Auf dem EPD sollte nun die Demo zu sehen sein. Zuerst wird ein Hello-World-Text auf einem schwarzen Balken eingeblendet, der Text "e-Paper Demo", sowie einige geometrische Objekte. Anschließend sollte folgendes Bild zu sehen sein:

 

Die Zeit im Display müsste bei 00:00 beginnend aufwärts zählen.

Versuchen wir nun, den Code des Beispiels zu verstehen. Die SPI-Bibliothek wird für den Datenaustausch mit dem Modul benötigt. die EPD-Bibliotheken sind für den Inhalt auf dem Display zuständig. Dann wird noch die imagedata.h inkludiert. Die dazugehörige imagedata.cpp beinhaltet die Daten für ein Bild:

#include <SPI.h>
#include <EPD1in54.h>
#include <EPDPaint.h>
#include "imagedata.h"

COLORED und UNCOLORED stehen für die Darstellung in Schwarz und Weiß auf dem Display:

#define COLORED     0
#define UNCOLORED   1

Im Kommentar des Quellcodes wird darauf hingewiesen, dass der Arduino UNO nicht genügend Arbeitsspeicher zur Verfügung hat und deswegen der Framebuffer nicht benutzt werden kann. Es muss dann ein kleinerer Puffer für das Bild zugewiesen werden und die Anzeige mehrmals in Teilbereichen aktualisiert werden. Auf der Webseite von Waveshare steht geschrieben, dass aus dem gleichen Grund die Funktionen zum Zeichnen nicht unterstützt werden. Wir berechnen den benötigten Speicher:

Der Arduino UNO hat 2 KByte Speicher. Das reicht nicht aus. Der Arduino MEGA hat 8 KByte Speicher. Das müsste theoretisch ausreichen. Für eine größere Auflösung ist dann ein größerer Puffer notwendig. Somit wird der MEGA für größere Displays auch nicht ausreichen. Ich habe mich hauptsächlich deswegen für die Verwendung des ESP32 entschieden.

Fahren wir fort mit der Quellcodeanalyse: Die beiden Objekte vom Typ EPDPaint und EPD1in54 brauchen wir später für die Darstellung auf dem Display. An dem Namen 1in54 erkennt man, dass es sich um die Displaygröße 1,54 Zoll in schwarz/weiß handelt. 1in54B ist das 1,54 Zoll (B) Display in schwarz/rot/weiß und 1in54C die schwarz/gelb/weiße Ausführung mit 152x152 Pixeln.

Das Objekt paint bekommt ein Zeichenarray übergeben, das als Bildpuffer dient. Das Objekt epd erhält die Pinnummern, an das unser Display angeschlossen ist:

unsigned char image[1024];
EPDPaint paint(image, 0, 0);    // width should be the multiple of 8
EPD1in54 epd(33, 25, 26, 27);   // reset, dc, cs, busy

Die Variablen für die Zeitmessung werden später benötigt, um unterbrechungsfrei im Sekundentakt zu zählen:

unsigned long timeStartMs;
unsigned long timeNowS;
unsigned long timeShowedS = 1000;

Im setup() wird das Display initialisiert und geprüft, ob es korrekt angeschlossen ist. Dann wird der Bildpuffer des Displays gelöscht. Wir werden an dieser Stelle darauf hingewiesen, dass es zwei Speicherbereiche gibt. Nach jedem Aufruf von SetFrameMemory() wird auf den jeweils anderen Speicherbereich umgeschaltet. Um also den Speicher wirklich zu löschen, muss die Funktion zweimal aufgerufen werden:

if (epd.init(lutFullUpdate) != 0) {
    Serial.print("e-Paper init failed");
    return;
}

epd.clearFrameMemory(0xFF);   // bit set = white, bit reset = black
epd.displayFrame();
epd.clearFrameMemory(0xFF);   // bit set = white, bit reset = black
epd.displayFrame();

Es folgt nun mit dem paint-Objekt das Zeichnen auf dem Display. Man kann sich das wie einen Overheadprojektor in der Schule vorstellen. Man nimmt transparente Folie und schneidet sie auf die gewünschte Größe. Darauf schreibt oder zeichnet man das gewünschte Motiv. Das macht man so oft, bis man mehrere kleine Teilfolien angefertigt hat. Diese fügt man dann zusammen und legt sie auf den Overheadprojektor.

Man schaltet am Ende den Projektor ein, das Licht geht an und das fertige Bild wird dann an der Leinwand angezeigt. Möchte man nun noch ein weiteres Teilmotiv hinzufügen, fertigt man es an und legt es zu den anderen Motiven auf den Projektor. Auf der Leinwand sieht es nun so aus, als wäre alles ein großes Motiv.

In der EPD-Bibliothek stehen mehrere Funktionen zur Verfügung, um Teilmotive zu erzeugen. Hier wird die Orientierung (Drehung) sowie die Größe des Teilmotivs festgelegt:

paint.setRotate(ROTATE_0);
paint.setWidth(200);
paint.setHeight(24);

Anschließend wird die Hintergrundfarbe Schwarz festgelegt. Danach wird der Text "Hello World!" an der Position x = 30 Pixel und y = 4 Pixel in der Schrift Font16 und Farbe Weiß geschrieben. Dem Quellcode der Bibliothek kann man entnehmen, dass die Schrift(größ)en Font8, Font12, Font16, Font20 und Font24 zur Verfügung stehen. Mit setFrameMemory() wird der Inhalt des Bildes, der im Arbeitsspeicher liegt, in den Bildpuffer im Display übertragen. Damit legen wir sinnbildlich das Teilmotiv auf den Overheadprojektor:

paint.clear(COLORED);
paint.drawStringAt(30, 4, "Hello world!", &Font16, UNCOLORED);
epd.setFrameMemory(paint.getImage(), 0, 10, paint.getWidth(), paint.getHeight());

Es folgen weitere Teilmotive wie Quadrate oder Linien. Die Zahlenwerte sind jeweils Startpunkte und Größen der Objekte als X- und Y-Koordinaten. Wurden alle Teilmotive auf den Projektor gelegt, wird das Licht eingeschaltet und das zusammengesetzte Bild erscheint auf der Leinwand:

epd.displayFrame();

Nach einer kurzen Pause wird dann das Bild geladen, dass in imagedata.cpp implementiert wurde:

epd.setFrameMemory(IMAGE_DATA);
epd.displayFrame();

IMAGE_DATA ist ein Array aus Zeichen, dass mit den Pixelwerten gefüllt ist, die letztendlich das Bild darstellen. Wie man eigene Bilder laden kann, erkläre ich im zweiten Teil.

Auf dem Display wird uns nun das zuvor gezeigte Bild angezeigt. Im Quellcode folgt als Nächstes nach dem setup() die Hauptschleife loop(). Dort wird die verstrichene Zeit gemessen. Nach jeder vollen Sekunde wird die Funktion updateTime() aufgerufen, der die aktuelle Sekunde übergeben wird. In dieser Funktion wird ein Array erstellt, in das der übergebene Wert geschrieben wird. Dabei wird für jede der vier Stellen die korrekte Darstellung berechnet. Das gesamte Array wird dann an das Display über- und ausgegeben. Ergebnis ist eine fortlaufende Zeit.

GxEPD2 Bibliothek

Nun wollen wir noch die GxEPD2-Bibliothek testen. Wir öffnen unter Beispiele->GxEPD2 das Projekt GxEPD2_Example. Mit Blick auf den Quellcode wird es jetzt etwas unübersichtlicher. Zuerst müssen wir die Zeile suchen, in der wir festlegen, welches Display wir an welchem Mikrocontroller verwenden. Ab Zeile 139 finden wir die Definitionen für das ESP32 Board. GxEPD2_154 steht hier wieder für 1,54 Zoll.

Es bleibt eine Auswahl von fünf Varianten. Jeweils am Ende der Zeilen steht in den Kommentaren der genaue Typ des Moduls und die Bildauflösung. Da ich kein Datenblatt von meinem Modul vorliegen habe (es gab über die Jahre mehrere Versionen des gleichen Typs und mein Display liegt hier schon etwas länger), habe ich es durch Ausprobieren herausgefunden.

Die Variante GDEP015OC1 funktioniert bei mir. Die Codezeile 141 wird folgendermaßen geändert:

GxEPD2_BW<GxEPD2_154, GxEPD2_154::HEIGHT> display(GxEPD2_154(/*CS=*/26, /*DC=*/ 25, /*RST=*/ 33, /*BUSY=*/ 27)); // GDEP015OC1 no longer available

Das Kompilieren dieser Demo nimmt (in meinem Fall unter Windows 7) relativ viel Zeit in Anspruch. Wurde das Programm auf den ESP32 geladen, werden abwechselnd mehrere Seiten angezeigt bestehend aus Texten und Bildern.

Ich möchte nun versuchen, mit dieser Bibliothek das gleiche Ergebnis zu erhalten, wie mit der EPD-Bibliothek. Es soll das Bild von Waveshare und die fortlaufende Zeit angezeigt werden. Dadurch kann ich dann einen besseren Vergleich durchführen und mich entscheiden, welche Bibliothek ich weiterhin verwenden werde.

Als Vorlage verwende ich das oben genannte Beispiel. Wir inkludieren die Bibliothek für schwarz/weiße Displays und die Schriftart für die Zeitanzeige:

#include <GxEPD2_BW.h>
#include <Fonts/FreeMonoBold18pt7b.h>

Anschließend erstellen wir ein Displayobjekt mit der Zeile, die wir für das Beispiel bereits gesucht hatten:

GxEPD2_BW<GxEPD2_154, GxEPD2_154::HEIGHT> display(GxEPD2_154(26, 25, 33, 27)); //CS, DC, RST, BUSY

Als Nächstes kopieren das Bildarray aus der imagedata.cpp und fügen es in unser Projekt als globale Variable ein (also außerhalb von Funktionen). Den Namen IMAGE_DATA behalten wir bei.

const unsigned char IMAGE_DATA[] PROGMEM = {
    /* 0X00,0X01,0XC8,0X00,0XC8,0X00, */
    0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X8F,0XFF,
    ...
}

Hinweis: Wichtig ist, dass die Bilddaten in den Flash- bzw. Programmspeicher, statt in den SRAM geschrieben werden. Das geschieht mit dem Variablenmodifikator PROGMEM. Weitere Infos dazu finden Sie hier.

Wir deklarieren uns die gleichen Variablen für die Zeitmessung, wie im EPD-Beispiel:

unsigned long timeStartMs;
unsigned long timeNowS;
unsigned long timeShowedS = 1000;

Es folgt der Inhalt der setup()-Funktion:

  display.init();
  display.setRotation(0);
  display.setFullWindow();
  display.fillScreen(GxEPD_BLACK);
  display.drawBitmap(0, 0, IMAGE_DATA, 200, 200, GxEPD_WHITE);
  while (display.nextPage());

  timeStartMs = millis();

Das Display wird initialisiert, dann genau wie im anderen Beispiel die Orientierung eingestellt. Danach wird das gesamte Display genutzt und dafür die Farbe auf Schwarz eingestellt. Anschließend zeichnen wir das Bild aus dem IMAGE_DATA-Array in der Farbe Weiß, bis der komplette Speicher übertragen wurde. Als letztes wird die Zeitmessung gestartet.

Der Inhalt der loop()-Funktion bleibt exakt der gleiche, wie im EPD-Beispiel:

  timeNowS = (millis() - timeStartMs) / 1000;
  if (timeNowS != timeShowedS) {
    timeShowedS = timeNowS;
    updateTime(timeShowedS);
  }
  delay(20);

Die Funktion updateTime müssen wir natürlich anpassen. Ich habe dafür Teile aus dem GxEPD2_Example übernommen:

char time_string[] = {'0', '0', ':', '0', '0', '\0'};
  int16_t tbx, tby;
  uint16_t tbw, tbh;
  //Fenster bestimmen, bevor die aktuelle Zeit eingetragen wird,
  //damit das Fenster auch immer gleich groß ist
  display.getTextBounds(time_string, 0, 0, &tbx, &tby, &tbw, &tbh);
  time_string[0] = seconds / 60 / 10 + '0';
  time_string[1] = seconds / 60 % 10 + '0';
  time_string[3] = seconds % 60 / 10 + '0';
  time_string[4] = seconds % 60 % 10 + '0';

Das Zeichenarray für die Zeitanzeige bleibt gleich. Die Variablen tbx, tby, tbw und tbh stehen für X- und Y-Koordinaten, sowie Breite und Höhe des anzuzeigenden Bildfensters. Mit getTextBounds() kann die Größe des angezeigten Textes auf dem Display abhängig vom Inhalt und der verwendeten Schrift ermittelt werden. Daraus resultiert später die Größe des Anzeigefensters.

Zu Beginn ist der Inhalt das Arrays 00:00. Wir ermitteln zu diesem Zeitpunkt daraus die Größe, damit das Fenster immer gleich groß bleibt. Das ist wichtig, da immer nur der Fensterbereich aktualisiert wird. Die Berechnung der korrekten Darstellung der einzelnen Ziffern ist wieder die gleiche, wie im anderen Beispiel.

Wir setzen nun die Orientierung, die Schriftart und die Schriftfarbe:

  display.setRotation(3);
  display.setFont(&FreeMonoBold18pt7b);
  display.setTextColor(GxEPD_BLACK);

FreeMonoBold18pt7b haben wir zu Beginn inkludiert. Für eine andere Schriftart oder -größe wird eine der anderen Headerdateien benötigt, die zur Adafruit_GFX-Bibliothek gehören. Eine Übersicht dafür findet man hier.

Die X- und Y-Koordinaten für die Positionierung der Zeitanzeige habe ich durch Probieren gefunden. Zuerst geschätzt und dann feinjustiert:

uint16_t x = 14;
  uint16_t y = 86 + tbh;
  uint16_t wx = x;
  uint16_t wy = 88;

Als letzter Schritt soll nun nicht das gesamte Display, sondern immer nur die Uhrzeit aktualisiert werden. Im GxEPD2_Example findet man Beispiele, wie man "partial refresh" benutzt. Hierfür brauchen wir das Fenster, das zuvor durch getTextBounds ermittelt wurde. Mit fillScreen() wird dann nur das Fenster gelöscht und anschließend der Text für die Zeitanzeige an die gleiche Stelle geschrieben:

 display.setPartialWindow(wx, wy, tbw + 4, tbh + 2);
  display.firstPage();
  do {
    display.fillScreen(GxEPD_WHITE);
    display.setCursor(x, y);
    display.print(time_string);
  } while (display.nextPage()); 


Hier finden Sie den gesamten Quellcode als Download:

Laden wir das Programm auf den ESP32, sehen wir die gleiche Demo wie vom EPD-Beispiel.

Um die Position des Textes innerhalb des Fensters besser bestimmen zu können, bietet es sich an, die Farben umzukehren, also das Fenster schwarz und den Text weiß anzuzeigen. Rutscht der Text aus dem Fenster, wird er abgeschnitten. Ich habe die Werte für die Box etwas erhöht, damit die Zeit ganz sicher innerhalb des Fensters angezeigt wird.

Eine detaillierte Beschreibung der Funktionen, die für die Anzeige von Inhalten benötigt werden, findet man in der Adafruit_GFX Reference.

Fazit

Es hat etwas gedauert, die Anwendung der Bibliotheken zu verstehen. Jedoch sollte man sie auch verwenden, da die Programmierung der EPDs nicht trivial ist. Das Kompilieren der GxEPD2-Bibliothek dauert wesentlich länger, als das der EPD-Bibliothek. Jedoch ist sie umfangreicher, da man auf die Adafruit_GFX-Bibliothek zurückgreifen kann. Es ist zwingend notwendig, genau zu wissen, welches Display man verwendet. Davon hängt ab, welcher Mikrocontroller oder eventuell weiteres Zubehör benötigt wird.

Ausblick

Im nächsten Teil möchte ich zeigen, wie man eigene Bilder auf dem Display anzeigt. Außerdem sollen Sensordaten angezeigt werden, statt einer fortlaufenden Zeit. Ich werde das EPD an den ESP8266 D1 Mini anschließen. Da die ESPs mit einem WLAN-Modul ausgestattet sind, möchte ich Netzwerkdaten anzeigen lassen.

Bis dahin

Andreas Wolter

für AZ-Delivery Blog

DisplaysEsp-32Projects for beginners

11 comments

samke

samke

@Andreas Wolter

Super, vielen Dank für den Denkanstoß, genau so hat es nun geklappt. Die ersten Zeichen werden nun richtig auf dem Display (2,9) angezeigt. Jetzt kann es weitergehen mit dem Ausprobieren :-)

Andreas Wolter

Andreas Wolter

@samke: in den Beispielsketches der GxEPD2-Bibliothek findet man die Initialisierungskommandos für die verschiedenen Displays. Dort muss man sich die passende Zeile raussuchen (abhängig vom Mikrocontroller und Display). Man muss entweder die richtige Zeile einkommentieren, oder die Zeile in seinen eigenen Sketch kopieren.
Hier im Beitrag ist es diese Zeile:
GxEPD2_BW<GxEPD2_154, GxEPD2_154::HEIGHT> display(GxEPD2_154(26, 25, 33, 27)); //CS, DC, RST, BUSY

an der 154 erkennt man, dass es sich um das 1,54" Display handelt. Für ein 2,9" Display muss man dann nach einer Zeile suchen, die 290 enthält. So wie diese:
//GxEPD2_BW<GxEPD2_290, GxEPD2_290::HEIGHT> display(GxEPD2_290(/CS=D8/ SS, /DC=D3/ 0, /RST=D4/ 2, /BUSY=D2/ 4));

für den passenden Mikrocontroller muss man dann auf diese Zeile achten:
#if defined (ESP8266)
der nachfolgende Codeblock ist dann für den ESP8266 gedacht. Für die Atmel Boards muss man nach dem Block mit der Definition für AVR suchen.

Ich hoffe, ich konnte helfen.

Grüße,
Andreas Wolter

samke

samke

Hi, ich hab das 2,9 inch ePaper – mit dem Beispiel hier bekomme ich zwar was angezeigt, aber natürlich in der falschen größe/Format. Was muss ich tun, damit das 2,9er Format zugrundegelegt wird? Danke schon mal für Tipps!

csierra67

csierra67

Vielen Dank Walther.. I have not paid attention to the existence of a version 2 display. Fortunately, Andreas has published a Teil 2 on this topic as of today and I am hopinf that it will fix my problems.

Csierra67

Walther Plath

Walther Plath

Mit 1.54inch e-paper v2 und NodeMCU ESP32 funktioniert es mit der GxEPD2.
Die ältere Version soll laut Waveshare einen anderen Controller haben, siehe: https://www.waveshare.com/wiki/1.54inch_e-Paper_Module
Angeschlossen habe ich entsprechend der Empfehlung von JM Zingg ( siehe https://github.com/ZinggJM/GxEPD2/blob/master/ConnectingHardware.md) wie folgt:
BUSY → 4, RST → 16, DC → 17, CS → SS, CLK → SCK, DIN → MOSI, GND → GND, 3.3V → 3.3V
und in Zeile 159 diese Version gewählt. Sucht nach
#if defined(ESP32)
// select one and adapt to your mapping, can use full buffer size (full HEIGHT)
danach die zweite unkommentieren:
GxEPD2_BW<GxEPD2_154_D67, GxEPD2_154_D67::HEIGHT> display(GxEPD2_154_D67(/CS=5/ SS, /DC=/ 17, /RST=/ 16, /BUSY=/ 4)); // GDEH0154D67
Bei mir wird ein Demo von GoodDisplay gezeigt.

csierra67

csierra67

@Andreas Wolter
Despite mein German is good enough to read you, I prefer to post in English, actually I am a Frenchman.
Congrats for your paper, it is clear and well documented. Unfortunately I was not able to have my b/w/r 1.54 inch display working with ESP32 dev VC4
Up to now I only was able to upload the waveshare exemple with an Arduino Uno.. at least I know that my display is working.. However all the other examples found on Internet or the examples with the EPD library and/or EPD_GFX or EPD_GFX2 library compile, can be upmloaded to the board but the display does not respond. I think it has to do with the choice of the library, change of the pin assignemnt..
As of now, e paper display appears to me to a non user friendly device as opposed to OLED and I guess I will stay away until a stabilization ouccurs with libraries, pin assignment, boards..
And I won’t buy bigger boards until this has not happened.
Tchuss
Csierra67
d

posti

posti

@Markus Walsleben

Wenn für den Puffer nicht genügend Platz vorhanden ist, muß der Inhalt in mehreren Anläufen zum Display geschickt werden.
Ob Das hier nötig ist oder gebraucht wird, habe ich aber nicht untersucht – beim Arduino ist Das aber auf jeden Fall so, daß einfach nicht genug Platz für ‘das ganze Bild im Speicher’ ist.
Für jeden Aufruf wird das ganze Bild ‘gemalt’.
Allerdings werden nur die Bereiche im Speicher aufgenommen, Die als Nächstes auch zum Display gesendet werden sollen – der Rest wird schlicht ignoriert.
Nun schickst Du das Bild mit first/nextpage ans Display.
Bei firstpage wird ‘nur’ der aktuelle Bereich auf ‘das obere Stück’ gesetzt, dann gezeichnet, gesendet und der Bereich um Eins erhöht.
Wenn bereits das ganze Display beschrieben wurde, bricht die while-Schleife ab (wenn z.B. der Puffer groß genug ist).
Sonst erst, wenn der letzte Bereich beschrieben wurde – bei den nextpage Aufrufen.

Man erkauft Sich die Nutzung bei wenig verfügbarem Speicher damit, daß man das komplette Bild mehrfach aufbaut und eben immer nur Stücke darauf zum Display schickt (da auch nur Stücke von der ganzen Zeichnung im Speicher landen).

Hoffe, ich konnte etwas Klarheit in die Sache bringen – ähnlich ist’s auch bei OLED.

Markus Walsleben

Markus Walsleben

Mir ist bei diesem Quelltext und auch bei diversen anderen Beispielen im Netz eine verwendete Funktion unklar. Auch auf der Seite der GxEPD-Library habe ich dazu nichts konkretes gefunden.
Was bewirken die Funktionen display.nextPage() und display.firstPage() ? Wo liegt die sinnvolle Verwendung?

Andreas Wolter

Andreas Wolter

Hallo liebe User,

ich möchte an dieser Stelle kurz auf Ihre Kommentare eingehen. Sie haben natürlich recht. Es handelt sich hier um das schwarz/weiß-Display. Im Kapitel Vorbereitung wurde das kurz erwähnt. Dort finden Sie auch den Hinweis, dass auf den Fotos ein anderes Dev Kit Board zu sehen ist. Dabei ging es hauptsächlich darum zu zeigen, welche Pinnummern verwendet wurden. Das Bild mit den Pinouts dagegen ist aus dem Datenblatt des Moduls, dass oben verlinkt wurde. Wenn Sie sich danach richten, sollte alles funktionieren. Es tut uns leid, dass das zu Verwirrungen führt. Es gibt mehrere ESP32 Boards, deren Pinnummern jedoch gleich sein sollten.

Was die Versionen 1 und 2 des Displays angeht, habe ich beim Hersteller nur die Informationen gefunden, dass Version 1 nur mit 3,3V Arbeitet. Version 2 hingegen hat einen eigenen Spannungsregler onboard, so dass auch 5V verwendet werden können. Die Bibliotheken sollten mit der Version 2 funktionieren. Die EPD-Bibliothek nutzt als Core den Code von Waveshare von 2017. Waveshare hat darauf hingewiesen, den Core zu aktualisieren. Das wurde auch getan. Das sollte also nicht die Fehlerursache sein.

Für die Varianten B (schwarz/weiß/rot) und C (schwarz/weiß/gelb) müssen Sie die Bibliotheken EPD1in54B.h bzw. EPD1in54C.h einbinden. Es werden dafür die Beispielprogramme EPD1in54BShowImage bzw. EPD1in54CShowImage mit der Bibliothek EPD mitgeliefert. Zu finden unter dem gleichnamigen Ordner in den Beispielen.

Vielen Dank für Ihre Hinweise!

Andreas Wolter

p.s.: die Inbetriebnahme des Displays hat auch mich einige Zeit gekostet, denn es wollte zu Beginn einfach nicht funktionieren.

Thomas Uhl

Thomas Uhl

Ähnliches Problem hier. Bei mir lag’s daran, dass ich ein dreifarbiges Waveshare-Display habe, die Beispiele im Artikel aber offenbar für die B/W-Variante ausgewählt sind.
Probier es mal mit dem der GFXEPD2-Bibliothek und dem Beispiel GFXEPD2_Example mit folgender Konfiguration:
GxEPD2_3C<GxEPD2_154c, GxEPD2_154c::HEIGHT> display(GxEPD2_154c(26, 25, 33, 27));
Wenn das funktioniert, dann brauchst du bei der EPD-Bibliothek auch die Farbvariante:
#include
Dafür muss dann aber der Code komplett umgeschrieben werden, weil das Modul dann zwei Framebuffer benötigt (den einen für Schwarz und den anderen für die dritte Farbe) und daher die Schnittstelle auch ganz anders definiert ist. Ein passendes Beispiel findest du aber in EPD1in54CShowImage.

Eberhard Werminghoff

Eberhard Werminghoff

Ich versuche seit geraumer Zeit das hier vorliegende Beispiel nachzubauen. Also habe ich den Bestelllink oben auf der Seite benutzt. Abgebildet ist ein 30-poliges Modul, geliefert wird ein 38-pol. Modul. Dass sollte nicht das Problem sein, kann aber bei Anfängern wegen der Bilder Irritationen hervorrufen. Da muss mindesten ein Hinweis sein.
Bestellt habe ich bei Waveshare das Display und bekam eine Version 2 geliefert. Offensichtlich ist die Anleitung für V1.x gedacht. Waveshare schreibt, dass die SW für die beiden Versionen unterschiedlich sein soll. Ist das richtig und das evtl. der Grund meines Scheiterns?
Gruß Eberhard

Leave a comment

All comments are moderated before being published

Recommended blog posts

  1. Install ESP32 now from the board manager
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. OTA - Over the Air - ESP programming via WLAN