feat(FOC): 重构FOC控制器实现并修复SVPWM算法支持

- 修复类名拼写错误:FOC_Controlroller -> FOC_Controller
- 移除不必要的角度归一化函数,直接使用fmod优化性能
- 添加完整的SVPWM算法实现,提高电机控制效率
- 重构PID参数配置,使用动态参数调整机制
- 增加电流反馈功能,实时监测电机运行状态
- 优化电压安全限制,提高系统稳定性
- 更新控制模式映射,支持更多控制策略
- 改进CAN通信协议,增加电流反馈传输
This commit is contained in:
cbb
2026-02-02 02:12:14 +08:00
parent 25e2edfd0c
commit c9934849c5
14 changed files with 386 additions and 233 deletions
+217 -90
View File
@@ -11,8 +11,7 @@
#include <cmath>
#include <gd32c10x.h>
FOC_Controlroller FOC; // FOC控制初始化
FOC_Controller FOC; // FOC控制初始化
extern sampler sampler;
extern angle_sensor KTH7823;
extern CAN_transmiter CAN0_transmiter;
@@ -24,27 +23,14 @@ extern EncoderVelocityKalman Vel_kalman; // 速度滤波
#define constrain(value, min, max, target_min, target_max) \
((value - min) / (max - min) * (target_max - target_min))
/**@
* @brief 归一化角度
*
* @param angle
* @return float
*/
inline float _normalizeAngle(float angle) {
float a = fmod(angle, 360.0f);
// 取余运算可以用于归一化,列出特殊值例子算便知
return a >= 0 ? a : (a + 360.0f);
}
// 通过Ia,Ib,Ic计算Iq,Id(目前仅输出Iq)
inline float FOC_Controlroller::cal_Iq_Id(float current_a, float current_b,
float current_c) {
inline float FOC_Controller::cal_Iq_Id(float current_a, float current_b,
float current_c) {
// 计算电气角度
float angle_el = _normalizeAngle(shaft_angle * PP);
float angle_el = fmod(shaft_angle * PP, 360.0f);
float I_alpha, I_beta;
// Clarke变换 (使用三相电流)
// arm_clarke_f32(current_a, current_b, &I_alpha, &I_beta);
I_alpha = (2.0f / 3.0f) * current_a - (1.0f / 3.0f) * current_b -
(1.0f / 3.0f) * current_c;
I_beta = _1_SQRT3 * current_b - _1_SQRT3 * current_c;
@@ -54,10 +40,9 @@ inline float FOC_Controlroller::cal_Iq_Id(float current_a, float current_b,
arm_sin_cos_f32(angle_el, &sin_el, &cos_el);
float I_q, I_d;
I_q = I_beta * cos_el - I_alpha * sin_el;
// arm_park_f32(I_alpha, I_beta, &I_d, &I_q, sin_el, cos_el);
return I_q * 1000.0f -
KE_FACTOR * rt_velocity; // 返回Iq值,乘以100以转换为mA
KE_FACTOR * rt_velocity; // 返回Iq值,乘以1000以转换为mA
}
/**
@@ -65,20 +50,22 @@ inline float FOC_Controlroller::cal_Iq_Id(float current_a, float current_b,
*
* @return u8 0表示初始化成功,1表示初始化失败
*/
u8 FOC_Controlroller::init() {
motor_init(); // 电机驱动初始化
vel_loop.set_PID(vel_loop_p * 100 / limit_voltage, 0.20f, 5e-5); // 设置电机速度控制参数
angle_loop.set_PID(angle_loop_p * 100 / limit_voltage, 100.0f,
u8 FOC_Controller::init() {
motor_init(); // 电机驱动初始化
vel_loop.set_PID(DEFAULT_vel_loop_p * 100 / voltage_power_supply, vel_loop_Ki,
vel_loop_Kd); // 设置电机速度控制参数
angle_loop.set_PID(DEFAULT_angle_loop_p * 100 / voltage_power_supply, 100.0f,
0.2f); // 设置电机角度控制参数
current_loop.set_PID(current_loop_p * 100 / limit_voltage, 5e-7f,
current_loop.set_PID(DEFAULT_current_loop_p * 100 / voltage_power_supply, 5e-7f,
7e-8); // 设置电机电流控制参数
vel_inVelAngloop.set_PID(vel_angloop_p * 100 / limit_voltage, 3.0f,
5e-4); // 设置电机速度控制参数
ang_inVelAngloop.set_PID(ang_angloop_p * 100 / limit_voltage, 0.0f,
5e-4); // 设置电机角度控制参数
vel_inVelAngloop.set_PID(DEFAULT_vel_angloop_p * 100, vel_angloop_Ki,
vel_angloop_Kd); // 设置电机速度控制参数
ang_inVelAngloop.set_PID(DEFAULT_ang_angloop_p * 100 / voltage_power_supply,
ang_angloop_Ki,
ang_angloop_Kd); // 设置电机角度控制参数
CAN0_transmiter.testfloat_union.f = DEFAULT_ang_angloop_p * 100 / voltage_power_supply;
return 0;
}
@@ -86,18 +73,18 @@ u8 FOC_Controlroller::init() {
* @brief 电机控制类构造函数
*
*/
FOC_Controlroller::FOC_Controlroller() { ; }
FOC_Controller::FOC_Controller() { ; }
/**
* @brief 设置电机输出,使用优化的SVPWM算法
* @brief 设置电机输出
*
* @param Uq: q轴电压
* @param Ud: d轴电压
* @param angle_el: 电机轴角度
*/
inline void FOC_Controlroller::setPhaseVoltage(float Uq, float Ud) {
inline void FOC_Controller::setPhaseVoltage(float Uq, float Ud) {
// 计算电气角度
float angle_el = _normalizeAngle(shaft_angle * PP);
float angle_el = fmod(shaft_angle * PP, 360.0f);
// 帕克逆变换 (直接计算,避免函数调用开销)
float sin_el, cos_el;
@@ -107,18 +94,126 @@ inline void FOC_Controlroller::setPhaseVoltage(float Uq, float Ud) {
// 克拉克逆变换 (使用预计算常量优化)
Ua = Ualpha + v_half;
Ub = sqrt3dv2 * Ubeta - 0.5f * Ualpha + v_half;
Uc = -0.5f * Ualpha - sqrt3dv2 * Ubeta + v_half;
Ub = SQRT3DV2 * Ubeta - 0.5f * Ualpha + v_half;
Uc = -0.5f * Ualpha - SQRT3DV2 * Ubeta + v_half;
if (Ua > v_safe)
Ua = v_safe;
else if (Ua < -v_safe)
Ua = -v_safe;
if (Ub > v_safe)
Ub = v_safe;
else if (Ub < -v_safe)
Ub = -v_safe;
if (Uc > v_safe)
Uc = v_safe;
else if (Uc < -v_safe)
Uc = -v_safe;
// 计算占空比并限制范围
duty_a = _constrain(Ua / v_safe, 0.0f, 1.0f);
duty_b = _constrain(Ub / v_safe, 0.0f, 1.0f);
duty_c = _constrain(Uc / v_safe, 0.0f, 1.0f);
// 设置PWM输出
float voltage_exchange = limit_voltage / v_safe;
duty_a = duty_a * voltage_exchange;
duty_b = duty_b * voltage_exchange;
duty_c = duty_c * voltage_exchange;
duty_a = Ua / voltage_power_supply * voltage_exchange;
duty_b = Ub / voltage_power_supply * voltage_exchange;
duty_c = Uc / voltage_power_supply * voltage_exchange;
Set_3Pwm(duty_a, duty_b, duty_c);
}
/**
* @brief 使用SVPWM算法设置电机输出(优化版)
*
* @param Uq: q轴电压
* @param Ud: d轴电压
*/
inline void FOC_Controller::setSVPWM_PhaseVoltage(float Uq, float Ud) {
// 计算电气角度(保持原有角度单位和范围)
float angle_el = fmod(shaft_angle * PP, 360.0f);
// 帕克逆变换
float sin_el, cos_el;
arm_sin_cos_f32(angle_el, &sin_el, &cos_el);
float Ualpha = Ud * cos_el - Uq * sin_el;
float Ubeta = Ud * sin_el + Uq * cos_el;
// 计算角度并归一化到 [0, 2π)
float angle = atan2f(Ubeta, Ualpha);
if (angle < 0)
angle += 2.0f * PI;
// 扇区与局部角度
int sector = (int)(angle * INV_PI_3) + 1;
if (sector < 1)
sector = 1;
else if (sector > 6)
sector = 6;
float local_angle = angle - (sector - 1) * PI_3;
// 模长计算
float magnitude = sqrtf(Ualpha * Ualpha + Ubeta * Ubeta);
// 计算电压调制比,同时限制最大输出电压
float modulation_index =
(magnitude / voltage_power_supply); // 90%作为安全裕量
// 电压限制
if (limit_voltage > voltage_power_supply) {
limit_voltage = voltage_power_supply;
}
float limit_percent = limit_voltage / v_safe;
if (modulation_index > limit_percent) {
// 限制电压
modulation_index = limit_percent;
// 同时相应地调整magnitude,保持电压矢量方向不变,根据调整后的调制比反推magnitude
magnitude = voltage_power_supply * limit_percent;
}
// 使用arm_sin_cos_f32计算local_angle的sin和cos
float sin_l, cos_l;
arm_sin_cos_f32(local_angle, &sin_l, &cos_l);
float T1 = modulation_index * (SQRT3DV2 * cos_l - COS_PI_3 * sin_l);
float T2 = modulation_index * sin_l;
float T0 = 1.0f - T1 - T2;
// 计算占空比(按规范化时间映射)
switch (sector) {
case 1:
duty_a = 0.5f * T0 + T1 + T2;
duty_b = 0.5f * T0 + T2;
duty_c = 0.5f * T0;
break;
case 2:
duty_a = 0.5f * T0 + T1;
duty_b = 0.5f * T0 + T1 + T2;
duty_c = 0.5f * T0;
break;
case 3:
duty_a = 0.5f * T0;
duty_b = 0.5f * T0 + T1 + T2;
duty_c = 0.5f * T0 + T2;
break;
case 4:
duty_a = 0.5f * T0;
duty_b = 0.5f * T0 + T1;
duty_c = 0.5f * T0 + T1 + T2;
break;
case 5:
duty_a = 0.5f * T0 + T2;
duty_b = 0.5f * T0;
duty_c = 0.5f * T0 + T1 + T2;
break;
case 6:
duty_a = 0.5f * T0 + T1 + T2;
duty_b = 0.5f * T0;
duty_c = 0.5f * T0 + T1;
break;
default:
duty_a = 0.0f;
duty_b = 0.0f;
duty_c = 0.0f;
break;
}
// 设置PWM输出
Set_3Pwm(duty_a, duty_b, duty_c);
}
@@ -126,7 +221,7 @@ inline void FOC_Controlroller::setPhaseVoltage(float Uq, float Ud) {
* @brief 电机关机
*
*/
void FOC_Controlroller::shut_down() {
void FOC_Controller::shut_down() {
is_shut_down = 1;
motor_sleep();
}
@@ -134,11 +229,11 @@ void FOC_Controlroller::shut_down() {
* @brief 占空比置0
*
*/
void FOC_Controlroller::drv_stop() { Set_3Pwm(0.0f, 0.0f, 0.0f); }
void FOC_Controller::drv_stop() { Set_3Pwm(0.0f, 0.0f, 0.0f); }
/**
* @brief 电机锁止
*/
float FOC_Controlroller::drv_hold() {
float FOC_Controller::drv_hold() {
float hold_pwm_duty = HOLD_PWM_DUTY;
if (HOLD_PWM_DUTY > 0.95f) {
hold_pwm_duty = 0.95f;
@@ -152,7 +247,7 @@ float FOC_Controlroller::drv_hold() {
* @brief 电机恢复
*
*/
void FOC_Controlroller::resume() {
void FOC_Controller::resume() {
over_current = false;
voltage_error = false;
is_shut_down = false;
@@ -162,12 +257,12 @@ void FOC_Controlroller::resume() {
* @brief 更新电源电压
*
*/
void FOC_Controlroller::update_power(void) {
voltage_power_supply = sampler.get_vbus_voltage();
if (voltage_power_supply < 36.0f and voltage_power_supply > 8.0f) {
void FOC_Controller::update_power(float voltage) {
if (voltage < 36.0f and voltage > 8.0f) {
voltage_error = false;
v_half = voltage_power_supply * 0.5f;
v_safe = voltage_power_supply * 0.95f;
voltage_power_supply = voltage;
v_half = voltage * 0.5f;
v_safe = voltage * 1.05f;
} else {
voltage_error = true;
}
@@ -179,51 +274,39 @@ void FOC_Controlroller::update_power(void) {
* @param target_velocity: 目标速度
* @return float: q轴电压
*/
float FOC_Controlroller::velocity_open_loop() {
float FOC_Controller::velocity_open_loop() {
// 通过时间间隔和目标速度计算需要转动的机械角度,存储在shaft_angle中,在此之前,还需要对轴角度归一化
shaft_angle = _normalizeAngle(shaft_angle + target_velocity * ANGLE_FACTOR *
REDUCTION_RATIO * 1.0 /
TIMER2_FREQUENCY);
shaft_angle = fmod(shaft_angle + target_velocity * REDUCTION_RATIO * 1.0 /
TIMER2_FREQUENCY,
360.0f);
// 因为在开环控制中,Ud始终为0,只控制Uq
const float Uq = voltage_power_supply / 2.0f;
setPhaseVoltage(Uq, 0.0f);
CAN0_transmiter.testfloat_union.f = shaft_angle;
setSVPWM_PhaseVoltage(Uq, 0.0f);
// CAN0_transmiter.testfloat_union.f = Uq;
// cal_Iq_Id(sampler.get_current('U'), sampler.get_current('V'),
// sampler.get_current('W'));
return limit_voltage;
}
/**
* @brief 电机初始化
*
* @param _PP: 电机极队数
*/
// void FOC_Controlroller::DFOC_alignSensor(int _PP) {
// u8 PP = _PP;
// setPhaseVoltage(3, 0, _3PI_2);
// delay_1ms(3000);
// zero_electric_angle = _electricalAngle();
// setPhaseVoltage(0, 0, _3PI_2);
// std::printf("0电角度:%f", zero_electric_angle);
// }
/**
* @brief 角度闭环控制
*
* @param target_angle: 目标角度
* @return float: 当前角度
*/
float FOC_Controlroller::angle_control() {
float FOC_Controller::angle_control() {
// PID 控制计算
float Uq = angle_loop(target_angle - rt_angle);
// 获取电机轴角度
shaft_angle = KTH7823.getcurrent_sensorangle();
rt_current = cal_Iq_Id(sampler.get_current('U'), sampler.get_current('V'),
sampler.get_current('W'));
// 设置相电压
setPhaseVoltage(Uq, 0.0f);
setSVPWM_PhaseVoltage(Uq, 0.0f);
return shaft_angle;
}
@@ -234,26 +317,70 @@ float FOC_Controlroller::angle_control() {
* @param max_velocity: 最大速度限制 (单位: rad/s)
* @return float: 当前角度
*/
float FOC_Controlroller::angle_control_with_velocity_limit() {
float FOC_Controller::angle_control_with_velocity_limit() {
// 计算角度误差
float angle_error = target_angle - rt_angle;
// 使用角度PID控制器计算目标速度
float target_velocity = ang_inVelAngloop(angle_error);
// 对目标速度进行限幅
target_velocity =
_constrain(target_velocity, -limit_velocity, limit_velocity);
// 使用速度PID控制器计算最终输出电压
// 根据目标速度大小,选择不同的PID参数
if (target_velocity < -120.0f) {
vel_inVelAngloop.set_P(vel_angloop_p * 2.0f);
} else if (target_velocity < -30.0f) {
vel_inVelAngloop.set_P(vel_angloop_p * 1.5f);
} else {
vel_inVelAngloop.set_P(vel_angloop_p);
}
float Uq = vel_inVelAngloop(rt_velocity - target_velocity);
CAN0_transmiter.testfloat_union.f = shaft_angle;
rt_current = cal_Iq_Id(sampler.get_current('U'), sampler.get_current('V'),
sampler.get_current('W'));
// 获取电机轴角度
shaft_angle = KTH7823.getcurrent_sensorangle();
// 设置相电压
setSVPWM_PhaseVoltage(Uq, 0.0f);
return shaft_angle;
}
/**
* @brief 带速度限制的角度闭环控制
*
* @param target_angle: 目标角度
* @param max_velocity: 最大速度限制 (单位: rad/s)
* @return float: 当前角度
*/
float FOC_Controller::MIT_Mode() {
// 第一层:角度环(外环)
// 根据目标角度和实际角度的差值,通过角度环PID控制器计算目标速度
float angle_error = rt_angle - target_angle;
float target_velocity =
ang_inVelAngloop(angle_error); // 使用angle_loop作为角度到速度的映射
// 第二层:速度环(中环)
// 根据目标速度和实际速度的差值,通过速度环PID控制器计算目标电流
float velocity_error = target_velocity - rt_velocity;
float target_current =
vel_inVelAngloop(velocity_error); // 使用vel_loop作为速度到电流的映射
CAN0_transmiter.testfloat_union.f = target_current;
// 第三层:电流环(内环)
// 计算当前实际电流
rt_current = cal_Iq_Id(sampler.get_current('U'), sampler.get_current('V'),
sampler.get_current('W'));
// 通过电流环PID控制器计算输出电压
float current_error = target_current - rt_current;
float Uq = current_loop(current_error);
// 获取电机轴角度
shaft_angle = KTH7823.getcurrent_sensorangle();
// 设置相电压
setPhaseVoltage(Uq, 0.0f);
setSVPWM_PhaseVoltage(Uq, 0.0f);
return shaft_angle;
}
@@ -264,30 +391,30 @@ float FOC_Controlroller::angle_control_with_velocity_limit() {
* @param target_velocity: 目标速度
* @return float: 当前速度
*/
float FOC_Controlroller::velocity_control() {
float FOC_Controller::velocity_control() {
// PID 控制计算
float Uq = vel_loop((rt_velocity - target_velocity) * 25);
// 获取电机轴角度
shaft_angle = KTH7823.getcurrent_sensorangle();
// 设置相电压
setPhaseVoltage(Uq, 0.0f);
CAN0_transmiter.testfloat_union.f =
cal_Iq_Id(sampler.get_current('U'), sampler.get_current('V'),
sampler.get_current('W'));
setSVPWM_PhaseVoltage(Uq, 0.0f);
rt_current = cal_Iq_Id(sampler.get_current('U'), sampler.get_current('V'),
sampler.get_current('W'));
return rt_velocity;
}
float FOC_Controlroller::current_control() {
float FOC_Controller::current_control() {
// PID 控制计算
float Iq = cal_Iq_Id(sampler.get_current('U'), sampler.get_current('V'),
sampler.get_current('W'));
float Iq = rt_current =
cal_Iq_Id(sampler.get_current('U'), sampler.get_current('V'),
sampler.get_current('W'));
float Uq = current_loop(target_current - Iq);
CAN0_transmiter.testfloat_union.f = Iq;
// 获取电机轴角度
shaft_angle = KTH7823.getcurrent_sensorangle();
// 设置相电压
setPhaseVoltage(Uq, 0.0f);
setSVPWM_PhaseVoltage(Uq, 0.0f);
return 1;
}
+35 -16
View File
@@ -5,52 +5,68 @@
#include "pid.h"
#include <cstdint>
class FOC_Controlroller {
class FOC_Controller {
public:
FOC_Controlroller();
FOC_Controller();
// 初始化函数
u8 init();
u8 control_mode = 0;
float limit_voltage = 0.0f;
float limit_velocity = 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;
float voltage_power_supply = 24.0f; // 电源电压
float v_safe = voltage_power_supply * 0.95f;
float v_safe = voltage_power_supply * 1.05f;
float duty_a = 0, duty_b = 0, duty_c = 0;
float Ua = 0, Ub = 0, Uc = 0;
float current_loop_p=DEFAULT_current_loop_p;
float vel_angloop_p=DEFAULT_vel_angloop_p;
float vel_loop_p=DEFAULT_vel_loop_p;
float ang_angloop_p=DEFAULT_ang_angloop_p;
float angle_loop_p=DEFAULT_angle_loop_p;
float vel_MIT_p=DEFAULT_vel_MIT_p;
float velocity_open_loop(void);
float angle_control(void);
float angle_control_with_velocity_limit(void);
float MIT_Mode(void);
float velocity_control(void);
float current_control(void);
void update_power(void);
void update_power(float voltage);
void DFOC_alignSensor(int _PP);
void shut_down(void);
void resume(void);
void drv_stop(void);
float drv_hold(void);
PIDController vel_loop = PIDController{
vel_loop_p * 100, 0.20f, 5e-5, 1000000, voltage_power_supply}; // 12V
PIDController angle_loop =
PIDController{angle_loop_p * 100, 100.0f, 0.2f, 10000000,
voltage_power_supply}; // 12V
PIDController current_loop = PIDController{
current_loop_p * 100, 5e-7f, 7e-8, 500, 24}; // 12V
PIDController vel_inVelAngloop = PIDController{
vel_angloop_p * 100, 3.0f, 5e-4, 1000000, voltage_power_supply};
// 此处默认值不作数
PIDController vel_loop = PIDController{vel_loop_p * 100, 0.0f, 0, 10000,
voltage_power_supply}; // 12V
PIDController angle_loop = PIDController{angle_loop_p * 100, 0, 0, 10000000,
voltage_power_supply}; // 12V
PIDController current_loop = PIDController{current_loop_p * 100, 0, 0, 1500,
voltage_power_supply}; // 12V
PIDController vel_inVelAngloop =
PIDController{vel_angloop_p * 100, 0, 0, 1000000, v_safe};
PIDController ang_inVelAngloop =
PIDController{ang_angloop_p * 100, 0.0f, 5e-4, 1000000, 999};
PIDController{ang_angloop_p * 100, 0, 0, 20000, 100};
void update_pid_limits() {
vel_loop.limit = voltage_power_supply;
@@ -64,12 +80,15 @@ class FOC_Controlroller {
float Ualpha, Ubeta = 0;
float zero_electric_angle = 0;
float v_half = voltage_power_supply * 0.5f; // 电源电压的一半
float startup_ramp_val = 0.0f; // 软启动系数
float startup_ramp_step = 0.01f; // 启动斜坡步长,可调节以控制启动速度
void setPhaseVoltage(float Uq, float Ud);
void setSVPWM_PhaseVoltage(float Uq, float Ud);
float cal_Iq_Id(float current_a, float current_b, float current_c);
};
// 定义函数指针类型
typedef float (FOC_Controlroller::*FOCFunctionPtr)(void);
typedef float (FOC_Controller::*FOCFunctionPtr)(void);
inline float _normalizeAngle(float angle);
inline float _electricalAngle();
+11 -3
View File
@@ -2,12 +2,12 @@
#define _constrain(amt, low, high) \
((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt)))
#include "Can.h"
#include "config.h"
#include <algorithm>
#include <cmath>
extern CAN_transmiter CAN0_transmiter;
constexpr float TIME_SLICE = 1e-4;
extern CAN_transmiter CAN0_transmiter;
PIDController::PIDController(float P, float I, float D, float ramp, float limit)
: P(P), I(I), D(D), output_ramp(ramp) // PID控制器加速度限幅
,
@@ -68,4 +68,12 @@ void PIDController::set_PID(float P, float I, float D) {
* @param P: P参数
* @return void
*/
void PIDController::set_P_percent(float pp) { this->P = pp; }
void PIDController::set_P(float pp) { this->P = pp; }
/**
* @brief 设置输出限幅
*
* @param limit: 输出限幅
* @return void
*/
void PIDController::set_limit(float limit) { this->limit = limit; }
+5 -1
View File
@@ -8,7 +8,9 @@ class PIDController {
float operator()(float error);
void set_PID(float P, float I, float D);
void set_P_percent(float pp);
void set_P(float pp);
void set_limit(float limit);
void reset(); // 重置PID控制器状态
float P; //!< 比例增益(P环增益)
float I; //!< 积分增益(I环增益)
@@ -21,5 +23,7 @@ class PIDController {
float output_prev; //!< 最后一个 pid 输出值
float integral_prev; //!< 最后一个积分分量值
unsigned long timestamp_prev; //!< 上次执行时间戳
float integral_separation_threshold; //!< 积分分离阈值,用于抗积分饱和
};
#endif
+2 -2
View File
@@ -15,7 +15,7 @@ constexpr float VCC_FACTOR = 11.0f;
constexpr float CURRENT_FACTOR =
1.0f / 50.0f * 100.0f; // 50倍放大,100倍电流采样电阻, 单位mA
extern CAN_transmiter CAN0_transmiter;
extern FOC_Controlroller FOC;
extern FOC_Controller FOC;
sampler sampler; // 采样器初始化
u16 adc_value[6] = {0}; // 显式初始化数组元素为0
/*!
@@ -240,7 +240,7 @@ void sampler::update_drv_temp() {
*/
void sampler::update_current() {
u8 idx = current_sample_index;
extern FOC_Controlroller FOC;
extern FOC_Controller FOC;
// 优化计算
const float scale = ADC_SCALE * CURRENT_FACTOR;
const float offset = CURRENT_OFFSET * CURRENT_FACTOR;
+38 -77
View File
@@ -21,7 +21,7 @@
constexpr u16 CANX = CAN0;
CAN_transmiter CAN0_transmiter; // CAN初始化
extern FOC_Controlroller FOC;
extern FOC_Controller FOC;
extern sampler sampler;
extern angle_sensor KTH7823;
extern EncoderAngleKalman Angle_kalman; // 角度滤波
@@ -447,13 +447,15 @@ void CAN_transmiter::update(void) {
target_angle_union.f = FOC.target_angle;
target_velocity_union.f = FOC.target_velocity;
target_current_union.f = FOC.target_current;
limit_velocity_union.f = FOC.limit_velocity;
rt_angle_union.f = FOC.rt_angle;
rt_velocity_union.f = FOC.rt_velocity;
rt_current_union.f = FOC.rt_current;
limit_voltage = FOC.limit_voltage * 1000;
mcu_temp = sampler.get_mcu_temp() * 100;
motor_temp = sampler.get_drv_temp() * 100;
Power_Voltage = sampler.get_vbus_voltage() * 1000;
rt_angle_union.f = FOC.rt_angle;
rt_velocity_union.f = FOC.rt_velocity;
MotorStatus = gpio_input_bit_get(GPIOB, GPIO_PIN_2) == RESET;
EEPROMStatus = flashEEP.EEPROMStatus;
Target_Control_Mode = FOC.control_mode;
@@ -465,57 +467,6 @@ void CAN_transmiter::update(void) {
v_current_union.f = sampler.get_current('V') * 1000;
}
/**
* @brief CAN发送函数
* @retval 0: 发送失败
* 1: 发送成功
*/
u8 CAN_transmiter::CAN_all_Send() {
u32 success_flag = 0;
constexpr u32 RT_Vel_Ang_FEED = 0x101;
constexpr u32 SET_Vel_Ang_FEED = 0x110;
constexpr u32 Current_FEED = 0x117;
constexpr u32 Status_FEED = 0x118;
constexpr u32 Limit_Vel_Vol_FEED = 0x119;
// 打包RT_Vel_Ang_FEED - 只清零实际使用的8字节
memset(transmit_data, 0, 8);
pack_float_to_bytes(transmit_data, 0, rt_angle_union);
pack_float_to_bytes(transmit_data, 4, rt_velocity_union);
success_flag += CAN_AsyncSend(RT_Vel_Ang_FEED, 8, transmit_data);
// 打包SET_Vel_Ang_FEED - 只清零实际使用的8字节
memset(transmit_data, 0, 8);
pack_float_to_bytes(transmit_data, 0, target_angle_union);
pack_float_to_bytes(transmit_data, 4, target_velocity_union);
success_flag += CAN_AsyncSend(SET_Vel_Ang_FEED, 8, transmit_data);
// 打包Current_FEED - 只清零实际使用的6字节
memset(transmit_data, 0, 6);
pack_u16_to_bytes(transmit_data, 0, u16(u_current_union.f));
pack_u16_to_bytes(transmit_data, 2, u16(w_current_union.f));
pack_u16_to_bytes(transmit_data, 4, u16(v_current_union.f));
success_flag += CAN_AsyncSend(Current_FEED, 6, transmit_data);
// 打包Status_FEED - 只清零实际使用的8字节
memset(transmit_data, 0, 8);
transmit_data[0] = MotorStatus;
transmit_data[1] = controller_Mode;
pack_u16_to_bytes(transmit_data, 2, motor_temp);
pack_u16_to_bytes(transmit_data, 4, mcu_temp);
pack_u16_to_bytes(transmit_data, 6, Power_Voltage);
success_flag += CAN_AsyncSend(Status_FEED, 8, transmit_data);
// 打包Limit_Vel_Vol_FEED - 只清零实际使用的6字节
memset(transmit_data, 0, 6);
pack_float_to_bytes(transmit_data, 0, limit_velocity_union);
pack_u16_to_bytes(transmit_data, 4, limit_voltage);
success_flag += CAN_AsyncSend(Limit_Vel_Vol_FEED, 6, transmit_data);
return success_flag;
}
/**
* @brief CANFD发送函数
* @retval 0: 发送失败
@@ -538,17 +489,19 @@ u8 CAN_transmiter::CANFD_all_Send() {
pack_u16_to_bytes(transmit_data, 11, Power_Voltage);
pack_float_to_bytes(transmit_data, 13, rt_angle_union);
pack_float_to_bytes(transmit_data, 17, rt_velocity_union);
pack_float_to_bytes(transmit_data, 21, testfloat_union);
pack_float_to_bytes(transmit_data, 21, rt_current_union);
pack_float_to_bytes(transmit_data, 25, testfloat_union);
pack_u16_to_bytes(transmit_data, 29, test_u16);
success_flag += CANFD_AsyncSend(CANFD_STATUS_ID, 32, transmit_data);
// 打包config数据 - 只清零实际使用的16字节
memset(transmit_data, 0, 16);
// 打包config数据 - 只清零实际使用的24字节
memset(transmit_data, 0, 24);
transmit_data[0] = controller_Mode;
pack_u16_to_bytes(transmit_data, 1, limit_voltage);
pack_float_to_bytes(transmit_data, 3, limit_velocity_union);
pack_float_to_bytes(transmit_data, 7, target_angle_union);
pack_float_to_bytes(transmit_data, 11, target_velocity_union);
success_flag += CANFD_AsyncSend(CANFD_CONFIG_ID, 16, transmit_data);
pack_float_to_bytes(transmit_data, 3, target_current_union);
pack_float_to_bytes(transmit_data, 7, target_velocity_union);
pack_float_to_bytes(transmit_data, 11, target_angle_union);
success_flag += CANFD_AsyncSend(CANFD_CONFIG_ID, 24, transmit_data);
return success_flag;
}
@@ -577,34 +530,42 @@ void CAN_transmiter::communication_check() {
if (receive_message.rx_efid == CANFD_CMD_ID) {
// 控制模式
FOC.control_mode = receive_message.rx_data[0];
// 目标角度
// 目标电压限制
FOC.limit_voltage =
float(unpack_bytes_to_u16(receive_message.rx_data, 1)) / 1000;
// 目标电流&目标速度
FOC.limit_velocity =
// 目标电流
target_current_union.f =
unpack_bytes_to_float(receive_message.rx_data, 3).f;
FOC.target_current = FOC.limit_velocity;
// 目标角度
target_angle_union.f =
unpack_bytes_to_float(receive_message.rx_data, 7).f;
FOC.target_angle = target_angle_union.f;
FOC.current_loop.set_limit(target_current_union.f);
// 目标速度
target_velocity_union.f =
unpack_bytes_to_float(receive_message.rx_data, 7).f;
FOC.ang_inVelAngloop.set_limit(target_velocity_union.f);
// 目标角度
target_angle_union.f =
unpack_bytes_to_float(receive_message.rx_data, 11).f;
// 赋值
FOC.target_angle = target_angle_union.f;
FOC.target_velocity = target_velocity_union.f;
FOC.target_current = FOC.target_velocity * 10.0f;
FOC.target_current = target_current_union.f;
// 解析PID参数
u16 P_config = unpack_bytes_to_u16(receive_message.rx_data, 15);
float voltage = FOC.limit_voltage;
FOC.current_loop.set_P_percent(current_loop_p * P_config / voltage);
// PID参数
u16 P_config = unpack_bytes_to_u16(receive_message.rx_data, 15);
FOC.current_loop_p = DEFAULT_current_loop_p * P_config / voltage;
P_config = unpack_bytes_to_u16(receive_message.rx_data, 17);
FOC.vel_loop.set_P_percent(vel_loop_p * P_config / voltage);
FOC.vel_loop_p = DEFAULT_vel_loop_p * P_config / voltage;
FOC.vel_MIT_p = DEFAULT_vel_MIT_p * P_config / voltage;
P_config = unpack_bytes_to_u16(receive_message.rx_data, 19);
FOC.angle_loop.set_P_percent(angle_loop_p * P_config / voltage);
FOC.angle_loop_p = DEFAULT_angle_loop_p * P_config / voltage;
FOC.ang_angloop_p = DEFAULT_ang_angloop_p * P_config / voltage;
P_config = unpack_bytes_to_u16(receive_message.rx_data, 21);
FOC.vel_inVelAngloop.set_P_percent(vel_angloop_p * P_config /
voltage);
FOC.vel_angloop_p = DEFAULT_vel_angloop_p * P_config;
} else if (receive_message.rx_efid == CANFD_RESET_ID) {
u8 first_byte = receive_message.rx_data[0];
u8 eigth_byte = receive_message.rx_data[7];
+19 -12
View File
@@ -6,6 +6,7 @@
extern "C" {
#endif
#include <cstdint>
#include "gd32c10x_can.h"
// 定义一个联合体类型用于float和byte数组之间的转换
@@ -72,24 +73,29 @@ class CAN_transmiter {
private:
bool is_sleep = false; // 是否休眠
u8 controller_Mode = 0; // 电机模式
float_union_t limit_velocity_union = {0}; // 限制速度
u16 limit_voltage = 0; // 限制电压
short mcu_temp = 0; // MCU温度
short motor_temp = 0; // 电机温度
u16 Power_Voltage = 0; // 电源电压
float_union_t rt_angle_union = {0}; // 实时角度
float_union_t rt_velocity_union = {0}; // 实时速度
bool MotorStatus = 0; // 电机状态码
u8 Target_Control_Mode = 0; // 目标控制模式
u8 controller_Mode = 0; // 当前模式
short mcu_temp = 0; // MCU温度
short motor_temp = 0; // 电机温度
u16 Power_Voltage = 0; // 电源电压
u16 limit_voltage = 0; // 限制电压
float_union_t rt_angle_union = {0}; // 实时角度
float_union_t rt_velocity_union = {0}; // 实时速度
float_union_t rt_current_union = {0}; // 实时电流
float_union_t target_angle_union = {0}; // 目标角度
u8 Target_Control_Mode = 0; // 目标控制模式
u8 EEPROMStatus = 0; // EEPROM状态码
float_union_t target_velocity_union = {0}; // 目标速度
float_union_t target_current_union = {0};
float_union_t target_current_union = {0}; // 目标电流
float_union_t u_current_union = {0}; // U相电流
float_union_t w_current_union = {0}; // W相电流
float_union_t v_current_union = {0}; // V相电流
bool MotorStatus = 0; // 电机状态码
u8 EEPROMStatus = 0; // EEPROM状态码
can_trasnmit_message_struct transmit_message; // 发送消息结构体
u8 transmit_mailbox = CAN_NOMAILBOX; // 初始化为无mailbox状态
u8 transmit_data[64]; // CANFD最大64字节
@@ -106,6 +112,7 @@ class CAN_transmiter {
FlagStatus can0_receive_flag; // CAN0接收标志
FlagStatus can0_send_flag; // CAN0发送标志
float_union_t testfloat_union = {0}; // 测试用
u16 test_u16 = 0;
bool MagStatus = 0; // 磁状态码
bool ThermalStatus = 0; // 热能状态码
+2 -2
View File
@@ -11,7 +11,7 @@
volatile u32 total_us100_counter = 0; // 总计数器,每100微秒增加1
extern u16 adc_value[7];
extern FOC_Controlroller FOC;
extern FOC_Controller FOC;
extern TaskScheduler scheduler;
extern CAN_transmiter CAN0_transmiter;
// 添加系统运行时间计数器
@@ -94,9 +94,9 @@ void TIMER2_IRQHandler(void) {
timer_interrupt_flag_clear(TIMER2, TIMER_INT_UP);
// 每50us执行一次的操作 - 电机控制
scheduler.taskFlags |= (1 << TASK_MOTOR_CONTROL);
scheduler.taskFlags |=
(1 << TASK_ANGLE_UPDATE) | (1 << TASK_VELOCITY_UPDATE);
scheduler.taskFlags |= (1 << TASK_MOTOR_CONTROL);
// 使用标志位控制,每100us执行一次其他任务
static bool isEvenCall = false;
+14 -12
View File
@@ -8,7 +8,6 @@
#include "flash.h"
#include "health.h"
#include "initial.h"
#include "motor.h"
#include "systick.h"
extern CAN_transmiter CAN0_transmiter; // CAN初始化
@@ -17,7 +16,7 @@ extern angle_sensor KTH7823; // 角度传感器
extern EncoderVelocityKalman Vel_kalman; // 速度滤波
extern EncoderAngleKalman Angle_kalman; // 角度滤波
extern ThermalController thermalController; // 热量控制器
extern FOC_Controlroller FOC; // FOC控制
extern FOC_Controller FOC; // FOC控制
extern FlashEEPROM flashEEP; // EEPROM类
extern VersionManager Version;
@@ -63,7 +62,7 @@ u8 hardware_init(void) {
init_status += Angle_kalman.init(KTH7823.getAngle()); // 角度滤波初始化
init_status += Vel_kalman.init(0.0f); // 速度滤波初始化
init_status += CAN0_transmiter.init(); // CAN初始化
init_status += FOC.init(); // FOC初始化
init_status += FOC.init(); // FOC初始化
return init_status;
}
@@ -85,17 +84,20 @@ void do_task(u32 currentTasks) {
// 函数指针数组,包含各种控制模式对应的函数
static FOCFunctionPtr control_functions[] = {
&FOC_Controlroller::drv_hold, // 0: 占空比置
&FOC_Controlroller::
angle_control_with_velocity_limit, // 1:
&FOC_Controller::drv_hold, // 0: 占空比置
&FOC_Controller::angle_control, // 1: 位置闭环控制
&FOC_Controller::velocity_control, // 2: 速度闭环控制
&FOC_Controller::
angle_control_with_velocity_limit, // 3:
// 角度闭环控制,带速度限制
&FOC_Controlroller::velocity_control, // 2: 速度闭环控制
&FOC_Controlroller::current_control, // 3: 电流闭环控制
&FOC_Controlroller::velocity_open_loop, // 4: 速度开环控制
&FOC_Controller::MIT_Mode, // 4: MIT 模式
&FOC_Controller::current_control, // 5: 电流闭环控制
&FOC_Controller::velocity_open_loop, // 6: 速度开环控制
};
// 边界检查,防止数组越界
if (FOC.control_mode >= 0 && FOC.control_mode < 5) { // 更新为7个控制模式
if (FOC.control_mode >= 0 &&
FOC.control_mode < 7) { // 更新为7个控制模式
// 调用对应的控制函数
(FOC.*control_functions[FOC.control_mode])();
}
@@ -115,8 +117,8 @@ void do_task(u32 currentTasks) {
if (currentTasks & (1 << TASK_VBUS_UPDATE)) { // 更新vbus电压值
power_manage();
}
if (currentTasks & (1 << TASK_CAN_TRANSMIT)) { // CAN通信
// CAN0_transmiter.testfloat_union.f = cnt_test; // 负载检测
if (currentTasks & (1 << TASK_CAN_TRANSMIT)) { // CAN通信
CAN0_transmiter.test_u16 = cnt_test; // 负载检测
cnt_test = 0;
CAN0_transmiter.can0_send_flag = SET;
CAN0_transmiter.communication_check();
+1
View File
@@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define MAIN_H
#include <cstdint>
void do_task(u32 currentTasks);
u8 hardware_init(void);
+34 -10
View File
@@ -1,5 +1,6 @@
#ifndef __CONFIG_H
#define __CONFIG_H
#include "gd32c10x_eval.h"
#include <cstdint>
// 如果使用CMSIS DSP库,需要定义ARM_MATH_CM4
@@ -58,22 +59,43 @@ constexpr float HOLD_PWM_DUTY = 0.95f;
constexpr u16 ANGLESENS_OFFSET = +0;
constexpr float KE_FACTOR = 14.0f;
// PID配置
constexpr float current_loop_p = 6e-2f / 100 * 12; // 电流P
constexpr float vel_loop_p = 0.01f / 100 * 12; // 速度P
constexpr float angle_loop_p = 20.0f / 100 * 12; // 角度P
constexpr float vel_angloop_p = 0.12f / 100 * 12; // 速度 速度-角度P
constexpr float ang_angloop_p = 100.0f / 100 * 12; // 角度 速度-角度P
constexpr float DEFAULT_current_loop_p = 6e-2f / 100 * 12; // 电流P
constexpr float DEFAULT_vel_loop_p = 0.018f / 100 * 12; // 速度P
constexpr float vel_loop_Ku = 3.600000e-03 * 0.7 * 100 / 12;
constexpr float vel_loop_Tu = 17.0f * 1e-3f;
constexpr float vel_loop_Ki = 1.2 * vel_loop_Ku / vel_loop_Tu;
constexpr float vel_loop_Kd = 0.075 * vel_loop_Ku * vel_loop_Tu * 2;
constexpr float DEFAULT_vel_angloop_p = 0.22f / 100; // 速度 速度-角度P
constexpr float vel_angloop_Ki = 12.0f; // 角度 速度-角度I
constexpr float vel_angloop_Kd = 6e-04f; // 角度 速度-角度D
constexpr float DEFAULT_ang_angloop_p = 120.0f / 100 * 12; // 角度 速度-角度P
constexpr float ang_angloop_Ki = 0.00f; // 角度 速度-角度I
constexpr float ang_angloop_Kd = 8e-04; // 角度 速度-角度D
constexpr float DEFAULT_angle_loop_p = 60.0f / 100 * 12; // 角度P
constexpr float DEFAULT_vel_MIT_p = 25.0f / 100 * 12; // 速度 速度-角度P
constexpr float vel_MIT_Ku = 6.72f * 100 / 12;
constexpr float vel_MIT_Tu = 62.0f * 1e-3f;
constexpr float vel_MIT_Ki = 3e-2f;
constexpr float vel_MIT_Kd = 5.355000e-05f;
// 常量定义
constexpr u8 SIZE_FLOAT = sizeof(float);
constexpr u8 SIZE_U32 = sizeof(uint32_t);
constexpr float ADC_MAX = 65536.0f;
constexpr float PI = 3.14159265358979323846f;
constexpr float INV_PI_3 = 3.0f / PI;
constexpr float PI_3 = PI / 3.0f;
constexpr float _1_SQRT3 = 0.57735026919f; // 1/sqrt(3)
constexpr float SQRT3 = 1.7320508075688772f;
constexpr float SQRT3DV2 = 0.8660254037844386f; // sqrt(3)/2
constexpr float COS_PI_3 = 0.5f;
constexpr float ANGLE_FACTOR = 25.0f / 180.0f * PI;
constexpr float DEG2RAD = 1.0f / 180.0f * PI;
constexpr float RAD2DEG = 180.0f / PI; // 修正RAD2DEG定义,应该是180/π
constexpr float _1_SQRT3 = 0.57735026919f; // 1/sqrt(3)
constexpr float sqrt3dv2 = 0.86602540378f; // sqrt(3)/2的预计算值
constexpr float RAD2DEG = 180.0f / PI; // 修正RAD2DEG定义,应该是180/π
constexpr u8 DEFAULT_VALUE = 0;
constexpr u8 CONFIG_SAVED_NUM = 6;
@@ -122,8 +144,10 @@ constexpr float ANGLESENS_FACTOR = 1.0f / ADC_MAX * 360.0f;
// TIMER2-任务调度
constexpr int TIMER2_PRESCALER = 119; // 120MHz / 120 = 1MHz
constexpr int TIMER2_PERIOD = 49; // 1MHz / 50 = 50us
constexpr float TIMER2_FREQUENCY = 1 / 5e-5;
constexpr int TIMER2_PERIOD = 49; // 1 / 1MHz * 50 = 50us
constexpr float TIME_SLICE =
(TIMER2_PERIOD + 1) * (TIMER2_PRESCALER + 1) / 120000000.0f; // 周期
constexpr float TIMER2_FREQUENCY = 1 / TIME_SLICE; // 频率
// TIMER1-PWM
constexpr int TIMER1_PRESCALER = 0; // 不分频,计数器时钟为120MHz
+3 -3
View File
@@ -13,7 +13,7 @@
FlashEEPROM flashEEP = FlashEEPROM();
extern angle_sensor KTH7823;
extern CAN_transmiter CAN0_transmiter;
extern FOC_Controlroller FOC; // FOC控制
extern FOC_Controller FOC; // FOC控制
fmc_state_enum write_ADDRESS(u32 address, u32 data) {
fmc_unlock();
@@ -125,7 +125,7 @@ u8 FlashEEPROM::read_saved_system_config(void) {
FOC.control_mode = (u8)data[0];
FOC.limit_voltage = data[1];
FOC.limit_velocity = data[2];
FOC.target_current = data[2];
KTH7823.angle_set(data[3]);
FOC.target_angle = data[4];
FOC.target_velocity = data[5];
@@ -389,7 +389,7 @@ FlashEepromStatus FlashEEPROM::save_system_config(bool saved) {
u32 CRC_NUM = 0x0000;
float data[CONFIG_SAVED_NUM] = {
(float)FOC.control_mode, FOC.limit_voltage,
FOC.limit_velocity, FOC.rt_angle,
FOC.target_current, FOC.rt_angle,
FOC.target_angle, FOC.target_velocity};
// 如果系统配置标记已保存,则无需再次保存
+2 -2
View File
@@ -8,7 +8,7 @@
extern sampler sampler;
extern CAN_transmiter CAN0_transmiter;
extern FOC_Controlroller FOC;
extern FOC_Controller FOC;
extern FlashEEPROM flashEEP;
ThermalController thermalController; // 热量控制器初始化
@@ -93,7 +93,7 @@ void angsens_MG_check(void) {
void power_manage(void) {
float last_vbus = sampler.get_vbus_voltage();
sampler.update_vbus_voltage();
FOC.update_power();
FOC.update_power(last_vbus);
float vbus = sampler.get_vbus_voltage();
if ((vbus < 22.0f) and (last_vbus > vbus) and vbus > 8.0f) {
FOC.shut_down();
+2 -2
View File
@@ -9,8 +9,8 @@
"requires": {
"arm:tools/open-cmsis-pack/cmsis-toolbox": "2.12.0",
"arm:tools/kitware/cmake": "3.31.5",
"arm:tools/ninja-build/ninja": "1.12.1",
"arm:tools/arm/mdk-toolbox": "1.1.0",
"arm:compilers/arm/armclang": "6.24.0"
"arm:compilers/arm/armclang": "6.24.0",
"arm:tools/ninja-build/ninja": "1.12.1"
}
}