GxEPD2 : Display Library for SPI E-Paper Displays available for Particle

It supports SPI e-paper displays from Dalian Good Display and the display boards from Waveshare that use these display panels.

This library replaces the GxEPD2_PP variant of GxEPD2, as the GxEPD2 library for Arduino is suitable for Particle also, just the examples need to be different.

This topic is intended for asking questions, reporting problems and issues, and hopefully telling your successful use of these displays. But the preferred place to ask questions to the author is in the Arduino Forum Displays topics:

https://forum.arduino.cc/index.php?topic=487007.0

https://forum.arduino.cc/index.php?topic=436411.0

The library is published for Particle and its repository is on GitHub:

https://github.com/ZinggJM/GxEPD2

The examples for Particle are in this folder on GitHub:

https://github.com/ZinggJM/GxEPD2/tree/master/extras/Particle/examples

These examples replace the Arduino examples in the published library for Particle.
Do the same if you want to upload a private copy, as the published version may lag behind the Arduino version on GitHub.

Note that this library may not be usable with the Particle WEB-IDE, most likely because of too many files contained.

4 Likes

Thanks for your support here @ZinggJM !!!

I am wondering: Is it normal, that it takes forever, when I click the Library in the Web IDE after search? Is there something broken? Or is it, because the library is so big?

I waited more than 15 minutes and still the page is empty and says “loading”. I tried with Chrome, Firefox and Edge. All the same! Other libraries load like a charm. But GXEPD2 and the older GXEPD_PP do not load!

Please help on resolving this. Or give me an alternative.

@Coding_Lizard, I have seen this happens with libraries with a large number of files. Try and hit refresh on your browser to see if it loads. Another approach is to use the Particle Workbench and “install” the library to your project.

Thanks for the quick help!

I installed Workbench an managed to compile the provided example locally. Will now have to verify that it actually works on my Xenon and is able to control my 7.5 inch display. Will post an update here soon.

1 Like

Could anyone offer a quick bit of advice on getting started with these libraries? I’m finding the initialization part confusing.

I have a couple of epaper displays from buydisplay.com (a 1.54" and a 4.2"), which seem similar to the waveshare devices but cheaper. I have managed to port their libraries over, but this library combined with Adafruit’s graphics library looks far better.

It is a 4 wire SPI, which I have connected as:
RST_PIN 6
DC_PIN 7
CS_PIN 8
BUSY_PIN 5

If I go with the 4.2", which is 400x300 resolution like the waveshare, do I just uncomment out the sections in the line below to give:?
GxEPD2_3C<GxEPD2_420c, GxEPD2_420c::HEIGHT> display(GxEPD2_420c(CS=D8 SS, DC=D7, RST=D6, BUSY=D4));

I’m not sure what the SS bit is after CS.

The link to the display is:

The data sheets show it uses a UC8159C which it looks like the supported waveshare devices will, so hopefully this will to. I’m happy to report back and do some testing if it will help add a few more devices to the supported list.

The CS (chip select) is the same as SS (slave select) for SPI.
Have you also got the MOSI and SCLK pins connected?

If you looked at the correctly formatted code line in the original library you'd see this

GxEPD2_3C<GxEPD2_270c, GxEPD2_270c::HEIGHT> display(GxEPD2_270c(/*CS=A2*/ SS, /*DC=*/ A1, /*RST=*/ A0, /*BUSY=*/ D4));

Notice the /* ... */ block comment :wink: Only SS is the actual pin, the gray stuff is only there for documentational purposes.

1 Like

@DaveH

It looks like you used a line from the example for the Arduino IDE, a line for ESP8266, e.g. Wemos D1 mini.

Note that the examples for Arduino IDE (still) will not compile for Particle, because of different (automatic) additions for forward declarations for .ino sources.

If you start from the repository version on GitHub, you find the examples for Particle on extras/Particle:

BTW: thank you for the link! now I have a copy of the original UC8159 controller specs; both Good Display and Waveshare produce their edited copy. I am not sure if they use the original controller chip, but I have seen remains of Ultra Chip in their documents.

Jean-Marc

Thanks for the advice. I had problems getting the gxepd2 library to load via the web ide and a few issues getting the desktop version up and running. Hopefully I can report something working tomorrow.

Thank you both, it is now working :smiley: I need need to go for the Workbench and not do web updates, but the serial console proved useful anyway.

@ScruffR - sorry I should have included the full wiring. That is:

Epaper--- Argon
1 Vin --- 3V3
2 GND --- GND
3 SDA --- MO (D12)
4 SCL --- SCK (D13)
5 /CS --- D8
6 D/C --- D7
7 RST --- D6
8 BUSY -- D5

To initialize I went with:
GxEPD2_3C<GxEPD2_420c, GxEPD2_420c::HEIGHT> display(GxEPD2_420c(/*CS=A2*/ D8, /*DC=*/ D7, /*RST=*/ D6, /*BUSY=*/ D5));

From YouTube videos and running the particle example, I do think the buydisplay screens must be much slower at updating than the waveshare ones. I did have problems with the example originally, it did not seem to be running the helloArduino and helloEpaper parts. Adding a bit more serial debugging, it was still updating one when sending the updates for the next bit. I ended up adding 20 seconds after showFont and drawBitmap.

I had wondered if I could display a slider for my Hue lights to make a control panel in my living room, but I think the update speed is going to be far too slow. I have one of those small joystick type buttons and pictured a small cursor under two sliders for lights and a heating temperature, and being able to bump it up. I think I’m going to need an OLED or LCD screen for that. Shame as the epaper looks so nice.

Thank you for the feedback! I was confused, as I forgot that Particle uses Ax and Dx for pin numbers.
I would be interested in diagnostic output for your e-paper; it looks like the BUSY line does not work as expected. It might be inverted. The Good Display 4.2" 3-color panel has about 16 seconds for refresh (BUSY active time).

