GPIO Zero库在传统的GPIO使用基础上还提供了很多的进阶功能,本文将对其中的一些内容进行摘录说明。
进阶功能 Source/Values模式GPIO Zero库提供了一种Source/Values的使用模式,有点类似于某些些上位机界面开发时用的
Binding,为的是降低代码的耦合度,减少程序员的工作量。
举个例子,如果你要通过Button来控制LED,当Button按下时点亮LED,按钮松开时熄灭LED。传统情况下你的代码大概是下面这个样子的:
from gpiozero import Button, LED
from signal import pause
led = LED(17)
button = Button(2)
button.when_pressed = lambda : led.on()
button.when_released = lambda : led.off()
pause()
通过GPIO Zero库的Source/Values模式,你的代码就可以是下面那样的了:
from gpiozero import Button, LED
from signal import pause
led = LED(17)
button = Button(2)
led.source = button # 关联button和led,当button活动时(被按下时)led活动(点亮)
pause()
可以看到用上Source/Values模式后大大简化了代码,不需要用代码检测数据源变化再做出响应,这一切都会在底层自动完成。这个例子中Button的状态是Values,实际使用中我们可以用各种东西当作Values,比如下面例子:
上图中通过CPU温度来调节LED亮度。
默认情况下CPUTemperature类将0 ~ 100摄氏度映射成0 ~ 1的值,实际使用时可以手动调整温度区间,比如使用 temp = CPUTemperature(min_temp=40, max_temp=90)
会将40 ~ 90摄氏度映射成0 ~ 1的值。
前面例子中数据都是来自库中类的对象,其实我们也可以用自己的可迭代数据作为Values:
from gpiozero import LED
from signal import pause
data = [1, 0, 1, 0, 1, 0, 1, 0, 1, 0]
led = LED(17)
led.source_delay = 1 # 设置数据驱动刷新速度为1秒一次(默认为0.01秒)
led.source = data
pause()
下面例子是使用迭代器作为Values:
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()
上面例子都是一个值来驱动一个对象,我们也可以用多个值来驱动多个对象:
from gpiozero import LED, Button
from gpiozero.tools import all_values, any_values
from signal import pause
led1 = LED(2)
led2 = LED(4)
btn1 = Button(20)
btn2 = Button(21)
led1.source = all_values(btn1, btn2) # 两个按钮都按下时点亮led1
led2.source = any_values(btn1, btn2) # 任意按钮都按下时点亮led2
pause()
更多内容可以参考:https://gpiozero.readthedocs.io/en/stable/source_values.html
Device Source Tools这一章节的内容是用来配合上一章节Source/Values使用的,上一章节说了Source/Values关系绑定前可以做各种处理,GPIO Zero库中提供了很多工具用来方便的做出这些处理。
GPIO Zero库中提供的工具蛮多,每一个都写了例程,可以参考下面连链接:
https://gpiozero.readthedocs.io/en/stable/api_tools.html
GPIO Zero库对于IO口的管理控制上有很多方便的功能,这章节就介绍下其中的 LEDBoard 和 ButtonBoard 两项功能。
在前面文章介绍LED、PWMLED、Button的时候都是单个的进行声明、控制与应答的,在GPIO Zero库中我们除了单个控制外还可以整组的控制,主要由下面两个类实现相关功能:
class gpiozero.LEDBoard(*pins, pwm=False, active_high=True, initial_value=False, pin_factory=None, **named_pins)
class gpiozero.ButtonBoard(*pins, pull_up=True, active_state=None, bounce_time=None, hold_time=1, hold_repeat=False, pin_factory=None, **named_pins)
观察上面的构造函数会发现它们和LED、PWMLED、Button的构造函数是很像的,如果你去查看类库可以发现不光是构造函数,其它的属性和方法等两者也是非常相似的,实际上两者的具体操作使用是差不多的。下面进行简单的演示:
from gpiozero import LEDBoard
from time import sleep
leds = LEDBoard(2, 3, 4, 17) # GPIO2 3 4 17上分别接了LED
def printandsleep():
print('{} {} {} {}'.format(leds[0].value, leds[1].value, leds[2].value, leds[3].value))
sleep(2)
leds.on() # 点亮所有LED
printandsleep()
leds.off() # 熄灭所有LED
printandsleep()
leds.on(0) # 点亮第一个LED(GPIO2),同leds[0].on()
printandsleep()
leds[-1].on() # 点亮最后一个LED(GPIO17),同leds.on(-1),这里也等同于leds.on(3)
printandsleep()
leds.on(1, 2) # 点亮第2、3个LED(GPIO3、GPIO4)
printandsleep()
for led in leds[2:]: # 选择第3、4个LED(GPIO4、GPIO17)
led.off()
printandsleep()
for led in leds[::2]: #从0开始步进为2选择LED,这里相当于第0、2个
led.toggle() # 翻转LED
printandsleep()
上面是基础的LED操作,下面再演示下PWMLED和Button的操作:
from gpiozero import LEDBoard, ButtonBoard
from time import sleep
from signal import pause
leds = LEDBoard(pwm=True, led0=2, led1=3) # GPIO2 3上分别接了LED, 相当于leds = LEDBoard(2, 3, pwm=true)
leds.led0.pulse() # 使led0以呼吸灯方式闪烁
leds.led1.value = 0.5 # 以50%占空比点亮led1
print('{} {}'.format(leds.led0.value, leds.led1.value))
sleep(3)
btns = ButtonBoard(17, 27) # GPIO17 27上分别接了Button
leds.source = btns.values # 该行将led0与第一个button绑定(GPIO17)、将led1与第二个button绑定(GPIO27)
pause()
上面代码中先接了两个LED,用PWM方式进行了控制,然后声明了两个Button,将LED和Button以上面的Source/Values方式进行绑定,分别按下按钮,LED分别会有响应。
这个章节可以说的内容其实挺多,但是其中很多东西都是基于具体的某个电路或成品的电路模块来设计的,这里就不进一步展开了,更多内容可以参考下面链接:
https://gpiozero.readthedocs.io/en/stable/recipes_advanced.html
https://gpiozero.readthedocs.io/en/stable/api_boards.html
GPIO Zero库中设计了对相关操作异常的反馈,可以使用 try...except...
语句进行捕获处理:
GPIO Zero库定义了哪些异常可以参考下面链接:
https://gpiozero.readthedocs.io/en/stable/api_exc.html
GPIO Zero库中提供了几个Internal Devices,用于获取树莓派的一些信息,下面分别列举进行简单说明:
TimeOfDay
class gpiozero.TimeOfDay(start_time, end_time, *, utc=True, pin_factory=None)
用来标示一天中某一时间段处于活动状态,start_time和end_time分别表示设备激活起始与结束时间,utc True表示使用UTC时间、False表示使用本地时间。
TimeOfDay对象有value属性,其值为True表示处于start_time和end_time时间之间。
PingServer
class gpiozero.PingServer(host, *, pin_factory=None)
ping host,如果能ping通则其value属性为True。
CPUTemperature
class gpiozero.CPUTemperature(sensor_file='/sys/class/thermal/thermal_zone0/temp', *, min_temp=0.0, max_temp=100.0, threshold=80.0, pin_factory=None)
获取CPU温度、对温度进行数值映射、设置报警阈值。
LoadAverage
class gpiozero.LoadAverage(load_average_file='/proc/loadavg', *, min_load_average=0.0, max_load_average=1.0, threshold=0.8, minutes=5, pin_factory=None)
设置将CPU平均负载映射为某一只区间,同时设置阈值,value值高于阈值时以活动表示。
DiskUsage
class gpiozero.DiskUsage(filesystem='/', *, threshold=90.0, pin_factory=None)
设置阈值,当磁盘空间使用率超过该值时以活动表示。
下面是简单的测试例子:
from gpiozero import TimeOfDay, PingServer, CPUTemperature, LoadAverage, DiskUsage
from datetime import time
am = TimeOfDay(time(10), time(11), utc=False)
pm = TimeOfDay(time(20), time(21), utc=False)
print('TimeOfDay 10~11h: {}'.format(am.value))
print('TimeOfDay 20~21h: {}'.format(pm.value))
google = PingServer('google.com')
baudu = PingServer('baidu.com')
print('Ping google: {}'.format(google.value))
print('Ping baudu: {}'.format(baudu.value))
temp = CPUTemperature()
print('CPU temperature: {}C'.format(temp.temperature))
print('CPU temperature value: {}'.format(temp.value))
la = LoadAverage()
print('LoadAverage {}'.format(la.is_active))
print('LoadAverage {}'.format(la.value))
disk = DiskUsage()
print('DiskUsage {}'.format(disk.is_active))
print('DiskUsage {}'.format(disk.value))
博客专家
原创文章 75获赞 254访问量 30万+
关注
私信
展开阅读全文
作者:Naisu_kun