Skip to Content

CrowPanel 4.2-Zoll E-Paper mit GxEPD2

CrowPanel 4.2-Zoll E-Paper mit GxEPD2

In diesem Blog zeige ich dir, wie du die GxEPD2-Bibliothek verwenden kannst, um auf einem CrowPanel 4,2-Zoll E-Paper zu zeichnen.

Die CrowPanel E-Paper von Elecrow werden mit Beispielcode geliefert, der zeigt, wie man auf dem Display zeichnet. Die Funktionalität dieses Codes ist jedoch recht eingeschränkt. Es wäre viel besser, wenn wir die leistungsfähigere GxEPD2 Libary. Leider gibt es Stand Dezember 2024 keine direkte Unterstützung für eines der CrowPanel E-Paper Displays in der GxEPD2-Bibliothek (siehe GxEPD2_display_selection_new_style.h).

Mit einer kleinen Anpassung können wir die GxEPD2-Bibliothek jedoch auf dem CrowPanel 4,2-Zoll E-Paper zum Laufen bringen, und in den folgenden Abschnitten zeige ich dir, wie das geht.

Benötigte Teile

Du benötigst ein CrowPanel E-Paper Display. In diesem Tutorial konzentriere ich mich auf die 4,2-Zoll-Version, die du dir auch besorgen solltest. Es gibt weitere Displaygrößen, und die Codebeispiele sollten größtenteils funktionieren, aber du musst wegen der unterschiedlichen Auflösung und des Display-Treibers Anpassungen vornehmen.

CrowPanel 4,2-Zoll E-Paper

Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.

CrowPanel 4,2-Zoll E-Paper Display

Das 4,2-Zoll E-Paper Display von CrowPanel ist ein Schwarz-Weiß-Display mit einer Auflösung von 400×300 Pixeln. Es kommt als integriertes Modul, das einen ESP32-S3-Chip, mehrere Tasten zur Steuerung des Displays und mehr enthält. Das folgende Bild zeigt die Vorderseite des Displays mit drei Steuerungstasten an der Seite:

Front of CrowPanel 4.2-inch E-Paper Display
Vorderseite des CrowPanel 4,2-Zoll E-Paper Displays (source)

Tasten

Die Tasten MENU und EXIT sind einfache Drucktasten, während der Drehschalter eine Hoch-, Runter- und Bestätigen/OK-Funktion unterstützt. Die Tasten sind vollständig programmierbar. Die folgende Tabelle zeigt, welche GPIO-Pins welchen Tasten zugeordnet sind:

TasteGPIO
MENUIO2
Drehschalter RunterIO4
Drehschalter HochIO6
Drehschalter Bestätigen (CONF)IO5
EXITIO1

Funktionen

Das Displaymodul enthält außerdem einen TF-Karten-Slot, eine LiPo-Batterie-Schnittstelle (SH1.0-2Pin) mit Ladefunktion und eine GPIO-Schnittstelle. Programmierung (und Stromversorgung) erfolgt über einen USB-C-Anschluss.

Interna of CrowPanel 4.2-inch E-Paper Display
Innere des CrowPanel 4,2-Zoll E-Paper Displays (source)

GPIO

Für GPIO stehen folgende Pins zur Verfügung: IO3; IO9; IO15; IO17; IO19; IO21; IO8; IO14; IO16; IO18; IO20; IO38. Das Pinout für den GPIO-Port ist auf dem Siebdruck, aber auch auf der Rückseite des Moduls zu finden:

Pinout of GPIO port
Pinout des GPIO-Ports (source)

Reset und Boot

Auf der Rückseite des Moduls befinden sich die Boot- und Reset-Tasten. Leider ragen diese über das Gehäuse hinaus und werden leicht versehentlich gedrückt, wenn man das Modul auf einen Tisch legt. Ich empfehle, sie mit einer Zange etwas zu kürzen, um das zu vermeiden.

Back of CrowPanel 4.2-inch E-Paper Display
Rückseite des CrowPanel 4,2-Zoll E-Paper Displays (source)

Andere CrowPanel E-Paper Displays

Das 4,2-Zoll Display ist Teil einer ganzen Serie ähnlicher E-Paper Displays mit unterschiedlichen Auflösungen, ESP32- und Treiberchips. Siehe die folgende Tabelle für eine Übersicht:

