Good Dispay ePaper for Arduino

I'm using GXEPD2_MultiDisplayExample with an Arduino Nano 33 Iot and three 2.9in DES displays with the DESPI-C02 (GDEW029M06) for each display.

I'm having trouble with partial refresh. It is leaving a significant ghosting effect running the example showPartialUpdate(). (See photos).
I tried enabling and disabling hasFastPartialUpdate and it had no change.
I tried using GDEW029 and GDEW029_T5. The screen did not work with 029. It worked with _T5 and had less ghosting but it was still there. There was less contrast with _T5 (see attached).

I adapted the example to work with the SAMD processor. I added in the three display instances.
For my wiring, each CS has its own pin, and each BUSY has its own pin. RST are disconnected (-1).
All SCK->D13. All SDI-> D11. All DC->D6. Power supply is going to the 3.3V out on the board (pin #17).

#if defined(ARDUINO_ARCH_SAMD)
#define RST_PIN 25 // D3(0)
#define MAX_DISPLAY_BUFFER_SIZE 15000ul // ~15k is a good compromise
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= MAX_DISPLAY_BUFFER_SIZE / (EPD::WIDTH / 8) ? EPD::HEIGHT : MAX_DISPLAY_BUFFER_SIZE / (EPD::WIDTH / 8))
GxEPD2_BW<GxEPD2_290_M06, MAX_HEIGHT(GxEPD2_290_M06)> display1(GxEPD2_290_M06(/*CS=4*/ 2, /*DC=*/ 6, /*RST=*/ -1, /*BUSY=*/ 4)); // GDEW029M06
GxEPD2_BW<GxEPD2_290_M06, MAX_HEIGHT(GxEPD2_290_M06)> display2(GxEPD2_290_M06(/*CS=4*/ 5, /*DC=*/ 6, /*RST=*/ -1, /*BUSY=*/ 7)); // GDEW029M06
GxEPD2_BW<GxEPD2_290_M06, MAX_HEIGHT(GxEPD2_290_M06)> display3(GxEPD2_290_M06(/*CS=4*/ 8, /*DC=*/ 6, /*RST=*/ -1, /*BUSY=*/ 9)); // GDEW029M06
#endif

Do you know what might be going on?

Thanks.

@d2468,

thank you for the detailed information about what you want to achieve.

I would suggest you first try one display with GxEPD2_Example.ino. The approach to try different driver classes is ok, but the correct driver class for your DES display is GxEPD2_290_M06.

I would need to know the RESE position you selected that corresponds to your pictures. It should be set to 0.47 ohms, see page 9 of GDEW029M06-201110.pdf.

If you disable hasFastPartialUpdate (by setting this attribute to false in GxEPD2_290_M06.h) you should see only full updates, refresh with flashing effect, and have no resulting ghosting.

My tests showed only minimal ghosting on the panel I have, and I think I use the same waveform (same parameters) as the demo from Good Display. But you can experiment yourself by changing values in GxEPD2_290_M06.cpp at lines beginning at 329:

// this panel doesn't seem to need balanced charge

#define T1  0 // charge balance pre-phase
#define T2  0 // optional extension
#define T3 25 // color change phase (b/w)
#define T4  0 // optional extension for one color
#define T5  0 // white sustain phase
#define T6  0 // black sustain phase

Jean-Marc

Thanks for the quick response.
The RESE is set to 0.47. It doesn't work at all when set to 3.

I'm always using GXEPD2_290_M06 for the driver class. I tried a couple times with other driver classes to see what would happen.

There is no ghosting when doing a full screen refresh. It's only when doing partial refresh that the ghosting is visible.

When disabling FastPartialUpdate, it displays "slow partial mode" as expected. It still runs the routine of

 if (display3.epd2.hasPartialUpdate)
  {
    showPartialUpdate(display3);
  }

The ghosting looks the same when FastPartialUpdate is enabled or disabled.

When running GXEPD2_Example with one display, the ghosting looks the same.

So it seems like this might be a waveform issue?
I was comparing the Good Display example code to the values in GxEPD2_290_M06.cpp. How does the good display code compare to yours? For example, from Good Display P202001204 Ap_29demo.h :

const unsigned char lut_vcom1[] PROGMEM={
0x00  ,0x19 ,0x01 ,0x00 ,0x00 ,0x01,
0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00
  ,0x00 ,0x00,          };

In your code GxEPD2_290_M06.cpp

const unsigned char GxEPD2_290_M06::lut_20_vcomDC_partial[] PROGMEM =
{
  0x00, T1, T2, T3, T4, 1, // 00 00 00 00
};

