一、电源监控的核心挑战

在嵌入式产品中,电源监控不仅是读取几个电压值那么简单。电池供电设备面临三大痛点:

  • 精度不足:ADC参考电压漂移、分压电阻误差导致电压测量偏差超过5%。
  • 动态响应慢:负载突变时,电压跌落无法及时捕获,可能触发误复位。
  • 电量估算不准:简单电压查表法在锂电池放电平台期误差极大,而纯库仑计法又受温度、老化影响。

因此,一个实用的电源监控方案需要硬件采样电路、高精度ADC/传感器、以及智能估算算法三者协同。

二、硬件采样电路设计

电压采样:分压电阻与高阻输入

对于MCU内置ADC(通常0~3.3V),需将电池电压(如4.2V~3.0V)分压到安全范围。

// 分压计算:Vout = Vin * R2 / (R1+R2)
// 例:R1=100kΩ, R2=100kΩ,则Vout = Vin/2,最大2.1V(安全)
// 注意:选用1%精度电阻,并联0.1uF电容滤除高频噪声

关键点

  • 分压电阻阻值不宜过小(避免漏电),也不宜过大(增加ADC源阻抗,导致采样误差)。建议10k~100kΩ。
  • 若MCU ADC输入阻抗较低,需加运放跟随器(如OPA333)隔离。

电流采样:低侧与高侧检测

  • 低侧检测:采样电阻串联在GND回路,简单但会抬高GND电位,影响系统。
  • 高侧检测:采样电阻在电源正极,需差分放大器或专用电流检测芯片(如INA226)。

推荐使用INA226(TI),它集成16位ADC、I2C接口,支持0~36V共模电压,可同时测量电压和电流,非常适合嵌入式系统。

// INA226关键寄存器
#define INA226_ADDR 0x40  // A0=0, A1=0
#define REG_CONFIG 0x00
#define REG_SHUNT  0x01   // 电流采样电压(uV)
#define REG_BUS    0x02   // 总线电压(mV)
#define REG_CALIB  0x05

三、软件配置与数据读取(STM32示例)

初始化I2C并配置INA226

#include "stm32f1xx_hal.h"

I2C_HandleTypeDef hi2c1;

void INA226_Init(void) {
    uint16_t config = 0x4127;  // AVG=16次平均, VSHUNT=1100us, VBUS=1100us, 连续模式
    uint8_t data[2] = {config >> 8, config & 0xFF};
    HAL_I2C_Mem_Write(&hi2c1, INA226_ADDR<<1, REG_CONFIG, 1, data, 2, 100);

    // 校准:设置电流LSB。假设采样电阻Rshunt=0.01Ω,最大电流5A
    // 电流LSB = 5A / 32768 ≈ 0.1526mA,取0.1mA,则CALIB = 0.00512 / (LSB * Rshunt)
    // 0.00512 / (0.0001 * 0.01) = 5120
    uint16_t calib = 5120;
    data[0] = calib >> 8; data[1] = calib & 0xFF;
    HAL_I2C_Mem_Write(&hi2c1, INA226_ADDR<<1, REG_CALIB, 1, data, 2, 100);
}

// 读取电压(mV)和电流(mA)
void INA226_Read(float *voltage_mV, float *current_mA) {
    uint8_t buf[2];
    uint16_t raw;

    // 读总线电压
    HAL_I2C_Mem_Read(&hi2c1, INA226_ADDR<<1, REG_BUS, 1, buf, 2, 100);
    raw = (buf[0] << 8) | buf[1];
    *voltage_mV = raw * 1.25f;  // 每个LSB=1.25mV

    // 读分流电压
    HAL_I2C_Mem_Read(&hi2c1, INA226_ADDR<<1, REG_SHUNT, 1, buf, 2, 100);
    raw = (buf[0] << 8) | buf[1];
    // 电流 = 分流电压 / 采样电阻,但已通过校准寄存器换算,直接读电流寄存器?
    // 实际上电流值需通过计算:电流 = 分流电压(uV) / Rshunt(mΩ) / 1000 (mA)
    // 但更简单:读取功率寄存器或直接计算。这里用分流电压计算
    float shunt_uV = (int16_t)raw * 2.5f;  // 每个LSB=2.5uV
    *current_mA = shunt_uV / 10.0f;  // Rshunt=0.01Ω=10mΩ,uV/10 = mA
}

电池电量估算:从库仑计到EKF

方法1:开路电压法(OCV)

  • 原理:电池静置后电压与SOC有固定曲线。
  • 缺点:需静置1小时以上,无法动态更新。

方法2:库仑计法(电流积分)

  • 原理:SOC = SOC0 + (1/Q_total) * ∫I dt。
  • 实现简单,但存在累积误差,需定期校准。
// 库仑计实现(基于定时器中断,每100ms累加)
float soc_percent = 100.0f;
float battery_capacity_mAh = 2000.0f;  // 电池容量
float current_mA;

void Timer_ISR(void) {
    // 假设每100ms调用一次
    float dt_h = 0.1f / 3600.0f;  // 小时
    soc_percent -= (current_mA * dt_h) / battery_capacity_mAh * 100.0f;
    if (soc_percent < 0) soc_percent = 0;
    if (soc_percent > 100) soc_percent = 100;
}

方法3:扩展卡尔曼滤波(EKF)

  • 融合OCV和库仑计,动态估计SOC和电池内阻。
  • 适合高精度场景,但计算量大,需浮点运算。
// EKF简化模型(状态:SOC,观测:电压)
// 状态方程:SOC(k+1) = SOC(k) - (I*dt)/Q
// 观测方程:V(k) = OCV(SOC) - I*R0 - V_RC
// 实际工程中需查表拟合OCV曲线

对于大多数嵌入式应用,库仑计+定期OCV校准是性价比最高的方案。建议在系统空闲时(电流接近0)测量电压,查OCV表修正SOC。

四、工程实践与注意事项

1. 采样噪声抑制

  • 硬件:在采样电阻两端并联100nF电容,但注意影响带宽。
  • 软件:使用滑动平均滤波或中值滤波,INA226内置16次平均已足够。

2. 温度补偿

  • 锂电池容量随温度下降,库仑计需乘以温度系数(如-0.5%/℃)。
  • 使用NTC测量电池温度,修正SOC计算。

3. 低功耗设计

  • 在待机模式关闭INA226(通过配置寄存器或断开电源),仅保留MCU的RTC唤醒。
  • 采样频率自适应:负载变化快时提高采样率,稳定时降低。

4. 校准流程

  • 出厂前用精密电源校准分压系数和采样电阻值。
  • 软件中存储校准系数,如电压增益和偏移。
// 校准示例:实际电压 = 读取值 * gain + offset
float voltage_real = voltage_mV * 1.0012f + 0.3f;  // 通过万用表比对得出

五、总结

电源监控设计需平衡精度、成本和复杂度。对于大多数产品,采用INA226等专用芯片配合库仑计算法即可满足需求。若追求极致精度,可引入EKF,但需评估MCU算力。最后,务必在真实负载下测试动态响应和电量估算误差,并根据结果调整滤波参数和校准系数。

希望本文能为你构建可靠的电源监控系统提供参考。如有疑问,欢迎在评论区交流。