Problems with GxEPD2 and partial update

Howdy,

I'm trying to use an esp32 (Lolin D32 Pro board) with an waveshare epaper display (2.9" BW) utilizing the GxEPD2 library. Everything works fine as long as I print directly to the display. However, using partial mode doesn't really work and I don't understand what's wrong. But since the example works, it must be something with my code.

So, here's the relevant part of it:

#define ENABLE_GxEPD2_GFX 0

#include <GxEPD2_BW.h>
//#include <GxEPD2_3C.h>
//#include <GxEPD2_7C.h>
#include <Fonts/FreeMonoBold9pt7b.h>

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

// time management
#include <Esp.h>
#include <esp_system.h>
#include <sys/time.h>

// GLOBALS
char timebuf[64];

struct ShowBoxParameters {
  uint16_t x, y, w, h;
};

void settime() {
  // set current day/time
  struct timeval tv;
  tv.tv_sec = 1641126821;  // enter UTC UNIX time (get it from https://www.unixtimestamp.com )
  settimeofday(&tv, NULL);

  // Set timezone to France (Europe/Paris)
  setenv("TZ", "CET-1CEST,M3.5.0/2,M10.5.0/ 3", 1);
  tzset();
}

void getClock() {
  time_t now;
  struct tm timeDetails;

  time(&now);
  localtime_r(&now, &timeDetails);

  Serial.print("The current date/time is ");
  Serial.println(&timeDetails, "%A, %B %d %Y %H:%M:%S");

  strftime(timebuf, sizeof(timebuf), "%H:%M:%S", &timeDetails);
}

void timeBoxCallback(const void *parameters) {
  const ShowBoxParameters* p = reinterpret_cast<const ShowBoxParameters*>(parameters);
  display.fillRect(p->x, p->y, p->w, p->h, GxEPD_WHITE);
  display.setCursor(p->x, p->y);
  display.print(timebuf);
}

void setup() {
  Serial.begin(115200);
  Serial.println();
  
  Serial.println("initializing epaper display");
  display.init(115200);
  display.setRotation(1);
  display.setFont(&FreeMonoBold9pt7b);
  display.setFullWindow();
  display.fillScreen(GxEPD_WHITE);
  Serial.print(" display width: ");
  Serial.println(display.width());
  Serial.print("display height: ");
  Serial.println(display.height());

  Serial.println("setting time");
  settime();

  Serial.println("setup done");
}

void loop() {
  uint16_t x = 8;
  uint16_t y = 8;
  ShowBoxParameters boxParameters{x, y, 70, 20};
  
  display.setFont(&FreeMonoBold9pt7b);
  display.setTextColor(GxEPD_BLACK);
  
  display.setPartialWindow(boxParameters.x, boxParameters.y,
                           boxParameters.w, boxParameters.h);
  
  while (1) {
    getClock();
    
    display.firstPage();
    do {
      display.drawPaged(timeBoxCallback, &boxParameters);
    } while (display.nextPage());
    delay(1000);
  }
}


extern "C" void app_main() {
  setup();
  loop();
}

Running this code results in this on the display:

On the serial monitor I can see this:

initializing epaper display
 display width: 296
display height: 128
setting time
setup done
The current date/time is Sunday, January 02 2022 13:51:34
_PowerOn : 35875
_Update_Full : 1543779
_Update_Part : 353505
The current date/time is Sunday, January 02 2022 13:51:37
_Update_Part : 353516
_Update_Part : 353528
..
The current date/time is Sunday, January 02 2022 13:51:40
_Update_Part : 353456
_Update_Part : 353446
The current date/time is Sunday, January 02 2022 13:51:42
_Update_Part : 353457
_Update_Part : 353465

etc.

So, what's wrong here? The stuff which can be seen on the display looks like the top or bottom 1 or 2 pixel wide line of the printed time. If I print more (e.g. also the date), then this scattered line gets wider.

I also did not understand the positioning of the cursor. From the logical point of view one would assume, that setCursor() uses coordinates relative to the current window (or full screen if not inside a window), But whatever values I tried, nothing worked.

It would be really great if someone could help me understand this.

Thanks in advance,
Tom

Ok, I managed to fix this by postioning the y point cursor 20 pixel below y of the window in timeBoxCallback():

display.setCursor(p->x, p->y+20);

However, now that the partial update works, another problem occurs:

The numbers which have changed so far, look a liitle fuzzy.

Any idea why it looks like this?

Yes, this is the first time I see the two options for paged display used together.
Using firstPage()..nextPage() and displayCallback() combined comes unexpected, and thus is not handled appropriately in GxEPD2.

Oops, I didn't read the remaining part of your post. But you could start fixing this first issue.

Jean-Marc

Ok, I changed the primary loop to this:

  while (1) {
    getClock();
    display.drawPaged(timeBoxCallback, &boxParameters);
    while (display.nextPage());
    delay(1000);
  }

Is this the correct way to do it?

It works, but still generates these strange artifacts.

No. Remove while (display.nextPage()); if you want to use the callback method.

Consider reading GxEPD2/README.md at master · ZinggJM/GxEPD2 · GitHub.

Hi Jean-Marc,

glad to have you help, I really appreciate this :slight_smile:

So now I have it changed to:

  while (1) {
    getClock();
    display.drawPaged(timeBoxCallback, &boxParameters);
    delay(1000);
  }

Works a treat but the strange artefacts of overwritten numbers persists.

Ok, today is Sunday. You can re-post your complete code, and most likely I will try it tomorrow.

And I need to know the panel you selected to compile for, and the inking on the flex connector of your panel.

Ok, this is the whole code:


#define ENABLE_GxEPD2_GFX 0

#include <GxEPD2_BW.h>
#include <Fonts/FreeMonoBold9pt7b.h>

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

// time management
#include <Esp.h>
#include <esp_system.h>
#include <sys/time.h>

// GLOBALS
char timebuf[64];

struct ShowBoxParameters {
  uint16_t x, y, w, h;
};


void settime() {
  // set current day/time
  struct timeval tv;
  tv.tv_sec = 1641126821;  // enter UTC UNIX time (get it from https://www.unixtimestamp.com )
  settimeofday(&tv, NULL);

  // Set timezone to France (Europe/Paris)
  setenv("TZ", "CET-1CEST,M3.5.0/2,M10.5.0/ 3", 1);
  tzset();
}
void getClock() {
  time_t now;
  struct tm timeDetails;

  time(&now);
  localtime_r(&now, &timeDetails);

  Serial.print("The current date/time is ");
  Serial.println(&timeDetails, "%A, %B %d %Y %H:%M:%S");

  strftime(timebuf, sizeof(timebuf), "%H:%M:%S", &timeDetails);
}

void timeBoxCallback(const void *parameters) {
  const ShowBoxParameters* p = reinterpret_cast<const ShowBoxParameters*>(parameters);
  display.fillRect(p->x, p->y, p->w, p->h, GxEPD_WHITE);
  display.setCursor(p->x, p->y+20);
  display.println(timebuf);
}

void setup() {
  Serial.begin(115200);
  Serial.println();
  
  Serial.println("initializing epaper display");
  display.init(115200);
  display.setRotation(1);
  display.setFont(&FreeMonoBold9pt7b);
  display.setFullWindow();
  display.clearScreen();
  display.fillScreen(GxEPD_WHITE);
  Serial.print(" display width: ");
  Serial.println(display.width());
  Serial.print("display height: ");
  Serial.println(display.height());

  Serial.println("setting time");
  settime();

  Serial.println("setup done");
}

void loop() {
  uint16_t x = 0;
  uint16_t y = 0;
  uint16_t w = 120;
  uint16_t h = 30;
  ShowBoxParameters boxParameters{x, y, w, h};
  
  display.setTextColor(GxEPD_BLACK);
  display.setPartialWindow(boxParameters.x, boxParameters.y, boxParameters.w, boxParameters.h);

  while (1) {
    getClock();
    display.drawPaged(timeBoxCallback, &boxParameters);
    delay(1000);
  }
  
}

extern "C" void app_main() {
  setup();
  loop();
}

In GxEPD2_display_selection_new_style.h I selected GxEPD2_290_T5.

On the flex cable it says: WFT0290CZ10 LW

Thanks for the effort so far and I wish you a good sunday.

PS:

As far I can tell, I seem to have this board+display: https://www.waveshare.com/product/displays/e-paper/2.9inch-e-paper-module.htm, at least mine looks precisely like this. The BS jumper is set to 0 (aka 4 pin SPI). I also added the modified init() to my setup:

display.init(115200, true, 2, false);

But this didn't change anything.

And I tried every other GxEPD2_290* driver class - none of the others are working.

best,
Tom

