feat(motor): 引入运行禁止机制重构电机控制安全系统
- 添加 run_inhibit.h/cpp 模块作为全局运行闸门,统一管理所有停机/唤醒逻辑 - 移除 FOC 控制器中的 5 个相互引用的开关机函数(shut_down/resume 等) - 将 nFAULT 硬件故障检测从仅上报改为运行门控制,连续采样故障时申请禁止位 - 改进电压检测逻辑,欠压判定现在通过 run_inhibit 统一执行停机动作 - 修正 PB2(nFAULT) 引脚配置为内部上拉输入,避免浮空误读导致系统锁死 - 在 CAN 状态帧中新增 RunInhibit 位图(字节 36-39),实时反映禁止运行的故障源 - 电流采样失效、过热故障现在通过禁止位管理而非直接操作驱动状态 - 校准函数增加运行许可检查,防止在停机状态下意外唤醒驱动
This commit is contained in:
+16
-11
@@ -18,6 +18,7 @@
|
||||
#include "gd32c10x_gpio.h"
|
||||
#include "initial.h"
|
||||
#include "motor.h"
|
||||
#include "run_inhibit.h"
|
||||
#include "systick.h"
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
@@ -766,7 +767,8 @@ void CAN_transmiter::update(void) {
|
||||
mcu_temp = sampler.get_mcu_temp() * 100;
|
||||
motor_temp = sampler.get_drv_temp() * 100;
|
||||
Power_Voltage = sampler.get_vbus_voltage() * 1000;
|
||||
MotorStatus = gpio_input_bit_get(GPIOB, GPIO_PIN_2) == RESET;
|
||||
// MotorStatus 不在此读取:改由 health.cpp 的 1ms nFAULT 轮询写入,
|
||||
// 那份判据同时决定是否停机,避免"上报的位"和"停机的依据"分家。
|
||||
EEPROMStatus = flashEEP.EEPROMStatus;
|
||||
Target_Control_Mode = FOC.control_mode;
|
||||
controller_Mode = FOC.control_mode;
|
||||
@@ -788,7 +790,9 @@ void CAN_transmiter::update(void) {
|
||||
u8 CAN_transmiter::send_status_frame() {
|
||||
// 打包 status 数据 - 只清零实际使用的 48 字节
|
||||
// v0.74:字节 32~35 新增 InitStatus(初始化错误码位图,0=全部正常,
|
||||
// 定义见 config.h INIT_ERR_*,含电流检测配平超限/无采样帧),36~47 预留
|
||||
// 定义见 config.h INIT_ERR_*,含电流检测配平超限/无采样帧)
|
||||
// 本版:字节 36~39 新增 RunInhibit(当前"禁止运行"来源位图,0=允许运行,
|
||||
// 定义见 sys/run_inhibit.h InhibitSource)。DBC 尚未加信号,抓原始帧即可读。
|
||||
memset(transmit_data, 0, 48);
|
||||
pack_u16_to_bytes(transmit_data, 0, mcu_temp);
|
||||
pack_u16_to_bytes(transmit_data, 2, motor_temp);
|
||||
@@ -808,6 +812,7 @@ u8 CAN_transmiter::send_status_frame() {
|
||||
transmit_data[30] = (test_u16 >> 8) & 0xFF;
|
||||
transmit_data[31] = cpu_usage;
|
||||
pack_u32_to_bytes(transmit_data, 32, (u32)init_error_flags);
|
||||
pack_u32_to_bytes(transmit_data, 36, run_inhibit.sources());
|
||||
// 使用节点 ID 构建发送 ID (高 16 位为节点 ID)
|
||||
return CANFD_AsyncSend(build_can_id(CANFD_STATUS_ID), 48, transmit_data);
|
||||
}
|
||||
@@ -1111,15 +1116,11 @@ void CAN_transmiter::handle_node_message(can_receive_message_struct ¤t_mes
|
||||
|
||||
void CAN_transmiter::handle_control_command(can_receive_message_struct ¤t_message) {
|
||||
// 控制帧布局:模式、电压限制、目标电流/速度/角度、三组 P 参数。
|
||||
/* 收到非零控制模式即视为驱动意图:v2 板 EN 经 R17 10k 下拉、DRV8313
|
||||
* 上电默认睡眠(上电配平后也保持睡眠态),控制路径里没有其他唤醒点,
|
||||
* 不在此唤醒则所有闭环控制都落在 Hi-Z 桥臂上永远无效。
|
||||
* 模式 0(drv_hold 主动锁止,A 相恒 HOLD_PWM_DUTY)不唤醒:上位机
|
||||
* 上电先发模式 0 当"静止待机"时不至于意外通电锁止发热;驱动已在
|
||||
* 唤醒态时模式 0 仍是锁止。幂等;关机态(过流/过压/过热)不唤醒,
|
||||
* 恢复仍由 power_manage / resume_from_thermal 统一管理。 */
|
||||
if (current_message.rx_data[0] != 0U && !FOC.is_shut_down) {
|
||||
motor_resume();
|
||||
// 这里不再直接碰驱动使能:唤醒功率级是 run_inhibit 闸门在 50us 控制任务里做的。
|
||||
// 非零模式 = 上位机使能意图,撤销"未使能"这一禁止位;模式 0(静止待机/锁止)
|
||||
// 不解除,保持上电默认睡眠。被禁止期间本函数照常收下参数,但控制函数不会被派发。
|
||||
if (current_message.rx_data[0] != 0U) {
|
||||
run_inhibit.release(INHIBIT_NOT_ENABLED);
|
||||
}
|
||||
FOC.control_mode = current_message.rx_data[0];
|
||||
FOC.limit_voltage = float(unpack_bytes_to_u16(current_message.rx_data, 1)) / 1000;
|
||||
@@ -1160,6 +1161,10 @@ void CAN_transmiter::handle_reset_command(can_receive_message_struct ¤t_me
|
||||
u8 eigth_byte = current_message.rx_data[7];
|
||||
|
||||
if (first_byte & 0x01) {
|
||||
// motReset = 撤销 nFAULT 这一禁止申请。之后能否真的重新运行由闸门看位图;
|
||||
// 若故障源还在,1ms 的 nFAULT 轮询会立刻重新 request(),而驱动唤醒建立期
|
||||
// (DRV_WAKE_SETTLE_50US)内输出保持 0,不会带故障出 torque。
|
||||
run_inhibit.release(INHIBIT_DRV_NFAULT);
|
||||
motor_reset();
|
||||
testfloat_union.f = KTH7823.getcurrent_sensorangle();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user