智能车制作

 找回密码
 注册

扫一扫,访问微社区

查看: 3258|回复: 6
打印 上一主题 下一主题

直立车在平衡点不移动抖动的厉害是神马情况???

[复制链接]

5

主题

18

帖子

0

精华

高级会员

Rank: 4

积分
820
威望
400
贡献
244
兑换币
244
注册时间
2014-7-25
在线时间
88 小时
毕业学校
陕西理工学院
跳转到指定楼层
1#
发表于 2015-4-7 19:51:19 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include <hidef.h>      /* common defines and macros */
#include "derivative.h"      /* derivative-specific definitions */
#include <math.h>
#define ushort unsigned short
#define uchar unsigned char

#define Motor_Dead 6
#define Motor_MAX 200
#define Motor_MIN -200

#define Gyrozhili 1329
#define Qjzhili   975
#define Zjmax     1605
#define Zjmin     675



#define  Bu_Chang   3//2//时间补偿函数
#define  Ji_Fen    20 //25//积分时间  
#define  gyro_pl 0.36////陀螺仪的比例系数
#define  qingjiao_pl 0.193//0.27//加速度计的比例系数


float gyro_pi_out,     // 陀螺仪的比例输出
      qingjiao_pi_out,  //加速度计的比例输出
      gyro_single,
      gyro_single_out,
      Gyro_Data,
      qingjiao,A,tuoluoyi;         //角度输出

float angle_P=10.5,   //直立PD控制参数P
      angle_D=1,    //直立PD控制参数D

      speed_P=0.6,
      speed_I=1;



int Left_Speed=0,
    Right_Speed=0,  
     count_flag=0,  
     temp_left=0,
     temp_right=0,
     now_speed_L=0,     //左测速
     now_speed_R=0,      //右测速
     Cal_Left_Speed=0,
     Cal_Right_Speed=0,
     Speed_Old=0,
     Speed_New=0,
     Speed_Keep=0,
     Speed_EPT=0,     //速度预期
     tly[20], tly1[6],
     jsd[20],AD0_MAX,AD0_MIN,AD1_MIN,AD1_MAX
    ;

/****************************************/
//作用:设置单片机总线频率
//输入:无
//输出:无
/****************************************/
void SetBusCLK_80M(void)
{
   CLKSEL_PLLSEL=0;//禁止锁相环时钟  
   PLLCTL_PLLON=1;//锁相环电路使能
   SYNR=0xc0|0x09;//VCO_CLOCK=2*16M*(1+SYNR)/(1+REFDV)=128MHZ;
   REFDV=0x80|0x01;//计算SYNR=10;REFDV=1;
   POSTDIV=0x00;//设置fpll=fvoc;
   //以下公式是进行计算
   //fvco=2*16M*(1+SYNR)/(1+REFDV)OSTDIV=0x00的时候,fpll=fvco
   //不等于零时fpll=fco/(2*POSTDIV);fbus=fpll/2;,
   _asm(nop);
   _asm(nop);
   while(!(CRGFLG_LOCK==1));//时钟频率已锁定,锁相环频率锁定
   CLKSEL_PLLSEL=1;//使能锁相环时钟  
}
/****************************************/
//作用:配置PWM模块
//输入:无
//输出:无
/****************************************/
void PWM_Init(void)
{
     PWME=0x00;//关闭所有PWM波通道
     PWMPRCLK=0x00;  //CLOCK A B总线不分频=80M
     PWMSCLA=20;   //对CLOCKA时钟40分频,SA的频率为2M
     PWMSCLB=20;   //对CLOCKB时钟40分频,SB的频率为2M


//*********第一路BTN7970的PWM波**********//左轮前进   
     PWME_PWME1=0;//
     PWMCTL_CON01=1; //01通道级联使用
     PWMPOL_PPOL1=1; //高电平翻转
     PWMCLK_PCLK1=1; //选择SA作为时钟源SA=2M
     PWMCAE_CAE1=0;  //居中对齐
     PWMPER01=200;   //频率为10KHz
     PWMDTY01=0;//
     PWMCNT01=0x00;  //01级联后计数器清零
     PWME_PWME1=1 ;  //使能01通道


//*************第二路BTN7960的PWM波************ //左轮后退就是反转
     PWME_PWME3=0;//
     PWMCTL_CON23=1; //23通道级联使用
     PWMPOL_PPOL3=1; //高电平翻转
     PWMCLK_PCLK3=1; //选择SA作为时钟源SA=2M
     PWMCAE_CAE3=0;  //居中对齐
     PWMPER23=200;   //频率为10KZ
     PWMDTY23=0;    //
     PWMCNT23=0x00;  //23级联后计数器清零
     PWME_PWME3=1;//使能23通道


//**************第三路BTN7960的PWM波************//右轮前进
     PWME_PWME5=0;//
     PWMCTL_CON45=1; //45通道级联使用
     PWMPOL_PPOL5=1; //高电平翻转
     PWMCLK_PCLK5=1; //选择SA作为时钟源SA=2M
     PWMCAE_CAE5=0;  //居中对齐
     PWMPER45=200;   //频率为10khz
     PWMDTY45=0;    //
     PWMCNT45=0x00;  //45级联后计数器清零
     PWME_PWME5=1;//使能45通道


//*************第四路BTN7960的PWM波***************//右轮后退就是反转
     PWME_PWME7=0;//
     PWMCTL_CON67=1; //45通道级联使用
     PWMPOL_PPOL7=1; //高电平翻转
     PWMCLK_PCLK7=1; //选择SA作为时钟源SA=2M
     PWMCAE_CAE7=0;  //居中对齐
     PWMPER67=200;   //频率为10KHZ
     PWMDTY67=0;    //
     PWMCNT67=0x00;  //45级联后计数器清零
     PWME_PWME7=1;//使能67通道

}

