C语言实现PID控制基本(三)——设定偏差范围

增加了稳定调节范围,在范围内与范围外变化率不同

#include
#include

struct _pid
{
    float SetSpeed;            //定义设定值
    float ActualSpeed;         //定义实际值
    float err;                 //定义偏差值
    float err_last;            //定义上一个偏差值
    float Kp,Ki,Kd;            //定义比例、积分、微分系数
    float voltage;             //定义电压值(控制执行器的变量)
    float integral;            //定义积分值
    float umax;
    float umin;
}pid;
void PID_init()
{
    printf("PID_init begin \n");
    pid.SetSpeed=0.0;
    pid.ActualSpeed=0.0;
    pid.err=0.0;
    pid.err_last=0.0;
    pid.voltage=0.0;
    pid.integral=0.0;
    pid.Kp=0.2;
    pid.Ki=0.1;       //这里加大了积分环节的值
    pid.Kd=0.2;
    pid.umax=400;
    pid.umin=-200;
    printf("PID_init end \n");
}
float PID_realize(float speed)
{
    int index;                      //声明系数
    pid.SetSpeed=speed;
    pid.err=pid.SetSpeed-pid.ActualSpeed;
   //偏差  =   设定 - 实际速度
   if(pid.ActualSpeed>pid.umax)     //实际速度大于设定最大值        超调  此时需要回调
    {

       if(abs(pid.err)>200)                //偏差绝对值大于200     当差距过大
        {
            index=0;                         //系数 0           直接将积分因式*0
        }
	   else                                //偏差绝对值不大于200    差距不大时
	   {
            index=1;                         //系数1            积分因式*1
            if(pid.err<0)                       //偏差小于0     
            {
              pid.integral+=pid.err;              //  如当integral累计到500  实际速度大于设定速度 需要减速 err是-10  那 500-10=490  积分减少
            }  
        }
    } //  因为实际速度大于设定最大值  设定最大值应该不比设定速度小 所以偏差err一定不大于0  存在等于0  当存在等于0时  不累加
   else if(pid.ActualSpeed<pid.umin) //实际速度小于设定最小值   未达到波动范围最小值 需要加速
   {
        if(abs(pid.err)>200)           //积分分离过程  偏差绝对值大于200    err 小于0   所以实际速度小于0  偏差大于200  偏差过大
        {
            index=0;                     //系数0    直接回0 
        
		}
		else                           //              偏差绝对值不大于200  err 小于0  偏差不大
		{
            index=1;                     //系数1    积分系数不变
            if(pid.err>0)                //偏差大于0  实际速度小于设定速度  
            {
            pid.integral+=pid.err;          // 积分加   如  需要加速   积分500+偏差10
            }
        }
    }
   else                             //实际速度不大于设定值最大值也不小于设定最小值    在某一近似范围
   {
        if(abs(pid.err)>200)           //积分分离过程    偏差绝对值大于200(范围数)  偏差过大
        {
            index=0;                       //系数0   积分回0
        }
		else                           //    偏差绝对值不大于200    实际速度跟设定速度偏差不大         
		{
            index=1;                       //系数1
            pid.integral+=pid.err;         //累加偏差   正常计算
        }
    }

    pid.voltage=pid.Kp*pid.err+index*pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last);
    //电压值(预计是给电机电压转换值)=  比例系数 * 偏差   +   系数0(1)*积分系数*积分值   +   微分*(偏差-上一次偏差)
    pid.err_last=pid.err;
    pid.ActualSpeed=pid.voltage*1.0;
	//预计是电压换算速度公式  1.0为某因式
    return pid.ActualSpeed;
}

void baocun(float speed)
{
	FILE *fp;
	fp=fopen("d:\\prcline.txt","a");  //保存数据 这里用a不用w,w会消除上一次数据保存本次数据
    fprintf(fp,"%f\n",speed);
	fclose(fp);
}

int main()
{   	
	int count=0;
    PID_init();
 
    while(count<1000)
    {
        float speed=PID_realize(200.0);
        printf("%f\n",speed);
        baocun(speed);
        count++;
    }
		system("pause");
    return 0;
}

C语言实现PID控制基本(三)——设定偏差范围_第1张图片

C语言实现PID控制基本(三)——设定偏差范围_第2张图片

你可能感兴趣的:(C语言,注释详解,PID)