Waveshare e-paper displays with SPI

I am using SparkFun babysitter with 5000mAh battery, Waveshare e-paper ESP8266 driver board and Waveshare 7.5" 3C e-Paper. Instead of using standard SDA and SCL pins, I am using 2 as SCL and 4 as SDA i.e. Wire.begin(4,2); which works fine.

But problem appears when I use display.print(HelloWorld); because of pin mapping in

GxEPD2 DC=4

GxEPD2_3C<GxEPD2_750c, GxEPD2_750c::HEIGHT / 4> display(GxEPD2_750c(/CS=15/ SS, /DC=4/ 4, /RST=5/ 5, /BUSY=16/ 16));


Shall I change DC to some other pin, I have tried but it shows in serial 

_PowerOn=9
_FullUpdate=10
_PowerOff=1

and doesn't print over to display. If I change `DC=4` then display works fine but I can't get communicate with SparkFun babysitter via `SDA (4)`.

Is there any way to move DC mapping to another pin for display?

@Shrzpk,

Good you found the right place to ask this question; you have a strange "Particle".

Waveshare chose to connect the DC line to the e-paper display to pin D4 of the ESP8266.

There is no chance to modify this in SW; you would need to cut traces and re-wire this line.

Search for a SW I2C implementation, but you would still be short of pins on ESP8266.

Jean-Marc

Thanks ZinggJM for the prompt reply.

Now I do undertand this and wants to get suggestion for the alternative SCL pin from ESP8266.

Unfortunately, i have damaged the pin D1(GPIO5) by one mistake and can't use for SCL communication.

Shall I change SCL from pin D4(GPIO2) to pin D7(GPIO13) or any other pin you suggest, as this can be change in software?

Shrzpk:
Thanks ZinggJM for the prompt reply.

Now I do undertand this and wants to get suggestion for the alternative SCL pin from ESP8266.

Unfortunately, i have damaged the pin D1(GPIO5) by one mistake and can't use for SCL communication.

Shall I change SCL from pin D4(GPIO2) to pin D7(GPIO13) or any other pin you suggest, as this can be change in software?

GPIO13 is not free! As I wrote, you are short of pins!

// mapping of Waveshare e-Paper ESP8266 Driver Board
// BUSY -> GPIO16, RST -> GPIO5, DC -> GPIO4, CS -> GPIO15, CLK -> GPIO14, DIN -> GPIO13, GND -> GND, 3.3V -> 3.3V
// NOTE for ESP8266: using SS (GPIO15) for CS may cause boot mode problems, use different pin in case

I can't help you with this.

Hey guys,

@ZinggJM thanks for your wonderful work, I'm working on a small project using 4.2-inch EPD-BW, I'm splitting my project into different CPP files. But now I'm struggling with ERRORS, I know that I'm making some stupid mistake. Looking for your suggestions regarding my mistake.

I'm trying to find out how can I call display(EPD) in different .cpp files.

Her I have displayed my ERROR:

MKRFULL:9:61: error: redefinition of 'GxEPD2_BW<GxEPD2_420, 300> display'

GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> display(GxEPD2_420(/*CS=5*/ 5, /*DC=*/ 4, /*RST=*/ 3, /*BUSY=*/ 2));

                                                           ^

In file included from F:\Psitron Technologies\CONF DOC\R&D LoRa\WordWarp\MKRFULL\MKRFULL.ino:5:0:

sketch\display.h:6:49: note: 'GxEPD2_BW<GxEPD2_420, 300> display' previously declared here

extern GxEPD2_BW<GxEPD2_420,GxEPD2_420::HEIGHT> display(GxEPD2_420(/*CS=5*/ 5, /*DC=*/ 4, /*RST=*/ 3, /*BUSY=*/ 2));

                                               ^~~~~~~

bitmap.cpp:8:61: error: redefinition of 'GxEPD2_BW<GxEPD2_420, 300> display'

GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> display(GxEPD2_420(/*CS=5*/ 5, /*DC=*/ 4, /*RST=*/ 3, /*BUSY=*/ 2));

                                                           ^

In file included from sketch\bitmap.cpp:5:0:

sketch\display.h:6:49: note: 'GxEPD2_BW<GxEPD2_420, 300> display' previously declared here

extern GxEPD2_BW<GxEPD2_420,GxEPD2_420::HEIGHT> display(GxEPD2_420(/*CS=5*/ 5, /*DC=*/ 4, /*RST=*/ 3, /*BUSY=*/ 2));

                                               ^~~~~~~

Her is my MKRFULL.ino file

#include <Arduino.h>
#include "bitmap.h"
#include <GxEPD2_BW.h>
#include <GxEPD2_3C.h>
#include "display.h"

#include <Fonts/FreeSansBold9pt7b.h>

GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> display(GxEPD2_420(/*CS=5*/ 5, /*DC=*/ 4, /*RST=*/ 3, /*BUSY=*/ 2));

void setup() {

Serial.begin(115200);  
display.init(115200);



display.firstPage();
do
{
//display.setRotation(1);  
display.fillScreen(GxEPD_WHITE);
display.setFont(&FreeSansBold9pt7b);
display.setTextColor(GxEPD_BLACK);
display.setCursor(150, 160);
display.println("Loading :)");
}
while (display.nextPage());{
}


drawBitmaps400x300();




}

void loop() {

}

Here is my display.h file

#ifndef DISPLAY_EPD
#define DISPLAY_EPD
#include <Arduino.h>
#include <GxEPD2_BW.h>
#include <GxEPD2_3C.h>
extern GxEPD2_BW<GxEPD2_420,GxEPD2_420::HEIGHT> display(GxEPD2_420(/*CS=5*/ 5, /*DC=*/ 4, /*RST=*/ 3, /*BUSY=*/ 2));
#endif

Here is my bitmap.cpp file

#include <Arduino.h>
#include <GxEPD2_BW.h>
#include <GxEPD2_3C.h>
#include "bitmaps/Bitmaps400x300.h" // 4.2"  b/w
#include "display.h"
#include "bitmap.h"

GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> display(GxEPD2_420(/*CS=5*/ 5, /*DC=*/ 4, /*RST=*/ 3, /*BUSY=*/ 2));

void drawBitmaps400x300()
{

const unsigned char* bitmaps[] =
{
 gImage_ashok,gImage_select,gImage_eye1,gImage_eyehand,gImage_eyeear,gImage_grees
};

if (display.epd2.panel == GxEPD2::GDEW042T2)
{

    display.firstPage();
    do
    {
      
      display.setPartialWindow(0, 0, 400, 60);
      display.drawInvertedBitmap(0, 0, bitmaps[1], display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_BLACK);
    }
    while (display.nextPage());
    delay(500);

}
}

Here is my bitmap.h file

#ifndef MAP_BIT
#define MAP_BIT
void drawBitmaps400x300();
#endif

Thank you in advance :slight_smile:

bitmap.cpp (790 Bytes)

bitmap.h (68 Bytes)

display.h (240 Bytes)

MKRFULL.ino (700 Bytes)

@03sarath,

Please read How to use this forum - please read.

Edit your post and put the error messages and the code presented into code tags, using the </> command symbol.

Explain what you try to achieve. Looking at the attached code should be the last resort for helpers.

As soon as you did that, I will consider looking at your problem.

Jean-Marc

Hey @ZinggJM,

Sorry for the mistake, I have made the changes as per your suggested.

Thank you.

Hi 03sarath,

thank you for the changes. I will look at this problem. I may need to check with code.

But I think it is an issue with "declaration" and "definition".

The compiler tells: 'GxEPD2_BW<GxEPD2_420, 300> display' previously declared here.

I think the extern statement defines a display instance, instead of declaring one.

Maybe 'extern GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> display;' would be correct.

But now dinner is ready, I will check later.

Jean-Marc

Hey @ZinggJM,

But how can we define 'extern GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> display;' without defining connection pins 'GxEPD2_420(/CS=5/ 5, /DC=/ 4, /RST=/ 3, /BUSY=/ 2)'.I'm bit confused :confused: ,No problem now you please enjoy your dinner, we can figure out.

03sarath:
Hey @ZinggJM,

But how can we define 'extern GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> display;' without defining connection pins 'GxEPD2_420(/CS=5/ 5, /DC=/ 4, /RST=/ 3, /BUSY=/ 2)'.I'm bit confused :confused: ,No problem now you please enjoy your dinner, we can figure out.

Hey @03sarath, you could have tried this yourself in the meantime. Learning by doing!

You can declare it extern multiple times, but it needs to be defined in one place only.

Hey @ZinggJM,

The good thing is I have tried :slight_smile: , But now got this following error,

sketch\bitmap.cpp.o:(.bss.display+0x0): multiple definition of `display'

sketch\MKRFULL.ino.cpp.o:(.bss.display+0x0): first defined here

collect2.exe: error: ld returned 1 exit status

exit status 1
Error compiling for board ESP32 Dev Module.

Only changes made in display.h file

#ifndef DISPLAY_EPD
#define DISPLAY_EPD
#include <Arduino.h>
#include <GxEPD2_BW.h>
#include <GxEPD2_3C.h>
extern GxEPD2_BW<GxEPD2_420,GxEPD2_420::HEIGHT> display;
#endif

I guess 'extern' is not working for defining oin connections.

Still learning by doing!

You just need to believe the error message from the compiler/linker:

sketch\bitmap.cpp.o

sketch\MKRFULL.ino.cpp.o

You still have 2 definitions in the corresponding source files.

I had noticed, but wanted you to learn by yourself.

Jean-Marc

Hey @ZinggJM,

I'm feeling that you're a great mentor, Yes I have removed 'GxEPD2_BW<GxEPD2_420,GxEPD2_420::HEIGHT> display;' in all other .cpp files.

Now I got this error which I have expected.

sketch\MKRFULL.ino.cpp.o:(.literal._Z5setupv+0x4): undefined reference to `display'

