跳到主要内容

基本用法

以下示例演示了 GPIO Zero 库的部分功能。请注意,所有配方都是假设 Python 3 编写的。在 Python 2 下可能也能运行,但并不保证!

导入 GPIO Zero

在 Python 中,脚本中使用的库和函数必须在文件顶部按名称导入,Python 默认内置的函数除外。

例如,要使用 GPIO Zero 中的 Button 接口,必须明确导入:

from gpiozero import Button

现在 Button 可以直接在脚本中使用了:

button = Button(2)

或者,也可以导入整个 GPIO Zero 库:

import gpiozero

在这种情况下,对 GPIO Zero 中所有项目的引用都必须加上前缀:

button = gpiozero.Button(2)

引脚编号

该库的 GPIO 引脚使用 Broadcom (BCM) 引脚编号,而非物理 (BOARD) 编号。与 RPi.GPIO 库不同的是,它不可配置。不过,可以通过为引脚编号提供前缀来转换其他方案(见下文)。

下图中任何标有 GPIO 的引脚都可以用作引脚编号。例如,如果 LED 连接到 GPIO17,则应将引脚编号指定为 17,而不是 11

GPIO 引脚布局3V3PowerGPIO2SDA I²CGPIO3SCL I²CGPIO4GroundGPIO17GPIO27GPIO223V3PowerGPIO10SPI MOSIGPIO9SPI MISOGPIO11SPI SCLKGroundID SDI²C IDGPIO5GPIO6GPIO13GPIO19GPIO26Ground5VPower5VPowerGroundGPIO14UART0 TXDGPIO15UART0 RXDGPIO18GroundGPIO23GPIO24GroundGPIO25GPIO8SPI CE0GPIO7SPI CE1ID SCI²C IDGroundGPIO12GroundGPIO16GPIO20GPIO21All Models40-pinmodels only113579111315171921232527293133353739246810121416182022242628303234363840USB Ports

如果希望使用物理(BOARD)编号,则可将引脚编号指定为 BOARD11。如果您熟悉 wiringPi 引脚编号(另一种物理布局),可以使用 WPI0 来代替。最后,还可以将引脚指定为 header:number(头:编号),例如 J8:11 表示头 J8(现代 Pis 上的 GPIO 头)上的物理引脚 11。因此,以下几行都是等价的:

led = LED(17)
led = LED("GPIO17")
led = LED("BCM17")
led = LED("BOARD11")
led = LED("WPI0")
led = LED("J8:11")

请注意,这些备用方案只是转换。如果您在命令行上请求设备状态,相关引脚编号将始终以 Broadcom (BCM) 方案报告:

led = LED("BOARD11")
led
<gpiozero.LED object on pin GPIO17, active_high=True, is_active=False>

在本手册中,我们将按照上图所示的 Broadcom (BCM) 布局使用默认的整数引脚编号。

LED (LED)

LED 接线图Raspberry Pi Model 2 v1.1© Raspberry Pi 2014http://www.raspberrypi.orgPowerHDMIAudioUSB 2xUSB 2xETHERNETDSI (DISPLAY)CSI (CAMERA)GPIO

反复打开和关闭 LED

from gpiozero import LED
from time import sleep

red = LED(17)

while True:
red.on()
sleep(1)
red.off()
sleep(1)

或者

from gpiozero import LED
from signal import pause

red = LED(17)

red.blink()

pause()
提示

Python 脚本结束时会终止进程,GPIO 可能会被重置。请使用 signal.pause() 使脚本继续运行。更多信息,请参阅 如何保持脚本运行?

亮度可变的 LED

LED 接线图Raspberry Pi Model 2 v1.1© Raspberry Pi 2014http://www.raspberrypi.orgPowerHDMIAudioUSB 2xUSB 2xETHERNETDSI (DISPLAY)CSI (CAMERA)GPIO

任何普通 LED 都可以使用 PWM(脉宽调制)设置其亮度值。在 GPIO Zero 中,可以使用 PWMLED(亮度值在 0 和 1 之间)来实现这一功能:

from gpiozero import PWMLED
from time import sleep

led = PWMLED(17)

while True:
led.value = 0 # off
sleep(1)
led.value = 0.5 # half brightness
sleep(1)
led.value = 1 # full brightness
sleep(1)

