GxEPD2_PP : Particle Display Library for SPI E-Paper Displays


#41

@Norfeldt I left only temporarily, and as I get informed about posts to this topic per mail, I am ready for answers.

You didn’t tell me if the published library GxEPD2_PP works for you. Are there issues? How do you use it?

I can only improve if I get feedback, with as complete information as possible.

I just need to start up a noisy notebook if I need to use Particle CLI, everything else is ok on the mini PC box I use for work with Particle.


#42

@ZinggJM :grinning: Glad to hear you haven’t given up on it!

I decided to clear my code and start from scratch since you might have updated the code.

I have imported the Adafruit_GFX_RK (1.3.5) library, but when I trie to import the GXEPD2_PP it just hangs on “Loading…” all the time.

It did not do this when I tried it before Christmas.


#43

I had the same problem with the WEB-IDE. I had to set the browser to clear cache on exit, then exit the browser and start again. This worked for me. And it worked again just now, on my Acer notebook with the noisy fan.

I created a new project in the WEB-IDE, loaded library GxEPD2_PP, added it to my new project, loaded GxEPD2_PP again, opened GxEPD2_PP_Example, selected all, and replaced the code of the new project with the selection, and clicked Verify. Verified successfully.

I don’t know if this is the standard way to use library examples for test. But this is how I tried to verify GxEPD2_PP.

Suggestions for testing are welcome.


#44

@ZinggJM I set cleared the cache on exit (tried first to clear it, close and open) for
https://build.particle.io and it worked!

I’m testing it right now.


#45

@ZinggJM Here are some of the results so far

I used your example code from https://github.com/ZinggJM/GxEPD2_PP/blob/master/examples/GxEPD2_PP_Example/src/GxEPD2_PP_Example.ino

Did the following changes

#include <Arduino.h>
#include <Adafruit_GFX.h>
#include <FreeSerifBoldItalic18pt7b.h> // ADDED
#include <FreeMonoBold9pt7b.h>

(changed the setFont to FreeSerifBoldItalic18pt7b where applicable)

#if defined(PARTICLE)
// select one and adapt to your mapping, for buffered drawing, can use full buffer size (full HEIGHT) for Photon
//GxEPD2_BW<GxEPD2_154, GxEPD2_154::HEIGHT> display(GxEPD2_154(/*CS=D5*/ SS, /*DC=*/ A1, /*RST=*/ A0, /*BUSY=*/ D4));
..
//GxEPD2_3C<GxEPD2_583c, GxEPD2_583c::HEIGHT / 4 > display(GxEPD2_583c(/*CS=D5*/ SS, /*DC=*/ A1, /*RST=*/ A0, /*BUSY=*/ D4));
GxEPD2_3C<GxEPD2_750c, GxEPD2_750c::HEIGHT / 4 > display(GxEPD2_750c(/*CS=D5*/ SS, /*DC=*/ A1, /*RST=*/ A0, /*BUSY=*/ D4));
#endif

// comment out unused bitmaps to reduce code space used
// #include "bitmaps/Bitmaps200x200.h" // 1.54" b/w
// #include "bitmaps/Bitmaps128x250.h" // 2.13" b/w
// #include "bitmaps/Bitmaps128x296.h" // 2.9"  b/w
// #include "bitmaps/Bitmaps176x264.h" // 2.7"  b/w
// #include "bitmaps/Bitmaps400x300.h" // 4.2"  b/w
//#include "bitmaps/Bitmaps640x384.h" // 7.5"  b/w // can't select together with the others for Photon
// 3-color
// #include "bitmaps/Bitmaps3c200x200.h" // 1.54" b/w/r
// #include "bitmaps/Bitmaps3c104x212.h" // 2.13" b/w/r
// #include "bitmaps/Bitmaps3c128x296.h" // 2.9"  b/w/r
// #include "bitmaps/Bitmaps3c176x264.h" // 2.7"  b/w/r
#include "bitmaps/Bitmaps3c400x300.h" // 4.2"  b/w/r

As you can see there seems to be some issue with the Hello Android and Hello E-Paper.


Is this a correct understanding of the following

void helloWorld()
{
  //Serial.println("helloWorld");
  display.setRotation(1);
  display.setFont(&FreeSerifBoldItalic18pt7b);
  display.setTextColor(GxEPD_BLACK);
  uint16_t x = (display.width() - 160) / 2;
  uint16_t y = display.height() / 2;
  display.setFullWindow();
  display.firstPage();
  do
  {
    display.fillScreen(GxEPD_WHITE);
    display.setCursor(x, y);
    display.println("Hello World!");
  }
  while (display.nextPage());
  //Serial.println("helloWorld done");
}

The display.firstPage() triggers some sort of async function that returns True when calling display.nextPage() for some period of time and then when ready (display print finish) it returns False and can exit the loop?


It’s not drawing any bitmaps. So uncommented this section back to the original setup.

// comment out unused bitmaps to reduce code space used
#include "bitmaps/Bitmaps200x200.h" // 1.54" b/w
#include "bitmaps/Bitmaps128x250.h" // 2.13" b/w
#include "bitmaps/Bitmaps128x296.h" // 2.9"  b/w
#include "bitmaps/Bitmaps176x264.h" // 2.7"  b/w
#include "bitmaps/Bitmaps400x300.h" // 4.2"  b/w
//#include "bitmaps/Bitmaps640x384.h" // 7.5"  b/w // can't select together with the others for Photon
// 3-color
#include "bitmaps/Bitmaps3c200x200.h" // 1.54" b/w/r
#include "bitmaps/Bitmaps3c104x212.h" // 2.13" b/w/r
#include "bitmaps/Bitmaps3c128x296.h" // 2.9"  b/w/r
#include "bitmaps/Bitmaps3c176x264.h" // 2.7"  b/w/r
#include "bitmaps/Bitmaps3c400x300.h" // 4.2"  b/w/r

Now some of the logo bitmaps are back

I would LOVE to print some of my own photos onto the display.


#46

To answer your questions:

  1. I was referring to the GxEPD2_PP library.
  2. I am not well placed to help you with published libraries as I have not published anything yet.

I am using the Web IDE. Typically I include a library in my project sometimes I copy and recreate the files and change them. I also use VSC (for the better editor) but not at the moment with the Particle extensions - waiting for a good beta version.

I originally asked if anyone knew of a library to drive e-paper displays and @peekay123 referred me to your Arduino github GxEPD library. I then found the GxEPD2 library. I figured out how it fitted together copied the files I needed and created .h and .cpp files in the Web IDE as needed. I then stripped out all the Arduino related stuff that is not necessary in the Particle space and worked through the compile errors until it compiled and then I flashed to a test Photon wired up to a 2.13" 3 colour display.


#47

@armor

BTW, the library you have posted does not build in the IDE without changes - the #includes do not need “…epd/”.

I do not understand this, as it works for me with the WEB-IDE.


#48

Yes, there is an issue with missing clipping of drawing to a partial window. See

The display.firstPage() triggers some sort of async function that returns True when calling display.nextPage() for some period of time and then when ready (display print finish) it returns False and can exit the loop?

display.firstPage() simply sets the graphics class to paged mode. Nothing asynchronous involved.

display.nextpage() transfers the buffer content - the page - to the controller. For the last page the controller is ordered to refresh the screen. For displays with “fast partial update” aka differential update, there is as second round to make both controller buffers have the same content. Then false is returned.

It’s not drawing any bitmaps. So uncommented this section back to the original setup.

Don’t understand what you mean. Aha, you had selected the wrong bitmaps for your b/w display:

#include "bitmaps/Bitmaps3c400x300.h" // 4.2"  b/w/r

These are the bitmaps for your display:

#include "bitmaps/Bitmaps640x384.h" // 7.5"  b/w // can't select together with the others for Photon

