课程导入
自动门,当你走到门前的时候会自动打开,想想是不是很方便呢?这节课,我们就来实现它。回顾前面的课程中,似乎没有电子模块可以用来检测人体接近,也没有可以模拟门打开的电子模块,虽说电机可以转动,但转速过快并且难以控制,不能用作开门和关门,到底该用哪些电子模块来实现自动门的项目效果呢?
知识锦囊
人体红外运动传感器
人体红外运动传感器用于检测是否有人或动物在其检测范围内运动,它是一种被动式红外传感器,当传感器闲置时,位于传感器检测范围内的物体,如房间、墙和桌子等,发射的红外线强度几乎恒定;而当有人或动物经过时,传感器检测到的红外线强度就会发生一定的变化,根据这些变化,就可以判定是否有人或动物经过。常用于安防警报,运动探测,智能开关或机器人领域等。注意,传感器检测距离最长为 3m 至 5m,我们建议的最佳检测距离为 2m 左右。
舵机
自动门的制作除了用到人体红外运动传感器之外,还要用到舵机。舵机是具有齿轮和反馈系统的直流电机,我们可以对舵机进行精确的位置控制,舵机又叫伺服电机,常用在需要角度变化并可以保持的控制系统,如机器人设备。在自动门项目中,我们通过迷你红外运动传感器来感知是否有人靠近,从而给舵机发出信号控制其转动,带动门板到固定位置,当人离开时,舵机控制门关闭。
实践操作
当我们需要控制舵机转动时,需要通过 PWM 信号来控制舵机的输出量,PWM 脉冲的占空比直接决定了舵机输出轴的转动位置,下图展示了频率为 50Hz 时,不同脉冲信号和舵机转动的角度的关系。
然而不同型号的舵机工作脉冲会有些许差异,我们手中的舵机我们使用频率为100HZ,对应脉冲宽度、转动角度及 duty_u16 数值之间的关系:
脉冲宽度(ms) | 转动角度(°) | duty_u16 |
---|---|---|
0.61 | 0° | 4000 |
1.1 | 45° | 7250 |
1.6 | 90° | 10500 |
2.6 | 180° | 17000 |
项目一:舵机控制
硬件连接
在该项目中,我们所需要使用的硬件有:
- 树莓派 Pico
- 树莓派 Pico 拓展板
- Grove - 舵机
使用 Grove 数据线将舵机连接到拓展板D20接口,对照上表我们尝试让舵机在45°和90°之间来回转动。
编写程序
首先引入需要用到的库,对舵机引脚进行定义。
from machine import Pin,PWM
from utime import sleep
pwm_servo = PWM(Pin(20))
pwm_servo.freq(100)
接下来通过 for 循环,将舵机从0°到180°转动循环10次,完整程序如下:
from machine import Pin,PWM
from utime import sleep
pwm_servo = PWM(Pin(20))
pwm_servo.freq(100)
for i in range(10):
pwm_servo.duty_u16(7250)
sleep(1)
pwm_servo.duty_u16(10500)
sleep(1)
运行程序可以发现,舵机会在0°到180°之间来回转动,循环十次,达到了我们想实现的效果。当我们想要控制舵机转动到其他角度,再去计算相对应的数值,如果我们想在其他的项目中结合舵机一起使用,也需要重新定义函数和相对应的数值,似乎并不方便。为此,我们就需要函数库了。简单来讲,库文件就是一个包含所有你定义的函数和变量的文件,库文件可以被其他的程序引入,以使用该库文件中的函数等功能。在前面的课程中,我们使用过很多 MicroPython 自带的标准库比如 machine,utime,还有使用者自主开发的第三方库,比如 lcd1602, dht11 等。本节课,我们将学习如何给舵机写一个简单的库文件,定义它的引脚以及转动的角度。
- 定义类
简单来说,类是用来描述具有相同属性和方法的对象集合,它定义了该集合中所有对象所共有的属性和方法 Python 中定义类要使用 class 来实现,类名后面以冒号结束。例如我们在前面课程中引入过 MicroPython 标准库machine 库中的 Pin 类,该类中就包含了所有关于 Pin 的函数。如下所示,我们定义了一个舵机的类。
class SERVO:
- 构造函数
接下来我们通过 def init() 为舵机的类添加构造函数,可以包含多个参数,当我们需要在函数中引用一个变量的时候,就需要通过函数体本身传入该参数的值,那么我们就需要先在函数体中设置这个参数。例如下方我们构造的函数,其作用是将某一引脚设置为输出 PWM 信号的引脚,那我们在函数体中需要引入的参数即为引脚号。除了 pi n以外,我们还引入了一个名为 self 的参数, self 代表类的实例,而非类,这也是类的函数和普通函数的区别。
def __init__(self,pin):
self.pin = pin
self.pwm = PWM(self.pin)
接下来,我们定义了 turn 函数用以计算舵机的转动角度val ,在该函数中,我们通过 freq() 给舵机输出 PWM 信号,并通过 duty_u16() 函数给舵机输出模拟值来控制舵机转动。需要注意的是,该模拟值是由公式:val/180*13000+4000 计算得出,我们需要通过 int() 函数把公式计算出的字符串或数字转换为整型。
def turn(self, val):
self.pwm.freq(100)
self.pwm.duty_u16(int(val/180*13000+4000))
完整库文件如下:
from machine import Pin, PWM #调用machine库
#下面定义了一个伺服对象
class SERVO:
#对创建的类添加构造方法:
def __init__(self, pin):
#下面定义pin和pwm两个实例变量
self.pin = pin
self.pwm = PWM(self.pin)
#下面定义了一个turn的实例方法,用以计算舵机的转动角度:
def turn(self, val):
self.pwm.freq(100)
self.pwm.duty_u16(int(val/180*13000+4000))
写好库文件后,我们将它命名为 servo.py 存储在 Pico 中,接下来就可以直接调用库中的函数了。修改项目一的程序如下,我们可以直接写入想要舵机转动的角度,运行该程序,看看效果吧。
from machine import Pin
from utime import sleep
from servo import SERVO
servo = SERVO(Pin(20))
for i in range(10):
servo.turn(20)
sleep(1)
servo.turn(160)
sleep(1)
项目二:用人体红外运动传感器控制舵机转动
接下来,我们用人体红外运动传感器控制舵机转动,实现自动门的效果。
硬件连接
在该项目中,我们所需要使用的硬件有:
- 树莓派 Pico
- 树莓派 Pico 拓展板
- Grove - 舵机
- Grove - 人体红外运动传感器
将人体红外运动传感器接入 D18 接口,将舵机接入 D20 接口。
编写程序
首先引入需要用到的库,并对舵机和人体红外运动传感器进行引脚定义,这里我们引用了刚才新建的舵机库。
from machine import Pin
from utime import sleep
from servo import SERVO
servo = SERVO(Pin(20))
miniPir = Pin(18, Pin.IN)
因为人体红外运动传感器只有两种状态,被触发和没有被触发,因此我们只需要判断它返回的值是否是1,并在交互区打印 “Motion Detected” 表示传感器被触发,这时舵机转动到160°表示门打开了,等待10秒,们自动关闭。完整程序如下:
from machine import Pin
from utime import sleep
from servo import SERVO
servo = SERVO(Pin(20))
miniPir = Pin(18, Pin.IN)
while True:
if miniPir.value()== 1:
print('Motion Detected')
servo.turn(160)
sleep(10)
servo.turn(20)
运行该程序,将其保存在电脑任意位置,用手在人体红外运动传感器附近挥动,观察舵机转动的效果。
用人体红外运动传感器控制舵机转动.mp4
思维拓展
项目一和项目二中,我们通过给舵机引脚写入模拟值控制舵机直接转动到想要的角度,你能尝试编写程序使舵机从0°开始,一点一点逐渐转动到180°吗?
from machine import Pin
from servo import SERVO
from time import sleep
servo = SERVO(Pin(20))
a = 180
while True:
a = a == 0 and 180 or a - 1
servo.turn(a)
sleep(0.1)