This repository has been archived on 2026-04-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
hero/Mecanum Wheel moving project 1/Core/Src/PID.c
2025-11-27 20:08:38 +08:00

119 lines
3.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "PID.h"
#include "main.h"
#include "M3508.h"
#include <math.h> // 用于isnan、isinf函数
#include "Remote.h"
#include "CToC.h"
/**
* @brief PID控制器初始化
*/
void PID_Init(PID_Controller_t* pid, float kp, float ki, float kd, float integral_limit, float output_limit)
{
pid->kp = kp;
pid->ki = ki;
pid->kd = kd;
pid->integral = 0.0f;
pid->prev_error = 0.0f;
pid->output = 0.0f;
pid->integral_limit = integral_limit;
pid->output_limit = output_limit;
}
/**
* @brief PID计算函数带保护
*/
float PID_Calculate(PID_Controller_t* pid, float error, float dt)
{
// 检查输入参数有效性
if (dt <= 0.0f || dt > 1.0f) {
dt = 0.01f; // 使用默认时间间隔
}
// 检查error是否为NaN或无穷大
if (isnan(error) || isinf(error)) {
error = 0.0f;
}
// 比例项
float proportional = pid->kp * error;
// 检查proportional是否为NaN
if (isnan(proportional) || isinf(proportional)) {
proportional = 0.0f;
}
// 积分项(带限幅)
pid->integral += error * dt;
if (pid->integral > pid->integral_limit) {
pid->integral = pid->integral_limit;
} else if (pid->integral < -pid->integral_limit) {
pid->integral = -pid->integral_limit;
}
float integral = pid->ki * pid->integral;
// 检查integral是否为NaN
if (isnan(integral) || isinf(integral)) {
integral = 0.0f;
pid->integral = 0.0f;
}
// 微分项添加dt保护
float derivative = 0.0f;
if (dt > 0.001f) { // 确保dt足够大避免除以很小的数
derivative = pid->kd * (error - pid->prev_error) / dt;
}
// 检查derivative是否为NaN
if (isnan(derivative) || isinf(derivative)) {
derivative = 0.0f;
}
pid->prev_error = error;
// 计算总输出
pid->output = proportional + integral + derivative;
// 检查总输出是否为NaN
if (isnan(pid->output) || isinf(pid->output)) {
pid->output = 0.0f;
// 重置PID状态
pid->integral = 0.0f;
pid->prev_error = 0.0f;
}
// 输出限幅
if (pid->output > pid->output_limit) {
pid->output = pid->output_limit;
} else if (pid->output < -pid->output_limit) {
pid->output = -pid->output_limit;
}
return pid->output;
}
/**
* @brief 初始化所有电机的PID控制器
*/
void Motor_PID_Init(void)
{
// PID参数需要根据实际电机调试
float speed_kp = 400.0f; // 速度环比例系数
float speed_ki = 0.05f; // 速度环积分系数
float speed_kd = 300.0f; // 速度环微分系数
for (int i = 0; i < 4; i++) {
PID_Init(&motor_controller[i].speed_pid, speed_kp, speed_ki, speed_kd, 3000.0f, 3000.0f);
}
}
/*
*函数简介:位置式PID清理
*参数说明:位置式PID参数结构体
*返回类型:无
*备注:重置PID内部状态用于模式切换或异常情况
*/
void PID_PositionClean(PID_Controller_t* pid)
{
pid->integral = 0.0f; // 清理积分项,防止积分饱和
pid->prev_error = 0.0f; // 清理上一次误差,防止微分冲击
pid->output = 0.0f; // 清理输出值
}