Waveshare e-paper displays with SPI

Thanks for the help. I had the wrong board manager URL which gave me 1.0.6 as the latest. Corrected the URL, installed 2.0.4 and it works perfectly. Thank you!

Hi. I was wondering if anyone would be willing to review my code. The code works to take the input from the serial monitor and then generate a QR code and display the text. This part works fine, but it will only work correctly the first time through the loop. The second time it only updates the text and does not generate a new QR code. I had it working perfectly earlier too and I can't figure out what changed! The issue stems from the code attached. Any help is much appreciated.

Edit I want to add that it makes it all the way to the point where the serial.print("end") is called without generating a new QR code, and then displays the text everytime new text is received in the serial monitor. If I remove the part after the "end, PAGE" printing it generates the new QR code perfectly every time.

void displayQRCode(char *msg, uint16_t x0, uint16_t y0)
// Paged display of the QR code with top left corner at (x0,y0) 
// on the display
{
  uint8_t QRData[qrcode_getBufferSize(QR_VERSION)];
  uint8_t blockSize;
  uint8_t page = 0;
 
  qrcode_initText(&QR, QRData, QR_VERSION, ECC_LOW, msg);
  PRINT("\n\nQR Size: ", QR.size);
  PRINT("\nLocation: ", x0);
  PRINT(",", y0);
  PRINT("\nDisplay Height: ", display.height());
 
  blockSize = (display.height() - (2 * QR_QUIET_ZONE)) / QR.size;
  PRINT("\nBlock Size: ", blockSize);
 
  Serial.print(F("\nGenerating QRCode Image - "));
  Serial.print(mesg);
  display.firstPage();
  do
  {
    page++;
    // Space all around
    display.fillRect(x0, y0, 
                     x0 + QR.size + (2 * QR_QUIET_ZONE), y0 + QR.size + (2 * QR_QUIET_ZONE),
                     GxEPD_WHITE);
 
    // For each vertical module
    for (uint8_t y = 0; y < QR.size; y++)
    {
      // Eor each horizontal module
      for (uint8_t x = 0; x < QR.size; x++)
      {
        if (qrcode_getModule(&QR, x, y))
          printQRBlock(x0 + (x * blockSize) + QR_QUIET_ZONE, 
                       y0 + (y * blockSize) + QR_QUIET_ZONE, 
                       blockSize, 
                       (qrcode_getModule(&QR, x, y)) ? GxEPD_BLACK : GxEPD_WHITE);
      }
    }
  } while (display.nextPage());
 
  Serial.print(F("\nEnd"));
  PRINT(" @ page ", page);
 
 display.setPartialWindow(0, 100, 296, 120);
  display.firstPage();
  do{
    display.fillScreen(GxEPD_WHITE);
    u8g2Fonts.setCursor(0, 128);
    u8g2Fonts.print(mesg);
    
  }while(display.nextPage());
}

Not likely, with incomplete code and no information about your hardware.
Ok, maybe someone with experience with the same QRcode code could help.

But maybe it is just a display.setFullWindow(); missing.

BTW: a backlink to previous information would be useful:

Version 3.1.3 of library GxEPD is available, install with Library Manager.

  • added support for GDEW0154T8 1.54" b/w 152x152 UC8151
  • added support for GDEW0154M09 1.54" b/w 200x200 JD79653A
  • added support for GDEW0154M10 1.54" b/w 152x152 UC8151D
  • added support for GDEH0154Z90 1.54" b/w/r 200x200 SSD1681
  • added support for GDEM0213B74 2.13" b/w 128x250 SSD1680
  • fixed methods updateWindow, updateToWindow, _rotate in all driver classes

Jean-Marc

Hi again. I was able to get the text and QR to display at the same time, you were correct, I need the display.setFullWindow() that was missing. The next thing I am struggling with is that I can't get the QR to encode everything that is entered in the serial monitor. I have tried so many things but there seems to be a limit and I can't make sense of the library for QR encoding. Anyone have any idea how to increase the amount of data that can be encoded into the QR? I know it is possible and it works perfectly until I enter too much into the serial monitor. Thanks


#include <qrcode.h>
#include <GxEPD2_BW.h>
#include <U8g2_for_Adafruit_GFX.h>

#include "GxEPD2_display_selection_new_style.h"

#define DEBUG 1
 
#if DEBUG
#define PRINTS(s)     do { Serial.print(F(s)); } while (false)
#define PRINT(s, v)   do { Serial.print(F(s)); Serial.print(v); } while (false)
#else
#define PRINTS(s)
#define PRINT(s, v)
#endif
 

