Ziel des Projekts
Als Elektronisches Papier (E‑Paper/-E-Ink) wird die Technik bezeichnet das Aussehen von Tinte auf Papier nachzubilden. Die Anzeige leuchtet nicht selbst, der Inhalt wird solange dargestellt bis eine Änderung erfolgt. Die Anzeige ist träge, ein Wechsel des Inhalts dauert einige Zeit, schnelle Bildwechsel sind nicht möglich.
Als Hardware sollen ein 1,54 Zoll Display mit einer Auflösung von 200×200 Pixeln und ein 4,2 Zoll Display mit 400×300 Pixeln verwendet werden.
Das Waveshare 1,54 Zoll Display kann die Farben weiß, rot und schwarz darstellen, das Waveshare 4,2 Zoll Display verfügt nur über die Farben schwarz und weiß.
Als Mikrocontroller sollen verschiedene ESP-Controller eingesetzt werden.
Konfiguration der Mikrocontroller
Anschluss des Displays
Die Pins CLK, DIN (COPI) und CS sind durch den SPI-Bus des jeweiligen Mikrocontrollers festgelegt, die anderen Pins können frei vergeben werden.

| Pin | ESP32 WROOM | NodeMCU | ESP32-C6 | Arduino Nano ESP32 |
|---|---|---|---|---|
| BUSY | 4 | D1 | 11 | D9 |
| RST | 22 | D2 | 2 | D7 |
| DC | 23 | D6 | 3 | D6 |
| CS | 5 (SPI) | D8 (SPI) | 18 (SPI) | D10 (SPI) |
| CLK | 18 (SPI) | D5 (SPI) | 21 (SPI) | D13 (SPI) |
| DIN | 23 (SPI) | D7 (SPI) | 19 (SPI) | D11 (SPI) |
| GND | GND | GND | GND | GND |
| VCC | 3,3V | 3,3V | 3,3V | 3,3V |
Grafikfunktionen
Funktionen der Bibliothek GxEPD2
| Schlüsselwort | Parameter | Aktion |
|---|---|---|
| width(); | Bildschirmbreite feststellen | |
| height(); | Bildschirmhöhe feststellen | |
| init(); | Display starten | |
| setRotation(Richtung); | Richtung = 0 → nicht drehen Richtung = 1 → 90° drehen Richtung = 2 → 180° drehen Richtung = 3 → 270 ° drehen | Bildschirm ausrichten |
| fillScreen(Farbe); | Standardfarben: GxEPD_WHITE GxEPD_BLACK GxEPD_RED | Bildschirmhintergrund |
| setFullWindow(); | gesamten Bildschirm nutzen | |
| setPartialWindow(StartX, StartY, EndeX, EndeY); | Teil des Bildschirm nutzen | |
| drawPixel(x, y, Farbe); | einzelnen Pixel zeichnen | |
| drawLine(StartX, StartY, EndeX, EndeY, Farbe); | Linie zeichnen | |
| drawFastHLine(StartX, StartY, Länge, Farbe); | horizontale Linie zeichnen | |
| drawFastVLine(StartX, StartY, Länge, Farbe); | vertikale Linie zeichnen | |
| drawRect(StartX, StartY,, Breite, Höhe, Farbe); | Rechteck zeichnen | |
| drawRoundRect(StartX, StartY, Breite, Höhe, Eckenradius, Farbe); | abgerundetes Rechteck zeichnen | |
| fillRect(StartX, StartY, Breite, Höhe, Füllfarbe); | ausgefülltes Rechteck zeichnen | |
| drawCircle(MittelpunkX, MittelpunktY, Radius, Farbe); | Kreis zeichnen | |
| fillCircle(MittelpunktX, MittelpunktY, Radius, Füllfarbe); | Ausgefüllten Kreis zeichnen | |
| setCursor(x, y); | Cursor setzen | |
| setTextSize(Textgröße); | Textgröße bestimmen | |
| setTextColor(Farbe); | Textfarbe setzen | |
| print("Text"); println("Text"); | Text schreiben | |
| setTextWrap(true/false); | false → Text fließt über den Rand des Displays hinaus true → Text wird am Ende umgebrochen | Zeilenumbruch |
| drawBitmap(x, y, Bitmap_Array, Breite, Höhe, Farbe); | Bitmap dartsellen |
Benötigte Bibliotheken

Die internen Schriften werden durch die Schriften der Bibliothek u8g2 ersetzt.

Die Auswahl des Treibers erfordert gelegentlich etwas Ausprobieren. Eine Liste der verfügbaren Treiber gibt es 🔗hier.
Ansicht auf einem 1,54 Zoll Display
![]() | ![]() | ![]() | ![]() |
| Text mit u8g2 | Kreise | horizontale Linien | abgerundete Rechtecke |
Das Programm
Waveshare 1,54 Zoll
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
// 3-farbiges Display #include "GxEPD2_3C.h" #include "U8g2_for_Adafruit_GFX.h" // Objekt u8g2Schriften U8G2_FOR_ADAFRUIT_GFX u8g2Schriften; // ESP32-Wroom // Anschlüsse: CLK -> 18, DIN -> 23, CS -> 5, DC-> 2, RST -> 22, BUSY -> 4 // GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, 200> // display(GxEPD2_DRIVER_CLASS(/*CS=*/5, /*DC=*/2, /*RST=*/22, /*BUSY=*/4)); // NodeMCU // CLK - D5, DIN -> D7, CS -> D8, DC -> D6, RST -> D2, BUSY -> D1 // GxEPD2_3C<GxEPD2_154_Z90c, GxEPD2_154_Z90c::HEIGHT> // display(GxEPD2_154_Z90c(/*CS*/ D8, /*DC*/ D6, /*RST*/ D2, /*BUSY*/ D1)); // ESP32-C6 // Anschlüsse: CLK -> 21, DIN -> 19, CS -> 18, DC-> 3, RST -> 10, BUSY -> 11 // GxEPD2_3C<GxEPD2_154_Z90c, GxEPD2_154_Z90c::HEIGHT> // display(GxEPD2_154_Z90c(/*CS*/ 18, /*DC*/ 3, /*RST*/ 10, /*BUSY*/ 11)); // Nano ESP32 // Anschlüsse: CLK -> D13, DIN -> D11, CS -> D10, DC-> D6, RST -> D7, BUSY -> D9 // GxEPD2_3C<GxEPD2_154_Z90c, GxEPD2_154_Z90c::HEIGHT> // display(GxEPD2_154_Z90c(/*CS*/ D10, /*DC*/ D6, /*RST*/ D7, /*BUSY*/ D9)); void setup() { display.init(115200, true, 2, false); // Schriften von u8g2 display zuordnen u8g2Schriften.begin(display); // interne Schriften Text(); delay(5000); // u8g2 Schriften TextFonts(); delay(5000); // ausgefüllte Kreise Kreise(); delay(5000); // horizontale Linien LinienHorizontal(); delay(5000); // vertikale Linien LinienVertikal(); delay(5000); // abgerundete Rechtecke Rechtecke(); display.hibernate(); } void Text() { display.setFullWindow(); display.fillScreen(GxEPD_WHITE); display.firstPage(); do { display.setCursor(1, 10); display.setTextColor(GxEPD_BLACK); display.setTextSize(2); display.print("Text"); display.setCursor(1, 40); display.setTextColor(GxEPD_RED); display.setTextSize(3); display.print("Text"); display.setCursor(1, 80); display.setTextColor(GxEPD_BLACK); display.setTextSize(4); display.print("Text"); display.setCursor(1, 120); display.setTextColor(GxEPD_RED); display.setTextSize(6); display.print("Text"); } while (display.nextPage()); } // alle Schriften können Umlaute darstellen void TextFonts() { display.setFullWindow(); display.fillScreen(GxEPD_WHITE); u8g2Schriften.setForegroundColor(GxEPD_BLACK); u8g2Schriften.setBackgroundColor(GxEPD_WHITE); display.firstPage(); do { u8g2Schriften.setCursor(1, 30); u8g2Schriften.setFont(u8g2_font_helvB24_tf); u8g2Schriften.print("Text"); u8g2Schriften.setCursor(1, 70); u8g2Schriften.setFont(u8g2_font_fub30_tf); u8g2Schriften.print("Text"); u8g2Schriften.setCursor(1, 120); u8g2Schriften.setFont(u8g2_font_inb38_mf); u8g2Schriften.print("Text"); u8g2Schriften.setCursor(1, 190); u8g2Schriften.setFont(u8g2_font_inb49_mr); u8g2Schriften.print("Text"); } while (display.nextPage()); } void Kreise() { display.setFullWindow(); display.fillScreen(GxEPD_WHITE); display.firstPage(); do { int Radius = 5; int StartX = Radius; int StartY = 5; while (StartX < display.width() - Radius) { for (int i = StartY; i < display.height() - Radius; i += 15) { display.fillCircle(StartX, i, Radius, GxEPD_RED); delay(1); } StartX += 15; } } while (display.nextPage()); } void LinienHorizontal() { display.setFullWindow(); display.fillScreen(GxEPD_WHITE); do { for (int i = 0; i < display.height() - 1; i += 10) { display.drawFastHLine(0, i, display.width(), GxEPD_BLACK); delay(1); } } while (display.nextPage()); } void LinienVertikal() { display.setFullWindow(); display.fillScreen(GxEPD_WHITE); do { for (int i = 0; i < display.width() - 1; i += 10) { display.drawFastVLine(i, 0, display.height(), GxEPD_BLACK); delay(1); } } while (display.nextPage()); } void Rechtecke() { display.setFullWindow(); display.fillScreen(GxEPD_WHITE); do { for (int i = 0; i < display.height() / 2; i += 10) { display.drawRoundRect(i, i, display.width() - 2 * i, display.height() - 2 * i, 5, GxEPD_BLACK); delay(10); } } while (display.nextPage()); } void loop() { // bleibt leer, Programm läuft nur einmal } |
Waveshare 2,9 Zoll
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
// schwarz/weiß Display #include "GxEPD2_BW.h" #include "U8g2_for_Adafruit_GFX.h" // Objekt u8g2Schriften U8G2_FOR_ADAFRUIT_GFX u8g2Schriften; // ESP32-Wroom // Anschlüsse: CLK -> 18, DIN -> 23, CS -> 5, DC-> 2, RST -> 22, BUSY -> 4 // GxEPD2_BW<GxEPD2_290_GDEY029T94, GxEPD2_290_GDEY029T94::HEIGHT> // display(GxEPD2_290_GDEY029T94(/*CS*/ 5, /*DC*/ 2, /*RST*/ 22, /*BUSY*/ 4)); // NodeMCU // CLK - D5, DIN -> D7, CS -> D8, DC -> D6, RST -> D2, BUSY -> D1 // GxEPD2_BW<GxEPD2_290_GDEY029T94, GxEPD2_290_GDEY029T94::HEIGHT> // display(GxEPD2_290_GDEY029T94(/*CS*/ D8, /*DC*/ D6, /*RST*/ D2, /*BUSY*/ D1)); // ESP32-C6 // Anschlüsse: CLK -> 21, DIN -> 19, CS -> 18, DC-> 3, RST -> 10, BUSY -> 11 // GxEPD2_BW<GxEPD2_290_GDEY029T94, GxEPD2_290_GDEY029T94::HEIGHT> // display(GxEPD2_290_GDEY029T94(/*CS*/ 18, /*DC*/ 3, /*RST*/ 10, /*BUSY*/ 11)); // Nano ESP32 // Anschlüsse: CLK -> D13, DIN -> D11, CS -> D10, DC-> D6, RST -> D7, BUSY -> D9 // GxEPD2_BW<GxEPD2_290_GDEY029T94, GxEPD2_290_GDEY029T94::HEIGHT> // display(GxEPD2_290_GDEY029T94(/*CS*/ D10, /*DC*/ D6, /*RST*/ D7, /*BUSY*/ D9)); void setup() { display.init(115200, true, 2, false); display.setRotation(1); // Schriften von u8g2 display zuordnen u8g2Schriften.begin(display); TextFonts(); delay(5000); // interne Schriften Text(); delay(5000); // ausgefüllte Kreise Kreise(); delay(5000); // horizontale Linien LinienHorizontal(); delay(5000); // vertikale Linien LinienVertikal(); delay(5000); // abgerundete Rechtecke Rechtecke(); } void Text() { display.setFullWindow(); display.fillScreen(GxEPD_WHITE); display.firstPage(); do { display.setCursor(1, 10); display.setTextColor(GxEPD_BLACK); display.setTextSize(2); display.print("Text"); display.setCursor(1, 40); display.setTextColor(GxEPD_BLACK); display.setTextSize(3); display.print("Text"); display.setCursor(1, 80); display.setTextColor(GxEPD_BLACK); display.setTextSize(4); display.print("Text"); } while (display.nextPage()); } // alle Schriften können Umlaute darstellen void TextFonts() { display.firstPage(); do { u8g2Schriften.setCursor(10, 10); u8g2Schriften.setForegroundColor(GxEPD_BLACK); u8g2Schriften.setBackgroundColor(GxEPD_WHITE); u8g2Schriften.setFont(u8g2_font_helvB12_tf); u8g2Schriften.print("Text"); u8g2Schriften.setCursor(10, 50); u8g2Schriften.setFont(u8g2_font_helvB24_tf); u8g2Schriften.print("Text"); u8g2Schriften.setCursor(10, 100); u8g2Schriften.setFont(u8g2_font_logisoso32_tf); u8g2Schriften.print("Text"); } while (display.nextPage()); } void Kreise() { display.fillScreen(GxEPD_WHITE); display.firstPage(); do { int Radius = 5; int StartX = Radius; int StartY = 5; while (StartX < display.width() - Radius) { for (int i = StartY; i < display.height() - Radius; i += 15) { display.fillCircle(StartX, i, Radius, GxEPD_BLACK); delay(1); } StartX += 15; } } while (display.nextPage()); } void LinienHorizontal() { display.setFullWindow(); display.fillScreen(GxEPD_WHITE); do { for (int i = 0; i < display.height() - 1; i += 10) { display.drawFastHLine(0, i, display.width(), GxEPD_BLACK); delay(1); } } while (display.nextPage()); } void LinienVertikal() { display.setFullWindow(); display.fillScreen(GxEPD_WHITE); do { for (int i = 0; i < display.width() - 1; i += 10) { display.drawFastVLine(i, 0, display.height(), GxEPD_BLACK); delay(1); } } while (display.nextPage()); } void Rechtecke() { display.setFullWindow(); display.fillScreen(GxEPD_WHITE); do { for (int i = 0; i < display.height() / 2; i += 10) { display.drawRoundRect(i, i, display.width() - 2 * i, display.height() - 2 * i, 5, GxEPD_BLACK); delay(10); } } while (display.nextPage()); } void loop() { // bleibt leer, Programm läuft nur einmal } |
Waveshare 4,2 Zoll
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
// schwarz/weiß Display #include "GxEPD2_BW.h" #include "U8g2_for_Adafruit_GFX.h" // Objekt u8g2Schriften U8G2_FOR_ADAFRUIT_GFX u8g2Schriften; // ESP32-Wroom // Anschlüsse: CLK -> 18, DIN -> 23, CS -> 5, DC-> 2, RST -> 22, BUSY -> 4 // GxEPD2_BW<GxEPD2_420_GDEY042T81, GxEPD2_420_GDEY042T81::HEIGHT> // display(GxEPD2_420_GDEY042T81(/*CS*/ 5, /*DC*/ 2, /*RST*/ 22, /*BUSY*/ 4)); // NodeMCU // CLK - D5, DIN -> D7, CS -> D8, DC -> D6, RST -> D2, BUSY -> D1 // GxEPD2_BW<GxEPD2_420_GDEY042T81, GxEPD2_420_GDEY042T81::HEIGHT> // display(GxEPD2_420_GDEY042T81(/*CS*/ D8, /*DC*/ D6, /*RST*/ D2, /*BUSY*/ D1)); // ESP32-C6 // Anschlüsse: CLK -> 21, DIN -> 19, CS -> 18, DC-> 3, RST -> 10, BUSY -> 11 // GxEPD2_BW<GxEPD2_420_GDEY042T81, GxEPD2_420_GDEY042T81::HEIGHT> // display(GxEPD2_420_GDEY042T81(/*CS*/ 18, /*DC*/ 3, /*RST*/ 10, /*BUSY*/ 11)); // Nano ESP32 // Anschlüsse: CLK -> D13, DIN -> D11, CS -> D10, DC-> D6, RST -> D7, BUSY -> D9 // GxEPD2_BW<GxEPD2_420_GDEY042T81, GxEPD2_420_GDEY042T81::HEIGHT> // display(GxEPD2_420_GDEY042T81(/*CS*/ D10, /*DC*/ D6, /*RST*/ D7, /*BUSY*/ D9)); void setup() { display.init(115200, true, 2, false); // Schriften von u8g2 display zuordnen u8g2Schriften.begin(display); TextFonts(); delay(5000); // interne Schriften Text(); delay(5000); // ausgefüllte Kreise Kreise(); delay(5000); // horizontale Linien LinienHorizontal(); delay(5000); // vertikale Linien LinienVertikal(); delay(5000); // abgerundete Rechtecke Rechtecke(); } void Text() { display.setFullWindow(); display.fillScreen(GxEPD_WHITE); display.firstPage(); do { display.setCursor(1, 10); display.setTextColor(GxEPD_BLACK); display.setTextSize(2); display.print("Text"); display.setCursor(1, 40); display.setTextColor(GxEPD_BLACK); display.setTextSize(3); display.print("Text"); display.setCursor(1, 80); display.setTextColor(GxEPD_BLACK); display.setTextSize(4); display.print("Text"); display.setCursor(1, 120); display.setTextColor(GxEPD_BLACK); display.setTextSize(6); display.print("Text"); } while (display.nextPage()); } // alle Schriften können Umlaute darstellen void TextFonts() { display.firstPage(); do { u8g2Schriften.setCursor(10, 30); u8g2Schriften.setForegroundColor(GxEPD_BLACK); u8g2Schriften.setBackgroundColor(GxEPD_WHITE); u8g2Schriften.setFont(u8g2_font_helvB24_tf); u8g2Schriften.print("Text"); u8g2Schriften.setCursor(10, 100); u8g2Schriften.setFont(u8g2_font_fub42_tf); u8g2Schriften.print("Text"); u8g2Schriften.setCursor(10, 180); u8g2Schriften.setFont(u8g2_font_logisoso58_tf); u8g2Schriften.print("Text"); u8g2Schriften.setCursor(10, 290); u8g2Schriften.setFont(u8g2_font_logisoso92_tn); u8g2Schriften.print("12345"); } while (display.nextPage()); } void Kreise() { display.fillScreen(GxEPD_WHITE); display.firstPage(); do { int Radius = 5; int StartX = Radius; int StartY = 5; while (StartX < display.width() - Radius) { for (int i = StartY; i < display.height() - Radius; i += 15) { display.fillCircle(StartX, i, Radius, GxEPD_BLACK); delay(1); } StartX += 15; } } while (display.nextPage()); } void LinienHorizontal() { display.setFullWindow(); display.fillScreen(GxEPD_WHITE); do { for (int i = 0; i < display.height() - 1; i += 10) { display.drawFastHLine(0, i, display.width(), GxEPD_BLACK); delay(1); } } while (display.nextPage()); } void LinienVertikal() { display.setFullWindow(); display.fillScreen(GxEPD_WHITE); do { for (int i = 0; i < display.width() - 1; i += 10) { display.drawFastVLine(i, 0, display.height(), GxEPD_BLACK); delay(1); } } while (display.nextPage()); } void Rechtecke() { display.setFullWindow(); display.fillScreen(GxEPD_WHITE); do { for (int i = 0; i < display.height() / 2; i += 10) { display.drawRoundRect(i, i, display.width() - 2 * i, display.height() - 2 * i, 5, GxEPD_BLACK); delay(10); } } while (display.nextPage()); } void loop() { // bleibt leer, Programm läuft nur einmal } |
Letzte Aktualisierung:



