Waveshare e-Paper display only outputs garbled noise instead of an image

Hello fellow Arduinoers

I am trying to create a clock with an Arduino and an e-Paper display. My issue is, that the display only outputs garbled noise instead of the images I want it to display: see garbled output

My setup is like this:

I have transformed the pictures (they look like this picture of a 0) to byte arrays using image2cpp:

https://javl.github.io/image2cpp/

This is my code:

#include <SPI.h>
#include "epd1in54_V2.h"
#include "epdpaint.h"
#include <stdio.h>

#include "numbers.h";

Epd epd;
unsigned char image[1024];
Paint paint(image, 0, 0);

#define COLORED     0
#define UNCOLORED   1

unsigned long cur_time = millis();

void setup() {
  Serial.begin(115200);
  Serial.println("e-Paper init and clear");
  epd.LDirInit();
  epd.Clear();

  /*
  paint.SetWidth(200);
  paint.SetHeight(24);
  paint.Clear(UNCOLORED);
  paint.DrawStringAt(0, 0, "Clock", &Font24, COLORED);
  epd.SetFrameMemory(paint.GetImage(), 0, 0, paint.GetWidth(), paint.GetHeight());
  epd.DisplayFrame();
  */
  
  Serial.println("e-Paper show pic");
  epd.HDirInit();
  epd.Display(NUMBER_0);
  
  //Serial.println("e-Paper goto sleep");
  //epd.HDirInit();
  //epd.Clear();
  //epd.Sleep();
}

void loop() {
  /*
  cur_time = millis();
  paint.SetWidth(200);
  paint.SetHeight(24);
  paint.Clear(UNCOLORED);
  paint.DrawStringAt(0, 0, cur_time, &Font24, COLORED);
  
  Serial.print(F("printing time: "));
  Serial.print(cur_time);
  Serial.print(F(" image of "));
  Serial.print(paint.GetWidth());
  Serial.print(F(" x "));
  Serial.print(paint.GetHeight());
  Serial.print(F(" at 0 50 "));
  
  epd.SetFrameMemory(paint.GetImage(), 0, 50, paint.GetWidth(), paint.GetHeight());
  epd.DisplayPartFrame();
  */
  
  delay(10000);
  
}

and this is the image byte array:

// 'number_0', 32x32px
const unsigned char NUMBER_0 [] PROGMEM = {
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, 
  0xff, 0xe0, 0x1f, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xff, 0x87, 0xc3, 0xff, 0xff, 0x8f, 0xc3, 0xff, 
  0xff, 0x1f, 0xf1, 0xff, 0xff, 0x1f, 0xf1, 0xff, 0xfe, 0x1f, 0xf0, 0xff, 0xfe, 0x1f, 0xf0, 0xff, 
  0x7e, 0x3f, 0xf0, 0xff, 0x7e, 0x3f, 0xf8, 0xfe, 0x7e, 0x3f, 0xf8, 0xfe, 0x7e, 0x3f, 0xf8, 0xfe, 
  0x00, 0x00, 0x00, 0x00, 0x7c, 0x3f, 0xf8, 0xfe, 0x7c, 0x3f, 0xf8, 0xfe, 0x7c, 0x3f, 0xf8, 0xfe, 
  0xfe, 0x3f, 0xf8, 0xfe, 0xfe, 0x3f, 0xf0, 0xff, 0xfe, 0x1f, 0xf0, 0xff, 0xfe, 0x1f, 0xf1, 0xff, 
  0xff, 0x1f, 0xf1, 0xff, 0xff, 0x0f, 0xe1, 0xff, 0xff, 0x8f, 0xc3, 0xff, 0xff, 0x83, 0xc3, 0xff, 
  0xff, 0xc0, 0x07, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};

Can anyone help me out here???

Thanks and all the best,

Chris

Have you checked your image code matches the size and orientation of your display and that you’ve declared the array the correct size .