与连续闪亮和熄灭类似,PWMLED 也可以脉冲(连续淡入淡出):

from gpiozero import PWMLED
from signal import pause

led = PWMLED(17)

led.pulse()

pause()

按钮 (Button)

Button 接线图Raspberry Pi Model 2 v1.1© Raspberry Pi 2014http://www.raspberrypi.orgPowerHDMIAudioUSB 2xUSB 2xETHERNETDSI (DISPLAY)CSI (CAMERA)GPIO

检查 Button 是否被按下:

from gpiozero import Button

button = Button(2)

while True:
if button.is_pressed:
print("Button is pressed")
else:
print("Button is not pressed")

等待按下按钮后再继续:

from gpiozero import Button

button = Button(2)

button.wait_for_press()
print("Button was pressed")

每次按下按钮都运行一个功能:

from gpiozero import Button
from signal import pause

def say_hello():
print("Hello!")

button = Button(2)

button.when_pressed = say_hello

pause()
提示

请注意,button.when_pressed = say_hello 这一行并不运行 say_hello 函数,而是创建一个指向按下按钮时要调用的函数的引用。意外使用 button.when_pressed = say_hello(),会将 when_pressed 操作设置为 None(该函数的返回值),这意味着按下按钮时什么也不会发生。

同样,按钮释放也可以附加功能:

from gpiozero import Button
from signal import pause

def say_hello():
print("Hello!")

def say_goodbye():
print("Goodbye!")

button = Button(2)

button.when_pressed = say_hello
button.when_released = say_goodbye

pause()

按钮 控制 LED

Button 控制 LED 接线图7115510101515202025253030AABBCCDDEEFFGGHHIIJJRaspberry Pi Model 2 v1.1© Raspberry Pi 2014http://www.raspberrypi.orgPowerHDMIAudioUSB 2xUSB 2xETHERNETDSI (DISPLAY)CSI (CAMERA)GPIO

按下 Button 时打开 LED

from gpiozero import LED, Button
from signal import pause

led = LED(17)
button = Button(2)

button.when_pressed = led.on
button.when_released = led.off

pause()

或者

from gpiozero import LED, Button
from signal import pause

led = LED(17)
button = Button(2)

led.source = button

pause()

按钮 控制 摄像头

使用 button.when_pressed = camera.capture 来触发 PiCamera 拍照是行不通的,因为 capture() 方法需要一个 输出 参数。不过,可以使用无需参数的自定义函数来实现:

from gpiozero import Button
from picamera import PiCamera
from datetime import datetime
from signal import pause

button = Button(2)
camera = PiCamera()

def capture():
camera.capture(f'/home/pi/{datetime.now():%Y-%m-%d-%H-%M-%S}.jpg')

button.when_pressed = capture

pause()

另一个例子是使用一个按钮来启动和停止摄像头预览,另一个按钮用来捕捉:

from gpiozero import Button
from picamera import PiCamera
from datetime import datetime
from signal import pause

left_button = Button(2)
right_button = Button(3)
camera = PiCamera()

def capture():
camera.capture(f'/home/pi/{datetime.now():%Y-%m-%d-%H-%M-%S}.jpg')

left_button.when_pressed = camera.start_preview
left_button.when_released = camera.stop_preview
right_button.when_pressed = capture

pause()

关机按钮

Button 类还提供了在按住按钮一定时间后运行函数的功能。本示例将在按住按钮 2 秒时关闭 Raspberry Pi:

from gpiozero import Button
from subprocess import check_call
from signal import pause

def shutdown():
check_call(['sudo', 'poweroff'])

shutdown_btn = Button(17, hold_time=2)
shutdown_btn.when_held = shutdown

pause()

LED板 (LEDBoard)

LED板 接线图7115510101515202025253030AABBCCDDEEFFGGHHIIJJRaspberry Pi Model 2 v1.1© Raspberry Pi 2014http://www.raspberrypi.orgPowerHDMIAudioUSB 2xUSB 2xETHERNETDSI (DISPLAY)CSI (CAMERA)GPIO

使用 LEDBoard 可以访问 LED 集合:

from gpiozero import LEDBoard
from time import sleep
from signal import pause

leds = LEDBoard(5, 6, 13, 19, 26)

