1. PID控制器基础实现
任务目标
实现一个位置式PID控制器,包含比例(P)、积分(I)、微分(D)三个环节的计算,并通过阶跃响应测试验证控制器行为。给定目标值与反馈值,控制器输出控制量,使系统输出逐步逼近目标值。
核心实现
#include <stdio.h>
#include <stdlib.h>
typedef struct {
double kp; // 比例系数
double ki; // 积分系数
double kd; // 微分系数
double integral; // 积分累计值
double prev_error; // 上一次误差
double dt; // 采样周期(秒)
} PIDController;
// 初始化PID参数
void pid_init(PIDController *pid, double kp, double ki, double kd, double dt) {
pid->kp = kp;
pid->ki = ki;
pid->kd = kd;
pid->integral = 0.0;
pid->prev_error = 0.0;
pid->dt = dt;
}
// 位置式PID计算
double pid_compute(PIDController *pid, double setpoint, double measurement) {
double error = setpoint - measurement;
// 积分项(累加)
pid->integral += error * pid->dt;
// 微分项(后向差分)
double derivative = (error - pid->prev_error) / pid->dt;
// 更新上一次误差
pid->prev_error = error;
// 输出 = P + I + D
return pid->kp * error + pid->ki * pid->integral + pid->kd * derivative;
}
// 模拟一阶惯性系统(被控对象):G(s) = 1 / (s + 1)
double plant_update(double output, double state, double dt) {
// 离散化:state_new = state + dt * (-state + output)
return state + dt * (-state + output);
}
int main() {
PIDController pid;
pid_init(&pid, 2.0, 0.5, 0.1, 0.01);
double setpoint = 1.0; // 目标值(阶跃输入)
double measurement = 0.0; // 当前测量值
double control = 0.0; // 控制器输出
printf("step, measurement, control\n");
for (int i = 0; i < 200; i++) {
control = pid_compute(&pid, setpoint, measurement);
measurement = plant_update(control, measurement, pid.dt);
if (i % 10 == 0) {
printf("%d, %.4f, %.4f\n", i, measurement, control);
}
}
return 0;
}
运行与验证
编译运行:
gcc pid_controller.c -o pid_controller -lm
./pid_controller
预期输出特征:程序输出200步仿真数据,每10步打印一次。观察测量值(measurement)应从0逐步上升并稳定在1.0附近(稳态误差趋近于0),控制量(control)在初始阶段较大,随后逐渐减小并趋于稳定。若P、I、D系数设置合理,系统应在约50~100步内收敛到目标值。
验证方法:将输出数据导入Excel或绘图工具,绘制测量值随时间变化曲线。若曲线呈现上升后收敛于1.0且无明显振荡,则PID参数整定正确,控制器实现无误。可尝试修改kp、ki、kd值观察响应变化:增大kp加快响应但可能引起振荡,增大ki消除稳态误差但可能超调,增大kd抑制振荡但过大可能导致系统不稳定。
关键说明
- 位置式PID直接对误差进行比例、积分、微分运算,输出为控制量,适用于执行机构不带积分特性的系统。
- 积分项采用累加方式,需注意积分饱和问题(本案例未做限幅,实际工程中应增加积分限幅或抗积分饱和处理)。
- 微分项采用后向差分法,对噪声敏感,实际应用中常配合低通滤波使用。
- 被控对象使用一阶惯性系统模拟,用于验证控制器闭环响应,实际工程中替换为真实系统模型或硬件接口即可。