Are these two equivalent? I'm not familiar with this style of coding.

If I begin to experiment with the waveforms, what values could T1-T6 span? 0 to 1? 0 to 25?
If this is more than you're willing to support, that's okay.

Thanks for the help.

IMG_5988.jpg

IMG_5988.jpg

One more interesting note. When running GxEPD2_Example, I connected the reset and defined the pins (using the same pins from my display3 in MultiExample. Everything worked as expected.

On going back to MultiExample, I disconnected the reset pin and ran the same code from before. However, now display3 doesnt work. I had to move to a different busy pin. Then sometimes, it would give me a "Busy Timeout!" on the serial monitor. After I disconnected the power to the Arduino, it behaves better but sometimes that same display hangs up.

I'll have to do some more methodical testing to understand why this is happening

@d2468,

I would expect that your Arduino Nano 33 Iot has enough pins, so you could use a separate RST pin for each display.

Then test again. I got confused by your two posts, don't really understand what worked and what didn't.

Methodical testing and reporting is a good idea.

Ok, I’ll take another stab at this.
There are two separate and unrelated(?) issues: 1. Going between Example and MultiDisplayExample and 2. ghosting on partial update
This is all using GxEPD2.

  1. I’m not looking for a fix to this issue as I know how to work around it. Maybe this is a bug report.

I setup MultiDisplayExample using separate reset and separate busy lines. (This seems to be more stable than having disconnected reset lines. I was getting weird behavior yesterday with “Busy Timeout!” when the resets were disconnected). I removed the “one common reset for all displays” lines in the beginning of void setup().

#if defined(ARDUINO_ARCH_SAMD)
#define MAX_DISPLAY_BUFFER_SIZE 15000ul // ~15k is a good compromise
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= MAX_DISPLAY_BUFFER_SIZE / (EPD::WIDTH / 8) ? EPD::HEIGHT : MAX_DISPLAY_BUFFER_SIZE / (EPD::WIDTH / 8))
GxEPD2_BW<GxEPD2_290_M06, MAX_HEIGHT(GxEPD2_290_M06)> display1(GxEPD2_290_M06(/*CS=4*/ 2, /*DC=*/ 6, /*RST=*/ 21, /*BUSY=*/ 3)); // GDEW029M06
GxEPD2_BW<GxEPD2_290_M06, MAX_HEIGHT(GxEPD2_290_M06)> display2(GxEPD2_290_M06(/*CS=4*/ 5, /*DC=*/ 6, /*RST=*/ 20, /*BUSY=*/ 17)); // GDEW029M06
GxEPD2_BW<GxEPD2_290_M06, MAX_HEIGHT(GxEPD2_290_M06)> display3(GxEPD2_290_M06(/*CS=4*/ 8, /*DC=*/ 6, /*RST=*/ 19, /*BUSY=*/ 18)); // GDEW029M06
#endif

void setup()
{
  Serial.begin(115200);
  Serial.println();
  Serial.println("setup");
  display1.init(115200); // enable diagnostic output on Serial
  display2.init(115200); // enable diagnostic output on Serial
  display3.init(115200); // enable diagnostic output on Serial
....

Everything works as expected.

From here, I open up GxEPD2_Example. I defined the pins as the same as my display2 in MultiDisplayExample.
Upon uploading and running this example, display2 and display 3 do the same thing, except that display #3 doesn’t do HelloWorld() and one of the hibernating functions. Everything else they do at the same time. Display1 remains blank.

If I restart my computer and run GxEPD2_Example before anything else, only display2 runs, leaving display1 and display3 blank (as expected).

#if defined(ARDUINO_ARCH_SAMD)
#define MAX_DISPLAY_BUFFER_SIZE 15000ul // ~15k is a good compromise
#if IS_GxEPD2_BW(GxEPD2_DISPLAY_CLASS)
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= MAX_DISPLAY_BUFFER_SIZE / (EPD::WIDTH / 8) ? EPD::HEIGHT : MAX_DISPLAY_BUFFER_SIZE / (EPD::WIDTH / 8))
GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=4*/ 5, /*DC=*/ 6, /*RST=*/ 20, /*BUSY=*/ 17));

I tried running GxEPD2_Example using ‘GxEPD2_display_selection_added.h’ and ‘GxEPD2_display_selection_new_style.h’ and they both had the same behavior as mentioned above.

Also, I’m not sure if this is possibly related, but on running GxEPD2_Example or GxEPD2_MultiDisplayExample for the first time after opening the Arduino IDE, I get a warning message during compiling. It uploads fine after the warning. If I compile it again, I do not get the warning message again. (Copied below as code)

In file included from C:\Users\D2468\AppData\Local\Arduino15\packages\arduino\tools\CMSIS-Atmel\1.2.0/CMSIS/Device/ATMEL/samd21/include/samd21.h:69:0,
                 from C:\Users\D2468\AppData\Local\Arduino15\packages\arduino\tools\CMSIS-Atmel\1.2.0/CMSIS/Device/ATMEL/samd.h:105,
                 from C:\Users\D2468\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.11\cores\arduino/WVariant.h:22,
                 from C:\Users\D2468\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.11\variants\nano_33_iot/variant.h:25,
                 from C:\Users\D2468\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.11\libraries\Wire/Wire.h:24,
                 from C:\Users\D2468\Documents\Arduino\libraries\Adafruit_BusIO-master/Adafruit_I2CDevice.h:1,
                 from C:\Users\D2468\Documents\Arduino\libraries\Adafruit_BusIO-master/Adafruit_BusIO_Register.h:1,
                 from C:\Users\D2468\Documents\Arduino\libraries\Adafruit_BusIO-master\Adafruit_BusIO_Register.cpp:1:
C:\Users\D2468\AppData\Local\Arduino15\packages\arduino\tools\CMSIS-Atmel\1.2.0/CMSIS/Device/ATMEL/samd21/include/samd21g18a.h:226:0: warning: "LITTLE_ENDIAN" redefined
 #define LITTLE_ENDIAN          1
 
In file included from c:\users\d2468\appdata\local\arduino15\packages\arduino\tools\arm-none-eabi-gcc\7-2017q4\arm-none-eabi\include\sys\types.h:67:0,
                 from c:\users\d2468\appdata\local\arduino15\packages\arduino\tools\arm-none-eabi-gcc\7-2017q4\arm-none-eabi\include\stdio.h:61,
                 from C:\Users\D2468\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.11\cores\arduino/api/Print.h:22,
                 from C:\Users\D2468\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.11\cores\arduino/api/Stream.h:25,
                 from C:\Users\D2468\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.11\cores\arduino/api/HardwareI2C.h:22,
                 from C:\Users\D2468\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.11\libraries\Wire/Wire.h:23,
                 from C:\Users\D2468\Documents\Arduino\libraries\Adafruit_BusIO-master/Adafruit_I2CDevice.h:1,
                 from C:\Users\D2468\Documents\Arduino\libraries\Adafruit_BusIO-master/Adafruit_BusIO_Register.h:1,
                 from C:\Users\D2468\Documents\Arduino\libraries\Adafruit_BusIO-master\Adafruit_BusIO_Register.cpp:1:
c:\users\d2468\appdata\local\arduino15\packages\arduino\tools\arm-none-eabi-gcc\7-2017q4\arm-none-eabi\include\machine\endian.h:17:0: note: this is the location of the previous definition
 #define LITTLE_ENDIAN _LITTLE_ENDIAN
 
In file included from C:\Users\D2468\AppData\Local\Arduino15\packages\arduino\tools\CMSIS-Atmel\1.2.0/CMSIS/Device/ATMEL/samd21/include/samd21.h:69:0,
                 from C:\Users\D2468\AppData\Local\Arduino15\packages\arduino\tools\CMSIS-Atmel\1.2.0/CMSIS/Device/ATMEL/samd.h:105,
                 from C:\Users\D2468\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.11\cores\arduino/WVariant.h:22,
                 from C:\Users\D2468\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.11\variants\nano_33_iot/variant.h:25,
                 from C:\Users\D2468\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.11\libraries\Wire/Wire.h:24,
                 from C:\Users\D2468\Documents\Arduino\libraries\Adafruit_BusIO-master/Adafruit_I2CDevice.h:1,
                 from C:\Users\D2468\Documents\Arduino\libraries\Adafruit_BusIO-master\Adafruit_I2CDevice.cpp:1:
C:\Users\D2468\AppData\Local\Arduino15\packages\arduino\tools\CMSIS-Atmel\1.2.0/CMSIS/Device/ATMEL/samd21/include/samd21g18a.h:226:0: warning: "LITTLE_ENDIAN" redefined
 #define LITTLE_ENDIAN          1
 
