GxEPD2 epaper and ESP8266 deep sleep

I'm using the GxEPD2 library for a black/white 2.9" Waveshare epaper v2 display. I was able to get the display drawn properly, including some lines and custom fonts. My first iteration did the basic drawing in setup() and then in loop() I would use display.setPartialWindow() to update three partial areas every five minutes. Worked great, but the ESP8266 had to be constantly plugged in. I refactored the code so that all the display interaction ran within setup() and then the ESP would deep sleep for five minutes. When I deployed this new code, the initial cold start drawing all worked properly, but when the display woke up from deep sleep and tried to use display.setPartialWindow() the epaper became a screen full of static.

I was able to trim down the code I'm using to something that is as bare-bones as I can make it while still demonstrating the issue:

#include <Arduino.h>
#include <GxEPD2_BW.h>
#include <user_interface.h>
#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/FreeSansBold9pt7b.h>
#include "GxEPD2_display_selection_new_style.h"

struct {
  uint8_t startup_count;
  bool clean_start;
} startup_data;

uint32_t sleep_interval = 180e6;
uint16_t max_starts_between_refresh = 3;

void setup()
{
  pinMode(D0, WAKEUP_PULLUP);
  Serial.begin(74880);
  Serial.setTimeout(2000);
  while (!Serial) { }

  ESP.rtcUserMemoryRead(0, (uint32_t *)&startup_data, sizeof(startup_data));
  rst_info *r_info = ESP.getResetInfoPtr();

  if ((*r_info).reason == 6 || startup_data.startup_count >= max_starts_between_refresh)
  {
    startup_data.startup_count = 1;
    startup_data.clean_start = true;
  }

  display.init(74880, startup_data.clean_start, 2, false);
  display.setRotation(1);
  display.setTextColor(GxEPD_BLACK);

  if (startup_data.clean_start)
  {
    display.firstPage();
    do {
      display.setFont(&FreeSans9pt7b);
      display.fillScreen(GxEPD_WHITE);
      display.setCursor(1, 17);
      display.print("Today is ");

      display.setFont(&FreeSansBold9pt7b);
      display.setCursor(1, 45);
      display.print("Happening Now:");
      display.setCursor(display.width() / 2, 45);
      display.print("Up Next:");
    } while (display.nextPage());
  }

  display.setPartialWindow(display.width() / 2, 0, display.width() / 2, 20);
  display.firstPage();
  do {
    display.setCursor(display.width() / 2, 17);
    display.setFont(&FreeSans9pt7b);
    display.print(millis());
  } while (display.nextPage());

  startup_data.startup_count += 1;
  startup_data.clean_start = false;
  ESP.rtcUserMemoryWrite(0, (uint32_t *)&startup_data, sizeof(startup_data));

  display.powerOff();
  delay(1000);
  ESP.deepSleep(sleep_interval);
}

void loop () { }

On this code, the initial startup displays just fine; the next time it wakes from sleep, it turns to static, and it continues to be static until after three wake cycles, at which point I force it to redraw the entire screen and it fixes itself again.

Some additional troubleshooting I've done on here was trying to track down where in the code the static actually happens - seems like as soon as I use setPartialWindow(), that's the issue - even if I do a full-screen partial display (eg. display.setPartialWindow(0, 0, display.width(), display.height())). If I omit the partial window and just let it wake up and go to sleep again, the screen doesn't have any issues (I thought perhaps there was some electrical noise involved in waking up that was causing it to mess up).

My guess is there's something about the ESP8266 waking up and how I'm initing the display that's causing issues?

What it normally looks like:

What it looks like when waking from deep sleep:

I did notice this when hovering over the init() method:

initial false for re-init after processor deep sleep wake up, if display power supply was kept this can be used to avoid the repeated initial full refresh on displays with fast partial update NOTE: garbage will result on fast partial update displays, if initial full update is omitted after power loss

So would I be correct that there is no way to combine deep sleep and partial updates?

@tmountjr, Hi, welcome to the forum!

Try with a 1k pull-up resistor on the RST line to the display.

The "clever" reset circuit of the Waveshare display board switches off supply completely, if RST is not actively pulled up. The ESP8266 can't do that during deep sleep.
-jz-

I will try that. Any code changes necessary or just drop a resistor between RST and 3v3? Do I need to adjust the init parameters? I see the last parameter is pulldown_rst_mode which is false - assume that stays the same since this is a pullUP?

No code change needed. pulldown_rst_mode is obsolete, was never really needed, as that interim Waveshare board had a diode to RST of the controller (it had not enough level converter channels).

So that worked like a charm on my test script! I'll re-upload the full script just to make sure but things are looking good.

The pullup was the key, i've got it waking up every 5m and refreshing itself just fine. I suppose I still have to try this on battery power rather than USB power but hopefully it won't make a difference.

Now has come the time to point you to the DESPI-C02.
I recommend this with bare panel for low power use with 3.3V processors.
Or search for a display module without level converters, with just the booster circuit for panel driving voltages.
-jz-

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