Open tobiasaska opened 5 years ago
From my experiences, the size and detail of the image seems to make a difference. Converting the image to a C-file before or using the IT8951 bmp-conversion function doesn't seem to make too much of a difference. Experimenting with partial updates where you only have to push a select buffer size can also help.
For now, designing for e-ink screens still seems to require thinking around the limited refresh rate.
But curious if waveshare has any suggestions too!
From my experiences, the size and detail of the image seems to make a difference. Converting the image to a C-file before or using the IT8951 bmp-conversion function doesn't seem to make too much of a difference. Experimenting with partial updates where you only have to push a select buffer size can also help.
For now, designing for e-ink screens still seems to require thinking around the limited refresh rate.
But curious if waveshare has any suggestions too!
Thank you for your reply. The problem does not seem to be the actual refresh rate which is around 450ms. The problem is the time to write the image from host frame buffer to IT8951 frame buffer. This takes 10 seconds using your demo code running on raspberry pi 3. For example when I use the demo program for windows providet by waveshare it doesnt take that long. How can I display a new image every 450ms or at least every second ?
I'm not part of waveshare, so I'm not sure... We've also noticed that the Windows application seems faster. Are you pushing full resolution bmp's? Don't small images or graphics from the other demo functions go faster?
I made it ~10 times faster by not using LCDWriteData but writing my own function that internally send all the data in one call. I also switched to 4BPP instead of 8 and made it again 2x faster. @tobiasaska
That sounds amazing @naluhh! Any plans to share your changes? Would love to try them out!
I made a quick test yesterday. I'm trying to make it even faster by extracting the picture directly into a 4bpp texture. I'm only planning on doing full screen updates. I'll share some code this week
I made it ~10 times faster by not using LCDWriteData but writing my own function that internally send all the data in one call. I also switched to 4BPP instead of 8 and made it again 2x faster. @tobiasaska
@naluhh Thank you very much for this piece of information. Thats exacly what i was looking for. I am pretty new to coding. Would you mind sharing your code with me/us?
https://github.com/waveshare/IT8951/pull/3
It's a work in progress. But you can try like this:
make
sudo ./IT8951 path_to_image.bmp
3
It's a work in progress. But you can try like this:
make sudo ./IT8951 path_to_image.bmp
Thank you! I will try this 👍
Tried it just now. Very noticeable speed boost! Awesome! Thank you! I think you also managed to move to 4bpp? Anyway to also include 8bpp as an option? Or would that reduce the performance boost significantly? You mentioned that even with 8bpp your changes were much faster. My application has some images that require the higher resolution...
@JorgosCoenen 4BPP is the maximum these screens can do anyway. Right now it's decoding the BMP in 8bpp and I then translate it to 4bpp. It would be much faster (less allocation, smaller file etc) to have a 4bpp image (png support it). I'm sure other optimizations could be done.
Could you try to replace this line:
stLdImgInfo.usEndianType = IT8951_LDIMG_B_ENDIAN;
by
stLdImgInfo.usEndianType = IT8951_LDIMG_L_ENDIAN;
Sure! Seems this makes the "interlacing" more pronounced. An image.
What's the resolution of your screen?
Ah, I'm using the 9.7" screen, so 1200x825. My images or also this resolution. I now notice that this repository only seems to refer to the 6" display... There doesn't seem to be one for the 9.7"🤨
I'm using the 10.3" one. Odd number of pixels (y axis) might be the problem with your screen. Without access to the hardware it'll be hard for me to fix it. It was working well for me, probably an alignment thing. Meanwhile you can go back to 8BPP. (You'll need to comment the loop, remove the / 2 on buffer size, and switch 4BPP to 8BPP)
Oh wow, hadn't seen that one, looks pretty great. Alright, looks back to normal (had to keep your "B_ENDIAN") and definitely still faster.
A good chunk of the time goes into turning on the screen, and decoding the bmp image. Both of them could be reduced. Pre-uploading image you want might help too. (the buffer is big enough to store several images)
Yeah, I keep the screen turned on in my application (added freeing the buffer to the bmp-function, instead of always using the cancel-function).
Does the library include anything to upload multiple images and switch between them? Would definitely also be an interesting hack.
the library doesn't support that. Be carefull, don't leave it on too long, you might reduce the lifespan of your screen/controller
Thanks for the heads-up! We have had them running for some long periods without noticeable impact so far. The only thing I've noticed is that sometimes the frame we built behind the screen become visible on the display if it's powered off (especially when in sun light). As if it's shining through.
No doubt that you'll reduce your screen lifespan and greatly increase the consumption by doing so
By decoding the image directly into the buffer, allocating only what's needed and optimizing and merging a few spi calls I was able to increase the speed even further. Depending on the raspberry pi you are using you might be even able to change the clock rate doing a 2x or 4x on the upload speed.
Impressive! We've been using both Pi zero's and 3B+'s, depending on the processing/battery required. On the zero's this is probably not possible?
@naluhh
Wow! You are solving all my problems I had working with the IT8951. You must have a lot of experience on this field. Thank you for sharing your improvements with us!
Can you try to replace BCM2835_SPI_CLOCK_DIVIDER_32 by BCM2835_SPI_CLOCK_DIVIDER_16 then BCM2835_SPI_CLOCK_DIVIDER_8, BCM2835_SPI_CLOCK_DIVIDER_4(in the init func). (Keep going down until it stop working basically). Stay on the commit of my branch you were.
Anything below 16 doesn't work on my Pi Zero (just a flicker in the top left corner). Slightly faster compared to at 32, yes! Don't have a 3B+ at hand right now, but I could try with that too.
Edit: this is still with the loop commented out and the 8bpp
I'm curious about the result on the 3B+. Could you give me back the results you get?
Also, if you don't care about accuracy, you could switch to 1 bpp buffer, which would divide the transfer duration by ~8 in your case
Ok, did manage to test on a 3B+. Getting the same result as on the Zero, only a flickering rectangle in the top left corner with clock_divider below 16. This rectangle flickers and goes away , the previous image stays on screen. But again, definitely a speed bump with 16 instead of 32 and I'm not noticing any quality loss. Full resolution (1200x825) bmp images are pushed in ~1 second (excl. init time).
You could also remove the line
EPD_Clear(0xff);
if you don't plan on showing partials image
Yeah, thanks so much, this has been really helpful!
Do you think having the images converted into arrays and using the EPD_DrawMatrix() function would be faster than the Show_bmp() function? I didn't see much of an improvement when we did this on the original code, but maybe with your changes?
I don't know, I personally switched to 4bpp png for performance/size reasons. (You can see the tip of my branch with libpng)
I optimized the maximum I could. I think someone with more knowledge on the subject could go even further. For my resolution (1872*1404) I'm able to reach 0.9 sec / image. For 1200x825 I reached 0.63 sec / image. The buffer upload takes 60% of the time, so if you are able to pre-upload your images, or upload severals images at the same time you could reach higher speed (the other part, IT8951LoadImgStart, takes 40% of the time but I don't have any clue on how to increase it's speed).
Really terrific results! Thanks again!
Could you say a little more about using png's instead of bmp's? I want to keep the same image quality (8bpp I guess), but using png's would really help our workflow and performance (I'm generating images in d3.js and having to convert them to bmp's in JS is not trivial for me and takes some time/processing power).
As I said, 4bpp is the maximum quality you'll get. If I had access to your screen, I could certainly fix it. The tip of my branch works with 4bpp png as input. Here is a video with a loop decoding png + uploading to the buffer + updating the screen
Do you mean that the display will not go above 4bpp, or the input image png has to be 4bpp?
I'm trying your branch now.
I don't understand why, but one of my Pi Zero will not go below 32 for the BCM2835_SPI_CLOCK_DIVIDER. It messes up the initialisation at least. I noticed it before too, when I wasn't using your latest branch with the png, but was just trying the lower values.
sudo ./IT8941 test-4bpp.png "** IT8951 ** Panel(W,H) = (1784,829) Image Buffer Address = 19F1F0 FW Version = {8?;?9~ LUT Version = o<>9"
When I put it at 32, it initialized correctly, but still crashes afterwards (whole Pi becomes stuck): sudo ./IT8941 test-4bpp.png "init start ** IT8951 ** Panel(W,H) = (1200,825) Image Buffer Address = 11A1E0 FW Version = SWv_0.2.1T LUT Version = M841"
I hardcoded my screen size, that's why (and also require a 4bpp png as input). The display is 4 bpp, therefore having an image higher than that is pure waste.
@naluhh how do you create 4bpp png? could you please add some examples of files and the process. Thank you!
I made a repo @pshkvsky https://github.com/naluhh/4bpp-converter/
hey @naluhh .. you implementation regarding the socket stuff looks very promising, but i cant get it run. Can you provide a working example?
I could get the socketserver working and got also client connection messages, when i did:
nc localhost 8888 < ~/test-out.png
i got always the message that the file is not valid. i tried also to supply the filename only, but without success.
nc localhost 8888 < <(echo ~/test-out.png)
what do i wrong here? ;)
May thanks in advance!
it's expecting a local path: ||Ufilename.png|| will make the client look for filename.png (4bpp png) and update it to the screen. If it doesn't have the file, it'll request it by sending a ||Dfilename.png|| to the server and expecting it to send it as png. It'll then cache it locally. I don't provide support for it, sorry
You can convert any image to a 4bpp via imagemagicks's convert a.png -depth 4 b.png
. I'm running @naluhh 's server, it's working really great!
1) Can i Store the Multiple image Buffer into IT8951 2) Can i load the one image half half buffer into IT8951 and then after Display
Hello, I am working with Raspberry Pi 3 and the 10.3" Epaper Display from Waveshare. The refresh rate is very fast but the time to write the data from host frame buffer to IT8951 Frame Buffer is about 10 seconds. This is way to long for my application. Is there any way to make this process faster? Or can write multible images to different Frame Buffers on the IT8951? Has this to do with SPI interface?