带详细注释的代码
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
/*-------- 模拟参数配置 --------*/
#define SIM_INERTIA 0.2f // 电机惯性系数(0-1,值越大响应越慢)
#define SIM_LATENCY 3 // 转速测量延迟周期数(模拟传感器延迟)
/*-------- PID控制器结构体 --------*/
typedef struct {
float Kp; // 比例系数
float Ki; // 积分系数
float Kd; // 微分系数
float e1; // 前一次误差
float e2; // 前两次误差
int32_t target; // 目标转速(RPM)
int32_t output; // 控制输出(PWM占空比,0-10000对应0%-100%)
} PID_Controller;
/*-------- 电机模拟器结构体 --------*/
typedef struct {
float real_speed; // 电机真实转速(带惯性)
int32_t display_speed; // 显示给控制器的转速(带测量延迟)
int32_t speed_buffer[SIM_LATENCY]; // 延迟缓冲区
} Motor_Simulator;
/*-------- PID初始化函数 --------
* 参数:pid控制器指针,PID系数
* 功能:初始化PID参数和状态*/
void PID_Init(PID_Controller *pid, float Kp, float Ki, float Kd) {
pid->Kp = Kp;
pid->Ki = Ki;
pid->Kd = Kd;
pid->e1 = pid->e2 = 0;
pid->target = 0;
pid->output = 0; // 初始输出从0开始
}
/*-------- PID更新函数 --------
* 参数:pid控制器指针,当前测量转速
* 功能:计算增量式PID输出并更新状态*/
void PID_Update(PID_Controller *pid, int32_t current) {
// 计算当前误差
float e0 = pid->target - current;
// 增量式PID公式:
// Δu = Kp*(e0-e1) + Ki*e0 + Kd*(e0-2e1+e2)
float delta = pid->Kp * (e0 - pid->e1)
+ pid->Ki * e0
+ pid->Kd * (e0 - 2*pid->e1 + pid->e2);
// 更新输出并限幅
pid->output += (int32_t)delta;
pid->output = (pid->output > 10000) ? 10000 :
(pid->output < 0) ? 0 : pid->output;
// 更新误差历史
pid->e2 = pid->e1;
pid->e1 = e0;
}
/*-------- 电机模拟器更新函数 --------
* 参数:电机指针,当前PWM占空比
* 功能:模拟电机动态响应和测量延迟*/
void Motor_Update(Motor_Simulator *motor, int32_t pwm) {
/* 物理模型计算 */
// 推力计算:PWM占空比转换为推力(300RPM/周期为最大推力)
float thrust = pwm / 10000.0f * 300.0f;
// 摩擦力计算:与当前速度成正比(0.1为摩擦系数)
float friction = motor->real_speed * 0.1f;
// 速度变化 = (推力 - 摩擦力) * 惯性系数
motor->real_speed += (thrust - friction) * (1.0f - SIM_INERTIA);
// 添加随机噪声(模拟测量误差)
motor->real_speed += (rand() % 21 - 10); // ±10RPM噪声
if(motor->real_speed < 0) motor->real_speed = 0;
/* 测量延迟模拟 */
// 更新环形缓冲区
for(int i = SIM_LATENCY-1; i > 0; i--)
motor->speed_buffer[i] = motor->speed_buffer[i-1];
motor->speed_buffer[0] = (int32_t)motor->real_speed;
// 显示延迟后的转速
motor->display_speed = motor->speed_buffer[SIM_LATENCY-1];
}
int main() {
PID_Controller pid;
Motor_Simulator motor = {0};
srand(time(NULL)); // 初始化随机数生成器
// 初始化PID参数(可调参数)
PID_Init(&pid, 2.8f, 0.15f, 0.5f);
pid.target = 2000; // 设置目标转速为2000RPM
// 打印表格头部
printf("时间(s)┃目标转速┃实际转速┃显示转速┃PWM输出┃误差\n");
printf("═══════╋════════╋════════╋════════╋═══════╋═════\n");
// 主控制循环(每周期模拟100ms)
for(int t = 0; t < 300; t++) {
// 1. 获取带延迟的测量转速
int32_t measured = motor.display_speed;
// 2. 更新PID控制器
PID_Update(&pid, measured);
// 3. 更新电机状态
Motor_Update(&motor, pid.output);
// 每秒打印一次状态
if(t % 10 == 0) {
printf("%6.1f ┃%7d ┃%7d ┃%7d ┃%5d%% ┃%4d\n",
t/10.0, // 当前时间(秒)
pid.target, // 目标转速
(int)motor.real_speed, // 真实转速
measured, // 控制器接收的转速
pid.output/100, // PWM百分比
pid.target - measured // 当前误差
);
}
}
return 0;
}
基于增量PID的电机速度控制仿真
一、项目概述
本代码实现了一个完整的直流电机速度控制仿真系统,采用增量式PID算法,具有以下特点:
- 纯软件仿真:无需硬件即可运行测试
- 真实物理模拟:包含惯性、摩擦力和测量延迟
- 可视化输出:实时显示控制状态
- 参数可调:方便测试不同控制效果
二、核心原理
1. 增量式PID控制
与传统位置式PID不同,增量式PID计算的是控制量的增量:
Δu = Kp*(e₀-e₁) + Ki*e₀ + Kd*(e₀-2e₁+e₂)
优势:
- 避免积分饱和
- 更易实现无扰切换
- 对计算误差不敏感
2. 电机物理模型
速度变化 = (推力 - 摩擦力) × 惯性系数
- 推力计算:
thrust = PWM% × 300 RPM/周期
- 摩擦力:
friction = 0.1 × 当前速度
- 平衡条件:当thrust = friction时达到稳态
3. 测量延迟模拟
使用环形缓冲区实现3个周期的测量延迟,更真实反映实际系统中的传感器响应。
三、关键代码解析
1. PID控制器结构
typedef struct {
float Kp, Ki, Kd; // PID系数
float e1, e2; // 历史误差
int32_t target; // 目标值
int32_t output; // 控制输出
} PID_Controller;
2. 电机模拟器
void Motor_Update(...) {
// 物理模型计算
float thrust = ...; // 与PWM成正比
float friction = ...; // 与速度成正比
// 延迟缓冲区处理
...
}
四、使用示例
输出示例(目标2000RPM)
时间(s)┃目标转速┃实际转速┃显示转速┃PWM输出┃误差
0.0 ┃ 2000 ┃ 0 ┃ 0 ┃ 0% ┃2000
1.0 ┃ 2000 ┃ 183 ┃ 0 ┃ 43% ┃2000
2.0 ┃ 2000 ┃ 612 ┃ 183 ┃ 67% ┃1817
3.0 ┃ 2000 ┃ 1235 ┃ 612 ┃ 78% ┃1388
4.0 ┃ 2000 ┃ 1859 ┃ 1235 ┃ 68% ┃ 765
5.0 ┃ 2000 ┃ 1982 ┃ 1859 ┃ 65% ┃ 141
6.0 ┃ 2000 ┃ 2016 ┃ 1982 ┃ 66% ┃ 18
参数调节建议
- 超调过大:增大Kd或减小Kp
- 收敛慢:增大Kp或Ki
- 稳态误差:适当增大Ki
五、扩展方向
- 添加图形界面:使用Matplotlib实时显示曲线
- 实现自动整定:加入Ziegler-Nichols自整定算法
- 支持多种电机:修改物理模型参数
- 添加负载扰动:模拟突加负载场景
六、总结
本代码为学习PID控制算法提供了完整的仿真环境,通过调整参数可以直观观察控制效果差异。实际硬件应用中需注意:
- 测量周期的精确性
- 传感器噪声处理
- 执行器输出限制
- 系统安全保护机制