Waveshare e-paper displays with SPI

@flori_2121,

from README.md of GxEPD2:

### Paged Drawing, Picture Loop
 - This library uses paged drawing to limit RAM use and cope with missing single pixel update support
 - buffer size can be selected in the application by template parameter page_height, see GxEPD2_Example
 - Paged drawing is implemented as picture loop, like in U8G2 (Oliver Kraus)
 - see https://github.com/olikraus/u8glib/wiki/tpictureloop
 - Paged drawing is also available using drawPaged() and drawCallback(), like in GxEPD
- ` // GxEPD style paged drawing; drawCallback() is called as many times as needed `
- ` void drawPaged(void (*drawCallback)(const void*), const void* pv) `
- paged drawing is done using Adafruit_GFX methods inside picture loop or drawCallback

### Full Screen Buffer Support
 - full screen buffer is selected by setting template parameter page_height to display height
 - drawing to full screen buffer is done using Adafruit_GFX methods without picture loop or drawCallback
 - and then calling method display()

from README.md of GxEPD:

### Paged Drawing, Picture Loop for AVR
- This library uses paged drawing to cope with RAM restriction and missing single pixel update support
- Paged drawing is implemented using callbacks to callback functions in the user application code,
- the picture loop is internal to the display classes and calls the callback function as many times as needed,
- this is a different implementation compared to the picture loop in U8G2 (Oliver Kraus)
- see also https://github.com/olikraus/u8glib/wiki/tpictureloop

for GxEPD you need to look at PagedDisplayForSmallRam.ino for AVR processors.

Maybe you can ask Oliver Kraus for a description of picture loop in German.

I´m now trying to start my waveshare ePaper 2.9in b/w display with an LoLin new nodemcu v3 (ESP8266). The suggested wiring is executed as followed:

// mapping suggestion from Waveshare SPI e-Paper to generic ESP8266
// BUSY -> GPIO4, RST -> GPIO2, DC -> GPIO0, CS -> GPIO15, CLK -> GPIO14, DIN -> GPIO13, GND -> GND, 3.3V -> 3.3V
// NOTE: connect 3.3k pull-down from GPIO15 to GND if your board or shield has level converters
// NOTE for ESP8266: using SS (GPIO15) for CS may cause boot mode problems, use different pin in case, or 3.3k pull-down

I now have the problem, that the follwing occurs while uploading the code:

Connecting............................_____..

And after a while it says:

esptool.FatalError: Failed to connect to ESP8266: Timed out waiting for packet header

It only occurs when the RST pin is connected to the GPIO2 (D4), otherwise the programm upload works. Maybe it has something to do with the shown "TX D1"? I don´t know.
Now my question is how am I able to deal with the problem, is there a possibility to change the wiring or the settings. What should I do to make the display work properly?

Thanks for your answer.

Layout:

Provide links to the product in question.

Then we might know, not just guess, you have a Waveshare board with the "clever" reset circuit.
And the site of your processor board might have a readable picture.

You may try with a pull-up on GPIO02. The internal pull-up might be too weak to fight against the pull-down of the "clever" reset circuit. Search for "clever" reset circuit to learn more about this. Or consult the schematics.

I use 10kOhm as pull-up and sometimes it works, sometimes not. When I disconnect the Pin Rst, it always uploads the program. Nevertheless, my display doesn´t react, even if the code is uploaded.

What ist the function of the Rst pin, is this pin necessary?

@kevinsteven,

I just lost the detailed post of my answer by one of these dreadful forum failures.

You now know where the init code is in Waveshare code and GxEPD2 driver code.
You can use your workaround or experiment with including/changing code in GxEPD2.
Unless no other users report this issue, we leave it as is, else I would need the actual panel donated.

Jean-Marc

    EPD_7IN5B_HD_SendCommand(0x46);  // Auto Write RAM