CrowPanel E-Paper Displays
CrowPanel E-Paper Displays (source)

Für dieses Tutorial habe ich das 4,2-Zoll Display verwendet, aber der Großteil des Codes funktioniert wahrscheinlich auch für die anderen Displaygrößen. Du musst jedoch einen passenden Treiber in der GxEPD2-Bibliothek finden. Mehr dazu im nächsten Abschnitt.

GxEPD2 Bibliothek

Die GxEPD2 Libary ist eine Arduino/ESP32 Display-Bibliothek für SPI E-Paper Displays. Wie bereits erwähnt, unterstützt sie viele verschiedene E-Paper Displays, aber bisher nicht direkt die CrowPanel E-Paper Displays.

Im Vergleich zum Demo-Code, der mit den CrowPanel Displays geliefert wird, ist die GxEPD2 Libary vorzuziehen. Sie bietet mehr functions und eine bessere Dokumentation, da sie vom Adafruit-GFX-Library abgeleitet ist, und lässt sich einfach installieren und verwenden.

Am wichtigsten ist, dass du Code, der mit der GxEPD2 Libary geschrieben wurde, über eine breite Palette verschiedener E-Paper Displays (wieder-)verwenden kannst, ohne ihn für spezifische Displays neu schreiben zu müssen.

Code auf CrowPanel E-Paper Display hochladen

Das Hochladen von Code auf das E-Paper Modul über die Arduino IDE ist einfach. Verbinde einfach das USB-Kabel und wähle als Board „ESP32S3 Dev Module“:

Selecting ESP32S3 Dev Module
Auswahl ESP32S3 Dev Module

Unter „Tools“ wähle idealerweise „Huge App“ für das Partition Scheme und „OPI PSRAM“ für die PSRAM-Einstellungen. Das ist zwar nicht zwingend für den Code in diesem Tutorial, aber es scheinen die empfohlenen Einstellungen zu sein.

Board settings for CrowPanel E-Paper display
Board-Einstellungen für CrowPanel E-Paper Display

Code zur Verwendung der GxEPD2 Bibliothek mit CrowPanel E-Paper Display

In diesem Abschnitt zeige ich dir, wie du die GxEPD2-Bibliothek mit dem CrowPanel E-Paper Display zum Laufen bringst. Es gibt zwei wichtige Schritte. Zuerst müssen wir einen GxEPD2-Treiber finden, der dieselbe Auflösung hat und denselben Treiberchip wie das CrowPanel Display unterstützt.

Das 4,2-Zoll Display verwendet den SSD1683 Treiberchip und hat eine Auflösung von 400×300 Pixeln. Wenn du in der Liste der unterstützten Treiber in GxEPD2_display_selection_new_style.h suchst, findest du zwei passende Einträge:

//#define GxEPD2_DRIVER_CLASS GxEPD2_420_GDEY042T81 // GDEY042T81 400x300, SSD1683 (no inking)
//#define GxEPD2_DRIVER_CLASS GxEPD2_420_GYE042A87  // GYE042A87, 400x300, SSD1683 (HINK-E042-A07-FPC-A1)  

Wenn du diese Treiber ausprobierst, erscheint jedoch nur ein sehr schwaches Bild von dem, was du zeichnest. Ich habe mir den demo code genauer angesehen und festgestellt, dass du auch die Stromversorgung für das Display einschalten musst. Das erreichst du, indem du den Ausgang an GPIO7 auf HIGH setzt.

Das folgende Beispiel zeigt den Text „Makerguides“ in der Mitte des 4,2-Zoll E-Paper Displays. Schau es dir zuerst kurz an, dann besprechen wir die Details:

#include "GxEPD2_BW.h"

#define PWR 7
#define BUSY 48
#define RES 47
#define DC 46
#define CS 45

GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> epd(GxEPD2_420_GYE042A87(CS, DC, RES, BUSY));

void epdPower(int state) { 
  pinMode(PWR, OUTPUT);  
  digitalWrite(PWR, state);  
}

void epdInit() {  
  epd.init(115200, true, 50, false);
  epd.setRotation(0);
  epd.setTextColor(GxEPD_BLACK);
  epd.setTextSize(4);
  epd.setFullWindow();
}

