源与值
GPIO Zero 提供了一种使用声明式编程范例将设备连接在一起的方法:将一个设备的值输入到另一个设备,例如将按钮的值输入到 LED:
from gpiozero import LED, Button
from signal import pause
led = LED(17)
button = Button(2)
led.source = button
pause()
相当于
from gpiozero import LED, Button
from time import sleep
led = LED(17)
button = Button(2)
while True:
led.value = button.value
sleep(0.01)
只不过前者是在后台线程中更新的,这样就可以同时做其他事情。
每个设备都有一个 value
属性(设备的当前值)。输入设备(如按钮)只能读取其值,但输出设备(如 LED)也可以设置其值来改变设备的状态:
>>> led = PWMLED(17)
>>> led.value # LED is initially off
0.0
>>> led.on() # LED is now on
>>> led.value
1.0
>>> led.value = 0 # LED is now off
每个设备都有一个 value
属性(持续 生成 设备当前值的生成器)。所有输出设备都有一个 source
属性,可以设置为任何 迭代器。设备将遍历所提供设备的值,以 source_delay
属性中指定的速率(默认值为 0.01 秒)为每个元素设置设备值。
最常见的用例是设置输出设备的源,使其与输入设备的值相匹配,如上面的例子。更有趣的例子是控制 LED 亮度的电位计:
from gpiozero import PWMLED, MCP3008
from signal import pause
led = PWMLED(17)
pot = MCP3008()
led.source = pot
pause()
其工作原理是,输入设备的 value
属性用于向输出设备输入值。在 v1.5 之前,source
必须直接设置为设备的 value
属性:
from gpiozero import PWMLED, MCP3008
from signal import pause
led = PWMLED(17)
pot = MCP3008()
led.source = pot.values
pause()
虽然这种方法仍受支持,但现在推荐的方法是将 source
设置为设备对象。
也可以将一个输出设备的 source
设置为另一个输出设备,使它们保持匹配。在本例中,红色 LED 被设置为与按钮匹配,绿色 LED 被设置为与红色 LED 匹配,因此当按下按钮时,两个 LED 都会亮起:
from gpiozero import LED, Button
from signal import pause
red = LED(14)
green = LED(15)
button = Button(17)
red.source = button
green.source = red
pause()
处理数值
设备的数值在传递给 source
之前也可以进行处理:
例如,编写一个生成器函数,将与 Button 值相反的值传入 LED:
from gpiozero import Button, LED
from signal import pause
def opposite(device):
for value in device.values:
yield not value
led = LED(4)
btn = Button(17)
led.source = opposite(btn)
pause()
另外,也可以使用自定义生成器从人工来源提供数值:
例如,编写一个生成器函数,随机生成 0 或 1:
from gpiozero import LED
from random import randint
from signal import pause
def rand():
while True:
yield randint(0, 1)
led = LED(17)
led.source = rand()
pause()
如果迭代器是无限的(即无限生成器),则会一直处理元素,直到 source
被更改或设置为 None
为止。
如果迭代器是有限的(例如一个列表),则会在处理完所有元素后终止(将设备值保留在最后一个元素上):
from gpiozero import LED
from signal import pause
led = LED(17)
led.source_delay = 1
led.source = [1, 0, 1, 1, 1, 0, 0, 1, 0, 1]
pause()
源工具
GPIO Zero 提供了一组现成的函数,用于处理 源/值,称为源工具。从 gpiozero.tools
中导入即可使用。
其中一些源工具是无需输入的人造源:
在此示例中,0 和 1 之间的随机值被传递给 LED,使其产生闪烁的蜡烛效果:
请注意,在上述示例中,source_delay
用于使 LED 对随机值的迭代速度稍慢一些。source_delay
可以设置为较大的数字(例如,1 表示延迟一秒),也可以设置为 0 以禁用任何延迟。
有些工具会使 用单个源并处理其值:
在此示例中,只有在未按下按钮时 LED 才会点亮:
from gpiozero import Button, LED
from gpiozero.tools import negated
from signal import pause
led = LED(4)
btn = Button(17)
led.source = negated(btn)
pause()
请注意,接收一个或多个 value
参数的源工具支持传递 ValuesMixin
衍生工具或迭代器,包括设备的 values
属性。
有些工具会组合多个源的值:
在本例中,只有同时按下两个按钮,LED 才会点亮(就像一个 AND 门):
from gpiozero import Button, LED
from gpiozero.tools import all_values
from signal import pause
button_a = Button(2)
button_b = Button(3)
led = LED(17)
led.source = all_values(button_a, button_b)
pause()
同样,带有两个按钮的 any_values()
将模拟一个 OR 门。
虽然大多数设备的 value
范围在 0 和 1 之间,但也有一些设备的数值范围在 -1 和 1 之间(如 Motor
、Servo
和 TonalBuzzer
)。一些源工具会输出-1 和 1 之间的值,非常适合这些设备,例如通过 sin_values()
中的
from gpiozero import Motor, Servo, TonalBuzzer
from gpiozero.tools import sin_values
from signal import pause
motor = Motor(2, 3)
servo = Servo(4)
buzzer = TonalBuzzer(5)
motor.source = sin_values()
servo.source = motor
buzzer.source = motor
pause()
在此示例中,所有三个设备都跟随 正弦波 运行。电机值在一个周期内从 0(停止)上升到 1(全速前进),然后回落到 0,再上升到 -1 (全速后退)。同样,舵机从中间点向右移动,然后向左移动;蜂鸣器从中间音调开始,逐渐提高频率,达到最高音调,然后降至最低音调。请注意,设置 source_delay
会改变设备迭代数值的速度。或者,也可以使用 cos_values()
工具,从-1 开始,然后升至 1,以此类推。
内部设备
GPIO Zero 还提供了几个 内部设备,代表操作系统本身提供的设施。这些设备可用于对时间或网络上是否有服务器等信息做出反应。这些类包括一个 value
属性,可用于向设备 source
源输入值。例如,连接到 Energenie
插座的电灯可以由 TimeOfDay
对象控制,使其在上午 8 点到晚上 8 点之间开启:
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()
使用 DiskUsage
类和 LEDBarGraph
可以在条形图上显示 Pi 的磁盘使用百分比:
from gpiozero import DiskUsage, LEDBarGraph
from signal import pause
disk = DiskUsage()
graph = LEDBarGraph(2, 3, 4, 5, 6, 7, 8)
graph.source = disk
pause()