4、电流采样与霍尔传感器调试

电流采样,是BMS系统里最核心的环节之一。说白了,电池的SOC估算准不准,很大程度上就取决于电流测得好不好。我见过不少项目,电压采样做得漂漂亮亮,结果电流一塌糊涂,最后SOC飘得没法看。今天咱们就把这块掰开揉碎了讲清楚。

4.1 霍尔传感器选型与供电

霍尔传感器选型,我个人的习惯是先看量程。你想想看,如果电池包最大持续电流200A,你选个300A的传感器,那在小电流区域分辨率就太差了。反过来,选小了又容易饱和。

选型时重点关注这几个参数:

  • 量程:建议取最大工作电流的1.2~1.5倍
  • 带宽:至少1kHz以上,不然动态响应跟不上
  • 线性度:0.5%以内,否则校准起来很麻烦
  • 温度漂移:这个容易被忽略,我踩过坑
我的经验:曾经有个项目,选了某品牌的霍尔传感器,常温下精度很好。结果夏天户外一跑,温度到65℃,零点漂移了将近50mV,换算成电流误差得有5A。从那以后,我选型必看温漂系数,最好选带温度补偿的型号。

供电方面,霍尔传感器通常需要隔离电源。我建议用DC-DC隔离模块,输出纹波控制在50mV以内。供电电压不稳,直接反映在输出上,这个坑别踩。

4.2 电流采样电路调试

电流采样电路,常见的有两种:差分运放和隔离运放。我分别说说。

4.2.1 差分运放方案

差分运放电路,说白了就是把霍尔传感器输出的差分信号转成单端信号,同时做一级放大。电路结构不复杂,但调试时要注意共模电压。

// 典型差分放大电路参数
R1 = R3 = 10kΩ
R2 = R4 = 100kΩ
增益 = R2/R1 = 10倍
共模抑制比(CMRR) ≥ 80dB

调试步骤我一般这样走:

  1. 先不给电流,测量运放输出,应该接近0V
  2. 给一个已知小电流,比如10A,看输出是否对应
  3. 逐步加大电流,检查线性度
  4. 重点测一下正负半周是否对称
注意:差分运放的输入端,一定要加RC滤波。我见过有人省了这两个电容,结果高频噪声直接耦合进来,ADC读数跳得跟心电图似的。

4.2.2 隔离运放方案

隔离运放,适合高压系统。比如800V平台,你总不能让采样电路和高压共地吧?隔离运放内部有磁隔离或容隔离,把高低压侧隔开。

调试隔离运放时,有个容易忽略的点:隔离侧的地和信号侧的地,不能直接连。我刚开始做的时候犯过这个错,一上电就把隔离芯片烧了。

4.3 电流零点漂移校准

零点漂移,是霍尔传感器的通病。为什么会这样?因为霍尔元件本身有残余电压,加上温度变化,零点就跑了。

校准方法,我推荐两步走:

  • 硬件校准:在电路板上加一个调零电位器,或者用DAC输出一个反向偏置电压
  • 软件校准:系统上电后,先判断电流为零(比如继电器断开时),采样此时的ADC值作为零点偏移
// 软件零点校准示例
#define ZERO_SAMPLE_COUNT 100

uint16_t zero_offset = 0;

void calibrate_zero_offset(void) {
    uint32_t sum = 0;
    for(int i = 0; i < ZERO_SAMPLE_COUNT; i++) {
        sum += read_adc();
        delay_ms(1);
    }
    zero_offset = sum / ZERO_SAMPLE_COUNT;
    // 保存到EEPROM
    save_to_eeprom(zero_offset);
}

int16_t get_corrected_current(void) {
    int16_t raw = read_adc();
    return raw - (int16_t)zero_offset;
}
避坑指南:我曾经遇到过一个问题:零点校准做得好好的,但每次重启后零点都不一样。查了半天,发现是ADC参考电压不稳定。后来加了独立的参考电压芯片,问题才解决。所以,校准之前,先确保参考电压是准的。

4.4 充放电电流方向判断

电流方向判断,直接决定了你是充电还是放电。霍尔传感器输出有正负之分,但不同厂家的定义可能不一样。

我一般这样处理:

  • 先确认传感器输出极性:正电流对应充电还是放电?
  • 在代码里定义一个方向标志位
  • 根据ADC值正负,设置充放电状态
typedef enum {
    CURRENT_IDLE = 0,
    CURRENT_CHARGE,
    CURRENT_DISCHARGE
} current_dir_t;

current_dir_t get_current_direction(int16_t current) {
    if(abs(current) < DEAD_ZONE) {
        return CURRENT_IDLE;  // 死区处理,防止抖动
    }
    return (current > 0) ? CURRENT_CHARGE : CURRENT_DISCHARGE;
}

这里有个细节:死区设置。如果电流很小,比如0.5A以内,你硬要判断方向,那就会频繁切换。我一般设个死区,小于这个值就当零电流处理。

4.5 电流积分与库仑计初始值设置

库仑计,说白了就是对电流做时间积分,算出充进去了多少电,放出来了多少电。公式很简单:

ΔSOC = (∫I dt) / 电池总容量

但实际做起来,坑不少。

4.5.1 积分算法实现

我推荐用梯形积分法,比矩形积分更准一些:

// 梯形积分法
float coulomb_count = 0.0f;
float previous_current = 0.0f;
uint32_t previous_time = 0;

void update_coulomb_count(float current, uint32_t timestamp_ms) {
    float dt = (timestamp_ms - previous_time) / 1000.0f;  // 转成秒
    float avg_current = (current + previous_current) / 2.0f;
    coulomb_count += avg_current * dt / 3600.0f;  // 转成Ah
    
    previous_current = current;
    previous_time = timestamp_ms;
}

4.5.2 初始值设置

库仑计的初始值,不能随便设。我见过有人直接设成0,结果SOC从一开始就是错的。

正确的做法:

  • 系统首次上电时,根据开路电压查表得到初始SOC
  • 把这个SOC换算成对应的库仑计初始值
  • 每次系统休眠前,保存当前库仑计值到EEPROM
  • 下次唤醒时,从EEPROM恢复
重要提醒:库仑计误差会累积。我做过测试,如果电流采样误差0.5%,运行10小时后,SOC误差可能达到5%以上。所以,一定要配合电压校准,定期修正SOC。这个后面章节会详细讲。

知识体系总览

下面这张图,把电流采样与霍尔传感器调试的核心逻辑串起来了。你可以对照着看,心里有个全局概念。

电流采样与霍尔传感器调试知识体系 电流采样系统 霍尔传感器选型与供电 电流采样电路调试 零点漂移校准 量程选择 隔离供电 差分运放 隔离运放 硬件校准 软件校准 充放电电流方向判断 库仑计初始值设置 极性确认 死区处理 积分算法 初始值恢复 目标:实现高精度、低漂移的电流测量与SOC估算

好了,电流采样这块的内容就这些。记住一个原则:电流测不准,后面所有算法都是空中楼阁。所以调试时多花点时间,值得。


专注资料整理