These bitmaps are drawn to any display, if uncommented:

 #include "bitmaps/Bitmaps200x200.h" // 1.54" b/w


#49

Okay, I read it like I could pick different sizes (since the 200x200 worked on my 7.5"). I tried the b/w for 7.5" and it works perfect! I can live without the red color - perhaps I can print some red text instead.

Suppose I wish to print a custom logo like this:

customLogo

How would I go about that? Let’s start with just adding it as a file that is falshed to the device.

BMP file can be downloaded from here:


Okay - I think I understand it. So it actually only goes 1 iteration in the helloWorld().

Then in the helloFullScreenPartialMode() the if statements makes calls to the display telling it that it needs to do more iteration before the last page is reached.
So display.epd2.hasFastPartialUpdate returns True once (things are added to the buffer) and then in the next iteration it returns False. Then it comes to display.epd2.hasPartialUpdate that sorta does the same thing to get another iteration.

Right?



#50

Nope

display.epd2.hasFastPartialUpdate is an attribute. It is true for displays with a controller that supports differential update and uses a wavetable for “fast partial update”, that uses only phases for differences.

I add a function helloWorldForDummies() to GxEPD2_Example in the next release of GxEPD2, and later to GxEPD2_PP:

void helloWorldForDummies()
{
  //Serial.println("helloWorld");
  // most e-papers have width < height (portrait) as native orientation, especially the small ones
  // in GxEPD2 rotation 0 is used for native orientation (most TFT libraries use 0 fix for portrait orientation)
  // set rotation to 1 (rotate right 90 degrees) to have enough space on small displays (landscape)
  display.setRotation(1);
  // select a suitable font in Adafruit_GFX
  display.setFont(&FreeMonoBold9pt7b);
  // on e-papers black on white is more pleasant to read
  display.setTextColor(GxEPD_BLACK);
  // not really centered, but allmost, should be improved
  uint16_t x = (display.width() - 160) / 2;
  uint16_t y = display.height() / 2;
  // full window mode is the initial mode, set it anyway
  display.setFullWindow();
  // here we use paged drawing, even if the processor has enough RAM for full buffer
  // so this can be used with any supported processor board.
  // the cost in code overhead and execution time penalty is marginal
  // tell the graphics class to use paged drawing mode
  display.firstPage();
  do
  {
    // this part of code is executed multiple times, as many as needed,
    // in case of full buffer it is executed once
    // IMPORTANT: each iteration needs to draw the same, to avoid strange effects
    // use a copy of values that might change, don't read e.g. from analog or pins in the loop!
    display.fillScreen(GxEPD_WHITE); // set the background to white (fill the buffer with value for white)
    display.setCursor(x, y); // set the postition to start printing text
    display.println("Hello World!"); // print some text
    // end of part executed multiple times
  }
  // tell the graphics class to transfer the buffer content (page) to the controller buffer
  // the graphics class will command the controller to refresh to the screen when the last page has been transferred
  // returns true if more pages need be drawn and transferred
  // returns false if the last page has been transferred and the screen refreshed for panels without fast partial update
  // returns false for panels with fast partial update when the controller buffer has been written once more, to make the differential buffers equal
  // (for full buffered with fast partial update the (full) buffer is just transferred again, and false returned)
  while (display.nextPage());
  //Serial.println("helloWorld done");
}


#51

:man_facepalming: sorry! I wasn’t paying attention to what was actually printed to the screen.

I think it was because I imagined that partial/differential update was to be used when you only want some parts of the screen to update while other parts (like logo) should be untouched.


:hugs: Thank you for adding something to us newbies. I appreciate it :hugs:


BTW: I updated the .BMP file because I forgot to convert it to greyscale.


#52

Yes, this is true. With “fast partial update” you have pure differential flicker free refresh in addition. And some displays without “fast partial update” flicker only in the partial window, whereas others flicker the whole screen even with partial update. See https://github.com/ZinggJM/GxEPD2/blob/master/MyEPDs_UpdateInfos.pdf