PID(proportion integration differentiation)其实就是指比例,积分,微分控制。目前来说,PID控制算法是一种使用非常广泛的算法。比在平衡车、无人机等方面的应用。PID算法是简单,又能体现反馈思想的控制算法,可谓经典中的经典。
PID控制流程简单,通过误差信号控制被测量,并且控制器本身就是比例、积分、微分3个环节的加和。通过这三个的组合可有效地纠正被控制对象的偏差,从而使其达到一个稳定的状态。
PID控制规律:
kp——比例增益,kp与比例度成倒数关系;
T——积分时间常数;
TD——微分时间常数;
u(x)——PID控制器的输出信号;
e(t)——给定值r(t)与测量值之差。
1、PID控制其实是对偏差的控制。
2、如果偏差为0,则比例环节不起作用,只有存在偏差时,比例环节才起作用。
3、积分环节主要是来消除静差,所谓静差,就是系统稳定后输出值和和设定值之间的差值,积分环节实际上就是偏差累计的过程,把累计的误差加到原来的所有系统上以抵消系统的静差。
4、微分信号则反应了偏差信号的变换规律,或者说变化趋势,根据偏差信号变化趋势来经行超前调节,增加系统的快速性。
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 \r\n");
while(1)
{
key = KEY_Scan(0);
while(count<1000)
{
float speed = PID_realize(200.0);
printf("%f \r\r",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 begin\r\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 \r\n");
}
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
emsp; 一部分数据,可以看到,逐渐的趋近了200,设定值200,但是这个过程相对比较长。
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 \r\n");
while(1)
{
key = KEY_Scan(0);
while(count<1000)
{
float speed = PID_realize(200.0);
printf("%f \r\r",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 begin\r\n");
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 \r\n");
}
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
基本思路是,当被控制量与设定的值偏差较大时,取消积分作用,当被控量接近给定值时,引入积分控制,以消除静差,提高精度。
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 \r\n");
while(1)
{
key = KEY_Scan(0);
while(count<1000)
{
float speed = PID_realize(200.0);
printf("%f \r\r",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 begin\r\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.04; //积分
pid.Kd =0.2; //微分
printf(“PID_init end \r\n”);
}
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;
}
通过测试,系统数据达到199所用的时间为原来的1/2,系统的快速性得到提升。
工程文件链接https://download.csdn.net/download/weixin_45488643/12647479有需要自己下载吧。