void setup() {
  epdPower(HIGH);
  epdInit();
  epd.fillScreen(GxEPD_WHITE);
  epd.drawRect(0, 0, 400, 300, GxEPD_BLACK);
  epd.setCursor(70, 130);
  epd.print("Makerguides");
  epd.display();
  epd.hibernate(); 
  epdPower(LOW);
}

void loop() {}

Include

Zuerst binden wir die GxEPD2 Libary ein, und da wir ein Schwarz-Weiß E-Paper verwenden, binden wir „GxEPD2_BW.h“ ein:

#include "GxEPD2_BW.h"

Falls du die GxEPD2 Libary noch nicht installiert hast, musst du das tun, damit dieser Code funktioniert. Du benötigst auch die Adafruit_GFX Bibliothek. Einfach install the libraries auf die übliche Weise installieren. Nach der Installation sollten sie im Library Manager wie folgt erscheinen.

Adafruit_GFX and GxEPD2 libraries in Library Manager
Adafruit_GFX und GxEPD2 Bibliotheken im Library Manager

Du brauchst keine der demo code, die mit den CrowPanel Displays geliefert werden.

Pin-Definitionen

Als nächstes definieren wir die SPI-Pins, die das Display zur Kommunikation mit dem ESP32 verwendet.

#define PWR 7
#define BUSY 48
#define RES 47
#define DC 46
#define CS 45

Ich habe diese Pins durch einen Blick in die Schematics of the CrowPanel 4.2-inch E-Paper display gefunden. Hier ist der relevante Ausschnitt aus dem Schaltplan, der die Verbindung zum E-Paper beschreibt:

Schematics of the CrowPanel 4.2-inch E-Paper display
Schaltplan des CrowPanel 4,2-Zoll E-Paper Displays (source)

Display-Objekt

Wie bereits erwähnt, gibt es keine direkte Unterstützung für das CrowPanel 4,2-Zoll E-Paper in der GxEPD2 Libary. Wir verwenden daher einen nahen Verwandten, um das epd Objekt zu erstellen, das unser E-Paper Display repräsentiert:

GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> epd(GxEPD2_420_GYE042A87(CS, DC, RES, BUSY));

Alternativ kannst du auch die GxEPD2_420_GDEY042T81 Klasse verwenden. Beide scheinen zu funktionieren, aber im folgenden Code habe ich die GxEPD2_420_GYE042A87 Klasse verwendet.

epdPower Funktion

Die epdPower() Funktion ist kritisch und speziell. Für andere E-Paper Displays brauchst du sie nicht, aber für das CrowPanel E-Paper schon. Sie setzt GPIO7 auf HIGH oder LOW und schaltet damit das E-Paper Display ein oder aus.

void epdPower(int state) { 
  pinMode(PWR, OUTPUT);  
  digitalWrite(PWR, state);  
}

Beachte, dass du das E-Paper (epdPower(LOW)) nach dem Zeichnen ausschalten kannst. Es zeigt das Bild weiterhin an, auch ohne Stromversorgung.

epdInit Funktion

Die epdInit() Funktion führt die übliche Initialisierung für die Grafik durch, wie Bildschirmrotation, Textfarbe, Textgröße und Aktualisierungsmodus.

void epdInit() {  
  epd.init(115200, true, 50, false);
  epd.setRotation(0);
  epd.setTextColor(GxEPD_BLACK);
  epd.setTextSize(4);
  epd.setFullWindow();
}

setup Funktion

In der setup() Funktion schalten wir das Display ein, füllen den Bildschirm mit Weiß, zeichnen einen Rahmen, geben den Text „Makerguides“ aus, zeigen das Bild an und schalten das Display dann wieder aus.

void setup() {
  epdPower(HIGH);
  epdInit();
  epd.fillScreen(GxEPD_WHITE);
  epd.drawRect(0, 0, 400, 300, GxEPD_BLACK);
  epd.setCursor(70, 130);
  epd.print("Makerguides");
  epd.display();
  epd.hibernate(); 
  epdPower(LOW);
}

Wenn du diesen Code hochlädst und ausführst, solltest du die folgende Ausgabe auf dem E-Paper Display sehen:

Testausgabe auf CrowPanel 4,2-Zoll E-Paper

Mit der Ergänzung der epdPower() Funktion kannst du die GxEPD2 Libary wie gewohnt verwenden, um auf dem CrowPanel 4,2-Zoll E-Paper Display zu zeichnen und zu schreiben. Im nächsten Abschnitt testen wir die partielle Aktualisierung.

