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:
+79
-33
@@ -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);
|
||||
}
|
||||
|
||||
// 检查其他可能的中断源
|
||||
|
||||
Reference in New Issue
Block a user