esp32-epaper-display
esp32-epaper-display copied to clipboard
Support EPD7in5_V2
Hi,
Please could you also support the new panels 7.5 V2 Black / White https://www.waveshare.com/7.5inch-e-Paper-HAT.htm
Thanks
Yes, but in the future.
I'm planning on abstracting the EPD to support more displays. I have a EPD2in7 i'll implement first, then i'll ring you up to test your display if you're okay with that.
Do you know the differences on the driver between v1 and v2. May I can help in development
The changes are quite small, it shouldn't be that difficult. Take a look at their repos here :
- https://github.com/waveshare/e-Paper/tree/master/Arduino/epd7in5_V2 (your version)
- https://github.com/waveshare/e-Paper/tree/master/Arduino/epd7in5 (the current version)
I took their code and change it a bit to put it in https://github.com/ugomeda/esp32-epaper-display/blob/master/epaper-esp32/src/epd.c
-
EPD_7in5__init()
isint Epd::Init(void)
-
EPD_WaitUntilIdle
isvoid Epd::WaitUntilIdle(void)
- etc
The pins are the same, you should only have to change the commands sent to the display.
Example :
EPD_SendCommand(0x01, "\x37\x00", 2); //POWER_SETTING
EPD_SendCommand(0x00, "\xCF\x08", 2); //PANEL_SETTING
EPD_SendCommand(0x06, "\xC7\xCC\x28", 3); //BOOSTER_SOFT_START
EPD_SendCommand(0x4, NULL, 0); //POWER_ON
EPD_WaitUntilIdle();
Should be replaced by
EPD_SendCommand(0x01, "\x07\x07\x3f\x3f", 2);
EPD_SendCommand(0x04, NULL, 0);
EPD_WaitUntilIdle();
Which is a translation of this code in Waveshare's implementation
SendCommand(0x01);
SendData(0x07);
SendData(0x07);
SendData(0x3f);
SendData(0x3f);
SendCommand(0x04);
DelayMs(100);
WaitUntilIdle();
If you get it working, please share the code :)
I have change the resolution to 800x480 on both server and ESP. but now the lodepng_decode throws an error 83 memory allocation failed on server also I have convert the image to grey-scale for test
I already had this problem, waveshare's ESP32 doesn't seem to have the 4MB additional memory and it fails. I developped a workaround at some point by loading the image into chunks, but it was very hacky. I fixed it by using a proper 2-bit image.
Loading the 2 colors 800x480 image in-memory only takes 2x800x480 bits, 94kB. This should fit easily into the 512 kB RAM of the ESP32. I'll try to find where i'm wasting so much memory tomorrow.
In the meantime, if you want to implement the color display, you can send a smaller image, ie a 800x240px image. It should display the top of the image, and random garbage after.
Ok, I manage to convert it to B/W and use 1 bit of depth. and It worked. But when I tried to send the image to the screen, esp got kernel panic
0;32mI (2734) EPD: Received new PNG of size 6654␛[0m
␛[0;32mI (2754) EPD: Sending image␛[0m
Guru Meditation Error: Core 1 panic'ed (LoadStoreError). Exception was unhandled.
Core 1 register dump:
PC : 0x400d1fc4 PS : 0x00060630 A0 : 0x800d2110 A1 : 0x3ffc78f0
A2 : 0x3ffe436c A3 : 0x00000320 A4 : 0x000001e0 A5 : 0x0001bc94
A6 : 0x00000001 A7 : 0x00000005 A8 : 0x40000000 A9 : 0x3ffc7917
A10 : 0x00000000 A11 : 0x00000028 A12 : 0x00000027 A13 : 0x00000000
A14 : 0x00000000 A15 : 0x00000000 SAR : 0x00000011 EXCCAUSE: 0x00000003
EXCVADDR: 0x40000000 LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xfffffffe
ELF file SHA256: cbcd4695c23db55df46f0af9d15a600fabee5c44e25d967637d9e0ca1451bfa8
Backtrace: 0x400d1fc1:0x3ffc78f0 0x400d210d:0x3ffc7950 0x400d1b1d:0x3ffc7a00 0x400d1bcc:0x3ffc7aa0 0x400904d9:0x3ffc7ae0
Rebooting... ets Jun 8 2016 00:22:57
Looks like you're trying to access memory which was not allocated. Probably because the PNG was loaded using 1-bit depth, but you're trying to read 2-bit depth images in the EPD code.
In epd.c
:
// 2-bit image, each byte contains 4 pixels
for (uint32_t i = 0; i < width * height / 4; i++)
{
...
Adapt the code after to read the proper indexes in the buffer.
could you explain a bit how you map the image ? It looks a bit complicate to me the EPD_loadImage
Yes, it's not straightforward since i have to translate from a 2-bit image to some weird 4-bit image. There is also a buffer to avoid sending the data pixel by pixel.
I'll try to explain as i write the code examples.
So, you're trying to draw a 1-bit image (= 8 pixels per byte) onto your 4-bit display. You'll have to go through the array (width x height) / (8 * 1-bit)
times :
for (uint32_t i = 0; i < width * height / 8; i++)
{
Then, extract each bit ((image[i] & (0x01 << X)) >> X
) and map it to the value the EPD expects (PIX_MAPPING[...]
) :
uint8_t pix_1 = PIX_MAPPING[(image[i] & (0x01 << 7)) >> 7];
uint8_t pix_2 = PIX_MAPPING[(image[i] & (0x01 << 6)) >> 6];
uint8_t pix_3 = PIX_MAPPING[(image[i] & (0x01 << 5)) >> 5];
uint8_t pix_4 = PIX_MAPPING[(image[i] & (0x01 << 4)) >> 4];
uint8_t pix_5 = PIX_MAPPING[(image[i] & (0x01 << 3)) >> 3];
uint8_t pix_6 = PIX_MAPPING[(image[i] & (0x01 << 2)) >> 2];
uint8_t pix_7 = PIX_MAPPING[(image[i] & (0x01 << 1)) >> 1];
uint8_t pix_8 = PIX_MAPPING[(image[i] & (0x03 << 0)) >> 0];
Looking at https://github.com/waveshare/e-Paper/blob/master/Arduino/epd7in5_V2/imagedata.cpp, it seems like the values are 0x00
and 0x03
for black/white, so no need to change the WHITE
, BLACK
or PIX_MAPPING
constants.
You then have to put the new 4-bit values into the buffer :
buffer[buffer_pos++] = pix_1 << 4 | pix_2;
buffer[buffer_pos++] = pix_3 << 4 | pix_4;
buffer[buffer_pos++] = pix_5 << 4 | pix_6;
buffer[buffer_pos++] = pix_7 << 4 | pix_8;
So this might be able to load the image into the display memory :
void EPD_loadImage(const uint8_t *image, const unsigned int width, const unsigned int height)
{
char buffer[BUFFER_SIZE];
int buffer_pos = 0;
// 2-bit image, each byte contains 8 pixels
for (uint32_t i = 0; i < width * height / 8; i++)
{
// each byte = 2 pixels
uint8_t pix_1 = PIX_MAPPING[(image[i] & (0x01 << 7)) >> 7];
uint8_t pix_2 = PIX_MAPPING[(image[i] & (0x01 << 6)) >> 6];
uint8_t pix_3 = PIX_MAPPING[(image[i] & (0x01 << 5)) >> 5];
uint8_t pix_4 = PIX_MAPPING[(image[i] & (0x01 << 4)) >> 4];
uint8_t pix_5 = PIX_MAPPING[(image[i] & (0x01 << 3)) >> 3];
uint8_t pix_6 = PIX_MAPPING[(image[i] & (0x01 << 2)) >> 2];
uint8_t pix_7 = PIX_MAPPING[(image[i] & (0x01 << 1)) >> 1];
uint8_t pix_8 = PIX_MAPPING[(image[i] & (0x03 << 0)) >> 0];
buffer[buffer_pos++] = pix_1 << 4 | pix_2;
buffer[buffer_pos++] = pix_3 << 4 | pix_4;
buffer[buffer_pos++] = pix_5 << 4 | pix_6;
buffer[buffer_pos++] = pix_7 << 4 | pix_8;
if (buffer_pos == BUFFER_SIZE || i == width * height / 8)
{
EPD_SendData(buffer, buffer_pos);
buffer_pos = 0;
}
}
}
I hope it helps !
why in the last pixel you use 0x03 and on the other 0x01? uint8_t pix_7 = PIX_MAPPING[(image[i] & (0x01 << 1)) >> 1]; uint8_t pix_8 = PIX_MAPPING[(image[i] & (0x03 << 0)) >> 0];
also as i understand you get 1 pixel / bit from image (so it should be black or white (0x00 or 0xFF) and then what do you try to do???
also I have done many trials with the code. I dont have any errors or kernel panic but it shows just random pixels
Can you fork the project and push your modifications so i can have a look ?
ok done https://github.com/antonatosn/esp32-epaper-display/tree/master/epaper-esp32
Found a few things :
EPD_SendCommand(0x01, "\x07\x07\x3f\x3f", 2);
The second parameter should be 4 (the length of the string), sorry about that.
EPD_SendCommand(0x00, "0x1F", 0);
You're sending the string "0x1F", you want this :
EPD_SendCommand(0x00, "\x1F", 1);
EPD_SendCommand(0x50, "\x10\x07", 2);
EPD_SendCommand(0x60, "\x22", 1); //TCON_SETTING
EPD_SendCommand(0x15, "\x00", 1);
//EPD_SendCommand(0x61, "\x02\x80\x01\x80", 4); //TCON_RESOLUTION
EPD_SendCommand(0x61, "\x03\x20\x01\xE0", 4);
//EPD_SendCommand(0x82, "\x1E", 1); //VCM_DC_SETTING: decide by LUT file
//EPD_SendCommand(0xE5, "\x03", 1); //FLASH MODE
EPD_SendCommand(0x10, NULL, 0); //DATA_START_TRANSMISSION_1
Doesn't to be updated, it should match https://github.com/waveshare/e-Paper/blob/master/Arduino/epd7in5_V2/epd7in5_V2.cpp#L61 :
SendCommand(0x61); //tres
SendData(0x03); //source 800
SendData(0x20);
SendData(0x01); //gate 480
SendData(0xE0);
SendCommand(0X15);
SendData(0x00);
SendCommand(0X50); //VCOM AND DATA INTERVAL SETTING
SendData(0x10);
SendData(0x07);
SendCommand(0X60); //TCON SETTING
SendData(0x22);
Also add this, which is the beginning of DisplayFrame()
SendCommand(0x13);
I ve made those change. Now its not flickering on startup but also doesn't show anything check on my repo i have update the code. May I missed something?
Il take a look tomorrow !
On Sun, May 3, 2020, 3:15 AM Nikos Antonatos [email protected] wrote:
I ve made those change. Now its not flickering on startup but also doesn't show anything check on my repo i have update the code. May I missed something?
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/ugomeda/esp32-epaper-display/issues/1#issuecomment-623037824, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAHDT46VPM7TJWAANDAXDRDRPTAUDANCNFSM4MXW2GVA .
I made some change and now something has started to appear. the picture is not clear but i can see the temp value and the weather icons but they are huge size. and also I am seeing vertical lines
Can you confirm you have the color version of the EPD ? Can you send a picture ?
If you can see something, It means you're pretty close !
A few more things to match the demo code :
EPD_SendCommand(0x4, NULL, 0); //POWER_ON
EPD_WaitUntilIdle();
//EPD_SendCommand(0x00, "0x1F", 1); //PANNEL SETTING
//KW-3f KWR-2F BWROTP 0f BWOTP 1f
EPD_SendCommand(0x00, NULL, 0);
Should be
EPD_SendCommand(0x4, NULL, 0); //POWER_ON
vTaskDelay(100 / portTICK_PERIOD_MS);
EPD_WaitUntilIdle();
EPD_SendCommand(0x00, "\x1f", 1);
The logic for the WaitUntilIdle seems to send a 0x71, change the function for this :
void EPD_WaitUntilIdle()
{
EPD_SendCommand(0x71, NULL, 0);
while (gpio_get_level(PIN_SPI_BUSY_NUM) == 0)
{
vTaskDelay(100 / portTICK_PERIOD_MS);
EPD_SendCommand(0x71, NULL, 0);
}
}
I'm also looking at this :
void Epd::Clear(void) {
SendCommand(0x10);
for(unsigned long i=0; i<height*width; i++) {
SendData(0x00);
}
SendCommand(0x13);
for(unsigned long i=0; i<height*width; i++) {
SendData(0x00);
}
SendCommand(0x12);
DelayMs(100);
WaitUntilIdle();
}
This is weird, seems like it's 1-byte per pixel and there is 2 commands to write 2 images, i'll look into it.
Ouch, so many things wrong here, you said you were using the B/W version in the first message, i thought you had the color version...
Let me see what changes...
Actually, the code is all for the B/W version, amazing !
So, more things comming from https://www.waveshare.com/wiki/File:E-Paper_ESP32_Driver_Board_Code.7z
{ EPD_7in5__init , EPD_loadE, -1 , 0, EPD_showC, "7.5 inch b" },// u 20
{ EPD_7in5_V2_init , EPD_loadAFilp, -1 , 0, EPD_7IN5_V2_Show, "7.5 inch V2" },// w 22
Seems line loadAFilp uses 1-bit -or 2-bit ?) images :
void EPD_loadAFilp()
{
// Come back to the image data end
Buff__bufInd -= 8;
// Get the index of the image data begin
int pos = Buff__bufInd - Buff__getWord(Buff__bufInd);
// Enumerate all of image data bytes
while (pos < Buff__bufInd)
{
// Get current byte
int value = Buff__getByte(pos);
// Invert byte's bits in case of '2.7' e-Paper
if (EPD_invert) value = ~value;
// Write the byte into e-Paper's memory
EPD_SendData(~(byte)value);
// Increment the current byte index on 2 characters
pos += 2;
}
}
Try sending the buffer directly to see what happens :
void EPD_loadImage(const uint8_t *image, const unsigned int width, const unsigned int height)
{
char buffer[BUFFER_SIZE];
int buffer_pos = 0;
EPD_SendCommand(0x13, NULL, 0);
for (uint32_t i = 0; i < width * height / 8; i++)
{
buffer[buffer_pos++] = image[i];
if (buffer_pos == BUFFER_SIZE || i == width * height / 8)
{
EPD_SendData(buffer, buffer_pos);
buffer_pos = 0;
}
}
}
it works.. but the color is opposite (its like negative where white is black and black white) also the size of the picture is smaller
also if I set EPD_SendCommand(0x00, "0x1F", 1); on init its not updating the panel
Amazing !
To revert the colors, juste use buffer[buffer_pos++] = ~image[i];
.
For the init, use "\x1f"
, NOT "0x1F"
.
Also make sure the method EPD_shutdown
matches waveshare's implementation.
Shutdown is the same no changes need
I ve try again on the init EPD_SendCommand(0x00, "0x1f", 1);
but its not working. I leave it off. it works without it
so the next thing is to make the image fit on screen On server I have change the image res to produce 800x480
[2020-05-03 13:48:25,953] :: INFO :: root :: {'version': 'p0t365fovq41yaimffkm078lvcwf2hho', 'image': <PIL.Image.Image image mode=1 size=800x480 at 0x7FB3F1600F28>, 'next_update': 93124.60900626}
also, another issue that i have is about locale. I change it to Greek language and the letters came as square boxes
To fit the image on the screen : please refer to the README, you have to update the size and position of your widgets.
Locale issue : this should not happen, the fonts used are OpenSans and LiberationSans, they both implement greek letters... I will have to look into that also.