超声波测距模块(树莓派)
首先来看一下这个测距模块长什么样子:
就是HC-SR04模块。
这个模块有四个引脚,分别是Vcc(高电平),GND(低电平),Trig(触发测距)以及Echo(返回测距结果)。
那么这个模块怎么使用呢,资料上的说明是这样的:
首先给出时序图:
- 在Vcc和GND的电平都正确的时候,如果想要让模块开始测距,需要给Trig脚一个不小于10us的高电平脉冲。
- 发出这个脉冲之后,模块会自动将Echo脚设置为高电平,并且模块会在这个时候发出超声波脉冲(图上说明是8个连续的脉冲,这个脉冲数字我们不用管,反正就是发出了脉冲)。
- 当超声波遇到障碍物反弹回来之后,会被模块接受到。接收到之后Echo脚会自动变成低电平,从而完成一次测距。
从上面的步骤可以看出,我们只需要测量Echo脚为高电平的时间,然后乘上声速/2就可以了(除2是因为超声波来回了一趟,路程为距离的两倍)
我们是在空气中测速的,声波为340m/s。
根据上面的过程,可以写出代码如下:
1 import RPi.GPIO as GPIO 2 import time 3 4 Vcc_Pin=33 5 Echo_Pin=37 6 Trig_Pin=35 7 8 def initDist(): 9 GPIO.setup(Vcc_Pin,GPIO.OUT,initial=GPIO.HIGH) 10 GPIO.setup(Trig_Pin,GPIO.OUT,initial=GPIO.LOW) 11 GPIO.setup(Echo_Pin,GPIO.IN) 12 13 def _getDist(): 14 time.sleep(0.1) 15 GPIO.output(Trig_Pin,GPIO.HIGH) 16 time.sleep(0.00002) #这里延时了20us,只要大于10us即可 17 GPIO.output(Trig_Pin,GPIO.LOW) 18 while GPIO.input(Echo_Pin)==GPIO.LOW: #等待Echo脚为高电平 19 pass 20 #print("echo gpio is high") 21 t=time.time() #开始计数 22 while GPIO.input(Echo_Pin)==GPIO.HIGH: #等待Echo脚为低电平 23 pass 24 #print("echo gpio is low") 25 t=time.time()-t #计数停止 26 #print(t,"s passed") 27 if t<=0: 28 print("Can't get distance") 29 return -1 30 return t*340/2 #返回距离(m为单位) 31 32 def getDist(): 33 dist=[] 34 print("measuring") 35 for i in range(0,5): 36 temp=_getDist() 37 if not temp==-1: 38 dist.append(temp) 39 sum=0 40 for i in dist: 41 sum+=i 42 return sum/len(dist) 43 44 if __name__=='__main__': 45 GPIO.setmode(GPIO.BOARD) 46 initDist() 47 str="you can input q to quit,or press other key to get a distance" 48 r=input(str) 49 try: 50 while not r =='q': 51 print(getDist()*100,"cm") 52 time.sleep(1) #延时1s 53 r=input(str) 54 except KeyboardInterrupt: 55 pass 56 GPIO.cleanup()
8~11行的initDist()函数初始化模块的引脚
13~30行_getDist()函数进行一次测距(其实这里已经获得了一次测量的距离了,但是为了防止数据偏差较大,后面还使用了getDist()函数取了平均值)
32~42行进行4次测距,并取平均值
44~56行main入口,当用户输入不为q的时候测距。测出的结果转化为cm。
这里14和52行的延时是为了模块能够反映过来。因为我在测试的时候发现不延时的话程序容易卡住。
具体的结果在这里: