feat(can): 增强CAN通信缓冲区管理机制

- 实现循环缓冲区队列管理CAN消息接收
- 添加缓冲区满/空状态检查函数
- 实现消息出队列dequeue_rx_message功能
- 在中断处理程序中添加消息入队列机制
- 优化CAN消息处理流程,支持批量处理

refactor(motor): 优化电机控制类结构和安全机制
- 重命名PID控制器参数变量名以提高可读性
- 添加过热关机标志位thermal_shutdown和相关处理函数
- 实现过热关机shut_down_thermal和过热恢复resume_from_thermal功能
- 调整关机逻辑,添加drv_stop调用确保电机完全停止
- 修正电流环控制中的占空比设置,改为单相保持

feat(motor): 实现FOC控制算法改进和零点校准功能
- 实现电机零点校准函数calibrate_zero_position用于位置补偿
- 修正FOC控制器中的电气角度计算,集成KTH7823校准角度补偿
- 新增d轴电流计算功能
- 重构PID参数初始化方式,使用统一的电压限制配置
- 更新SVPWM相电压设置算法,改进角度归一化处理
- 修改缺省扇区输出占空比从0.0f改为0.5f以提高稳定性

fix(control): 修复控制回路方向和频率计算问题
- 修正角度控制回路中的误差计算方向
- 修正开环速度控制中的频率参数使用
- 修正速度环控制中的误差计算方向
- 修正MIT模式下多级PID控制器的参数设置和误差计算

refactor(filter): 修正编码器速度计算算法
- 移除速度计算中的冗余乘法因子2

feat(pid): 扩展PID控制器功能
- 添加reset方法用于重置PID内部状态

chore(build): 更新开发工具版本和ADC配置
- 更新csolution版本至2.13.0
- 调整ADC采样时间配置以优化性能
This commit is contained in:
cbb
2026-03-09 01:35:26 +08:00
parent 9689841148
commit a26dd1cc8e
14 changed files with 514 additions and 313 deletions
+79 -33
View File
@@ -19,8 +19,6 @@
#include <random>
constexpr u16 CANX = CAN0;
CAN_transmiter CAN0_transmiter; // CAN初始化
extern FOC_Controller FOC;
extern sampler sampler;
extern angle_sensor KTH7823;
@@ -35,6 +33,51 @@ dma_parameter_struct dma_tx_parameter;
uint8_t can_rx_buffer[8]; // CAN接收缓冲区
uint8_t can_tx_buffer[8]; // CAN发送缓冲区
CAN_transmiter CAN0_transmiter; // CAN初始化
// CAN接收缓冲区相关函数实现
/*!
\brief 检查CAN接收缓冲区是否已满
\param[in] none
\param[out] none
\retval bool 返回true表示缓冲区已满,false表示未满
\note 通过比较头指针的下一个位置和尾指针来判断缓冲区是否已满
使用循环缓冲区策略,当(rx_buffer_head + 1) %
CAN_RX_BUFFER_SIZE等于rx_buffer_tail时, 表示缓冲区已达到最大容量
*/
bool CAN_transmiter::is_rx_buffer_full() {
return ((rx_buffer_head + 1) % CAN_RX_BUFFER_SIZE) == rx_buffer_tail;
}
/*!
\brief 检查CAN接收缓冲区是否为空
\param[in] none
\param[out] none
\retval bool 返回true表示缓冲区为空,false表示缓冲区不为空
\note 通过比较头指针和尾指针是否相等来判断缓冲区是否为空
*/
bool CAN_transmiter::is_rx_buffer_empty() {
return rx_buffer_head == rx_buffer_tail;
}
/**
* @brief 从接收缓冲区中取出一条CAN消息
*
* 该函数检查接收缓冲区是否为空,如果不为空则取出缓冲区队列头部的消息,
* 并更新队列尾部索引。如果缓冲区为空,则返回false。
*
* @param message 引用类型的输出参数,用于存储取出的CAN接收消息结构体
* @return bool 返回操作是否成功,true表示成功取出消息,false表示缓冲区为空
*/
bool CAN_transmiter::dequeue_rx_message(can_receive_message_struct &message) {
if (!is_rx_buffer_empty()) {
message = rx_message_buffer[rx_buffer_tail];
rx_buffer_tail = (rx_buffer_tail + 1) % CAN_RX_BUFFER_SIZE;
return true;
}
return false;
}
/*!
\brief initialize CAN GPIO
\param[in] none
@@ -521,30 +564,32 @@ void CAN_transmiter::communication_check() {
can0_send_flag = RESET;
}
// CAN0 接收数据标志
if (SET == can0_receive_flag) {
// printf("\r\n can0 %X receive data:", receive_message.rx_efid);
// for (i = 0; i < receive_message.rx_dlen; i++) {
// printf(" %02x", receive_message.rx_data[i]);
// 处理所有接收到的CAN消息(从环形缓冲区中)
can_receive_message_struct current_message;
while (dequeue_rx_message(current_message)) {
// printf("\r\n can0 %X receive data:", current_message.rx_efid);
// for (i = 0; i < current_message.rx_dlen; i++) {
// printf(" %02x", current_message.rx_data[i]);
// }
if (receive_message.rx_efid == CANFD_CMD_ID) {
if (current_message.rx_efid == CANFD_CMD_ID) {
// 控制模式
FOC.control_mode = receive_message.rx_data[0];
FOC.control_mode = current_message.rx_data[0];
// 目标电压限制
FOC.limit_voltage =
float(unpack_bytes_to_u16(receive_message.rx_data, 1)) / 1000;
float(unpack_bytes_to_u16(current_message.rx_data, 1)) / 1000;
// 目标电流
target_current_union.f =
unpack_bytes_to_float(receive_message.rx_data, 3).f;
unpack_bytes_to_float(current_message.rx_data, 3).f;
FOC.current_loop.set_limit(target_current_union.f);
FOC.vel_inMITloop.set_limit(target_current_union.f);
// 目标速度
target_velocity_union.f =
unpack_bytes_to_float(receive_message.rx_data, 7).f;
unpack_bytes_to_float(current_message.rx_data, 7).f;
FOC.ang_inVelAngloop.set_limit(target_velocity_union.f);
FOC.ang_inMITloop.set_limit(target_velocity_union.f);
// 目标角度
target_angle_union.f =
unpack_bytes_to_float(receive_message.rx_data, 11).f;
unpack_bytes_to_float(current_message.rx_data, 11).f;
// 赋值
FOC.target_angle = target_angle_union.f;
FOC.target_velocity = target_velocity_union.f;
@@ -553,26 +598,26 @@ void CAN_transmiter::communication_check() {
// 解析PID参数
float voltage = FOC.limit_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;
u16 P_config = unpack_bytes_to_u16(current_message.rx_data, 15);
FOC.cur_loop_p = DEFAULT_current_loop_p * P_config / voltage;
FOC.cur_MIT_p = DEFAULT_current_MIT_p * P_config / voltage;
P_config = unpack_bytes_to_u16(receive_message.rx_data, 17);
P_config = unpack_bytes_to_u16(current_message.rx_data, 17);
FOC.vel_loop_p = DEFAULT_vel_loop_p * P_config / voltage;
P_config = unpack_bytes_to_u16(receive_message.rx_data, 19);
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_angloop_p = DEFAULT_vel_angloop_p * P_config;
FOC.vel_MIT_p = DEFAULT_vel_MIT_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];
P_config = unpack_bytes_to_u16(current_message.rx_data, 19);
FOC.ang_loop_p = DEFAULT_angle_loop_p * P_config / voltage;
FOC.ang_angloop_p = DEFAULT_angle_angloop_p * P_config / voltage;
FOC.ang_MIT_p = DEFAULT_angle_MIT_p * P_config / voltage;
} else if (current_message.rx_efid == CANFD_RESET_ID) {
u8 first_byte = current_message.rx_data[0];
u8 eigth_byte = current_message.rx_data[7];
// 电机重置
if (first_byte & 0x01) {
motor_reset();
testfloat_union.f = KTH7823.getcurrent_sensorangle();
}
// EEPROM重置
if (first_byte >> 1 & 0x01) {
@@ -593,16 +638,17 @@ void CAN_transmiter::communication_check() {
app_prepare_deep_sleep(true);
// CAN_Sleep();
}
} else if (receive_message.rx_efid == CANFD_VERSION_ID) {
} else if (current_message.rx_efid == CANFD_VERSION_ID) {
// 处理版本号请求,发送当前系统版本信息
Version.sendVersionInfoViaCan();
} else if (receive_message.rx_efid == CANFD_BOOT_ID) {
} else if (current_message.rx_efid == CANFD_BOOT_ID) {
motor_sleep();
flashEEP.save_system_config(false);
fmc_unlock();
OTA_SET(n_APP_LATEST_EN_ADDR, OTA_NOT_AVAL); // 设置APP为不激活
fmc_lock();
jumpToBOOT();
} else if (receive_message.rx_efid == 0x00000102) {
} else if (current_message.rx_efid == 0x00000102) {
volatile u32 *flash_ptr = (volatile u32 *)n_APP_LATEST_EN_ADDR;
u32 app_enable = *flash_ptr;
flash_ptr = (volatile u32 *)n_APP_LATEST_CHECK_ADDR;
@@ -614,9 +660,8 @@ void CAN_transmiter::communication_check() {
CANFD_AsyncSend(CANFD_OTA_ACK_ID, 2, transmit_data);
}
} else {
printf("Unknown CAN ID: %X\n", receive_message.rx_efid);
printf("Unknown CAN ID: %X\n", current_message.rx_efid);
}
can0_receive_flag = RESET;
}
}
@@ -662,10 +707,11 @@ void CAN0_RX0_IRQHandler(void) {
dma_channel_enable(DMA0, DMA_CH4);
// 读取接收到的数据
can_message_receive(CAN0, CAN_FIFO0, &CAN0_transmiter.receive_message);
can_receive_message_struct temp_message;
can_message_receive(CAN0, CAN_FIFO0, &temp_message);
// 接收标志位置1
CAN0_transmiter.can0_receive_flag = SET;
// 将接收到的消息加入环形缓冲区
CAN0_transmiter.enqueue_rx_message_from_isr(temp_message);
}
// 检查其他可能的中断源