Jean-Marc

Is there a way I could gather diagnostic output for you?

The diagnostic output should be available from the serial console, if init(115200) is called with a nonzero bitrate parameter. The BUSY times reported are in microseconds.

BUSY is active LOW according to the controller specs, same as for the Good Display panel.

That looks to be reporting 26 all the time.

I am testing using the following bit of code:

#include <Adafruit_GFX_RK.h>
#include <GxEPD2.h>
#define ENABLE_GxEPD2_GFX 0
#include <Arduino.h>
#include <Adafruit_GFX.h>
#include <FreeSerifBold24pt7b.h>
#include <GxEPD2_BW.h>
#include <GxEPD2_3C.h>

#include "benji_image.h"

// Init the screen object
GxEPD2_3C<GxEPD2_420c, GxEPD2_420c::HEIGHT> display(GxEPD2_420c(/*CS=A2*/ D8, /*DC=*/ D7, /*RST=*/ D6, /*BUSY=*/ D5));

// setup() runs once, when the device is first turned on.
void setup() {
  // Put initialization like pinMode and begin functions here.
  Serial.begin(115200);
  char tmpStr[50];  // Used for debugging messages
  Serial.println("GxEPD test starting");

  // Wake up display
  display.init(115200);
  // first update should be full refresh
  display.setRotation(1);

  display.setFont(&FreeSerifBold24pt7b);
  display.setTextColor(GxEPD_RED);
  display.setFullWindow();

  int16_t tbx, tby; uint16_t tbw, tbh; // boundary box window
  display.getTextBounds("Benji!", 0, 0, &tbx, &tby, &tbw, &tbh); // it works for origin 0, 0, fortunately (negative tby!)
  // center bounding box by transposition of origin:
  uint16_t x = ((display.width() - tbw) / 2) - tbx;
  uint16_t y = tbh;

  display.firstPage();  
  do {
      display.fillScreen(GxEPD_WHITE);
      display.drawInvertedBitmap(0,tbh+2,benjiBW,310,300,GxEPD_BLACK);
      display.setCursor(x,y);
      display.print("Benji!");
  } while (display.nextPage());
}


int x=0;
int basePos=30;
int addPos=0;
char tmpStr[80];

void loop() {
  sprintf(tmpStr, "Loop num=%d, addPos=%d", x, addPos);
  Serial.println(tmpStr);

  if(display.epd2.hasPartialUpdate) {
    Serial.println("  Has partial update");
  } else {
    Serial.println("  Does not have partial update");
  }

  // Move the cursor
  display.setPartialWindow(basePos,380,40+80,16); // Width is 80+cursor width
  display.firstPage();
  do {
    display.fillScreen(GxEPD_WHITE);
    display.fillRect(basePos+(addPos*80), 380, 40, 16, GxEPD_BLACK);
  } while (display.nextPage());
  x++; 
  if(addPos==0) {
    addPos=1;
  } else {
    addPos=0;
  }
  delay(20000);
}

That just displays an image and then every 20 seconds it should move a cursor (just a filled rectangle) left and right. I was hoping that with partialUpdate I could just refresh a small area of the screen and avoid the whole thing redrawing. Is that just not how the partial update works and if I want that smoothness then (cheap) epaper is not the answer? At the moment, it redraws the whole screen.

The console output from this is

Loop num=24, addPos=0
  Has partial update
_Update_Part : 26
Loop num=25, addPos=1
  Has partial update
_Update_Part : 26
Loop num=26, addPos=0
  Has partial update
_Update_Part : 26
Loop num=27, addPos=1
  Has partial update
_Update_Part : 26

@DaveH,

there is something wrong with your BUSY line, it doesn’t work.
I would also like to see the complete diagnostics, to also see _powerOn and _powerOff and _Update_Full times. _Update_Full and _Update_Part times are equal for e-papers that have no differential update, e.g. 3-color.

Partial update should work, but not for the 4.2" 3-color, because of an error of the controller.
See https://github.com/ZinggJM/GxEPD2/blob/master/MyEPDs_UpdateInfos.pdf

static const bool usePartialUpdateWindow = false; // needs be false to work

in GxEPD2_420c.cpp. You could change this to true to see the efferc.

3-color e-paper displays are only usable for rather static displays, in my opinion.

Jean-Marc

Nice spot. I had my BUSY and RST lines mixed up. This does change the output a little:

Serial monitor opened successfully:
_PowerOn : 38050
_Update_Full : 15419676
_PowerOff : 20090
Loop num=0, addPos=0
_PowerOn : 38079
_Update_Part : 15420219
Loop num=1, addPos=1
_Update_Part : 15415770
Loop num=2, addPos=0
_Update_Part : 15416086
Loop num=3, addPos=1
_Update_Part : 15413328
Loop num=4, addPos=0
_Update_Part : 15415414

Changing that value to true did not make any difference.

Are the two color displays faster at updating and more usable for a menu driven system? This was only really an experiment to see how the displays I bought performed. The smaller 1.54" I got looks like it will be a very good option for a temperature sensor and displaying the output, perhaps only updating every 5 minutes. Using the larger one a bit more dynamically was only something I thought of after I bought it.

The b/w e-paper displays are considerably faster. Take a look at MyEPDs_UpdateInfos.pdf, and the vendor specs.
The 1.54" can be used up to with one refresh ever second, the other small ones every 2 seconds.
This will affect life expectancy, see specs, although in practice you can achieve 10 times the number of refreshes specified. Changing the usePartialUpdateWindow value should make a difference, only the partial window should show flashing. But half the screen would be disturbed, unless they fixed this in the newer controller chips of this display.