GxEPD2_PP : Particle Display Library for SPI E-Paper Displays


#94

So I’ve been playing around with this library for a couple of days now, and am sufficiently stumped as to how to get it to do what I want.

Goals:

  • Display Full screen Images
  • Display different sized text in the same update
  • Show some text inverted in a configurable sized section with “normal” text
  • Completely clear the display
  • Full buffer drawing

This is what I have now, using the 2.9" Waveshare display. Any help would be greatly appreciated.

#include <Adafruit_GFX_RK.h>
#include <GxEPD2_PP.h>

// base class GxEPD2_GFX can be used to pass references or pointers to the display instance as parameter, uses ~1.2k more code
// enable or disable GxEPD2_GFX base class
#define ENABLE_GxEPD2_GFX 0

#include <Arduino.h>
#include <Adafruit_GFX.h>
#include <FreeMonoBold9pt7b.h>
#include <FreeMono12pt7b.h>
// #include "imagedata.h"

#include <GxEPD2_BW.h>
#include <GxEPD2_3C.h>

GxEPD2_BW<GxEPD2_290, GxEPD2_290::HEIGHT> display(GxEPD2_290(/*CS=A2*/ SS, /*DC=*/ A1, /*RST=*/ A0, /*BUSY=*/ A4));
// GxEPD2_BW<GxEPD2_290_T5, GxEPD2_290_T5::HEIGHT> display(GxEPD2_290_T5(/*CS=A2*/ SS, /*DC=*/ A1, /*RST=*/ A0, /*BUSY=*/ A4)); // GDEW029T5

#include "bitmaps/Bitmaps128x296.h" // 2.9"  b/w

const char HelloWorld[] = "Hello World!";
const char HelloArduino[] = "Hello Arduino!";
const char HelloEpaper[] = "Hello E-Paper!";

void setup()
{
  Serial.begin(115200);
  Serial.println();
  Serial.println("setup");
  delay(100);
  display.init(115200);
  display.clearScreen();
  display.writeScreenBuffer();
  delay(1000);
  drawBitmaps128x296();
  drawBitmaps128x296();
  display.clearScreen();
  display.writeScreenBuffer();
  delay(1000);
}

void loop()
{
  //Serial.println("helloArduino");
  display.setRotation(1);
  display.setFont(&FreeMonoBold9pt7b);
  display.setTextColor(GxEPD_BLACK);
  int16_t tbx, tby; uint16_t tbw, tbh;
  // align with centered HelloWorld
  display.getTextBounds(HelloWorld, 0, 0, &tbx, &tby, &tbw, &tbh);
  uint16_t x = ((display.width() - tbw) / 2) - tbx;
  // height might be different
  display.getTextBounds(HelloArduino, 0, 0, &tbx, &tby, &tbw, &tbh);
  uint16_t y = ((display.height() / 4) - tbh / 2) - tby; // y is base line!
  // make the window big enough to cover (overwrite) descenders of previous text
  uint16_t wh = FreeMonoBold9pt7b.yAdvance;
  uint16_t wy = (display.height() / 4) - wh / 2;
  display.setFullWindow();
  // display.setPartialWindow(8, wy, display.width(), wh);
  display.firstPage();
  do
  {
    display.fillScreen(GxEPD_WHITE);
    //display.drawRect(x, y - tbh, tbw, tbh, GxEPD_BLACK);
    display.setCursor(x, y);
    display.print(HelloArduino);
    display.setCursor(x - 40 , y + 80);
    display.print(HelloEpaper);
    display.setFont(&FreeMono12pt7b);
    display.setCursor(x + 40 , y + 60);
    display.print(HelloWorld);
  }
  while (display.nextPage());
  delay(5000);
  display.setFullWindow();
  display.fillScreen(GxEPD_WHITE);
  display.firstPage();
  do
  {
    display.fillScreen(GxEPD_WHITE);
    //display.drawRect(x, y - tbh, tbw, tbh, GxEPD_BLACK);
    display.setCursor(x, y + 20);
    display.print(HelloWorld);
  }
  while (display.nextPage());
  delay(5000);
}