leds.on()
sleep(1)
leds.off()
sleep(1)
leds.value = (1, 0, 1, 0, 1)
sleep(1)
leds.blink()

pause()

使用 pwm=TrueLEDBoard 可以控制每个 LED 的亮度:

from gpiozero import LEDBoard
from signal import pause

leds = LEDBoard(5, 6, 13, 19, 26, pwm=True)

leds.value = (0.2, 0.4, 0.6, 0.8, 1.0)

pause()

高级 LEDBoard 方案 中查看更多 LEDBoard 示例。

LED条形图 (LEDBarGraph)

LED条形图 接线图7115510101515202025253030AABBCCDDEEFFGGHHIIJJRaspberry Pi Model 2 v1.1© Raspberry Pi 2014http://www.raspberrypi.orgPowerHDMIAudioUSB 2xUSB 2xETHERNETDSI (DISPLAY)CSI (CAMERA)GPIO

使用 LEDBarGraph 可以像条形图一样处理 LED 集合:

from gpiozero import LEDBarGraph
from time import sleep

graph = LEDBarGraph(5, 6, 13, 19, 26, 20)

graph.value = 1 # (1, 1, 1, 1, 1, 1)
sleep(1)
graph.value = 1/2 # (1, 1, 1, 0, 0, 0)
sleep(1)
graph.value = -1/2 # (0, 0, 0, 1, 1, 1)
sleep(1)
graph.value = 1/4 # (1, 0, 0, 0, 0, 0)
sleep(1)
graph.value = -1 # (1, 1, 1, 1, 1, 1)
sleep(1)

由于 LED 只能在 pwm=False 时开启或关闭(默认值),因此数值基本上是四舍五入的。

不过,在 pwm=True 时使用 LEDBarGraph 可以使用 LED 亮度获得更精确的数值:

from gpiozero import LEDBarGraph
from time import sleep

graph = LEDBarGraph(5, 6, 13, 19, 26, pwm=True)

graph.value = 1/10 # (0.5, 0, 0, 0, 0)
sleep(1)
graph.value = 3/10 # (1, 0.5, 0, 0, 0)
sleep(1)
graph.value = -3/10 # (0, 0, 0, 0.5, 1)
sleep(1)
graph.value = 9/10 # (1, 1, 1, 1, 0.5)
sleep(1)
graph.value = 95/100 # (1, 1, 1, 1, 0.75)
sleep(1)

LED字符显示屏 (LEDCharDisplay)

LED字符显示屏 接线图7115510101515202025253030AABBCCDDEEFFGGHHIIJJRaspberry Pi Model 2 v1.1© Raspberry Pi 2014http://www.raspberrypi.orgPowerHDMIAudioUSB 2xUSB 2xETHERNETDSI (DISPLAY)CSI (CAMERA)GPIO

使用 LEDCharDisplay(实际上支持任意数量的显示段),可以用普通的 7 段显示 来表示各种字符:

from gpiozero import LEDCharDisplay
from time import sleep

display = LEDCharDisplay(21, 20, 16, 22, 23, 24, 12, dp=25)

for char in '321GO':
display.value = char
sleep(1)

display.off()

或者

from gpiozero import LEDCharDisplay
from signal import pause

display = LEDCharDisplay(21, 20, 16, 22, 23, 24, 12, dp=25)
display.source_delay = 1
display.source = '321GO '

pause()

高级 LEDBoard 方案 中查看更多多字符示例。

交通信号灯 (TrafficLights)

交通信号灯 接线图7115510101515202025253030AABBCCDDEEFFGGHHIIJJRaspberry Pi Model 2 v1.1© Raspberry Pi 2014http://www.raspberrypi.orgPowerHDMIAudioUSB 2xUSB 2xETHERNETDSI (DISPLAY)CSI (CAMERA)GPIO

完整的交通灯系统

使用像 Pi-Stop 这样的 TrafficLights 套件:

from gpiozero import TrafficLights
from time import sleep

lights = TrafficLights(2, 3, 4)

lights.green.on()

while True:
sleep(10)
lights.green.off()
lights.amber.on()
sleep(1)
lights.amber.off()
lights.red.on()
sleep(10)
lights.amber.on()
sleep(1)
lights.green.on()
lights.amber.off()
lights.red.off()

或者