EPD_7IN5B_HD_SendData(0xF7);
EPD_7IN5B_HD_ReadBusy();        //waiting for the electronic paper IC to release the idle signal

EPD_7IN5B_HD_SendCommand(0x47);  // Auto Write RAM
EPD_7IN5B_HD_SendData(0xF7);
EPD_7IN5B_HD_ReadBusy();        //waiting for the electronic paper IC to release the idle signal




EPD_7IN5B_HD_SendCommand(0x01);  // Set MUX as 527
EPD_7IN5B_HD_SendData(0xAF);
EPD_7IN5B_HD_SendData(0x02);
EPD_7IN5B_HD_SendData(0x01);


0x02AF is not 527.
Using a different number of gates to scan will result in a different waveform. Maybe the waveform in OTP of the new panels is for a different panel, and this change corrects the timing. Your reported refresh times **are** slightly different than mine.

@ZinggJM, @kevinsteven,

I have the same panel (GDEH075Z90 880x528 3-color panel) and can also confirm the very dark red and the rather gray black. Unfortunately, the demo code already mentioned (examples/esp32-waveshare-epd/examples/epd7in5b_HD-demo) is very dark in red and the black is not always very clean (see screenshots).

I have also observed that the black areas look rather gray at the end, even though they looked very good during the drawing.

This is my first color e-ink display, so I am not sure if I have too high expectations for the saturation of the red color. Or is it more likely that this is a hardware problem (display / HAT)?

For the sake of completeness: I am using the display on a Lolin D32 pro.

Thanks in advance.
Matthias


flori_2121:
I use 10kOhm as pull-up and sometimes it works, sometimes not. When I disconnect the Pin Rst, it always uploads the program. Nevertheless, my display doesn´t react, even if the code is uploaded.

What ist the function of the Rst pin, is this pin necessary?

The RST pin of the panel/controller allows to make sure the controller can be reset cleanly, e.g. after a slow VCC rise.
It also allows to wake up the controller from deep sleep (hibernate() method of GxEPD2).
But this normal function of the RST pin doesn't work cleanly with the "clever" reset circuit of Waveshare boards.
I would try with 3.3k pull-up.

@mattacker,

did you try with both positions of the RESE switch? See also this post.

Make sure the VCC supply to the panel is 3.3V and stable. The big panels need strong enough supply.

Jean-Marc

@ZinggJM thank you very much for your quick feedback! I seem to have skipped this post. It is true that when I use the display configuration "A" on the e-Paper Driver HAT, it is now red as I would expect. Thank you!

Hi to all
I decide to work with e-paper displays so i borow a TTGO T5 2.13 module from a friend to test it.
My problem is that i don't know how to make it work.
I have tried so far many examples i found on the internet but i had no luck.
I am using arduino IDE to program it.The examples compiled succefully and downloaded to the board with no errors.
But after that , nothing.
Please help me to start.
My friend bought the board 2 months ago from:
https://www.aliexpress.com/item/4000348231634.html?spm=a2g0s.9042311.0.0.27424c4dFsU1nH
The examples that i tried was from

ZinggJM / GxEPD and ZinggJM / GxEP2

@jxid,

thank you for the clickable link!

Unfortunately you didn't tell exactly what you tried, and what the results were.

In the CUSTOMER REVIEWS of the page you link to I see:

Super fast delivery by PPL (from Poland). I've just tried few examples and it works great. Magic string which worked for me: GxEPD2_BW display(GxEPD2_213_B73(/CS=5/ EPD_CS, /DC=17/ EPD_DC, /RST=16/ EPD_RST, /BUSY=4/ EPD_BUSY)); // 2-Colour display (B/W) 18 Aug 2020 06:38

Did you try with this constructor line? But it is not correct.

GxEPD2_BW<GxEPD2_213_flex, GxEPD2_213_flex::HEIGHT> display(GxEPD2_213_flex(/*CS=5*/ 5, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4)); // GDEW0213I5F