void drawBitmaps128x296()
{
  const unsigned char* bitmaps[] =
  {
    Bitmap128x296_1, logo128x296, first128x296, second128x296, third128x296
  };
  bool m = display.mirror(true);
  for (uint16_t i = 0; i < sizeof(bitmaps) / sizeof(char*); i++)
  {
    display.firstPage();
    do
    {
      display.fillScreen(GxEPD_WHITE);
      display.drawInvertedBitmap(0, 0, bitmaps[i], display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_BLACK);
    }
    while (display.nextPage());
    delay(2000);
  }
  display.mirror(m);
}

#95

Display different sized text in the same update

You need to #include all fonts you want to use, and use display.setFont() to select the active font.

Show some text inverted in a configurable sized section with “normal” text

Draw a black rectangle, and write the text over it with GxEPD_WHITE.

Full buffer drawing

Read the README.MD
GxEPD2 has an example: https://github.com/ZinggJM/GxEPD2/tree/master/examples/GxEPD2_NotPagedExample


#96

It looks like using the full buffer has solved my issue with images, and the alternating displays in my loop(). The formatting of the README makes it harder to understand what I needed to do, since bullet points are breaking up sentences and interrupting the flow.

The only thing I still can’t figure out is how to completely clear the display.
This sequence displays the second last image shown at startup, then goes through the bitmap list and my custom logo, then completely clears the display before going into the main loop().

void setup()
{
  Serial.begin(115200);
  delay(100);
  display.init(115200);
  // display.setFullWindow();
  // display.clearScreen();
  display.fillScreen(GxEPD_WHITE);
  display.display(false);
  // display.fillScreen(GxEPD_WHITE);
  // display.display(false);
  delay(5000);
  drawBitmaps128x296();
  drawlogo();
  display.fillScreen(GxEPD_WHITE);
  display.display(false);
  delay(5000);
}

Why isn’t the display blank for 5 seconds before going into drawBitmaps(), but it is after draw logo?


#97

I wouldn’t expect this with display.display(false); maybe with display.display(true);

Unfortunately it takes time for me to make a system ready for testing with Particle. I only have a system ready for tests with Arduino. So I may test and answer in 2 to 3 days maybe.


#98

I confirm that this doesn’t work with neither the published version of this library, nor the version on GitHub.

The library lags behind the GxEPD2 library for Arduino.

from README.MD of GxEPD2_PP:

Version 1.1.0

  • corresponds to GxEPD2 Version 1.1.6
  • added support for GDEH0213B72 2.13" b/w, replacement for GDE0213B1

from README.MD of GxEPD2:

Version 1.1.8

  • fix for incomplete download in GxEPD2_WiFi_Example
  • added missing method displayWindow() to GxEPD2_GFX base class
  • fix and clean up of initial refresh for panels with differential update
  • initial refresh needs to be full update, not “fast partial update”, for these panels,
  • as the screen content may differ from the “previous buffer” content.
  • add clean of controller buffer(s) on initial write to controller, for partial update.

Version 1.1.7

  • enhanced support for full buffered, non-paged use, for processors with enough RAM
  • use void display(bool partial_update_mode = false); corresponds to update() in GxEPD
  • use added void displayWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
  • use added writeImagePart(…), drawImagePart(…), used by displayWindow()
  • added example GxEPD2_NotPagedExample.ino
  • several fixes, e.g. parameter range check in setPartialWindow()

The version of GxEPD2 published for Particle also does not have these fixes.

I will update the versions for Particle, but don’t know yet when I have time for this.
Updating the versions is not the problem, but testing takes time.

Don’t use display.display() with this version, for e-papers with “fast partial update”.
Use at least one full update before using partial update (like in the example).
Use a partial update to full screen equal to the initial full update, before using partial updates.

