解锁流程基础:解锁条件、解锁时序、解锁状态机设计

电机解锁,说白了就是给电机一个「允许转动」的信号。但你别小看这一步——我见过太多因为解锁逻辑没写好,导致电机上电瞬间乱转、甚至烧驱动器的案例。今天咱们就把解锁流程的底裤扒干净。

解锁条件:不是所有信号都能放行

电机解锁不是拍脑袋决定的。它需要满足一组硬性条件。我个人习惯把这些条件分成三类:

条件类型 具体项 说明
电气条件 母线电压正常、相电流为零、驱动使能就绪 电压过低或过高都不行,电流不为零解锁会炸
通信条件 CAN/PWM 指令有效、校验通过、超时未复位 通信断了必须锁死,防止飞车
机械条件 霍尔/编码器状态稳定、抱闸已松开、温度正常 传感器抖动时解锁,位置会跳变
我曾经踩过的坑: 有一次只检查了电压阈值,没做电压纹波检测。结果电源纹波大时,解锁瞬间电压跌到欠压点以下,电机刚转就停,反复震荡把 MOS 管烧了。后来我加了个 50ms 的电压稳定窗口,问题才解决。

解锁时序:时间窗口是硬约束

解锁不是瞬间完成的。它有一个严格的时序窗口。你想想看,如果解锁信号和 PWM 使能信号不同步,会发生什么?

我一般把解锁时序拆成四个阶段:

  1. 预充电阶段(5~10ms)——先让母线电容充到目标电压的 90% 以上
  2. 状态确认阶段(1~2ms)——再次读取所有传感器,确认无异常
  3. 解锁脉冲阶段(0.5~1ms)——输出一个极窄的 PWM 脉冲,检测电流响应
  4. 正式解锁阶段——进入正常运行状态

关键点: 解锁脉冲阶段是我个人习惯加的「安全探针」。如果这个脉冲检测到电流异常(比如短路或开路),立刻终止解锁流程,而不是等到正式运行时才发现问题。

解锁状态机设计:把流程变成代码

状态机是解锁流程的骨架。我习惯用有限状态机(FSM)来管理,每个状态对应一个明确的动作和转移条件。

下面是我在项目中常用的解锁状态机:

typedef enum {
  LOCKED,           // 锁定状态
  PRECHARGE,        // 预充电
  SENSOR_CHECK,     // 传感器检测
  UNLOCK_PULSE,     // 解锁脉冲
  UNLOCKED,         // 已解锁
  FAULT             // 故障状态
} MotorState_t;

MotorState_t currentState = LOCKED;

void MotorUnlockFSM(void) {
  switch(currentState) {
    case LOCKED:
      if (AllConditionsMet()) {
        StartPrecharge();
        currentState = PRECHARGE;
      }
      break;
    case PRECHARGE:
      if (PrechargeDone()) {
        currentState = SENSOR_CHECK;
      } else if (PrechargeTimeout()) {
        currentState = FAULT;
      }
      break;
    case SENSOR_CHECK:
      if (SensorDataValid()) {
        SendUnlockPulse();
        currentState = UNLOCK_PULSE;
      } else {
        currentState = FAULT;
      }
      break;
    case UNLOCK_PULSE:
      if (PulseResponseOK()) {
        currentState = UNLOCKED;
      } else {
        currentState = FAULT;
      }
      break;
    case UNLOCKED:
      // 正常运行
      break;
    case FAULT:
      // 锁死,等待复位
      break;
  }
}

我的习惯: 每个状态都加一个超时计数器。比如 PRECHARGE 状态超过 20ms 还没完成,直接进 FAULT。这样即使硬件卡死,软件也能兜底。

状态机可视化:一张图看懂流程

光看代码可能不够直观。我画了一张状态转移图,把每个状态和转移条件标清楚。嗯,这张图在我做项目评审时帮了大忙。

电机解锁状态机流程图 LOCKED PRECHARGE SENSOR_CHECK UNLOCK_PULSE UNLOCKED FAULT 条件满足 预充完成 传感器正常 脉冲响应正常 超时 传感器异常 脉冲异常 复位 说明:实线箭头为正常流程,红色虚线为故障转移,紫色虚线为复位路径

状态机设计的三个原则

做了这么多年嵌入式,我总结出状态机设计的三个铁律:

  • 单一出口原则——每个状态只有一个正常出口和一个故障出口,别搞多个分支
  • 超时兜底原则——每个状态都配一个看门狗定时器,超时自动进 FAULT
  • 幂等恢复原则——从 FAULT 恢复后,必须重新走完整解锁流程,不能跳状态

我曾经踩过的坑: 有一次为了省代码,在 FAULT 状态直接跳转到 UNLOCKED。结果电机在异常状态下突然解锁,把机械臂甩出去了。从那以后,我所有状态机都强制要求 FAULT 只能通过复位回到 LOCKED,绝不允许跨状态跳转。

解锁时序的实测波形

理论说完了,咱们看点实际的。下面是我用示波器抓的一组解锁时序波形数据:

阶段 持续时间 关键信号 正常范围
预充电 8ms 母线电压从 0V 升至 48V 5~15ms
传感器检测 1.2ms 霍尔信号稳定无抖动 < 2ms
解锁脉冲 0.8ms 相电流峰值 0.5A 0.3~1.0A
正式解锁 — PWM 使能拉高 —

你看,整个解锁流程从开始到完成,也就 10ms 左右。但就是这 10ms,如果任何一个环节出问题,后果都很严重。

我的习惯: 每次调试新板子,我都会用示波器抓解锁时序,跟表格里的数据对比。如果哪个阶段的时间偏差超过 20%,我就回去查代码或硬件。这个习惯帮我提前发现了至少 5 次硬件设计问题。

好了,解锁流程的基础就聊到这儿。记住:解锁条件要严、时序要准、状态机要稳。这三样做好了,电机解锁就不会出幺蛾子。