摘要:本文介绍使用红外测距模块GP2Y0E03实现避障小车
在前边已经介绍了两种非接触测距的办法,分别是超声波测距和激光测距,在这里,再介绍另一种常用的测距传感器——红外测距传感器。红外测距的工作原理是,利用红外信号与障碍物距离的不同反射强度也不同的原理,进行障碍物远近的检测。红外测距传感器具有一对红外信号发射与接收二极管,发射管发射特定频率的红外信号,接收管接收这种频率的红外信号,当红外的检测方向遇到障碍物时,红外信号反射回来被接收管接收,经过处理之后,通过数字传感器接口返回到检测设备,检测设备即可利用红外的返回信号来识别周围环境的变化。
本次使用的红外测距模块依然是使用的IIC总线通信协议,这个模块的测量范围是4~50厘米,用在避障小车上应该是足够了,但需要注意的是,当与被测物体距离小于4厘米时,红外模块可能会返回一个不正确的结果,因此在设计和使用这个红外测距模块的时候,要避免与被测物体的距离小于4厘米。另外需要注意的是,红外测距的一个缺点就是可能会受环境中的其他红外线的干扰,不适合阳光直射的地方,不过在室内使用的话问题不大。
下图就是这次使用的红外测距模块。
红外测距模块GP2Y0E03的特征如下:
- 内置信号处理电路的红外LED和CMOS图像传感器
- 测距范围:4到50厘米
- 低电压运行:最小2.7V
- 紧凑尺寸(16.7×11.0×5.2mm)
- 高精度测量
- 数字(IIC)/模拟输出类型
其引脚定义如下:
序号 | 标识 | 用途 |
1 | VDD | 电源正极。2.7V~5.5V |
2 | Vout(A) | 模拟电压输出 |
3 | GND | 电源负极。 |
4 | VIN(IO) | IO口供电电压 |
5 | GPIO1 | 片选信号输入端 |
6 | SCL | IIC时钟线 |
7 | SDA | IIC数据线 |
这个红外测距模块比之前的PCF8574模块要复杂一些,因此在使用IIC协议驱动红外测距仪进行测距操作时,也要复杂一些了。在GP2Y0E03内部有一系列的寄存器,这些寄存器用来保存着与外部设备相交互的数据,当外部设备需要读写某个寄存器的数据时,需要先发送该寄存器的地址,然后再接收或者发送数据。
在使用GP2Y0E03红外测距模块进行测量的时候,主要涉及到了以下几个寄存器。
地址 | 名称 | 寄存器有效位 | 缺省值 | 含义 |
0x35 | 移位数量 | [2:0] | 0x02 | 1:返回结果最大值128cm 2:返回结果最大值64cm |
0x5E | 测量距离[11:4] | [7:0] | 测量结果高位 | |
0x5F | 测量距离[3:0] | [3:0] | 测量结果低位 |
最后的测量距离为:(测量结果高位*16+测量结果低位)/16/2^n
其中n为移位数量。
在这里只是列举了与读取测量结果相关的几个寄存器,如果相看更多的寄存器,请参考官方的datasheet文档。
接下来就把这个红外测距模块与ESP32开发板连接到一起,具体的连接方法如下:
序号 | GP2Y0E03模块 | ESP32开发板模块 |
1 | VDD | +3.3V |
2 | Vout(A) | 空 |
3 | GND | GND |
4 | VIN(IO) | +3.3V |
5 | GPIO1 | +3.3V |
6 | SCL | P22 |
7 | SDA | P21 |
下面就打开“Arduino IDE”软件,看一下读取红外测距模块测量数据的详细程序。如下所示:
#include <Wire.h> int distance = 0; // 保存测量结果 byte high, low = 0; // 测量结果的高位和低位 int shift = 0; // 移位数量 #define ADDRESS 0x40 // 测距模块IIC地址 #define DISTANCE_REG 0x5E #define SHIFT 0x35 void setup() { // 初始化 Wire.begin(); Serial.begin(115200);
delay(50);
// 读取移位寄存器的数值 Wire.beginTransmission(ADDRESS); Wire.write(SHIFT); Wire.endTransmission();
Wire.requestFrom(ADDRESS, 1); while(Wire.available() == 0); shift = Wire.read(); } void loop() { // 请求2个字节的测量结果 Wire.beginTransmission(ADDRESS); Wire.write(DISTANCE_REG); Wire.endTransmission();
Wire.requestFrom(ADDRESS, 2);
while(Wire.available() < 2);
high = Wire.read(); low = Wire.read();
distance = (high * 16 + low)/16/(int)pow(2,shift); // 计算结果,单位厘米
Serial.print("距离是:"); Serial.print(distance); Serial.println("厘米");
delay(50); } |
在上面的程序中,每次读取GP02Y0E03红外测距模块寄存器内的数据之前,都要先发送多要读取的寄存器的地址,然后再请求相应的数据。
编译、上传程序,运行的结果如下:
好了,关于红外测距模块就介绍到这里了,你是不是可以把读取数据的代码封装到一个函数中,然后替换之前小车的测距函数,然后用红外测距模块实现自动避障功能了呢?