Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Performance improvements using spidev to update the 12.48inch e-Paper Module with Python #7

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

MediumFidelity
Copy link

@MediumFidelity MediumFidelity commented Mar 10, 2021

These changes significantly reduce the time required to process the image to display and update the panel. This is particularly true on less powerful hardware, like the Raspberry Pi Zero W. Highlights of the changes are:

  • Use the Python spidev library to access SPI, instead of a C "bit banged" implementation.
  • Transfer pixel data as a bulk transfer, using the SPI.writebytes2() function.
  • Access the bytes of the image using tobytes('raw').
  • Turn on DEBUG logging by default and print the times to transfer pixel data and update the panel.
  • Clean up some whitespace.
  • Lay the groundwork for a Jetson implementation.

The following dependencies are needed (similar to other Waveshare E Ink displays):

sudo apt install python3-pip python3-pil python3-numpy
sudo pip3 install RPi.GPIO
sudo pip3 install spidev

Using the existing demo code as an example running in the following environment, the runtime is greatly reduced.

Hardware:
Raspberry Pi Zero W
OS:
Raspbian GNU/Linux 10 (buster)
Software:
Python 3.7.3

Original:

python3 epd_12in48_test.py
real	2m41.054s
user	2m29.895s
sys	0m0.220s

Using branch epd12in48_spidev_python:

python3 epd_12in48_test.py
real	0m35.100s
user	0m13.356s
sys	0m7.339s

Further improvement are possible too, removing or tightening up sleep() calls and changing how the busy pin is polled.
Also, an initial call to clear() probably isn't needed due to how the entire panel is updated.

Experimental support for the 12.48inch e-Paper Module (B) has been added, but is untested with a real panel.

Use SPI.writebytes2() to send pixel data in builk.
…a significant performance improvement.

Use PIL to convert incoming images to 1-bit color and directly access the pixel data to send, which saves a lot of time on slower platforms.
@makew0rld
Copy link

Am I right in understanding this removes the dependency on DEV_Config.so entirely? Nice work.

@MediumFidelity
Copy link
Author

Am I right in understanding this removes the dependency on DEV_Config.so entirely?

Yes, I left it in there since I didn’t update the 3-color version of the panel. It’s on my todo list to get one to finish the job.

Nice work.

Thanks!

@makew0rld
Copy link

Ah, I didn't catch that this doesn't update the B model as well. I just ordered that product today. Once it arrives I would be happy to test the code. I'll admit I don't really understand what you've done, but maybe I could learn. Would the approach to speeding up the 3-color display be very different? I'd imagine it's just the same ideas applied to another part of the code. If you apply them and code it up I can test it for you.

@MediumFidelity
Copy link
Author

Would the approach to speeding up the 3-color display be very different?

It's about the same, the difference being that the black/white image and red image are written separately. I'll get those changes added in over the next few days. Keep in mind, that's software engineer's estimate, so it might be longer. ;-)

If you apply them and code it up I can test it for you.

Thanks for the offer, I'll take you up on that.

@MediumFidelity
Copy link
Author

@makeworld-the-better-one I just pushed the initial pass at supporting the B version (black/white/red) of the panel with Python on the Raspberry Pi. Let me know if it works for you, I can't test it.

Happy Pi Day!

@makew0rld
Copy link

That's great! My display hasn't arrived yet, it could be a week, could be longer. Once it does I'll try it out and let you know here. 𝜋

@makew0rld
Copy link

Could you also update the example epd_12in48B_test.py file?

…EBUG logger, and handle any exceptions when drawing to the panel.
@MediumFidelity
Copy link
Author

Good catch @makeworld-the-better-one, the epd_12in48B_test.py file has been updated. When your panel arrives let me know how testing goes. I'll update the PR to mention the dependencies to install on a Raspberry Pi to use it.

@fpammer
Copy link

fpammer commented Mar 25, 2021

@MediumFidelity Thank you for this hugely improved version.

I also tried to create a version without the dependency to the DEV_Config.so but ran into some issues. Your solution works and is faster then the original to boot!

Tested on the red/white/black version.

red-spiderman

@makew0rld
Copy link

makew0rld commented Mar 25, 2021

@fpammer Cool to see it works! I don't think you should need DEV_Config.so though, what was the issue?

@fpammer
Copy link

fpammer commented Mar 25, 2021

@fpammer Cool to see it works! I don't you should need DEV_Config.so though, what was the issue?

Sorry my wording was not very clear. The version in this pull request is great because it works without the DEV_Config.so. I was having trouble getting the SPI settings correct on my own attempt to get rid of the .so.

@MediumFidelity
Copy link
Author

@MediumFidelity Thank you for this hugely improved version.

You're welcome, I'm happy to help!

Tested on the red/white/black version.

