2

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

 1 year ago
source link: https://www.cnblogs.com/xiaohuzaixue/p/17438460.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

电赛控制类PID算法实现 - xioahuhu - 博客园

一、什么是PID

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

2776504-20230528182516619-1960146850.png
  • PID控制系统原理框图
    2776504-20230528172026934-1045701598.png

二、PID离散化

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

2776504-20230528183149610-589703979.png

离散化后最终得到位置式PID:

2776504-20230528183321351-1791896745.png

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


1. 位置式PID公式

2776504-20230528182807088-289161166.png

2. 增量式PID公式

2776504-20230528182858566-1918676559.png

三、两种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); //返回计算值
}

__EOF__


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK