Waveshare e-paper displays with SPI

bogus105:
Dear ZinggJM,

could you tell us more how to use 2.9inch Waveshare display with Arduino Nano/Uno. Let's leave 5V-3.3V voltage conversion issues.
I don't know pin assignments and library usage:/

I tried to figure out pinout shown in i.e. GxGDEH029A1.cpp file but it is for DESTM32-S2 connection board for STM32 system not for Arduino:/

Please put some light how to talk to WaveShare e-papers from Arduino.

One of the problems i found during compilation is that variable used to store screen resolution is uint8_t. 2.9inch screen has 296 x 128 pixels so 296 is greater that uint8_t can handle so overflow errors appeard. This is just one of the errors.

I have decided that I will look at your problems as soon as your post is more specific, more clearly stated, and more correct.

My code is generic as far as possible, with target processor specific default values for the constructor.
The DESTM32-S2 connection board is NOT STM32 specific, but its pinout matches the DESTM32-S1 STM32 demo board from Good Display.
Please state which uint8_t variable (name it!) you mean, and what other errors you refer to.

Thank you ZinggJM for your answer.

You're right there was no much details in my previous post. It was rather indication:)
The only progress i made so far after playing with various libraries was when i modified Waveshare 'string' example found here:

in arduino/string/ folder.
The following files are in this folder:
Display_Lib.h
EPD_drive.cpp
EPD_drive.h
EPD_drive_gpio.cpp
EPD_drive_gpio.h
string.ino

As you said: Nano doesn't have enough RAM for these files so i included

#include <avr/pgmspace.h>

in two files:
Display_Lib.h
EPD_drive.h

and then i changed big data tables like:

const unsigned char waveshare[4736] = {........ton of data....};

to

const unsigned char waveshare[4736] PROGMEM = {........ton of data....};

Now compilation is errorless.
Loaded things up to Nano and my progress is e-paper screen was cleared (waveshare logo that was on screen when i bought it disappeared).
No test text string was displayed.

On serial monitor i can see this:

------------Clear full screen-----------------
full init
*set register Start
send data :
send data :
send data :
send data :
send data :
send data :
send data :
send data :
send data :
send data :
*set register end
send data :
Busy is Low

full clear

send data :
send data :

------start send display data!!---------<<<<<<<
Busy is Low

send data1
Busy is Low

full over
*set register Start
send data :
send data :
send data :
send data :
send data :
send data :
send data :
send data :
send data :
send data :
*set register end
send data :
Busy is Low

po operacji clear full
--------------Clear part screen------------
*set register Start
send data :
send data :
send data :
send data :
send data :
send data :
send data :
send data :
send data :
send data :
*set register end
send data :
Busy is Low

------start send display data!!---------<<<<<<<
send data :
send data :
send data :
send data :
Busy is Low

Busy is Low

send data :
send data :
send data :
send data :
Busy is Low

po czyszczeniu czesciowym ekranu
h
FFFFFFD5 FFFFFFD5 FFFFFFD5 FFFF

and so on. I seems Nano resets itself.

I wonder why BUSY line on display module is low?

The code part that checks this looks like this:

/*******************************************************************************
function:
read busy
*******************************************************************************/
unsigned char WaveShare_EPD::ReadBusy(void)
{
unsigned long i=0;
for(i=0;i<400;i++){
// println("isEPD_BUSY = %d\r\n",isEPD_CS);
if(isEPD_BUSY==EPD_BUSY_LEVEL) {
Serial.println("Busy is Low \r\n");
return 1;
}
driver_delay_xms(10);
}
return 0;
}

In for loop that you can see that during first loop execution BUSY line is compared with EPD_BUSY_LEVEL, if its true "Busy is Low" is printed and the whole ReadBusy procedure is terminated with " return 1; ".
Why this procedure returns 0 or 1 if it is not checked anywhere in the code whether 0 or 1 is returned?

Then i modified main program loop to check BUSY line status: it is LOW all the time. Maybe there is sth wrong with my module?
I checked BUSY line with multimeter and in fact it is 0 V almost all the time:/

I'm using modified Nano board for 3.3V operation. Brief description is here:

https://forum.arduino.cc/index.php?topic=491012.0

Hi bogus105

Please use code tags for code, "</>" at top left, it makes your post more pleasant to read.

You do not provide any info concerning errors, so I forget about those.

When you put data into PROGMEM, you need to read it with the corresponding read function; there are tutorials about this.

The BUSY line is active when the controller takes time for commands, e.g. on update to display.

I have not yet tried to use the Waveshare code; I may do this, but not with UNO or NANO to avoid the need for level converters or series resistors.