Partielle Aktualisierung des CrowPanel E-Paper Displays

Im obigen Code haben wir eine vollständige Aktualisierung des E-Paper Inhalts durchgeführt. Diese Vollaktualisierung ist gelegentlich notwendig, um Nachbilder zu entfernen, ist aber langsam (mehrere Sekunden) und verursacht starkes Flackern des E-Papers.

Für die meisten Anwendungen möchtest du nur einen Teil des Displays aktualisieren, ohne Flackern und viel schneller. Zum Beispiel, um die Ziffern einer laufenden Uhr anzuzeigen. Eine partielle Aktualisierung ermöglicht das. Für mehr Details siehe das Partial Refresh of e-Paper Display Tutorial.

Der folgende Code ist im Wesentlichen derselbe wie in diesem Tutorial. Er führt zuerst eine Vollaktualisierung durch, um das Display zu löschen, und gibt den Text „msec:“ aus. Danach führt er kontinuierlich partielle Aktualisierungen durch und aktualisiert die laufenden Millisekunden. Unten ist ein Screenshot der Display-Ausgabe:

Display output for full- and partial refresh
Anzeigeausgabe für Voll- und Teilaktualisierung

Hier ist der vollständige Code für diesen Test. Der einzige Unterschied zum Code im Partial Refresh of e-Paper Display ist, dass wir die epdPower() Funktion erneut verwenden müssen, um das Display einzuschalten. Und natürlich ist der Display-Treiber anders.

#include "GxEPD2_BW.h"

#define PWR 7
#define BUSY 48
#define RES 47
#define DC 46
#define CS 45

GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> epd(GxEPD2_420_GYE042A87(CS, DC, RES, BUSY));

void epdPower(int state) { 
  pinMode(PWR, OUTPUT);  
  digitalWrite(PWR, state);  
}

void drawFull(const void* pv) {
  epd.setFullWindow();
  epd.setCursor(40, 60);
  epd.print("msec: ");
}

void drawPartial(const void* pv) {
  uint16_t x = 120, y = 50, w = 130, h = 34;
  epd.setPartialWindow(x, y, w, h);
  epd.setCursor(x + 30, y + 10);
  epd.print(millis());
  epd.drawRect(x, y, w, h, GxEPD_BLACK);
}

void setup() {
  epdPower(HIGH);
  epd.init(115200, true, 50, false);
  epd.setRotation(0);
  epd.setTextSize(2);
  epd.setTextColor(GxEPD_BLACK);
  epd.drawPaged(drawFull, 0);  
}

void loop() {
  epd.drawPaged(drawPartial, 0);
  epd.hibernate();
}

Wenn du diesen Code hochlädst und ausführst, solltest du die folgende Ausgabe sehen. Beachte, dass die Millisekunden in unter 0,5 Sekunden aktualisiert werden und dass es fast kein Flackern gibt (nur ein wenig um den Rahmen):

Partial refresh on CrowPanel 4.2-inch E-Paper
Partielle Aktualisierung auf CrowPanel 4,2-Zoll E-Paper

Voll- und Teilaktualisierung funktionieren also gut auf dem CrowPanel 4,2-Zoll E-Paper Display mit dem gewählten GxEPD2-Treiber GxEPD2_420_GYE042A87.

Im nächsten und letzten Abschnitt zeige ich dir, wie du die partielle Aktualisierung und die Tasten des CrowPanel Displays nutzt, um ein einfaches Menü zu implementieren, das drei LEDs steuert.

GPIO-Steuerung über Menü auf CrowPanel E-Paper Display

Eine der Demos für das CrowPanel Display zeigt ein einfaches Menü mit Einträgen, die per Tastendruck aktiviert oder deaktiviert werden können.

Hier bauen wir etwas Ähnliches, verwenden aber die GxEPD2-Bibliothek, und unsere Tasten steuern drei LEDs. Der folgende Screenshot zeigt, wie das Menü aussehen wird:

LED-Auswahlmenü auf CrowPanel Display

