这是一个用于比赛的循迹跟踪小车项目,他是怎么在兼顾尺寸和速度性的同时满足小车高性能的要求的呢?
循迹小车在创客圈里面并不是什么新鲜事,但普通的循迹小车要么比较大,要么则比较重,并不适合用来比赛。在我们当地的创客圈子里面有一个循迹小车的比赛项目,要求上场的小车的尺寸不能超过12x20cm,那我们该怎样来满足这样的需求呢?
本项目的主要开发过程分为三个部分:电子构建,结构设计和3D打印,程序配置和调试。下面我们就来完成它吧。 第一步:电机在开发此项目的过程中,要切记的一点是我们是在开发一个比赛用的小车。此处我选用了Pololu提供的电机,他家的电机分为四种:低功率、中等功率、高功率和长寿命高功率,这四种电机的工作电压都为6V,而且物理尺寸也基本相同。低功率的电机功耗较低,但是要知道我们这是为了比赛,所以应该选择那两种高功率的电机。其中长寿命高功率的电机的使用寿命更长,但是并不能承受高于6V的电压。综合考虑之后,我选择了高功率的电机,它们能够不中断地连续使用好几个小时,这已经足够了。
接下来我们应该选择多少的传动比呢?通常电机的传动比越高,电机的速度就越低,但是电机提供的扭矩却更高,就能提供更高的加速度。对比较重的机器人来说这确实非常重要。我的建议是在30:1到10:1的传动比之间做出选择,最后我选择的四个传动比为10:1的电机,毕竟是为了比赛,我会尽量降低小车的质量,从而提供更高的速度。当然,你也可以选择使用2个30:1的传动比的电机,这样为了获得更高的速度,你需要为电机提供高于6V的电压。
第二步:车轮因为电机的速度是以每分钟的转速衡量的,所以在转速固定的情况下,轮子直径越大,理论上就跑得越快,但与此同时轮子也会越重。综合考虑之后我选择了直径32毫米的窄边车轮,其单个重量为3.2克。
第三步:电池电池方面我推荐使用储能密度大、可充电的LiPo电池。我使用的是850mAh 7.4V双芯LiPo电池。
第四步:球脚轮为了能让小车的电机获得足够的反应时间,需要将小车的循迹探测器尽量前置,那么这就需要用到2个前置的球脚轮.当然这两个球脚轮并不是必需的,如果你的小车的设计能够在行进过程中维持平衡,或者只是采用后轮驱动的方式运动(将探测器安装在车体前部),那么就不需要这两个球脚轮。
注意两只球脚轮的相对位置,不要让其对小车的行进方向产生影响。
第五步:小车结构为了在保证小车基本结构上尽量降低小车的质量,我选择自己设计小车的结构件。然后用3d打印机打印出来即可。注意,打印之前需要导出适合3D打印机的STL文件。
第六步:探测器组件这一步我需要搭建能够用来探测地面标线的探测器设备。这里我用到了9个CNY70光电传感器(5个或7个应该也可以),9个220Ω电阻和9个56kΩ下拉电阻。另外我还设计了一个简易的PCB板用来承载我的电路结构。 这套探测器的原理很简单,每个CNY70传感器都会产生0-5V的电压,其中0V左右表示探测到黑色,5V左右则是白色。CNY70提供了0-1024的精度范围。
电路板上一共引出了11个接口,其中两个分别是接地和5V电源,其它9个是传感器的模拟输出。电路本身并不复杂,复制以下电路9次即可。 第七步:主电路设计探测器的电路不复杂,主电路却相对较为复杂一点。这里我们没有使用常见的Arduino,而是使用了PIC18F4550单片机,因为其体积更小,而且在某些比赛中是禁止使用Arduino的。 电路设计如下:
相关文件:
VPOWEREXP.pdf
TOPLAYER.pdf
BOTTONLAYER.pdf
VPOWER.pdsprj
主电路的组件清单如下:
PIC18F4550单片机
20MHz晶振
3到6个LED(PCB上只使用了3个)
3个220欧姆电阻(用于LED)
2个10nF陶瓷电容
2个18nF陶瓷电容
L293D或SN7544(电机驱动模块)
开关
三个按钮
7805三端稳压器(为单片机提供5V电压)
线材等
接下来就是制作对应的PCB板。
然后将各个组件焊接到PCB上。
第十一步:路径跟踪确定了中心线之后就需要控制电机对线进行跟踪了。由于我们采用的电机并不具有直接转向的功能,我们需要用到另一种转向方式:速度差转向——通过为小车的轮子设定不同的速度从而让小车整体产生转向效果。控制速度则用到了常用的脉冲宽度调制,这一部分整合到了小车的代码中。此处我们需要用到一个函数MotorsSpeed(a,b),其将定义电机的速度,并将其设置到区间(-1000,1000)之间,包括前后速度。
void MotorsSpeed(int A,int B){
///If mode equals alfa then we invert the motors voltage
MotorASpeed(MODE == ALFA ? A : B);
MotorBSpeed(MODE == BETA ? A : B);
}
void MotorASpeed(int S){
S = min(S,1000);
S = max(S,-1000);
ADIR = S > 0 ? 0 : 1;
S = S > 0 ? S : 1000 + S;
CCP1CONbits.DC1B1 = S % 4;
CCPR1L = S / 4;
}
void MotorBSpeed(int S){
S = min(S,1000);
S = max(S,-1000);
BDIR = S > 0 ? 0 : 1;
S = S > 0 ? S : 1000 + S;
CCP2CONbits.DC2B = S % 4;
CCPR2L = S / 4;
}
实现了对电机的速度控制,就可以实现转向算法了。
void LineFollow(){
double kp,kd,kr,speed;
///POSICION has the value of the center of the line previously calculated
kp = KP[speedMode];
kd = KD[speedMode];
kr = KR[speedMode];
DER = POSICION - LP; ///We calculate how much the line has moved from the last iteration PIDf = (POSICION* kp + DER * kd);
if (PIDf > 0){
MotorsSpeed(Mr(speed-PIDf,kr) , speed); ///Mr makes the value to multiply by KR if it is negative. You can delete it
}else{
MotorsSpeed(speed , Mr(speed+PIDf,kr) ); ///Mr makes the value to multiply by KR if it is negative. You can delete it
}
LP = POSICION; ///We store the last line position
}
第十二步:完成部署好了算法也就大功告成了,接下来就该拿到赛场上比试比试。哦,看起来高手还是挺多的嘛……
[media]http://v.qq.com/page/y/2/w/y0175nzad2w.html[/media]