/****************************************/
//作用:配置AD寄存器
//输入:无
//输出:无
/****************************************/
void ATD0_Init (void)
{
   ATD0DIEN=0x00; //禁止数字输入功能
   ATD0CTL0=0x06;
   ATD0CTL1=0xC0; //分辨率为12位,采样前放电
   ATD0CTL2=0x40; //快速清除标志位,禁止外部触发,禁止中断
   ATD0CTL3=0xB0; //转换结果右对齐,每个序列转换6个通道。非FIF0
   ATD0CTL4=0x1F; //采样时间4个周期,prs=19
   ATD0CTL5=0x30; //对通道0-3连续采样,同时启动转换  
}
/*void inittly() //对陀螺仪输出进行滤波使其平滑
{
    int i,j,temp;
    for(i = 0;i<6;i++) //0,1,2,3,4,5
    {        

     while(!ATD0STAT2_CCF0);
       tly1[i]=ATD0DR0;

    }
    for(i = 0;i<6;i++)  //对数组中的6个结果进行比较大小
    {
      for(j = i+1;j<6;j++)
      {
           if(tly1[i]<tly1[j])  //按从大到小的顺序
           {
               temp = tly1[j];
               tly1[j] = tly1[i];
               tly1[i] = temp;
            }
        }
      }

      tuoluoyi = (tly1[1]+tly1[2]+tly1[3]+tly1[4])/4;//取较大的四个值求平均值

  }*/

/****************************************/
//作用:配置定时器模块寄存器
//输入:无
//输出:无
/****************************************/
void PIT_Init(void)//我们这一块定义1ms的采样周期,对于外部的AD采样周期
{
    PITCFLMT=0x00;//禁止定时器模块
    PITCE_PCE0=1;//使能定时器0
    PITMUX=0x00;//使用16位定时器,使用微定时基准0计数
    PITMTLD0=80-1;//装入8位微定时初值,这个数值由我们定时时间决定
    PITLD0=1000-1;//装入16位计数的初值,这个数值也由我们的定时时间决定
//定时时间的计算。我们假设定时时间为t=(PITMTLD0+1)*(PITLD0+1)*(1/fbus)
//总线时钟我们在锁相环中已经设定好好了, fbus=80Mhz
    PITINTE=0x01;//使能定时器通道0中断  
    PITCFLMT=0x80;//使能定时器模块
}


void TimInit (void)
{

PACTL=0X00;
PACNT=0X0000;//设置脉冲累加器初值
PACTL_PAEN=1;
}


