E-paper: GxEPD2 library, multidisplay with multiplexer

Hi to the forum,

I have a little project, i want to digitize a tennis scoreboard. I bought 6 e-paper weactstudio 2,9 inch (2 per each tennis set, 3 sets overall).

According to GitHub - WeActStudio/WeActStudio.EpaperModule: WeAct Studio 2.13/2.9 Inch Epaper Module EPD I was able to address the display using the GxEPD2_290_BS module using an ESP32 board.

To use more displays I have to spent 4 gpio pins for each display like:

GxEPD2_BW<GxEPD2_290_BS, GxEPD2_290_BS::HEIGHT> heimSet1(GxEPD2_290_BS(/*CS=5*/ 35, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 15)); // DEPG0290BS 128x296, SSD1680
GxEPD2_BW<GxEPD2_290_BS, GxEPD2_290_BS::HEIGHT> gastSet1(GxEPD2_290_BS(/*CS=5*/ 34, /*DC=*/ 14, /*RST=*/ 12, /*BUSY=*/ 2)); // DEPG0290BS 128x296, SSD1680

The proposals in the GxEPD2_MultiDisplayExample.ino example in the GxEPD2 didn't work for me, so with 6 displays I am running out of gpio pins.

And here is my question. Can I use a I/O multiplexer (like 74HC4051) for each of the CS,DC,RST,BUSY pins, so that I am having just one display object in my code and for each action I address the corresponding pins of the display I want to use via the multiplexer?

... and if this is a bad idea does anyone has another solution for my problem?

Best regards

Joachim

You could be more specific, then someone might be able to help.

In general, only CS and BUSY can't be shared. For RST you need the trick shown in the example.
And you could use wired or for BUSY.
Of course you can use a multiplexer for CS.
-jz-

DEPG0290BS has BUSY active HIGH, so use a 6-to-1 or 8-to-1 OR gate.
If you intend to use display hibernate, then you need to specify RST for each. Would need gated RST connections.
Use either a gated multiplexer for CS, or one input of the multiplexer as "enable" for the common CS parameter in the constructors.

Hi,

thank you for your fast reply. Here is my code to address 2 displays at once which didn't work well.

In my reset_display function I draw the digit 0. In setup I do this first for heimSet1, then for gastSet1. But the digits 0 is being shown simultaneously for two times. So with my setup I think that the displays are not driven separately. After that I draw the digit 4. It is also on both displays but on one the "0" shines through.

#define ENABLE_GxEPD2_GFX 0

#include <GxEPD2_BW.h>
#include <GxEPD2_3C.h>
#include <Fonts/FreeMonoBold9pt7b.h>
#include "digits.h"

GxEPD2_BW<GxEPD2_290_BS, GxEPD2_290_BS::HEIGHT> heimSet1(GxEPD2_290_BS(/*CS=5*/ 35, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 15)); // DEPG0290BS 128x296, SSD1680
GxEPD2_BW<GxEPD2_290_BS, GxEPD2_290_BS::HEIGHT> gastSet1(GxEPD2_290_BS(/*CS=5*/ 34, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 2)); // DEPG0290BS 128x296, SSD1680

void setup()
{

  Serial.begin(57600);
  Serial.println("Es geht los ...");
  
  heimSet1.init();
  gastSet1.init();
  
  reset_display(heimSet1);
  reset_display(gastSet1);
  
  drawTheDigit(heimSet1,4);
  
}

void reset_display(GxEPD2_BW<GxEPD2_290_BS, GxEPD2_290_BS::HEIGHT>& display) {

  Serial.println("Setze auf Null ...");

  display.setRotation(0);
  display.setFullWindow();
  display.firstPage();

  do
  {
    display.fillScreen(GxEPD_WHITE);
    display.drawInvertedBitmap(0, 0,epd_bitmap_0b, 128, 296, GxEPD_BLACK);
  }
  while (display.nextPage());
  
}

void drawTheDigit(GxEPD2_BW<GxEPD2_290_BS, GxEPD2_290_BS::HEIGHT>& display, int digit) {

  display.setRotation(0);
  display.setPartialWindow(0, 0, display.width(), display.height());
  display.firstPage();

  do
  {
    display.fillScreen(GxEPD_WHITE);
    display.drawInvertedBitmap(0, 0,epd_bitmap_allArray[digit] , 128, 296, GxEPD_BLACK);
  }
  while (display.nextPage());
 
}

void loop() {
  // put your main code here, to run repeatedly:
}

This is the result picture:

Is this approach wrong?

Kind regards,

Joachim

Yes.

