树莓派入门:Python使用HC-SR04超声波测距模块实现测距并用LED小灯泡实现报警
初学树莓派,一般都都是从LED小灯泡和HC-SR04超声波测距模块起步。这里将两个模块结合到一起,从而实现测距并在距离障碍物太近时闪亮LED灯进行提示。
由于树莓派是基于linux系统的多任务操作系统,故会因系统进程的切换而导致测量结果不准确。若需要准确结果,可以采用单片机。
一、基本原理
这里我们主要介绍GPIO操作以及HC-SR04的原理。
1、树莓派基本的GPIO操作
GPIO(英语:General-purpose input/output),通用型之输入输出的简称,树莓派中的GPIO模块可以很方便的实现GPIO。
GPIO的基本操作大致可分为输入(input)、输出(output)和脉宽调制(pwm),下面简单介绍一下GPIO操作。
导入GPIO
import RPi.GPIO as GPIO
指定针脚编号方式
GPIO.setmode(GPIO.BOARD)
或者
GPIO.setmode(GPIO.BCM)
关闭警告
GPIO.setwarnings(False)
设置接口的输入输出
GPIO.setup(channel1,GPIO.OUT)
GPIO.setup(channel2,GPIO.IN)
GPIO.setup(channel3, GPIO.OUT, initial=GPIO.HIGH)
GPIO.output(channel1,state) # GPIO.HIGH\GPIO.LOW (True\False)
GPIO.input(channel2)
GPIO.input(channel3)
清理针脚占用
GPIO.cleanup()
PWM调制
# 创建一个 PWM 实例,需要两个参数
# 第一个是GPIO端口号,这里我们用26号
# 第二个是频率(Hz),频率越高LED看上去越不会闪烁,相应对CPU要求就越高,设置合适的值就可以
pwm = GPIO.PWM(RED_LED,60)
#启用PWM,参数是占空比,范围:0.0<=占空比<=100.0
pwm.start(0)
#更改占空比
pwm.ChangeDutyCycle(i)
#停止PWM
pwm.stop()
2、树莓派40Pin引脚对照表
3、HC-SR04超声波测距模块
HC-SR04 模块可以测量 3cm – 4m 的距离,精确度可以达到 3mm。这个模块包括 超声波发射器、超声波接收器和控制电路三部分,有 4 个引脚。
测距原理
HC-SR04 的测距过程
- 树莓派向 Trig 脚发送一个持续 10us 的脉冲信号。
- HC-SR04 接收到树莓派发送的脉冲信号,开始发送超声波 (start sending ultrasoun),并把 Echo置为高电平, 然后准备接收返回的超声波。
- 当 HC-SR04 接收到返回的超声波 (receive returned ultrasound) 时,把 Echo 置为低电平。
二、准备工作
准备工作分为两部分,即材料的准备和组件的连接
1、材料准备
- 树莓派3b+(3b、4等都可以)
- 面包板
- 杜邦线(母对母、公对母)
- HC-SR04超声波测距模块
- LED小灯泡
- 电阻(可选)
2、组件连接
准备好材料后,即可开始连接组件了。然而对很多初学者来说,搞不懂树莓派中的引脚作用和编号是很正常的。不用着急,按照上面的40Pin引脚图中的编号来连接就可以了。
HC-SR04接口
HC-SR04的4 个引脚由 2 个电源引脚(Vcc 、GND)和 2 个控制引脚(Trig、Echo)组成。
Vcc 和 Gnd 接 5v DC 电源,但不推荐用独立电源给它供电,应使用树莓派或单片机的 GPIO 口输出 5v 和 Gnd 给它供电。不然会影响这个模块的运行。
Trig 引脚用来接收来自树莓派的控制信号。接任意 GPIO 口。
Echo 引脚用来发送测距结果给树莓派。接任意 GPIO 口。
(注意 Echo 返回的是 5v信号,而树莓派的 GPIO 接收超过 3.3v 的信号可能会被烧毁,因此最好加一个分压电路!虽然我这里没有添加,也没烧坏>OvO<)
接线
通过比对40Pin引脚对照表,结合代码中用到的编号和功能连接零件即可,完成效果如图。
三、编写代码
#适用于树莓派3b+和HC-SR04
import RPi.GPIO as GPIO
import time
TRIG = 4
ECHO = 17
RED_LED = 26
pwm = None
INTERVAL = 5
def distanceInit():
print('Distance Measurement In Progress')
GPIO.setmode(GPIO.BCM)
GPIO.setup(TRIG,GPIO.OUT)
GPIO.setup(ECHO,GPIO.IN)
def distanceStart():
#发送trig信号,持续10us的方波脉冲
GPIO.output(TRIG,True)
time.sleep(0.00001)
GPIO.output(TRIG,False)
#等待低电平结束,然后记录时间
while GPIO.input(ECHO) == 0:
pass
pulse_start = time.time()
#等待高电平结束,然后记录时间
while GPIO.input(ECHO) == 1:
pass
pulse_end = time.time()
#距离(单位:m) = (pulse_end – pulse_start) * 声波速度 / 2
#声波速度取 343m/s
#
#距离(单位:cm) = (pulse_end – pulse_start) * 声波速度 / 2 * 100
#即 (pulse_end – pulse_start) * 17150
pulse_duration = pulse_end - pulse_start
distance = pulse_duration * 17150
distance = round(distance,2)
# print("Distance:{}cm".format(distance))
return distance
def ledStart():
global pwm
GPIO.setup(RED_LED, GPIO.OUT)
# 创建一个 PWM 实例,需要两个参数,第一个是GPIO端口号,这里我们用26号
# 第二个是频率(Hz),频率越高LED看上去越不会闪烁,相应对CPU要求就越高,设置合适的值就可以
pwm = GPIO.PWM(RED_LED,60)
#启用PWM,参数是占空比,范围:0.0<=占空比<=100.0
pwm.start(0)
for i in range(3):
#电流从小到大,LED由暗到亮
for i in range(101):
#更改占空比
pwm.ChangeDutyCycle(i)
time.sleep(0.02)
#电流从大到小,LED由亮变暗
for i in range(100,-1,-1):
pwm.ChangeDutyCycle(i)
time.sleep(0.02)
pwm.stop()
try:
distanceInit()
while True:
distance = distanceStart()
print("Distance:{}cm".format(distance))
if distance < 100:
ledStart()
time.sleep(INTERVAL)
except KeyboardInterrupt:
if pwm != None:
pwm.stop()
GPIO.cleanup()
四、运行
运行程序后,命令行会不断显示当前的距离。当距离的值小于100cm的时候,LED灯将会闪3次。