inky
inky copied to clipboard
Port to gpiod for Bookworm/Pi 5 and beyond
Hey ho, we're in the process of transitioning the Inky library and examples to gpiod, virtual environments and the shiny new Pi 5.
As such, I'd really like your feedback!
Progress
- [ ] inky - old 2nd generation, 2/3-colour Inky pHAT boards and wHAT boards - (yellow) pHAT works, other untested
- [ ] inky_ssd1608 - newer Inky pHAT boards based on the SSD1608 - (red) pHAT works, others untested
- [x] inky_ssd1683 - newer Inky wHAT boards - :tada: seems to work for me on my Pi 5. (SEE BELOW)
- [x] inky_uc8159 - Inky Impressions 4 - it works! (SEE BELOW)
- [x] inky_uc8159 - Inky Impressions 5.7" - it works! (SEE BELOW)
- [x] inky_ac073tc1a - Inky Impressions 7.3" - It works!
Note: Most examples using GPIO have not been ported, with the exception of examples/7color/buttons.py
.
Note: The simulator might be broken. I am removing conditional imports and custom ImportError
trapping where I can, since this overcomplicates the codebase especially when we try to move to gpiod.
π Installation Instructions π
Grab this branch and install with the --unstable
(local downloaded copy of the library) flag:
git clone https://github.com/pimoroni/inky -b gpiod
cd inky
./install.sh --unstable
A venv should be created for you, though this step will be skipped if you're already inside one (in theory).
If you get errors, make sure you activate that virtual environment. Your bash prompt should start with (pimoroni)
:
source ~/.virtualenvs/pimoroni/bin/activate
The installer should have added some new lines to /boot/firmware/config.txt
so that SPI gets out of the way of the chip-select pin and the EEPROM i2c is enabled (for detecting your Inky board type)-
dtoverlay=spi0-0cs
dtoverlay=i2c1
dtoverlay=i2c1-pi5
Reboot your Pi, and see if anything breaks.
Things to look out for:
- Any errors writing
/boot/firmware/config.txt
and that the lines mentioned above are present - Make sure
/boot/config.txt
is still a symlink to/boot/firmware/config.txt
- I thinksed
breaks this horribly (Note: On my Pi it now seems like this is not a symlink on purpose?) - Examples and such are copied to
~/Pimoroni
- No missing packages or heinous compile steps during install
- Your product actually works!
Inky wHAT (ssd1683)
Tested before the dtoverlay=spi0-0cs
change, which worked, but this broke SSD1683 because it was using the default SPI chip-select behaviour. I have migrated everything over to use soft chip-select, though it might be worth seeing if we can give it over to the SPI driver on all counts and avoid needing to load that overlay.
Inky Impressions 5.7"
I've been having trouble with this, and I'm still suspicious but it seems to now be working-
PYTHONPATH=../../ python3 image.py --type 7colour --file images/inky-4.0-redchain.jpg
I have a test board with no EEPROM data, so it blurts out:
Detected None
Failed to detect an Inky board. Trying --type/--colour arguments instead...
/home/phil/Development/pi/inky/inky/inky_uc8159.py:242: UserWarning: SPI: Cannot disable chip-select!
warnings.warn("SPI: Cannot disable chip-select!")
/home/phil/Development/pi/inky/inky/inky_uc8159.py:337: UserWarning: Busy Wait: Held high. Waiting for 1.00s
warnings.warn(f"Busy Wait: Held high. Waiting for {timeout:0.2f}s")
/home/phil/Development/pi/inky/inky/inky_uc8159.py:337: UserWarning: Busy Wait: Held high. Waiting for 0.20s
warnings.warn(f"Busy Wait: Held high. Waiting for {timeout:0.2f}s")
/home/phil/Development/pi/inky/inky/inky_uc8159.py:337: UserWarning: Busy Wait: Held high. Waiting for 32.00s
warnings.warn(f"Busy Wait: Held high. Waiting for {timeout:0.2f}s")
This may have been another SPI chip-select issue.
Inky Impressions 4"
My 4" proto has no EEPROM data flashed, so I modified stripes.py
as follows:
#!/usr/bin/env python3
# To simulate:
# from inky.mock import InkyMockImpression as Inky
#from inky.auto import auto
from inky.inky_uc8159 import Inky
#inky = auto(ask_user=True, verbose=True)
inky = Inky((640, 400))
for y in range(inky.height - 1):
color = y // (inky.height // 7)
for x in range(inky.width - 1):
inky.set_pixel(x, y, color * 0x11)
inky.show()
# To simulate:
# inky.wait_for_window_close()
@Gadgetoid Tried this with an older Inky What (red) and it's sorta but not really working. Display updates (yay) but is offset and doesn't cover the full screen.
Any idea where to start on to get things working correctly?
Ooof! Thatβsβ¦ interesting π¬ I canβt for the life of me remember if there were two variants of the WHAT- but I believe there were.
Poking through code (on my phone, eek) maybe yours is an O.G. rather than an SSD1683 WHAT? Should be possible to construct an Inky() instance with the correct (400, 300)? resolution.
What does the identify.py script say?
@Gadgetoid here's the output:
No display EEPROM detected,
you might have an old Inky board that doesn't have an EEPROM - eg: early Inky pHAT boards.
Try running examples with --colour <black/red/yellow>
Or writing your code using:
from inky.phat import InkyPHAT
display = InkyPHAT("<black/red/yellow>")
Checking the back of the board, there's no EEPROM. I've been using --type what --colour red
with the other scripts.
I've also got an old school yellow PHAT that works as expected, so that's cool.
Tried --type whatssd1683
just to see what would happen. Answer: nothing at all.
@Gadgetoid Ok, interesting. I created an instance of InkyWHAT
in the REPL and I can draw boxes correctly with .set_pixel
without any issues. I've tried loading the what logo image with .set_image
and things go off the rails. Which lead me to look at .set_image
, which seems to be broken. Here's the implementation in the gpiod branch:
def set_image(self, image):
"""Copy an image to the buffer.
"""
image = image.resize((self.width, self.height))
if not image.mode == "P":
palette_image = Image.new("P", (1, 1))
r, g, b = 0, 0, 0
if self.colour == "red":
r = 255
if self.colour == "yellow":
r = g = 255
palette_image.putpalette([255, 255, 255, 0, 0, 0, r, g, b] + [0, 0, 0] * 252)
image.load()
image = image.im.convert("P", True, palette_image.im)
canvas = Image.new("P", (self.rows, self.cols))
width, height = image.size
canvas.paste(image, (0, 0, width, height))
self.buf = numpy.array(canvas, dtype=numpy.uint8).reshape((self.cols, self.rows))
That's all good, until it hits the new canvas. It looks like self.rows
and self.cols
are swapped. On the wHAT, this creates a canvas of (300,400) instead of (400, 300), which then gets the existing image pasted into it. That distorted image then gets put in the buffer.
To confirm that was the issue, I swapped self.rows
and self.cols
:
canvas = Image.new("P", (self.cols, self.rows))
The result:
I haven't looked into whether this change breaks things on my pHAT or not yet. Frankly, it's a little weird to me that it's working anywhere.
I haven't looked into whether this change breaks things on my pHAT or not yet. Frankly, it's a little weird to me that it's working anywhere.
Looks like I updated this code as part of this branch, but it's as of yet untested.
I would expect it to break the pHAT if it was using the same driver. It may be that the cols/rows values for the displays need updating and the code tweaked to use them properly. Very much something I need to write a test for!
Yeah, you might not really need cols/rows at all (except maybe for backward compatibility with early versions). It looks like they're just the same values as the width and height for all displays?
Assuming the test tests what I think it does - I'm pretty rusty on these old Inky boards - then just removing the additional canvas and image pasting step seems to work. Afaik this step does nothing at best, since the image is already resized to the display width/height. Raised the new test and possible fix and a PR against this branch here: https://github.com/pimoroni/inky/pull/188
@Gadgetoid
Make sure /boot/config.txt is still a symlink to /boot/firmware/config.txt
It isn't.
Here's the identify for my board:
Found: Yellow wHAT
Display: 400x300
Color: yellow
PCB Variant: 1.2
Display Variant: 2
Time: b'2023-02-01 09:29:03.0'
When I run the logo example following the above installation instructions, I get:
$ python3 logo.py
Inky pHAT/wHAT: Logo
Displays the Inky pHAT/wHAT logo.
Detected Yellow wHAT
/home/pi/.virtualenvs/pimoroni/lib/python3.11/site-packages/inky/inky.py:254: UserWarning: SPI: Cannot disable chip-select!
warnings.warn("SPI: Cannot disable chip-select!")
My Inky shows the same display as in the comment by @stonehippo (although mine is yellow).
It isn't.
Yeah, they changed that recently-ish just to keep me on my toes :cry:
In that case, what's in your /boot/firmware/config.txt
?
@Gadgetoid Here you go!
# For more options and information see
# http://rptl.io/configtxt
# Some settings may impact device functionality. See link above for details
# Uncomment some or all of these to enable the optional hardware interfaces
dtparam=i2c_arm=on
#dtparam=i2s=on
dtparam=spi=on
# Enable audio (loads snd_bcm2835)
dtparam=audio=on
# Additional overlays and parameters are documented
# /boot/firmware/overlays/README
# Automatically load overlays for detected cameras
camera_auto_detect=1
# Automatically load overlays for detected DSI displays
display_auto_detect=1
# Automatically load initramfs files, if found
auto_initramfs=1
# Enable DRM VC4 V3D driver
dtoverlay=vc4-kms-v3d
max_framebuffers=2
# Don't have the firmware create an initial video= setting in cmdline.txt.
# Use the kernel's default instead.
disable_fw_kms_setup=1
# Run in 64-bit mode
arm_64bit=1
# Disable compensation for displays with overscan
disable_overscan=1
# Run as fast as firmware / board allows
arm_boost=1
[cm4]
# Enable host mode on the 2711 built-in XHCI USB controller.
# This line should be removed if the legacy DWC2 controller is required
# (e.g. for USB device mode) or if USB support is not required.
otg_mode=1
[all]
dtoverlay=i2c1
dtoverlay=i2c1-pi5
dtoverlay=spi0-0cs
Looks like I need a try/catch around the chip select disable call- since it isnβt owned by the SPI driver π¬
Oh hmm, wait, this warning is the result of such a try/catch.
Sorry I have completely lost the plot from juggling so much stuff that my memory was purged of any and all recollection of this issue.
More discussion and a potential fix should be detailed here. I'll get some install instructions added for the fix branch so it's easier for you to try - https://github.com/pimoroni/inky/pull/188
Hello, I tried installing this branch with the given instructions on the Pi 5, but I get the below error. Any ideas?
Building wheel for spidev (pyproject.toml) ... error
error: subprocess-exited-with-error
Γ Building wheel for spidev (pyproject.toml) did not run successfully.
β exit code: 1
β°β> [27 lines of output]
/tmp/pip-build-env-cogozc2i/overlay/lib/python3.11/site-packages/setuptools/dist.py:447: SetuptoolsDeprecationWarning: Invalid dash-separated options
!!
********************************************************************************
Usage of dash-separated 'description-file' will not be supported in future
versions. Please use the underscore name 'description_file' instead.
By 2024-Sep-26, you need to update your project and remove deprecated calls
or your builds will no longer be supported.
See https://setuptools.pypa.io/en/latest/userguide/declarative_config.html for details.
********************************************************************************
!!
opt = self.warn_dash_deprecation(opt, section)
running bdist_wheel
running build
running build_ext
building 'spidev' extension
creating build
creating build/temp.linux-aarch64-cpython-311
aarch64-linux-gnu-gcc -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -fPIC -I/home/david/pinky/.venv/include -I/usr/include/python3.11 -c spidev_module.c -o build/temp.linux-aarch64-cpython-311/spidev_module.o
spidev_module.c:28:10: fatal error: Python.h: No such file or directory
28 | #include <Python.h>
| ^~~~~~~~~~
compilation terminated.
error: command '/usr/bin/aarch64-linux-gnu-gcc' failed with exit code 1
[end of output]
note: This error originates from a subprocess, and is likely not a problem with pip.
ERROR: Failed building wheel for spidev
Successfully built inky
Failed to build spidev
ERROR: Could not build wheels for spidev, which is required to install pyproject.toml-based projects
β WARNING: ^^^ π¬ previous command did not exit cleanly!
Done!
Hello, I tried installing this branch with the given instructions on the Pi 5, but I get the below error. Any ideas?
Building wheel for spidev (pyproject.toml) ... error error: subprocess-exited-with-error Γ Building wheel for spidev (pyproject.toml) did not run successfully. β exit code: 1 β°β> [27 lines of output] /tmp/pip-build-env-cogozc2i/overlay/lib/python3.11/site-packages/setuptools/dist.py:447: SetuptoolsDeprecationWarning: Invalid dash-separated options !! ******************************************************************************** Usage of dash-separated 'description-file' will not be supported in future versions. Please use the underscore name 'description_file' instead. By 2024-Sep-26, you need to update your project and remove deprecated calls or your builds will no longer be supported. See https://setuptools.pypa.io/en/latest/userguide/declarative_config.html for details. ******************************************************************************** !! opt = self.warn_dash_deprecation(opt, section) running bdist_wheel running build running build_ext building 'spidev' extension creating build creating build/temp.linux-aarch64-cpython-311 aarch64-linux-gnu-gcc -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -fPIC -I/home/david/pinky/.venv/include -I/usr/include/python3.11 -c spidev_module.c -o build/temp.linux-aarch64-cpython-311/spidev_module.o spidev_module.c:28:10: fatal error: Python.h: No such file or directory 28 | #include <Python.h> | ^~~~~~~~~~ compilation terminated. error: command '/usr/bin/aarch64-linux-gnu-gcc' failed with exit code 1 [end of output] note: This error originates from a subprocess, and is likely not a problem with pip. ERROR: Failed building wheel for spidev Successfully built inky Failed to build spidev ERROR: Could not build wheels for spidev, which is required to install pyproject.toml-based projects β WARNING: ^^^ π¬ previous command did not exit cleanly! Done!
aaand it looks like this fixes it... sudo apt-get install python3-dev
any ideas on this one?