Thank you very much for testing it on that panel. If mounting the panel in an IKEA frame isn't too complicated (I ordered a custom matte board), I'll probably pick up the red/white/black panel as well.

@makew0rld
Copy link

Just wondering, does this improve the advertised 8s (16s for color) refresh time? Or is that a minimum time sort of, and this just gets closer to it.

@MediumFidelity
Copy link
Author

Just wondering, does this improve the advertised 8s (16s for color) refresh time? Or is that a minimum time sort of, and this just gets closer to it.

That's the minimum time of a full panel refresh, so as it stands, this PR just gets closer to that.

@speedyg0nz
Copy link

Deleted my earlier comments since they were resolved. However, I noticed a weird situation when running the improved code. It's best seen from the image below, but somehow the colors came out inverted in the new code, when running the same example file provided. I'm not sure how @fpammer managed to display the image correctly, but when I tried to display any image, the red color always came out incorrectly inverted. Any thoughts, @MediumFidelity?

display2

@MediumFidelity
Copy link
Author

I'm not sure how @fpammer managed to display the image correctly, but when I tried to display any image, the red color always came out incorrectly inverted.

Hi @speedyg0nz, Sorry about the delay, missed the notification. I didn't have a tri-color display to test with, but it looks like the red channel bits are flipped. Agreed that I don't know how it'd work with others. Let me check the data sheet.

I still waiting for Waveshare to restock these displays (the red looks great!), but they say the semiconductor industry madness is causing them issues, so it might be a long time.

@speedyg0nz
Copy link

Hi @speedyg0nz, Sorry about the delay, missed the notification. I didn't have a tri-color display to test with, but it looks like the red channel bits are flipped. Agreed that I don't know how it'd work with others. Let me check the data sheet.

@MediumFidelity , thanks for getting getting back! Just wanted to say that this is amazing work and the display refresh time is indeed significantly shorter when running it on my RPi0. The inverted red channel is the only issue I encountered but otherwise it was simply a drop-in replacement.

I still waiting for Waveshare to restock these displays (the red looks great!), but they say the semiconductor industry madness is causing them issues, so it might be a long time.

Yeah, I got one around a year back when they still had stock and it was largely sitting around collecting dust until I finally completed my E-Ink desktop calendar project a few weeks back. Since then, I've been looking to optimize the performance and reduce the time needed to refresh the screen, since it runs off a small-ish battery.

@missionfloyd
Copy link

missionfloyd commented Mar 10, 2022

This repo seems to be abandoned. This could probably go in https://github.com/waveshare/e-Paper

@MediumFidelity
Copy link
Author

I just received a 12.48inch e-paper Module (B), they are finally back in stock. I'm looking through the changes @SSYYL introduced with the "V2" version of the B (red/black/white) panel. Looks like there were some initialization commands removed (defaults were okay?), but I still need to check the commands themselves to see if there are functional differences.

Once I sort that out, I'll get the performance improvements folded in again. I have a black/white version of the panel mounted in a frame, and displaying the "true" phase of the moon, and it looks beautiful.

@speedyg0nz I'll take a look at the red channel inversion too. It's easy to flip that stuff.

@MediumFidelity
Copy link
Author

MediumFidelity commented Dec 23, 2022

@speedyg0nz For the red issue, it was an easy fix to flip the value of the red channel. If you want to make a local edit, in the display function, use a bitwise NOT (the ~ in Python) when setting the values of the red channel in the buffer:

        for y in  range(492, 984):
            for x in  range(0, 81):
                buf_M1S2_black[idx] = buf_black[y*163 + x]
                buf_M1S2_red[idx] = ~buf_red[y*163 + x]   # <--- 
                idx += 1

There are 4 places to add it, for each of the 4 regions of the display.

I'm still going through changes Waveshare introduced to see what's what.

@SSYYL
Copy link
Collaborator

SSYYL commented Jan 13, 2023

Hi @MediumFidelity, Sorry it took so long to reply.
We launched V2 version, except for the hardware changes, the basic function is the same as V1.
The major changes were that the initialization function was updated, and external LUT (WaveForm) was not used
Any problems or improvements are welcome to submit issues or PR.

@speedyg0nz
Copy link

@speedyg0nz For the red issue, it was an easy fix to flip the value of the red channel. If you want to make a local edit, in the display function, use a bitwise NOT (the ~ in Python) when setting the values of the red channel in the buffer:

        for y in  range(492, 984):
            for x in  range(0, 81):
                buf_M1S2_black[idx] = buf_black[y*163 + x]
                buf_M1S2_red[idx] = ~buf_red[y*163 + x]   # <--- 
                idx += 1

There are 4 places to add it, for each of the 4 regions of the display.

I'm still going through changes Waveshare introduced to see what's what.

Finally got around to testing this out and adding the bitwise NOT fixed the color inversion! Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants