电机控制
SV630P 伺服电机驱动器配置上电自动使能
步进电机控制
无刷直流电机控制
PID-C控制示例
BLDC 双环位置控制
RT-Thread中MPU6050使用详解及DMP姿态解算
ICM42688传感器万向节死锁现象
SimpleBGC 代码解读
机械回零策略
使用 STM32F407VET6 进行双电机 FOC 控制方案
FOC电流采集方案总结
本文档使用 MrDoc 发布
-
+
首页
PID-C控制示例
PID-C 库使用指南 GitHub 链接 PID-C 库地址:"https://github.com/geekfactory/PID" (https://github.com/geekfactory/PID) 这是一个用纯 C 语言编写的轻量级 PID 控制器实现,非常适合嵌入式系统使用。 基本使用方法 1. 文件结构 下载库后,主要包含以下文件: - "pid.c" - PID 控制器实现源码 - "pid.h" - 头文件,包含所有函数声明和结构体定义 2. 核心 API 函数 // 初始化 PID 控制器 void pid_init(pid_ctrl_t *pid, float kp, float ki, float kd, float dt); // 设置 PID 参数 void pid_set_parameters(pid_ctrl_t *pid, float kp, float ki, float kd); // 设置输出限幅 void pid_set_limits(pid_ctrl_t *pid, float min, float max); // 执行 PID 计算 float pid_calculate(pid_ctrl_t *pid, float setpoint, float measured); // 重置 PID 控制器(清空积分项等) void pid_reset(pid_ctrl_t *pid); 3. 完整使用示例代码 #include "pid.h" #include <stdio.h> // 定义采样时间(秒) #define DT 0.01f int main() { pid_ctrl_t pid_controller; float setpoint = 100.0f; // 目标值 float measured_value = 0.0f; // 测量值 float output = 0.0f; // PID 输出 // 初始化 PID 控制器:Kp=2.0, Ki=0.5, Kd=0.1, 采样时间=0.01s pid_init(&pid_controller, 2.0f, 0.5f, 0.1f, DT); // 设置输出限幅(例如 PWM 范围 0-255) pid_set_limits(&pid_controller, 0.0f, 255.0f); // 模拟控制循环 for (int i = 0; i < 1000; i++) { // 读取传感器测量值(这里用模拟值代替) measured_value = read_sensor(); // 执行 PID 计算 output = pid_calculate(&pid_controller, setpoint, measured_value); // 将输出应用到执行器 apply_control_signal(output); // 等待一个采样周期 delay(DT * 1000); // 转换为毫秒 } return 0; } // 模拟传感器读取函数 float read_sensor(void) { // 这里应该是实际的传感器读取代码 // 例如:读取编码器、ADC 等 return some_sensor_value; } // 模拟控制信号应用函数 void apply_control_signal(float control_signal) { // 这里应该是实际的控制代码 // 例如:设置 PWM 占空比、控制电机驱动器等 set_pwm_duty_cycle(control_signal); } 4. 在嵌入式系统中的实际应用示例(STM32) #include "pid.h" #include "stm32f1xx_hal.h" #include "encoder.h" // 编码器驱动 #include "motor_driver.h" // 电机驱动 pid_ctrl_t position_pid; TIM_HandleTypeDef *encoder_tim; float target_angle = 0.0f; // PID 控制任务(在定时器中断中调用) void pid_control_task(void) { static uint32_t last_time = 0; uint32_t current_time = HAL_GetTick(); // 确保固定的采样时间(例如 10ms) if (current_time - last_time >= 10) { float dt = (current_time - last_time) / 1000.0f; last_time = current_time; // 读取编码器获取当前位置(度) int32_t encoder_count = __HAL_TIM_GET_COUNTER(encoder_tim); float current_angle = (encoder_count / ENCODER_PPR) * 360.0f; // PID 计算 float pwm_output = pid_calculate(&position_pid, target_angle, current_angle); // 应用控制信号到电机 motor_set_pwm(pwm_output); } } // 初始化函数 void system_init(void) { // 初始化编码器 encoder_tim = &htim2; // 假设使用 TIM2 作为编码器接口 HAL_TIM_Encoder_Start(encoder_tim, TIM_CHANNEL_ALL); // 初始化 PID 控制器 pid_init(&position_pid, 5.0f, 0.1f, 0.05f, 0.01f); // Kp=5, Ki=0.1, Kd=0.05 pid_set_limits(&position_pid, -100.0f, 100.0f); // PWM 限幅 // 设置目标位置 target_angle = 90.0f; // 目标:90度 } 5. 高级功能使用 // 积分抗饱和和微分滤波示例 void advanced_pid_setup(pid_ctrl_t *pid) { // 设置积分限幅防止积分饱和 pid->integral_limit = 50.0f; // 启用微分滤波(减少高频噪声影响) pid->derivative_filter_enabled = 1; pid->derivative_filter_alpha = 0.1f; // 滤波系数 } // 实时调整 PID 参数 void adaptive_pid_control(pid_ctrl_t *pid, float error) { // 根据误差大小自适应调整参数 if (fabs(error) > 10.0f) { // 大误差时使用更强的 P 控制 pid_set_parameters(pid, 8.0f, 0.0f, 0.0f); } else { // 小误差时启用积分和微分 pid_set_parameters(pid, 5.0f, 0.1f, 0.05f); } } 主要特点 1. 轻量级:代码简洁,适合资源受限的嵌入式系统 2. 纯 C 实现:不依赖特定平台或操作系统 3. 可配置:支持输出限幅、积分抗饱和等高级功能 4. 易移植:可以轻松移植到各种微控制器平台 编译说明 将 "pid.c" 和 "pid.h" 添加到你的项目中,在编译时确保包含这两个文件即可。 这个库非常适合在 STM32、ESP32、Arduino 等嵌入式平台上实现精确的 PID 控制。
qingkai
2025年11月23日 11:10
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码