void IO_Init(void)
{
DDRM=0XFF;
PTM_PTM0=1;
   PTM_PTM1=0;

}

/*************************************************************/
/*                        AD采集函数                         */
/*************************************************************/
         void ADcaiji(void)
         {
          int i,j;
    for(i = 0;i<=19;i++)
    {        
     while(!ATD0STAT2_CCF0);
       tly[i]=ATD0DR0;
    }
    AD0_MAX=tly[0];//对AD0_MAX附初值
AD0_MIN=tly[0];//对AD0_MIN附初值
  for(i = 0;i<=19;i++)  {

        if(tly[i]>AD0_MAX)
   {
    AD0_MAX=tly[i] ; //将数组AD0中的值与初值比较找出最大值
   }
else if (tly[i]<AD0_MIN)
   {
    AD0_MIN=tly[i] ; //将数组AD0中的值与初值比较找出最小值
   }

}
     Gyro_Data =(tly[0]+tly[1]+tly[2]+tly[3]+tly[4]+tly[5]+tly[6]+tly[7]+tly[8]+tly[9]+tly[10]+tly[11]+tly[12]+tly[13]+tly[14]+tly[15]+tly[16]+tly[17]+tly[18]+tly[19]-AD0_MAX-AD0_MIN)/18;


     for(j =0;j<=19;j++)
    {        
       while(!ATD0STAT2_CCF1);
       jsd[j]=ATD0DR1;
    }

       AD1_MAX=jsd[0];
AD1_MIN=jsd[0];
for(j =0;j<=19;j++) {

        if(jsd[j]>AD1_MAX)
  {
    AD1_MAX=jsd[j] ; //将数组AD0中的值与初值比较找出最大值
  }
else if (jsd[j]<AD1_MIN)
  {
   AD1_MIN=jsd[j] ; //将数组AD0中的值与初值比较找出最小值
  }
    }
           qingjiao = (jsd[0]+jsd[1]+jsd[2]+jsd[3]+jsd[4]+jsd[5]+jsd[6]+jsd[7]+jsd[8]+jsd[9]+jsd[10]+jsd[11]+jsd[12]+jsd[13]+jsd[14]+jsd[15]+jsd[16]+jsd[17]+jsd[18]+jsd[19]-AD1_MAX-AD1_MIN)/18;//采集20次取平均值
         


        }

           void kalman_update(void)
{
         
          float Q =1,R =60;
          static float RealData = 0,RealData_P = 0;
          float NowData = 0,NowData_P = 0;
          float Kg = 0,accelerometer_angle=0;
         


   accelerometer_angle=qingjiao;  // 请注意 这个赋值,为了输出,任何时刻仅有一个



    NowData = RealData ;
    NowData_P = sqrt(Q*Q+RealData_P*RealData_P);
    Kg = sqrt(NowData_P*NowData_P/(NowData_P*NowData_P+R*R));
    RealData = NowData + Kg*(accelerometer_angle - NowData);
    RealData_P = sqrt((1-Kg)*NowData_P*NowData_P);

    qingjiao =  RealData;         




}         


        /*************************************************************/
/*    将陀螺仪得到角速度数值和加速度计的得到的数值进行拟合   */
/*************************************************************/   
void gyroscope_angle(void)
{    float qingjiao_bu_out;



  qingjiao_pi_out=(qingjiao-Qjzhili)*qingjiao_pl;//加速度计比例输出

// gyro_pi_out=(-Gyro_Data+tuoluoyi)*gyro_pl;//陀螺仪比例输出
  gyro_pi_out=(-Gyro_Data+Gyrozhili)*gyro_pl;//陀螺仪比例输出

  gyro_single=gyro_single_out;

  qingjiao_bu_out=(qingjiao_pi_out-gyro_single)/Bu_Chang;//时间补偿

  gyro_single_out+=(qingjiao_bu_out+gyro_pi_out)/Ji_Fen;//角度输出
  gyro_single_out=gyro_single_out;


}  
          void kalman_update1(void)
{
         
          float Q =1,R =1;
          static float RealData = 0,RealData_P = 0;
          float NowData = 0,NowData_P = 0;
          float Kg = 0,accelerometer_angle=0;
         


   accelerometer_angle=gyro_single_out;  // 请注意 这个赋值,为了输出,任何时刻仅有一个



    NowData = RealData ;
    NowData_P = sqrt(Q*Q+RealData_P*RealData_P);
    Kg = sqrt(NowData_P*NowData_P/(NowData_P*NowData_P+R*R));
    RealData = NowData + Kg*(accelerometer_angle - NowData);
    RealData_P = sqrt((1-Kg)*NowData_P*NowData_P);

    gyro_single_out=  RealData;         




}         
               
       
       
