一、什么是PID

学过自动控制原理的对PID并不陌生,PID控制是对偏差信号e(t)进行比例、积分和微分运算变换后形成的一种控制规律。PID 算法的一般形式:

电赛控制类PID算法实现-LMLPHP

  • PID控制系统原理框图
    电赛控制类PID算法实现-LMLPHP

二、PID离散化

对PID连续系统离散化,从而方便在处理器上实现,PID 离散表示形式:

电赛控制类PID算法实现-LMLPHP

离散化后最终得到位置式PID:
电赛控制类PID算法实现-LMLPHP

u(k)为控制器输出的控制量;(输出)
e(k)为偏差信号,它等于给定量与输出量之差;(输入)
Kp 为比例系数;
Ti 为积分时间常数;
Td 为微分时间常数。


1. 位置式PID公式

电赛控制类PID算法实现-LMLPHP

2. 增量式PID公式

电赛控制类PID算法实现-LMLPHP


三、两种PID的不同点

  • 位置式
    是一种非递推算法,输出值U(k)和执行机构的实际位置一一对应,在不带积分部件的对象中可以很好的应用。但是每次输出均与过去的状态有关,计算量大。
  • 增量式
    输出的是增量,控制增量的值仅与最近3次采样值有关,不需要累计偏差,运算量小,计算错误影响小。但会积分截断效应大,有稳态误差。

四、C语言程序实现

  • pid.c
#include "pid.h"

/*定义PID参数结构体*/
typedef struct _PID
{
    float Kp,Ki,Kd;//比例系数、积分系数、微分系数
    float SetValue,ActualValue;//目标值、实际值
    float Error;//第K次误差
    float LastError;//第K-1次误差
    float PreError;//第K-2次误差
    float SumError;//累计偏差
    float Integral,MaxI;//积分、积分限幅
    float Output,MaxOut;//输出、输出限幅
}PID;

/************************************************
*@brief  :位置式PID控制器
*@param  :PID结构体变量地址,当前实际值
*@retval : 期望输出值
*************************************************/
int32_t Position_PID_Control(PID *pid,float Cur_Value)
{
    pid->Error=pid->SetValue-Cur_Value; //计算偏差      
    pid->SumError +=pid->Error;//累计偏差
    pid->ActualValue=(pid->Kp*(pid->Error-pid->LastError))//比例环节
    +(pid->Ki*pid->SumError)//积分环节
    +(pid->Kd*(pid->Error-pid->LastError);//微分环节
    pid->LastError=pid->Error;
    return ((int32_t)pid->ActualValue); //返回计算值	 
}

/************************************************
*@brief  :速度闭环PID控制
*@param  :PID结构体变量地址,当前实际值
*@retval : 期望输出值
*************************************************/
int32_t Inc_Pid_Ctrl(PID *pid,float Cur_Value)
{
    pid->Error=pid->SetValue-Cur_Value; //计算偏差
    pid->ActualValue +=(pid->Kp*(pid->Error-pid->LastError))//比例环节
    +(pid->Ki*(pid->Error))//积分环节
    +(pid->Kd*(pid->Error-2*pid->LastError+pid->PreError));//微分环节 
    pid->PreError=pid->LastError;//存储偏差,进行下次计算                                                             
    pid->LastError=pid->Error;                                                            	
    return ((int32_t)pid->ActualValue); //返回计算值
}

06-06 01:59