天天看点

毕设系列 -- 经典单片机控制算法:PID1 简介2 什么是PID4 PID算法实现5 最后

文章目录

  • 1 简介
  • 2 什么是PID
    • 2.1 P:比例
    • 2.2 I:积分
    • 2.3 D:微分
    • 3 PID算法能做什么
  • 4 PID算法实现
    • 4.1 位置式pid算法实现
    • 4.2 增量式PID实现:
    • 4.3 抗积分饱和的PID算法实现
  • 5 最后

1 简介

Hi,大家好,这里是丹成学长,今天向大家讲解经典单片机控制算法:

PID控制算法

大家可用于 课程设计 或 毕业设计

2 什么是PID

2.1 P:比例

成比例地反映控制系统的偏差信号e(t),偏差一旦产生,控制器立即产生控制作用,以减小偏差。当仅有比例控制时系统输出存在稳态误差(Steady-state error)。

P参数越小比例作用越强,动态响应越快,消除误差的能力越强。通常将P参数由大向小调,以能达到最快响应又无超调(或无大的超调)为最佳参数。

2.2 I:积分

为消除静差,提高系统的无差度。积分作用的强弱取决于积分时间常数T,T越大,积分作用越弱,反之则越强。

2.3 D:微分

反映偏差信号的变化趋势,并能在偏差信号变得太大之前,在系统中引入一个有效的早期修正信号,从而加快系统的动作速度,减少调节时间。在微分控制中,控制器的输出与输入误差信号的微分(即误差的变化率)成正比关系。

D越大,微分作用越强,D越小,微分作用越弱。系统调试时通常把D从小往大调,具体参数由试验决定。

毕设系列 -- 经典单片机控制算法:PID1 简介2 什么是PID4 PID算法实现5 最后

3 PID算法能做什么

既然是一种控制算法,PID理所应当的用于单片机对某种器件的控制, 一般控制对象:

  • 温控(烤箱,冰箱等)
  • 电机转速控制
  • 平衡车控制
  • 飞行器控制
  • 压力、温度、流量、液位控制器

平衡车

毕设系列 -- 经典单片机控制算法:PID1 简介2 什么是PID4 PID算法实现5 最后

PID温控

毕设系列 -- 经典单片机控制算法:PID1 简介2 什么是PID4 PID算法实现5 最后

4 PID算法实现

PID算法不止一种,学长把常用的PID算法实现列举给大家

4.1 位置式pid算法实现

struct _pid{
    float SetSpeed;            //定义设定值
    float ActualSpeed;        //定义实际值
    float err;                //定义偏差值
    float err_last;            //定义上一个偏差值
    float Kp,Ki,Kd;            //定义比例、积分、微分系数
    float voltage;          //定义电压值(控制执行器的变量)
    float integral;            //定义积分值
}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.015;
    pid.Kd=0.2;
    printf("PID_init end \n");
}

float PID_realize(float speed){
    pid.SetSpeed=speed;
    pid.err=pid.SetSpeed-pid.ActualSpeed;
    pid.integral+=pid.err;//位置式pid是对积分的持续累加,容易造成积分饱和,是系统过调
    pid.voltage=pid.Kp*pid.err+pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last);
    pid.err_last=pid.err;
    pid.ActualSpeed=pid.voltage*1.0;
    return pid.ActualSpeed;
}
int main(){
    printf("System begin \n");
    PID_init();
    int count=0;
    while(count<1000)
    {
        float speed=PID_realize(200.0);
        printf("%f\n",speed);
        count++;
    }
return 0;
}

           

4.2 增量式PID实现:

#include<stdio.h>
#include<stdlib.h>

struct _pid{
    float SetSpeed;            //定义设定值
    float ActualSpeed;        //定义实际值
    float err;                //定义偏差值
    float err_next;            //定义上一个偏差值
    float err_last;            //定义最上前的偏差值
    float Kp,Ki,Kd;            //定义比例、积分、微分系数
}pid;

void PID_init(){
    pid.SetSpeed=0.0;
    pid.ActualSpeed=0.0;
    pid.err=0.0;
    pid.err_last=0.0;
    pid.err_next=0.0;
    pid.Kp=0.2;
    pid.Ki=0.015;
    pid.Kd=0.2;
}

float PID_realize(float speed){
    pid.SetSpeed=speed;
    pid.err=pid.SetSpeed-pid.ActualSpeed;
    float incrementSpeed=pid.Kp*(pid.err-pid.err_next)+pid.Ki*pid.err+pid.Kd*(pid.err-2*pid.err_next+pid.err_last);//只和前后三次的误差值有关,也方便计算
    pid.ActualSpeed+=incrementSpeed;
    pid.err_last=pid.err_next;
    pid.err_next=pid.err;
    return pid.ActualSpeed;
}

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

4.3 抗积分饱和的PID算法实现

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)      //蓝色标注为积分分离过程
        {
            index=0;
        }else{
            index=1;
            if(pid.err<0)
            {//如果超上限要嘛加负值要嘛就不加了,免得进入饱和区
              pid.integral+=pid.err;          

                    }
        }
    }else if(pid.ActualSpeed<pid.umin){
        if(abs(pid.err)>200)      //积分分离过程
        {
            index=0;
        }else{
            index=1;
            if(pid.err>0)
            {//如果超下限要嘛加正值要嘛就不加了免得进入饱和区
            pid.integral+=pid.err;
            }
        }
    }else{
        if(abs(pid.err)>200)                    //积分分离过程
        {
            index=0;
        }else{
            index=1;
            pid.integral+=pid.err;
        }
    }

    pid.voltage=pid.Kp*pid.err+index*pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last);


    pid.err_last=pid.err;
    pid.ActualSpeed=pid.voltage*1.0;
    return pid.ActualSpeed;
}
           

5 最后

技术解答
毕设帮助:<Q>746876041
           

继续阅读