Arduino + GP2D12红外测距传感器+LCD1602
GP2Y0A21YKIR Sensor是日本夏普公司推出的一款性价比高、最常用的红外测距传感器、其与GP2D12测量射程相同,但探测面积略有增加,可用来对物体的距离进行测量,实现轮式机器人的避障功能。它不但体积小、功耗低、价格便宜,而且测距效果好,适合广大机器人发烧友使用。赶快给你的机器人配备一双犀利的眼睛吧!
技术规格:
1.测量射程范围:10 - 80 cm
2.最大允许角度:>40°
3.电源电压:4.5 - 5.5V
4.平均功耗:33 - 40mA
5.峰值功耗:约200mA
6.更新频率/周期:25Hz/40ms
7.模拟输出噪声:<200mV
8.精度和采集的AD位数以及转化计算公式相关,10AD一般能达到0.1CM.
9.测量距离与输出模拟电压关系:2.4V~0.4V模拟信号对应10cm~80cm,输出与距离成反比非线性关系。
尺寸:29.5×13×13.5 mm
实验任务是:把GP2D12红外线测距传感器采集的数据,通过Arduino控制器的算式转换为实际距离值,再显示在集成了I2C接口的LCD1602液晶面板上。
上图就是GP2D12红外线测距传感器的电压值与距离值的关系曲线,从这个曲线可以看出,电压输出与距离成反比,而且是非线性关系。根据上图关系曲线,大约关系为10cm距离时有2.55V输出,80cm距离时有0.42V输出。可以通过该曲线拟合出电压值与距离值的数学关系式,但是这个关系式里的距离是参考距离值,实际距离值=(参考距离值-0.42)cm,另外由于Arduino的模拟量采样命令analogRead(),采样的数据范围是0至1023,对应的电压范围是0至5V,每格数据代表0.0049V,于是读取的有效数据应该由86(0.42V)至520(2.548V)。所以最终可以推导出实际距离与采样数据之间的关系式为:
实际距离=2547.8/((float)采样数据*0.49-10.41)-0.42
这个实际距离与采样数据之间的关系式,您会在下面程序中再次看到,我用红色字体标注出来了。
实验中,我们用到的I2C接口的LCD1602也是比较方便的。
用四根杜邦线,把1602LCD后面的I2C接口四个引脚与Xbee传感器扩展板V5的I2C专用端口连接起来,就可以实现Arduino控制器与LCD1602液晶的I2C硬件联系,如文章的第一张图所示。这个集成了I2C接口的1602LCD好用,不仅体现在硬件连线方便,而且您使用专门为这个LCD液晶写的库文件LiquidCrystal_I2C,编写程序也特别简单。
本模块与Arduino连接是这样子的:
把GP2D12传感器连接到Arduino传感器扩展板的模拟量端口0、LCD1602的I2C引脚连接到传感器扩展板的I2C专用端口,又安装好和LiquidCrystal_I2库文件,那就可以编写GP2D12传感器距离值采集和LCD1602液晶显示的程序了。
实验所需要的代码是这样:
[mw_shl_code=c,true]// 声明集成了I2C接口的LCD1602编程所需库文件
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
//设置LCD1602的I2C地址为0x27,LCD1602为两行,每行16个字符的液晶显示器
LiquidCrystal_I2C lcd(0x27,16,2);
int GP2D12 = 0;//把夏普GP2D12红外测距传感器连接在模拟量端口0
int val; //存储从GP2D12红外测距传感器读到的值
float temp;//存储由传感器读取值,通过计算处理后的浮点型距离值
int distance;//存储由传感器读取值,通过计算处理后的整数型距离值
//初始化程序
void setup() {
//LCD的I2C通讯初始化需要执行两次
lcd.init(); // 给LCD的I2C通讯初始化
delay(20);
lcd.init(); // 给LCD的I2C通讯初始化
delay(20);
lcd.backlight();//点亮LCD背光灯
}
//主程序
void loop() {
//读取GP2D12红外测距传感器模拟量数据
val = analogRead(GP2D12);
//通过以下算式,把传感器读取值处理成浮点型距离值
temp=2547.8/((float)val*0.49-10.41)-0.42;
lcd.clear();//LCD清屏
// 定位光标在LCD第0行、第0列
lcd.setCursor(0, 0);
//在LCD第0行第0列开始显示"Distance:"
lcd.print("Distance:");
// 定位光标在LCD第2行、第8列
lcd.setCursor(7, 1);
//如果传感器读取值大于80或者小于10,
if(temp>80||temp<10)
{
//则在LCD第1行、第7列开始显示"OverRange"
lcd.print("OverRange");
}
//如果传感器读取值在10到80之间,
else
{
//把浮点型距离值取整
distance=int(temp);
//则在LCD第2行、第8列开始显示距离值
lcd.print(distance);
//在距离值后显示单位"cm"
lcd.print("cm");
}
delay(500);//延时500ms
}
[/mw_shl_code]
下面介绍一下三角法红外测距原理:
Sharp的红外传感器都是基于一个原理,三角测量原理。红外发射器按照一定的角度发射红外光束,当遇到物体以后,光束会反射回来,如图1所示。反射回来的红外光线被CCD检测器检测到以后,会获得一个偏移值L,利用三角关系,在知道了发射角度a,偏移距L,中心矩X,以及滤镜的焦距f以后,传感器到物体的距离D就可以通过几何关系计算出来了。
可以看到,当D的距离足够近的时候,L值会相当大,超过CCD的探测范围,这时,虽然物体很近,但是传感器反而看不到了。当物体距离D很大时,L值就会很小。这时CCD检测器能否分辨得出这个很小的L值成为关键,也就是说CCD的分辨率决定能不能获得足够精确的L值。要检测越是远的物体,CCD的分辨率要求就越高。
非线性输出:
Sharp GS2XX系列的传感器的输出是非线性的。没个型号的输出曲线都不同。所以,在实际使用前,最好能对所使用的传感器进行一下校正。对每个型号的传感器创建一张曲线图,以便在实际使用中获得真实有效的测量数据。下图是典型的Sharp GP2D12的输出曲线图。
从上图中,可以看到,当被探测物体的距离小于10cm的时候,输出电压急剧下降,也就是说从电压读数来看,物体的距离应该是越来越远了。但是实际上并不是这样的,想象一下,你的机器人本来正在慢慢的靠近障碍物,突然发现障碍物消失了,一般来说,你的控制程序会让你的机器人以全速移动,结果就是,"砰"的一声。当然了,解决这个方法也不是没有,这里有个小技巧。只需要改变一下传感器的安装位置,使它到机器人的外围的距离大于最小探测距离就可以了。如图3所示:
代码二是直接通过串口监视窗口来看所测得的距离:
[mw_shl_code=c,true]char GP2D12;
char a,b;
void setup()
{
Serial.begin(9600); //
}
void loop()
{
int val;
GP2D12=read_gp2d12_range(0);
a=GP2D12/10;
b=GP2D12%10;
val=a*10+b;
if(val>10&&val<80)
{
Serial.print(a,DEC);//
Serial.print(b,DEC);//
Serial.println("cm");//
}
else Serial.println("over");//
delay(50);
}
float read_gp2d12_range(byte pin)
{
int tmp;
tmp = analogRead(pin);
if (tmp < 3)return -1;
return (6787.0 /((float)tmp - 3.0)) - 4.0;
}
[/mw_shl_code]
GP2D12使用性能个人点评:优点:
1. 红外传感器连接使用简单,对于1米以内的中距离测试精度良好、性能优越。
2. 数据测量值稳定,测量结果波动较小。
3. 数据传输稳定,程序读取简单不会在数据传输过程中出现卡死的现象,错误信号较少。
GP2D12使用注意及使用优化方式:
1. 当多个GP2D12同时连接Arduino板使用时,由于供电量的增加,可能造成电压不稳定而对测量结果产生偏差。从硬件角度可以通过在VCC与 GND之间接电容的方式来稳定对GP2D12的供电,减少供电电压波动对测量结果的影响,或者在GND与数据线之间接一个电容减小输出电压的波动略去可能出现的误差信号,提高数据稳定性。(接线见附录图)
2. 针对测量时可能产生的干扰和误差数值,可能从软件的角度进行改进和防止,通过多次的测量记录,排除一场输入量后,取均值来的到一个较为稳定更为接近实际值的测量数据。其次可以根据实际的使用要求,可以进行有效值的范围定义,过滤超出范围的测量结果,该范围可根据使用情况自行界定。
3. 针对红外传感器测量时,可能受环境光影响测量结果,在安放使用时竟可能避免传感器正对灯光的使用,可以将 GP2D12的发射接收端水平放置进行测量,尽可能减少环境光带来的干扰。
总体来说GP2D12在对测量精度要求不高,测量范围在1m以内的情况下,对物体距离值的定位是非常简单有效地、操作简便、实用性强。