单片机学习小组
直播中

香脆面

11年用户 575经验值
私信 关注

什么是PID控制算法呢?PID控制算法有何作用

什么是PID控制算法呢?PID控制算法有何作用?
PID控制算法有哪几种类型呢?如何对其进行测试?


回帖(1)

李丽波

2022-2-25 09:42:02
1、PID算法简介


  PID(proportion integration differentiation)其实就是指比例,积分,微分控制。目前来说,PID控制算法是一种使用非常广泛的算法。比在平衡车、无人机等方面的应用。PID算法是简单,又能体现反馈思想的控制算法,可谓经典中的经典。
  PID控制流程简单,通过误差信号控制被测量,并且控制器本身就是比例、积分、微分3个环节的加和。通过这三个的组合可有效地纠正被控制对象的偏差,从而使其达到一个稳定的状态。
PID控制规律:



kp——比例增益,kp与比例度成倒数关系;
T——积分时间常数;
TD——微分时间常数;
u(x)——PID控制器的输出信号;
e(t)——给定值r(t)与测量值之差。

1.1、各个环节的作用


1、PID控制其实是对偏差的控制。
2、如果偏差为0,则比例环节不起作用,只有存在偏差时,比例环节才起作用。
3、积分环节主要是来消除静差,所谓静差,就是系统稳定后输出值和和设定值之间的差值,积分环节实际上就是偏差累计的过程,把累计的误差加到原来的所有系统上以抵消系统的静差。
4、微分信号则反应了偏差信号的变换规律,或者说变化趋势,根据偏差信号变化趋势来经行超前调节,增加系统的快速性。

2、位置型PID算法


2.1、离散表达形式:




2.2、位置型代码


核心算法部分。


main函数,按下开发板的KEY0,程序开始测试。

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "pid.h"
#include "usart.h"
#include "key.h"

//PID算法测试
int main(void)
{      
                int count;
          u8 key;
                delay_init();                     //延时函数初始化         
                LED_Init();                          //初始化与LED连接的硬件接口
          KEY_Init();
                PID_init();
          uart_init(9600);
                printf("System begin rn");
               
         
                while(1)
                {
                        key = KEY_Scan(0);
                        while(count<1000)
                        {
                        float speed = PID_realize(200.0);
                        printf("%f rr",speed);
                        count++;
                        }
                        delay_ms(10);
                        if(key == KEY0_PRES)
                        {
                                count =0;
                        }
                }
}


pid.c 文件
  统一初始化变量,尤其是Kp、Ki、Kd3个参数,对于要求的控制效果调试过程中,通过调试这个3个变量直接进行调参。

#include "pid.h"
#include "usart.h"

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 beginrn");
        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 rn");
}

float PID_realize(float speed)
{
        pid.SetSpeed = speed;
        pid.err = pid.SetSpeed - pid.ActualSpeed ;
        pid.integral += pid.err ;
        // 算法基本公式  没有考虑死区问题和上下限
        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;
      
}


pid.h 文件

#ifndef __PID_H
#define __PID_H      

void PID_init(void);
float PID_realize(float speed);

#endif


2.3、测试效果


emsp; 一部分数据,可以看到,逐渐的趋近了200,设定值200,但是这个过程相对比较长。


3、增量型PID算法


3.1 、离散表达式:




3.2 增量型代码


核心算法部分。


main函数代码如下:

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "pid.h"
#include "usart.h"
#include "key.h"

//PID算法测试
int main(void)
{      
                int count;
          u8 key;
                delay_init();                     //延时函数初始化         
                LED_Init();                          //初始化与LED连接的硬件接口
          KEY_Init();
                PID_init();
          uart_init(9600);
                printf("System begin rn");
               
         
                while(1)
                {
                        key = KEY_Scan(0);
                        while(count<1000)
                        {
                        float speed = PID_realize(200.0);
                        printf("%f rr",speed);
                        count++;
                        }
                        delay_ms(10);
                        if(key == KEY0_PRES)
                        {
                                count =0;
                        }
                }
}



pid.c 代码如下:
  统一初始化变量,尤其是Kp、Ki、Kd3个参数,对于要求的控制效果调试过程中,通过调试这个3个变量直接进行调参。

#include "pid.h"
#include "usart.h"
#include
#include

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

void PID_init()
{
        printf("Pid_init beginrn");
        pid.SetSpeed = 0.0;
        pid.ActualSpeed = 0.0;
        pid.err = 0.0;
        pid.err_next = 0.0;
        pid.err_last = 0.0;
        pid.Kp = 0.2;
        pid.Ki = 0.015;
        pid.Kd =0.2;
        printf("PID_init end rn");
}

float PID_realize(float speed)
{
        float incrementSpeed;
        pid.SetSpeed = speed;
        pid.err = pid.SetSpeed - pid.ActualSpeed ;
        // 算法基本公式
        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 ;
}


pid.h 文件如下:

#ifndef __PID_H
#define __PID_H      

void PID_init(void);
float PID_realize(float speed);

#endif


3.3、效果展示




4、积分分离的PID控制算法


  基本思路是,当被控制量与设定的值偏差较大时,取消积分作用,当被控量接近给定值时,引入积分控制,以消除静差,提高精度。


4.1、代码实现


main函数:

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "pid.h"
#include "usart.h"
#include "key.h"

//PID算法测试
int main(void)
{      
                int count;
          u8 key;
                delay_init();                     //延时函数初始化         
                LED_Init();                          //初始化与LED连接的硬件接口
          KEY_Init();
                PID_init();
          uart_init(9600);
                printf("System begin rn");
               
         
                while(1)
                {
                        key = KEY_Scan(0);
                        while(count<1000)
                        {
                        float speed = PID_realize(200.0);
                        printf("%f rr",speed);
                        count++;
                        }
                        delay_ms(10);
                        if(key == KEY0_PRES)
                        {
                                count =0;
                        }
                }
}



pid.c 文件
#include “pid.h”
#include “usart.h”
#include
#include

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 beginrn”);
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.04; //积分
pid.Kd =0.2; //微分
printf(“PID_init end rn”);
}

float PID_realize(float speed)
{
int index;
pid.SetSpeed = speed;
pid.err = pid.SetSpeed - pid.ActualSpeed ;
pid.integral += pid.err ;
// 算法实现过程
if(abs(pid.err)>200) //设定值 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;

}

4.2、效果图


  通过测试,系统数据达到199所用的时间为原来的1/2,系统的快速性得到提升。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分