/*************************************************************/
/*                     直立PD                                 */
/*************************************************************/         
void CarAngleAdjust(void)
{
      int nLeft=0,
      nRight=0,
      nSpeed=0,
      nP=0,
      nD=0;
      nP=(-gyro_single_out)*angle_P;
      nD=(-gyro_pi_out)*angle_D;
      nSpeed=nP+nD;
      Left_Speed=nSpeed+Cal_Left_Speed;
      Right_Speed=nSpeed+Cal_Right_Speed;
       if((gyro_single_out>45)||(gyro_single_out<-45))
  {
        Left_Speed=0;
        Right_Speed=0;


  }  
}

/*************************************************************/
/*                  测速函数                                 */
/*************************************************************/
void CarSpeedGet(void)
{
    PTM_PTM0=~PTM_PTM0;
    PTM_PTM1=~PTM_PTM1;
    if(PTM_PTM0==1)
    {
      if(Left_Speed>0)
      temp_left+=PACNT;
      else
       temp_left-=PACNT;

    }
    else
    {
     if(Right_Speed>0)
      temp_right+=PACNT;
      else
       temp_right-=PACNT;

    }





    PACNT=0;
    count_flag++;

}

/*************************************************************/
/*                  速度PI控制                              */
/*************************************************************/
  void CarMotorSpeedAdjust(void)
  {
// float SpeedOut;
// float EK0,EK1;

   int nLeftSpeed=0,
        nRightSpeed=0,
        nP=0,
        nI=0,
        nSpeed=0,
        nSpeedChang=0;


        nLeftSpeed=(int)now_speed_L;
         nRightSpeed=(int)now_speed_R;
         nSpeed=(nLeftSpeed+nRightSpeed)/2;
          nSpeedChang=Speed_EPT-nSpeed;
          nP=nSpeedChang*speed_P;
          nI=nSpeedChang*speed_I;
           Speed_Old=Speed_New;
          Speed_Keep-=nI;
          Speed_New=(Speed_Keep>>3)-nP;




           if(Speed_Keep>Motor_MAX)
              Speed_Keep=Motor_MAX;
          if(Speed_Keep<Motor_MIN)
              Speed_Keep=Motor_MIN;


  }

void CarMotorSpeedOutCal(void)
{
     int nSpeedOut;

     nSpeedOut=Speed_New-Speed_Old;

     nSpeedOut=nSpeedOut*(count_flag/20)+Speed_Old;

     Cal_Left_Speed=Cal_Right_Speed=nSpeedOut;


}


/*************************************************************/
/*                  电机控制                                  */
/*************************************************************/
  void SetMotor(void)
   {
      int T_Left_Speed,T_Right_Speed;
      T_Left_Speed=Left_Speed;
      T_Right_Speed=Right_Speed;


      if(T_Left_Speed>=0)
      {
        T_Left_Speed+=Motor_Dead;
        if( T_Left_Speed>Motor_MAX)
            T_Left_Speed=Motor_MAX;
        PWMDTY45=T_Left_Speed;
        PWMDTY67=0;
      }


      else
      {
         T_Left_Speed=-T_Left_Speed;
         T_Left_Speed+=Motor_Dead;
         if( T_Left_Speed>Motor_MAX)
         T_Left_Speed=Motor_MAX;
         PWMDTY67=T_Left_Speed;
         PWMDTY45=0;
      }


      if(T_Right_Speed>=0)
      {
        T_Right_Speed+=Motor_Dead;
        if( T_Right_Speed>Motor_MAX)
            T_Right_Speed=Motor_MAX;
        PWMDTY01=T_Right_Speed;
        PWMDTY23=0;
      }


      else
      {
         T_Right_Speed=- T_Right_Speed;
         T_Right_Speed+=Motor_Dead;
         if( T_Right_Speed>Motor_MAX)
         T_Right_Speed=Motor_MAX;
        PWMDTY23=T_Right_Speed;
        PWMDTY01=0;
      }
}
/*************************************************************/
/*              初始化                                        */
/*************************************************************/
  void DeviceInit()
{
    SetBusCLK_80M();
    COPCTL&=0XF8;
    ATD0_Init();
   // inittly();
    PWM_Init();
    PIT_Init();
    TimInit();
    IO_Init();

}  
void delay (int x)
{
int m,n;
for (m=x;m>0;m--)
for (n=200;n>0;n--);
}


