嵌入式电源监控实战:电压/电流采样与电池电量估算的完整方案
👁 8 阅读 · 2026-08-20 · 嵌入式 电源
在嵌入式系统中,电源监控是保障设备稳定运行的核心环节,尤其对于电池供电的便携设备,精准的电压电流采样和电量估算直接关系到续航优化与安全保护。本文从硬件采样电路设计、ADC与传感器选型出发,深入讲解电压分压、电流检测放大器(如INA226)的使用,并对比开路电压法、库仑计法及扩展卡尔曼滤波(EKF)在电池SOC估算中的优劣。通过STM32平台上的完整代码示例,演示如何配置I2C读取INA226数据、校准偏移,以及实现基于电流积分的动态电量更新。文章还涵盖采样噪声抑制、温度补偿和低功耗策略等工程细节,帮助开发者构建可靠、高效的电源监控子系统。
## 一、电源监控的核心挑战
在嵌入式产品中,电源监控不仅是读取几个电压值那么简单。电池供电设备面临三大痛点:
- **精度不足**:ADC参考电压漂移、分压电阻误差导致电压测量偏差超过5%。
- **动态响应慢**:负载突变时,电压跌落无法及时捕获,可能触发误复位。
- **电量估算不准**:简单电压查表法在锂电池放电平台期误差极大,而纯库仑计法又受温度、老化影响。
因此,一个实用的电源监控方案需要硬件采样电路、高精度ADC/传感器、以及智能估算算法三者协同。
## 二、硬件采样电路设计
### 电压采样:分压电阻与高阻输入
对于MCU内置ADC(通常0~3.3V),需将电池电压(如4.2V~3.0V)分压到安全范围。
```c
// 分压计算: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共模电压,可同时测量电压和电流,非常适合嵌入式系统。
```c
// 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
```c
#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。
- 实现简单,但存在累积误差,需定期校准。
```c
// 库仑计实现(基于定时器中断,每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和电池内阻。
- 适合高精度场景,但计算量大,需浮点运算。
```c
// 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. 校准流程
- 出厂前用精密电源校准分压系数和采样电阻值。
- 软件中存储校准系数,如电压增益和偏移。
```c
// 校准示例:实际电压 = 读取值 * gain + offset
float voltage_real = voltage_mV * 1.0012f + 0.3f; // 通过万用表比对得出
```
## 五、总结
电源监控设计需平衡精度、成本和复杂度。对于大多数产品,采用INA226等专用芯片配合库仑计算法即可满足需求。若追求极致精度,可引入EKF,但需评估MCU算力。最后,务必在真实负载下测试动态响应和电量估算误差,并根据结果调整滤波参数和校准系数。
希望本文能为你构建可靠的电源监控系统提供参考。如有疑问,欢迎在评论区交流。