No, I don't think so. The inking is different, this is the

//#define GxEPD2_DRIVER_CLASS GxEPD2_290_T94_V2 // GDEM029T94  128x296, SSD1680, Waveshare 2.9" V2 variant

I believe.

The GDEW029T5 and the GDEW029T5D look exactly identical, both with the inking you reported, but have different versions of the controller UC8151 vs. UC8151D.

If only one driver class works, then you have selected the correct one. But Waveshare might still use a different version with different or missing wavetable in OTP.

BTW: you could try the firstPage()..nextPage() method instead, in case the drawPaged() method is missing an addition needed by some controllers. I seldom re-check with drawPaged().

Jean-Marc

@ardunjip

Your code works fine on my GDEW029T5 when compiled for GDEW029T5.
It also works fine on my GDEW029T5D when compiled for GDEW029T5, to my surprise.
Therefore I do not know what is wrong with your display, or what panel it uses.
You should test once more with GxEPD2_Example.ino, and pay attention to the partial update tests.

I had to remove extern "C" void app_main() to compile your code with the Arduino IDE.

So I don't know what compile environment you use.
Actual versions of Arduino IDE prompt you for updates of known libraries.
As this may not happen in your environment, please report the version of GxEPD2 you use, and your compile tool.

Jean-Marc

Hello Jean-Marc,

I cannot directly use the example, since it doesn't compile (function declarations in wrong order):

../main/GxEPD2_Example.cpp:736:5: error: 'drawBitmaps3c200x200' was not declared in this scope
     drawBitmaps3c200x200();

But I have a version of the example code where I removed all the bitmap stuff and rearranged the function declarations so it compiles. Nothing else has been changed though.

However, the weird rendering of characters is the same with the example code as in mine. No difference at all.

Here's my environment:

So I work on the commandline using the IDF tool chain, e.g. idf.py build etc. I don't have the arduino IDE installed.

Tom

PS: I also tried to use the firstPage/nextPage method as you suggested earlier but this doesn't change anything.

Your environment is not supported with GxEPD2. And it looks like the panel of your display is not supported either.

Jean-Marc

Ahm, ok. So I installed the latest arduino IDE, added the esp32 core via board manager, installed the GxEPD2 library from library manager and run a couple of examples successfully (e.g. the Wifi_Scan, it works like a charm and displays networks in the console). So in general the IDE works.

Then I created a new project with my code. I did not change anything.

The project compiles and gets uploaded but it stops after display.init() no epaper and no more serial output. The same happens when I try the GxEPD2_Example. The only thing I can see in the console is:

ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371 
ets Jun  8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv: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:10944
load:0x40080400,len:6388
0x40080400: _init at ??:?

entry 0x400806b4
initializing epaper display

Then it stops.

Wiring is unchanged and I can upload my firmware using IDF as I could before, so nothing changed, here's the relevant part of the include file:

#elif defined(ARDUINO_ESP32_DEV) // e.g. TTGO T8 ESP32-WROVER
GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=4*/ 5, /*DC=*/ 13, /*RST=*/ 22, /*BUSY=*/ 19));

(note: if I add an #error "using dev board" below the elif then compilation fails at this point so I am sure it is the correct point where I defined the pinout)

Maybe the arduino IDE does something weird with pin numbering or the library crashes somehow - I don't know.

Versions being used now:

  • Arduino IDE 1.8.10
  • GxEPD2 1.4.2
  • esp32 core 1.0.6

I tried different boards "Lolin d32 pro" (the one I actually have) or "esp32 dev" (the one which gets detected) but this doesn't matter, same result.

Has anyone an idea what else I could do? Bying a new display? But how can I determine if it is supported by GXEPD2, because whereever I can order it, the display Chip is never reported?

And why does the display work when programmed via IDF (at least displaying something) but not when I use the Arduino IDE?

You need to update the package download link, then update to actual (2.0.1)

Your board may be from rejects, e.g. have a wrong RESE resistor value.

Hi Jean-Marc,

oh indeed! With 2.0.1 the display works but still shows there artifacts. So it seems nothing have to do with the build environment but the display itself.

I've read the Waveshare FAQ again and they state that the display should be set to sleep mode or power off after use - which I never did. In fact it lay 2 or 3 years in the drawer. So maybe it's just bricked.

Is there any resource where I can read more about this? Maybe I could replace the resistor myself?

Thanks a lot 4 your effort so far!

Tom

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.