Waveshare e-paper displays with SPI

Hello everyone, i have some questions.

I have 6 e-ink screens 2,13 (D) and i need to display 1 different image for each screen.
What can you advise for driving them?

If i use SPI, I think i need 6 CS pins for displays + 6 CS pins for SRAM + 1 CS pin for the SD.
but i dont how configurate the PIN SRAM on my E-paper Shield.

Is it easier to use the SPI or I2C protocol to control 6 e-papers?

Thx in advance.

Guifox:
Hello everyone, i have some questions.

I have 6 e-ink screens 2,13 (D) and i need to display 1 different image for each screen.
What can you advise for driving them?

If i use SPI, I think i need 6 CS pins for displays + 6 CS pins for SRAM + 1 CS pin for the SD.
but i dont how configurate the PIN SRAM on my E-paper Shield.

Is it easier to use the SPI or I2C protocol to control 6 e-papers?

Thx in advance.

I assume you have 6 2.13inch-e-paper-d.htm

And one or 6 e-paper-shield.htm

I assume you want to drive them with an Arduino (UNO or MEGA?) or STM32 Nucleo board.

If you want to use 6 shields, it is unclear to me how you want to wire them.

If you want to use the on-board SRAM, I assume you use the Waveshare demo and library.

Is it easier to use the SPI or I2C protocol to control 6 e-papers?

I don't know how you could drive the SPI panels with I2C, but you could use a I2C port expander for the CS pins.

I have no actual experience with the Waveshare demo and library, but I doubt it can be easily extended for multiple displays.

My library GxEPD2 has an example for multiple displays on ESP8266 or ESP32, but the library does not support external SRAM. GxEPD2_MultiDisplayExample

This is the limited help I can give you. Hopefully you get more answers to your post.

ZinggJM:
I assume you have 6 2.13inch-e-paper-d.htm

And one or 6 e-paper-shield.htm

I assume you want to drive them with an Arduino (UNO or MEGA?) or STM32 Nucleo board.

Exactly. I have arduino Uno and E-paper shield & arduino NANO and E-paper HAT.

If you want to use the on-board SRAM, I assume you use the Waveshare demo and library.

Yes i want to use on-board SRAM, but i dont understand how the SRAM configuration works on the "Waveshare demo".

I don't know how you could drive the SPI panels with I2C, but you could use a I2C port expander for the CS pins.

I have no actual experience with the Waveshare demo and library, but I doubt it can be easily extended for multiple displays.

My library GxEPD2 has an example for multiple displays on ESP8266 or ESP32, but the library does not support external SRAM. GxEPD2_MultiDisplayExample

This is the limited help I can give you. Hopefully you get more answers to your post.

No problem, thx u very much for the answer.

I recently discovered that Waveshare now has a link to this topic in their Wiki pages.
See also post #1255.

So I have to expect more questions related to their demo code and library, especially for this shield.

Learning new things is the reason for me to "play" with Arduinos, e-papers, TFTs, and peripherals.

So most likely I will learn about the Waveshare demo for this shield in the coming week(s).
And maybe also about their "Loader" demo.

Ok thx, i will check.

But if someone has already made two e-papers work at the same time, I'm a taker.

I can't separate the SRAM. When I want to display image 1 on CS_1 and image 2 on CS_2, it displays both images on both PINs. I suspect that the problem comes from PROGMEM, but i'm not sure.

Hi ZinggJM.

I have a 2.9" B/W screen working properly. I can place images and text.

Now I need to load a BMP from HTTP. I follow your GxEPD_WIFI_EXAMPLE and I'm able to load images but not completely.

This is the output of the serial monitor:

downloading file "coca8.bmp"
connecting to xxxxxxx.com
requesting URL: http://xxxxxxxxx/bmp/coca8.bmp
request sent
headers received
File size: 38968
Image Offset: 1078
Header size: 40
Bit Depth: 8
Image size: 128x296
Error: got no more after 33324 bytes read!
bytes read 33324
loaded in 848 ms

For some reason, the read bytes are not the same as the file size.

I tried with the images used on your example but same results.
The screen loads partially the image.

