3、电流传感器校准:ADC偏移校准、增益校准、温度补偿
电流测量,是电池管理算法里最基础也最要命的一环。你想想看,如果电流都测不准,那SOC估算、健康度评估,全都会跟着跑偏。我这些年调试过的智能手表,十块里有七八块,问题根源都出在电流传感器校准没做好。
说白了,电流传感器校准就三件事:ADC偏移校准、增益校准、温度补偿。这三件事做扎实了,电流数据才能用。咱们一个一个说。
3.1 ADC偏移校准:把零点的“虚电”清掉
什么是ADC偏移?就是当实际电流为零时,ADC读出来的值却不是零。我遇到过最夸张的一次,某款手表在待机状态下,ADC居然读出了15mA的“电流”。这要是直接拿去算电量,一天下来能多算30%的消耗。
为什么会这样?ADC内部有偏置电压,运放也有失调电压,再加上PCB走线引入的微小压差。这些因素叠加起来,就形成了偏移误差。
偏移校准的方法其实很简单:让电流强制为零,然后记录ADC的输出值。这个值就是偏移量,后续每次采样都把它减掉。
核心公式:
I实际 = (ADC原始 - ADC偏移) × 增益系数
具体怎么做?我习惯在系统上电后、负载还没开启之前,先做一次偏移校准。这时候电池没有充放电,电流理论上就是零。连续采样64次或128次,取平均值作为偏移量。为什么要取平均?因为单次采样有噪声,平均一下更稳。
// 偏移校准示例代码
#define OFFSET_SAMPLES 128
int32_t adc_offset_calibrate(void) {
int32_t sum = 0;
for (int i = 0; i < OFFSET_SAMPLES; i++) {
sum += read_adc_raw(); // 读取ADC原始值
delay_us(10); // 间隔10微秒
}
return sum / OFFSET_SAMPLES; // 返回偏移量
}
我的小技巧:偏移校准不要只做一次。温度变化、电源电压波动都会让偏移量漂移。我建议每隔5分钟或者每次从深度睡眠唤醒后,重新做一次偏移校准。代价很小,收益很大。
3.2 增益校准:让读数跟实际电流对上
偏移校准搞定了零点,但斜率对不对呢?这就是增益校准要解决的问题。
增益误差,说白了就是ADC读数的“放大倍数”不准。比如实际流过1A电流,ADC读出来只有0.95A,那增益误差就是5%。
我曾经遇到过一款手表,充电电流显示总是偏小。用户充了2小时,手表显示只充了80%,实际上电池已经满了。查到最后,发现是电流检测电阻的精度不够,加上运放增益有偏差,导致测量值整体偏低了12%。
增益校准需要一个已知的精确电流源。在产线上,通常用高精度万用表或者专门的电流校准仪。给手表通一个标准电流(比如100mA),然后记录ADC的读数。
增益系数计算公式:
增益系数 = 标准电流值 / (ADC测量 - ADC偏移)
这个系数,每个设备都不一样。因为电阻、运放、ADC都有个体差异。所以增益校准必须在每块手表出厂前单独做,不能用一个固定值。
| 校准点 | 标准电流 | ADC原始值 | 减去偏移后 | 增益系数 |
|---|---|---|---|---|
| 零点 | 0 mA | 512 | 0 | - |
| 正向点 | 100 mA | 1024 | 512 | 0.1953 mA/LSB |
| 负向点 | -100 mA | 0 | -512 | 0.1953 mA/LSB |
注意:增益校准最好在正负两个方向都做。有些ADC或运放的正负增益并不完全对称。如果只校准正向,反向测量时误差会翻倍。我吃过这个亏,后来就改成双向校准了。
3.3 温度补偿:别让温度毁了你的校准
偏移和增益都校准好了,是不是就万事大吉了?不是。温度一变,一切归零。
电流检测电阻的阻值会随温度变化,运放的失调电压也会随温度漂移。智能手表戴在手腕上,温度从冬天的零下10度到夏天的40度,跨度超过50度。如果不做温度补偿,校准精度会大打折扣。
我记得有一次做低温测试,把手表放进-20度的恒温箱。结果电流测量值直接漂了8%。一开始以为是代码bug,查了两天才发现是检测电阻的温度系数在作怪。
温度补偿通常有两种做法:
- 查表法:在多个温度点下测量偏移和增益,建立温度-补偿值对应表。运行时根据当前温度查表插值。
- 公式法:用多项式拟合温度漂移曲线,运行时直接计算补偿值。
我个人更推荐查表法。原因很简单:温度漂移往往不是线性的,用公式拟合高阶多项式,计算量不小,而且容易过拟合。查表法虽然占用一点Flash空间,但精度可控,调试也方便。
// 温度补偿查表示例
typedef struct {
int16_t temperature; // 温度,单位0.1度
int16_t offset_delta; // 偏移变化量
int16_t gain_delta; // 增益变化量,单位ppm
} temp_comp_entry_t;
// 假设在-20, 0, 25, 50, 70度五个点做了标定
const temp_comp_entry_t comp_table[5] = {
{-200, 15, 1200}, // -20度时偏移增加15,增益增加1200ppm
{ 0, 5, 500}, // 0度时偏移增加5,增益增加500ppm
{ 250, 0, 0}, // 25度时为零点(基准点)
{ 500, -3, -400}, // 50度时偏移减少3,增益减少400ppm
{ 700, -8, -900} // 70度时偏移减少8,增益减少900ppm
};
int32_t apply_temp_compensation(int32_t raw_adc, int16_t current_temp) {
// 查表并线性插值,得到当前温度下的补偿值
// 然后修正偏移和增益
// 具体插值代码略...
}
避坑指南:我曾经在量产时发现,同一批手表在高温下的电流测量值差异很大。排查后发现,是PCB布局导致部分手表的热量无法均匀传导到温度传感器。温度传感器测到的温度比实际检测电阻的温度低了5度。所以,温度传感器的位置一定要靠近电流检测电阻,最好紧贴着放。
3.4 校准流程总结
好了,把这三步串起来,就是完整的电流传感器校准流程:
- 第一步:上电后,无负载状态下做偏移校准,记录ADC偏移量。
- 第二步:通入标准电流,做增益校准,计算增益系数。正反方向都要做。
- 第三步:在不同温度下标定偏移和增益的变化,建立温度补偿表。
- 第四步:运行时,先读温度,查表得到补偿值,再修正偏移和增益,最后算出实际电流。
你可能会问:这些校准参数存哪里?我习惯存在Flash的末尾区域,专门划出一块校准参数区。每块手表出厂前写入,运行时只读不写。这样既安全又高效。
电流传感器校准,看起来是小事,但做不好就是大事。我见过太多项目,算法模型建得漂漂亮亮,最后死在数据源头上。校准工作虽然枯燥,但它是整个电池管理系统的地基。地基稳了,上面的楼才能盖得高。