倒车雷达的核心原理是距离检测,距离检测目前常用的有两种方案,一种是通过激光进行检测,原理上可分为TOF,也就是记录发射激光和收到激光之间的时间间隔;第二是三角测距法,利用固定的激光发射角度,看反射回来激光的落点落在CCD传感器的位置来进行测距。无论基于哪种原理,激光测距技术共同的优点都是精度比较高,对被测物体尺寸,形状要求小。但缺点也很明显,激光测距视场非常窄,只能测一条线上的障碍物,如果障碍物并不在激光头的正前方,则无法测量。
另一种方案是超声波测距方案,也就是我们熟知的声纳。原理上和上面提到的TOF一致,都是测量发射信号和接收到反射信号之间的时间,以此来计算速度。但超声波由于频率较低,速度较慢,在不同介质中传播速度不一致,同时衍射现象较为明显。这些特性导致超声波测距的精度并不高,但优势是视场较宽,可以检测更大的范围。
从上面的介绍可以看出,两种方案的优缺点正好可以相互互补,因此我会结合两种方案,在实际中验证上述差异,并结合他们的优点,制作一个高精度雷达。
首先先说说激光雷达的使用方法。项目中我使用的激光雷达是VL53L0X。
我们先要在python中安装必要的驱动库:
pip3 install adafruit-circuitpython-vl53l0x
安装完成后,将VL53L0X连接到核桃派的I2C1接口上,接线方式如下:
SCL: PI7
SDA: PI8
VCC: 3.3V
GND: GND
完成连线后,新建一个python文件,写入以下代码:
import board
import time
import busio
import adafruit_vl53l0x
i2c = busio.I2C(board.SCL1, board.SDA1)
sensor = adafruit_vl53l0x.VL53L0X(i2c)
lazer_val = sensor.range
print("Lazer: {0} mm".format(lazer_val))
然后使用python
来运行它,如果一切顺利,应该就可以看到一下输出
下面我们再试一下超声波传感器。市面上常见的超声波传感器有SR-04和US-100两种。其中US-100支持串口输出,温度测量,精度范围也更好,但实际体验下来差别不大。因此这里我们使用最经典的TRIG-ECHO触发方式来进行通讯。
首先安装库文件:
pip3 install adafruit-circuitpython-hcsr04 adafruit-circuitpython-us100
接下来是接线:
TRIG: PI6
ECHO: PI5
VCC: 3.3V
GND: GND
接着在我们刚才创建的文件中加入以下内容:
import adafruit_hcsr04
sonar = adafruit_hcsr04.HCSR04(trigger_pin=board.PI6, echo_pin=board.PI5)
sonar_val = int(sonar.distance*10)
print("Sonar: {0} mm".format(sonar_val))
由于这次涉及到了GPIO的硬件使用,因此我们需要用sudo python
来运行它,如果一切顺利,应该就可以看到一下输出:
接着我们测试一下雷达特性:
可以看到在距离较短时,激光雷达所得测量值更精准,也更小。在此时参考激光雷达的读数会更为保守。
而当障碍物不在雷达正前方时,我们可以看到声纳依旧可以检测到物体,但激光雷达检测不到,显示的距离远大于声纳读数。
因此我们可以结合上面两个结果,只要其中任意读数低于100,就响起警报。警报使用的是GPIO控制有源蜂鸣器实现。这里需要注意的是,蜂鸣器不可直接用GPIO驱动,如果直接驱动,不但功率低声音小,还有一定损坏GPIO的风险。我们要使用三极管或mos管来驱动蜂鸣器。
接线方式如下:
5V: 5V
signal: PC8
GND: GND
完整代码如下:
import board
import time
import busio
import adafruit_vl53l0x
i2c = busio.I2C(board.SCL1, board.SDA1)
print(i2c.scan())
sensor = adafruit_vl53l0x.VL53L0X(i2c)
import adafruit_hcsr04
sonar = adafruit_hcsr04.HCSR04(trigger_pin=board.PI6, echo_pin=board.PI5)
from digitalio import DigitalInOut, Direction, Pull
buz = DigitalInOut(board.PC8)
buz.direction = Direction.OUTPUT
while True:
try:
time.sleep(0.5)
lazer_val = sensor.range
sonar_val = int(sonar.distance*10)
print("Lazer: {0} mm".format(lazer_val))
print("Sonar: {0} mm".format(sonar_val))
if lazer_val < 100 or sonar_val < 100:
buz.value = 1
else:
buz.value = 0
except:
print("Retrying!")
time.sleep(0.5)