智能车制作
标题:
《飞思卡尔光电结束散尽经验和程序》
[打印本页]
作者:
251663924
时间:
2014-7-31 17:43
标题:
《飞思卡尔光电结束散尽经验和程序》
做智能车的过程中,如果有一天我把车做出来了,并且做的不错,我会把代码以及思路贡献出来,让以后做车的同学们少走些弯路,我们是省赛一等奖,所以看看还是有些意义的。
我是做光电的,不知道其他智能车是怎么写的,但根本都差不多。光电车控制简单分为3部分:寻迹,方向控制,电机控制。
首先我是基于lpld库写的程序,如果没看懂的话可以稍微了解下这个库
寻迹:首先进行ccd采集,有人搞半天都不知道曝光时间是什么东西。你可以大致的认为曝光改变ccd电压作用的,你可以先用静态曝光试试看,如果算法写的好的话,再用动态曝光。我们没用曝光程序,有人觉得不可思议,其实是可以的,我们用的是固定6ms采集。
void ImageCapture(uint8 * ImageData) //图像采集128个点
{
unsigned char i;
CCD_SI1; // SI = 1
delay200ns();
CCD_CLK1; // CLK = 1
delay200ns();
CCD_SI0; // SI = 0
delay200ns();
//delay 20us for the first pixel
delay10us();
ImageData[0]=LPLD_ADC_Get(ADC0,AD8);
CCD_CLK0; // CLK = 0
for(i=1;i<128;i++)
{
delay200ns();
delay200ns();
CCD_CLK1; //CLK=1
delay200ns();
delay200ns();
ImageData
=LPLD_ADC_Get(ADC0,AD8);
CCD_CLK0; //CLK=0
}
delay200ns();
delay200ns();
CCD_CLK1; // CLK = 1
delay200ns();
delay200ns();
CCD_CLK0; // CLK = 0
}
采集好之后就可以进行区分黑白底了,区分黑白底方法主要分为两种:二值化法,边沿法。我相信大部分都用的二值化法,因为边沿法对采集回来的图像和ccd本身性能要求比较高,我也写过,不太好写。我们用的就是二值化方法,二值化主要就是确定一个阈值,确定阈值的方法也有很多种 ,我首先举一些我听过的算法,一种是车子在开机的时候采集赛道信息,分出黑点的灰度blackdc,以及白点的灰度whitedc,如果跑的过程中出现灰度在blackdc+20以下的默认为低,出现灰度在whitedc-20以上的默认为高,这是一种方法。
第二种方法,比较常用求平均值,怎么说呢,在不丢线的情况下,这个方法是可行的,丢线时要作特殊处理。第三种方法,就是静态阈值,就是自己在跑之前,通过上位机看一下图像,人为的输入一个阈值,这种方法有个弊端吧,就是每次换个新环境的时候,你都要担心你的阈值准不准确。我们用的是静态的阈值。
有了阈值就可以找出左右线了。
//==============随后即是提取黑线,代码如下:=====================
/*车位置越大说明靠左,ccd看到右边的还是右边的,左边还是左边的
直道时如果车位置较小,说明在车子靠右
弯道时,比如左转弯,他只看到右边的线,车位置也很小。
*/
void Get_Flag(void) //我感觉这里应该舍弃两边的几个点
{
shiziwan=0;
fandiuxianflag=0;//防丢线标志位
int16 left_num,right_num;
left_flag=0;
right_flag=0;
erzhihua();//二值化,里面包含了求动态阀值
Filter_Pixel_Two();//滤波
Filter_Pixel_Three();//滤波
if(left_point>100)
{
right_flag=0;
for(left_num=midlinexian;left_num>90;left_num--) //取得最左边的点,舍弃第一个坏点, 从上次车的中点开始向左边寻找舍弃了10个点
{
if(pixel[left_num]-pixel[left_num-1]==200)
{
left_point=left_num;
left_flag=1;
break;
}
}
fandiuxianflag=1;
}
if(right_point<28)
{
left_flag=0;
for(right_num=midlinexian+1;right_num<38;right_num++) //取得最右边的点舍弃了10个点 右边死区110
{
if(pixel[right_num]-pixel[right_num+1]==200)
{
right_point=right_num;
right_flag=1;
break;
}
}
fandiuxianflag=2;
}
if((fandiuxianflag!=1)&&(fandiuxianflag!=2))
{
for(left_num=midlinexian;left_num>11;left_num--) //取得最左边的点,舍弃第一个坏点, 从上次车的中点开始向左边寻找舍弃了10个点
{
if(pixel[left_num]-pixel[left_num-1]==200)
{
left_point=left_num;
left_flag=1;
break;
}
}
for(right_num=midlinexian+1;right_num<114;right_num++) //取得最右边的点舍弃了10个点 右边死区110
{
if(pixel[right_num]-pixel[right_num+1]==200)
{
right_point=right_num;
right_flag=1;
break;
}
}
}
}
有的时候在转弯的时候会出现串道的情况,就是跑到旁边的赛道了,这个时候要做特殊处理,上面有写。就是让他只检测一定范围的区域就行了。
寻迹到这就讲完了,重点就是上面这个程序。
接下来就是方向控制
对于方向控制基本上就两种方法:一个就是连续控制,一个就是分段控制。
这两种方法,我比较偏向于第一个,第一种跑起来更平滑。在直道的时候给个固定p值,弯道的时候给个二次函数的p值,算法如下:
if(a<14)
{
K_Direction_P=19; //14
K_Direction_D=100;
}
else if(a<26)
{
K_Direction_P=0.018*a*a+1.226*a; //a>16,P=0.048*a*a+0.037
K_Direction_D=100;
}
else
{
K_Direction_P=42; //a>16,P=0.048*a*a+0.037*a;
K_Direction_D=100;
}
这里的a是当前位置到中线的差值。
d值一般给大点就行了,有消抖的左右。
然后就是控制舵机打脚了,这个比较简单,
mid_err2=mid_err1; //上次偏差
mid_err1=midline-64; //车位置与中点的差
mid_err_err=mid_err1-mid_err2;
DirectionOutnew=(uint32)(angle_value+(K_Direction_P*mid_err1 +K_Direction_D*mid_err_err));//angle_value是指0度的时候对应的占空比angle_value=750
DirectionOutold=DirectionOutnew;
if(DirectionOutnew>rightlimit) //rightlimit=639向右打弯
{
LPLD_FTM_PWM_ChangeDuty(FTM0,FTM_Ch0,rightlimit);
}
else if(DirectionOutnew {
LPLD_FTM_PWM_ChangeDuty(FTM0,FTM_Ch0,leftlimit);
}
else
{
LPLD_FTM_PWM_ChangeDuty(FTM0,FTM_Ch0,DirectionOutnew);
}
就是中间值+pid值就行了,关于pid算法,什么增量式,什么是位置式,这没必要纠结,能用就行。用c编写程序的时候要经常用到变量的强制转换。还有就是定义变量的时候一定要注意变量大小。有时出错了,找一晚上都找不出来,最后才发现是变量定义的有问题。
最后就是最重要的速度控制了。速度控制是提速的保证,你的车想跑多快,不仅仅是方向控制写的好,到了后期大家拼的就是速度控制了。关于速度控制主要有三种方法:pid,bang-bang,pid+bang-bang;
那哪种方法好呢,只能说,哪种你的车跑的快,哪种就好。bang-bang算法具有很强的加速能力和减速能力,有个弊端就是容易飘逸。如果控制的好,我感觉是非常nb的。pid算法速度具有很强的连续性,加减速看的不明显,直道与弯道速度不能差太大,跑起来四平八稳,过弯道能力强。我们用的就是pid算法。pid+bangbang算法被认为是最理想的,本人也写过,一直到校赛我一直都用pid+bangbang ,效果其实也还行。但是最后不知道怎么还是钟情于pid了,呵呵。
接下来就是速度控制,
//===============速度控制函数==================
void speed_control(void)
{
float a,b;
a=abs(mid_err1);
if(stopflag==1) //stopflag是起跑线标志
{
speed_mid=0;
}
else
{
if(a<6)
{
speed_mid=zhixianspeed_mid;
}
else if(a<20)
{
speed_mid=ruwanspeed_mid1;
}
else
{
speed_mid=ruwanspeed_mid1-10;
}
}
/* if(stop==1)
{
speed_mid=0;
fanzhuanduty=1000;
if(ch0_pulseacc<3)
{
fanzhuanduty=0;
}
}*/
speed_pluse=ch0_pulseacc;//speed_pluse=pluse/(float)speedcount;
if(speed_pluse<5) //当编码器的值很小的时候,让车停下来
{
stop=1;
}
speed_err1=speed_mid-speed_pluse;
speedoutold=speedoutnew;
p_value=K_p*(speed_err1-speed_err2);
i_value=K_i*speed_err1;
d_value=K_d*(speed_err1-2*speed_err2+speed_err3);
speedoutnew=speedoutold+(p_value+i_value+d_value);//著名的pid算法,绝对正确
speed_err3=speed_err2;
speed_err2=speed_err1;
if(stop==1)
{
speedoutnew=0;
}
if(speedoutnew<-6000)
{
speedoutnew=-6000;
}
if(speedoutnew>6000)
{
speedoutnew=6000;
}
if((speed_pluse>speed_mid)&&(a<10)&&(stopflag==0)) //刚入弯的时
{ //候,如果当前速度大于目标速度,清
LPLD_FTM_PWM_ChangeDuty(FTM1,FTM_Ch0,0); //零
speed_zhen;
speedoutnew=0;
speed_err1=0;
speed_err2=0;
}
else
{
if(speedoutnew>0)
{
LPLD_FTM_PWM_ChangeDuty(FTM1,FTM_Ch0,(uint32)speedoutnew);
speed_zhen;
}
else
{
b=-speedoutnew;
LPLD_FTM_PWM_ChangeDuty(FTM1,FTM_Ch0,(uint32)b);//正转方向占空比为0 反转
speed_fang;
}
}
}
关于电机驱动我建议用mos管,btn能把你手烫熟了。
好了到了这里,基本就写完了,有人问那你人字弯和障碍以及十字怎么没写。我只能说自己探索的过程是别人无法知道的乐趣。再说明年就不一定是人字弯了,肯定又有新的挑战了。只有不断不断的学习,才能一直进步,不要满足现状。
作者:
机器人没名字
时间:
2014-7-31 18:00
楼主好人
作者:
wajuka
时间:
2014-7-31 18:08
顶
作者:
竹音清影
时间:
2014-7-31 18:28
浪险。
作者:
chenqiang
时间:
2014-7-31 18:39
好人啊
作者:
那那喃喃俺奶奶
时间:
2014-7-31 19:04
楼主 你好,,我想知道你那滤波是怎么回事
作者:
cjn
时间:
2014-7-31 19:14
:victory:
作者:
A.Iniesta
时间:
2014-7-31 22:18
楼主好人
作者:
wuguangnan110
时间:
2014-7-31 23:23
厉害1
作者:
1072964526
时间:
2014-8-1 01:09
不知道楼主是怎么解决光线太强的问题的,是大津法么?
作者:
43380249
时间:
2014-8-1 13:35
作者:
邵志伟
时间:
2014-8-1 16:33
红树伟业的采集~~~~我也觉的这个采集不错,曝光时间改到1ms也能稳定运行(1ms包括两个CCD采集和所有数据处理,我就是这么做的,动态曝光,其实比较针对光线变换不均比较好)
人字弯还是没有挑战,我希望明年踹谢娜裤脚弯
就是,某个赛区铺错了的那个~~~
作者:
仰望,蘫迗
时间:
2014-8-1 23:18
顶~不沉
作者:
我忘了
时间:
2014-8-2 08:59
记得当初咱谈论时是那么的纯洁,有些弯路就不用走了,咱共享出来,至少直接能跑,大家都强了,智能车制作才会有新思路,才会越来越强,哈哈,当时你还说让我把硬件也开源,但我觉得很丑啊,就不丢那人了。
作者:
chinahuangyong
时间:
2014-8-5 07:53
楼主动态p 是怎么算出来的呀?
作者:
天芒
时间:
2014-8-5 10:18
十字不用写吧
作者:
wijop
时间:
2014-8-5 15:36
LZ好银
作者:
lixuezhj
时间:
2014-8-6 10:41
狂赞,句句经典
作者:
wylnii
时间:
2014-8-10 13:44
!!!!!!!!!!!!!!!!!!!
作者:
只是你
时间:
2014-8-31 10:32
作者:
晒太阳的蘑菇
时间:
2014-8-31 15:07
楼主厉害
欢迎光临 智能车制作 (http://dns.znczz.com/)
Powered by Discuz! X3.2