from gpiozero import TrafficLights
from time import sleep
from signal import pause

lights = TrafficLights(2, 3, 4)

def traffic_light_sequence():
while True:
yield (0, 0, 1) # green
sleep(10)
yield (0, 1, 0) # amber
sleep(1)
yield (1, 0, 0) # red
sleep(10)
yield (1, 1, 0) # red+amber
sleep(1)

lights.source = traffic_light_sequence()

pause()

使用 LED 组件:

from gpiozero import LED
from time import sleep

red = LED(2)
amber = LED(3)
green = LED(4)

green.on()
amber.off()
red.off()

while True:
sleep(10)
green.off()
amber.on()
sleep(1)
amber.off()
red.on()
sleep(10)
amber.on()
sleep(1)
green.on()
amber.off()
red.off()

组合设计

按钮定格

每次按下按钮时,摄像头模块都会拍摄一张照片:

from gpiozero import Button
from picamera import PiCamera

button = Button(2)
camera = PiCamera()

camera.start_preview()
frame = 1
while True:
button.wait_for_press()
camera.capture(f'/home/pi/frame{frame:03d}.jpg')
frame += 1

请参阅 按钮定格 获取完整资源。

反应游戏

反应游戏 接线图7115510101515202025253030AABBCCDDEEFFGGHHIIJJRaspberry Pi Model 2 v1.1© Raspberry Pi 2014http://www.raspberrypi.orgPowerHDMIAudioUSB 2xUSB 2xETHERNETDSI (DISPLAY)CSI (CAMERA)GPIO

当看到灯亮起时,最先按下按钮的人获胜!

from gpiozero import Button, LED
from time import sleep
import random

led = LED(17)

player_1 = Button(2)
player_2 = Button(3)

time = random.uniform(5, 10)
sleep(time)
led.on()

while True:
if player_1.is_pressed:
print("Player 1 wins!")
break
if player_2.is_pressed:
print("Player 2 wins!")
break

led.off()

请参阅 快速反应游戏 获取完整资源。

GPIO音乐盒

GPIO音乐盒 接线图7115510101515202025253030AABBCCDDEEFFGGHHIIJJRaspberry Pi Model 2 v1.1© Raspberry Pi 2014http://www.raspberrypi.orgPowerHDMIAudioUSB 2xUSB 2xETHERNETDSI (DISPLAY)CSI (CAMERA)GPIO

每个按钮都会发出不同的声音!

from gpiozero import Button
import pygame.mixer
from pygame.mixer import Sound
from signal import pause

pygame.mixer.init()

button_sounds = {
Button(2): Sound("samples/drum_tom_mid_hard.wav"),
Button(3): Sound("samples/drum_cymbal_open.wav"),
}

for button, sound in button_sounds.items():
button.when_pressed = sound.play

pause()

请参阅 GPIO音乐盒 获取完整资源。

按下时全部打开

FishDish

按下按钮时,蜂鸣器和所有指示灯都会亮起。

from gpiozero import FishDish
from signal import pause

fish = FishDish()

fish.button.when_pressed = fish.on
fish.button.when_released = fish.off

pause()

Ryanteck TrafficHat:(译注:由 Ryanteck 出品的 交通灯 小板)

from gpiozero import TrafficHat
from signal import pause

th = TrafficHat()

th.button.when_pressed = th.on
th.button.when_released = th.off

pause()

使用 LEDBuzzer,和 Button 组件:

from gpiozero import LED, Buzzer, Button
from signal import pause

button = Button(2)
buzzer = Buzzer(3)
red = LED(4)
amber = LED(5)
green = LED(6)

things = [red, amber, green, buzzer]

def things_on():
for thing in things:
thing.on()

def things_off():
for thing in things:
thing.off()

button.when_pressed = things_on
button.when_released = things_off

pause()

全彩LED (RGBLED)

全彩LED 接线图7115510101515202025253030AABBCCDDEEFFGGHHIIJJRaspberry Pi Model 2 v1.1© Raspberry Pi 2014http://www.raspberrypi.orgPowerHDMIAudioUSB 2xUSB 2xETHERNETDSI (DISPLAY)CSI (CAMERA)GPIO

RGBLED 制作色彩:

from gpiozero import RGBLED
from time import sleep

