Raspberry Pi

GPIO : Quick/Easy Transition from wiringPi to gpiod

Bernard Karmilowicz


Problem: Both the GPIO sysfs interface in Linux and the wiringPi GPIO management package are deprecated. The "new" character device driver (gpiod) based commands for managing GPIO over Linux behave differently than wiringPi's gpio command. In particular; The gpiod-based gpioset command releases GPIO lines to their default state upon the command's exit (especially bad if a connected device is not expecting to "see" a floating signal), and the gpiod-based gpioget command automatically converts GPIO output lines to inputs rather than providing the option of determining what the line is being driven to (i.e. high or low) when the line is an output. This gpiod-based command behavior requires a different approach than with wiringPi's gpio command for configuring, using, and querying the Raspberry Pi GPIO lines intended as outputs.

Solution: A simple and light GPIO service to initialize GPIO lines intended as outputs when the Raspberry Pi boots, and a script which uses gpiod in a manner emulating a subset of the wiringPi gpio command's behavior with respect to GPIO output lines. This solution achieves my goal of booting a Raspberry Pi with specified pins being configured as outputs driven low, maintaining those pins as outputs while the Raspberry Pi is energized, and having changes to the logic-state of those outputs persist regardless of whether the user "pi" is logged on.

Disclaimer: This solution was implemented to solve the problem for my purposes. The solution may not be appropriate for your purposes. No warranty is implied. Use at your own risk.

Naming Convention: The instructions which follow include references to "ha" rather than "gpio" since the solution to the problem noted above was first implemented on a Raspberry Pi used for home automation (HA). For example; The script used for the GPIO initialization service is named "hainit" rather than the more general "gpioinit", and the file containing a Broadcom (BCM) GPIO-line to Raspberry Pi GPIO-pin cross-reference table is named "ha.table" rather than the more general "gpio.table".

  1. Copy the GPIO cross-reference table to /home/pi/etc/ha.table
  2. Customize the records in ha.table. Only the first two columns are required. In particular; Replace my BCM GPIO-line numbers (second column) with BCM GPIO-line numbers reflecting your application. Run the pinout command on your Raspberry Pi to help determine which GPIO lines you are using as outputs (inputs are not represented in ha.table). SigIDs (first column) must be unique counting numbers in the set {1..n}, where 'n' is the count of all GPIO-specific records (i.e. those which are not comment/header, or blank) in ha.table. This SysID re/numbering is especially important if records were added or deleted, but the numbers do not need to be in any order (e.g. ascending or descending).
  3. Copy the GPIO initialization script to /home/pi/bin/hainit
  4. If you added or deleted records in ha.table, then update the set range on line 8 in hainit accordingly.
  5. chmod 500 /home/pi/bin/hainit
  6. Copy the GPIO control script to /home/pi/bin/hactl
  7. If you added or deleted records in ha.table, then update lines 13, 25, 26, and 44 in hactl accordingly. (except for line 25; these updates are cosmetic)
  8. chmod 500 /home/pi/bin/hactl
  9. Copy the GPIO service unit-file to /etc/systemd/system/home-automation.service
  10. Tell systemd to reconfigure itself, thereby incorporating the GPIO service, by issuing the command:
    sudo systemctl daemon-reload
  11. Tell systemd to start the GPIO service automatically when booting, by issuing the command:
    sudo systemctl enable home-automation.service
  12. Check the status of GPIO service, by issuing the command:
    systemctl status home-automation.service

For each GPIO line listed in ha.table; The GPIO service runs one gpiod gpioset command (via /home/pi/bin/hactl) in the background to keep driving the GPIO lines low when the Raspberry Pi is booted. To confirm these processes exist, issue the command:

ps -fC gpioset

If/when hactl is later run by the user "pi", and if that run would invert a GPIO line's output (e.g. if hactl is told to drive a currently-low line high), then the latest gpioset background process for that line is replaced with a new gpioset background process for that line. These processes survive the user "pi" logging out, or programs/scripts which run hactl exiting, thereby providing output-drive persistence.

The hainit script can easily be modified to change the start-up state (on/low or off/high) of each GPIO line listed in ha.table, and the hactl script can easily be modified to use positive (1 == on/true) rather than negative (1 == off/false) logic for those outputs.



Last updated: 2024-02-10 (after upgrading from Bullseye to Bookworm)

background image