本文介绍使用红外测距模块GP2Y0E03实现避障小车
在前边已经介绍了两种非接触测距的办法,分别是超声波测距和激光测距,在这里,再介绍另一种常用的测距传感器——红外测距传感器。红外测距的工作原理是,利用红外信号与障碍物距离的不同反射强度也不同的原理,进行障碍物远近的检测。红外测距传感器具有一对红外信号发射与接收二极管,发射管发射特定频率的红外信号,接收管接收这种频率的红外信号,当红外的检测方向遇到障碍物时,红外信号反射回来被接收管接收,经过处理之后,通过数字传感器接口返回到检测设备,检测设备即可利用红外的返回信号来识别周围环境的变化。
本次使用的红外测距模块依然是使用的IIC总线通信协议,这个模块的测量范围是4~50厘米,用在避障小车上应该是足够了,但需要注意的是,当与被测物体距离小于4厘米时,红外模块可能会返回一个不正确的结果,因此在设计和使用这个红外测距模块的时候,要避免与被测物体的距离小于4厘米。另外需要注意的是,红外测距的一个缺点就是可能会受环境中的其他红外线的干扰,不适合阳光直射的地方,不过在室内使用的话问题不大。
下图就是这次使用的红外测距模块。

红外测距模块GP2Y0E03的特征如下:
其引脚定义如下:

| 序号 | 标识 | 用途 |
| 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:返回结果最大值128cm2:返回结果最大值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红外测距模块寄存器内的数据之前,都要先发送多要读取的寄存器的地址,然后再请求相应的数据。
编译、上传程序,运行的结果如下:

好了,关于红外测距模块就介绍到这里了,你是不是可以把读取数据的代码封装到一个函数中,然后替换之前小车的测距函数,然后用红外测距模块实现自动避障功能了呢?

