Waveshare e-paper displays with SPI

@weow147, Hi, welcome to the forum!

Thank you for posting code in a code window. Please also post diagnostic output in a code window, too.

Please read How to get the best out of this forum if you haven't done yet.

Your diagnostic output looks uncommon; I would expect to see busy times from diagnostic output in Serial Monitor.

Busy Timeouts most likely are caused by SPI communication not working, or wrong panel selected.

Please report your wiring, point-to-point, to be able to check against your constructor parameters.
And provide a link to the display you bought, to see if you bought it with a HAT for connection.

Note that my suggested wiring and parameters are different than the wiring used by the Waveshare examples. Just make sure that your wiring corresponds to your parameters.

Yes, MKR1000 is SAMD architecture.

Jean-Marc

Sir-

-Diagnostic Output was copy/pasted from serial monitor. Will place in code window next time. :+1:
-display 800×480, 7.5inch E-Ink raw display
-Hat Universal e-Paper Raw Panel Driver HAT

HAT -> MKR1000
Busy -> 5
RST   -> 6
DC    -> 7
CS    -> 4
CLK  -> 9 SCK
DIN  -> 8 MOSI
GND -> GND
VCC  -> VCC (confirmed 3.3V)

I'm using the suggested mappings from GxEPD2_wiring_examples.h

// mapping suggestion for Arduino MKR1000 or MKRZERO
// note: can't use SS on MKR1000: is defined as 24, should be 4
// BUSY -> 5, RST -> 6, DC -> 7, CS-> 4, CLK -> 9, DIN -> 8

This configuration also matches the constructor in GxEPD2_display_selection_new_style.h

//lines 194 and 195 from GxEPD2_display_selection_new_style.h
// adapt the constructor parameters to your wiring
GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=4*/ 4, /*DC=*/ 7, /*RST=*/ 6, /*BUSY=*/ 5));

Noted: Waveshare wiring differs from ZinggJM wiring - i like yours better.

I must have the wrong panel??

No, I don't think so. If the Waveshare demo works, this is the correct panel for this resolution.

But the actual version of the HAT has the "clever" reset circuit, that needs the shortened reset pulse (at least for the big panels), see in README.md:

  • note that Waveshare bords with "clever" reset circuit may need shortened reset pulse
  • use init(115200, true, 2, false) for Waveshare boards with "clever" reset circuit
  • note that Waveshare bords with "clever" reset circuit need 1k pull-up on RST on ESP8266, or different pin

I don't have the actual HAT version, so I can't test. I prefer the DESPI-C02 for 3.3V processors.

nailed it! this worked! where did you find that information?!

Great attention to detail my friend - very much appreciated. I'd buy you a beer if i could!

Thank you for the feedback! Feedback is what drives me.

And feedback from a user pointed me to the shortened reset in the Waveshare code, some time ago.

Jean-Marc

Hello Jean-Marc

I am in quite the pickle as I have purchased this display that does not seem to work with Arduino! (waveshare 1.54 inch module type c)

the only code that works on the screen for AVR architecture is some example code that draws a non-modifiable static image and then sleeps

Would it be possible to get this screen working with your library or should I return it and buy this one instead? https://www.waveshare.com/1.54inch-e-paper-module-b.htm

@fernflower1, Hi, welcome to the forum! Thanks for the clickable links.

If you can easily get it replaced, e.g. if from a local shop, I would suggest to do so.
The https://www.waveshare.com/1.54inch-e-paper-module-b.htm is the same panel as GDEH0154Z90 from Good Display and is supported by GxEPD2.
But if you ordered it from China or abroad the shipping cost might not justify return.

You could try to get your https://www.waveshare.com/1.54inch-e-paper-module-c.htm working with GxEPD2.
It most likely has the same panel as the GDEM0154C90 from Good Display.
From SPECIFICATIONS I see that it has the controller SSD1680.
In GxEPD2_display_selection_new_style.h you can see on line 61 that the GDEM029C90 has the same controller.
You could change WIDTH and HEIGHT to 154 in https://github.com/ZinggJM/GxEPD2/blob/master/src/epd3c/GxEPD2_290_C90c.h
and select this display to compile, to try if this works.

Jean-Marc

Good Morning e-paper fans and Jean-Marc!

My question today is about saving power in a digital clock.

Pseudocode for my main loop is something like this:

void loop()
{
//  wakeup coulomb counter (used to monitor battery status)
//  get current time from rtc, set by wifi during setup()
//  wakeup screen
//  update screen with current time, system uptime and battery status
//  sleep coulomb counter
display.hibernate();  
display.powerOff(); 
LowPower.sleep(59000); lowpower delay for about a minute
}

Questions:

  • what is the wakeup behavior? is there a command or method? i dont see anything like that in deepSleepTest(). Is just happens automatically?
  • display.hibernate(); doesnt work. The screen looks bad after the next update and requires a full redraw of all my icons and graphics. It takes about 90 seconds to draw all my static background graphics and i dont want to 'redraw' every cycle through my main loop. Is there a fix or alternative? what is the purpose of .hibernate if you have to redraw the screen each time?
  • display.powerOff() seems to work perfectly... is there a catch? the serial output shows "_PowerOff : 39243" and i get no further serial information during subsequent updates. This is fine by me - unless i'm testing/debugging i shutdown serial after setup(). I'm going to let it run all day while i'm at work and see how it looks when i get home. What am i missing conceptually?
  • what is the difference between .hibernate() and .powerOff() ?
  • are there any other power savings tips folks can give me?

THANKS!

@weow147,

Your e-paper HAT has level converters and the "clever" reset circuit.
You can either keep RST high, supplying it from the processor pin or by a 1k pull-up, to keep the controller and its memory powered. The current drawn will be high compared to the idle current of an e-paper panel.
Or you can let RST drop low (by its pull-down) and let power drawn by the HAT and e-paper panel drop to zero, if you switch all connected processor pins to INPUT to avoid phantom feed. But then you will need to restore the controller memory after power up, and do a full refresh.
Or you can replace the HAT with a DESPI-C02 if you use a 3.3V processor, e.g. your MKR1000. Then you can use init() with false for initial if processor restarted, if power to the controller is kept.

Note that hibernate() calls powerOff() internally.
Hibernate stops the controller, but lets it keep memory.

Jean-Marc

Ok, I’m beginning to understand after reading your thoughts and digging around in GxEPD_BW.h. There’s lots of good comments in there…

  • powerOff() turns off the generation of panel driving voltages to avoid screen fading over time
  • hibernate() calls powerOff() AND sets the controller to deep sleep BUT ONLY if wakeable by RST

then I found these comments in the .init method.

  • Garbage will result on displays with fast partial update, if initial full update is omitted after power loss
  • init false to re-initialize the processor after deep sleep wakeup. This can be used to avoid repeated initial full refresh on displays with fast partial update (like mine)
    I don’t THINK I’m losing power, but I AM getting garbage after hibernating… I think this is why my screen looks like crap after calling display.hibernate().

So the solution (I think) is to use display.init(false) to re-initialize the display after hibernation. Apparently this only works if the display is wakeable by RST (drop low, may also have to switch to INPUT to avoid phantom feed). I’ll try it when I get home.

I don’t fully understand how the “clever” reset works, or how it’s hindering me…

How much power does .hibernate() save anyway? If it’s significant then I will probably go ahead and buy the DESPI-C02.

THANKS!

Not much, but significant for low power use with infrequent refresh.
See panel specs accessible from GDEW075T7.

I don't know if the shortened reset pulse is good enough for panel deep sleep wakeup.
I have never tested this, as this use case simply makes no sense.
The "clever" reset circuit only makes sense for power save, if you are willing to do a full creation of content and refresh of the screen.

Just take a look at the schematics, accessible from the wiki page linked from the Waveshare site's product page.

Jean-Marc

  • Refresh power: 38mW(typ.)
  • Standby power: <0.017mW

I assume i need to hibernate in order to draw only 0.017 mW?

