feat(FOC): 实现电角度零位自动校准并修复ADC采样干扰问题
- 新增FlashEEPROM用于保存零位校准角,掉电不丢失 - 实现安全的零位校准算法:运行中禁止校准、对齐后重新采样、保存到Flash - 重构ADC架构:分离ADC0(PWM同步电流采样)和ADC1(VBUS/DRV温度轮询) - 解决ADC采样冲突:移除ADC0的regular连续扫描,避免与注入组抢占资源 - 修复VBUS电压读取错误:从DMA缓冲区改为直接ADC1单次转换 - 修正开环控制Uq幅值限幅逻辑,保留符号避免反转时抖动 - 更新CAN协议:电流数据改为有符号16位打包,支持负电流传输 - 调整版本号至v26.8.16.7
This commit is contained in:
+42
-21
@@ -11,6 +11,7 @@
|
||||
#include "adc.h"
|
||||
#include "ang_sensor.h"
|
||||
#include "config.h"
|
||||
#include "flash.h"
|
||||
#include "motor.h"
|
||||
#include "pid.h"
|
||||
#include "systick.h"
|
||||
@@ -29,7 +30,7 @@ extern angle_sensor KTH7823;
|
||||
extern CAN_transmiter CAN0_transmiter;
|
||||
extern EncoderVelocityKalman Vel_kalman; // 速度滤波
|
||||
extern CurrentKalman Current_kalman;
|
||||
extern u16 adc_value[3]; // regular DMA缓冲区:MCU温度 / DRV温度 / VBUS
|
||||
extern FlashEEPROM flashEEP;
|
||||
|
||||
// 齿槽转矩补偿:查表 + 线性插值
|
||||
// angle_el: 电角度(度)
|
||||
@@ -271,26 +272,30 @@ void FOC_Controller::print_cogging_c_array(const char *title,
|
||||
* @return void
|
||||
*/
|
||||
void calibrate_zero_position(void) {
|
||||
// Set_3Pwm(.25, 0, 0); // 起劲
|
||||
// delay_1ms(1000);
|
||||
// KTH7823.update();
|
||||
// 运行中禁止校准:要求控制模式为停止(0)且基本静止,
|
||||
// 否则转子无法对齐到电气 0°,标定结果错误,甚至因电角度突变导致失控。
|
||||
if (FOC.control_mode != 0 || fabsf(FOC.rt_velocity) > CALIB_MAX_SPEED) {
|
||||
return;
|
||||
}
|
||||
|
||||
// // 改进校准算法:获取当前传感器角度并计算补偿值
|
||||
// float current_sensor_angle = KTH7823.getcurrent_sensorangle();
|
||||
// float electrical_angle = fmodf(current_sensor_angle * PP, 360.0f); //
|
||||
// 计算当前电角度
|
||||
// 使能电机驱动器,准备对齐
|
||||
motor_resume();
|
||||
|
||||
// // 计算需要的补偿值,使得当前位置对应0°电角度
|
||||
// KTH7823.calibration_angle = -electrical_angle;
|
||||
// 施加固定电压矢量(A 相高电平),让转子对齐到电气 0° 位置
|
||||
Set_3Pwm(ALIGN_PWM_DUTY, 0.0f, 0.0f);
|
||||
delay_1ms(ALIGN_SETTLE_MS);
|
||||
|
||||
// // 对补偿角进行归一化处理,确保在[-180, 180]范围内
|
||||
// KTH7823.calibration_angle = fmodf(KTH7823.calibration_angle + 180.0f,
|
||||
// 360.0f); if (KTH7823.calibration_angle < 0) { KTH7823.calibration_angle
|
||||
// += 360.0f;
|
||||
// }
|
||||
// KTH7823.calibration_angle -= 180.0f;
|
||||
// 对齐稳定后重新采样传感器角度,再计算零位补偿角,使当前位置对应电气 0°
|
||||
KTH7823.update();
|
||||
float current_sensor_angle = KTH7823.getcurrent_sensorangle();
|
||||
float electrical_angle = fmodf(current_sensor_angle * PP, 360.0f);
|
||||
KTH7823.set_calibration(-electrical_angle);
|
||||
|
||||
// Set_3Pwm(0, 0, 0); // 停止
|
||||
// 停止施加电压
|
||||
Set_3Pwm(0.0f, 0.0f, 0.0f);
|
||||
|
||||
// 保存校准角到 Flash,掉电不丢
|
||||
flashEEP.save_calibration_angle(KTH7823.calibration_angle);
|
||||
}
|
||||
|
||||
// 通过Ia,Ib,Ic计算Iq,Id(目前仅输出Iq)
|
||||
@@ -722,8 +727,11 @@ void FOC_Controller::update_power(float voltage) {
|
||||
* @return void
|
||||
*/
|
||||
void FOC_Controller::fast_voltage_check(void) {
|
||||
// 直接从DMA缓冲区读取最新ADC值(regular rank2 是 VBUS)
|
||||
float current_vbus = adc_value[2] * (3.3f / 4096.0f) * 11.0f;
|
||||
// ADC1 单次转换读取 VBUS(ch6,11:1 分压)。
|
||||
// 旧实现读 regular DMA 的 adc_value[2],通道顺序调整后该下标已是 DRV温度,
|
||||
// 属漏改:NTC 分压值(~1.06V)按 11 倍分压换算仅 ~11.5V,逼近跌落阈值。
|
||||
float current_vbus =
|
||||
adc1_read_raw(ADC_CHANNEL_6) * (3.3f / 4096.0f) * 11.0f;
|
||||
|
||||
// 更新基准电压(峰值检测)
|
||||
// 电压上升时,基准电压跟随;电压下跌时,基准电压保持
|
||||
@@ -778,8 +786,21 @@ float FOC_Controller::velocity_open_loop() {
|
||||
sampler.get_current('W'), angle_el_cog);
|
||||
|
||||
// 因为在开环控制中,Ud 始终为 0,只控制 Uq
|
||||
const float Uq = _constrain(target_velocity * REDUCTION_RATIO * 0.005f,
|
||||
2.0f, voltage_power_supply * 0.5f);
|
||||
// 幅度限幅必须保留符号:原 _constrain 下限为 +2V,负速度会被钳到 +2V,
|
||||
// 磁场角度反向而 Uq 仍为正,导致反转时电机原地抖动。
|
||||
float Uq = target_velocity * REDUCTION_RATIO * 0.005f;
|
||||
const float UQ_MIN_MAG = 2.0f;
|
||||
const float UQ_MAX_MAG = voltage_power_supply * 0.5f;
|
||||
// 零速不输出,避免 2V 最小幅值导致静止时缓慢爬行
|
||||
if (Uq != 0.0f) {
|
||||
float Uq_mag = fabsf(Uq);
|
||||
if (Uq_mag < UQ_MIN_MAG) {
|
||||
Uq_mag = UQ_MIN_MAG;
|
||||
} else if (Uq_mag > UQ_MAX_MAG) {
|
||||
Uq_mag = UQ_MAX_MAG;
|
||||
}
|
||||
Uq = (Uq < 0.0f) ? -Uq_mag : Uq_mag;
|
||||
}
|
||||
setSVPWM_PhaseVoltage(Uq + get_cogging_compensation(angle_el_cog), 0.0f, angle_el_cog);
|
||||
return limit_voltage;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user