In file included from c:\users\d2468\appdata\local\arduino15\packages\arduino\tools\arm-none-eabi-gcc\7-2017q4\arm-none-eabi\include\sys\types.h:67:0,
                 from c:\users\d2468\appdata\local\arduino15\packages\arduino\tools\arm-none-eabi-gcc\7-2017q4\arm-none-eabi\include\stdio.h:61,
                 from C:\Users\D2468\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.11\cores\arduino/api/Print.h:22,
                 from C:\Users\D2468\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.11\cores\arduino/api/Stream.h:25,
                 from C:\Users\D2468\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.11\cores\arduino/api/HardwareI2C.h:22,
                 from C:\Users\D2468\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.11\libraries\Wire/Wire.h:23,
                 from C:\Users\D2468\Documents\Arduino\libraries\Adafruit_BusIO-master/Adafruit_I2CDevice.h:1,
                 from C:\Users\D2468\Documents\Arduino\libraries\Adafruit_BusIO-master\Adafruit_I2CDevice.cpp:1:
c:\users\d2468\appdata\local\arduino15\packages\arduino\tools\arm-none-eabi-gcc\7-2017q4\arm-none-eabi\include\machine\endian.h:17:0: note: this is the location of the previous definition
 #define LITTLE_ENDIAN _LITTLE_ENDIAN

