Guide to…Embracing GPIOZero

The new kid on the GPIO block…

A newest way to interface with hardware on the Raspberry Pi is on the prowl called GPIOZero, a new Python library.

The brainchild of Ben Nuttall from the Raspberry Pi foundation, this is intended to replace the original RPi.GPIO created by Ben Croston way back in 2012!

Since the foundation is supporting this replacement, GPIOZero is destined to become the de-facto-standard for hardware interfacing.

If you want a little more information about the what, why and wherefore take a trip to RasPi.TV for a GPIOZero introduction with Ben Nuttall himself.

Questions???

Well there are few which most people may consider…the first being…

Why?

The clear reason for this is to make the coding process more natural and easier to understand without forcing unfamiliar concepts and ideas onto beginners before they are ready.  The library provides an additional abstraction layer on top of the existing RPi.GPIO base.

As Alex (RasPi.TV) shows this translates very well:

# RPi.GPIO                       #GPIO Zero
from RPi import GPIO              from gpiozero import LED
from time import sleep            from time import sleep
GPIO.setmode(GPIO.BCM)
GPIO.setup(25, GPIO.OUT)         led = LED(25)
GPIO.output(25,1)                led.on()
sleep(5)                         sleep(5)
GPIO.output(25,0)                led.off()

 

The aim of less code to get things started and less nonsensical code “magic” is clear.  This makes a far easier to read and understand result.  I’ve had to overcome similar issues in my workshops, so I can see the point here.

BCM Pin Numbering? Only BCM number and nothing but…

Humm, yes BCM pin numbering… BCM numbering is where the GPIO pins are numbered according to their GPIO reference on the actual SoC (System-on-Chip) package.

The BCM numbering bears no relation to their actual position on the Raspberry Pi GPIO header!

As an engineer, the BCM numbering makes real sense to me, as this is the reference you have to use when referring to the GPIO within any low level language.

HOWEVER… this (in my personal opinion) is at odds with making things as simple and easy to understand as possible.

RPiGPIOPinout

GPIO Header Layout (for later Raspberry Pi models)

This is further complicated because older versions of the Raspberry Pi actually have different wiring between the GPIO header and the SoC so there are different BCM numbers for on the same physical pins.

RPi_Originals

For the original models of the Raspberry Pi, the BCM GPIO numbers are different for certain pins on the GPIO header.  These pins are still the same if the physical pin numbering is used, regardless of the model.

Numbering pins based on their physical position seemed like a far easier concept to teach those unfamiliar with the inner workings of computers and microchips.

This was asked in the RasPi.TV interview, so you can make your own mind up, I can see advantages of both approaches.

The RPi.GPIO module supports both modes, so the user was free to use whichever made most sense to them.

RPiGPIOBasic

Physical Pin Numbering

It would take very little so allow the GPIOZero library to support BCM number as default (with no explicit configuration) and allow for this to be overridden if desired.

I’ve also asked the same, via Twitter and via Email but unfortunately it became a sore topic and not something that was open to discussions.  I did try and I hoped that in private discussions some headway could have been made, but I wasn’t given a response (I’ll assume purely because it is always busy busy at the foundation…they just don’t stop!).

The most compelling reason for this, that I can see, is to force a standard so that things become consistent (well if you do not have different versions of the Raspberry Pi).  I may not agree on the standard or see the logic, but I’ll survive.

As RasPi.TV (again…purely by chance here, but Alex does seem to have this one sussed) has worked out, there is one saving grace…the BCM GPIO pins on the newest Raspberry Pi models now number GPIO02 to GPIO27.  Which is put to excellent use by his RasPiO Pro Hat:

f70a581c306ce0d7a02d290dbc911f6d_original

RasPiO Pro Hat – Image credit RasPi.TV

How has using buttons and inputs changed?

The GPIOZero getting started guide covers some of the details.

from gpiozero import Button
button = Button(2)
button.wait_for_press()
print('You pushed me')

 

This is just one method supported for button detection, another is shown below:

from gpiozero import LED, Button
led = LED(17) button = Button(2)
button.when_pressed = led.on
button.when_released = led.off

3rd Party Hat/Hardware Support?

The library already has built in support for a number of 3rd party hardware add-ons.  I am hopeful that this will be open for anyone to submit code for, so that everyone is able to provide GPIOZero style support for a particular Pi peripheral.

 

Should we use it?

That is up to you, but I would say a 100% yes.

ANYTHING which makes coding easier to do is a positive in my view.

The easier you make it the easier it is for the programmer to put their ideas into action (which is the primary reason for coding!).

At the end of the day, GPIOZero is likely to be the standard library for GPIO control and hopefully will grow to include features which the original RPi.GPIO did not.

Check out the GPIOZero site for full documentation on how to use it.

The seamless GPIO.BOARD solution for GPIOZero

Since it makes sense to give people a choice to use the GPIO in the way they find works for them, I’ve created a little solution so you can choose to use GPIO.BOARD (Physical Pin) numbering.  If you don’t set a mode, it’ll just use GPIO.BCM by default (so there is no impact either way).

The files needed are available from here:

github.com – PiHw gpiozero

To set this up you will need to do the following:

  • Locate the devices.py files for PiZero on your Raspberry Pi, these are located in the following places:
    1. /usr/lib/python3/dist-packages/gpiozero/devices.py
    2. /usr/lib/python2.7/dist-packages/gpiozero/devices.py
  • Replace the line which has “GPIO.setmode(GPIO.BCM)” with the following (see devices.py as an example):
#######Added CODE replacing "GPIO.setmode(GPIO.BCM)"########
def setmode():
  try:
    from os import environ
    if "GPIOZERO_BOARD" in environ:
      print(environ["GPIOZERO_BOARD"])
      GPIO.setmode(GPIO.BOARD)
    else:
      #Using BCM pin numbers
      GPIO.setmode(GPIO.BCM)
  except NameError:
    #Using BCM pin numbers
    GPIO.setmode(GPIO.BCM)

setmode() #Set GPIO mode BCM/BOARD
############################################################

 

  • Ensure you have this version of gpiopins.py in the same directory as your script (or it is added to the Python library path).
  • Use the following code when requiring GPIO.BOARD with GPIOZero!

Example testzero.py:

#!/usr/bin/python3
# testzero.py
#
# Example using GPIOZero with GPIO.BOARD numbering
# PiStop in Location C (BOARD pins 8,10,12)
#
# Note: 1. gpiopins.py must be located in python path or same directory.
#       2. /usr/lib/python3/dist-packages/gpiozero/devices.py should be updated as shown in devices.py file.

import gpiopins as GPIO
GPIO.setmode(GPIO.BOARD)

from gpiozero import LED
from time import sleep

green=LED(8)
yellow=LED(10)
red=LED(12)

green.blink()
sleep(0.1)
yellow.blink()
sleep(0.1)
red.blink()

 

Simple!

I shall ask if this could be added to GPIOZero (as it has ZERO impact on other users – BCM stays as the default).  But I may script it as a recipe so I have it available in my Pi-Kitchen anyway.

Advertisement