I will continue to post to this thread with the sage of my EDP and GxEDP2 journey.
I and grateful to Jean-Marc Zingg for his amazing work on the GxEDP2 ePaper Library.
I purchased a Good Display 2.7" BW display for my initial exposure to ePaper.
Good Display PN GDEW027W3 + the DESPI-C02 Adapter Board.
I do have a project in mind however at the moment I'm simply trying to understand how to use the library and get some text on the screen. I started with the GxEPD example "GxEPD2_HelloWorld.ino" and was able to get the display up and running with a Pro Mini.
Now I've moved to a ESP8266 to run the "GxEPD2_NotPagedExample.ino" again with almost no problems. However I'm only a fair(or worse) C coder and a only have a hint of C++ under my belt. I'm basically a visual / graphical guy so I don't pick up somethings as quickly as others do.
So I took the "GxEPD2_NotPagedExample.ino" and pared it down to just printing text and hibernating. I've added comments for the methods used however I'm sure there are some errors. I'm posting my code (actually @ZinggJM's code) in case others.
My next goals is how to understand how the screen data goes from the µP memory to the display IC (with two buffers) to the screen. I expect this has something to do with the writeImageAgain method.
/* Based on "GxEPD2_NotPagedExample.ino" a display Library example for SPI e-paper panels from Dalian Good Display
and boards from Waveshare.
Requires HW SPI and Adafruit_GFX. Caution: the e-paper panels require 3.3V supply AND data lines!
Author: Jean-Marc Zingg
______________________________________________________________________________________________________
This file is a pared down version of "GxEPD2_NotPagedExample.ino". All code except that needed
to display some text in the middle of the display has been removed. My goal is to simplify
the code allowing a better understanding of the functions needed to display text.
This file is for use with an esp32 or esp8266. I've only tested it on an esp8266 (NodeMCU)
All the compiler "#if defined" statements have been removed for clarity (mine) with the decisions for
the esp8266 and GDEW027W3 display.
CAUTION: my line by line comments probably have some errors.
EPD = electronic paper display aka e-Paper
Program function: Display "text_01" in the center of the screen then hibernate.
todo: These are just programming, little to do with how the display works.
1) Modify the "displayText()" procedure to accept text pointer.
2) Modify the "displayText()" procedure to accept coordinates and / or descriptors. i.e. center, center left, top left, bottom left etc
3) Modify the "displayText()" procedure to accept different fonts.
*/
// 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
// uncomment next line to use class GFX of library GFX_Root instead of Adafruit_GFX
//#include <GFX.h>
// Note: if you use this with ENABLE_GxEPD2_GFX 1:
// uncomment it in GxEPD2_GFX.h too, or add #include <GFX.h> before any #include <GxEPD2_GFX.h>
#include <GxEPD2_BW.h> // in this file you must find the #include for your display and uncomment it.
//#include <GxEPD2_3C.h>
#include <Fonts/FreeMonoBold9pt7b.h>
#include <StreamString.h> // Apparently needed to "Print" to the screen. Seems to be special for the ESP8266
// or at least different
#define PrintString StreamString // guess this is only a name change (for clarity?)
// Constructor: creates an EPD object named "display"
// select one and adapt to your mapping, can use full buffer size (full HEIGHT)
GxEPD2_BW<GxEPD2_270, GxEPD2_270::HEIGHT> display(GxEPD2_270(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
void setup()
{
// for output to IDE Serial monitor
Serial.begin(115200);
Serial.println();
Serial.println("setup");
delay(100);
display.init(115200); // the init fcn simply sends a low pulse to display board rst line.
// This is the only way to wake the display IC from hibernation.
// first update should be full refresh
displayText();
delay(1000);
// partial refresh mode can be used to full screen,
// effective if display panel hasFastPartialUpdate
// helloFullScreenPartialMode();
delay(10000);
display.powerOff();
//deepSleepTest();
Serial.println("setup done");
}
void loop() { }
// note for partial update window and setPartialWindow() method:
// partial update window size and position is on byte boundary in physical x direction
// the size is increased in setPartialWindow() if x or w are not multiple of 8 for even rotation, y or h for odd rotation
// see also comment in GxEPD2_BW.h, GxEPD2_3C.h or GxEPD2_GFX.h for method setPartialWindow()
const char text_01[] = "Good Display 2.7\"";
const char hibernating[] = "hibernating ...";
const char again[] = "again";
void displayText()
{
display.setRotation(1);
display.setFont(&FreeMonoBold9pt7b);
display.setTextColor(GxEPD_BLACK);
int16_t tbx, tby; uint16_t tbw, tbh;
display.getTextBounds(text_01, 0, 0, &tbx, &tby, &tbw, &tbh); // send a textarray, originx, originy returns the center point of the text and
// the height & width at the previously defined font... I think?
// center bounding box by transposition of origin:
uint16_t x = ((display.width() - tbw) / 2) - tbx;
uint16_t y = ((display.height() - tbh) / 2) - tby;
// full window mode is the initial mode, set it anyway
display.setFullWindow(); // setspartial_mode = false; sets the screen x,y = 0 and height & width to display max
display.fillScreen(GxEPD_WHITE);
display.setCursor(x, y);
display.print(text_01); // writes text_01 in the controllers memory.
display.display(false); // screen will not change until this command is made.
// with partial update = false. display buffer content to screen, useful for full screen buffer
// not sure which buffer is in play here. µP or the display IC buffer(s)
delay(5000);
display.getTextBounds(hibernating, 0, 0, &tbx, &tby, &tbw, &tbh);
uint16_t hx = (display.width() - tbw) / 2;
uint16_t hy = (display.height() / 3) + tbh / 2; // y is base line!
display.getTextBounds(again, 0, 0, &tbx, &tby, &tbw, &tbh);
uint16_t ax = (display.width() - tbw) / 2;
uint16_t ay = (display.height() * 2 / 3) + tbh / 2; // y is base line!
display.fillScreen(GxEPD_WHITE);
display.setCursor(hx, hy);
display.print(hibernating);
display.setCursor(ax, ay);
display.print(again);
display.display(false);
display.hibernate(); //turns powerOff() and sets controller to deep sleep for minimum power use, ONLY if wakeable by RST (rst >= 0)
// here powerOff() = turns off generation of panel driving voltages, avoids screen fading over time
}