For the second issue, ghosting during partial update. (follow up from post #460 and #462).

I still get the bad ghosting effect during partial update in Example or MultiDisplayExample. The RESE is set to 0.47 Ohm. You recommended experimenting with changing the waveform in GxEPD2_290_M06.cpp beginning at lines 329.

I was comparing the Good Display example code to the values in GxEPD2_290_M06.cpp. How does the good display code compare to yours? For example, from Good Display P202001204 Ap_29demo.h :

const unsigned char lut_vcom1[] PROGMEM={
0x00  ,0x19 ,0x01 ,0x00 ,0x00 ,0x01,
0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00
  ,0x00 ,0x00,          };

In your code GxEPD2_290M06.cpp

const unsigned char GxEPD2_290_M06::lut_20_vcomDC_partial[] PROGMEM =
{
  0x00, T1, T2, T3, T4, 1, // 00 00 00 00
};

Are these two equivalent? I'm not familiar with this style of coding.

If I begin to experiment with the waveforms, what values could T1-T6 span? 0 to 1? 0 to 25? If this is more than you're willing to support, that's okay.

Thanks for the help.

@d2468,

If this is more than you're willing to support, that's okay.

You need to be careful with your wording with me. I am willing to help, but I am in no way obliged to. If I get exact information, not too much confusion, and polite tone, I usually try to help. Else I may just stop answering.

Jean-Marc

This was for start. I will add more.

If I begin to experiment with the waveforms, what values could T1-T6 span? 0 to 1? 0 to 25?

Yes, 0 to 25, not more than 50. The demo code uses a single differential phase of length 0x19 which happens to be 25 in decimal. The demo code uses an additional following ground phase of length 0x01. I think I tried that, with no difference, but I am not sure. you can try adding the following line to each array:

0x00, 0x01, 0x00, 0x00, 0x00, 0x01

This should result in the exact same waveform as the demo code.

If you use GxEPD2_Example.ino with all 3 displays connected, you need to make sure the other 2 CS lines are held inactive. Floating CS may even produce spurious effects with DESPI-C02. Connecting lines may act as antennas.

Hi Jean-Marc,

I experimented with changing the waveform without much success. I reached out to Good Display to see if they were able to help.

They asked which code I was using and I linked to your GxEPD2_Example code.

They recommended "please add 0x10 command as in below picture".
This code is from their example code, obviously different than your library.

Is it possible this 0x10 command is added somewhere in GxEPD2_290_M06.cpp ?

Thank you for your help. It is much appreciated.

@d2468,

You can try adding whatever you like. Then you can report your findings.

Good Display demo code always writes "old data" and "new data" to both buffers before differential refresh.

GxEPD2 has the concept to make sure the "old data" buffer corresponds to the state on display after every refresh.

Dear Jean-Marc,

thanks for all your great work you are doing, finally I found a display (GDEW0371W7) at Good Display for my project, when I saw your library - that was perfect. :+1:

I got the display running on an ESP32 (Wemos D1 Pro) based on the GD example code without issues. When trying with your library (using same pins, updated in GxEPD2_display_selection_new_style), the display shows no reaction at all.

Looking at GD documentation, I see an update from 2020, and in the doc rev=2.0 of 2019/07/17. I see also a new driver documentation with code GD8102, that is different from IL0324 you are using in your library ( you added the GDEW0371W7 display to your library on August 2019, the GD revision 2.0 is from July).

I also compared the initialization section from “GxEPD2_371::_InitDisplay()” with GD part and I can see some differences.

Maybe the problem is with the new revision?

I am a bit stuck here and it would be great to know, if you also see the root cause in the new revision -or maybe just a stupid mistake on my side - so I would continue to check.

Any help is very much appreciated.

Thanks a lot
Christian

@HappyChriss, Hi Christian,

Please always post links to the products in question.

Good Display would use a new panel name for a new controller.
But they have changed their controller naming convention. The two controllers are the same.
See their 2 websites:
3.71 inch e-paper display e-ink screen panel 4 grayscale GDEW0371W7,2-Color EPD,e-paper displa (e-paper-display.com)
3.71 inch e-paper display e-ink screen panel 4 grayscale, GDEW0371W7_e-ink display-Good Display (good-display.com)

Yes, they may have updated their demo code examples. Did you check with both old and new example?

First you should take a look at diagnostic output from the GxEPD2 example in Serial Monitor.
And report the result in a code window in your post.

Jean-Marc

Report the wiring you used and the constructor. Make sure you use the HW SPI pins.
Good Display demos use SW SPI.

Hi Jean-Marc,

I don’t know of any other way to reach out to you. Sorry for potentially misusing this thread. I would like to take you up on this here GitHub - ZinggJM/GxEPD2: Arduino Display Library for SPI E-Paper Displays

I can and will only support e-paper panels I have!

  • donation panels from users are welcome, to add support to GxEPD2

I would love to see support for the Good Display 11.6" GDEH116T91. So, if I were to send you such a display (and the DESPI-C03 adapter should you need one) would you consider extending your fantastic library to add support for it? Thanks for all the efforts supporting the maker community either way!

@frightanic, welcome to the forum! Yes, this is the correct place for this question.

large size 11.6 inch epaper screen module SPI resolution 960x640, GDEH116T91_e-ink display-Good Display (good-display.com)

I am highly interested in a donation of this panel, and I would add support for it to GxEPD2.
I would not buy it myself, as I am waiting for a solution with parallel interface and higher resolution for big e-paper panels. But as demo code is available, it should be easy enough to support it with GxEPD2. Just note that I actually have several panels waiting for support, and can’t spend full time for this, so it will take some time.

Please send a personal message to confirm your interest, and I answer with my address.
The DESPI-C03 is not needed, it should work with one of the DESPI-C02 I have.

Jean-Marc

1 Like

Thank you! I do not see any option to send you a personal message. Did they drop this with the new forum application maybe? Anyhow, my email is marcel ät frightanic dot com.

I would not buy it myself, as I am waiting for a solution with parallel interface and higher resolution for big e-paper panels.

This one maybe https://youtu.be/FD2wlDOLoSk

@frightanic,

Messages are still available, but I was also confused. There are 2 ways:

  • Right-click on your Avatar/Account symbol on top right. Open in new tab. Click tab messages.

  • Click on your Avatatar/Account symbol oon top right. Click on down button bottom left. Click tab messages.

I sent you a PM with my address. You should see a notification mark on your Account symbol.

Jean-Marc

Thank you for the link. Nice, but too big and too expensive, I think.
I look forward for more information on this: Raspberry Pi 9.7 inch Parallel e-paper display DERPI-T0A_e-ink display-Good Display (good-display.com)

Hey @ZinggJM just wanted to say thank you for always being super engaged with the community! I wrote an article about using the GDEW0213T5 with the DESPI-C02, because I had trouble with the setup process and distilled all the knowledge I got from here into the post Arduino - (e-ink) Good Display (GDEW0213T5). Thanks again!

Version 1.3.2 of library GxEPD2 is available, install with Library Manager.

  • added support for GDEW0213T5D 104x212 b/w e-paper panel
  • added support for GDEW029T5D 128x296 b/w e-paper panel
  • added support for GDEW0213Z19 104x212 b/w/r e-paper panel
  • added support for GDEW029Z13 128x296 b/w/r e-paper panel
  • both GDEW0213Z19 and GDEW029Z13 support only full screen refresh (controller issue)

Jean-Marc

1 Like

Version 3.1.1 of library GxEPD is available, install with Library Manager.

  • added support for GDEM029T94 2.9" b/w, actual Waveshare 2.9" b/w
  • updated example GxEPD_WiFi_Example, for actual GitHub certificate

This panel has been reported to be used on the actual Waveshare 2.9" b/w board.
But I don't have this Waveshare board, so I can't check and test with.

Jean-Marc