sketch\MKRFULL.ino.cpp.o:(.literal._Z5setupv+0x18): undefined reference to `display'

collect2.exe: error: ld returned 1 exit status

exit status 1
Error compiling for board ESP32 Dev Module.

I hope it is asking for pin definitions 'GxEPD2_420(/CS=5/ 5, /DC=/ 4, /RST=/ 3, /BUSY=/ 2)' for EPD now, But really, I don't have any idea, how to define that now. Can you please suggest some way.

Ok, I may be a bad teacher, I know that. But to be a good teacher I would first need to know the capabilities of the learner.
I didn't expect you don't get it.

You need to have exactly one definition of display. First you had several, then you had two, now you have none.

You need to keep one definition of display, usually the one in the .ino file, MKRFULL.ino in your case.

I hope this has become clear now.

Jean-Marc

just in case...

#include <Arduino.h>
#include "bitmap.h"
#include <GxEPD2_BW.h>
#include <GxEPD2_3C.h>
#include "display.h"

#include <Fonts/FreeSansBold9pt7b.h>

GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> display(GxEPD2_420(/*CS=5*/ 5, /*DC=*/ 4, /*RST=*/ 3, /*BUSY=*/ 2));

void setup() {

  Serial.begin(115200);
  display.init(115200);



  display.firstPage();
  do
  {
    //display.setRotation(1);
    display.fillScreen(GxEPD_WHITE);
    display.setFont(&FreeSansBold9pt7b);
    display.setTextColor(GxEPD_BLACK);
    display.setCursor(150, 160);
    display.println("Loading :)");
  }
  while (display.nextPage()); {
  }


  drawBitmaps400x300();




}

void loop() {

}
#ifndef DISPLAY_EPD
#define DISPLAY_EPD
#include <Arduino.h>
#include <GxEPD2_BW.h>
#include <GxEPD2_3C.h>
//extern GxEPD2_BW<GxEPD2_420,GxEPD2_420::HEIGHT> display(GxEPD2_420(/*CS=5*/ 5, /*DC=*/ 4, /*RST=*/ 3, /*BUSY=*/ 2));
extern GxEPD2_BW<GxEPD2_420,GxEPD2_420::HEIGHT> display;
#endif
#include <Arduino.h>
#include <GxEPD2_BW.h>
#include <GxEPD2_3C.h>
#include "bitmaps/Bitmaps400x300.h" // 4.2"  b/w
#include "display.h"
#include "bitmap.h"

//GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> display(GxEPD2_420(/*CS=5*/ 5, /*DC=*/ 4, /*RST=*/ 3, /*BUSY=*/ 2));

void drawBitmaps400x300()
{

  const unsigned char* bitmaps[] =
  {
    //gImage_ashok,gImage_select,gImage_eye1,gImage_eyehand,gImage_eyeear,gImage_grees
  };

  if (display.epd2.panel == GxEPD2::GDEW042T2)
  {

    display.firstPage();
    do
    {

      display.setPartialWindow(0, 0, 400, 60);
      display.drawInvertedBitmap(0, 0, bitmaps[1], display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_BLACK);
    }
    while (display.nextPage());
    delay(500);

  }
}
#ifndef MAP_BIT
#define MAP_BIT
void drawBitmaps400x300();
#endif

Hey @ZinggJM,

Thanks a lot that is working perfectly good now, I hope I will become good learner, thanks for your lesson again.

Have a nice day,
Best regards,

Sarath

GxEPD Version 3.0.9 is available, installable or updated with Library Manager.

  • fixed BMP handling, e.g. for BMPs created by ImageMagick
  • see also Arduino Forum Topic 1 bit depth BMP created with ImageMagick all black using GxEPD2 - Displays - Arduino Forum
  • added support for GDEW075T7 7.5" b/w 800x480
  • GDEW075T7 has differential update (1.6s) using a charge balancing waveform
  • added "fast partial update" (differential update) for GDEW0371W7 3.7" b/w 240x416
  • improved differential update waveform for GDEW026T0 2.6" b/w 152x256
  • fixed init code & improved differential update for GDEW042T2 4.2" b/w 300x400
  • note that all differential refresh waveforms are a compromise (ghosting, big font use)
  • parameters for differential waveform for these display can easily be changed for experimenting
  • GDEW042T2 would have greyed background without sustain phase
  • GDEW042T2 needs multiple full refreshes after extended use of partial updates

Please note that I recommend to use GxEPD2 for Newbies or new projects.

Both GxEPD and GxEPD2 are known by Library Manager and can be installed directly.

Jean-Marc

Dear ZinggJM,

Could you, please, advise if there is a way to make the Cyrillic text a bit bigger. The following code works fine except that the text in Cyrillic font is small.

I could not find a bigger Cyrillic font in the U8g2 fonts. And I could not figure out how to add a custom font. There is no such issue with the French and German fonts as you can see on the photo.

I like this Cyrillic font, it works both for Russian and Ukrainian languages. If only there was a way to scale it a bit bigger.

[SOLVED] See: Cyrillic fonts for U8g2_for_Adafruit_GFX (on 1.54 inch E-Ink display) - Displays - Arduino Forum

// mapping suggestion for AVR, UNO, NANO etc.
// BUSY -> 7, RST -> 9, DC -> 8, CS-> 10, CLK -> 13, DIN -> 11

// 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 <GxEPD2_BW.h>
#include <GxEPD2_3C.h>
#include <Fonts/FreeMonoBold9pt7b.h>
#include <U8g2_for_Adafruit_GFX.h>


#define MAX_DISPAY_BUFFER_SIZE 800 // 
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= MAX_DISPAY_BUFFER_SIZE / (EPD::WIDTH / 8) ? EPD::HEIGHT : MAX_DISPAY_BUFFER_SIZE / (EPD::WIDTH / 8))
// select one and adapt to your mapping
GxEPD2_BW<GxEPD2_154, MAX_HEIGHT(GxEPD2_154)> display(GxEPD2_154(/*CS=10*/ SS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));

#include "GxEPD2_boards_added.h"

U8G2_FOR_ADAFRUIT_GFX u8g2Fonts;

void setup()
{
  Serial.begin(115200);
  Serial.println();
  Serial.println("setup");
  display.init();
  u8g2Fonts.begin(display); // connect u8g2 procedures to Adafruit GFX
  helloWorld();
  delay(1000);

}

void loop()
{
}

void helloWorld()
{
  //Serial.println("helloWorld");
  uint16_t bg = GxEPD_WHITE;
  uint16_t fg = GxEPD_BLACK;
  u8g2Fonts.setFontMode(1);                 // use u8g2 transparent mode (this is default)
  u8g2Fonts.setFontDirection(0);            // left to right (this is default)
  u8g2Fonts.setForegroundColor(fg);         // apply Adafruit GFX color
  u8g2Fonts.setBackgroundColor(bg);         // apply Adafruit GFX color


  display.firstPage();
  do
  {
    display.fillScreen(bg);
    u8g2Fonts.setFont(u8g2_font_10x20_t_cyrillic);  // select u8g2 font from here: https://github.com/olikraus/u8g2/wiki/fntlistall
    u8g2Fonts.setCursor(20, 30); // start writing at this position
    u8g2Fonts.print("Привет мир!");

    u8g2Fonts.setCursor(20, 60); // start writing at this positionu8g2Fonts.setCursor(20, 30); // start writing at this position
    u8g2Fonts.print("Прівєт мир!");

    u8g2Fonts.setFont(u8g2_font_timB18_tf);  // select u8g2 font from here: https://github.com/olikraus/u8g2/wiki/fntlistall
    u8g2Fonts.setCursor(20, 100); // start writing at this position
    u8g2Fonts.print("S'il vous plaît.");

    u8g2Fonts.setCursor(20, 140); // start writing at this position

    u8g2Fonts.print("Grüßen.");

  }
  while (display.nextPage());

}

@OleksiyM

Could you, please, advise if there is a way to make the Cyrillic text a bit bigger.

U8g2_for_Adafruit_GFX doesn't seem to have a setFontSize() method, but even this would not help, as you are looking for "a bit", not a multiple.

I tried the obvious, searching for "Cyrillic" in the forum, but didn't find something obvious.

I suggest you create a new topic, e.g. "Cyrillic fonts for Adafruit_GFX or U8g2_for_Adafruit_GFX", as this is of general interest. Don't just copy the text of your post (cross-posting is disliked), but add a link to your post. I am sure the experts will have an answer, or hints where to look.

Jean-Marc

Added:

Found available Fonts to use with Adafruit_GFX

see also: Adafruit_GFX fork extended for UTF-8 by Bodmer.

@ZinggJM

Great work with the library! I am working on a ESP32 based project, using a Waveshare 2.9 B/W EPD and your GxEPD2 library.

I have the code setup currently so the ESP32 hosts a web form where the user enters a few text fields and hits submit and the data is first stored to nvram, then written to the EPD, and then everything goes to deep sleep. It works OK, except when words don't fit perfectly. Then the user has wake the device up, re-enter setup mode to adjust spacing and try again.

What I'd like to do is provide some kind of live or easy to refresh preview, either on the website, EPD, or both. For the live web preview, I was wondering if it would be possible to export the display buffer to a bitmap that would then be loaded by the browser showing the user what their changes would look like when written to the EPD.

For the on-device preview, I was thinking of just using a partial refresh every time the user switches text fields on the browser. I can conceive how to code this part but i'm still open to suggestions.

Thanks,

Matt

@mattard

I was wondering if it would be possible to export the display buffer to a bitmap that would then be loaded by the browser showing the user what their changes would look like when written to the EPD.

Yes, this is possible and quite easy, as your processor has enough RAM for full-buffered graphics, and you have a b/w e-paper display.

The quick and dirty approach is to add an accessor method to the class GxEPD2_BW that returns the _buffer pointer. The buffer content is still valid after update to the display.

The clean approach is to use a Adafruit_GFX GFXcanvas1 for buffered graphics instead. The content of the canvas can be presented on the display through the drawBitmap() method, using the getBuffer() accessor.

You would then need to send the buffer content in BMP format to the client. This is quite easy if you use a depth of 1. I attach an example that writes BMP depth 1 format to SD.

Note: GxEPD2_SD_WriteBitmap.ino is a quick and dirty example, it was not really meant to get published.

I was thinking of just using a partial refresh every time ..

You could use partial refresh to full screen for this.

Jean-Marc

GxEPD2_SD_WriteBitmap.ino (8.35 KB)