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();
|
||||
}
|
||||
|
||||
@@ -207,8 +207,9 @@ class CAN_transmiter {
|
||||
float_union_t w_current_union = {0}; // W 相电流
|
||||
float_union_t v_current_union = {0}; // V 相电流
|
||||
|
||||
bool MotorStatus = 0; // 电机状态码
|
||||
u8 EEPROMStatus = 0; // EEPROM 状态码
|
||||
// MotorStatus 不在此处:判据与上报都收在 health 的 1ms nFAULT 轮询里,
|
||||
// 声明见 public 段(与 MagStatus/ThermalStatus 同处),避免出现第二个写手。
|
||||
|
||||
can_trasnmit_message_struct transmit_message; // 发送消息结构体
|
||||
u8 transmit_mailbox = CAN_NOMAILBOX; // 初始化为无 mailbox 状态
|
||||
@@ -377,6 +378,9 @@ class CAN_transmiter {
|
||||
|
||||
bool MagStatus = 0; // 磁状态码
|
||||
bool ThermalStatus = 0; // 热能状态码
|
||||
// nFAULT 状态位(STATUS 帧 motStatus)。唯一写手 = health.cpp 的 1ms nFAULT
|
||||
// 轮询,值与"是否允许运行"的判据同源;CAN update() 不再自行读引脚。
|
||||
bool MotorStatus = 0; // 门驱动故障状态码
|
||||
/**
|
||||
* @brief communication_check 函数
|
||||
* @return void
|
||||
|
||||
@@ -23,7 +23,7 @@ extern void KTH7823_spi_init(void);
|
||||
/**
|
||||
* @brief 门驱动芯片引脚预初始化
|
||||
* @note 新板:DRVSLP(PB12) 置低保持 DRV8323 睡眠、片选 PB14 释放、
|
||||
* PB2(nFAULT) 浮空输入。必须在任何可能拉高使能脚的代码之前调用;
|
||||
* PB2(nFAULT) 内部上拉输入。必须在任何可能拉高使能脚的代码之前调用;
|
||||
* 老板:无操作(原时序在 timer1_gpio_config 中保持不变)。
|
||||
*/
|
||||
void gate_driver_preinit(void) {
|
||||
@@ -35,8 +35,8 @@ void gate_driver_preinit(void) {
|
||||
/* SPI 片选默认释放(SCLK 空闲低时才允许 CS 翻转) */
|
||||
gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_14);
|
||||
gpio_bit_set(GPIOB, GPIO_PIN_14);
|
||||
/* nFAULT 低有效 */
|
||||
gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
|
||||
/* nFAULT 低有效,开漏输出 → 内部上拉,避免浮空误读成故障 */
|
||||
gpio_init(GPIOB, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -221,8 +221,11 @@ void motor_init(void) {
|
||||
timer1_pwm_config();
|
||||
// 使能GPIOB时钟
|
||||
rcu_periph_clock_enable(RCU_GPIOB);
|
||||
// 配置PB2为输入引脚,用于读取电机状态(nFAULT)
|
||||
gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
|
||||
// 配置PB2为输入引脚,用于读取电机状态(nFAULT)。
|
||||
// 用内部上拉(GPIO_MODE_IPU)而不是浮空:nFAULT 是开漏输出,无故障时靠
|
||||
// 上拉保持高。现在 PB2 电平直接决定"允不允许运行",浮空输入在接线未确认
|
||||
// 或无上拉时会随机读低,把整机锁死;内部上拉(~40kΩ)与外部上拉并联无害。
|
||||
gpio_init(GPIOB, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
|
||||
/* 配置GPIOB的PB14为推挽输出 SPICS */
|
||||
gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,
|
||||
GPIO_PIN_14 | GPIO_PIN_12);
|
||||
|
||||
Reference in New Issue
Block a user