Try a small image first to see if the coding of the image is correct ( or an example with the display library ) or that the library works with your display to identify the problem area.

The image I am trying to display is only 32x32 pixel. I only exchanged the byte array of my picture with the byte array of the demo picture. According to the library, this is the display function:

void Epd::Display(const unsigned char* frame_buffer)
{
	int w = (EPD_WIDTH % 8 == 0)? (EPD_WIDTH / 8 ): (EPD_WIDTH / 8 + 1);
	int h = EPD_HEIGHT;

	if (frame_buffer != NULL) {
		SendCommand(0x24);
		for (int j = 0; j < h; j++) {
			for (int i = 0; i < w; i++) {
				SendData(pgm_read_byte(&frame_buffer[i + j * w]));
			}
		}
	}

	//DISPLAY REFRESH
	DisplayFrame();
}

So I only provide the char array - as shown above in my code.

Am I missing something here?

Unsure !

Do you know if and how I could check if my byte array is somehow wrong? I mean, the original code from waveshare is displaying a full size image and more less all I did, was exchanging the byte array of that image with my own :frowning:

An image with zero dimension? Maybe, I am not familiar with Waveshare code.

class Paint {
public:
    Paint(unsigned char* image, int width, int height);

I totally agree; I did not understand that as well

I also tried your GxEPD2 lib, but the example GxEPD2_Example gives me a warning about stability issues due to high memory demand

Sketch uses 25694 bytes (83%) of program storage space. Maximum is 30720 bytes.
Global variables use 1598 bytes (78%) of dynamic memory, leaving 450 bytes for local variables. Maximum is 2048 bytes.
Low memory available, stability problems may occur.

I actually would rather like to use your code instead of some strange wave share lib that seems outdated, but I also need to include code for RTC clock and GPS and so I rather constraint here.

You can reduce code size by commenting out example bitmaps.
You can reduce ram size by reducing MAX_DISPLAY_BUFFER_SIZE, page buffer size, leading to more pages using paged drawing with GxEPD2.

I have had byte array converters that give strange results , there’s no harm in trying another - lots on line

class Paint {
public:
    Paint(unsigned char* image, int width, int height);

The dimensions are not contained in the image; you need to provide them to the Paint class.

Oops, Paint is a canvas class. It doesn't take an image, but a memory location for the canvas. I should not answer to topics I barely know anything about.

void Epd::Display(const unsigned char* frame_buffer)
{
	int w = (EPD_WIDTH % 8 == 0)? (EPD_WIDTH / 8 ): (EPD_WIDTH / 8 + 1);
	int h = EPD_HEIGHT;

	if (frame_buffer != NULL) {
		SendCommand(0x24);
		for (int j = 0; j < h; j++) {
			for (int i = 0; i < w; i++) {
				SendData(pgm_read_byte(&frame_buffer[i + j * w]));
			}
		}
	}

	//DISPLAY REFRESH
	DisplayFrame();
}

This method expects a bitmap of the size of the display.

1 Like

Arghh. Does that mean, the library can only display images with the exact dimension of the display? That would ruin my idea. I wanted to create the digital equivalent of a flip clock

Ok. Feedback from my side:

I created a 200x200px image, converted it to byte array with the same service as originally, used the same code as in my initial post an et voila, as ZinggJM suggested, it now works.

Apparently the epd.display() function needs a full canvas. Now. That is an issue for me, as I would like to update partially, as in only single digits. Will close and promote ZinggJM reply as the answer.

Low Level Bitmap Drawing Support

  • bitmap drawing support to the controller memory and screen is available:
  • either through the template class instance methods that forward calls to the base display class
  • or directly using an instance of a base display class and calling its methods directly

from https://github.com/ZinggJM/GxEPD2/blob/master/README.md

If you don't need graphics, you don't need the graphics template class with its graphics buffer, just an instance of a driver class. It can draw bitmaps of sizes different from screen size. Even parts of a bitmap (from ram or code space).

Jean-Marc

1 Like

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