Files
Motor_v2/Robot_V2/Algorithm/FOC.h
T
cbb 7c4aaa5ee6 feat(FOC): 优化FOC控制算法并修复多个控制环路问题
- 重构cal_Iq_Id函数,移除电角度参数传递,改用预计算的sin/cos值
  以避免重复三角函数计算,提升性能约15-300周期
- 修复角度同步Uq前馈学习中的运动方向判断逻辑,解决反转时的
  震荡问题和正转正常反转震荡的根本原因
- 实现低速缩放因子函数get_mode3_velocity_scale,改进静摩擦
  hunting抑制效果
- 优化电压检测逻辑,将阻塞式ADC读取改为连续模式零等待,
  提升实时性能
- 修复初始化期间电压分母为零的问题,添加下限保护防止P增益
  无穷大
- 实现PID控制器测量微分功能,消除目标阶跃时的微分冲击
- 改进积分抗饱和策略,添加外部饱和泄放功能,优化到位稳定
  性能

perf(Filter): 优化中值滤波算法性能

- 针对ADC_FILTER_SIZE=6的固定场景实现最优排序网络,
  用12次比较替代通用std::nth_element算法,显著提升性能
- 保留通用回退路径处理其他尺寸情况
2026-09-01 02:46:25 +08:00

339 lines
9.6 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.
/**
* @file Algorithm/FOC.h
* @brief 算法模块源文件
* @note 本文件仅补充 Doxygen 文档注释,不改变代码逻辑。
*/
// 函数声明
#ifndef _FOC_H
#define _FOC_H
#include "config.h"
#include "pid.h"
#include <cstdint>
/**
* @brief FOC_Controller 类或结构体
*/
class FOC_Controller {
public:
FOC_Controller();
// 初始化函数
/**
* @brief 初始化对象或模块
* @return u8 返回值
*/
u8 init();
u8 control_mode = 0;
float limit_voltage = 0.0f;
float target_angle = 0.0f;
float target_velocity = 0.0f;
float target_current = 0.0f;
float rt_angle = 0.0f;
float rt_velocity = 0.0f;
float rt_current = 0.0f;
bool over_current = false;
bool voltage_error = false;
bool is_shut_down = false;
bool thermal_shutdown = false; // 过热关机标志
bool emergency_shutdown = false; // 紧急电压跌落关机标志
float voltage_power_supply = 24.0f; // 电源电压
float v_safe = voltage_power_supply / 1.05f;
float duty_a = 0, duty_b = 0, duty_c = 0;
// 快速电压检测相关成员(基于跌幅检测)
float vbus_reference = 0.0f; // 基准电压(峰值检测,跟踪当前额定电压)
float last_vbus_fast = 0.0f; // 上次电压值(快速检测用)
u32 vbus_drop_count = 0; // 电压跌落计数器(防抖)
float cur_loop_p = DEFAULT_current_loop_p;
float vel_loop_p = DEFAULT_vel_loop_p;
float ang_loop_p = DEFAULT_angle_loop_p;
float vel_angloop_p = DEFAULT_vel_angloop_p;
float ang_angloop_p = DEFAULT_angle_angloop_p;
float ang_MIT_p = DEFAULT_angle_MIT_p;
float vel_MIT_p = DEFAULT_vel_MIT_p;
float cur_MIT_p = DEFAULT_current_MIT_p;
/**
* @brief velocity_open_loop 函数
* @return float 返回值
*/
float velocity_open_loop(void);
/**
* @brief angle_control 函数
* @return float 返回值
*/
float angle_control(void);
/**
* @brief angle_control_with_velocity_limit 函数
* @return float 返回值
*/
float angle_control_with_velocity_limit(void);
/**
* @brief MIT_Mode 函数
* @return float 返回值
*/
float MIT_Mode(void);
/**
* @brief velocity_control 函数
* @return float 返回值
*/
float velocity_control(void);
/**
* @brief current_control 函数
* @return float 返回值
*/
float current_control(void);
/**
* @brief 更新 power 相关状态
* @param[in] voltage 参数
* @return void
*/
void update_power(float voltage);
/**
* @brief DFOC_alignSensor 函数
* @param[in] _PP 参数
* @return void
*/
void DFOC_alignSensor(int _PP);
/**
* @brief shut_down 函数
* @return void
*/
void shut_down(void);
/**
* @brief resume 函数
* @return void
*/
void resume(void);
/**
* @brief drv_stop 函数
* @return void
*/
void drv_stop(void);
/**
* @brief drv_hold 函数
* @return float 返回值
*/
float drv_hold(void);
/**
* @brief PWM_out 函数
* @return float 返回值
*/
float PWM_out(void);
/**
* @brief shut_down_thermal 函数
* @return void
*/
void shut_down_thermal(void); // 过热关机
/**
* @brief resume_from_thermal 函数
* @return void
*/
void resume_from_thermal(void); // 过热恢复
/**
* @brief fast_voltage_check 函数
* @return void
*/
void fast_voltage_check(void); // 快速电压检测(100us周期调用)
// 齿槽转矩补偿
bool cogging_comp_enabled = false;
float cogging_comp_scale = COGGING_COMP_SCALE;
float cogging_table[COGGING_TABLE_SIZE] = {0}; // 齿槽补偿表-正转 (mA)
float cogging_table_rev[COGGING_TABLE_SIZE] = {0}; // 齿槽补偿表-反转 (mA)
/**
* @brief 获取 get_cogging_compensation 对应的数据或状态
* @param[in] angle_el 参数
* @return float 返回值
*/
inline float get_cogging_compensation(float angle_el);
// === 校准相关(DEBUG,平时不启用)===
// 启用方法:config.h 中 FOC_DEBUG 改为 1
#if FOC_DEBUG
volatile bool cogging_calib_request = false;
/**
* @brief 齿槽校准状态机入口,每个周期按当前状态派发到对应处理函数
* @return void
*/
void calibrate_cogging_tick(void);
/**
* @brief 处理齿槽校准空闲态,收到请求后保存现场并进入稳定等待态
* @return void
*/
void start_cogging_calibration(void);
/**
* @brief 处理齿槽校准稳定等待态,等待电机进入稳定低速运行
* @return void
*/
void cogging_settling_tick(void);
/**
* @brief 处理齿槽校准采样态,按分频周期累计每个电角度桶的电流
* @return void
*/
void cogging_sampling_tick(void);
/**
* @brief 处理齿槽校准停止态,等待停稳后完成本轮数据归一化
* @return void
*/
void cogging_stopping_tick(void);
/**
* @brief 处理齿槽校准完成态,生成补偿表并打印校准结果
* @return void
*/
void cogging_done_tick(void);
/**
* @brief 计算当前校准轮次的平均电流并去除直流偏置
* @return float 当前轮次直流偏置,单位 mA
*/
float process_cogging_run_data(void);
/**
* @brief 切换到下一轮齿槽校准运行方向并重新进入稳定等待态
* @return void
*/
void start_next_cogging_run(void);
/**
* @brief 根据 3 次正转和 3 次反转采样结果生成最终补偿表
* @return void
*/
void build_cogging_tables(void);
/**
* @brief 打印齿槽补偿表的人类可读角度/电流列表
* @param[in] title 表格标题字符串
* @param[in] table 待打印的补偿表
* @return void
*/
void print_cogging_table(const char *title, float *table);
/**
* @brief 打印可直接复制回源码的齿槽补偿 C 数组
* @param[in] title 输出标题字符串
* @param[in] arrayName C 数组名
* @param[in] table 待打印的补偿表
* @return void
*/
void print_cogging_c_array(const char *title, const char *arrayName,
float *table);
/**
* @brief CogCalibState 枚举定义
*/
enum class CogCalibState : u8 {
IDLE = 0,
SETTLING,
SAMPLING,
STOPPING,
DONE
};
CogCalibState cog_calib_state = CogCalibState::IDLE;
u8 cog_calib_run = 0;
u32 cog_calib_sample_count = 0;
u32 cog_calib_settle_tick = 0;
u32 cog_calib_stop_tick = 0;
u8 cog_calib_saved_mode = 0;
float cog_calib_saved_vel = 0;
static float cog_calib_run_data[6][COGGING_TABLE_SIZE]; // 3正+3反
static float cog_calib_accum[COGGING_TABLE_SIZE];
static u32 cog_calib_count[COGGING_TABLE_SIZE];
#endif // FOC_DEBUG
// 此处默认值不作数
// 注意:构造期 limit_voltage 尚为 0,分母一律用 voltage_power_supply(24V),
// 否则 P 初始化为 +inf;运行期各模式每周期 set_P/set_PID 覆盖。
// 内环 output_ramp 保持原值:实测收紧到 2000 V/s 会在制动段引入相位滞后,
// 导致到位抖动,已回退。
PIDController vel_loop =
PIDController{DEFAULT_vel_loop_p * 100 / voltage_power_supply, vel_loop_Ki,
vel_loop_Kd, 10000, voltage_power_supply};
PIDController angle_loop =
PIDController{DEFAULT_angle_loop_p * 100 / voltage_power_supply, 100.0f,
0.02f, 10000000, voltage_power_supply};
PIDController current_loop = PIDController{
DEFAULT_current_loop_p * 100 / voltage_power_supply, current_loop_Ki,
current_loop_Kd, 1500, voltage_power_supply};
PIDController vel_inVelAngloop =
PIDController{DEFAULT_vel_angloop_p * 100, vel_angloop_Ki,
vel_angloop_Kd, 1e6, v_safe};
PIDController ang_inVelAngloop =
PIDController{DEFAULT_angle_angloop_p * 100 / voltage_power_supply,
ang_angloop_Ki, ang_angloop_Kd, 1e4, 100};
PIDController ang_inMITloop =
PIDController{DEFAULT_angle_MIT_p * 100 / voltage_power_supply, angle_MIT_Ki,
angle_MIT_Kd, 1e5, 100};
PIDController vel_inMITloop = PIDController{
DEFAULT_vel_MIT_p * 100, vel_MIT_Ki, vel_MIT_Kd, 1e9, 1000};
PIDController current_inMITloop = PIDController{
DEFAULT_current_loop_p * 100 / voltage_power_supply, current_loop_Ki,
current_loop_Kd, 1500, voltage_power_supply};
/**
* @brief 更新 pid_limits 相关状态
* @return void
*/
void update_pid_limits() {
vel_loop.limit = voltage_power_supply;
angle_loop.limit = voltage_power_supply;
current_loop.limit = voltage_power_supply;
vel_inVelAngloop.limit = voltage_power_supply;
}
protected:
float shaft_angle = 0;
float Ualpha, Ubeta = 0;
float v_half = voltage_power_supply * 0.5f; // 电源电压的一半
// 本周期电角度的 sin/cos:update_el_sincos() 每周期算一次,
// Park 变换与逆 Park 变换共用,避免同一角度算两次三角函数
float el_sin = 0.0f;
float el_cos = 0.0f;
/**
* @brief 每周期计算一次电角度 sin/cos 供 Park/逆Park 共用
* @param[in] angle_el 电角度(度)
* @return void
*/
inline void update_el_sincos(float angle_el);
/**
* @brief 设置 setSVPWM_PhaseVoltage 对应的参数或状态
* @param[in] Uq 参数
* @param[in] Ud 参数
* @return void
*/
void setSVPWM_PhaseVoltage(float Uq, float Ud);
/**
* @brief cal_Iq_Id 函数
* @param[in] current_a 参数
* @param[in] current_b 参数
* @param[in] current_c 参数
* @return float 返回值
* @note 电气角度三角函数用 update_el_sincos() 的预计算结果
*/
float cal_Iq_Id(float current_a, float current_b, float current_c);
float update_angle_sync_uq_feedforward(u8 mode, float table[],
u16 table_size, float mech_angle,
float target_vel, float actual_vel,
float velocity_error);
float get_mode3_velocity_p(float target_vel, float actual_vel);
float get_mode3_velocity_scale(float target_vel, float actual_vel,
float min_scale);
};
// 定义函数指针类型
typedef float (FOC_Controller::*FOCFunctionPtr)(void);
/**
* @brief calibrate_zero_position 函数
* @return void
*/
void calibrate_zero_position(void);
#endif