2. 基础知识
VCU 的核心功能,说白了就是五件事:上下电、挡位、扭矩、能量、故障。这五个模块就像人的五脏六腑,缺一不可。我做了这么多年 VCU 开发,每次接手新项目,第一件事就是把这五个模块的架构理清楚。今天咱们一个一个过。
核心观点:VCU 的五个核心功能模块不是孤立的。上下电是基础,挡位是意图,扭矩是执行,能量是效率,故障是安全。它们之间互相耦合,开发时必须统一考虑。
2.1 整车上下电管理
上下电管理是 VCU 最基础的功能,也是整车安全的第一道防线。你想想看,一辆车如果连上电都控制不好,后面的功能全是白搭。
我个人习惯把上下电分为三个阶段:唤醒阶段、主上电阶段、下电阶段。每个阶段都有严格的状态机控制。
| 阶段 | 触发条件 | VCU 动作 | 典型时间 |
|---|---|---|---|
| 唤醒阶段 | 钥匙 ON / 远程唤醒 | 唤醒 BMS、MCU、DC-DC,自检 | ≤ 200ms |
| 主上电阶段 | 自检通过 + 制动信号 | 闭合主继电器,预充完成,READY 灯亮 | ≤ 500ms |
| 下电阶段 | 钥匙 OFF / 故障触发 | 降扭矩→断开继电器→休眠 | ≤ 300ms |
避坑指南:我曾经遇到过一个问题——预充继电器粘连导致上电瞬间电流冲击。后来我们在状态机里加了预充完成检测的超时判断,如果 1 秒内预充电压没达到 90%,直接报故障并禁止主继电器闭合。这个坑,踩过一次就记住了。
上下电管理的核心代码逻辑,其实就是个有限状态机。我贴一段简化版的伪代码,大家感受一下:
// 上下电状态机 - 简化示例
typedef enum {
POWER_OFF,
WAKE_UP,
PRE_CHARGE,
MAIN_POWER_ON,
POWER_DOWN,
SLEEP
} PowerState_t;
PowerState_t currentState = POWER_OFF;
void PowerStateMachine(void) {
switch(currentState) {
case POWER_OFF:
if(KeyOnSignal == TRUE) {
WakeUpBMS();
WakeUpMCU();
currentState = WAKE_UP;
}
break;
case WAKE_UP:
if(SelfCheckPassed() && BrakeSignal == TRUE) {
StartPreCharge();
currentState = PRE_CHARGE;
}
break;
case PRE_CHARGE:
if(PreChargeVoltage >= 0.9 * BatteryVoltage) {
CloseMainRelay();
SetReadyLight(ON);
currentState = MAIN_POWER_ON;
} else if(PreChargeTimeout == TRUE) {
SetFaultCode(FAULT_PRECHARGE_FAIL);
currentState = POWER_DOWN;
}
break;
// ... 其他状态处理
}
}
2.2 挡位管理
挡位管理,说白了就是解析驾驶员的意图。你挂 D 挡还是 R 挡,VCU 得知道,而且得安全地执行。
挡位管理有几个关键点:
- 挡位信号采集:旋钮式、电子挡杆、怀挡,不同硬件有不同的信号协议
- 挡位状态机:P→R→N→D 的切换逻辑,必须防抖、防误操作
- 安全互锁:车速 > 5km/h 时禁止挂 R 挡,这是硬性要求
经验之谈:我建议大家在挡位管理里加一个"挡位请求仲裁"模块。什么意思呢?就是驾驶员按了挡位按钮,VCU 先判断当前条件是否允许切换,允许了才执行。这样能避免很多误操作导致的安全事故。
挡位切换的时序要求很严格。我记得有一次标定,客户反映挂 D 挡后车辆响应有延迟。查了半天,发现是挡位信号滤波时间太长。后来把滤波窗口从 50ms 调到 20ms,问题就解决了。
2.3 扭矩管理
扭矩管理是 VCU 最核心的功能,也是最能体现标定水平的地方。你想想看,驾驶员踩油门,VCU 要算出来给电机发多少扭矩,这个计算过程涉及十几个输入信号。
扭矩管理的流程大致是这样的:
- 驾驶员需求解析:油门踏板开度 → 基础扭矩请求
- 限制条件叠加:电池 SOC 限制、电机温度限制、车速限制
- 扭矩仲裁:驾驶员需求 vs 安全限制,取最小值
- 扭矩输出:通过 CAN 发送扭矩指令给 MCU
| 限制条件 | 影响范围 | 典型标定值 |
|---|---|---|
| SOC 限制 | SOC < 20% 时限制峰值扭矩 | 峰值扭矩降为 60% |
| 电机温度限制 | 温度 > 120°C 时降扭 | 每升高 5°C 降 10% 扭矩 |
| 车速限制 | 车速 > 150km/h 时限制扭矩 | 扭矩上限 80Nm |
| 故障限制 | 检测到严重故障时扭矩归零 | 扭矩 = 0 |
关键点:扭矩管理的核心是"安全优先"。任何时候,限制条件叠加后的扭矩值必须小于等于驾驶员请求值。说白了,VCU 只能给比驾驶员要的少的扭矩,不能多给。
2.4 能量管理
能量管理,说白了就是怎么让车跑得更远、更省电。这部分工作,标定工程师的发挥空间很大。
能量管理主要包括:
- 能量回收策略:滑行回收、制动回收,回收扭矩的标定
- DC-DC 控制:12V 低压电池的充电管理
- 热管理协调:电池加热/冷却的能耗优化
我个人觉得能量回收是最有意思的部分。你想想看,同样的路况,回收扭矩标得大,续航能多 5%-8%,但驾驶感受会变差,乘客容易晕车。这里面的平衡,全靠标定经验。
标定技巧:我建议能量回收扭矩不要用固定值,而是根据车速和制动深度做 MAP 查表。低速时回收扭矩小一点,避免"踩刹车就点头"的感觉;高速时回收扭矩可以大一些,回收效率更高。
2.5 故障诊断与处理
故障诊断是 VCU 的"守门员"。没有故障诊断,前面四个功能再完善,出了故障也是白搭。
故障诊断分三个等级:
| 故障等级 | 定义 | VCU 响应 |
|---|---|---|
| 一级故障 | 严重安全故障(如绝缘故障) | 立即下高压,扭矩归零 |
| 二级故障 | 性能受限故障(如电机过温) | 降扭矩,点亮故障灯 |
| 三级故障 | 提示性故障(如传感器漂移) | 记录故障码,不影响驾驶 |
避坑指南:我曾经遇到过一个问题——故障误报导致车辆频繁下电。查了三天,发现是 CAN 总线干扰导致信号跳变。后来我们在故障诊断里加了"确认次数"机制,连续 3 次采样都报故障才确认,误报率直接降到零。
故障诊断的代码实现,核心是"采样→滤波→判断→响应"四个步骤。嗯,这里要注意,故障判断的周期不能太长,否则故障发生了 VCU 还不知道,那就危险了。我一般把故障诊断任务的周期设在 10ms-20ms。
// 故障诊断 - 简化示例
void FaultDiagnosisTask(void) {
// 1. 采样
uint16_t insulationResistance = GetInsulationResistance();
// 2. 滤波(滑动平均)
static uint16_t filterBuffer[5];
static uint8_t index = 0;
filterBuffer[index++] = insulationResistance;
if(index >= 5) index = 0;
uint16_t avgResistance = Average(filterBuffer, 5);
// 3. 判断
if(avgResistance < INSULATION_THRESHOLD) {
faultCounter++;
if(faultCounter >= 3) { // 连续 3 次确认
SetFaultCode(FAULT_INSULATION_FAIL);
SetFaultLevel(FAULT_LEVEL_1);
PowerDownImmediately();
}
} else {
faultCounter = 0;
}
}
好了,五个核心功能模块就讲到这里。每个模块展开都能讲一整天,今天咱们先把框架搭起来。后面几章会逐个深入,尤其是扭矩管理和能量管理,那是标定的重头戏。