const uint8_t CLK_PIN = 13;
const uint8_t DATA_PIN = 11;
const uint8_t CS_PIN = 10;
const uint8_t DC_PIN = 9;
const uint8_t RST_PIN =0 ;
U8G2_FOR_ADAFRUIT_GFX u8g2Fonts;
QRCode QR;

const uint16_t MSG_BUF_SIZE = 180;
char mesg[MSG_BUF_SIZE] = { '\0' }; // Serial input message buffer
 
const uint8_t QR_VERSION = 3;
const uint8_t QR_QUIET_ZONE = 4;    // quiet zone all around


void displayText(char)
{
  display.setPartialWindow(0, 115, 296, 20);
    uint16_t bg = GxEPD_WHITE;
  uint16_t fg = GxEPD_BLACK;
  u8g2Fonts.setForegroundColor(fg);         // apply Adafruit GFX color
  u8g2Fonts.setBackgroundColor(bg);
  u8g2Fonts.setFont(u8g2_font_lubI08_tf);
  display.firstPage();
  do{
    display.fillScreen(GxEPD_WHITE);
    u8g2Fonts.setCursor(0, 125);
    u8g2Fonts.print(mesg);
  }while (display.nextPage());
 }




bool readSerial(void)
{
  static char* cp = mesg;
  bool gotNewData = false;
 
  while (Serial.available())
  {
    *cp = (char)Serial.read();
    if ((*cp == '\n') || (cp - mesg >= MSG_BUF_SIZE - 2)) // end of message character or full buffer
    {
      *cp = '\0'; // end the string
      // restart the index for next filling spree and 
      // flag we have a message waiting
      cp = mesg;
      gotNewData = true;
    }
    else  // move char pointer to next position
      cp++;
  }
   
  return(gotNewData);
}
 



void printQRBlock(uint16_t x, uint16_t y, uint8_t size, uint16_t col)
// Draw a square block of size pixels. Drawing individual pixels as this is faster
// that line segments and much faster that a filled rectangle.
{
  for (uint16_t i = 0; i < size; i++)
    for (uint16_t j = 0; j < size; j++)
      display.drawPixel(x + i, y + j, col);
}




void displayQRCode(char *msg, uint16_t x0, uint16_t y0)
// Paged display of the QR code with top left corner at (x0,y0) 
// on the display
{
  display.setFullWindow();
  uint8_t QRData[qrcode_getBufferSize(QR_VERSION)];
  uint8_t blockSize;
  uint8_t page = 0;
 
  qrcode_initText(&QR, QRData, QR_VERSION, ECC_LOW, msg);
  PRINT("\n\nQR Size: ", QR.size);
  PRINT("\nLocation: ", x0);
  PRINT(",", y0);
  PRINT("\nDisplay Height: ", display.height());
 
  blockSize = (display.height() - (2 * QR_QUIET_ZONE)) / QR.size;
  PRINT("\nBlock Size: ", blockSize);
 
  Serial.print(F("\nGenerating QRCode Image - "));
  Serial.print(mesg);
  display.firstPage();
  do
  {
    page++;
    // Space all around
    display.fillRect(x0, y0, 
                     x0 + QR.size + (2 * QR_QUIET_ZONE), y0 + QR.size + (2 * QR_QUIET_ZONE),
                     GxEPD_WHITE);
 
    // For each vertical module
    for (uint8_t y = 0; y < QR.size; y++)
    {
      // Eor each horizontal module
      for (uint8_t x = 0; x < QR.size; x++)
      {
        if (qrcode_getModule(&QR, x, y))
          printQRBlock(x0 + (x * blockSize) + QR_QUIET_ZONE, 
                       y0 + (y * blockSize) + QR_QUIET_ZONE, 
                       blockSize, 
                       (qrcode_getModule(&QR, x, y)) ? GxEPD_BLACK : GxEPD_WHITE);
      }
    }
    } while (display.nextPage());

  Serial.print(F("\nEnd"));
  PRINT(" @ page ", page);
  
  
}



void setup()
{
   Serial.begin(57600);
  Serial.print(F("\nNeuralink Histo QR Code Generator\nEnter Data into Serial Monitor to Generate New QR Code\nEnsure line ending is newline"));
  display.init();
  display.setTextColor(GxEPD_BLACK);
  display.firstPage();
  display.setRotation(1);

  u8g2Fonts.begin(display); // connect u8g2 procedures to Adafruit GFX
  delay(1000);
 

}