Wir können im Menü mit den Hoch- und Runter-Tasten des Drehschalters navigieren und mit der Bestätigungstaste einen Menüpunkt auswählen. Wenn ein Eintrag ausgewählt ist, wird eine LED der entsprechenden Farbe, die an GPIO angeschlossen ist, eingeschaltet, z.B. schaltet die Auswahl „Rot“ eine rote LED ein:

Red LED selected in Menu
Rote LED im Menü ausgewählt

Schaltplan

Der folgende Schaltplan zeigt, wie du die drei LEDs an den GPIO-Port des CrowPanel Displays anschließt. Die Kathode jeder LED ist mit Masse (GND) verbunden. Die Anode der roten LED ist an GPIO3 angeschlossen, die grüne LED an GPIO9 und die blaue an GPIO15. Ich habe für jede LED einen Vorwiderstand von 220Ω verwendet:

Connecting three LEDs to CrowPanel Display
Anschluss von drei LEDs an CrowPanel Display

Code zur Navigation im Menü und Steuerung der LEDs

Unten findest du den Code, um das Menü zu navigieren, Einträge auszuwählen und abzuwählen und entsprechend die LEDs zu steuern:

#include "GxEPD2_BW.h"
#include <Fonts/FreeMonoBold24pt7b.h>

#define PWR 7
#define BUSY 48
#define RES 47
#define DC 46
#define CS 45
#define W 400
#define H 300

#define HOME_KEY 2
#define EXIT_KEY 1
#define PREV_KEY 6
#define NEXT_KEY 4
#define OK_KEY 5

int cursor = 0;
const int xoff = 70;
const int n_items = 3;
const char* items[] = { "Red", "Green", "Blue" };
const int pins[] = { 3, 9, 15 };
bool states[] = { false, false, false };
const int ypos[] = { 100, 100 + 60, 100 + 2 * 60 };

GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> epd(GxEPD2_420_GYE042A87(CS, DC, RES, BUSY));


void epdPower(int state) { 
  pinMode(PWR, OUTPUT);  
  digitalWrite(PWR, state);  
}

void drawCursor() {
  int16_t s = 12;
  int16_t x0 = xoff - s;
  int16_t y0 = ypos[cursor] - 12;
  int16_t x1 = x0 - s;
  int16_t y1 = y0 - s;
  int16_t x2 = x0 - s;
  int16_t y2 = y0 + s;
  epd.fillTriangle(x0, y0, x1, y1, x2, y2, GxEPD_BLACK);
}

void updateCursor(const void* pv) {
  epd.setPartialWindow(0, 0, xoff, 300);
  drawCursor();
}

void drawItem(int index) {
  int16_t xb, yb;
  uint16_t wb, hb;
  epd.setCursor(xoff + 5, ypos[index]);
  epd.getTextBounds(items[index], xoff + 5, ypos[index], &xb, &yb, &wb, &hb);
  if (states[index]) {
    epd.setTextColor(GxEPD_WHITE);
    epd.fillRect(xb - 5, yb - 3, W - 2 * xoff, hb + 6, GxEPD_BLACK);
  } else {
    epd.setTextColor(GxEPD_BLACK);
    epd.fillRect(xb - 5, yb - 3, W - 2 * xoff, hb + 6, GxEPD_WHITE);
  }
  epd.print(items[index]);
}

void updateItems(const void* pv) {
  epd.setPartialWindow(xoff, 0, W - xoff, 300);
  drawItems();
}

void drawItems() {
  for (int i = 0; i < n_items; i++) {
    drawItem(i);
  }
}

void initEPD() {
  epdPower(HIGH);
  epd.init(115200, true, 50, false);
  epd.setRotation(0);
  epd.setTextColor(GxEPD_BLACK);
  epd.setFont(&FreeMonoBold24pt7b);
  epd.setFullWindow();
  epd.fillScreen(GxEPD_WHITE);
}

void initButtons() {
  pinMode(HOME_KEY, INPUT);
  pinMode(EXIT_KEY, INPUT);
  pinMode(PREV_KEY, INPUT);
  pinMode(NEXT_KEY, INPUT);
  pinMode(OK_KEY, INPUT);
}

void initPins() {
  for (int i = 0; i < n_items; i++) {
      pinMode(pins[i], OUTPUT);
  }    
}

void setup() {
  initEPD();
  initButtons();
  initPins();
  drawItems();
  drawCursor();
  epd.display();
}

