waveshare 2.13b (blk/wht/red) displays nothing but mostly red garbage.
Hi there!
firstly thanks for all the awesome work on this. I'm super excited to play with it.
It seems the 2.13b is different enough that the standardization of the driver seems to have sorta rendered it unfunctional.
I'll play around with it and see if I can't get something working, but figured I'd open an issue first before digging in.
Hi,
Thanks for the info - I don't think I've heard anyone try the tricolor variety of this yet (I haven't had time to try my 2.9" tricolor one yet) so whether it works or not is pretty much a gamble. Does your display work with the reference Python code from Waveshare?
yep! reference code works. I stripped reference files down to just the pieces needed to run the 2.13bc waveshare demo code:
minimal_reference_code/
├── lib
│ └── waveshare_epd
│ ├── __init__.py
│ ├── epd2in13bc.py
│ └── epdconfig.py
├── pic
│ ├── 100x100.bmp
│ ├── 2in13bc-b.bmp
│ ├── 2in13bc-ry.bmp
│ └── Font.ttc
└── test
└── epd_2in13bc_test.py
Currently, I'm testing on ubuntu 20.04 64bit on a pi4, but arguably that shouldn't matter..
Running from the same venv, the reference code behaves as expected..
attaching the above files as a targz in case it's helpful at all. I'll continue to dork around with it and see if I can make any progress minimal_reference_code.tar.gz
Well, quickly looking at the display method, it seems to me that it's missing the PARTIAL_OUT (0x92) command entirely after writing the buffers (note: current code actually ignores the red data completely anyway).
Waveshare's example has this (lines 123-135 in epd2in13bc.py):
def display(self, imageblack, imagered):
self.send_command(0x10)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(imageblack[i])
self.send_command(0x92)
self.send_command(0x13)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(imagered[i])
self.send_command(0x92)
self.send_command(0x12) # REFRESH
self.ReadBusy()
And PaperTTY has this (https://github.com/joukos/PaperTTY/blob/master/drivers/drivers_colordraw.py#L79-L96):
# this variant is for EPD1in54c, EPD2in13b and EPD2in9b - EPD1in54b and EPD2in7b override it
def display_frame(self, frame_buffer_black, *args):
frame_buffer_red = args[0] if args else None
if frame_buffer_black:
self.send_command(self.DATA_START_TRANSMISSION_1)
self.delay_ms(2)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(frame_buffer_black[i])
self.delay_ms(2)
if frame_buffer_red:
self.send_command(self.DATA_START_TRANSMISSION_2)
self.delay_ms(2)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(frame_buffer_red[i])
self.delay_ms(2)
self.send_command(self.DISPLAY_REFRESH)
self.wait_until_idle()
Note that currently in the above method, the frame_buffer_red will always be None because it's ignored in WaveshareColor class's draw method - currently there's no implementation to use it.
The difference here seems to be that after the data is sent, the command 0x92 should (probably) be sent too, so maybe try to replace the display_frame method in drivers_colordraw.py (lines 79-96) with this:
# this variant is for EPD1in54c, EPD2in13b and EPD2in9b - EPD1in54b and EPD2in7b override it
def display_frame(self, frame_buffer_black, *args):
frame_buffer_red = args[0] if args else None
if frame_buffer_black:
self.send_command(self.DATA_START_TRANSMISSION_1)
self.delay_ms(2)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(frame_buffer_black[i])
self.send_command(self.PARTIAL_OUT)
self.delay_ms(2)
if frame_buffer_red:
self.send_command(self.DATA_START_TRANSMISSION_2)
self.delay_ms(2)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(frame_buffer_red[i])
self.delay_ms(2)
self.send_command(self.PARTIAL_OUT)
self.send_command(self.DISPLAY_REFRESH)
self.wait_until_idle()
It's very likely that's not the only problem, but maybe worth a try to see if it makes a difference.
didn't make much of a difference yet. I'll keep tinkering on my branch
Okay, good luck, please make a PR if you get it working :) Maybe I'll have time to try the 2.9" too at some point (and figure out what options there should be for using the colors).
okay. Found out that using the D driver seems to work if I use the --nopartial flag. that's at least progress for the moment, and points me in a direction
oh interesting:
(papertty) pi@ubuntu:~/PaperTTY$ ./papertty.py --nopartial --driver EPD2in13b scrub
Loading PIL font tom-thumb.pil. Font size is ignored.
Traceback (most recent call last):
File "./papertty.py", line 794, in <module>
cli()
File "/home/pi/.virtualenvs/papertty/lib/python3.8/site-packages/click/core.py", line 829, in __call__
return self.main(*args, **kwargs)
File "/home/pi/.virtualenvs/papertty/lib/python3.8/site-packages/click/core.py", line 782, in main
rv = self.invoke(ctx)
File "/home/pi/.virtualenvs/papertty/lib/python3.8/site-packages/click/core.py", line 1259, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/home/pi/.virtualenvs/papertty/lib/python3.8/site-packages/click/core.py", line 1066, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/home/pi/.virtualenvs/papertty/lib/python3.8/site-packages/click/core.py", line 610, in invoke
return callback(*args, **kwargs)
File "/home/pi/.virtualenvs/papertty/lib/python3.8/site-packages/click/decorators.py", line 33, in new_func
return f(get_current_context().obj, *args, **kwargs)
File "./papertty.py", line 514, in scrub
ptty.driver.scrub(fillsize=size)
File "/home/pi/PaperTTY/drivers/drivers_base.py", line 60, in scrub
self.fill(self.black, fillsize=fillsize)
File "/home/pi/PaperTTY/drivers/drivers_base.py", line 67, in fill
self.draw(x, 0, image)
File "/home/pi/PaperTTY/drivers/drivers_color.py", line 41, in draw
self.display_frame(self.get_frame_buffer(image))
File "/home/pi/PaperTTY/drivers/drivers_colordraw.py", line 485, in get_frame_buffer
super().get_frame_buffer(image, reverse=reverse)
File "/home/pi/PaperTTY/drivers/drivers_full.py", line 75, in get_frame_buffer
raise ValueError('Image must be same dimensions as display: required ({0}x{1}), got ({2}x{3})'
ValueError: Image must be same dimensions as display: required (104x212), got (16x212)
and
(papertty) pi@ubuntu:~/PaperTTY$ ./papertty.py --nopartial --driver EPD2in13d scrub
Loading PIL font tom-thumb.pil. Font size is ignored.
Traceback (most recent call last):
File "./papertty.py", line 794, in <module>
cli()
File "/home/pi/.virtualenvs/papertty/lib/python3.8/site-packages/click/core.py", line 829, in __call__
return self.main(*args, **kwargs)
File "/home/pi/.virtualenvs/papertty/lib/python3.8/site-packages/click/core.py", line 782, in main
rv = self.invoke(ctx)
File "/home/pi/.virtualenvs/papertty/lib/python3.8/site-packages/click/core.py", line 1259, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/home/pi/.virtualenvs/papertty/lib/python3.8/site-packages/click/core.py", line 1066, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/home/pi/.virtualenvs/papertty/lib/python3.8/site-packages/click/core.py", line 610, in invoke
return callback(*args, **kwargs)
File "/home/pi/.virtualenvs/papertty/lib/python3.8/site-packages/click/decorators.py", line 33, in new_func
return f(get_current_context().obj, *args, **kwargs)
File "./papertty.py", line 514, in scrub
ptty.driver.scrub(fillsize=size)
File "/home/pi/PaperTTY/drivers/drivers_base.py", line 60, in scrub
self.fill(self.black, fillsize=fillsize)
File "/home/pi/PaperTTY/drivers/drivers_base.py", line 67, in fill
self.draw(x, 0, image)
File "/home/pi/PaperTTY/drivers/drivers_partial.py", line 597, in draw
self.display_full(self.get_frame_buffer(image))
File "/home/pi/PaperTTY/drivers/drivers_partial.py", line 112, in get_frame_buffer
raise ValueError('Image must be same dimensions as display \
ValueError: Image must be same dimensions as display (104x212).
(papertty) pi@ubuntu:~/PaperTTY$
The reason it crashes is perhaps related to the orientation (maybe), the pull request opened a while ago has some thoughts about it: https://github.com/joukos/PaperTTY/pull/52.
16x212 does sound pretty wrong though...