led = RGBLED(red=9, green=10, blue=11)

led.red = 1 # full red
sleep(1)
led.red = 0.5 # half red
sleep(1)

led.color = (0, 1, 0) # full green
sleep(1)
led.color = (1, 0, 1) # magenta
sleep(1)
led.color = (1, 1, 0) # yellow
sleep(1)
led.color = (0, 1, 1) # cyan
sleep(1)
led.color = (1, 1, 1) # white
sleep(1)

led.color = (0, 0, 0) # off
sleep(1)

# slowly increase intensity of blue
for n in range(100):
led.blue = n/100
sleep(0.1)

运动传感器 (MotionSensor)

运动传感器 接线图7115510101515202025253030AABBCCDDEEFFGGHHIIJJRaspberry Pi Model 2 v1.1© Raspberry Pi 2014http://www.raspberrypi.orgPowerHDMIAudioUSB 2xUSB 2xETHERNETDSI (DISPLAY)CSI (CAMERA)GPIO

MotionSensor(运动传感器) 检测到运动时,点亮 LED

from gpiozero import MotionSensor, LED
from signal import pause

pir = MotionSensor(4)
led = LED(16)

pir.when_motion = led.on
pir.when_no_motion = led.off

pause()

光传感器 (LightSensor)

光传感器 接线图7115510101515202025253030AABBCCDDEEFFGGHHIIJJRaspberry Pi Model 2 v1.1© Raspberry Pi 2014http://www.raspberrypi.orgPowerHDMIAudioUSB 2xUSB 2xETHERNETDSI (DISPLAY)CSI (CAMERA)GPIO

LightSensor(光传感器) 检测明暗:

from gpiozero import LightSensor

sensor = LightSensor(18)

while True:
sensor.wait_for_light()
print("It's light! :)")
sensor.wait_for_dark()
print("It's dark :(")

在光线变化时运行功能:

from gpiozero import LightSensor, LED
from signal import pause

sensor = LightSensor(18)
led = LED(16)

sensor.when_dark = led.on
sensor.when_light = led.off

pause()

或使 PWMLED 根据检测到的光亮度改变亮度:

from gpiozero import LightSensor, PWMLED
from signal import pause

sensor = LightSensor(18)
led = PWMLED(16)

led.source = sensor

pause()

距离传感器 (DistanceSensor)

距离传感器 接线图7115510101515202025253030AABBCCDDEEFFGGHHIIJJRaspberry Pi Model 2 v1.1© Raspberry Pi 2014http://www.raspberrypi.orgPowerHDMIAudioUSB 2xUSB 2xETHERNETDSI (DISPLAY)CSI (CAMERA)GPIO

提示

在上图中,从传感器到面包板的导线可以省略;只需将传感器直接插入面包板,面向边缘即可(遗憾的是,如果传感器的示意图没有遮住面包板的大部分,就很难在图中说明这一点!)。

让距离传感器(DistanceSenso) 检测最近物体的距离:

from gpiozero import DistanceSensor
from time import sleep

sensor = DistanceSensor(23, 24)

while True:
print('Distance to nearest object is', sensor.distance, 'm')
sleep(1)

当有东西靠近传感器时,运行一个功能:

from gpiozero import DistanceSensor, LED
from signal import pause

sensor = DistanceSensor(23, 24, max_distance=1, threshold_distance=0.2)
led = LED(16)

sensor.when_in_range = led.on
sensor.when_out_of_range = led.off

pause()

旋转编码器 (RotaryEncoder)

旋转编码器 接线图7115510101515202025253030AABBCCDDEEFFGGHHIIJJRaspberry Pi Model 2 v1.1© Raspberry Pi 2014http://www.raspberrypi.orgPowerHDMIAudioUSB 2xUSB 2xETHERNETDSI (DISPLAY)CSI (CAMERA)GPIO

提示

在本方案中,使用的是普通阳极 RGB LED。通常情况下,Pi 项目会使用共阴极 RGB LED,因为它们在电气上更容易理解。但在本例中,所有三个元件都可以在一个发光旋转编码器中找到,该编码器包含一个共阳极 RGB LED 和一个瞬时按钮。这也是按钮为低电平有效接线的原因,与本文档中的大多数其他示例相反。

