智能车制作

标题: 电磁 源代码 [打印本页]

作者: 943294069    时间: 2011-10-3 16:33
标题: 电磁 源代码
留下来,发挥点余热,仅作参考

#include <hidef.h>      /* common defines and macros */
#include "derivative.h"      /* derivative-specific definitions */
#include "stdio.h"
#pragma  LINK_INFO DERIVATIVE "mc9s12xs128"
#define  Cha_zhi_M   17
#define  AD_deadline 20
#define  Mid         3510
#define  speed_MAX   600
#define  speed_MIN   0            
#define  sum_adv     180  
              
uint    ADval0[10],ADval1[10],ADval2[10],ADval3[10],ADval4[10],ADval5[10],ADval6[10],ADval7[10];  
uint    ADvv0,ADvv1,ADvv2,ADvv3,ADvv4,ADvv5,ADvv6,ADvv7;
uint    ADv0,ADv1,ADv2,ADv3,ADv4,ADv5,ADv6,ADv7;
uint    AD_mix[8],AD_Mux_Num0,AD_Mux_Num1,AD_Mux_Num2,ADNum_sum;
float   adnum1,adnum2,adsum,adcha;
float   x=0,last_x,b,angle_DAT,pre_angle=3295,pulse_counter;
uchar   x_work=0,M_flag=0,z_flag=0,zero=1,Break;
float   KP=3,KI=0.02,KD=0.5,D_kp=2,D_kd=0,kk=0.35,bili;//PID的初始值
int     fasong,max_speed,min_speed;
int     stopcount,first=0;
int     de=180,del=20;
int     ERROR1,PWM_OUT;
int     wending_x=0,ruwan=0,leter_x,wdjiasu=0,shache;
long    tiaobian,wandaojs=13000,wdganraojs,wendingganraojs;
long    zhidao_js=0,zdjiasu=0,zdganrao_js,zdwendingganrao_js;
long    wandao_js=13000,wdganrao_js,wendingganrao_js;  
long    chujie_js,cjganrao_js,chujieganrao_js;   
long    s_count=0;  
typedef struct PID           //定义数法核心数据
{
    signed int ideal_speed;  //速度PID,速度设定值
    signed int v_FeedBack;   //速度PID,速度反馈值
    signed long v_PreError;  //速度PID,前一次,速度误差,,vi_Ref - vi_FeedBack
    signed long v_PreDerror; //速度PID,前一次,速度误差之差,d_error-PreDerror;
    float v_Kp;              //速度PID,Ka = Kp
    float v_Ki;              //速度PID,Kb = Kp * ( T / Ti )
    float v_Kd;              //速度PID,
    signed long Moto_Out;    //电机控制输出值
}
PID;
PID sPID;
/***函数声明***/
void   PLLInit24M(void);
void   SciInit(void);  
void   PWM_Init(void);
void   ATD_Init(void);
void   TimerAccInit(void);
void   GetVal(void);
float  ads(float y);
void   Car_position(void);
void   DJ_angle(void) ;//舵机的角度计算
void   speedset(void);                                                                                                
void   PID_Init(void);
float  PID_Control(PID *pp );
void   GO(void);
void   ifstop(void);
void   stop();
void   if_Break(void);
void   j_line(void);
void   SciWrite();
void   setPID(void);
void main(void)
{
    PLLInit24M();
    while(de--)    //起始延时
    {
      while(del--);
    }
    PWM_Init();
    ATD_Init();
    TimerAccInit();
    PID_Init();
    SciInit();
    speedset();
    EnableInterrupts;
  
    for(;;)
    {
        _FEED_COP();      //看门狗
        GetVal();
        Car_position();
        j_line();         //路况判断
        DJ_angle();
        if_Break();       //刹车
        GO();
        ifstop();         //停车
        if(s_count>2200)
        stop();
    /*    fasong=ADvv0;
      SciWrite(fasong);
      
      fasong=ADvv1;
      SciWrite(fasong);
      
      fasong=ADvv2;         
      SciWrite(fasong);
      
      fasong=ADvv3;
      SciWrite(fasong);
      
      fasong=ADvv4;
      SciWrite(fasong);
      
      fasong=ADvv5;
      SciWrite(fasong);
      fasong=ADvv6;
      SciWrite(fasong);
      fasong=ADvv7;
      SciWrite(fasong);   
      fasong=0x0;
      SciWrite(fasong); */
    }
  
}
//--------------锁相环-------------//
void  PLLInit24M()
{
    CLKSEL&=0x7f;
    PLLCTL_PLLON=0;
    SYNR =0xC5;
    REFDV=0x81;
    PLLCTL_PLLON=1;
    while (( CRGFLG&0x08) == 0x00);
    CLKSEL |= (1<<7);
}
//----------------SCI--------------//
void SciInit()
{
    SCI0BD=0x9c;         //9600bps  Baud Rate=BusClock/(16*SCIBD)
    SCI0CR1=0;         //正常8位模式,无奇偶校验
    SCI0CR2=0X0c;      //发送允许   中断允许
}
//-----------------写SCI数据---------------------------------//
void SciWrite(int fasong)
{
    while (!(SCI0SR1&0x80));
    SCI0DRL=fasong;           
}
//-----------------PWM--------------------------//
void  PWM_Init()
{
    PWMCTL=0xf0;  //01级联,23级联
    PWMPOL=0x00;  //起始输出高电平
    PWMCAE=0x00;  //左对齐输出
    PWMPRCLK=0x12;//01  Clock A=12M,Clock B=24M
    PWMCLK=0xff;  //所有的都选成SA或者SB
    PWMSCLA=0x03; //SA=2MHZ
    PWMSCLB=0x01; //SB=12MHZ
    PWMPER01=6666;//  周期为舵机  ,01级联使用SA时钟源1/((1/2M)*6666)=300HZ
    PWMPER23=600; // 47020 k电机  ,23级联使用SB时钟源1/((1/12M)*600)=20KHZ
    PWMPER67=600; //470600      
    PWMCNT01=0;
    PWMCNT23=0;
    PWMCNT67=0;
    PWME=0xff;
    PWMDTY01=Mid;
    PWMDTY23=0;
    PWMDTY67=0;
}
//-------------------AD-----------------------------//
void ATD_Init(void)
{
    ATD0CTL1 = 0x00;  
    ATD0CTL2 = 0x40; //转换完成后标志位自动清零
    ATD0CTL3 = 0x80; //转换序列长度为8
    ATD0CTL4 = 0x6D; //06
    ATD0CTL5 = 0x30;
    ATD0DIEN = 0x00;
}
//------------------编码器中断时间------------------//
void TimerAccInit(void)
{
    TCTL3 = 0x80;    //CH7 capture on falling edges only
    PACTL_PAEN = 1;
    PACNT = 0;      
    RTICTL = 0xBF;   // 1 100 1111   1/(16M/320*10^3)s = 20ms     
    CRGINT_RTIE = 1;   
}
//-----------------AD读取------------------//
void GetVal()
{
    uchar  i,j,k,m;
    uint  JiaoHuan;
    ADv0=0;ADv1=0;ADv2=0;ADv3=0;ADv4=0;ADv5=0;ADv6=0;ADv7=0;
    for(i=0;i<10;i++)
    {
        while(!ATD0STAT0_SCF);
        ADval0[i]= ATD0DR0L;ADval1[i]= ATD0DR1L;ADval2[i]= ATD0DR2L;ADval3[i]= ATD0DR3L;
        ADval4[i]= ATD0DR4L;ADval5[i]= ATD0DR5L;ADval6[i]= ATD0DR6L;ADval7[i]= ATD0DR7L;        
    }
    for(m=0;m<10;m++)      
    {
        ADv0+=ADval0[m];ADv1+=ADval1[m];ADv2+=ADval2[m];ADv3+=ADval3[m];
        ADv4+=ADval4[m];ADv5+=ADval5[m];ADv6+=ADval6[m];ADv7+=ADval7[m];
    }
        
        ADvv0=ADv0*0.1179;
        ADvv1=ADv1*0.1250;        
        ADvv2=ADv2*0.1250;        
        ADvv3=ADv3*0.0988;
        ADvv4=ADv4*0.1000;        
        ADvv5=ADv5*0.0910;
        ADvv6=ADv6*0.1231;        
        ADvv7=ADv7*0.1221;  
      
        if(ADvv0>AD_deadline||ADvv1>AD_deadline||ADvv2>AD_deadline||ADvv3>AD_deadline||ADvv4>AD_deadline||ADvv5>AD_deadline||ADvv6>AD_deadline||ADvv7>AD_deadline)
             x_work=1;
        else x_work=0;
        if(ADvv0<=65&&ADvv1<=15&&ADvv2<=15&&ADvv3<=15&&ADvv4<=15&&ADvv5<=15&&ADvv6<=15&&ADvv7<=15)
            zero=0;
        else zero=1;
        AD_mix[0]= ADvv0*10+1;
        AD_mix[1]= ADvv1*10+2;
        AD_mix[2]= ADvv2*10+3;
        AD_mix[3]= ADvv3*10+4;
        AD_mix[4]= ADvv4*10+5;
        AD_mix[5]= ADvv5*10+6;
        AD_mix[6]= ADvv6*10+7;
        AD_mix[7]= ADvv7*10+8;
        for(k=0;k<=7;k++)
        {
          for(j=k+1;j<=7;j++)
          {
             if(AD_mix[k]<AD_mix[j])
             {
                 JiaoHuan=AD_mix[k];
                 AD_mix[k]=AD_mix[j];
                 AD_mix[j]=JiaoHuan;
             }
          }
        }
        AD_Mux_Num0 = AD_mix[0]%10;
        AD_Mux_Num1 = AD_mix[1]%10;
        AD_Mux_Num2 = AD_mix[2]%10;
        adnum1=AD_mix[0]/10;
        adnum2=AD_mix[1]/10;
        adsum=adnum1+adnum2;
        bili=sum_adv/adsum;
        adnum1*=bili;
        adnum2*=bili;
        if((AD_mix[0]/10-AD_mix[1]/10)==0)
           M_flag=2;
        if((AD_mix[1]/10-AD_mix[2]/10)==0)
           M_flag=1;      
        ADNum_sum = AD_Mux_Num0 + AD_Mux_Num1;
        adcha=adnum1-adnum2;
}
//----------------绝对值-------------------//
float ads(float y)
{
    if(y<0)  y=-y;
    return y;
}
//---------------偏差计算------------------//
void  Car_position()
{  
    if(x_work&&!(M_flag==1)&&!(M_flag==2))
    {
        switch(ADNum_sum)
        {
          case 3://1,2号传感器的值最大
                 if(AD_Mux_Num0==1)
                   x=-(adcha*30/Cha_zhi_M+90); //m1差值是固定
                 else  if(AD_Mux_Num0==2)
                   x=-(90-adcha*30/4/Cha_zhi_M);
                 b=x;
                 z_flag=0;
                 break;
          case 5:
                 if(AD_Mux_Num0==2)
                   x=-(adcha/2*30/Cha_zhi_M+60);
                 else  if(AD_Mux_Num0==3)
                   x=-(60-adcha/2*30/Cha_zhi_M); //确定车的位置
                 b=x;
                 z_flag=0;
                 break;
          case 7:
                 if(AD_Mux_Num0==3)
                   x=-(adcha/2*30/Cha_zhi_M+30);
                 else   if(AD_Mux_Num0==4)
                   x=-(30-adcha/2*30/Cha_zhi_M);
                 b=x;
                 z_flag=1;
                 break;
          case 9:
                 if(AD_Mux_Num0==4)
                   x=-(adcha/2*30/Cha_zhi_M);
                 else  if(AD_Mux_Num0==5)
                   x=adcha/2*30/Cha_zhi_M;
                 b=x;
                 z_flag=1;
                 break;
          case 11:
                 if(AD_Mux_Num0==5)
                   x=(30-(adcha)/2*30/Cha_zhi_M);
                 else  if(AD_Mux_Num0==6)
                   x=(adcha/2*30/Cha_zhi_M+30);
                 b=x;
                 z_flag=1;
                 break;
          case 13:
                 if(AD_Mux_Num0==6)
                   x=(60-adcha/2*30/Cha_zhi_M);
                 else  if(AD_Mux_Num0==7)
                   x=(adcha/2*30/Cha_zhi_M+60);
                 b=x;
                 z_flag=0;
                 break;
          case 15:
                 if(AD_Mux_Num0==7)
                   x=(90-adcha*30/3/Cha_zhi_M);
                 else  if(AD_Mux_Num0==8)
                   x=(adcha*30/Cha_zhi_M+90);        
                 b=x;
                 z_flag=0;
                 break;
         default:break;
         }
   }
   else   
   {
       x=b;
       M_flag=0;
   }
   tiaobian=ads(x-leter_x);                 //偏差跳变计算
   leter_x=x;
}
作者: 943294069    时间: 2011-10-3 16:34
//------------------道路分析-----------------//
void j_line()
{   
    if(tiaobian<6)                          //稳定赛道
    {
      wandaojs+=pulse_counter;              //累加编码器脉冲
      if((wandaojs-wendingganraojs)>500)    //跳变干扰排除
        wdganraojs=0;
    }
    else
    {                                       //不稳定次数累加
      wdganraojs++;
      wendingganraojs=wandaojs;
      if(wdganraojs>4)
      {
         wandaojs=0;
         wdganraojs=0;
      }
    }

////////////////////////////////////////   
    if(ads(x)<80)               //直道判断
    {
      zhidao_js+=pulse_counter;              //直道脉冲累加
      if((zhidao_js-zdwendingganrao_js)>300)  //直道跳变排除
        zdganrao_js=0;
    }
    else                                    //直道不稳定累加
    {
      zdganrao_js++;
      zdwendingganrao_js=zhidao_js;
      if(zdganrao_js>4)      
      {
        zhidao_js=0;
        zdganrao_js=0;
      }
    }
///////////////////////////////////////////     
    if(ads(x)>=80&&ads(x)<220)
    {   
      wandao_js+=pulse_counter;              //累加编码器脉冲
      if((wandao_js-wendingganrao_js)>300)    //跳变干扰排除
        wdganrao_js=0;  
    }
    else
    {                                       //不稳定次数累加
      wdganrao_js++;
      wendingganrao_js=wandao_js;
      if(wdganrao_js>4)      
      {
        wandao_js=0;
        wdganrao_js=0;
      }
    }
///////////////////////////////////////////
    if(ads(x)>=220)               //直道判断
    {
      chujie_js+=pulse_counter;              //直道脉冲累加
      if((chujie_js-chujieganrao_js)>300)  //直道跳变排除
        cjganrao_js=0;
    }
    else                                    //直道不稳定累加
    {
      cjganrao_js++;
      chujieganrao_js=chujie_js;
      if(cjganrao_js>4)      
      {
        chujie_js=0;
        cjganrao_js=0;
      }
    }     
}
//-----------------刹车-------------------------//
void  if_Break()
{   
    Break=0;                                      //正反转标志
   
    if( (zhidao_js>15000&&ads(x)>=80)||(wandao_js>20000&&(ads(x)>=220||ads(x)<80))||(chujie_js>20000&&ads(x)<65))      
        ruwan=1;
    else ruwan=0;
   
    if(ruwan==1||shache>0)//弯道刹车判断
    {
      PWMDTY67 =600;
      PWMDTY23 =0;
      if(pulse_counter>65)                        //刹车判断
        shache++;
      else  shache=0;
      if(shache==1)                             //计数清零
      {
          ruwan=0;
          wandaojs=0;
          wendingganraojs=0;
          wdganraojs=0;
          zhidao_js=0;zdganrao_js=0;zdwendingganrao_js=0;
          wandao_js=0;wdganrao_js=0;wendingganrao_js=0;
          chujie_js=0;cjganrao_js=0;chujieganrao_js=0;
      }
      Break=1;                                    //刹车标志为1
    }
}
//--------------舵机的角度计算-----------------//
void DJ_angle(void)
{   
    angle_DAT=Mid+(x)*D_kp+(x-last_x)*D_kd;//舵机的角度控制
    pre_angle=angle_DAT;            //存储当前的车的坐标和舵机的拐角,以便下次作为前次的值来使用
    if(angle_DAT>4610)
      angle_DAT=4610;
    else if(angle_DAT<2410)
      angle_DAT=2410;
    last_x=x;
}
//---------------拨码开关--------------------------//
void   speedset()
{
    DDRB=0x00;
    if     (!(PORTB&0x01))
    {  
        D_kp=1.85; D_kd=40;  max_speed=70;
    }
    else if(!(PORTB&0x02))
    {
        D_kp=1.9; D_kd=40;  max_speed=80;
    }
    else if(!(PORTB&0x04))
    {
        D_kp=1.95; D_kd=70;  max_speed=90;
    }
    else if(!(PORTB&0x08))
    {
        D_kp=2.3; D_kd=100;  max_speed=95;
    }
    else if(!(PORTB&0x10))
    {   
        D_kp=2.1; D_kd=65;  max_speed=100;
    }
    else if(!(PORTB&0x20))
    {   
        D_kp=2.1; D_kd=105;  max_speed=130;
    }
    else if(!(PORTB&0x40))
    {   
        D_kp=2.1; D_kd=110;  max_speed=135;
    }
     else if(!(PORTB&0x80))
    {   D_kp=2.1; D_kd=120;  max_speed=140;
        
    }  
}
//-----------------结构体-----------------//
void   PID_Init()
{
    sPID.ideal_speed = 0 ;        //速度设定值,自己定的,会随着程序的执行有不同的变化,这是一个变的值。
    sPID.v_FeedBack = 0 ;  //速度反馈值这是由编码器里测出来的。  
    sPID.v_PreError = 0 ;   //前一次,速度误差,ideal_speed - vi_FeedBack:就是设定速度和真实速度的差
    sPID.v_PreDerror = 0 ;   //前一次,速度误差之差,d_error-PreDerror;设定速度和真实速度的差是所谓的误差,将前一次误差和这一次误差相差就是误差之差
    sPID.v_Kp = KP;
    sPID.v_Ki = KI;
    sPID.v_Kd = KD;            
    sPID.Moto_Out = 0; //电机控制输出值//占空比的设定,初始为0
}
/*-------PID系数设置------*/
void  setPID(void)
{
   
        sPID.v_Kp=5;
        sPID.v_Ki=0.01;
        sPID.v_Kd=0;
   
}
//-----------------电机PID----------------//
float PID_Control(PID *pp )
{  
   signed long  error1,error2,error3;//error是预定的速度和返回速度之差,d_error是偏差的偏差
   
   pp->v_FeedBack= pulse_counter;
  
   if(wandaojs>10000)                           //稳定赛道加速
   {
      if(wdjiasu<21)                            //递增
        wdjiasu+=3;
   }                          
   else
      wdjiasu=0;                                //否则为0
   pp->ideal_speed=max_speed+wdjiasu;
   error1 = (signed long)(pp->ideal_speed - pp->v_FeedBack); // 当前偏差计算   
   ERROR1 = error1;
   error2 = error1 - pp->v_PreError;//速度的偏差的偏差
   error3 = error2 - pp->v_PreDerror;//这一次偏差的差和前一次偏差的差的差
   pp->v_PreError = error1; //存储当前偏差        
   pp->v_PreDerror = error2;//存储偏差的偏差
   setPID();
   
      pp->Moto_Out+=(signed long)((pp ->v_Kp*error2)+pp->v_Ki*error1+ pp->v_Kd*error3);
   
   if( pp->Moto_Out > speed_MAX )
      pp->Moto_Out = speed_MAX;
   if( pp->Moto_Out < speed_MIN )
      pp->Moto_Out = speed_MIN;
   return (pp->Moto_Out);// 返回预调节占空比
}
//------------------执行-----------------//
void GO()
{   
   
   PWMDTY01 = angle_DAT;
    if(Break==0)
    {  
        PWM_OUT  = PID_Control(&sPID);
        PWMDTY23 = PWM_OUT;
        PWMDTY67 = 0;
    }
}
//-----------------停车条件---------------//
void  ifstop()
{
    char j=0;
    DDRA=0x00;
    if(!(PORTA&&0x01))
    {           
        if(stopcount<100)
          first=1;
        else  stop();      
    }   if(first==1)
      stopcount++;
    if(stopcount>1000)
      stopcount=1000;
}
//-------------------停车-----------------//
void   stop()
{
    for(;;)
    {
        GetVal();
        Car_position();
        j_line();
        DJ_angle();
        PWMDTY01=angle_DAT;
        PWMDTY23=0;
        PWMDTY67=6*pulse_counter;
        if(pulse_counter==0)
        while(1)
        {
            PWMDTY23=0;   
            PWMDTY67=0;
        }
    }
  
}

#pragma CODE_SEG NON_BANKED
void interrupt 7 RTI_interrupt(void)//做什么用的
{
    CRGFLG |= 0x60;  
    pulse_counter = PACNT*0.8;//n/360*18/76*16.7,,,,0.8
    PACNT = 0;
    s_count++;
}
作者: aspwen    时间: 2011-10-4 23:18
谢谢,参考共享。想请问一下,你的电磁是怎样排布的
作者: song513    时间: 2011-10-7 19:45
顶,有魄力!
作者: wgl404    时间: 2011-10-8 15:02
这个必须顶!
作者: Oner    时间: 2011-10-8 22:04
受教了。
作者: Oner    时间: 2011-10-8 22:04
受教了。                                       1
作者: O.Z.N    时间: 2011-10-13 22:31
好东西
作者: 我の小车    时间: 2011-10-14 11:06
受领了。。
作者: 寂寞坏孩子9856    时间: 2011-10-20 01:58
好人啊
作者: xiaoG    时间: 2011-11-9 21:47
诅咒看此贴不回的人做出车来跑不了
作者: walkwithrain    时间: 2011-11-15 00:04
这个必须有!
作者: chen19910528    时间: 2011-11-15 11:10
支持楼主一下!!
作者: 刘世林    时间: 2011-11-15 13:26

作者: sutaihua    时间: 2011-11-21 21:46
我喜欢。。。
作者: 2009KONE    时间: 2011-11-21 22:53
楼主好人啊
作者: 天才大空翼    时间: 2011-11-21 23:02
不错,可惜,电磁车要直立了。
作者: 断翅at雄鹰    时间: 2011-11-23 14:29
看了
作者: jyh728    时间: 2011-11-24 00:38
怎么感觉不全啊 。。。顺便说一下传感器布局啊
作者: 664626482    时间: 2011-11-24 23:09
给力,你们用的电机驱动是什么
作者: 943294069    时间: 2012-1-17 15:24
注意:这程序是第六届电磁组的,速度2.9m/s
作者: 943294069    时间: 2012-1-17 15:27
fasong变量为蓝牙使用,发送数据回上位机
作者: 943294069    时间: 2012-1-17 15:29
传感器8个 ,一排
作者: 王谦623    时间: 2012-2-14 09:49
非常感谢!
作者: 春风    时间: 2012-2-18 14:16
这样也行呀。
作者: 有-木-友    时间: 2012-2-18 14:25
好孩子!
作者: zhu_xuekui    时间: 2012-2-21 01:38
牛  牛   牛  
作者: linping9656    时间: 2012-2-27 21:34
哎,我都不会
作者: pcj2011    时间: 2012-2-27 22:27
mark
作者: 圣徒    时间: 2012-3-10 09:46
好人好人啊太感谢了
作者: 影之歌    时间: 2012-3-11 01:11
好强大~!顶~!
作者: sincelh    时间: 2012-3-25 00:23
呃  看一下
作者: f43    时间: 2012-3-25 08:58
谢谢楼主啊
作者: 涛涛    时间: 2012-3-25 09:35
谢谢楼主!!

作者: 涛涛    时间: 2012-3-25 09:35
  哈哈哈~~~
作者: zhangwenqiang    时间: 2012-7-1 13:49
MARK
作者: 精忠报国    时间: 2012-7-18 11:23
受领了。。
作者: 张路军    时间: 2012-8-29 21:25
好东西!楼主好人!
作者: HAWX    时间: 2014-11-30 20:41
太感谢了

作者: 13862773798    时间: 2016-3-3 20:04
谢!!!




欢迎光临 智能车制作 (http://dns.znczz.com/) Powered by Discuz! X3.2