This would be for TTGO T8 ESP32-WROVER. Adapted parameters for TTGO T5.

Did you try with the constructor lines for all other 2.13" b/w panels?

I have no idea which panel this TTGO board uses, and if it is a panel that is supported by GxEPD2.

You could provide diagnostic output from the example from Serial Monitor, in a code window, please.

Jean-Marc

LILYGO® TTGO T5 V2.3 2.13 Inch E-Paper Screen New Driver Chip

#define ELINK_BUSY 4
#define ELINK_RESET 16
#define ELINK_DC 17
#define ELINK_SS 5

hello @ZinggJM, I really need your help now.
I´m now starting waveShare ePaper 1.54in b/w display with ESP32. Everything was perfect with your library and Example. (or maybe I have found no problems yet).
But after the other people use it for a few weeks, I find the display is not enough stable anymore. The display may at times show not very well after each display.update or display.updateWindow

I'm not sure if the display is broken. I have set enable display.init

  Serial.begin(115200);
  display.init(115200); // disable diagnostic output on Serial

I will send count to serial when the button is down and let the display update. The Arduino serial monitor will get the feedback when the display is fine:

07:55:30.088 -> current number: 609
07:55:30.088 -> _InitDisplay : 2781
07:55:30.183 -> _PowerOn : 90706
07:55:30.795 -> _Update_Part : 595730
07:55:32.717 -> current number: 610

07:55:32.764 -> _InitDisplay : 2206
07:55:32.812 -> _PowerOn : 90707
07:55:33.423 -> _Update_Part : 595737

but sometimes I will just get the other feedback when the display can not show well:

07:48:53.292 -> current number: 604
07:48:53.292 -> _InitDisplay : 2161
07:48:53.292 -> command 0x1 : 1
07:48:53.292 -> command 0x3c : 1
07:48:53.292 -> command 0x11 : 3690
07:48:53.292 -> command 0x4f : 1
07:48:53.292 -> _PowerOn : 1
07:48:53.292 -> command 0x44 : 635
07:48:53.292 -> command 0x4e : 1
07:48:53.292 -> command 0x4f : 1
07:48:53.292 -> command 0x22 : 5561
07:48:53.292 -> _Update_Part : 1
07:48:53.623 -> command 0x4f : 1
  • so I really need your suggestion if the display is broken or I made some mistake.

  • Furthermore, could you please tell me whether it is possible to directly use Arduino to get the feedback from display.update. So I can check the feedback: If "command" then repeats display.update or ESP.restart().

Thank you for your help and look forward to your message.

@kaichen2012,

welcome to the forum. I guess you have already read How to get the best out of this forum (short version)

Thank you for using code windows! Karma++.

But I need to know the exact display you use, please post a clickable link.

And I need to know the constructor line you selected.

It used to work, but now it doesn't work reliably anymore? What is the difference?
What might have happened in the meantime?

Jean-Marc

@ZinggJM
Thank you for your reply.

But I need to know the exact display you use, please post a clickable link.

My display is: https://www.waveshare.com/wiki/1.54inch_e-Paper_Module

And I need to know the constructor line you selected.

I'm sorry but I'm not exactly sure what you mean, I'd like to copy some of my code and library.

#include <GxEPD.h>

// select the display class to use, only one

#include <GxGDEH0154D67/GxGDEH0154D67.h>  // 1.54" b/w

#include GxEPD_BitmapExamples
#include "IMG_Logo.h"

// FreeFonts from Adafruit_GFX
#include <Fonts/FreeMonoBold9pt7b.h>
#include <Fonts/FreeMonoBold12pt7b.h>
#include <Fonts/FreeMonoBold18pt7b.h>
#include <Fonts/FreeMonoBold24pt7b.h>

#include <GxIO/GxIO_SPI/GxIO_SPI.h>
#include <GxIO/GxIO.h>

// for SPI pin definitions see e.g.:
// C:\Users\xxx\Documents\Arduino\hardware\espressif\esp32\variants\lolin32\pins_arduino.h

GxIO_Class io(SPI, /*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16); // arbitrary selection of 17, 16
GxEPD_Class display(io, /*RST=*/ 16, /*BUSY=*/ 4); // arbitrary selection of (16), 4

// set position and coordinate of Logo,AdapterID,Counter and Time...
uint16_t Rotation = 1;
uint16_t x_ID = 100;
uint16_t y_ID = 24;
uint16_t y_CounterTitel = y_ID+30;
uint16_t y_Counter = y_CounterTitel+55;
uint16_t y_Update = display.height()-53;
uint16_t x_LastTime = 28;
uint16_t y_LastTime = display.height()-31;
uint16_t x_LastCount = 28;
uint16_t y_LastCount = display.height()-5;
#include <Bounce2.h>
#include <EEPROM.h>
#include <Wire.h>

It used to work, but now it doesn't work reliably anymore? What is the difference?
What might have happened in the meantime?

yes, it used to work well. Or the problem was always there but I never found it.
The current status is, sometimes after display.update or display.updateWindow would the display show not well. For example:

  • Two characters overlap each other. serial.print work well
  • the display is stuck after update. Serial.print work well, the feedback from display.update is unnormal
  • display not working. Serial.print work well,the feedback from display.update is unnormal
  • serial keep on coming unreadable random code

so I want to find, how to directly use Arduino(ESP32) to get the feedback from display.update. We can always check the feedback:

  • If we get "command" or unreadable random code, then repeats display.update or ESP.restart().

I'm sorry to be too long-winded but hope you could understand what I mean.

Thank you again for your patience to read...

@kaichen2012,

Ok, thanks for the link and the code extract.

Now I know that you use the library GxEPD and some example code unknown to me.

And of course you don't understand "constructor line used", as this is what you would use with GxEPD2.

For new users or new projects I recommend to use GxEPD2, and to install it through Library Manager.
Then we know for sure that you use the official and actual version.

Please run GxEPD2_Example.ino, selecting the constructor line for your display, and report if this works.

Maybe check the wiring; does every line still make good contact? And measure supply voltage.

Jean-Marc

@ZinggJM
Thank you for your suggestion.
:slight_smile: I didn't notice that we have already the new library.
Ok, then I will try to use the library GxEPD2. Of course, I would report it to you.
(Maybe next week, because I have not enough time this week.) hope it works.
Thanks again for your help !!! Have a nice day.

Finally after some test i manage to run the GxEPD2_Example with success!!!
What i tried:

  1. In GxEPD2_Example.ino i uncomment:
#include "bitmaps/Bitmaps128x250.h" // 2.13" b/w
  1. In GxEPD2_display_selection.h i use(uncomment):
GxEPD2_BW<GxEPD2_213_B73, GxEPD2_213_B73::HEIGHT> 
display(GxEPD2_213_B73(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 
4)); // GDEH0213B73

in
#if define(ESP32)

and the everything worked fine.

Thanks for your help.

Hi, i'm attempting to use a NodeMCU ESp8266 with the waveshare7.5inch HD.
I'm using the HelloWorld Sketch example, and it appears to flash to the NodeMCU, but nothing is showing on the screen.
GxEPD2_BW<GxEPD2_420_M01, GxEPD2_420_M01::HEIGHT> display(GxEPD2_420_M01(/*CS=0*/ 0, /*DC=4*/ 4, /*RST=5*/ 5, /*BUSY=16*/ 16)); // GDEW042M01

GxEPD2_BW<GxEPD2_420_M01, GxEPD2_420_M01::HEIGHT> display(GxEPD2_420_M01(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=5*/ 5, /*BUSY=16*/ 16)); // GDEW042M01

I've tried both sets of code above for the pin connections.

Currently I have

