21323| 15
|
基于Arduino的寻线小车的设计与制作(甲壳虫篇) |
先来看看甲壳虫的视频吧,能够完成小车寻线任务和遇到阻碍张开翅膀的功能: 所选小车零件清单: 1,Romeo V2.2板; 2,智能灰度寻线传感器; 3,miniQ小车; 4,红外测距传感器; 5,9g舵机; 6,RGB灯盘; 7,3D打印件若干。 小车设计机械篇: 途中紫红色的地方是舵机,用来打开翅膀。绿色部分是安装寻线的底座,外形上设计成甲壳虫的嘴(扁平化设计),后面蓝色的区域是放置小车主控板的地方,把该区域预留出来,防止在设计其他部件的时候,不至于由于主控板位置而阻碍其他部件的正常使用。 甲壳虫翅膀从动原理如上图所示,翅膀可跟头通过合页连接起来,这样一来就可以实现翅膀的张与合,然后通过舵机来拉动连杆,让翅膀运作; 如图所示的是甲壳虫嘴型的设计,上面有舵机安装孔,寻线传感器安装孔和安装在小车上的固定孔。 上图是小车头的设计,包含了避障传感器的安装位置,合页的位置,与底部让位给舵机的槽; 上左图是甲壳虫翅膀的设计,它需要通过连杆才能与舵机相连,于是笔者用虫虫的铁丝脚手动做了一个连杆,如上右图所示。 小车设计硬件篇: 小车的主要任务是寻线,本次设计采用了六个寻线传感器来寻找小车底部的轨迹: 具体安装如下: 寻线传感器用的是型号为SEN0147智能灰度传感器,避障传感器用的是型号为SEN0014 的GP2Y0A21 距离传感器,舵机选的是9g舵机型号为SER0006,他们与Romeo板的连接图如下: 小车设计软件篇 既然硬件与机械都做好了,接下来就是让小车跑起来的节奏了,首先是寻线任务,如何实现小车找到线,并且按照线的轨道去行驶呢,本文就实现这一目的采用了一种PID算法形式的寻线方案。 首先我们来了解一下小车寻线的简单方案; 每个位置上的传感器检测到黑线之后所做出的动作是不一样的,中间的传感器检测到小车拐弯就拐小一点,边上的检测到拐弯就大一点,以此类推,通过六个传感器检测之后所反映的位置的不同来调节小车轮子的速度,从而来控制小车能够在黑线上左右摆动形式的前进。笔者以此为背景,结合PID控制的原理,制作出一种基于PID算法的寻线思路。 来说说PID控制原理,PID控制原理是建立在闭环系统中,让系统区域稳定变换的控制机制。它可以让整个系统不会因为剧烈变化从而使得这个系统运作在不稳定中,如下图所示: 通过不断反复比较输入量,设定量与输出量之间的关系,通过PID算法的不断运算,去调节输出量,使得整个系统始终在设定量左右徘徊变换,最终置不变,那么由上图这个框架我们就知道了,我们需要的参数有哪些:首先 输入量=传感器检测到线的位置的变化率; 设定量=黑线始终在中间,并且不发生变化; 输出量=小车的速度(由于改变了小车两个轮子之间的速度差使得小车传感器检测到黑线的频率发生变化,这里的反馈信息是小车速度的变化,间接改变了小车传感器检测的频率,从而构建了这个系统的反馈部分) PID控制算法是由P(比例)算法,I(积分)算法和D(微分)算法共同决定的,这里就简单的描述一下:P算法说白了,就是输出量与设定量之间产生的差值乘以一个值来改变这个系统的输出,这样做的好处就是可以直接改变系统的状态,比如说小车l3传感器检测到黑线,那小车要右拐,然后直接让小车的左轮的速度乘以一个数,使小车这个轮子的速度瞬间变大然后直接拐弯; 但是这样的系统直接变换很难控制,所以需要加一个量来控制它的变化方向——积分算法。积分算法的实质是累加误差值,因为我们的目的是让传感器不发生变化,这样一来小车就能在黑线中直行。这样通过累积误差值来控制小车的话,会让小车不会因为速度变换的太快而离开黑线。(如果P算法乘积过大也会让系统不稳定) 最后是D算法,D算法的实质是误差的变化率,它可以反映出输出量与设定量差值的变化率,就是变化快慢的意思,也可以达到一个让系统变化速度平和一点。 以上是笔者简单的介绍了PID算法的原理,接下来就对程序上如何实现展开叙述: 我们设定这个小车前方传感器的变换率为0,接下来就是输入量: float Decide_input(float table[]) //定义输入量函数; { float templ=0,tempr=0; float a=table[0],b=table[1],c=table[2],d=table[3],e=table[4],f=table[5]; //将六个传感器检测到的数据记录下来 templ=MaxThree(a,b,c); //选择左边三个传感器中数字最大的,也就是黑线的位置 tempr=MaxThree(d,e,f)*(-1); //选择右边三个传感器中数字最大的,也就是黑线的位置 if(abs(templ)>abs(tempr)){SwitchMaxspeed(templ);return templ;} //选出最大的量作为最后黑线位置判断的依据 else if(abs(templ)==abs(tempr)){SwitchMaxspeed(0);return 0;} else {SwitchMaxspeed(tempr); return tempr;} } 接着是PID算法的实现: void PID_speed(int a) //PID算法函数 { float error=0; //输入与设定的误差变量 unsigned long now = millis(); unsigned long timeChange = (now - LastTime); if(timeChange>=1) //以一定的时间(1ms)来检测上一状态和下一状态 { error = Setpoint- Input; //计算输入与设定的误差 ITerm=ITerm+0.01 * error; // I算法,不停的累加误差值,从而控制系统变化的方向 if(ITerm>a)ITerm=a; else if(ITerm<-a)ITerm=-a; double dInput=(Input-LastInput); //D算法,单位时间误差的变化量,即误差变化率 Outputtemp = 10 * error + ITerm-dInput*11; //PID算法公式,通过它,可算出系统调节后的输出量 if(Outputtemp>a)Outputtemp=a; else if(Outputtemp<-a)Outputtemp=-a; else Outputtemp=Outputtemp; LastInput=Input; LastTime=now; } } 左后将算好的差值传给电机,也就是输出量: cardriver(60+Outputtemp,60-Outputtemp);//电机转动函数,60为基准速度,然后加减输出量来达到对小车的控制,其中需要注意的是输出量可为负值) 写到这里,这份帖子也应该结束了,但是呢这个小制作还没有结束,后期还有很多地方需要改进,无论是机械结构还是算法逻辑等等,后期有改进之后,在从新发布一份更加详细更加简单易懂的帖子以供交流,如果大家有什么好的建议也可以跟我说说,方便我改进。持续中。。。。。。 |
2.16 KB, 下载次数: 6757
6寻线程序
© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed