/*******************************************************************************
* 积分分离的增量型PID控制算法C语言实现
*******************************************************************************
* 在普通PID控制中,引入积分环节的目的,主要是为了消除静差,提高控制精度。
* 但是在启动、结束或大幅度增减设定时,短时间内系统输出有很大的偏差,会造成PID运算的积分积累,
* 导致控制量超过执行机构可能允许的最大动作范围对应极限控制量,
* 从而引起较大的超调,甚至是震荡,这是绝对不允许的。
* 为了克服这一问题,引入了积分分离的概念,其基本思路是
* 当被控量与设定值偏差较大时,取消积分作用;
* 当被控量接近给定值时,引入积分控制,以消除静差,提高精度。
*******************************************************************************
* PID增量表达式:∆u(k) = Kp*(error(k) - error(k-1)) + Ki*(error(k)) + Kd*(error(k) - 2*error(k-1) + error(k-2))
* 最终的结果 = u(k) + ∆u(k)
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
struct _pid
{
float SetSpeed; // 定义设定值
float ActualSpeed; // 定义实际值
float error; // 定义偏差值
float error_next1; // 定义偏差值(k-1)
float error_next2; // 定义偏差值(k-2)
float Kp,Ki,Kd; // 定义比例、积分、微分系数
}pid; // 定义了一个结构名为_pid的结构变量pid
void PID_init()
{
printf("PID_init begin\n");
pid.SetSpeed = 0.0;
pid.ActualSpeed = 0.0;
pid.error = 0.0;
pid.error_next2 = 0.0;
pid.error_next1 = 0.0;
pid.Kp = 0.2; // 需要自行整定
pid.Ki = 0.04; //
pid.Kd = 0.2; //
printf("PID_init end\n");
}
float PID_realize(float speed)
{
float incrementSpeed;
float index;
pid.SetSpeed = speed;
pid.error = pid.SetSpeed - pid.ActualSpeed;
if(fabsf(pid.error) > 200) // abs()是用来求int型的绝对值,
// fabsf()是用来求float型的绝对值,
// fabs()是用来求double型的绝对值,要用库math.h
{
index = 0;
}
else
{
index = 1;
}
incrementSpeed = pid.Kp*(pid.error - pid.error_next1) + index*pid.Ki*pid.error + pid.Kd*(pid.error - 2*pid.error_next1 + pid.error_next2);
pid.ActualSpeed += incrementSpeed;
pid.error_next2 = pid.error_next1;
pid.error_next1 = pid.error;
return pid.ActualSpeed;
}
int main()
{
PID_init();
int count = 0;
while(count < 1000) // 运行1000次,得到1000个数据
{
float speed = PID_realize(200.0);
printf("%f\n",speed);
count++;
}
return 0;
}