/*************************************************************/
/*               主函数                                       */
/*************************************************************/
void main(void)
{

  DisableInterrupts; //关闭所有中断
  DeviceInit();//所有装置初始化
  delay (1000);
  EnableInterrupts;
  for(;;)
  {
    _FEED_COP(); /* feeds the dog */
  } /* loop forever */

}
/*************************************************************/
/*          1M定时中断                                          */
/*************************************************************/
#pragma CODE_SEG __NEAR_SEG NON_BANKED //指示该程序在不分页区
void interrupt 66 PIT0(void)
{  


   ADcaiji();//获取传感器信息
kalman_update();

   gyroscope_angle();//角度滤波
            kalman_update1();
   CarAngleAdjust();//角度调整

   CarSpeedGet();
  if(count_flag==20)
   {
     now_speed_L=temp_left;
    now_speed_R=temp_right;
    temp_left=0;
    temp_right=0;
     CarMotorSpeedAdjust();
     count_flag=0;

  }

   CarMotorSpeedOutCal();

  SetMotor();
       //直立电机控制
   PITTF_PTF0=1;//清中断标志位
}

跪求大神!!!!




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

5

主题

18

帖子

0

精华

高级会员

Rank: 4

积分
820
威望
400
贡献
244
兑换币
244
注册时间
2014-7-25
在线时间
88 小时
毕业学校
陕西理工学院
2#
 楼主| 发表于 2015-4-7 20:03:17 | 只看该作者
人工置顶~
回复 支持 反对

使用道具 举报

5

主题

18

帖子

0

精华

高级会员

Rank: 4

积分
820
威望
400
贡献
244
兑换币
244
注册时间
2014-7-25
在线时间
88 小时
毕业学校
陕西理工学院
3#
 楼主| 发表于 2015-4-7 20:03:56 | 只看该作者
真心求助~
回复 支持 反对

使用道具 举报

18

主题

301

帖子

0

精华

常驻嘉宾

Rank: 8Rank: 8

积分
4946
威望
2641
贡献
1439
兑换币
1337
注册时间
2014-8-31
在线时间
433 小时
毕业学校
河海大学
4#
发表于 2015-4-7 23:05:56 | 只看该作者
你的死区电压貌似有点儿大,,,
回复 支持 反对

使用道具 举报

1

主题

12

帖子

0

精华

高级会员

Rank: 4

积分
570
威望
300
贡献
164
兑换币
166
注册时间
2014-11-11
在线时间
53 小时
毕业学校
黑龙江科技大学
5#
发表于 2015-4-8 09:30:43 | 只看该作者
你看看融合后的角度不变时  变化幅度是多少
回复 支持 反对

使用道具 举报

2

主题

78

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2299
威望
1069
贡献
626
兑换币
703
注册时间
2014-12-30
在线时间
302 小时
毕业学校
武大
6#
发表于 2015-5-9 15:14:31 | 只看该作者
你们解决了吗
回复 支持 反对

使用道具 举报

1

主题

57

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
243
威望
141
贡献
64
兑换币
77
注册时间
2016-7-25
在线时间
19 小时
7#
发表于 2017-3-19 17:19:01 | 只看该作者
把P值调大
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-9-20 22:34 , Processed in 0.235615 second(s), 28 queries , Gzip On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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