Also, why does the use case make no sense? I only want to update a small part of the screen, once per minute (maybe less), and use as little power as possible in between updates. That seems like a very common use case to me.

Does hibernate REQUIRE a full creation of content and refresh?

Yes, in all cases that have the "clever" reset circuit, and use it to remove power.
Maybe, even if not used to remove power; the capacitors may not be sufficient to have power to the controller during the shortened reset pulse.
No, if the more clever connection module DESPI-C02 is used.

P 14/54 of GDEW075T7 V2.0 Specification.pdf:
Standby panel current 0.215mA
Deep sleep mode current 2..5 uA

This HAT of mine doesn't seem so clever anymore... DESPI-C02 is better!

Hello.
So I am stupid and I can't understand in which way.
I have a waveshare 4.2" b/w and I have hooked it correctly to an arduino uno with great results using GxEPD2.
Now I tried doing the same with my bluepill, with no result whatsoever.
I have the latest core by stm, and use an stlink v2 to upload.
I'm trying the default "Example" sketch.

Examining everything with my scope I can see that PA5, which is sck is displaying an sck activity and PA7 is displaying serial data -like behaviour.

The problem is that I cannot find what the other pins are. I tried probing around the board after the reset but nothing works. I tried using the following:

// adapt the constructor parameters to your wiring
GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=4*/ 3, /*DC=*/ 2, /*RST=*/ 1, /*BUSY=*/ 0));

or

// adapt the constructor parameters to your wiring
GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=4*/ PA3, /*DC=*/ PA2, /*RST=*/ PA1, /*BUSY=*/ PA0));

or

// adapt the constructor parameters to your wiring
GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=4*/ PA_3, /*DC=*/ PA_2, /*RST=*/ PA_1, /*BUSY=*/ PA_0));

or even

// adapt the constructor parameters to your wiring
GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=4*/ A3, /*DC=*/ A2, /*RST=*/ A1, /*BUSY=*/ A0));

But the selected pin never display anything at all on them during the serial communication. I tried hooking up the display regardless but to no avail.

The rest of the entire sketch, meaning all of the files, are the default, except for the fact that I uncommented

#define GxEPD2_DISPLAY_CLASS GxEPD2_BW
#define GxEPD2_DRIVER_CLASS GxEPD2_420     // GDEW042T2   400x300, UC8176 (IL0398)

what am I doing wrong?

Thanks

Hi @ilfuria, Hi All,

GxEPD2 can't currently be used with the official STM32 package!

More exactly, analog capable pins can't be used as IO pins with GxEPD2 with the official STM32 package. Reason: the analog pins have numbers starting at 0xC0, which are < 0 as int8_t, and interpreted as not connected by GxEPD2.

See C:\Users\ZinggJ\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.1.0\cores\arduino\pins_arduino_analog.h

I will need to change pin number parameter types to int16_t.

You could try to use PBx pins at interim, except PB0, PB1. HW SPI pins SCK and MOSI should work, but not SS.

Sorry, I did not notice this change in the STM32 package.

Jean-Marc

thanks, sure enough with PB6:9 it works perfectly fine. Cheers!

Hi I have a question about displaying degree symbol ° in the waveshare 1.54 inch E-paper.
I have tried several methods below, but none of them works:

  1. display.print(char('°'));
  2. display.print(char(176)); // ascii
  3. display.print(char(223)); // LCD
  4. display.print("\xC2\xB0"); // UTF-8, this works in serial

Since I'm fairly new to this, hope you can help me solve this !!!
Many thanks.

@shawhuang22, Hi, welcome to the forum!

Please read How to get the best out of this forum, if you haven't done yet.

The answer to your question depends heavily on the library you intend to use!

Adafruit_GFX fonts do not support UTF-8 and have no degree symbol, afaik.

GxEPD2 can be used with U8g2_for_Adafruit_GFX which supports UTF-8 and has support for many more fonts.

See also example GxEPD2_U8G2_Fonts_Example.ino.

Jean-Marc

Thanks for the suggestion. I have found a font which supports the degree symbol. Actually it automatically convertt char " ' " to '°'.