Busy : D0
RST : D1
CD : D2
CS : D3
CLK : D5
DIN : D7
GND : GND
VCC : 3V3

If I run the code, i get.

Executable segment sizes:
IROM   : 247620          - code in flash         (default or ICACHE_FLASH_ATTR) 
IRAM   : 27340   / 32768 - code in IRAM          (ICACHE_RAM_ATTR, ISRs...) 
DATA   : 1248  )         - initialized variables (global, static) in RAM/HEAP 
RODATA : 800   ) / 81920 - constants             (global, static) in RAM/HEAP 
BSS    : 40520 )         - zeroed variables      (global, static) in RAM/HEAP 
Sketch uses 277008 bytes (28%) of program storage space. Maximum is 958448 bytes.
Global variables use 42568 bytes (51%) of dynamic memory, leaving 39352 bytes for local variables. Maximum is 81920 bytes.
esptool.py v2.8
Serial port COM3
Connecting....
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
MAC: 8c:aa:b5:63:dc:3a
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Auto-detected Flash size: 4MB
Flash params set to 0x0340
Compressed 281168 bytes to 206826...
Wrote 281168 bytes (206826 compressed) at 0x00000000 in 18.9 seconds (effective 118.7 kbit/s)...
Hash of data verified.

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

And the light near the USB plug stays on and lit, but the screen does not change.

Appreciate any help! Or should I just get the Universal e-Paper Driver HAT, Onboard ESP8266?

@jlt220,

welcome to the forum! Thank you for using code windows. Karma++ for your start.

Please post a link, preferably clickable, to the e-paper you bought. Then we know if it is b/w or 3-color.
And also report the connection module you use, e.g. Waveshare e-paper HAT.

The constructor line you selected corresponds to a different display or panel, 4.2" instead of 7.5" HD.

And the constructor parameters need to correspond to your wiring.

The symptoms you describe seem to indicate a boot mode issue. Check the processor description for boot mode pins, and maybe add pull-down and pull-up resistors, if you use a HAT with the "clever" reset circuit. See preceding posts.

And finally you could show diagnostic output from Serial Monitor in a code window.

Jean-Marc

Or should I just get the Universal e-Paper Driver HAT, Onboard ESP8266?

You need a connection module that has the booster circuit for panel driving voltages.
Either the HAT, or a ESP8266 or ESP32 e-paper driver board, or e.g. the DESPI-C02.

Appreciate the help!

https://www.waveshare.com/wiki/7.5inch_HD_e-Paper_HAT is the display. With the Waveshare e-paper Hat.

and the NodeMCU HiLetgo NodeMCU LUA ESP8266 CP2102 ESP-12E Internet Wifi Carte de développement Open Source,Shenzhen HiLetgo Technology Co., Ltd

I'll look in to the Serial Monitor as well.

Thank you,
-J

Hi,

these are my first steps with a MCU, so please be patient with me...

I cannot get the 3.7 inch waveshare epaper (3.7inch-e-Paper-HAT) working with my ESP32 (esp-32-dev-kit-c-v4). I tried different pin assignments, the alternative init method ("clever" reset circuit), other examples, other IDEs, but: I am always getting a "busy timeout" in nextpage() and nothing displayed on the epaper.

I added some serial output for debugging...

// GxEPD2_MinimumExample.ino by Jean-Marc Zingg

// purpose is e.g. to determine minimum code and ram use by this library

// see GxEPD2_wiring_examples.h of GxEPD2_Example for wiring suggestions and examples
// if you use a different wiring, you need to adapt the constructor parameters!

// uncomment next line to use class GFX of library GFX_Root instead of Adafruit_GFX, to use less code and ram
//#include <GFX.h>

#include <GxEPD2_BW.h> // including both doesn't use more code or ram
#include <GxEPD2_3C.h> // including both doesn't use more code or ram

// select the display class and display driver class in the following file (new style):
//#include "GxEPD2_display_selection_new_style.h"