void loop() {
  if (!digitalRead(PREV_KEY)) {
    cursor = --cursor < 0 ? n_items - 1 : cursor;
    epd.drawPaged(updateCursor, 0);
  }
  if (!digitalRead(NEXT_KEY)) {
    cursor = ++cursor >= n_items ? 0 : cursor;
    epd.drawPaged(updateCursor, 0);
  }
  if (!digitalRead(OK_KEY)) {
    states[cursor] = !states[cursor];
    epd.drawPaged(updateItems, 0);
    digitalWrite(pins[cursor], states[cursor] ? HIGH : LOW);
  }
  if (!digitalRead(HOME_KEY)) {
    cursor = 0;
    epd.drawPaged(updateCursor, 0);
  }  
  if (!digitalRead(EXIT_KEY)) {
    for (int i = 0; i < n_items; i++) {
      states[i] = false;
      digitalWrite(pins[i], LOW);  
    }      
    epd.drawPaged(updateItems, 0);
  }
  delay(100);
}

Lass uns den Code in seine Komponenten aufteilen, um ihn besser zu verstehen.

Bibliotheken und Konstanten

Wir beginnen mit dem Einbinden der notwendigen Bibliotheken für das E-Paper Display und fonts. Die Konstanten definieren die Pins für Display und Tasten sowie die Abmessungen des Displays.

#include "GxEPD2_BW.h"
#include <Fonts/FreeMonoBold24pt7b.h>

#define PWR 7
#define BUSY 48
#define RES 47
#define DC 46
#define CS 45
#define W 400
#define H 300

Tastendefinitionen

Wir definieren die Pins für die Tasten, die zur Navigation im Menü verwendet werden. Jede Taste hat eine bestimmte Funktion: HOME, EXIT, PREV, NEXT und OK.

#define HOME_KEY 2
#define EXIT_KEY 1
#define PREV_KEY 6
#define NEXT_KEY 4
#define OK_KEY 5

Variablen

Mehrere Variablen werden deklariert, um den Menüstatus zu verwalten. cursor verfolgt die aktuelle Auswahl, items enthält die Namen der LEDs, und states speichert, ob jede LED an- oder ausgeschaltet ist. ypos gibt an, wo die Menüpunkte auf dem Display angezeigt werden.

int cursor = 0;
const char* items[] = { "Red", "Green", "Blue" };
const int pins[] = { 3, 9, 15 };
bool states[] = { false, false, false };
const int ypos[] = { 100, 160, 220 };

E-Paper Display Objekt

Wie zuvor wird das E-Paper Display Objekt mit der GxEPD2_BW Klasse erstellt. Damit wird das Display mit den angegebenen Pins eingerichtet. Wenn du ein anderes CrowPanel E-Paper Display hast, musst du diese Zeile anpassen.

GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> epd(GxEPD2_420_GYE042A87(CS, DC, RES, BUSY));

Stromversorgungs-Funktion

Die epdPower() Funktion steuert die Stromversorgung des E-Paper Displays. Sie setzt den Power-Pin als Ausgang und schreibt den angegebenen Zustand (HIGH oder LOW).

void epdPower(int state) { 
  pinMode(PWR, OUTPUT);  
  digitalWrite(PWR, state);  
}

Cursor-Zeichen-Funktion

Die drawCursor() Funktion stellt die aktuelle Auswahl im Menü visuell dar, indem sie ein Dreieck an der entsprechenden Position zeichnet.

void drawCursor() {
  int16_t s = 12;
  int16_t x0 = xoff - s;
  int16_t y0 = ypos[cursor] - 12;
  epd.fillTriangle(x0, y0, x1, y1, x2, y2, GxEPD_BLACK);
}

Beachte, dass die zugehörige updateCursor() Funktion eine partielle Aktualisierung durchführt und nur den Bereich des Bildschirms aktualisiert, in dem der Cursor angezeigt wird. Sie wird z.B. aufgerufen, wenn die Hoch- oder Runter-Tasten gedrückt werden.

void updateCursor(const void* pv) {
  epd.setPartialWindow(0, 0, xoff, 300);
  drawCursor();
}

Eintrag-Zeichen-Funktion

Die drawItem() Funktion zeigt einen Eintrag im Menü an. Sie prüft den Zustand der LED und ändert den Hintergrund auf Schwarz, wenn ein Eintrag ausgewählt ist.

