Raspberry Pi Python IO
Enable Hardware
On Raspberry Pi OS-Desktop:
- access the start menu
Preferences->Raspberry Pi Configuration
On the command line:
sudo raspi-config
- enable/disable various IO in interface options
Check Pinout
Use pinout
to identify GPIO pin numbers from terminal.
GPIO Zero
The GPIO Zero library provides an API to many common Raspberry Pi interfaces.
Install
On Raspberry Pi OS:
sudo apt update
sudo apt install python3-gpiozero
Some Examples
See GPIO Zero recipes for many more examples.
Turning on an LED
from gpiozero import LED
from time import sleep
led = LED(26)
led.on()
sleep(1)
Reading from a Button
Button
is by default a switch which pulls the input low when active. See button docs for more options.
from gpiozero import Button
button = Button(21)
if button.is_pressed:
print("<Pressed>")
else:
print("<None>")
Commanding a Servo
Servo
has range -1.0 to 1.0AngularServo
has range from -90 to 90 (but can be changed)
from gpiozero import AngularServo
from time import sleep
servo = Servo(18)
while True:
servo.angle = 45
sleep(2)
servo.angle = -45
sleep(2)
- If the
servo.angle = None
, then it receives no power
Reading from an Encoder
from gpiozero import RotaryEncoder
from time import sleep
# Note: For https://www.dfrobot.com/product-1431.html
encoder = RotaryEncoder(5, 6, max_steps=105, wrap=True)
while True:
print("encoder position {}".format(encoder.value*180))
sleep(1)
Generic Output Devices
from gpiozero import DigitalOutputDevice
from time import sleep
dout = DigitalOutputDevice(26)
while True:
sleep(1)
dout.off()
sleep(1)
dout.on()
Generic Input Devices
from gpiozero import DigitalInputDevice
from time import sleep
din = DigitalInputDevice(21, pull_up=True)
din.when_activated=lambda: print("HIGH")
din.when_deactivated=lambda: print("LOW")
while True:
sleep(1)
if din.value:
print("{} seconds".format(din.active_time))
else:
print("{} seconds".format(din.inactive_time))
Reducing Servo Jitter
When running the servo code above, we get the warning:
PWMSoftwareFallback: To reduce servo jitter, use the pigpio pin factory.
We would like our PWM to be hardware driven, rather than be at the mercy of the OS.
There are two steps:
- Install
pigpio
- Use GPIO Zero pin factories
Installing pigpio
On Raspberry Pi OS:
sudo apt update
sudo apt install pigpio
sudo apt install python3-pigpio
pigpio daemon
pigpio
uses a daemon (that takes port :8888
) to control IO pins.
The daemon must be running to control IO pins from your Raspberry Pi.
Start the pigpio daemon:
sudo systemctl start pigpiod
Enable pigpio daemon at boot:
sudo systemctl enable pigpiod
Using a Pin Factory
GPIO Zero uses Pin Factroies to provide various pin drivers.
Once pigpio
is installed, we can use its pin factory.
from gpiozero import Servo
from gpiozero.pins.pigpio import PiGPIOFactory
from time import sleep
factory = PiGPIOFactory()
servo = Servo(18, pin_factory=factory)
while True:
servo.min()
sleep(2)
servo.mid()
sleep(2)
servo.max()
sleep(2)
This time, the pulses are very stable and the servo has no jitter.
Jitter Comparison
I wanted to compare pigpio
to the default pin driver; so I put a scope on the two implementations:
- yellow is
pigpio
- on closer inspection only jitters about 0.2 microseconds; error (0.02%).
- blue is the default driver
- it appears to put out two pulses per cycle
- the second pulse seems to be asyncronous and the average of the two provide the servo pulse
pigpio
GPIO Zero doesn’t support some IO (such as serial).
In these cases, we can interface with the pigpio daemon directly.
See the pigpio python API for more details.
Interfacing with a serial port
Assuming pigpio
is already installed and the daemon is running:
import pigpio
import time
pi = pigpio.pi()
if not pi.connected:
exit()
s = pi.serial_open("/dev/ttyS0", 115200)
pi.serial_write(s, "j")
time.sleep(1)
len, data = pi.serial_read(s, 100)
if len > 0:
print(data.decode("utf-8"))
else:
print("no data")
- This interfaces with a bittle on a Raspberry Pi 3
- Other models of Raspberry Pi may use
/dev/ttyAMA0
- Other models of Raspberry Pi may use
- When debugging serial ports, consider PySerial’s miniterm