ePaper display - and buttons

Hi there, i am trying to figure out the way how i would use a paper display module and buttons at the same time. I have to say that i am fairly new to C and ESP/Arduinos at all, so please dont be too harsh :wink:

the issue i am having is, that i do not quite understand the logic of "parallel" or non blocking things at the same time (i dont have the correct wording here...). I have a main thread which looks like this (as well as some other logic, but this is i guess the important stuff):

void setup(void)
{
  //...
  // Initialize graphic library
  initializeDisplay();

  // Draw splash screen
  drawSplashScreen();
  //...
}

void loop(void)
{
  drawScreen(state.currentScreen);
  checkButtons();
}

initializing the display looks like this:

void initializeDisplay()
{
  display.init(115200, true, 2, false); // USE THIS for Waveshare boards with "clever" reset circuit, 2ms reset pulse
  initDisplayRotation();
}

then i have a function wich basically gets called every loop. (i used to use a non-ePaper display before, there it worked just fine)

void updateText(const String &text, int16_t x, int16_t y)
{
  int16_t tbx, tby;
  uint16_t tbw, tbh;

  display.setFont(&FreeMonoBold9pt7b);
  display.setTextColor(GxEPD_BLACK);
  display.getTextBounds(text.c_str(), 0, 0, &tbx, &tby, &tbw, &tbh);

  display.setPartialWindow(x, y - tbh, tbw, tbh * 2);
  display.firstPage();
  do
  {
    display.fillRect(x, y - tbh, tbw, tbh * 2, GxEPD_WHITE);
    display.setCursor(x, y);
    display.print(text);
  } while (display.nextPage());
}

void drawOdometerLayout()
{
  String partial = String(memory.config.tripPartial);
  String total = String(memory.config.tripTotal);
  String heading = String(state.currentHeading);

  if (memory.config.precision == 1)
  {
    // Remove last digit
    partial.remove(partial.length() - 1);
    total.remove(total.length() - 1);
  }

  // Calculate positions and bounding boxes
  int16_t tbx, tby;
  uint16_t tbw, tbh;

  // Set up the display
  display.setFullWindow();
  display.firstPage();

  // Clear the display
  display.fillScreen(GxEPD_WHITE);

  // Draw status bar
  drawStatusBar();

  // Draw title (total distance)
  display.setFont(&FreeMonoBold9pt7b);
  display.setTextColor(GxEPD_BLACK);
  display.getTextBounds(total.c_str(), 0, 0, &tbx, &tby, &tbw, &tbh);
  int16_t title_x = (display.width() - tbw) / 2;
  display.setCursor(title_x, 28);
  display.print(total);

  // Draw heading
  display.getTextBounds(heading.c_str(), 0, 0, &tbx, &tby, &tbw, &tbh);
  int16_t heading_x = display.width() - tbw - 5;
  display.setCursor(heading_x, 28);
  display.print(heading);
  display.drawCircle(display.width() - 20, 12, 3, GxEPD_BLACK);

  // Draw partial distance
  display.getTextBounds(partial.c_str(), 0, 0, &tbx, &tby, &tbw, &tbh);
  int16_t partial_x = (display.width() - tbw) / 2;
  display.setCursor(partial_x, 63);
  display.print(partial);

  // Perform partial update on the relevant text areas only
  updateText(partial, partial_x, 63);
  updateText(total, title_x, 28);
  updateText(heading, heading_x, 28);
}

fot the buttons i use PushButton library:

here is the issue now where i dont know what the correct way is to fix it:
i assume the while ... do loop prevents the main loop to function properly and blocks the whole thing. so whenever i press a button, it only recognizes the press when i accidently hit one loop cycle and the buttons get read.

what is the way to go here and how would i update my code to have responsive buttons and a responsive (as much as possible with epaper) display?

And as a second question:
looking at this first attempt of drawing something to the epaper display, what would be the strategy to make it draw faster? Currently it feels like it needs a second or so to to each of these function calls: updateText(partial, partial_x, 63);

Any Help would be great!

thanks a lot!

Separate your code into functions.
One function reads your buttons.
One function writes to epaper.
One function (does what you want).
One function (does even more stuff).

Now that you have four functions, you will use "event timing" to call each function at a defined interval. Here is an example of calling four functions at even intervals...

unsigned long timer, interval = 1000; // event timers
int counter = 0; // a counter

void setup() {
  Serial.begin(115200); // start serial communications
}

void loop() {
  if (millis() - timer > interval) { // program has been running longer than "interval"
    timer = millis(); // store a new "time zero"

    // this depends on the number of functions you have.
    if (counter > 3) counter = 0; // check loop counter for overflow
    switch (counter) { // use counter to select the function
      case (0): { // if counter is 0
          function_0(); // call this function
          break; // exit this case
        }
      case (1): {
          function_1();
          break;
        }
      case (2): {
          function_2();
          break;
        }
      case (3): {
          function_3();
          break;
        }
    }
    counter++; // increment function counter
  }
}

void function_0() {
  Serial.print("f0 ");
}
void function_1() {
  Serial.print("f1 ");
}
void function_2() {
  Serial.print("f2 ");
}
void function_3() {
  Serial.println("f3");
}

This playlist covers the millis() function that you will use very often in your program writing.

1 Like

See also GxEPD2/examples/GxEPD2_RotaryUsingBusyCallback/GxEPD2_RotaryUsingBusyCallback.ino at master ยท ZinggJM/GxEPD2 ยท GitHub

Hi, thanks for the links! Seems quite complicated to me :wink:
Is there any other library wich already solves this problem with a better dev experience?

Cheers and thanks!

You have several options for this:

  • search through all forks of GxEPD2 or GxEPD. There are some forks that address this.
  • use the manufacturer library or demo, make sure that the refresh command is the last command before return by removing the busy wait, check in your code for busy before calling any e-paper command.
  • ...

In GxEPD2 and GxEPD the busy wait is not at the end of method calls, to allow its nice features of paged display and fast partial refresh.