嵌入式中PID控制的实现与验证(开源)
本文介绍了PID控制器的C语言实现方法,包括位置式和增量式两种算法。内容涵盖PID控制原理、离散化差分方程、代码实现(含抗饱和和输出限幅处理)及嵌入式应用示例。通过单相逆变器闭环控制的仿真验证,表明两种PID实现方式均能有效跟踪给定值,控制效果与系统自带PID一致。文章还提供了获取仿真模型的方法,并预告将在后续视频中展示嵌入式实际效果。该PID代码可直接移植到STM32、DSP等嵌入式平台使用。
一、PID控制器的实现(C语言实现)
PID控制(比例-积分-微分控制)是一种广泛应用于工业自动化和过程控制中的反馈控制策略。它通过调节控制量,使系统的输出尽可能地接近期望的目标值(设定值)。PID控制器基于系统误差(即目标值与实际输出之间的差)进行调整,以达到系统稳定性和期望的性能。
1、PID控制器传递函数
PID控制器的连续时间传递函数为:
位置式PID计算的是当前控制量和目标值之间的差值,控制信号基于误差量的绝对值来进行调整。增量式PID则根据误差的变化量来计算控制量的增量,控制信号的调整是基于上一时刻控制量的变化量。增量式PID由于其计算效率高、动态响应快、适应性强等优势,更常被应用于如电机驱动、DC-DC变换器、功率因数校正等需要快速响应和高效控制的系统中。
2、离散化实现(差分方程)
PID离散化过程中,积分项使用后向欧拉离散化,微分项使用前向差分离散化。此部分内容可自行查阅资料。
位置式PID控制器的差分方程
增量式PID控制器的差分方程
式中,e[k]为当前误差(参考值 - 反馈值),u[k]为控制器总输出。
在嵌入式(STM32、DSP)中,可以根据上述差分方程编写离散化PID控制器的C语言代码。
3、PID控制的C语言实现
位置式PID实现代码
#include <math.h>
// PID控制器结构体(位置式)
typedef struct {
// 参数
float Kp; // 比例系数
float Ki; // 积分系数
float Kd; // 微分系数
float Ts; // 采样周期
// 积分限制
float max_integral; // 积分上限
float min_integral; // 积分下限
// 输出限制
float max_output; // 输出上限
float min_output; // 输出下限
// 状态变量
float integral; // 积分累加值
float prev_error; // 上一次误差
} PIDController;
// 初始化PID控制器
void PID_Init(PIDController *pid,
float Kp, float Ki, float Kd,
float Ts,
float max_integral, float min_integral,
float max_output, float min_output)
{
pid->Kp = Kp;
pid->Ki = Ki;
pid->Kd = Kd;
pid->Ts = Ts;
pid->max_integral = max_integral;
pid->min_integral = min_integral;
pid->max_output = max_output;
pid->min_output = min_output;
// 初始化状态
pid->integral = 0.0f;
pid->prev_error = 0.0f;
}
// 执行PID控制计算(位置式)
float PID_Update(PIDController *pid, float setpoint, float measurement) {
// 计算误差
float error = setpoint - measurement;
// 比例项
float P = pid->Kp * error;
// 积分项(带抗饱和)
pid->integral += error * pid->Ts;
// 积分限幅
if (pid->integral > pid->max_integral) {
pid->integral = pid->max_integral;
} else if (pid->integral < pid->min_integral) {
pid->integral = pid->min_integral;
}
float I = pid->Ki * pid->integral;
// 微分项
float derivative = (error - pid->prev_error) / pid->Ts;
float D = pid->Kd * derivative;
// 计算输出
float output = P + I + D;
// 输出限幅
if (output > pid->max_output) {
output = pid->max_output;
} else if (output < pid->min_output) {
output = pid->min_output;
}
// 保存当前误差
pid->prev_error = error;
return output;
}
增量式PID实现代码
// PID控制器结构体(增量式)
typedef struct {
// 参数
float Kp; // 比例系数
float Ki; // 积分系数
float Kd; // 微分系数
float Ts; // 采样周期
// 输出限制
float max_output; // 输出上限
float min_output; // 输出下限
// 状态变量
float prev_error; // 上一次误差
float prev_error2; // 上上次误差
float prev_output; // 上一次输出
} PIDController_Incremental;
// 初始化增量式PID
void PID_Inc_Init(PIDController_Incremental *pid,
float Kp, float Ki, float Kd,
float Ts,
float max_output, float min_output)
{
pid->Kp = Kp;
pid->Ki = Ki;
pid->Kd = Kd;
pid->Ts = Ts;
pid->max_output = max_output;
pid->min_output = min_output;
// 初始化状态
pid->prev_error = 0.0f;
pid->prev_error2 = 0.0f;
pid->prev_output = 0.0f;
}
// 执行增量式PID计算
float PID_Inc_Update(PIDController_Incremental *pid, float setpoint, float measurement) {
// 计算误差
float error = setpoint - measurement;
// 计算增量
float delta_u = pid->Kp * (error - pid->prev_error)
+ pid->Ki * pid->Ts * error
+ pid->Kd * (error - 2*pid->prev_error + pid->prev_error2) / pid->Ts;
// 计算新输出
float output = pid->prev_output + delta_u;
// 输出限幅
if (output > pid->max_output) {
output = pid->max_output;
} else if (output < pid->min_output) {
output = pid->min_output;
}
// 更新状态
pid->prev_error2 = pid->prev_error;
pid->prev_error = error;
pid->prev_output = output;
return output;
}
4、使用示例
位置式PID使用示例
int main() {
PIDController pid;
// 初始化参数
float Kp = 1.0f;
float Ki = 0.1f;
float Kd = 0.01f;
float Ts = 0.01f; // 10ms采样
// 初始化控制器
PID_Init(&pid, Kp, Ki, Kd, Ts,
100.0f, -100.0f, // 积分限幅
10.0f, -10.0f); // 输出限幅
// 控制循环
while(1) {
float setpoint = ...; // 获取设定值
float measurement = ...; // 获取测量值
float output = PID_Update(&pid, setpoint, measurement);
// 应用控制输出
apply_control(output);
delay_ms(Ts * 1000); // 等待下一个采样周期
}
}
增量式PID使用示例
int main() {
PIDController_Incremental pid;
// 初始化参数
float Kp = 1.0f;
float Ki = 0.1f;
float Kd = 0.01f;
float Ts = 0.01f; // 10ms采样
// 初始化控制器
PID_Inc_Init(&pid, Kp, Ki, Kd, Ts,
10.0f, -10.0f); // 输出限幅
// 控制循环
while(1) {
float setpoint = ...; // 获取设定值
float measurement = ...; // 获取测量值
float output = PID_Inc_Update(&pid, setpoint, measurement);
// 应用控制输出
apply_control(output);
delay_ms(Ts * 1000); // 等待下一个采样周期
}
}
二、仿真验证
图1展示了所搭建的单相逆变器闭环控制仿真模型,采用PID控制器闭环调节单相逆变器的有效值。
PID控制器包括系统自带、C语言位置式PID控制器、C语言增量式PID控制器三种形式。在此处应用场景中,三种PID的Kd设置为零。
图 1 仿真模型截图
图2展示了系统自带的位置式PID控制器与C语言位置式PID控制器的仿真结果。两种实现方式在控制效果上完全一致,逆变器输出的电感电流能够精确跟踪给定值。这验证了C语言位置式PID控制器的有效性。
图3展示了C语言增量式PID控制器的仿真结果(与图2略有区别)。逆变器输出的电感电流能够精确跟踪给定值,验证了C语言实现的增量式PID控制器的有效性。
图 2 系统自带位置式PID控制器与C语言位置式PID控制器的仿真结果
图 3 C语言增量式PID控制器的仿真结果
在公众号“电源海盗船"中,回复“PID_Singlephase_inverter”我将发出这个仿真文件,包括单相逆变器闭环控制仿真模型、C语言位置式PID控制器、C语言增量式PID控制器。
C语言PID控制器可直接移植到嵌入式(STM32、DSP28335)中!!!后续将在B站(电赛海盗船)更新视频,展示嵌入式中实际效果。

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)