一、PID控制器的实现(C语言实现)

PID控制(比例-积分-微分控制)是一种广泛应用于工业自动化和过程控制中的反馈控制策略。它通过调节控制量,使系统的输出尽可能地接近期望的目标值(设定值)。PID控制器基于系统误差(即目标值与实际输出之间的差)进行调整,以达到系统稳定性和期望的性能。

1、PID控制器传递函数

PID控制器的连续时间传递函数为:

位置式PID计算的是当前控制量和目标值之间的差值,控制信号基于误差量的绝对值来进行调整。增量式PID则根据误差的变化量来计算控制量的增量,控制信号的调整是基于上一时刻控制量的变化量。增量式PID由于其计算效率高、动态响应快、适应性强等优势,更常被应用于如电机驱动、DC-DC变换器、功率因数校正等需要快速响应和高效控制的系统中。

2、离散化实现(差分方程)

PID离散化过程中,积分项使用后向欧拉离散化,微分项使用前向差分离散化。此部分内容可自行查阅资料。

位置式PID控制器的差分方程

增量式PID控制器的差分方程

式中,e[k]为当前误差(参考值 - 反馈值),u[k]为控制器总输出。

在嵌入式(STM32DSP)中,可以根据上述差分方程编写离散化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控制器可直接移植到嵌入式(STM32DSP28335)中!!!后续将在B站(电赛海盗船)更新视频,展示嵌入式中实际效果。

Logo

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

更多推荐