找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6648|回复: 3
收起左侧

搞平衡车热身之PID试验程序

[复制链接]
ID:80436 发表于 2015-5-21 22:41 | 显示全部楼层 |阅读模式
先上代码
#include <string.h>   
#include <stdio.h>
#include "RobotLib.h"
int flag=0;
/*====================================================================================================   
    PID Function   

    The PID  function is used in mainly   
    control applications. PIDCalc performs one iteration of the PID   
    algorithm.  

    While the PID function works, main is just a dummy program showing   
    a typical usage.   
=====================================================================================================*/  

typedef struct PID {  

        int  SetPoint;           //  ???? Desired Value  

        int  Proportion;         //  ???? Proportional Const   
        int  Integral;           //  ???? Integral Const   
        int  Derivative;         //  ???? Derivative Const  

        int  LastError;          //  Error[-1]   
        int  PrevError;          //  Error[-2]   
        int  SumError;           //  Sums of Errors  

} PID;  

/*====================================================================================================   
   位置式PID

=====================================================================================================*/  

int PIDCalc( PID *pp, int NextPoint )   
{   
    int  dError,   
         Error;  

        Error = pp->SetPoint -  NextPoint;          // ??   
        pp->SumError += Error;                      // ??   
        dError = pp->LastError - pp->PrevError;     // ????   
        pp->PrevError = pp->LastError;   
        pp->LastError = Error;   
        return (pp->Proportion * Error              // ???   
            +   pp->Integral * pp->SumError         // ???   
            +   pp->Derivative * dError             // ???   
        );   
}  


/*====================================================================================================
   增量式PID
=====================================================================================================*/
double PIDCalc_delt( PID *pp, double NextPoint )
{
        double dError, Error;
        Error = pp->SetPoint - NextPoint;       // ?????  ???????????
        dError= pp->Proportion * Error  +  pp->Integral * pp->LastError  +  pp->Derivative * pp->PrevError;
        pp->PrevError = pp->LastError;          // ?????  ????????????
        pp->LastError = Error;
        return (dError);
}
/*====================================================================================================   
   Initialize PID Structure   
=====================================================================================================*/  

void PIDInit (PID *pp)   
{   
    memset ( pp,0,sizeof(PID));   
}  

/*====================================================================================================   
    Main Program   
=====================================================================================================*/  


/*#define N 12
int sensor (void)                    //  Dummy Sensor Function   
{   
  char count,i,j;
  int ad_data[N];
  int sum=0;
  int advalue=0;
  int temp=0;
  for (count = 0; count<=N; count++)
  {
  ad_data[count]=AI(1);
  }
  for (j=0;j<N-1;j++)
  {
  for (i=0;i<N-1;i++)
  {
  if (ad_data[i]>ad_data[i+1])
  {
    temp=ad_data[i];
    ad_data[i]=ad_data[i+1];
    ad_data[i+1]=temp;
  }
  }
  }
  for (count=0;count<N;count++)
  {
  sum=ad_data[count];
  }
  advalue=sum/(N-2);
  return advalue;

}  */
void Run(int left_speed,int right_speed)
{
SetMoto(0,-left_speed);
SetMoto(1,-right_speed);
}

int speed=0;
void actuator(int rDelta)            //  Dummy Actuator Function   
{
     speed=rDelta;
     if(flag==1)
     {
if (speed>100)
{
speed=100;
}
else if(speed<-100)
{
speed=-100;
}
}
else if(flag==2)
{
   speed=rDelta/3;
if (speed>50)
{
speed=50;
}
else if(speed<-50)
{
speed=-50;
}
    else if (speed<10 && speed>0)//电机死区
    {
      speed=8;
    }
    else if (speed>-10 && speed<0) //电机死区
    {
      speed=-8;
    }
}
Run(speed,speed);

}  
#define N 12
int sensor1(void)//均值滤波。最简单的一种
{
  int buffer[N];
  int count=0;
  int sum=0;
  int ad=0;
  for (count=0;count<N;count++)
  {
  buffer[count]=AI(1);
  wait(0.001);
  }
  for (count=0;count<N;count++)
  {
  sum+=buffer[count];
  }
  ad=sum/N;
  return ad;
}

void main(void)   
{   
    PID      setPID;                   //  PID Control Structure   
    int      OutPut;                   //  PID Response (Output)   
    int      InPut;                    //  PID Feedback (Input)  

    PIDInit ( &setPID );                  //  Initialize Structure   
    setPID.Proportion = 20;              //  Set PID Coefficients   
    setPID.Integral   = 0.5;   
    setPID.Derivative = 0.5;   
    setPID.SetPoint   = 150;            //  Set PID Setpoint  
    while(0)
    {
      printf("%d\n", sensor1());
    //  wait(0.2);
    }
    while(1)
     {                          //  Mock Up of PID Processing  
        InPut = sensor1();                //  Read Input
         if(InPut-setPID.SetPoint>80 ||InPut-setPID.SetPoint<-80)//分段式PID.距离远,比例系数大点
         {
            flag=1;
     PIDInit ( &setPID );                  //  Initialize Structure   
    setPID.Proportion = 20;              //  Set PID Coefficients   
    setPID.Integral   = 0.5;   
    setPID.Derivative = 0.5;   
   setPID.SetPoint   = 150;            //  Set PID Setpoint  

         }
         else if (InPut-setPID.SetPoint<20 ||InPut-setPID.SetPoint<-20)//距离近,PID参数相应小一点
         {
         flag=2;
         PIDInit ( &setPID );                  //  Initialize Structure   
       setPID.Proportion = 2;              //  Set PID Coefficients   
       setPID.Integral   = 0.3;   
       setPID.Derivative = 0;   
       setPID.SetPoint   = 150;            //  Set PID Setpoint  
         }

      //  wait(0.05);  
        OutPut = PIDCalc ( &setPID,InPut );   //  Perform PID Interation   
        actuator ( OutPut );              //  Effect Needed Changes   
        printf("InPut=%d\n,Output=%d\n",InPut,OutPut );
       // wait(0.1);
      }   
}



效果还不错(手机录像不行,改天补上视频)。(控制器性能强大。主频144M RAM 1M ROM 2M)基本没有超调,两个震荡周期就稳定了。设定的目标是150(测距传感器返回值).小车在距离150很远时是100%的速度跑的。快接近150时,速度马上降得很快。第一次到150时,会超前1cm左右,然后往回跑,逼近150时,刚好停下,趋于稳定。传感器在149 150 151左右跳动。小车也在不断微调。反应非常灵敏。最后基本上小车在+-1mm左右晃或者不动的状态。

我后面试过不用PID来做位置控制。也是可以,效果不好就是。震荡比较剧烈。需要调整6 7表周期才会停到目标点。没有PID那么迅速 灵敏。
简单许多,代码如下,非常简单。
distance=sensor1();
   NeedSpeed=distance-SetPoint;

   printf("distance=%d\n,NeedSpeed=%d\n",distance,NeedSpeed );
  Run(NeedSpeed,NeedSpeed);



回复

使用道具 举报

ID:113448 发表于 2016-4-15 23:41 | 显示全部楼层
回复

使用道具 举报

ID:113448 发表于 2016-7-23 08:55 | 显示全部楼层
厉害
回复

使用道具 举报

ID:98249 发表于 2019-4-19 09:30 | 显示全部楼层
楼主思路清晰,功能完善学习了
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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