// alternately you can copy the constructor from GxEPD2_display_selection.h or GxEPD2_display_selection_added.h of GxEPD2_Example to here
// e.g. for Wemos D1 mini:
//GxEPD2_BW<GxEPD2_154_D67, GxEPD2_154_D67::HEIGHT> display(GxEPD2_154_D67(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4)); // GDEH0154D67
GxEPD2_BW<GxEPD2_371, GxEPD2_371::HEIGHT> display(GxEPD2_371(5, 17, 16, 4)); //CS, DC, RST, BUSY

void setup()
{
  Serial.begin(115200);

  Serial.println("init");
  display.init();
  
  // comment out next line to have no or minimal Adafruit_GFX code
  display.setTextColor(GxEPD_BLACK);
  Serial.println("firstPage");
  display.firstPage();
  bool quit = false;
  while (!quit)
  {
    Serial.println("fillscreen");
    display.fillScreen(GxEPD_WHITE);
    
    Serial.println("say hello");
    // comment out next line to have no or minimal Adafruit_GFX code
    display.print("Hello World!");
    
    Serial.println("nextPage");
    if (display.nextPage())
    {
      Serial.println("nextPage returned true");
    }
    else
    {
      Serial.println("nextPage returned false");
      quit = true;
    }
  }
}

void loop() {};

Compiler output:

Sketch uses 259593 bytes (19%) of program storage space. Maximum is 1310720 bytes.
Global variables use 29004 bytes (8%) of dynamic memory, leaving 298676 bytes for local variables. Maximum is 327680 bytes.
esptool.py v2.6
Serial port /dev/cu.usbserial-0001
Connecting........_
Chip is ESP32D0WDQ6 (revision 1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
MAC: f0:08:d1:d2:2f:18
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 921600
Changed.
Configuring flash size...
Auto-detected Flash size: 4MB
Compressed 8192 bytes to 47...
Wrote 8192 bytes (47 compressed) at 0x0000e000 in 0.0 seconds (effective 2622.1 kbit/s)...
Hash of data verified.
Compressed 17392 bytes to 11186...
Wrote 17392 bytes (11186 compressed) at 0x00001000 in 0.2 seconds (effective 888.4 kbit/s)...
Hash of data verified.
Compressed 259712 bytes to 119560...
Wrote 259712 bytes (119560 compressed) at 0x00010000 in 2.3 seconds (effective 903.7 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 128...
Wrote 3072 bytes (128 compressed) at 0x00008000 in 0.0 seconds (effective 928.3 kbit/s)...
Hash of data verified.

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

My current pin setup is:

Busy : 4
RST : 16
DC : 17
CS : 5
CLK : 18 (SCK)
DIN : 23 (MOSI)
GND : GND
VCC : 3V3

Output:

⸮Ԙz⸮⸮⸮⸮⸮⸮0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:9720
ho 0 tail 12 room 4
load:0x40080400,len:6352
entry 0x400806b8
init
firstPage
fillscreen
say hello
nextPage
Busy Timeout!
nextPage returned false

Did I select the wrong display/driver class? The GxEPD2_371 seems to have other values for WIDTH and HEIGHT (240x418) than the epaper from waveshare (480x280). And the epaper is not really B/W, it has 4 gray levels...

Thanks for your great work.

EDIT:
Just in this moment, I got the epaper working with the waveshare libs/demo, see: 3.7inch_e-Paper_HAT
Download "e-Paper ESP32 Driver Codes"
Example: epd3in7-demo

I had to change the pin setup in DEV_Config.h:

#define EPD_SCK_PIN  18
#define EPD_MOSI_PIN 23
#define EPD_CS_PIN   5
#define EPD_RST_PIN  16
#define EPD_DC_PIN   17
#define EPD_BUSY_PIN 4

So my hardware and setup are working properly. I think, the 3.7 inch epaper from waveshare is not supported by GxEPD2.