Jean-Marc

I may reconsider to try with UNO and NANO, as I just received level converters that I want to use anyway:

https://www.aliexpress.com/item/8-channel-level-conversion-module-two-way-conversion-between-3-3V-and-5V-IO-access-5V/32811827434.html

I think any Arduino UNO or NANO user should have some of those ready at hand, or some other make.

TeK32:
This is great, thank you!

Would you care to make your code compatible with the ESP32 as well?

Yes, I did. I have updated GxEPD on GitHub.

bogus105:
Thank you ZinggJM for your answer.

You're right there was no much details in my previous post. It was rather indication:)
The only progress i made so far after playing with various libraries was when i modified Waveshare 'string' example found here:
http://www.waveshare.com/wiki/File:2.9inch_e-Paper_Module_code.7z

in arduino/string/ folder.
The following files are in this folder:
Display_Lib.h
EPD_drive.cpp
EPD_drive.h
EPD_drive_gpio.cpp
EPD_drive_gpio.h
string.ino

As you said: Nano doesn't have enough RAM for these files so i included

#include <avr/pgmspace.h>

in two files:
Display_Lib.h
EPD_drive.h

and then i changed big data tables like:

const unsigned char waveshare[4736] = {........ton of data....};

to

const unsigned char waveshare[4736] PROGMEM = {........ton of data....};

Now compilation is errorless.
Loaded things up to Nano and my progress is e-paper screen was cleared (waveshare logo that was on screen when i bought it disappeared).
No test text string was displayed.
...

I could compile the Waveshare string example successfully for Arduino UNO and NANO.

The waveshare array is referenced nowhere in the code, and therefore not included in the link process, at least with the actual Arduino IDE 1.8.3.

Do you use an older version of Arduino, or have you done other changes to the code?

I would just ignore your posts, but try to answer, so other users interested in these displays do not become insecure.

Hello
I would like to use the "waveshare" 1.54 inch screen with an arduino MKR Zero, do you think this is possible?
Are the changes to be made to your library important?

This should be simple. The device has 32kB RAM, so the ~5kB display buffer is no problem.

I need to fix the GxIO_SPI class for AVR and SAM or all non-ESP processors, and will add SAMD.
I will make sure it compiles with SAMD, and try to check it with my MKR-1000 (sitting idle in some drawer waiting to be used).

I can't promise a deadline, but should be ready in less than a week or so.

Thank you
No problem for the delai, it will be a pleasure to use your library when it is ready

Sorry i'm not writing everyday ZinggJM nut i'm at work and i can't read this forum every day:)

Youv'e said you compiled Waveshare string example on Uno/Nano with no issues.
How?

I use Arduino IDE 1.6.8

When attempt to compile original 'string.ino' example from waveshare i got error: global variables use 3 313 bytes (161%) od dynamic memory, leaving -1 265 bytes for local variables. Maxiumum is 2 048 bytes.

So 'string' exmple simply won't fit in Uno/Nano:/

I also tried to load an example from your library: GxEPD_SPI_TestExample
The following errors came up:

In file included from C:\Users\Raport\Documents\Arduino\libraries\GxEPD-master/GxGDEH029A1/GxGDEH029A1.cpp:31:0,

                 from C:\Users\Raport\Documents\Arduino\libraries\GxEPD-master\examples\GxEPD_SPI_TestExample\GxEPD_SPI_TestExample.ino:37:

C:\Users\Raport\Documents\Arduino\libraries\GxEPD-master/GxGDEH029A1/GxGDEH029A1.h:37:30: warning: integer overflow in expression [-Woverflow]

 #define GxGDEH029A1_Y_PIXELS 296

                              ^

C:\Users\Raport\Documents\Arduino\libraries\GxEPD-master/GxGDEH029A1/GxGDEH029A1.h:41:28: note: in expansion of macro 'GxGDEH029A1_Y_PIXELS'

 #define GxGDEH029A1_HEIGHT GxGDEH029A1_Y_PIXELS

                            ^

C:\Users\Raport\Documents\Arduino\libraries\GxEPD-master/GxGDEH029A1/GxGDEH029A1.h:43:53: note: in expansion of macro 'GxGDEH029A1_HEIGHT'

 #define GxGDEH029A1_BUFFER_SIZE GxGDEH029A1_WIDTH * GxGDEH029A1_HEIGHT / 8

                                                     ^

C:\Users\Raport\Documents\Arduino\libraries\GxEPD-master/GxGDEH029A1/GxGDEH029A1.h:85:21: note: in expansion of macro 'GxGDEH029A1_BUFFER_SIZE'

     uint8_t _buffer[GxGDEH029A1_BUFFER_SIZE];

                     ^

C:\Users\Raport\Documents\Arduino\libraries\GxEPD-master/GxGDEH029A1/GxGDEH029A1.h:85:44: error: overflow in constant expression

     uint8_t _buffer[GxGDEH029A1_BUFFER_SIZE];

                                            ^

C:\Users\Raport\Documents\Arduino\libraries\GxEPD-master/GxGDEH029A1/GxGDEH029A1.h:85:44: error: size of array '_buffer' is negative

C:\Users\Raport\Documents\Arduino\libraries\GxEPD-master/GxGDEH029A1/GxGDEH029A1.cpp: In member function 'virtual void GxGDEH029A1::fillScreen(uint16_t)':

C:\Users\Raport\Documents\Arduino\libraries\GxEPD-master/GxGDEH029A1/GxGDEH029A1.h:37:30: warning: integer overflow in expression [-Woverflow]

 #define GxGDEH029A1_Y_PIXELS 296

                              ^

C:\Users\Raport\Documents\Arduino\libraries\GxEPD-master/GxGDEH029A1/GxGDEH029A1.h:41:28: note: in expansion of macro 'GxGDEH029A1_Y_PIXELS'

 #define GxGDEH029A1_HEIGHT GxGDEH029A1_Y_PIXELS

                            ^

C:\Users\Raport\Documents\Arduino\libraries\GxEPD-master/GxGDEH029A1/GxGDEH029A1.h:43:53: note: in expansion of macro 'GxGDEH029A1_HEIGHT'

 #define GxGDEH029A1_BUFFER_SIZE GxGDEH029A1_WIDTH * GxGDEH029A1_HEIGHT / 8

                                                     ^

C:\Users\Raport\Documents\Arduino\libraries\GxEPD-master/GxGDEH029A1/GxGDEH029A1.cpp:112:28: note: in expansion of macro 'GxGDEH029A1_BUFFER_SIZE'

   for (uint16_t x = 0; x < GxGDEH029A1_BUFFER_SIZE; x++)

                            ^

C:\Users\Raport\Documents\Arduino\libraries\GxEPD-master/GxGDEH029A1/GxGDEH029A1.cpp: In member function 'virtual void GxGDEH029A1::drawBitmap(const uint8_t*, uint32_t)':

C:\Users\Raport\Documents\Arduino\libraries\GxEPD-master/GxGDEH029A1/GxGDEH029A1.h:37:30: warning: integer overflow in expression [-Woverflow]

 #define GxGDEH029A1_Y_PIXELS 296

                              ^

C:\Users\Raport\Documents\Arduino\libraries\GxEPD-master/GxGDEH029A1/GxGDEH029A1.h:41:28: note: in expansion of macro 'GxGDEH029A1_Y_PIXELS'

 #define GxGDEH029A1_HEIGHT GxGDEH029A1_Y_PIXELS

                            ^

C:\Users\Raport\Documents\Arduino\libraries\GxEPD-master/GxGDEH029A1/GxGDEH029A1.h:43:53: note: in expansion of macro 'GxGDEH029A1_HEIGHT'

 #define GxGDEH029A1_BUFFER_SIZE GxGDEH029A1_WIDTH * GxGDEH029A1_HEIGHT / 8

                                                     ^

C:\Users\Raport\Documents\Arduino\libraries\GxEPD-master/GxGDEH029A1/GxGDEH029A1.cpp:147:28: note: in expansion of macro 'GxGDEH029A1_BUFFER_SIZE'

   for (uint32_t i = 0; i < GxGDEH029A1_BUFFER_SIZE; i++)

                            ^

exit status 1
Error compiling for board Arduino Nano.

Does it mean it's not suitable for Arduino Nano because of Nano's poor memory reservours?
Have a good day.

Now you have understood what I need from you if I should try to help you.

First, as I already told you, the waveshare string example can be successfully compiled for Arduino Nano.
I did not yet try to run it on my Nano, but I have it ready complete with level converter.

Second, the current version of my GxEPD on GitHub is not suitable for UNO or Nano, as it needs a buffer of ~5kB in RAM. And the current GxIO_SPI only works correctly on ESP8266 and ESP32, because the setFrequency() method only works for these. I work on a fix for this. For these displays max SPI frequency is 4MHz.

Third, you need to upgrade your Arduino IDE to the actual version (1.8.3) to compile the waveshare string example, as I already told you. And GxEPD most likely will need version 1.8.x, at least for UNO, Nano.

Fourth, I will provide a new version of the small e-paper GxEPD classes for AVR (UNO and Nano) with reduced buffer and support for bitmaps in PROGMEM. Only the reduced part of the display will be available for use with Adafruit_GFX. An initial version for 2.9inch runs on my Nano. But this is not my priority.

Bear in mind that I am a hobby Arduino user like you; I do this for fun, and provide help only as long as I consider it a pleasure.

Now i understand:) Thank you for your time. Your reply convinced me to order esp8266. Too much constrains with Nano - RAM size being the most anoying.
I'll try to change IDE to the newest one but as i said - i can play with arduino at work only and IDE must be installed by company's administrator (he's not at work now and it's not easy to convience him to do it thanks to company policy:(:(:frowning:

ZinggJM:
...
And the current GxIO_SPI only works correctly on ESP8266 and ESP32, because the setFrequency() method only works for these. I work on a fix for this. For these displays max SPI frequency is 4MHz.
...

Interim fix applied to GxIO_SPI, GxEPD updated on GitHub GitHub - ZinggJM/GxEPD: A simple E-Paper display library with common base class and separate IO class for Arduino.

Hi. Thank's for this library. I'm using it with a nodemcu (esp8266) and a Waveshare 2.9 e-paper. And it works showing decent text in my case.

However I am trying to write a "partial update" function and I am a bit at a loss understanding the protocol used in communicating with the display. Also and especially after looking in the datasheet by Waveshare. :o
There seems to be some code/communication dedicated to this (_SetRamArea, _SetRamPointer)? But I don't understand the parameters used there and if they really are what I hope them to be.

ZinggJM:
...
Fourth, I will provide a new version of the small e-paper GxEPD classes for AVR (UNO and Nano) with reduced buffer and support for bitmaps in PROGMEM. Only the reduced part of the display will be available for use with Adafruit_GFX. An initial version for 2.9inch runs on my Nano. But this is not my priority.
...

And finally the idea trickled into my head ("s'zwänzgi isch abegheit") - I had a short look at U8g2, for a ST7565 display. Divide the display into 4 pages, let the user draw or print his picture 4 times, each time updating one page window to the display using the "partial update" function of these displays.

Not really my recommendation to use UNO or Nano with e-paper displays, but interesting coding practice for me anyway.

UlrichKu:
Hi. Thank's for this library. I'm using it with a nodemcu (esp8266) and a Waveshare 2.9 e-paper. And it works showing decent text in my case.

However I am trying to write a "partial update" function and I am a bit at a loss understanding the protocol used in communicating with the display. Also and especially after looking in the datasheet by Waveshare. :o
There seems to be some code/communication dedicated to this (_SetRamArea, _SetRamPointer)? But I don't understand the parameters used there and if they really are what I hope them to be.

I wrote my last post at the same time, there you can see that I intend to use partial update.

And Good Display have the actual demo code available on their downloade page, with improved partial update.

http://www.good-display.com/download_list/downloadcategoryid=35&isMode=false.html

(_SetRamArea, _SetRamPointer) basically are the same functions as for TFT displays (e.g. setWindow or setWindowAddress), but the x-address is not a pixel number but a byte address (x/8). This fact, combined with the missing read GRAM function, makes direct pixel draw to GRAM impossible.

ZinggJM:
I wrote my last post at the same time, there you can see that I intend to use partial update.

I noticed that. :slight_smile: Funny conincidence.
However in my case I'm looking for it to speedup thing and/or improve redraw.

ZinggJM:
And Good Display have the actual demo code available on their downloade page, with improved partial update.

What environment does this target? My knowledge stops as C++ and Arduino IDE at the moment.

ZinggJM:
(_SetRamArea, _SetRamPointer) basically are the same functions as for TFT displays (e.g. setWindow or setWindowAddress), but the x-address is not a pixel number but a byte address (x/8). This fact, combined with the missing read GRAM function, makes direct pixel draw to GRAM impossible.

But you could update ie only 8 pixels (1 byte) with this if you wanted to?

The demo code is for STM32 using Keil5 programming environment. The - earlier version of the - code is the base of the waveshare code and of my GxEPD display classes.

Write single byte may be possible, I have no experience, but display update time will not be shorter than for a full line, I guess.

ZinggJM:
Write single byte may be possible, I have no experience, but display update time will not be shorter than for a full line, I guess.

Probably not. The question was just if I understood this correctly.

So one would:

  • Use correct LUT
  • Set ram pointer and area correctly
  • Write partial data
  • Update display (with 0x04 data instead of 0xc7)

?