Sorry for the inconvenience, my Arduino libraries are more important for me and for most users.

Note that the GxEPD2 version on GitHub can be used with Particle as private library (untested for Particle). The examples for Particle are in directory “extras”.


#99

Perhaps I’m misunderstanding the example; but when I copied the Hello World code over into my project, and condensed it down to what I believe I needed, I’m still getting a similar problem. This time I still get the second last image shown instead of a blank screen, and I also get another 5 seconds of the last image shown before going into drawbitmaps().

void setup()
{
  Serial.begin(115200);
  delay(100);
  display.init(115200);
  display.setFullWindow();
  display.firstPage();
  do
  {
    display.fillScreen(GxEPD_WHITE);
  }
  while (display.nextPage());
  delay(2000);
  drawBitmaps128x296();
  drawlogo();
  display.fillScreen(GxEPD_WHITE);
  display.display();
  delay(2000);
  fontDemo();
}

#100

I confirm this also, but I have no idea why. I have checked that the example works, so this should work also. I have currently no time to investigate further.


#101

// mapping suggestion from Waveshare SPI e-Paper to Particle Photon
// A5 MOSI
// A4 MISO
// A3 SCK
// A2 SS
// BUSY -> D4, RST -> A0, DC -> A1, CS -> A2, CLK -> A3, DIN -> A5, GND -> GND, 3.3V -> 3.3V
// NOTE: it looks like MISO can’t be used as general input pin for BUSY.

// NOTE: it looks like MISO can’t be used as general input pin for BUSY.

It works with my Photon, if I use the constructor from my example:

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

If BUSY doesn’t work, transfer from graphics buffer to controller buffer may fail, causing the effect.

You should always observe diagnostic output in Serial Monitor, but this doesn’t work well with Particle, as it disconnects from USB during upload.

I don’t like this environment.


#102

One way to deal with that would be using an autoconnecting terminal or

particle serial monitor --follow

#103

Thank you for your answer. But I am really not fluent with Particle use, so at first sight I don’t understand

particle serial monitor --follow

But ok, this is for a command window, a command to Particle CLI.


#104

Please note that I will no longer watch this topic (muted), as I don’t like to get alarmed by e-mails.
I simply do not have the capacity to support e-paper use on more than one environment.
Use the Arduino Forum Display for any question concerning my libraries, and I will try to answer there.
https://forum.arduino.cc/index.php?topic=487007.new#new


#105

Not sure if this serves any point as the author has effectively killed this thread.

But for the record switching BUSY to D4 fixed my initial clearing issue, not that this helps me too much as my PCBs are already fabbed using A4.


#106

Sucks he stopped working on this platform.

So what device and display were you having issues with exactly?


#107

I don’t think he actually meant he’d stop working on it, he’s just not actively monitoring this thread anymore.
Instead he invites people to tag him on the Arduino forum instead - and I suppost he’ll still monitor his GitHub repo


#108

I took that as he only plans on working on the Arduino library and does not have the Time or desire to support the Particle platform any longer.

So it sounds to me like we will just have to solve any Arduino library to Particle library issues ourself unless he has a change of heart :heart:


#109

Yes, I just only randomly take a look at this thread. I also have disabled issues on all my GitHub repositories, as they were also used for asking questions, ignoring my issue template.


#110

GxEPD2 should be usable also for Particle. There is an example for Particle in the extras folder on GitHub.
I will publish GxEPD2 for Particle from time to time, but you can also just upload GxEPD2 as a private library (delete the examples folder first, and replace it with the example folder from extras/Particle).


#111

I will update GxEPD2_PP one last time, after I have done the next version of GxEPD2.
Thereafter GxEPD2_PP will no longer be supported.

I think I will start a new thread for GxEPD2 in this forum, as soon as the next version of GxEPD2 is ready.


#112

This thread is discontinued by the author/creator. It is replaced by:


closed #113