// create display class instances for each display, each instance with different CS line, each instance with RST disabled,
// (or use separate RST pins for each display),
// each instance with different BUSY line, or BUSY lines or-ed to one pin
// disable reset line to disable cross resets by multiple instances

Didn't you understand what cross resets means?

RST parameter needs be set to -1, so init() will not (cross-)reset the displays.

  // one common reset for all displays
  digitalWrite(RST_PIN, HIGH);
  pinMode(RST_PIN, OUTPUT);
  delay(20);
  digitalWrite(RST_PIN, LOW);
  delay(20);
  digitalWrite(RST_PIN, HIGH);
  delay(200);

  display1.init(115200); // enable diagnostic output on Serial
  display2.init(115200); // enable diagnostic output on Serial
  display3.init(115200); // enable diagnostic output on Serial
#if defined(ESP32)
  display4.init(115200); // enable diagnostic output on Serial
#endif

Added:

I had to re-think and check for the possible cross-reset effect.
Cross-reset would only be an issue if hibernate() is used, as the controller needs reset for wake-up.
The cross-reset on init() isn't an issue, as the controller initialization occurs only at first write to the controller buffer.

You seem to have some other issue. And I don't know if diagnostic output would be of any help.
Could it be that one of your CS lines is stuck at zero?

IO34 6 I GPIO34, ADC1_CH6, RTC_GPIO4
IO35 7 I GPIO35, ADC1_CH7, RTC_GPIO5

Your CS lines are on input only ESP32 pins!

H,

thanks again for your reply.
A little step forward. I was able to "share" the reset pin with this code.

#define ENABLE_GxEPD2_GFX 0

#include <GxEPD2_BW.h>
#include <GxEPD2_3C.h>
#include <Fonts/FreeMonoBold9pt7b.h>
#include "digits.h"

#define RST_PIN 16

GxEPD2_BW<GxEPD2_290_BS, GxEPD2_290_BS::HEIGHT> heimSet1(GxEPD2_290_BS(/*CS=5*/ 35, /*DC=*/ 17, /*RST=*/ -1, /*BUSY=*/ 15)); // DEPG0290BS 128x296, SSD1680
GxEPD2_BW<GxEPD2_290_BS, GxEPD2_290_BS::HEIGHT> gastSet1(GxEPD2_290_BS(/*CS=5*/ 34, /*DC=*/ 12, /*RST=*/ -1, /*BUSY=*/ 2)); // DEPG0290BS 128x296, SSD1680


void setup()
{

  Serial.begin(115200);
  Serial.println("Es geht los ...");

  // one common reset for all displays
  digitalWrite(RST_PIN, HIGH);
  pinMode(RST_PIN, OUTPUT);
  delay(20);
  digitalWrite(RST_PIN, LOW);
  delay(20);
  digitalWrite(RST_PIN, HIGH);
  delay(200);
  
  heimSet1.init();
  gastSet1.init();
  
  reset_display(heimSet1);
  reset_display(gastSet1);
  
  drawTheDigit(heimSet1,4);

 
}

But when I connect both DC displays wire to pin 17 the result stays as above, both displays are driven simultaneously.

Best regards,

Joachim

Check my addition concerning your CS pins.

Hi and thank you,

I changed the CS Pins to 25,26 and it worked.

You said that CS and BUSY can't be shared but in the example It seems to be possible doing this:

// BUSY lines can be or-ed with diodes and pulldown register for displays with BUSY active HIGH

As I am not an expert in electonics i need a little help in explication. I suppose that this is the 8-to-1 OR gate you mentioned above.

Would this be the right gate for me?
https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&ved=2ahUKEwjHs4zB5N7_AhXI-KQKHWagBGIQFnoECDEQAQ&url=https%3A%2F%2Fwww.st.com%2Fresource%2Fen%2Fdatasheet%2FCD00000322.pdf&usg=AOvVaw2IvwrNddnk38yAYrgxBghP&opi=89978449

... and I connect the BUSY wires of the display to PIN A-G of the IC and connect the BUSY PIN configured in my code to PIN X.

What do I have to do in addition ( -> with diodes and pulldown register for displays with BUSY active HIGH, do you mean pulldown resistor?)? i.e. connect the configured BUSY PIN with a 10 kOhm resistor to ground ...

Sorry for my (silly) questions.

Thanks again,

Joachim

Yes, this should work. It seems to work in a wide voltage range, and has non-inverted and inverted output. And it is a clean solution.

When I did my proto-board to test with multiple displays, I didn't have a suitable device, and used diodes and a pull-up or pull-down resistor instead. I used both, Pull-down for BUSY active HIGH and pull-up for active low, on two separate IO pins.

See https://forum.arduino.cc/t/waveshare-e-paper-displays-with-spi/467865/232

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.