智能车制作

 找回密码
 注册

扫一扫,访问微社区

查看: 3968|回复: 20
打印 上一主题 下一主题

《飞思卡尔光电结束散尽经验和程序》

  [复制链接]

4

主题

11

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
410
威望
209
贡献
111
兑换币
116
注册时间
2014-3-9
在线时间
45 小时
毕业学校
安徽大学
跳转到指定楼层
1#
发表于 2014-7-31 17:43:58 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
做智能车的过程中,如果有一天我把车做出来了,并且做的不错,我会把代码以及思路贡献出来,让以后做车的同学们少走些弯路,我们是省赛一等奖,所以看看还是有些意义的。
我是做光电的,不知道其他智能车是怎么写的,但根本都差不多。光电车控制简单分为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能把你手烫熟了。


好了到了这里,基本就写完了,有人问那你人字弯和障碍以及十字怎么没写。我只能说自己探索的过程是别人无法知道的乐趣。再说明年就不一定是人字弯了,肯定又有新的挑战了。只有不断不断的学习,才能一直进步,不要满足现状。


评分

1

查看全部评分

回复

使用道具 举报

17

主题

215

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1668
威望
863
贡献
459
兑换币
545
注册时间
2014-3-2
在线时间
173 小时
21#
发表于 2014-8-31 15:07:24 | 只看该作者
楼主厉害
回复 支持 反对

使用道具 举报

2

主题

33

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
340
威望
147
贡献
113
兑换币
81
注册时间
2014-8-17
在线时间
40 小时
毕业学校
还没
20#
发表于 2014-8-31 10:32:51 | 只看该作者
回复 支持 反对

使用道具 举报

1

主题

37

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1070
QQ
威望
554
贡献
328
兑换币
325
注册时间
2013-8-24
在线时间
94 小时
19#
发表于 2014-8-10 13:44:38 | 只看该作者
!!!!!!!!!!!!!!!!!!!
回复 支持 反对

使用道具 举报

3

主题

39

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1442
威望
760
贡献
446
兑换币
471
注册时间
2013-7-18
在线时间
118 小时
18#
发表于 2014-8-6 10:41:27 | 只看该作者
狂赞,句句经典
回复 支持 反对

使用道具 举报

5

主题

833

帖子

0

精华

跨届大侠

Rank: 10Rank: 10Rank: 10

积分
6207

优秀会员奖章活跃会员奖章论坛元老奖章在线王奖章

威望
3103
贡献
1968
兑换币
1747
注册时间
2014-5-8
在线时间
568 小时
17#
发表于 2014-8-5 15:36:03 | 只看该作者
LZ好银
回复 支持 反对

使用道具 举报

6

主题

227

帖子

0

精华

常驻嘉宾

Rank: 8Rank: 8

积分
4239
威望
1991
贡献
1328
兑换币
1288
注册时间
2013-1-12
在线时间
460 小时
16#
发表于 2014-8-5 10:18:39 | 只看该作者
十字不用写吧
回复 支持 反对

使用道具 举报

1

主题

142

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2057
威望
1042
贡献
497
兑换币
693
注册时间
2013-2-26
在线时间
259 小时
15#
发表于 2014-8-5 07:53:32 | 只看该作者
楼主动态p 是怎么算出来的呀?
回复 支持 反对

使用道具 举报

1

主题

6

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
291
威望
141
贡献
88
兑换币
90
注册时间
2014-3-10
在线时间
31 小时
毕业学校
安徽大学
14#
发表于 2014-8-2 08:59:32 | 只看该作者
记得当初咱谈论时是那么的纯洁,有些弯路就不用走了,咱共享出来,至少直接能跑,大家都强了,智能车制作才会有新思路,才会越来越强,哈哈,当时你还说让我把硬件也开源,但我觉得很丑啊,就不丢那人了。
回复 支持 反对

使用道具 举报

12

主题

875

帖子

0

精华

常驻嘉宾

删繁就简。

Rank: 8Rank: 8

积分
4602

活跃会员奖章优秀会员奖章论坛元老奖章在线王奖章

QQ
威望
2924
贡献
594
兑换币
1807
注册时间
2013-7-20
在线时间
542 小时
13#
发表于 2014-8-1 23:18:10 | 只看该作者
顶~不沉
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

关于我们|联系我们|小黑屋|智能车制作 ( 黑ICP备2022002344号

GMT+8, 2024-12-24 11:30 , Processed in 0.051913 second(s), 33 queries , Gzip On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表