为清晰起见,图中显示了三个独立的组件,但同样的电路也可以用这种常见的 发光旋转编码器 代替。

将旋转编码器(RotaryEncoder)、RGBLED 和按钮(Button) 作颜色选择器:

from threading import Event
from colorzero import Color
from gpiozero import RotaryEncoder, RGBLED, Button

rotor = RotaryEncoder(16, 20, wrap=True, max_steps=180)
rotor.steps = -180
led = RGBLED(22, 23, 24, active_high=False)
btn = Button(21, pull_up=False)
led.color = Color('#f00')
done = Event()

def change_hue():
# Scale the rotor steps (-180..180) to 0..1
hue = (rotor.steps + 180) / 360
led.color = Color(h=hue, s=1, v=1)

def show_color():
print(f'Hue {led.color.hue.deg:.1f}° = {led.color.html}')

def stop_script():
print('Exiting')
done.set()

print('Select a color by turning the knob')
rotor.when_rotated = change_hue
print('Push the button to see the HTML code for the color')
btn.when_released = show_color
print('Hold the button to exit')
btn.when_held = stop_script
done.wait()

伺服 (Servo)

依次在最小位置、中间位置和最大位置之间控制伺服(Servo):

from gpiozero import Servo
from time import sleep

servo = Servo(17)

while True:
servo.min()
sleep(2)
servo.mid()
sleep(2)
servo.max()
sleep(2)

使用按钮在最小和最大位置之间控制伺服(Servo):

from gpiozero import Servo, Button

servo = Servo(17)
btn = Button(14)

while True:
servo.min()
btn.wait_for_press()
servo.max()
btn.wait_for_press()

自动伺服(Servo)连续缓慢扫动:

rom gpiozero import Servo
from gpiozero.tools import sin_values
from signal import pause

servo = Servo(17)

servo.source = sin_values()
servo.source_delay = 0.1

pause()

使用角度伺服(AngularServo)可以指定角度:

from gpiozero import AngularServo
from time import sleep

servo = AngularServo(17, min_angle=-90, max_angle=90)

while True:
servo.angle = -90
sleep(2)
servo.angle = -45
sleep(2)
servo.angle = 0
sleep(2)
servo.angle = 45
sleep(2)
servo.angle = 90
sleep(2)

电机 (Motor)

电机 接线图7115510101515202025253030AABBCCDDEEFFGGHHIIJJRaspberry Pi Model 2 v1.1© Raspberry Pi 2014http://www.raspberrypi.orgPowerHDMIAudioUSB 2xUSB 2xETHERNETDSI (DISPLAY)CSI (CAMERA)GPIO

正向和反向旋转电机(Motor):

from gpiozero import Motor
from time import sleep

motor = Motor(forward=4, backward=14)

while True:
motor.forward()
sleep(5)
motor.backward()
sleep(5)

机器人 (Robot)

机器人 接线图7115510101515202025253030AABBCCDDEEFFGGHHIIJJRaspberry Pi Model 2 v1.1© Raspberry Pi 2014http://www.raspberrypi.orgPowerHDMIAudioUSB 2xUSB 2xETHERNETDSI (DISPLAY)CSI (CAMERA)GPIO

让机器人(Robot) 在(大致)一个正方形内行驶:

from gpiozero import Robot, Motor
from time import sleep

robot = Robot(left=Motor(4, 14), right=Motor(17, 18))

for i in range(4):
robot.forward()
sleep(10)
robot.right()
sleep(1)

制作一个带有距离传感器(DistanceSensor)的机器人(Robot),当物体靠近它 20 厘米以内时,它就会逃跑:

from gpiozero import Robot, Motor, DistanceSensor
from signal import pause

sensor = DistanceSensor(23, 24, max_distance=1, threshold_distance=0.2)
robot = Robot(left=Motor(4, 14), right=Motor(17, 18))

sensor.when_in_range = robot.backward
sensor.when_out_of_range = robot.stop
pause()

组合控制

按钮控制机器人

按钮控制机器人 接线图7115510101515202025253030AABBCCDDEEFFGGHHIIJJRaspberry Pi Model 2 v1.1© Raspberry Pi 2014http://www.raspberrypi.orgPowerHDMIAudioUSB 2xUSB 2xETHERNETDSI (DISPLAY)CSI (CAMERA)GPIO

将四个 GPIO 按钮用作机器人(Robot)的前进/后退/左转/右转控制器:

from gpiozero import Robot, Motor, Button
from signal import pause

robot = Robot(left=Motor(4, 14), right=Motor(17, 18))

left = Button(26)
right = Button(16)
fw = Button(21)
bw = Button(20)

fw.when_pressed = robot.forward
fw.when_released = robot.stop

left.when_pressed = robot.left
left.when_released = robot.stop

right.when_pressed = robot.right
right.when_released = robot.stop

bw.when_pressed = robot.backward
bw.when_released = robot.stop

pause()

键盘控制机器人

机器人 接线图7115510101515202025253030AABBCCDDEEFFGGHHIIJJRaspberry Pi Model 2 v1.1© Raspberry Pi 2014http://www.raspberrypi.orgPowerHDMIAudioUSB 2xUSB 2xETHERNETDSI (DISPLAY)CSI (CAMERA)GPIO

使用上/下/左/右键控制机器人(Robot):

import curses
from gpiozero import Robot, Motor

robot = Robot(left=Motor(4, 14), right=Motor(17, 18))

actions = {
curses.KEY_UP: robot.forward,
curses.KEY_DOWN: robot.backward,
curses.KEY_LEFT: robot.left,
curses.KEY_RIGHT: robot.right,
}

def main(window):
next_key = None
while True:
curses.halfdelay(1)
if next_key is None:
key = window.getch()
else:
key = next_key
next_key = None
if key != -1:
# KEY PRESSED
curses.halfdelay(3)
action = actions.get(key)
if action is not None:
action()
next_key = key
while next_key == key:
next_key = window.getch()
# KEY RELEASED
robot.stop()

curses.wrapper(main)
提示

本教程使用标准的 curses 模块。该模块要求 Python 在终端中运行才能正常工作,因此该方案无法在 IDLE 等环境中运行。

如果你更喜欢在 IDLE 下运行的版本,下面的方案就足够了:

from gpiozero import Robot, Motor
from evdev import InputDevice, list_devices, ecodes

robot = Robot(left=Motor(4, 14), right=Motor(17, 18))

# Get the list of available input devices
devices = [InputDevice(device) for device in list_devices()]
# Filter out everything that's not a keyboard. Keyboards are defined as any
# device which has keys, and which specifically has keys 1..31 (roughly Esc,
# the numeric keys, the first row of QWERTY plus a few more) and which does
# *not* have key 0 (reserved)
must_have = {i for i in range(1, 32)}
must_not_have = {0}
devices = [
dev
for dev in devices
for keys in (set(dev.capabilities().get(ecodes.EV_KEY, [])),)
if must_have.issubset(keys)
and must_not_have.isdisjoint(keys)
]
# Pick the first keyboard
keyboard = devices[0]

keypress_actions = {
ecodes.KEY_UP: robot.forward,
ecodes.KEY_DOWN: robot.backward,
ecodes.KEY_LEFT: robot.left,
ecodes.KEY_RIGHT: robot.right,
}

for event in keyboard.read_loop():
if event.type == ecodes.EV_KEY and event.code in keypress_actions:
if event.value == 1: # key pressed
keypress_actions[event.code]()
if event.value == 0: # key released
robot.stop()
提示

本方案使用第三方 evdev 模块。请先使用 sudo pip3 install evdev 安装该库。请注意,evdev 只适用于本地输入设备;本方案无法通过 SSH 运行。

运动传感器机器人

运动传感器机器人 接线图7115510101515202025253030AABBCCDDEEFFGGHHIIJJRaspberry Pi Model 2 v1.1© Raspberry Pi 2014http://www.raspberrypi.orgPowerHDMIAudioUSB 2xUSB 2xETHERNETDSI (DISPLAY)CSI (CAMERA)GPIO

让机器人在检测到运动时向前驱动:

from gpiozero import Robot, Motor, MotionSensor
from signal import pause

robot = Robot(left=Motor(4, 14), right=Motor(17, 18))
pir = MotionSensor(5)

pir.when_motion = robot.forward
pir.when_no_motion = robot.stop

pause()

或者

from gpiozero import Robot, Motor, MotionSensor
from gpiozero.tools import zip_values
from signal import pause

