1. 项目背景与核心目标
在电动汽车和储能系统的开发中,车载充电机(OBC)的电池充电协议设计一直是工程师面临的关键挑战。最近我在一个实际项目中遇到了一个典型问题:如何在现有硬件架构下实现更精准的电池充电控制?这个问题的核心在于如何有效利用VBAT(电池电压)信号来优化充电过程。
现有的PFC(功率因数校正)+LLC(谐振变换器)控制架构已经能够稳定运行,但充电策略还停留在比较基础的输出电压/电流控制阶段。通过引入VBAT作为核心控制变量,我们可以实现:
- 更精准的电池状态识别
- 更安全的充电过程管理
- 更高效的能源转换
- 更完善的故障保护机制
这个方案最吸引人的地方在于,它完全基于现有硬件平台,不需要额外增加成本,只需通过软件升级就能显著提升系统性能。下面我将详细解析这个方案的实现细节。
2. 硬件基础与采样系统
2.1 现有ADC采样架构
项目现有的ADC采样系统已经相当完善,包含多路关键信号采集:
c复制// 全局帧结构示例
typedef struct {
uint16_t vout_raw; // 输出电压原始值
uint16_t isense_raw; // 输出电流原始值
uint16_t vbt_raw; // 电池电压采样值(PC5/VBT_SENSE_CH)
uint16_t v3v3_raw; // 3.3V监测电压
uint16_t tsense_pfc_raw;// PFC温度采样
uint16_t tsense_llc_raw;// LLC温度采样
} adc_global_frame_t;
这些采样值通过adc1_sample_aux_1khz()函数在1kHz的控制节拍下定期更新,为充电控制提供了实时数据支持。
2.2 VBAT采样电路设计要点
VBAT采样电路的设计有几个关键考虑因素:
- 分压电阻选择:需要根据电池组最高电压确定分压比,同时考虑电阻精度和温度系数
- 滤波设计:采用两级RC滤波,时间常数需与采样频率匹配
- 保护电路:TVS管用于过压保护,确保异常情况下不会损坏ADC输入
- PCB布局:采样走线应远离高频开关节点,减少噪声干扰
实际调试中发现,VBAT采样电路的稳定性直接影响整个充电系统的可靠性。建议在PCB设计阶段就预留π型滤波的位置,方便后续调试调整参数。
3. 充电协议状态机设计
3.1 核心状态定义
基于VBAT的充电状态机包含以下主要状态:
| 状态 | 触发条件 | 执行动作 | 退出条件 |
|---|---|---|---|
| IDLE | 系统上电 | 检测VBAT | VBAT>Vmin |
| PRE_CHARGE | VBAT<Vmin | 限流充电 | VBAT≥Vmin |
| CC_CHARGE | VBAT正常 | 恒流充电 | VBAT≥Vfloat |
| CV_CHARGE | VBAT≥Vfloat | 恒压充电 | I≤Iterm |
| FINISHED | I≤Iterm | 停止充电 | 用户操作 |
| FAULT | 异常条件 | 保护动作 | 故障清除 |
3.2 状态转换逻辑实现
状态机的实现需要考虑以下几个关键点:
- 滞回比较:状态转换阈值应设置适当的滞回区间,防止频繁切换
- 时间滤波:状态判断应加入适当的时间窗口滤波,避免误动作
- 故障优先:任何状态下出现故障都应立即进入保护状态
- 平滑过渡:状态切换时控制参数应渐变,避免输出突变
c复制// 状态机处理函数示例
void charge_state_machine_1kHz(void)
{
static uint32_t state_timer = 0;
// 故障检测具有最高优先级
if(check_fault_conditions()){
current_state = STATE_FAULT;
state_timer = 0;
return;
}
switch(current_state){
case STATE_IDLE:
if(vbat > VMIN_THRESHOLD){
current_state = STATE_PRE_CHARGE;
state_timer = 0;
}
break;
case STATE_PRE_CHARGE:
state_timer++;
if(vbat >= VMIN_THRESHOLD + HYST){
if(state_timer > DEBOUNCE_TIME){
current_state = STATE_CC_CHARGE;
state_timer = 0;
}
}
break;
// 其他状态处理...
}
}
4. VBAT在充电控制中的应用
4.1 充电阶段划分依据
VBAT作为核心控制变量,主要参与以下决策:
- 充电阶段判断:根据VBAT与预设阈值的比较结果确定当前充电阶段
- 充电参数调整:不同阶段采用不同的电压/电流设定值
- 电池健康度评估:通过VBAT变化趋势分析电池状态
- 故障检测:VBAT异常波动可能指示连接问题或电池故障
4.2 控制算法实现细节
在1kHz控制节拍下,VBAT参与控制的典型流程如下:
- ADC采样值转换为实际电压值
- 低通滤波处理消除高频噪声
- 与各阈值比较确定当前控制模式
- 计算所需的PFC/LLC控制参数
- 输出PWM占空比更新
c复制// VBAT参与控制的示例代码
void charge_control_1kHz(void)
{
// 1. 获取并转换VBAT采样值
float vbat = adc_to_voltage(g.vbt_raw);
// 2. 一阶低通滤波
static float vbat_filtered = 0.0f;
vbat_filtered = 0.9f * vbat_filtered + 0.1f * vbat;
// 3. 根据VBAT确定充电模式
if(vbat_filtered < V_MIN){
// 预充电模式
set_charge_current(I_PRE);
set_charge_voltage(V_MAX);
}
else if(vbat_filtered < V_FLOAT){
// 恒流充电模式
set_charge_current(I_CC);
set_charge_voltage(V_MAX);
}
else {
// 恒压充电模式
set_charge_current(I_MAX); // 实际由闭环控制
set_charge_voltage(V_FLOAT);
}
// 4. 执行闭环控制
run_pfc_llc_control();
}
5. 通信协议与故障处理
5.1 充电过程报文定义
系统需要与BMS(电池管理系统)进行通信,典型的报文格式如下:
| 字节 | 内容 | 说明 |
|---|---|---|
| 0 | 帧头 | 0x55 |
| 1 | 命令字 | 0x01:状态查询 0x02:参数设置 |
| 2-3 | VBAT | 电池电压(单位mV) |
| 4-5 | IOUT | 输出电流(单位mA) |
| 6 | 状态 | 充电状态/故障代码 |
| 7 | 校验和 | 前面7字节的累加和 |
5.2 故障分级与处理策略
基于VBAT的故障检测主要包括:
- VBAT开路检测:长时间VBAT=0且IOUT=0
- VBAT短路检测:VBAT突降伴随IOUT突增
- VBAT异常波动:短时间内变化超过合理范围
- VBAT超限:超过电池规格书规定的范围
故障处理采用分级策略:
- 一级故障:警告并记录,不影响充电
- 二级故障:降功率运行
- 三级故障:立即停止充电
6. 实际调试经验与优化
6.1 VBAT采样校准技巧
在实际调试中发现几个关键点:
- ADC参考电压校准:3.3V参考电压的实际值需要用高精度万用表测量后校准
- 分压电阻精度:1%精度的电阻在实际应用中可能仍会产生较大误差,建议:
- 使用0.1%精度的分压电阻
- 或者在软件中为每个通道添加校准系数
- 温度补偿:电阻值会随温度变化,高温环境下需要特别注意
6.2 抗干扰设计
开关电源环境中存在大量高频噪声,针对VBAT采样的抗干扰措施包括:
-
硬件方面:
- 增加π型滤波电路
- 采用屏蔽线连接
- 确保良好接地
-
软件方面:
- 采用滑动平均滤波
- 添加中值滤波预处理
- 设置合理的变化率限制
c复制// 改进的VBAT采样处理
float process_vbat_sample(uint16_t raw)
{
#define SAMPLE_HISTORY 8
static uint16_t samples[SAMPLE_HISTORY];
static uint8_t index = 0;
// 更新采样缓冲区
samples[index++] = raw;
if(index >= SAMPLE_HISTORY) index = 0;
// 中值滤波
uint16_t temp[SAMPLE_HISTORY];
memcpy(temp, samples, sizeof(temp));
bubble_sort(temp, SAMPLE_HISTORY);
uint16_t median = temp[SAMPLE_HISTORY/2];
// 转换为电压值
float voltage = median * VREF / 4096.0f / DIVIDER_RATIO;
// 变化率限制
static float last_voltage = 0.0f;
const float MAX_DELTA = 0.1f; // 最大允许100mV变化
if(fabs(voltage - last_voltage) > MAX_DELTA){
if(voltage > last_voltage){
voltage = last_voltage + MAX_DELTA;
}else{
voltage = last_voltage - MAX_DELTA;
}
}
last_voltage = voltage;
return voltage;
}
7. 系统集成与测试
7.1 模块化实现建议
为了便于维护和升级,建议采用如下模块划分:
-
硬件抽象层(HAL):
- ADC采样驱动
- PWM输出驱动
- 通信接口驱动
-
应用层(APP):
- 充电状态机
- 控制算法
- 故障处理
- 通信协议
-
配置层(CFG):
- 电池参数配置
- 保护阈值设置
- 校准参数存储
7.2 测试方案设计
完整的测试应包含以下环节:
-
单元测试:
- VBAT采样精度测试
- 状态机逻辑测试
- 控制算法验证
-
集成测试:
- 充电全过程测试
- 模式切换测试
- 故障注入测试
-
系统测试:
- 不同电池类型兼容性测试
- 温度变化测试
- 长期稳定性测试
测试中需要特别关注VBAT在以下边界条件下的表现:
- 电池连接瞬间的VBAT变化
- 充电结束时的VBAT稳定性
- 故障恢复后的VBAT采样恢复
8. 性能优化方向
基于VBAT的充电控制还可以进一步优化:
- 自适应充电算法:根据VBAT变化趋势动态调整充电参数
- 电池健康度监测:通过充电过程中的VBAT特性分析电池状态
- 温度补偿:结合温度传感器数据对VBAT进行补偿
- 学习功能:记录历史充电数据优化后续充电策略
在实际项目中,我发现一个有趣的优化点:通过分析VBAT在恒流充电阶段的上升斜率,可以估算电池的内阻变化,从而提前发现电池老化问题。这个功能实现起来并不复杂,但对提升系统价值很有帮助。
c复制// 电池内阻估算示例
void estimate_battery_resistance(void)
{
static float vbat_start;
static uint32_t cc_start_time;
if(charge_state == STATE_CC_CHARGE){
if(cc_phase_just_started){
vbat_start = vbat_filtered;
cc_start_time = system_tick;
}
else {
float delta_v = vbat_filtered - vbat_start;
uint32_t delta_t = system_tick - cc_start_time;
float slope = delta_v / (delta_t * 0.001f); // V/s
// 根据斜率估算内阻
float r_estimate = slope / I_CC;
update_battery_health(r_estimate);
}
}
}
这个方案成功的关键在于平衡实时性和准确性。VBAT采样和处理需要在1kHz的控制周期内完成,同时又要保证数据的可靠性。经过多次迭代,我们最终采用的方案是在保持核心算法简洁的前提下,通过精心设计的滤波和故障检测机制来确保系统稳定性。