void loop() {
  if (readSerial())
  {
   displayQRCode(mesg, 0, 0);
   //displayText(mesg);
  }}

Hey luki_v11,

I have the exact same problem you had. I did fix the screen size issue, but now i cannot use the color red from my screen. Did you also had that problem, and how did you fix it?

Hi @ZinggJM !

I come here to query some help..
I'm working on a tiny dashboard project, with a 1"54 - 200*200 - Waveshare e-paper display... But i'm absolutely unable to achieve a partial update... The full update works perfectly, but partial update just won't, and I don't understand why :thinking:

I dig a lot through the forum and diverse website... But I wasn't able to figure out what's go wrong...

Context : For the testing phase (and sharing it here), I just put all my code in the "main.cpp".
I try to display the numbers of second using millis(), and partialy refresh the display every second.
I'm using the GxEPD2 lib, with VSCode and PlatformIO.

So, here is my code !

#include <Arduino.h>

// Include libraries:
#include <Adafruit_GFX.h>
#include <GxEPD2_BW.h>
#include "epd/GxEPD2_154_D67.h"

#include <Fonts/FreeMonoBold12pt7b.h>

#define ENABLE_GxEPD2_GFX 0
#define MAX_DISPLAY_BUFFER_SIZE 200
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= MAX_DISPLAY_BUFFER_SIZE / (EPD::WIDTH / 8) ? EPD::HEIGHT : MAX_DISPLAY_BUFFER_SIZE / (EPD::WIDTH / 8))




GxEPD2_BW<GxEPD2_154_D67, MAX_HEIGHT(GxEPD2_154_D67)> display(GxEPD2_154_D67(/*CS=10*/ 10, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));


void setup() 
{
  // put your setup code here, to run once:
  display.init(115200);
  delay(100);
  
  display.setFullWindow();
  display.setRotation(1);

  display.setTextWrap(false); 
  display.setFont(&FreeMonoBold12pt7b);
  display.setTextColor(GxEPD_BLACK);
    //Basic configuration for the display
    
  display.firstPage();
  do
  {
      //Draw "hud" Elements, two lines and the label "Sec :"
      display.drawFastHLine(0, 100, 200, GxEPD_BLACK);
      display.drawFastVLine(100, 100, -100, GxEPD_BLACK);
      
      display.setCursor(15,50);
      display.print("Sec :");

  } while (display.nextPage());
    
 

}



void loop() 
{
  
  static uint32_t time = 0;
  static uint32_t l_time = 0;   //l_time stand for 'Last Time'
  
  
  time = millis();              //store the actual time.

  if (time - l_time >= 1000)    //Verify a gap of 1sec since the last excetution of the loop, then, command the display.
  {
    l_time = time;              //store the actual time in 'Last Time' to détermine the next gap
    
    
    display.setPartialWindow(100, 0, 98, 98);   // <-- don't want to work...
    display.setRotation(1);
    display.setFont(&FreeMonoBold12pt7b);
    display.setTextColor(GxEPD_BLACK);          //Configuration again. Don't know if it's needed. I just looked at how some other people code were built...

    display.firstPage();
    do
    {
      
      display.fillScreen(GxEPD_WHITE);    //Clean the previous display in the 
      display.setCursor(115, 50);
      display.print(time/1000);           // print the time value in front of the "Sec" label.
     
  
    } while (display.nextPage());

  }
        //this whole loop don't display anything. I don't know why...


}

Voilà ! I hope someone can help me... I'm sure a studip mistake I've made... but I'm kinda lost and don't know where the problem can come from.

I've also tried to run the "PartialUpdateExample" from the GxEPD lib.. It's seems to work, but I'm not sure it does exactly what he's supposed to do... :thinking:
The "GooDisplay" logo appear, then fade out gradualy.. And then nothing.. Just a slow grey flickering :sweat_smile:

Maybe my Board is screwed ?..

In advance, thanks you for your time, and your help !
Gabriel.

I have no idea what are you talking about. :slight_smile: I had many problems!

Just saw, that some people struggle with Certs. Just set your Client insecure and forget about Certificates. :stuck_out_tongue_winking_eye:

// Wifi Client for secure connection (HTTPS)
WiFiClientSecure client;

// No Certificate
client.setInsecure();

Hi @gmaveryck, I just noticed these two lines. Maybe you just need to exchange them:

    // setPartialWindow, use parameters according to actual rotation.
    // x and w should be multiple of 8, for rotation 0 or 2,
    // y and h should be multiple of 8, for rotation 1 or 3,
    // else window is increased as needed, 
    // this is an addressing limitation of the e-paper controllers
    virtual void setPartialWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h) = 0;