robot = Robot(left=Motor(4, 14), right=Motor(17, 18))
pir = MotionSensor(5)

robot.source = zip_values(pir, pir)

pause()

电位器

电位器 接线图7115510101515202025253030AABBCCDDEEFFGGHHIIJJRaspberry Pi Model 2 v1.1© Raspberry Pi 2014http://www.raspberrypi.orgPowerHDMIAudioUSB 2xUSB 2xETHERNETDSI (DISPLAY)CSI (CAMERA)GPIOMCP3008

连续打印连接到 MCP3008 模数转换器的电位计的数值(数值在 0 和 1 之间):

from gpiozero import MCP3008

pot = MCP3008(channel=0)

while True:
print(pot.value)

使用 PWM 在 LED 柱状图上显示电位器的值,以表示不会 "填满" LED 的状态:

from gpiozero import LEDBarGraph, MCP3008
from signal import pause

graph = LEDBarGraph(5, 6, 13, 19, 26, pwm=True)
pot = MCP3008(channel=0)

graph.source = pot

pause()

使用 ADC 测量温度

将 TMP36 温度传感器连接到 MCP3008 模数转换器的第一通道:

from gpiozero import MCP3008
from time import sleep

def convert_temp(gen):
for value in gen:
yield (value * 3.3 - 0.5) * 100

adc = MCP3008(channel=0)

for temp in convert_temp(adc.values):
print('The temperature is', temp, 'C')
sleep(1)

3个电位器控制的全彩LED

RTBLED+电位器 接线图7115510101515202025253030AABBCCDDEEFFGGHHIIJJRaspberry Pi Model 2 v1.1© Raspberry Pi 2014http://www.raspberrypi.orgPowerHDMIAudioUSB 2xUSB 2xETHERNETDSI (DISPLAY)CSI (CAMERA)GPIOMCP3008

连接三个电位器(红、绿、蓝),用每个电位器的值组成 LED 的颜色:

from gpiozero import RGBLED, MCP3008

led = RGBLED(red=2, green=3, blue=4)
red_pot = MCP3008(channel=0)
green_pot = MCP3008(channel=1)
blue_pot = MCP3008(channel=2)

while True:
led.red = red_pot.value
led.green = green_pot.value
led.blue = blue_pot.value

另外,下面的示例与此相同,但使用的是 source 属性而不是 while 循环:

from gpiozero import RGBLED, MCP3008
from gpiozero.tools import zip_values
from signal import pause

led = RGBLED(2, 3, 4)
red_pot = MCP3008(0)
green_pot = MCP3008(1)
blue_pot = MCP3008(2)

led.source = zip_values(red_pot, green_pot, blue_pot)

pause()

定时加热灯

如果您饲养的宠物(如乌龟)需要每天在一定时间内打开保温灯,您可以使用 Energenie Pi-mote 远程控制保温灯,并使用 TimeOfDay 类来控制时间:

from gpiozero import Energenie, TimeOfDay
from datetime import time
from signal import pause

lamp = Energenie(1)
daytime = TimeOfDay(time(8), time(20))

daytime.when_activated = lamp.on
daytime.when_deactivated = lamp.off

pause()

互联网连接状态指示灯

您可以使用一对绿色和红色 LED 灯来指示互联网连接是否正常。只需使用 PingServer 类即可识别 ping 到 baidu.com 是否成功。如果成功,则点亮绿色 LED 灯;如果不成功,则点亮红色 LED 灯:

from gpiozero import LED, PingServer
from gpiozero.tools import negated
from signal import pause

green = LED(17)
red = LED(18)

google = PingServer('baidu.com')

google.when_activated = green.on
google.when_deactivated = green.off
red.source = negated(green)

pause()

CPU温度条形图

您可以使用内置的 CPUTemperature 类读取 Raspberry Pi 自身 CPU 的温度,并将其显示在 LED 的 "条形图" 上:

from gpiozero import LEDBarGraph, CPUTemperature
from signal import pause

cpu = CPUTemperature(min_temp=50, max_temp=90)
leds = LEDBarGraph(2, 3, 4, 5, 6, 7, 8, pwm=True)

leds.source = cpu

pause()

中文翻译版以英文版相同知识授权方式共享:BSD-3-Clause。交流 Q群:498908352