void drawItem(int index) {
  epd.setCursor(xoff + 5, ypos[index]);
  if (states[index]) {
    epd.setTextColor(GxEPD_WHITE);
    epd.fillRect(...);
  } else {
    epd.setTextColor(GxEPD_BLACK);
    epd.fillRect(...);
  }
  epd.print(items[index]);
}

Um alle Menüpunkte zu zeichnen, wird die drawItems() Funktion verwendet:

void drawItems() {
  for (int i = 0; i < n_items; i++) {
    drawItem(i);
  }
}

Und der Zustand aller Einträge wird durch eine partielle Aktualisierung des Bildschirmbereichs, in dem die Menüpunkte sind, aktualisiert:

void updateItems(const void* pv) {
  epd.setPartialWindow(xoff, 0, W - xoff, 300);
  drawItems();
}

Initialisierungs-Funktionen

Mehrere Initialisierungsfunktionen sind definiert: initEPD() initialisiert das E-Paper Display, initButtons() setzt die Tasten-Pins als Eingänge, und initPins() setzt die LED-Pins als Ausgänge.

void initEPD() {
  epdPower(HIGH);
  ...
}

void initButtons() {
  pinMode(HOME_KEY, INPUT);
  ...
}

void initPins() {
  for (int i = 0; i < n_items; i++) {
      pinMode(pins[i], OUTPUT);
  }    
}

Setup-Funktion

Die setup() Funktion wird einmal beim Programmstart aufgerufen. Sie initialisiert das E-Paper Display, die Tasten und LED-Pins und zeichnet die Anfangseinträge und den Cursor auf das Display.

void setup() {
  initEPD();
  initButtons();
  initPins();
  drawItems();
  drawCursor();
  epd.display();
}

Loop-Funktion

Die loop() Funktion läuft kontinuierlich. Sie prüft den Zustand der Tasten und aktualisiert die Cursor-Position oder schaltet die LEDs basierend auf Benutzereingaben um. Das Display wird entsprechend mit einem paginierten Neuzeichnen und partieller Aktualisierung aktualisiert.

void loop() {
  if (!digitalRead(PREV_KEY)) {
    ...
  }
  if (!digitalRead(NEXT_KEY)) {
    ...
  }
  if (!digitalRead(OK_KEY)) {
    ...
  }
  if (!digitalRead(HOME_KEY)) {
    ...
  }  
  if (!digitalRead(EXIT_KEY)) {
    ...
  }
  delay(100);
}

Die PREV_KEY bewegt den Cursor einen Menüpunkt nach oben und die NEXT_KEY einen Menüpunkt nach unten. Wenn das Ende oder der Anfang des Menüs erreicht ist, springt der Cursor zum anderen Ende.

Mit der OK_KEY kannst du den Zustand eines Eintrags umschalten. Die HOME_KEY setzt den Cursor auf den ersten Menüpunkt und die EXIT_KEY hebt alle Auswahlen auf.

Demo des Codes

Zusammenfassend bietet dieser Code eine Benutzeroberfläche auf einem E-Paper Display zur Steuerung von drei LEDs. Der Benutzer kann durch die Optionen navigieren und die LEDs mit physischen Tasten ein- oder ausschalten. Der folgende kurze Videoclip zeigt, wie das aussieht:

Steuerung von LEDs mit Menü auf E-Paper Display

Fazit

In diesem Tutorial hast du gelernt, wie du die GxEPD2-Bibliothek verwendest, um auf einem CrowPanel 4,2-Zoll E-Paper Display zu zeichnen und zu schreiben.

Wenn du mehr Hintergrundinformationen zu E-Paper Displays suchst, schau dir das Interfacing Arduino with E-ink Display und das Partial Refresh of e-Paper Display Tutorial an.

Auch wenn du nach anderen Anwendungen suchst, könnten die Weather Station on e-Paper Display, das Temperature Plotter on e-Paper Display, das Digital Clock on e-Paper Display und das Analog Clock on e-Paper Display Tutorials interessant sein.

Wenn du Fragen hast, kannst du sie gerne im Kommentarbereich stellen. Viel Spaß beim Basteln ; )

Links

Hier einige Links rund um das CrowPanel 4,2-Zoll E-Paper Display, die ich beim Schreiben dieses Tutorials als nützlich empfand: