红外循迹传感器PID循迹算法

红外循迹传感器PID循迹算法

前一段时间参加了一个小车循迹竞速的比赛,获得了一个还行的成绩,所以在这里想把里面的核心部分PID寻线算法给大家分享一下。

关于做好的实物视频我上传到了B站,大家可以点击查看:小车双向PID循迹视频
两轮差速PID红外循迹视频
红外循迹模块的视频演示:红外循迹模块使用演示视频

大家如果要购买产品的话可以点击我的淘宝链接:小车驱动板链接

红外循迹模块链接:三路PID红外循迹模块实物链接

红外循迹模块百度云资料链接:三路PID红外循迹模块资料链接 提取码:bh0w

循迹小车程序下载链接:开源程序下载链接

复制这段内容后打开百度网盘手机App,操作更方便哦
(本程序在小车前后安装了两个红外循迹模块具有双向循迹功能,会根据到终点的距离来调节小车速度,可以进行三级调速。本程序获得过软银杯机器人竞速组的冠军,也是个小比赛,作者水平有限,只是想跟大家分享下经验,如果有需要的可以下载)

我做了两个关于红外循迹模块的原理讲解和使用视频上传到了B站上,如果大家感觉文档说明的不是很清楚的话也可以看视频,本人水平有限,如果视频中有讲的不好的地方希望大家多多包涵,如果有需要的话可以在上方实物链接中购买循迹模块和小车驱动板产品,感谢大家支持。

三路pid红外循迹模块原理视频讲解:三路pid红外循迹模块原理视频讲解

三路pid红外循迹模块参数配置视频讲解:三路pid红外循迹模块参数配置视频讲解

红外传感器循迹原理如图1所示:

图1 红外传感器原理

图1 红外传感器原理

 红外二极管发射红外光,接收管接受反射的红外光信号。不同的颜色反光效果不同,如果红外光照射在黑色物体上,由于黑色物体对光的吸收能力强,反射的光很少。但照在白色物体上,由于白色物体对光的吸收能力弱,反射的光较多。从而当红外二极管发出的光照射在不同颜色的物体上时,接收管接受的红外光强度也不同,从而可以判断出前面物体的颜色。
图2 赛道

图2 赛道

 红外循迹就是根据这个原理,将红外模块安装在寻迹小车上,然后再赛道上面贴上黑色胶带,当检测到黑色时说明小车在黑线上,检测到白色是说明小车偏离黑线,则需要向黑线靠近,赛道如图2所示。市面上大多数红外循迹传感器采用数字式的,也就是将红外接收管接受到的模拟量信号通过电压比较转换为0和1的数值信号,按照这种方法寻线的话至少需要两个红外传感器,固定在黑线两侧,当左边红外传感器检测到偏离黑线时往右偏,当右边红外传感器检测到偏离黑线时往左偏。这样确实可以寻线,但是寻线效果相当不好,这样寻线有以下几个缺点:
①寻线精度差
②容易偏离轨迹
③寻线速度慢
 不过也有优点,优点就是程序简单。市场上也有五路的和七路的但是这样效果也就好那么一点。其实市场上这种将模拟量变成数字量的方法本身就将精度很高的传感器变为精度低的了。因为采集红外接收管信号的方式是通过AD采集,如果是10位AD的话精度位1024,采用STM32F103C8T6的话有12位AD,采集的精度位4096。但这种采集精度高的处理方法是比较好,但是处理的过程相对麻烦,大致思路就是单片机通过内部AD采集循迹传感器模拟量,然后通过PID参数控制舵机角度。
 下面我要介绍的红外循迹模块也就是这种直接通过单片机内部AD采集红外循迹传感器数据,然后根据数据PID动态调调节舵机角度的方法。采用的红外循迹模块为三路循迹模块实物如图3所示,电路原理图如图4所示。

在这里插入图片描述

图3 三路红外循迹传感器实物图

 循迹模块电路原理图

图4 循迹模块电路原理图

 其中三个红外管的功能不同,左右两个红外管的作用是判断传感器离黑线边界的距离,获取的AD值越大说明离黑线越远,则舵机需要转动的角度也就越大。中间的一个红外管的作用是判断是否传感器在黑线内,我将用一个曲线图来向大家表示原理,便于大家理解,图5位循迹模块安装图。
循迹传感器安装图

图5 循迹传感器安装图

 将循迹传感器固定在小车上,传感器离轨道的高度为3cm左右,假设左两个红外传感器之间的距离和轨道黑线的宽度相同为3cm,传感器从左到右移动获得的图像如图6所示:
在这里插入图片描述

图6 左右传感器向左移动图像

 将右传感器值减去左传感器值可得到图像如图7所示:
在这里插入图片描述

图7 左右传感器相减数据整合图

 这时获取的数据有效长度只能在3cm黑线轨迹之内,当数据为0时表示小车循迹方向没有偏差,大于0说明小车往左偏,小于0说明小车往右偏,数值越大说明偏离的越大。但是由于数据有效长度只有3cm当小车速度快时,容易冲出有效循迹黑线范围,同时我们也注意到,有效长度左边和右边有一段数据没有用到,我可以尝试将左有两段没用用到的数据纳入到有效处理数据。
图8 根据中传感器获取左右阈值点

图8 根据中传感器获取左右阈值点

 如上图8所示,我们可以通过中间的红外传感器来获取,当中间传感器小于阈值时,通过判断左右两个红外传感器相减值得正负来处理左右两边的数据,数据翻转将斜率变为原来2倍。得到的最终效果图如下如所示,最终得到的宽度为原来3倍左右,为9cm。即使传感器完全偏离黑线,最终也会回来,最终达到处理后的效果为图9所示。
图9 最终数据处理效果

图9 最终数据处理效果

 图10为将模块从左到右移动后三个红外对管的数据和整合后的数据输出情况,由于手动移动的,所以数据有点波动。

matlab绘制实际PID循迹模块输出效果

图10 matlab绘制PID循迹模块实际输出效果图

 综上所述,需要经过这几步达到最终效果:
(1)确定左右传感器差值(D_AD_VALUE):
确定方法:将传感器放到白色纸上,将左右两个传感器的数据通过串口发送到电脑上,获取左右两个传感器差值,D_AD_VALUE=Left_AD-Right_AD。
(2)确定左传感器峰值点(LEFT_MAX)和右传感器峰值点(RIGHT_MAX):
确定方法:将左红外传感器和右红外传感器分别从左到右移动,将数据通过串口发送到电脑上观察数据获取最大值,一般当传感器移动到黑线中间是获得数据最大值。
(3)确定左阈值点(LEFT_THREASH)和右阈值点(RIGHT_THREASH):
确定方法:当达到左传感器达到峰值时,观察中间红外传感器数值,此时中间红外传感器数值即为左阈值点。同样当达到右传感器达到峰值时,观察中间红外传感器数值,此时中间红外传感器数值即为右阈值点。
(4)进行数据整合:
①当中间传感器获取的AD数值在左阈值点和右阈值点之间时,将获取到的左传感 器数据(Left_AD)与右传感器数据(Right_AD)相减加上左右传感器差 Data_Out=(Left_AD-Right_AD+D_AD_VALUE)。
②当①中获取的数据大于零(DATA_OUT>0)且中间传感器获取的数据小于左阈 值时(Mid_AD<LEFT_THREASH), Data_Out=(2*LEFT_MAX-Left_AD)2
③当①中获取的数据大于零(DATA_OUT>0)且中间传感器数据获取的数据小于左阈 值时(Mid_AD<RIGHT_THREASH), Data_Out=(2
RIGHT_MAX-RIGHT_AD)*2

综上所述换成用C语言形式写即为:

//获取循迹传感器输出函数
//返回值:int类型,范围循迹传感器数据,根据此值来调节小车舵机角度
int GetTraceDate()
{
	int Data_Out;//定义数据输出变量
	int Left_AD,Right_AD,Mid_AD;//定义左右中传感器AD值变量
	Left_AD=Get_Adc(2);
 	Mid_AD=Get_Adc(3);
	Right_AD=Get_Adc(4);
	Data_Out=(Left_AD-Right_AD+D_AD_VALUE);
	if((Data_Out>0)&&(Mid_AD<LEFT_THERSH))
	{	
		Data_Out=(2*LEFT_MAX-Left_AD)*2;
	} 
	else if((Data_Out<0)&&(Mid_AD<RIGHT_THERSH))
	{
		Data_Out=(Right_AD-2*RIGHT_MAX)*2;
	}
	return Data_Out;
}

注意:这是最理想情况下的调节步骤,在调试时需要根据自己的模块安装位置和黑线宽度调节一些参数,但大致调试步骤就是这样,关于详细的调节步骤和细节方面可以参考我发布到B站上的视频教程。

如果大家感觉配置麻烦的话我做了一款一键配置的循迹模块,配置简单,串口直接输出数据,使用于1-4cm线宽,如果大家感兴趣的话可以查看此篇博客有详细介绍:串口直输型循迹传感器

  • 177
    点赞
  • 1321
    收藏
    觉得还不错? 一键收藏
  • 45
    评论
下面是使用红外循迹传感器PID控制算法控制差速转向小车的示例代码,使用Arduino IDE编写: ``` //定义红外循迹传感器的引脚号 #define LEFT_SENSOR A0 #define RIGHT_SENSOR A1 //定义电机控制引脚号 #define LEFT_MOTOR_PIN 5 #define RIGHT_MOTOR_PIN 6 //定义PID控制算法的参数 #define KP 1.2 #define KI 5 #define KD 0.1 //定义PID控制器 class PIDController { private: double _kp, _ki, _kd; double _targetValue; double _error, _lastError, _sumError; unsigned long _lastTime; public: PIDController(double kp, double ki, double kd) { _kp = kp; _ki = ki; _kd = kd; _targetValue = 0; _error = 0; _lastError = 0; _sumError = 0; _lastTime = millis(); } void setTargetValue(double targetValue) { _targetValue = targetValue; } double compute(double inputValue) { unsigned long currentTime = millis(); double deltaTime = (double)(currentTime - _lastTime) / 1000; _lastTime = currentTime; _error = _targetValue - inputValue; _sumError += _error * deltaTime; double deltaError = (_error - _lastError) / deltaTime; _lastError = _error; double outputValue = _kp * _error + _ki * _sumError + _kd * deltaError; return outputValue; } }; //定义PID控制器实例 PIDController pid(KP, KI, KD); void setup() { pinMode(LEFT_SENSOR, INPUT); pinMode(RIGHT_SENSOR, INPUT); pinMode(LEFT_MOTOR_PIN, OUTPUT); pinMode(RIGHT_MOTOR_PIN, OUTPUT); pid.setTargetValue(0.5); //设置目标值为0.5 } void loop() { //读取红外循迹传感器的值 int leftSensorValue = analogRead(LEFT_SENSOR); int rightSensorValue = analogRead(RIGHT_SENSOR); double sensorValue = (double)(leftSensorValue + rightSensorValue) / 2.0 / 1023.0; //计算PID控制算法的输出值 double outputValue = pid.compute(sensorValue); //将输出值转换成电机控制信号 int leftMotorSpeed = 255 * (1 - outputValue); int rightMotorSpeed = 255 * (1 + outputValue); //控制小车的转向 analogWrite(LEFT_MOTOR_PIN, leftMotorSpeed); analogWrite(RIGHT_MOTOR_PIN, rightMotorSpeed); } ``` 上述代码中,首先定义了红外循迹传感器的引脚号和电机控制引脚号。然后定义了PID控制器的参数和实例,包括比例系数、积分系数、微分系数、目标值和误差等。在`setup()`函数中,初始化了引脚和目标值。在`loop()`函数中,读取红外循迹传感器的值,并根据PID控制算法计算输出值。最后将输出值转换成电机控制信号,控制小车的转向。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 45
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值