电量(SOC)算法

除了参数的监控与保护之外,作为BMS系统,其中最重要的功能还有一项,那便是SOC的计算。
  
  SOC,全称是State of Charge,系统荷电状态,也叫剩余电量,代表的是电池使用一段时间或长期搁置不用后的剩余容量与其完全充电状态的容量的比值,常用百分数表示。
  
  其取值范围为0~100,当SOC=0时表示电池放电完全,当SOC=100时表示电池完全充满。
  
  那么SOC有什么意义呢?
  
  任何一个产品,对于一般的终端用户而言,如果对其直接提供电压、电流之类的电池参数,那么用户可能十分费解,因为对他们来说,使用的电源产品唯一能够理解的,似乎就只有电量。
  
  比如当我询问你的手机还剩多少电?你肯定不会回答电池的端电压还有3.54V,而是直接告诉我还剩大概80%。电动车也是一样,我们甚至可以粗糙的用几个柱状图来表示电池当前的状况,这样也总比直接提供准确的电压要好理解很多,即使不准,但能让用户直观的理解工程师想要表达的意思。
  
  因此,计算出准确的SOC,不仅能提升用户体验,而且好能延长产品的使用寿命,这对于任何一块产品而言意义都非常巨大。
  
  在一般的BMS系统中,计算电量的方式大概有两种:
  
  ①:硬件
  
  所谓硬件,便是使用一些专门的电量计芯片来计算电量,比如说TI的BQ34Z100,这是一块基于阻抗跟踪技术的电量计,其计算精度不错,而且操作简单,只需要在前期进行一些简单的操作(使用TI官方软件进行基本参数配置,计算电池化学参数CHEM_ID,进行充放电循环学习导出量产文件等)然后就可以直接从芯片里读出电量值。(电量计芯片的方法本文不涉及,感兴趣的同学可以自行查阅资料)
  
  ②:软件
  
  软件计算SOC的方法也不少,有开路电压法、安时积分法、内阻法、神经网络和卡尔曼滤波法…
  
  开路电压法由于要预计开路电压,因此需要长时间静置电池组,内阻法存在着估算内阻的困难,在硬件上也难以实现,神经网络和卡尔曼滤波法则由于系统设置的困难,而且在电池管理系统中应用时成本很高,不具备优势,因此相对于开路电压法、内阻法、神经网络和卡尔曼滤波法本而言,安时积分由于简单、有效而常被采用。
  本文主要介绍基的BMS的SOC的编程语言算法。
  

积分是一个数学模拟的概念,如果转化为生活语言,就是累积一端时间的量,如果转化为程序语言,就是把某个变量相乘在相加计算和。
  
  安时积分中的基本参量自然是电流,在任何一个能源系统运行之时,最能够体现其运行负荷状态的必然就是电流,比如一个电机,如果想要转的快,回路上的电流必然增大,比如一个灯泡,如果想要更亮更闪,回路上的电流也要增大。

SOC的数学定义是什么?

上面说过,SOC就是一颗电池还剩多少电,也就是容量,电池容量的定义是,在一定条件下,所放出的电量,即电池的容量,我们通常以安培、小时作为单位,简称安时(用 AH 表示)。
  
  假如有一颗电池当前的容量是20AH,就是说明,如果我们用1A的电流来进行放电,理论上它可以使用20个小时,等我们把这颗电池用光之后,再使用1A的电流来充电,理论上也需要20个小时才能充满。
  
  如果使用2A的电流来充放电,那么时间也会从20小时缩短到10小时……
  
  安时积分的基本原理就是把电流按照时间进行累计,然后记入剩余电量之中,这和用管子朝泳池里灌水是一个道理。
  
  系统启动,传感器开始电流采集,假如每隔20us采集一次,如果采集到的充电电流是1.5A,那么我就认为,在这20us的时间段内,充电电流一直都是1.5A,那么这段时间里增加的电量就是1.5A * 20us(这里为了表达清晰暂时不转换单位)。

系统充电:现在的剩余电量 = 20us前的电量 + 20us内产生的电量;

系统放电:现在的剩余电量 = 20us前的电量 - 20us内产生的电量;
  
  我们采集到的电流信息,是负载/充电器回路上的电流信息,当电流大于某个阈值的时候(300mA),我们认为是放电,当电流小于某个阈值的时候(-300mA),我们认为是充电,这个没有问题,不过,如果采集到的电流为0,那么系统就真的没有任何消耗吗?
  
  当然不是,就算是MCU本身也是需要消耗能源的,它使用的也是电池的电,只不过没有计入积分之中,如果想要算法更加精确,我认为BMS板子的固定功耗是不能忽略的,虽然电流消耗不大,但毕竟是时时刻刻的在消耗,而且这个消耗几乎不会有很大的改变,如果考虑了固定功耗,那么新的算法如下:

系统充电:现在的剩余电量 = 20us前的电量 + 20us内产生的电量 - 系统固定功耗电流;

系统放电:现在的剩余电量 = 20us前的电量 - 20us内产生的电量 - 系统固定功耗电流;

  tim_cal_ms = OSTimeGet() - time;//就算现在经过的时间time = OSTimeGet();             //保存现在的时间/* 安时积分 *//* 容量 = (当前功率电流 - 系统固定功耗) * 时间 */cap_mAms = (cap_mAms - (current_mA * tim_cal_ms)) - (SYSTEM_FIXED_POWER_CURRENT * tim_cal);/* 充电电量或者放电电量累积超过 10mAh */if((cap_mAms > 36000000) || (cap_mAms < -36000000)){capacity += cap_mAms / 3600000;   /*整数个 mAh */cap_mAms = cap_mAms  % 3600000;   /* 不足1mAh的电量,做累积 */}

以上便是安时积分的基本原理,看着非常简单,不过,现在还有一个问题,20us内产生的电量(current_mA * tim_cal_ms)这个值我是可以计算出来的,但是20us前的电量(cap_mAms)这个值又从何而来呢?
  
  这个自然是来自20us之前的状态,我们再往前推,找到40us前的状态,然后再往前推,找到60us之前的状态……
  
  如果一直往前推以后,肯定会发现一个问题,这个电量算法的安时积分需要一个起点,也就是系统运行之后,我的第一个参与计算的电量是多少?
  
  初始电量的来源一般采用开路电压法来确认,一颗新电池,如果在静态的情况下(无充放电)呆了2个小时以上,那么这个时候直接使用电压来寻找电量是很准确的,比如说3.6V对应100%电量,2.7V对应1%电量,3V对应50%电量,这完全可以做几次充放电实验来列出一个表,横坐标是电压,纵坐标就是电量。

 1 const OCV_VALUE_S  OcvTable_Dischg_1C[101] = {         {2999, 0},2         {3129, 1},  {3262, 2},  {3292, 3},  {3314, 4},  {3330, 5},3         {3344, 6},  {3366, 7},  {3375, 8},  {3383, 9},  {3390, 10},4         {3404, 11}, {3410, 12}, {3416, 13}, {3421, 14}, {3426, 15},5         {3437, 16}, {3441, 17}, {3446, 18}, {3450, 19}, {3454, 20},6         {3462, 21}, {3466, 22}, {3470, 23}, {3473, 24}, {3480, 25},7         {3484, 26}, {3487, 27}, {3490, 28}, {3493, 29}, {3497, 30},8         {3503, 31}, {3506, 32}, {3510, 33}, {3513, 34}, {3519, 35},9         {3523, 36}, {3526, 37}, {3529, 38}, {3532, 39}, {3539, 40},
10         {3543, 41}, {3546, 42}, {3550, 43}, {3554, 44}, {3561, 45},
11         {3565, 46}, {3569, 47}, {3573, 48}, {3578, 49}, {3587, 50},
12         {3592, 51}, {3596, 52}, {3601, 53}, {3607, 54}, {3617, 55},
13         {3623, 56}, {3629, 57}, {3635, 58}, {3641, 59}, {3654, 60},
14         {3661, 61}, {3667, 62}, {3674, 63}, {3688, 64}, {3696, 65},
15         {3703, 66}, {3710, 67}, {3718, 68}, {3726, 69}, {3741, 70},
16         {3749, 71}, {3758, 72}, {3766, 73}, {3782, 74}, {3790, 75},
17         {3799, 76}, {3807, 77}, {3816, 78}, {3833, 79}, {3842, 80},
18         {3851, 81}, {3860, 82}, {3877, 83}, {3887, 84}, {3896, 85},
19         {3905, 86}, {3914, 87}, {3933, 88}, {3943, 89}, {3953, 90},
20         {3962, 91}, {3972, 92}, {3992, 93}, {4002, 94}, {4013, 95},
21         {4024, 96}, {4048, 97}, {4063, 98}, {4082, 99}, {4190, 100}};

系统上电以后,读取电池总电压,然后寻找到一个初始的电量值,虽然有些误差,不过完全可以用这个值来参与以后的积分运算……
  
  不过,还有一个问题,如果这块电池并未静置2小时以上,刚才还在大功率放电,然后由于某种问题系统重启,这个时候采用开路电压法似乎就不可行了!
  
  关于这个问题,可以用一些设计来解决,比如MCU不断电,或者设计一颗外部独立RTC,增加外部的flash,实时储存SOC和相关的信息,在系统启动后,读取flash中的SOC,然后判断其存入的时刻是否经过了2小时,如果上一次存入的SOC的时间和现在的时间相差2小时,那么可以采用开路电压法确定初始SOC。如果事件间隔很小,那么就直接使用FLASH中存储的SOC值来当做初始SOC。


用安时积分算法来计算SOC,其最大的缺点就是误差容易累积,甚至有些误差是不可避免的,比如采用开路电压法得到的初始SOC值,比如硬件的采集精度,如果每次实际的充电电流是0.9A,而采集出来的电流是0.1A,按照时间长此以往的累积下去,最后的电量肯定是虚高的。

在这个时候,我们需要一些方法,利用电池本身的特性,来对安时积分算法进行校准。

在循环中校准

锂电池充电需要经过几个过程,当电池电量低,那么首先是恒流升压充电,这时电流固定不变,电压逐渐升高,等电池电量接近饱和之时,会变成恒压降流充电,电压不在发生明显变化,电流会急速减小,过程如下图所示。

正是因为锂电池的如此特性,因此我们便有了一个校准SOC的时机,当在充电过程中,一旦出现了恒压降流,并且这种状态持续了足够长的时间,那么就可以说明电池已经充满了。
  
  假如由于之前的计算和采集存在误差,导致系统现在的SOC等于70%,系统也可以主动使用算法来修正这个结果,要么直接将SOC人工设定为100%,要么主动放大积分的因子,使其加速充电,以更快的速度朝着100%毕竟。
  
  在放电过程中也可以校准,当电池的电压已经接近低压极限,然后电流也只有几百个毫安,那么就可以将SOC看做是0%了。

卡尔曼滤波和开路电压校准

前面提到过,当电池静置2小时以后,此刻电压相对平稳,我们可以使用开路电压法直接估算SOC的最新值,也可以用开路电压和卡尔曼滤波结合起来用。
  
  卡尔曼滤波是一种很有名的数据校准算法,也可以应用在SOC的计算之上。
  
  卡尔曼滤波的本质是解决一个信任度的问题,我们采集到的电压查表得到的SOC,与安时积分计算出来的SOC,到底哪个更加准确?
  
  具体的算法理论这里不展开,我直接把代码贴出来以供参考:

uint8_t Kalman_Filter_Algorithm(float calculation_vaule, float Q, float R, float measure_vaule)
{static float x_last = 0;static float p_last = 0;static float kg;static float x_mid;static float x_now;static float p_mid;static float p_now;
/*Q:过程噪声,Q增大,动态响应变快,收敛稳定性变坏R:测量噪声,R增大,动态响应变慢,收敛稳定性变好
*/if ((measure_vaule > calculation_vaule) && ((measure_vaule - calculation_vaule) > 10)){measure_vaule = calculation_vaule + 10;}else if ((calculation_vaule > measure_vaule) && ((calculation_vaule - measure_vaule) > 10)){measure_vaule = calculation_vaule - 10;}else{;}x_now = calculation_vaule;// 先验估算值x_mid = calculation_vaule;// 先验协方差p_mid = p_last + Q;// 卡尔曼增益kg = p_mid / (p_mid + R);// 最优估计值x_now = x_mid + kg*(measure_vaule - x_mid);// 最新协方差p_now = (1 - kg)*p_mid;p_last = p_now;x_last = x_now;return (uint8_t)x_now;
}

有了以上量准校准的方法,相信系统的SOC在一般情况下不会偏差太大。

现在做个总结,关于SOC的计算策略图如下:

电池管理系统之神奇的BMS(二)相关推荐

  1. 电池管理系统之神奇的BMS(一)

    什么是BMS? 首先必须弄懂一个定义,什么是BMS? BMS其实就是BATTERY MANAGEMENT SYSTEM的缩写,中文名字叫电池管理系统,顾名思义,是专门用来进行锂电池运行管理的模块,对象 ...

  2. BMS(电池管理系统)第一课——BMS系统框架简介什么是BMS?

    为什么需要BMS? 1.锂离子电池使用范围受限: 对于锂离子电池,其理想的工作范围受限很大,并不宽泛.因此,锂离子电池在应用过程中必须进行管理,尤其在动力电池的应用场景下. 2.安全问题Distort ...

  3. 中国BMS电池管理系统市场研究报告(2022版)

    内容介绍: BMS最核心的三大功能为电芯监控.荷电状态(SOC)估算以及单体电池均衡.BMS监测到单体锂电池芯的工作温度和电量,并自动采取措施均衡单体锂电池芯的充放电电流和防止过温现象发生.能使电动汽 ...

  4. 无线蓄电池测试系统管理软件,电池管理系统(BMS)自动化测试平台

    电池管理系统(BMS)自动化测试平台 电池管理系统(Battery Management System, BMS)着重于电池芯的安全保护,用于保护电池芯在过高压状态下引起的起火爆炸燃烧危险,以及在过低 ...

  5. BMS(电池管理系统)第11课—动力电池系统安全

    ​从两个问题开始和大家讨论一下系统安全 为什么需要安全设计? 新能源汽车越来越多: 行业水平良莠不齐: 电池技术仍需要提高: 动力电池容易热失控引起连锁反应: 电气部件失效率: 安全设计包括那些内容? ...

  6. 如何学好并做好电池管理系统(BMS)

    1.先一如既往地说一说电池管理系统的由来: (1)形象地说,电池是电动汽车的心脏,而电池管理系统(以下简称为BMS)是电池的大脑:BMS是为了在合适的时候给电动汽车提供合适的能量: (2)BMS能够发 ...

  7. bms中soh计算方式_BMS电池管理系统由浅入深全方位解析

    何为BMS? BMS电池管理系统(BATTERY MANAGEMENT SYSTEM)俗称电池保姆或电池管家,主要就是为了智能化管理及维护各个电池单元,防止电池出现过充电和过放电,延长电池的使用寿命, ...

  8. 电池管理系统BMS的常见测试方法

    目录 一.BMS是什么? 二.BMS要实现哪些功能? 三.BMS测试的必要性及测试方法 1.通过实物进行测试:将被管理的电池组实物与BMS对接进行测试. 2.预计仿真电池组进行仿真和验证 一.BMS是 ...

  9. 电动车电池管理系统c语言实训,纯电动汽车电池管理系统(BMS)实训台,汽车电池教学设备...

    TW-CAR60纯电动汽车电池管理系统(BMS)实训台 一.概 述 本设备可展示并真实运行动力电池组及管理系统工作过程,系统通电即可工作,显示并采集电池总电压,容量,单节电池电压,单节电池温度,电池故 ...

最新文章

  1. 蓝牙的自适应跳频技术
  2. awk打印第一个字母
  3. mysql 嵌入式 c开发环境_【Linux】嵌入式C语言MySQL编程(libmysqlclient-dev使用)
  4. TFS 路径...已在工作区...
  5. 【原创】Eclipse实现图形化界面插件-vs4e
  6. 2016经典微小说:《轮回》
  7. 计算机组成原理mw,计算机组成原理 存储器
  8. TreeList显示CheckBox
  9. matlab求多元极大似然估计,matlab求极大似然估计
  10. Application.DoEvents()那些事
  11. 详细船舶信息爬虫教程:船讯网根据MMSI爬取对应船舶属性信息|附python爬虫代码
  12. 《金融学》笔记 第二章 货币制度
  13. 阿里巴巴未来十年使命、愿景和价值观
  14. 华为路由器用Linux开发,华为路由交换设备配置综合实验(实验六合一)
  15. 测试——Bug的生命周期,生命周期流程图
  16. Error: Network Error
  17. 计算机删除登录用户,Windows10账户删除怎么登陆 如何删除账户
  18. 彻底解决2440/2410触摸屏跳点以及抖动问题
  19. mysql explain不准确_mysql explain预估剖析
  20. 打印表格打印机没有反应_windows10下office2016文档和表格 hp打印机 按打印没反应解决办法...

热门文章

  1. 词对齐任务:依附于机器翻译
  2. Python 一个函数快速复制sheet工作表到另一个工作簿
  3. 泰雷兹云安全报告显示,云端数据泄露和复杂程度呈上升趋势
  4. cmdline(一):cmdline是什么?cmdline怎么添加?
  5. echars地图 省市二级联动 插件
  6. php采集新浪视频hlv格式源地址
  7. 绩效考核中如何填写自我评价?(上)
  8. 武器装备系统数字孪生技术
  9. 风口过后,知识付费将如何走下去?
  10. 支付宝小程序(免押金预支付)注意事项