4. 电池建模:等效电路模型、RC模型参数辨识、模型验证
好,咱们进入电池建模这一章。
说实话,很多做智能手表的工程师,一上来就调算法参数。结果呢?电池状态估得乱七八糟。为什么?因为模型本身就不准。你想想看,地基没打好,上面盖多高的楼都没用。
我个人习惯,做任何电池管理算法之前,先花时间把模型搞明白。模型准了,后面的事情就顺了。
4.1 为什么要给电池建模?
电池不是理想电压源。它的电压会随着电流、温度、老化程度变化。你没法用一个简单的公式描述它。
建模的目的,说白了就是找一个数学表达式,能模拟电池的真实行为。有了这个模型,我们才能估算剩余电量、预测续航、做充放电控制。
我在项目中遇到过,有人直接用开路电压查表法估算电量。结果呢?动态负载下一塌糊涂。就是因为没考虑电池的极化效应和动态响应。
4.2 等效电路模型(ECM)
等效电路模型是最常用的电池模型。它用电阻、电容这些基本元件,搭一个电路来模拟电池特性。
4.2.1 最简单的Rint模型
Rint模型就一个理想电压源串联一个内阻。公式很简单:
V(t) = OCV(SOC) - I(t) * R0
其中OCV是开路电压,R0是内阻。这个模型太粗糙了,只能用在电流变化很小的场景。智能手表这种动态负载,千万别用。
4.2.2 一阶RC模型
这个就实用多了。它加了一个RC并联网络,用来模拟电池的极化效应。
V(t) = OCV(SOC) - I(t)*R0 - Vp(t)
dVp/dt = I(t)/Cp - Vp(t)/(Rp*Cp)
Vp就是极化电压。R0是欧姆内阻,Rp是极化内阻,Cp是极化电容。
嗯,这里要注意:一阶RC模型在大多数场景下够用了。我做过对比,二阶RC模型精度提升有限,但计算量翻倍。对于智能手表的MCU来说,一阶RC是性价比最高的选择。
4.2.3 二阶RC模型
如果你对精度要求特别高,可以用二阶。它有两个RC网络,分别模拟电化学极化和浓差极化。
V(t) = OCV(SOC) - I(t)*R0 - Vp1(t) - Vp2(t)
但说实话,我在手表项目里很少用二阶。算力有限,而且参数辨识难度大,容易过拟合。
4.3 RC模型参数辨识
模型搭好了,参数怎么来?这就是参数辨识要做的事。
4.3.1 辨识方法概述
参数辨识分两类:离线辨识和在线辨识。
- 离线辨识:在实验室做特定测试,采集数据,然后用算法拟合参数。一次搞定,部署后不再更新。
- 在线辨识:设备运行时实时更新参数。能适应老化,但计算量大。
智能手表我建议用离线辨识为主,在线微调为辅。为什么?手表算力有限,跑复杂的在线算法会拖慢系统。
4.3.2 脉冲放电测试法
这是最经典的离线辨识方法。流程如下:
- 把电池充到满电,静置1小时
- 以固定电流放电一段时间(比如10秒)
- 停止放电,静置40分钟
- 重复步骤2-3,直到电池放空
采集到的电压响应曲线,可以用来提取参数。
4.3.3 参数提取方法
看电压响应曲线:
- 电流开始瞬间的电压跳变 → 欧姆内阻R0
- 放电期间的电压缓慢下降 → 极化参数Rp、Cp
- 静置期间的电压恢复 → 同样反映极化参数
具体计算可以用最小二乘法拟合。我贴一段Python代码,帮你理解:
import numpy as np
from scipy.optimize import curve_fit
# 定义一阶RC模型的电压响应函数
def rc_model(t, R0, Rp, Cp, OCV):
# t: 时间数组
# I: 电流(假设恒流)
I = 0.5 # 放电电流 0.5A
tau = Rp * Cp
V = OCV - I*R0 - I*Rp*(1 - np.exp(-t/tau))
return V
# 假设你采集了时间t和电压V数据
t_data = np.array([0, 1, 2, 3, 5, 8, 10])
V_data = np.array([4.15, 4.10, 4.08, 4.07, 4.06, 4.055, 4.05])
# 初始猜测
p0 = [0.1, 0.05, 1000, 4.2]
# 拟合
popt, pcov = curve_fit(rc_model, t_data, V_data, p0=p0)
R0, Rp, Cp, OCV = popt
print(f"R0={R0:.4f}Ω, Rp={Rp:.4f}Ω, Cp={Cp:.1f}F")
4.3.4 不同SOC下的参数变化
电池参数不是常数。R0、Rp、Cp都会随SOC变化。所以你要在不同SOC点做测试,然后建立参数-SOC的查找表。
| SOC (%) | R0 (mΩ) | Rp (mΩ) | Cp (F) |
|---|---|---|---|
| 100 | 45 | 30 | 1200 |
| 80 | 48 | 32 | 1150 |
| 60 | 52 | 35 | 1080 |
| 40 | 58 | 40 | 950 |
| 20 | 68 | 48 | 800 |
| 0 | 85 | 60 | 600 |
4.4 模型验证
参数辨识完了,怎么知道模型准不准?验证!
4.4.1 验证数据集
千万别用辨识用的数据来验证。那叫过拟合检验,没有意义。你要用独立的测试数据。
我建议准备三种测试工况:
- 恒流放电:验证基本精度
- 动态电流:模拟实际使用(比如看视频、刷网页)
- 脉冲负载:模拟通信、GPS等突发大电流
4.4.2 误差指标
常用的指标有:
- RMSE(均方根误差):反映整体偏差
- MAE(平均绝对误差):直观易懂
- 最大误差:看最坏情况
对于智能手表,我一般要求RMSE小于20mV,最大误差不超过50mV。超过这个范围,算法估计的电量就会不准。
4.4.3 验证结果分析
把模型预测的电压和实测电压画在一起对比。如果偏差有规律,说明模型结构有问题。如果偏差随机,可能是参数精度不够。
# 验证代码示例
import matplotlib.pyplot as plt
# 假设你有实测电压V_real和模型预测V_pred
time = np.arange(len(V_real))
error = V_real - V_pred
rmse = np.sqrt(np.mean(error**2))
mae = np.mean(np.abs(error))
max_err = np.max(np.abs(error))
print(f"RMSE: {rmse*1000:.1f}mV")
print(f"MAE: {mae*1000:.1f}mV")
print(f"Max Error: {max_err*1000:.1f}mV")
plt.figure(figsize=(10, 6))
plt.subplot(2, 1, 1)
plt.plot(time, V_real, label='Real')
plt.plot(time, V_pred, '--', label='Model')
plt.ylabel('Voltage (V)')
plt.legend()
plt.subplot(2, 1, 2)
plt.plot(time, error*1000)
plt.ylabel('Error (mV)')
plt.xlabel('Time (s)')
plt.show()
4.5 实战建议
最后,给你几个我踩过坑后的建议:
- 别追求完美模型:一阶RC模型够用了。把精力放在参数辨识的准确性上。
- 注意采样率:电压采样率至少10Hz,才能捕捉到电流跳变时的电压响应。
- 考虑温度补偿:手表戴在手上,温度变化范围大。一定要做温度补偿。
- 验证要全面:不同SOC、不同温度、不同负载都要测。我曾经只做了常温验证,结果低温下模型完全不能用。
好了,电池建模这部分就讲到这里。下一章我们聊聊如何用这个模型来做SOC估计。到时候你会发现,模型建好了,算法调起来就顺手多了。