The function used is "drawBitmapFrom_HTTP_ToBuffer" without any changes.

Any suggestions?

Thanks!!!!

Hi javiercuellar,

what happens with the bitmaps the original GxEPD_WIFI_EXAMPLE tries to download?

There is only one example with http:, the other bitmaps are on GitHub and use https:.

I had no problems with http:, but severe problems with https: on ESP8266, before using BearSSL.

I assume it is a timeout issue. The code for http: does not retry so hard (or at all) as for https.

If you or someone else has some good http: places with bitmaps for test, then I could do more tests.

Thanks for your answer.

I attach the file from the example (http://www.squix.org/blog/wunderground/chanceflurries.bmp).

Also attached another BMP of coca cola and the actual photo of both on the display so you can see it is cropped.

The chanceflurries.bmp on the screen... check carefully that it is missing part of the top black area.

I will take a look at the https example.

I don't know if it is time out problem because it updates very fast after I send the update order.

Thanks

chanceflurries.jpg

coca8.jpg

Just theck both functions

drawBitmapFrom_HTTPS_ToBuffer and
drawBitmapFrom_HTTP_ToBuffer

and the core code that goes after the file is open

Serial.print("requesting URL: ");
Serial.println(String("http://") + host + path + filename);

.....
.....

is exactly the same.

So, i'm not able to find this

ZinggJM:
The code for http: does not retry so hard (or at all) as for https.

Error: got no more after 33324 bytes read!

I think this is the relevant information. Did you get this error in all cases of wrong result?

Yes.

And also, all the pictures that I tested has the same problem. I download all bmp showed on the example from
raw.githubusercontent.com/ZinggJM/GxEPD2/master/extras/bitmaps and
raw.githubusercontent.com/prenticedavid/MCUFRIEND_kbv/master/extras/bitmaps/

The file is uploaded correctly, at least it shows, correct file and image size.

javiercuellar:
File size: 38968
Image size: 128x296

Looks like it skips something during the reading of the file..

No, it doesn't skip, it gets an incomplete download. Note that BMP files are in reverse order usually.

Please report which processor you use; I will check tomorrow. You use GxEPD as far as I see.

I'm using ESP-12s with librarys

#include <GxEPD.h>
#include <GxGDEH029A1/GxGDEH029A1.h>

Any suggestions for debugging? maybe checking if the real size of the received file before reading it ?

Thanks!

There is something wrong with WiFiClient on both platforms, ESP8266 and ESP32, but slightly different.

I didn't notice if this worked correctly on earlier versions, as the chanceflurries.bmp looked ok, but I had issues with big BMPs over https:.

I will check if I find a related issue reported for the platforms, but this is difficult, as there are many open issues.

For ESP8266 I get:

downloading file "chanceflurries.bmp"
connecting to www.squix.org
requesting URL: http://www.squix.org/blog/wunderground/chanceflurries.bmp
request sent
HTTP/1.1 200 OK

headers received
File size: 30138
Image Offset: 138
Header size: 124
Bit Depth: 24
Image size: 99x100
bytes read 28938
loaded in 503 ms
Power On : 37569
update : 4108839
Power Off : 40005

For ESP32 I get:

downloading file "chanceflurries.bmp"
connecting to www.squix.org
requesting URL: http://www.squix.org/blog/wunderground/chanceflurries.bmp
request sent
HTTP/1.1 200 OK

headers received
File size: 30138
Image Offset: 138
Header size: 124
Bit Depth: 24
Image size: 99x100
Error: got no more after 29892 bytes read!
bytes read 29892
loaded in 1258 ms
Power On : 37916
update : 4108103
Power Off : 39934

bytes read should be identical to File size for valid BMP files and successful download for bitmaps that fit on the sceen.

There is nothing I can do about this in the example, and yes, this part of the code is identical for http: and https:, both try to avoid failing on client.read() by checking client.available().

Aha, the WiFiClient can be disconnected but still have bytes available in the Stream.

This needs further investigation, but the following change seems to work:

uint32_t read(WiFiClient& client, uint8_t* buffer, int32_t bytes)
{
  int32_t remain = bytes;
  uint32_t start = millis();
  //while (client.connected() && (remain > 0))
  while ((remain > 0))
  {
    if (client.available())
    {
      int16_t v = client.read();
      *buffer++ = uint8_t(v);
      remain--;
    }
    else delay(1);
    if (millis() - start > 2000) break; // don't hang forever
  }
  return bytes - remain;
}

Hi

May be not a Waveshare screen..... I've just t tested new ePaper display from Lolin ( 2"13, 250x122, IL3897 controller)
Lolin EPD.png
connector.jpg

I'ts OK with GxEPD2 library and GxEPD2_213_B72 selected :slight_smile:
GxEPD_Example runs on D1 Mini ESP8266, fast partial display OK

Thanks for this library !

Lolin EPD.png

connector.jpg

Hi al1fch,

thanks for the feedback. The panel is almost certainly from Good Display.

For other users: please note that this board does not have level converters like the newer boards from Waveshare, it is for 3.3V supply and 3.3V data lines, perfect for Wemos/Lolin ESP8266 or ESP32.

Hi ZinggIM

After a lot of testing and hundreds of "Serial.println" everywhere, now it is working!!!! All BMP are loaded properly. Tested with 1, 4, 8,1 6 and 24 bit images.

What I did was comment on the line:

if (!connection_ok || !displayclient.connected()) break;

after both for-loop for rows and columns.

I think it is not needed to check it in those points because the reading of the file is done on functions: read16, read32, skip and read where you check for the correct connection.

      bytes_read += skip(rowPosition - bytes_read);
      for (uint16_t row = 0; row < h; row++, rowPosition += rowSize) // for each line
      {
    //   if (!connection_ok || !displayclient.connected())  break;
        delay(1); // yield() to avoid WDT
        uint32_t in_remain = rowSize;
        uint32_t in_idx = 0;
        uint32_t in_bytes = 0;
        uint8_t in_byte = 0; // for depth <= 8
        uint8_t in_bits = 0; // for depth <= 8
        uint16_t color = GxEPD_WHITE;
        for (uint16_t col = 0; col < w; col++) // for each pixel
        {
          yield();
        //  if (!connection_ok || !displayclient.connected()) break;
          // Time to read more pixel data?
          if (in_idx >= in_bytes) // ok, exact match for 24bit also (size IS multiple of 3)
          {
            uint32_t get = in_remain > sizeof(input_buffer) ? sizeof(input_buffer) : in_remain;

Now the serial monitor output shows (File size and bytes read are exactly the same!!):

request sent
headers received
File size: 39094
Image Offset: 1078
Header size: 40
Bit Depth: 8
Image size: 128x297
bytes read 39094
loaded in 925 ms

@javiercuellar,

ok, you are on the right track. Did you read post #1333?

I don't see displayclient in my code.

Not checking for client.connected() should be ok and does help, but not checking connection_ok will let the download hang indefinite if connection is lost.

I use "displayclient" instead of client. ( defined as WiFiClient displayclient; )

Yes, I also change suggestion on post #1333, not only on read () function, also on skip() function.

 //while (client.connected() && (remain > 0))
  while ((remain > 0))

but there were no changes, still cropped image.

After more testing, the code exits the for-loop (that is the reason for crop image) because in the line

if (!connection_ok || !client.connected()) break;

!client.connected() is true (don't know why, maybe because the downloaded file reaches EOF ?? )

So, finally, and following your suggestion left it as

 //     if (!connection_ok || !client.connected())  break;
        if (!connection_ok ) break;
        delay(1); // yield() to avoid WDT
        uint32_t in_remain = rowSize;
        uint32_t in_idx = 0;
        uint32_t in_bytes = 0;
        uint8_t in_byte = 0; // for depth <= 8
        uint8_t in_bits = 0; // for depth <= 8
        uint16_t color = GxEPD_WHITE;
        for (uint16_t col = 0; col < w; col++) // for each pixel
        {
          yield();
          //    if (!connection_ok || !client.connected()) break;}
          if (!connection_ok ) break;
          // Time to read more pixel data?