from e.g. GxEPD2_GFX.h, which can serve as an overview of the upper layer methods.
See also GxEPD2_BW.h

I did not check your code yet, e.g. for cursor positioning. Tell me if you need further help.

You need to provide a link to your display for your other issue, and for the connection module.

Jean-Marc

Added:
Waveshare seems to use a different panel now for the V2, without having changed the version!.
See fix 1in54_V2 partial refresh abnormal · waveshare/e-Paper@c28eca7 · GitHub
This controller has no wavetable for differential refresh in OTP.
Maybe it would work with GxEPD2_150_BN, panel GDEP0150BN 200x200, SSD1681, TTGO T5 V2.4.1.

Hi @ZinggJM
Thanks you for your answer !

First thing, sorry, I forgot the link, so, there it is :

The connection module is built-in if I understood correctly...
I read on some forum there's somes issues with this module/driver.. But I also read they were patched some times ago.. :person_shrugging:
So, I assume it's ok !
I use the GxEPD2 lib v1.4.8

So, I've tried to reverse these two lines

in this way :

    display.setRotation(1);
    display.setPartialWindow(100, 0, 98, 98); 

Unfortunately, nothing happen...

For the cursor position, I've already tried different thing.. Like in absolute and relative coordinates (in partialWindow mode) , multiple of 8, etc etc.. And always the same result :sweat_smile:

I just read your edit, and yes.. I seem to be a hardware/driver issue ! I'll take a look at this link and documentation !

Thanks you a lot again ! I'll keep you informed !
Gabriel.

EDIT :
I just try with the "GxEPD2_150_BN"... AND IT WOOORRRK !
Ehm.. Sorry ! But, hell ! I'm just so happy, after more than a week struggling on this issue !

Thanks you again AGAIN ! :grin:

Maybe, can I help on something to fix this issue in the lib ?

No need to, in my opinion. GxEPD2_154_D67 works with panel GDEH0154D67 from Good Display. This panel was also used by Waveshare with the V2 board, I believe. I do have that board and will verify. If Waveshare uses a different panel now, then this is a documentation issue.

But yes, you can do me a favor and report the inking you find on the flex connector.
The panel on TTGO 1.5" has just FPC8101.

Jean-Marc

I got the same inscription on mine.. "FPC-8101"
So, It seems to be a documentation issue, if I understand ?

Yes, Waveshare should state that they use a different panel now, and change the sticker to V3.
I may change the README.md to state that the GDEP0150BN now is used on Waveshare 1.5" b/w.

I verified that my Waveshare 1.54" b/w board with sticker V2 and panel with inking HINK-E0154A07-A1 works fine with GxEPD2_154_D67.

I think I miss explaing something..
I'm use the Waveshare 1.54" V2 display, with the FPC-8101 mark on it, and I was able to make it work using the GDEP0150BN lib..

I hope I didn't say something wrong earlier :sweat_smile:

Yes, thanks to your information we now know that the GDEP0150BN panel is used on the current Waveshare 1.54" b/w V2 board, and therefore works with the GxEPD2_150_BN driver class. Nobody will notice that the panel is1 mm less in diagonal dimension.

Jean-Marc

Okay ! My bad, sorry, I did not understood this !

Hello, The support that ZingJm gives is amazing..

I have a GoodDisplay GDEW042T2 with DESPI-CO2 board but I'm not sure of the pinout to use with a ESP32 Mini ( Pinout of Mini )

Info on the DESPI-CO2 Click Here

Hi again,

I assume you compile for the MH-ET LIVE ESP32MiniKit. Then you should take a look at
C:\Users\xxx\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.4\variants\mhetesp32minikit\pins_arduino.h to find:

static const uint8_t SS    = 5;
static const uint8_t MOSI  = 23;
static const uint8_t MISO  = 19;
static const uint8_t SCK   = 18;

These are the standard ESP32 HW SPI pins. So you should be able to use the suggested pins for ESP32 of GxEPD2.
I have not checked if any of the other pins (DC, RST, BUSY) need to be changed. You can check on the pinout yourself. If you need to change, you need to change the constructor parameters accordingly.

The DESPI-CO2 has the following pins labeled, but they don't match up with your explanation above. I'm looking online for non-standard labels but its confusing. Do you already have this documented or know where to find it?

BUSY
RES
D/C
CS
SCK
SDI
GND
3.3V