enviroplus-python
enviroplus-python copied to clipboard
Repackage to latest boilerplate, Pi 5 + Bookworm compatibility
Using This Branch
Hey ho, this is the first Pimoroni Python product - ignoring all of its library dependencies - to make a full transition to gpiod, virtual environments and the shiny new Pi 5.
As such, I'd really like your feedback!
To use this library:
git clone https://github.com/pimoroni/enviroplus-python -b feature/repackage
cd enviroplus-python
./install.sh --unstable
A venv should be created for you, though this step will be skipped if you're already inside one (in theory).
Things to look out for:
- Any errors writing
/boot/firmware/config.txt - Make sure
/boot/config.txtis still a symlink to/boot/firmware/config.txt- I thinksedbreaks this horribly - Examples and such are copied to
~/Pimoroni - No missing packages or heinous compile steps during install
Some debugging steps:
- Run
gpioinfoto see the state of your IO (needsapt install gpiod) - Run
cat /proc/device-tree/modelsincegpiodevicelooks here to try and do per-platform pin setup
TODO
Pre-requisites
- [x] libgpiod / gpiod applied & released
- [x] sounddevice, does it still work?
- [ ] Get the "venv" stuff right- pending some direction from Pi maybe? - https://github.com/raspberrypi/bookworm-feedback/issues/100
- I really don't know if what we're doing is strictly right but it's at least close enough
- [ ] Smooth over libgpiod differences between platforms (https://github.com/pimoroni/gpiodevice-python)
- Still some issues in
gpiodevice-pythonwhere it will fail quite cryptically if you try to look up a number rather than a pin label, eek!
- Still some issues in
Need porting (maybe)
- [x] pimoroni-bme280 - WIP https://github.com/pimoroni/bme280-python/pull/26
- [x] pms5003 - WIP https://github.com/pimoroni/pms5003-python/pull/19
- [x] ltr559 - https://github.com/pimoroni/ltr559-python/pull/17 (merged, and released v1.0.0)
- [x] st7735 - WIP https://github.com/pimoroni/st7735-python/pull/33
- [x] ads1015 - https://github.com/pimoroni/ads1015-python (merged, and released v1.0.0)
Gotchas
Caught in this port, raspi-config nonint do_serial has now changed to ignore the nonint flag and show a UI. Seems to have been split into do_serial and do_serial_pi5 - https://github.com/RPi-Distro/raspi-config/blob/9ccd4bbe5eccaf09137cc42eefd18f95072c70f2/raspi-config#L1174-L1218
Pull Request Test Coverage Report for Build 6877866546
- 120 of 128 (93.75%) changed or added relevant lines in 6 files are covered.
- No unchanged relevant lines lost coverage.
- Overall coverage increased (+0.3%) to 94.845%
| Changes Missing Coverage | Covered Lines | Changed/Added Lines | % |
|---|---|---|---|
| tests/conftest.py | 71 | 79 | 89.87% |
| <!-- | Total: | 120 | 128 |
| Totals | |
|---|---|
| Change from base Build 5669236330: | 0.3% |
| Covered Lines: | 276 |
| Relevant Lines: | 291 |
💛 - Coveralls
FWIW I'll give this a test soon; requires me to rebuild the Pi Zero that's on my desk in my home office running an Enviro, but given this relates to a bug I'd previously raised, it is on my radar to get to it sometime shortly.
That would be super appreciated, thank you. I don't have a Pi Zero set up for testing at the moment, so who knows what chaos might ensue. Right now some of the libraries only do GPIO detection for Pi 4 and Pi 5 so I suspect everything will break horribly and I'll need to fire up a Pi Zero to do some sleuthing.
I have released ported versions of all the libraries Enviro depends upon, so things are probably more broken than when I started right now :sob:
With gpiod the location and names of GPIO "lines" seems to be inconsistent across Pi platforms, and certainly inconsistent between Pi and ROCK, and I'm trying very hard not to write yet another Pi-specific unify-all-the-pins library since that will surely bite me later.
I've had some fun on an old Pi Zero W - I forgot how pokey they are compared with 2W, but that's where my Enviro+ has been living.
Fresh install of Bookworm needed a few additional packages (which may have been missing due to my choosing a lite version) - as a minimum
apt install git patchelf autoconf libopenblas0 libopenblas-dev libopenjp2-y
Also needed to manually pip install pillow
I also found that calls to raspi-config from the pyproject.toml were failing until I did an apt upgrade.
The sensors are now working, but anything that tries to use the LCD fails:
$ python all-in-one-enviro-mini.py
2023-11-24 15:20:42.283 INFO all-in-one.py - Displays readings from all of Enviro plus" sensors
Press Ctrl+C to exit!
Woah there, suitable gpiochip not found!
❌ PIN21: not found - /dev/gpiochip0 (pinctrl-bcm2835)!
For the sake of additional info, here's the output from pinctrl
$ pinctrl -p
1: 3v3
2: 5v
3: a0 -- | hi // GPIO2 = SDA1
4: 5v
5: a0 -- | hi // GPIO3 = SCL1
6: gnd
7: ip -- | hi // GPIO4 = input
8: ip -- | lo // GPIO14 = input
9: gnd
10: ip -- | hi // GPIO15 = input
11: ip -- | lo // GPIO17 = input
12: a0 -- | lo // GPIO18 = PCM_CLK
13: ip -- | hi // GPIO27 = input
14: gnd
15: ip -- | hi // GPIO22 = input
16: ip -- | lo // GPIO23 = input
17: 3v3
18: op -- -- | lo // GPIO24 = output
19: a0 -- | lo // GPIO10 = SPI0_MOSI
20: gnd
21: a0 -- | lo // GPIO9 = SPI0_MISO
22: ip -- | lo // GPIO25 = input
23: a0 -- | lo // GPIO11 = SPI0_SCLK
24: op -- -- | hi // GPIO8 = output
25: gnd
26: op -- -- | hi // GPIO7 = output
27: ip -- | hi // GPIO0 = input
28: ip -- | hi // GPIO1 = input
29: ip -- | hi // GPIO5 = input
30: gnd
31: ip -- | hi // GPIO6 = input
32: ip -- | lo // GPIO12 = input
33: ip -- | lo // GPIO13 = input
34: gnd
35: a0 -- | lo // GPIO19 = PCM_FS
36: ip -- | lo // GPIO16 = input
37: ip -- | lo // GPIO26 = input
38: a0 -- | lo // GPIO20 = PCM_DIN
39: gnd
40: a0 -- | lo // GPIO21 = PCM_DOUT
Oh, and the PMS stuff has issues...
$ python combined.py
2023-11-24 15:30:01.341 INFO combined.py - Displays readings from all of Enviro plus' sensors
Press Ctrl+C to exit!
Traceback (most recent call last):
File "/home/andypiper/enviroplus-python/examples/combined.py", line 43, in <module>
pms5003 = PMS5003()
^^^^^^^^^
File "/home/andypiper/.virtualenvs/pimoroni/lib/python3.11/site-packages/pms5003/__init__.py", line 109, in __init__
self._pin_enable, self._pin_reset = gpiodevice.get_pins_for_platform(PLATFORMS)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: not enough values to unpack (expected 2, got 0)
... but as you said, things are likely broken where the pins are not consistent, and the underlying libraries need ports... :-/
Thank you!
I think both of these problems relate to missing pin definitions for Pi Zero. With any luck pushing out a new version of gpiodevice (my oh-dear-am-I-rewriting-Blinka? library) should be all that's needed.
Looks like in the case of PMS5003 it's not producing any error output, which I kinda expect since I reworked stuff around that to default to full error reports and make "quiet" mode a function argument but haven't released a new gpiodevice library yet..
What do you see if you:
cat /sys/device-tree/model
and gpioinfo (which is part of libgpiod and gives more useful information about the chips)
Note that apt install gpiod is required for use of gpioinfo, now done.
$ gpioinfo
gpiochip0 - 54 lines:
line 0: "ID_SDA" unused input active-high
line 1: "ID_SCL" unused input active-high
line 2: "SDA1" unused input active-high
line 3: "SCL1" unused input active-high
line 4: "GPIO_GCLK" unused input active-high
line 5: "GPIO5" unused input active-high
line 6: "GPIO6" unused input active-high
line 7: "SPI_CE1_N" "spi0 CS1" output active-low [used]
line 8: "SPI_CE0_N" "spi0 CS0" output active-low [used]
line 9: "SPI_MISO" unused input active-high
line 10: "SPI_MOSI" unused input active-high
line 11: "SPI_SCLK" unused input active-high
line 12: "GPIO12" unused input active-high
line 13: "GPIO13" unused input active-high
line 14: "TXD1" unused input active-high
line 15: "RXD1" unused input active-high
line 16: "GPIO16" unused input active-high
line 17: "GPIO17" unused input active-high
line 18: "GPIO18" unused input active-high
line 19: "GPIO19" unused input active-high
line 20: "GPIO20" unused input active-high
line 21: "GPIO21" unused input active-high
line 22: "GPIO22" unused input active-high
line 23: "GPIO23" unused input active-high
line 24: "GPIO24" unused input active-high
line 25: "GPIO25" unused input active-high
line 26: "GPIO26" unused input active-high
line 27: "GPIO27" unused input active-high
line 28: "SDA0" unused input active-high
line 29: "SCL0" unused input active-high
line 30: "CTS0" unused input active-high
line 31: "RTS0" unused input active-high
line 32: "TXD0" unused input active-high
line 33: "RXD0" unused input active-high
line 34: "SD1_CLK" unused input active-high
line 35: "SD1_CMD" unused input active-high
line 36: "SD1_DATA0" unused input active-high
line 37: "SD1_DATA1" unused input active-high
line 38: "SD1_DATA2" unused input active-high
line 39: "SD1_DATA3" unused input active-high
line 40: "CAM_GPIO1" unused output active-high
line 41: "WL_ON" unused output active-high
line 42: "NC" unused input active-high
line 43: "WIFI_CLK" unused input active-high
line 44: "CAM_GPIO0" "cam1_regulator" output active-high [used]
line 45: "BT_ON" "shutdown" output active-high [used]
line 46: "HDMI_HPD_N" "hpd" input active-low [used]
line 47: "STATUS_LED_N" "ACT" output active-low [used]
line 48: "SD_CLK_R" unused input active-high
line 49: "SD_CMD_R" unused input active-high
line 50: "SD_DATA0_R" unused input active-high
line 51: "SD_DATA1_R" unused input active-high
line 52: "SD_DATA2_R" unused input active-high
line 53: "SD_DATA3_R" unused input active-high
And I think sys should be proc for the other command...
$ cat /proc/device-tree/model
Raspberry Pi Zero W Rev 1.1
(really really old and smol!)
@Gadgetoid Hi. I have bought enviro. I'm trying it with Raspbery PI ZERO too. I have exactly the same issue for all-in-one-enviro-mini.py like andypiper: PIN21: not found - /dev/gpiochip0 (pinctrl-bcm2835)!
Are there any updates? When we can expect fix for this problem? How can I help you?
Note: There are some issues for Bookworm with RPI Imager compatibility. It is not so easy to set Wifi connection profile during microSD card flashing via RPI Imager. I have spent a lot of time to be able flash microSD card for Bookworm with wifi connection profile - so I'm sharing my steps also here - https://raspberrypi.stackexchange.com/questions/144850/headless-wi-fi-setup-without-the-rpi-imager-bootfs-wpa-supplicant-conf-not-supp/145264#145264
Thanks
The PIN21: not found issue is related, I think, to the GPIO naming difference between Pi 5 and Pi 4.
There's no longer any standard naming scheme for IO, since that was something that RPi.GPIO smoothed over and I'm apprehensive to create and maintain another Pi-specific GPIO abstraction layer.
In most cases if PIN21 is missing, you need to find where that's being used - in the example code in this instance - and substitute for GPIO9.
The comments try, but fail, to make this clear:
https://github.com/pimoroni/enviroplus-python/blob/e6cd19c57b210000b3fb01e6e4b133a57d16c042/examples/lcd.py#L24
I'll probably have to try and to platform detection and smooth over this.
I'll take a look at this on my board tomorrow and see if I can "monkey-patch" for a Pi Zero at least.
Thanks! I have checked the code and the only thing I have found is, that here https://github.com/pimoroni/gpiodevice-python/blob/main/gpiodevice/platform/pi.py is missing "pinctrl-bcm2835" :
def get_gpiochip_labels():
if get_name() is not None:
return (
"pinctrl-rp1", # Pi 5 - Bookworm, /dev/gpiochip4 maybe
"pinctrl-bcm2711", # Pi 4 - Bullseye, /dev/gpiochip0 maybe
"pinctrl-bcm2835" # Added By Matho - PI Zero - Bookworm /dev/gpiochip0
)
return None
But dont think it solves the problem.
missing "pinctrl-bcm2835"
I should probably add this for completeness, but get_pins_for_platform just looks up the name of the board and then searches for that in the dict with various levels of specificity.
https://github.com/pimoroni/gpiodevice-python/blob/2e79df44f9fd15125c3b47ed9f330b66d17b3a58/gpiodevice/init.py#L157-L167
PMS5003 uses the platform set:
PLATFORMS = {
"Radxa ROCK 5B": {"enable": ("PIN_15", OUTH), "reset": ("PIN_13", OUTL)},
"Raspberry Pi 5": {"enable": ("PIN15", OUTH), "reset": ("PIN13", OUTL)},
"Raspberry Pi 4": {"enable": ("GPIO22", OUTH), "reset": ("GPIO27", OUTL)}
}
So any effort to auto-detect will fail, since I'm guessing cat /proc/device-tree/model on a Pi Zero returns something like "Raspberry Pi Zero".
If you could post the output of /proc/device-tree/model and gpioinfo that would help me find the right gpio bank and pin names for adding to the list. I'm going to have very limited access to hardware over Christmas 😬
From tinkering elsewhere it looks like the GPIO banks and pins are named via the device tree overlays, I may be making a fatal mistake assuming they'll ever be consistent enough for me to do pin defaults across multiple libraries 😬 ... it's tricky balancing the "argh everything is broken I must fix this now" with the "I must fix this in an actually robust, future-proof way."
@Gadgetoid
$ cat /proc/device-tree/model
Raspberry Pi Zero W Rev 1.1
$ gpioinfo
gpiochip0 - 54 lines:
line 0: "ID_SDA" unused input active-high
line 1: "ID_SCL" unused input active-high
line 2: "SDA1" unused input active-high
line 3: "SCL1" unused input active-high
line 4: "GPIO_GCLK" unused input active-high
line 5: "GPIO5" unused input active-high
line 6: "GPIO6" unused input active-high
line 7: "SPI_CE1_N" "spi0 CS1" output active-low [used]
line 8: "SPI_CE0_N" "spi0 CS0" output active-low [used]
line 9: "SPI_MISO" unused input active-high
line 10: "SPI_MOSI" unused input active-high
line 11: "SPI_SCLK" unused input active-high
line 12: "GPIO12" unused input active-high
line 13: "GPIO13" unused input active-high
line 14: "TXD1" unused input active-high
line 15: "RXD1" unused input active-high
line 16: "GPIO16" unused input active-high
line 17: "GPIO17" unused input active-high
line 18: "GPIO18" unused input active-high
line 19: "GPIO19" unused input active-high
line 20: "GPIO20" unused input active-high
line 21: "GPIO21" unused input active-high
line 22: "GPIO22" unused input active-high
line 23: "GPIO23" unused input active-high
line 24: "GPIO24" unused input active-high
line 25: "GPIO25" unused input active-high
line 26: "GPIO26" unused input active-high
line 27: "GPIO27" unused input active-high
line 28: "SDA0" unused input active-high
line 29: "SCL0" unused input active-high
line 30: "CTS0" unused input active-high
line 31: "RTS0" unused input active-high
line 32: "TXD0" unused input active-high
line 33: "RXD0" unused input active-high
line 34: "SD1_CLK" unused input active-high
line 35: "SD1_CMD" unused input active-high
line 36: "SD1_DATA0" unused input active-high
line 37: "SD1_DATA1" unused input active-high
line 38: "SD1_DATA2" unused input active-high
line 39: "SD1_DATA3" unused input active-high
line 40: "CAM_GPIO1" unused output active-high
line 41: "WL_ON" unused output active-high
line 42: "NC" unused input active-high
line 43: "WIFI_CLK" unused input active-high
line 44: "CAM_GPIO0" "cam1_regulator" output active-high [used]
line 45: "BT_ON" "shutdown" output active-high [used]
line 46: "HDMI_HPD_N" "hpd" input active-low [used]
line 47: "STATUS_LED_N" "ACT" output active-low [used]
line 48: "SD_CLK_R" unused input active-high
line 49: "SD_CMD_R" unused input active-high
line 50: "SD_DATA0_R" unused input active-high
line 51: "SD_DATA1_R" unused input active-high
line 52: "SD_DATA2_R" unused input active-high
line 53: "SD_DATA3_R" unused input active-high
$ python3.11 lcd.py
2023-12-15 16:56:32.181 INFO lcd.py - Hello, World! example on the 0.96" LCD.
Press Ctrl+C to exit!
Woah there, suitable gpiochip not found!
❌ PIN21: not found - /dev/gpiochip0 (pinctrl-bcm2835)!
Thanks!
And some another findings:
- I'm providing output of
gpioreadall5.pyfrom this repository: https://github.com/Milliways2/GPIOreadall . Seems, that https://pinout.xyz/pinout/enviro match with this screenshot
- I did some progress with display. If I setup lcd sample with following setup, the display backlight works, but there is no text on display
disp = st7735.ST7735(
port=0,
cs=1,
dc='GPIO13', #"PIN21", # "GPIO9" on a Raspberry Pi 4
backlight='GPIO12', #"PIN32", # "GPIO12" on a Raspberry Pi 4
rotation=270,
spi_speed_hz=10000000
)
- I have run something like:
get_pin("GPIO0,GPIO1,GPIO2,GPIO3,GPIO4,GPIO5,GPIO6,GPIO7,GPIO8,GPIO9,GPIO10,GPIO11,GPIO12,GPIO13,GPIO14,GPIO15,GPIO16,GPIO17,GPIO18,GPIO19,GPIO20,GPIO21,GPIO22,GPIO23,GPIO24,GPIO25,GPIO26,GPIO27", "st7735-dc", OUTL)
and the output is:
Woah there, suitable gpiochip not found! ❌ GPIO0: not found - /dev/gpiochip0 (pinctrl-bcm2835)! ❌ GPIO1: not found - /dev/gpiochip0 (pinctrl-bcm2835)! ❌ GPIO2: not found - /dev/gpiochip0 (pinctrl-bcm2835)! ❌ GPIO3: not found - /dev/gpiochip0 (pinctrl-bcm2835)! ❌ GPIO4: not found - /dev/gpiochip0 (pinctrl-bcm2835)! ✅ GPIO5: (line 5) found - /dev/gpiochip0 (pinctrl-bcm2835)! ✅ GPIO6: (line 6) found - /dev/gpiochip0 (pinctrl-bcm2835)! ❌ GPIO7: not found - /dev/gpiochip0 (pinctrl-bcm2835)! ❌ GPIO8: not found - /dev/gpiochip0 (pinctrl-bcm2835)! ❌ GPIO9: not found - /dev/gpiochip0 (pinctrl-bcm2835)! ❌ GPIO10: not found - /dev/gpiochip0 (pinctrl-bcm2835)! ❌ GPIO11: not found - /dev/gpiochip0 (pinctrl-bcm2835)! ✅ GPIO12: (line 12) found - /dev/gpiochip0 (pinctrl-bcm2835)! ✅ GPIO13: (line 13) found - /dev/gpiochip0 (pinctrl-bcm2835)! ❌ GPIO14: not found - /dev/gpiochip0 (pinctrl-bcm2835)! ❌ GPIO15: not found - /dev/gpiochip0 (pinctrl-bcm2835)! ✅ GPIO16: (line 16) found - /dev/gpiochip0 (pinctrl-bcm2835)! ✅ GPIO17: (line 17) found - /dev/gpiochip0 (pinctrl-bcm2835)! ✅ GPIO18: (line 18) found - /dev/gpiochip0 (pinctrl-bcm2835)! ✅ GPIO19: (line 19) found - /dev/gpiochip0 (pinctrl-bcm2835)! ✅ GPIO20: (line 20) found - /dev/gpiochip0 (pinctrl-bcm2835)! ✅ GPIO21: (line 21) found - /dev/gpiochip0 (pinctrl-bcm2835)! ✅ GPIO22: (line 22) found - /dev/gpiochip0 (pinctrl-bcm2835)! ✅ GPIO23: (line 23) found - /dev/gpiochip0 (pinctrl-bcm2835)! ✅ GPIO24: (line 24) found - /dev/gpiochip0 (pinctrl-bcm2835)! ✅ GPIO25: (line 25) found - /dev/gpiochip0 (pinctrl-bcm2835)! ✅ GPIO26: (line 26) found - /dev/gpiochip0 (pinctrl-bcm2835)! ✅ GPIO27: (line 27) found - /dev/gpiochip0 (pinctrl-bcm2835)!
I tried to set all green GPIO numbers for dc= attribute, without success
I guess you should be using SPI_MISO in lieu of GPIO13 or PIN21, it looks like the SPI driver isn't claiming it, so it should work-
line 7: "SPI_CE1_N" "spi0 CS1" output active-low [used]
line 8: "SPI_CE0_N" "spi0 CS0" output active-low [used]
line 9: "SPI_MISO" unused input active-high
(Sorry for the long delay, much-needed Christmas hols!)
Thanks! This combination works on my RPI Zero:
# Create LCD class instance.
disp = st7735.ST7735(
port=0,
cs=1,
dc='SPI_MISO', # "GPIO9" on a Raspberry Pi 4
backlight='GPIO12', # "GPIO12" on a Raspberry Pi 4
rotation=270,
spi_speed_hz=10000000
)
But if I try python3.11 lcd.py the Hello World text is not correctly shown. Some characters are white, but some not. Some characters have only few white pixels, like some issues with driver?
I will give it a try on my RPI 4, too, if the problem persists also on RPI 4 8GB model
Any update if this will be merged?
Error during installation:
Installing missing packages: python3-cffi libportaudio2
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
E: Unable to locate package python3-cffi libportaudio2
⚠ WARNING: ^^^ 😬 previous command did not exit cleanly!
E: Unable to locate package python3-cffi libportaudio2
Ouch, that means the install script is effectively running:
sudo apt install "python3-cffi libportaudio2"
Which results in:
E: Unable to locate package python3-cffi libportaudio2
Rather than the subtly different:
sudo apt install python3-cffi libportaudio2
I have broken the apt package management somehow, and probably everywhere too 😬
Edit: Okay, I see it. sigh
Also, on Bullseye the installer seems to mostly work save for:
Running: "sudo raspi-config nonint do_serial_cons 1"
/usr/bin/raspi-config: 2909: do_serial_cons: not found
⚠ WARNING: ^^^ 😬 previous command did not exit cleanly!
Running: "sudo raspi-config nonint do_serial_hw 1"
/usr/bin/raspi-config: 2909: do_serial_hw: not found
⚠ WARNING: ^^^ 😬 previous command did not exit cleanly!
Which I can't easily fix without abstracting the call to raspi-config. This change was made across these commits:
- https://github.com/RPi-Distro/raspi-config/commit/1fec46aed10e57d60dd5f3d63159736ef3567c6d
- https://github.com/RPi-Distro/raspi-config/commit/b5c00767768dbeb625dd7e91827c9ac4b0d11232
- https://github.com/RPi-Distro/raspi-config/commit/a5bd201044510a208ac481829fd4dd18f915ad47