尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

18650锂电池电量估算:从放电曲线到嵌入式实现

发布时间:2026/9/24 11:45:20

资讯中心
01
ARTICLE

18650锂电池电量估算:从放电曲线到嵌入式实现

18650锂电池电量估算:从放电曲线到嵌入式实现
18650锂电池在嵌入式电量计项目里出现的频率极高但真正把电压和容量之间的关系吃透的人并不多。大多数人拿到一颗电芯第一反应是查规格书上的标称容量然后写一段线性映射的代码用ADC读回来的电压直接换算成百分比。这种做法在实验室里看起来能用一旦装进真实设备跑上几天电量跳变、关机后重启电量暴涨、低电量时突然掉电关机这些问题就会集中爆发。我自己在第一个BMS项目上就吃过这个亏当时用了一颗国产18650标称2600mAh代码里按3.0V到4.2V线性映射结果设备在3.5V附近显示还有40%电量实际再跑十分钟就黑屏了。这篇文章想做的事情很具体把18650从放电曲线到电量估算这条链路讲清楚包括电压和容量到底是怎么对应的、为什么不能简单线性映射、ADC采样环节有哪些坑、开路电压法和库仑计法各自适合什么场景、以及在没有专业电量计芯片的情况下怎么用普通MCU做出可用的估算。内容会涉及BMS、ADC采样、嵌入式实现这些关键词适合正在做电池管理、便携设备电量显示、或者单纯想搞明白18650特性的嵌入式开发者。不管你是刚接触电池管理的新手还是已经用过几款电量计芯片的老手这里面的实测数据和踩坑记录应该都能给你一些参考。1. 18650放电曲线的真实形状与规格书背后的信息1.1 规格书上的放电曲线是怎么测出来的几乎所有18650规格书里都会附一张放电曲线图横轴是放电容量纵轴是电压通常会有0.2C、0.5C、1C、2C几条不同倍率的曲线。很多人看这张图只看个大概形状觉得电压从4.2V缓慢下降到3.0V就完事了。但如果你仔细看测试条件会发现几个关键信息往往被忽略。标准容量测试通常是在25摄氏度环境下以0.2C恒流放电到2.5V或2.75V截止。注意这里的截止电压和实际设备的工作截止电压往往不一样。设备端可能3.3V就关机了而规格书测到2.5V这中间差了0.8V对应的是电池最后一段容量。如果你按规格书的2600mAh来设计但设备实际只能用到3.3V以上那可用容量可能只有2200mAh左右。这个差异在项目初期如果不搞清楚后面做电量估算时会出现系统性偏差。还有一个容易被忽略的点是温度。规格书上的曲线是25度测的低温下电池内阻增大电压平台整体下移同样的剩余容量对应的电压会更低。零下十度的时候一颗满电的18650开路电压可能只有3.9V左右如果代码里还按25度的曲线去查表电量显示会直接偏低十几个百分点。1.2 不同倍率放电对电压平台的压缩效应我用同一颗三星30Q做过一组对比测试分别在0.2C、0.5C、1C、2C下恒流放电记录电压随容量的变化。结果很直观放电倍率越大电压平台越低曲线整体向左下方压缩。具体数据是这样的0.2C放电时3.6V对应的放电容量大约是总容量的55%到了1C放电3.6V对应的容量降到了45%左右2C放电时更是降到38%附近。这意味着如果你的设备工作电流波动很大比如电机启动瞬间电流飙升用电压查表法估算电量就会在负载变化时产生剧烈跳变。这个现象的本质是电池内阻上的压降。负载电流越大内阻消耗的电压越多端电压就越低。端电压等于开路电压减去内阻乘以电流。所以同样剩余50%容量空载时端电压可能是3.7V带1A负载时可能只有3.55V。如果你的电量估算只看端电压负载一变电量显示就跟着变用户体验会非常糟糕。1.3 平台区、陡降区和截止区的容量分布把一条典型的18650放电曲线分成三段来看会更容易理解电压和容量的关系。第一段是平台区从4.2V到大约3.5V这一段占据了总容量的70%到80%。特点是电压变化缓慢从4.2V降到3.5V电压只变了0.7V但容量释放了大部分。这一段也是电压查表法最不准的区域因为电压变化太小ADC的微小误差就会导致容量估算出现很大偏差。比如12位ADC在3.7V附近1个LSB对应的电压大约是0.8mV但电池电压在这个区间的斜率可能只有每毫安时0.1mV左右算下来1个LSB的误差就能造成好几毫安时的容量误判。第二段是陡降区从3.5V到3.0V左右这一段电压下降明显加快容量大概占总量的15%到20%。这一段反而是电压查表法相对准确的地方因为电压变化快同样的ADC精度对应的容量分辨率更高。第三段是截止区3.0V以下电压急剧下降容量只剩几个百分点。这一段在实际设备中通常已经被保护板切断了因为过放会对电池造成不可逆损伤。理解这三段的分布对后面设计估算策略非常关键。平台区不能只靠电压陡降区可以适当依赖电压截止区要提前预警。2. 电压查表法为什么在平台区会失效2.1 ADC精度与电压分辨率的数学关系先算一笔账。假设你用STM32的12位ADC参考电压3.3V那么1个LSB对应的电压是3.3V除以4096约等于0.806mV。如果电池电压经过分压电阻减半后再进ADC那实际电池电压的分辨率就是1.61mV。现在看18650在平台区的电压斜率。以一颗2600mAh的电芯为例在3.7V附近每释放100mAh容量电压大约下降15mV到25mV。取中间值20mV那么1.61mV的ADC分辨率对应的容量分辨率是100mAh乘以1.61除以20约等于8mAh。看起来还行8mAh对于2600mAh来说只有0.3%。但问题在于ADC的绝对精度远不止1个LSB。实际ADC有偏移误差、增益误差、噪声。STM32的ADC在常温下INL可能达到正负2个LSB再加上参考电压本身的精度比如常用的TL431是0.5%3.3V参考就是正负16.5mV。这些误差叠加起来实际电压测量误差可能达到正负20mV以上。20mV在平台区对应的容量误差就是100mAh接近4%的电量显示误差。这还只是静态误差没有算温度漂移和长期稳定性。2.2 平台区电压滞回与负载瞬态的影响比ADC精度更麻烦的是电池本身的滞回特性。同一颗电池充电到3.7V和放电到3.7V对应的实际剩余容量是不一样的。充电时由于极化效应端电压会偏高放电时端电压偏低。这个滞回窗口在平台区可能有30mV到50mV。我实测过一颗松下NCR18650B充电到3.7V静置两小时后开路电压是3.68V放电到3.7V静置两小时后开路电压是3.72V。同样的端电压实际容量差了大约5%。如果你的设备在充电和放电之间切换电量显示就会来回跳。负载瞬态的影响更直接。设备从待机切到发射模式电流从10mA跳到500mA端电压可能瞬间跌落80mV到120mV。如果电量估算代码没有做负载补偿电量显示会瞬间掉好几个百分点负载一撤又涨回来。这种跳变在用户看来就是电量不准。2.3 开路电压法的适用条件与静置时间要求开路电压法OCV是电压查表法里最靠谱的一种核心思想是在电池静置足够长时间后端电压近似等于开路电压此时电压和剩余容量有相对稳定的对应关系。但关键词是静置足够长时间。电池从负载撤掉后端电压不会立刻恢复到开路电压而是需要一个弛豫过程。这个过程跟电池化学体系、温度、之前的放电倍率都有关系。一般来说静置30分钟能恢复到90%左右静置2小时能恢复到98%以上。在实际设备里很难保证每次估算前都有2小时静置。手机可能锁屏几分钟就解锁电动车可能等红灯几十秒。所以OCV法通常只在特定时机使用比如设备开机时、长时间待机后、或者充电结束时。开机时如果距离上次使用已经过了很久这时候读到的电压就比较接近OCV可以用来做一次校准。注意OCV法在平台区的分辨率依然有限它的价值更多是提供一个绝对参考点用来修正库仑计法的累积误差而不是单独用来做实时估算。3. 库仑计法的实现细节与累积误差控制3.1 采样电阻选型与电流积分的基本原理库仑计法的思路很直接电流对时间积分就是电荷量。放电时电流为负充电时为正累积起来就是剩余容量。公式很简单Q等于电流对时间的积分。实现上通常用一个采样电阻串联在电池回路里测量电阻两端的压差来得到电流。采样电阻的选型有几个考量。阻值太大会增加功耗和压降阻值太小则信号太弱容易被噪声淹没。对于18650这种容量在2000mAh到3500mAh的电池工作电流通常在几十毫安到几安培之间。如果最大电流按3A算采样电阻选10毫欧满量程压降是30mV。这个信号用MCU的ADC直接采有点勉强因为30mV对应的ADC码值只有37个LSB分辨率太差。所以通常需要加一级运放放大比如放大50倍变成1.5V满量程这样ADC就能充分利用。采样电阻的精度也很关键。普通厚膜电阻的温漂可能达到100ppm每摄氏度在电流采样这种应用里温漂直接转化为电流测量误差。建议选合金电阻或者四端子电阻温漂控制在25ppm以内。我一开始用普通0805电阻夏天和冬天测出来的容量差了将近8%后来换成合金电阻才稳定下来。3.2 积分周期与ADC采样时序的配合电流积分的精度很大程度上取决于采样频率和积分算法。理论上采样越快积分越准但MCU的资源有限不可能无限制提高采样率。我的经验是对于18650这种应用1Hz到10Hz的电流采样率基本够用。如果负载变化很快比如有脉冲式的大电流那采样率需要提高到100Hz以上或者用硬件积分器。积分算法本身也有讲究。最简单的做法是每次采样后把电流乘以采样周期累加到总电荷里。但这样会引入量化误差和截断误差。更好的做法是用梯形积分即用相邻两次采样的平均值乘以时间间隔。如果采样周期固定还可以用滑动平均滤波先处理电流数据再积分。还有一个容易被忽略的点是ADC采样时刻和PWM或其他周期性负载的同步。如果设备里有PWM控制的电机或LED电流会周期性波动。如果ADC采样恰好总是采在波峰或波谷积分结果就会有系统性偏差。解决办法是让ADC采样时刻随机化或者用比PWM频率高得多的采样率。3.3 自放电与温度对累积误差的长期影响库仑计法最大的问题是累积误差。每次电流测量的微小偏差都会随时间累积跑上几天几周误差可能大到无法接受。自放电是其中一个因素。18650的自放电率通常在每月2%到5%之间高温下更高。如果库仑计没有考虑自放电满电放置一个月后实际容量已经少了3%但库仑计还显示100%。温度对采样电阻和ADC基准的影响也会累积。采样电阻的温漂、ADC参考电压的温漂都会导致电流测量值随温度变化。如果设备工作环境温度变化大比如户外设备这个误差会很明显。控制累积误差的常用手段是定期用OCV法校准。比如设备每次开机时如果检测到电池已经静置足够长时间就用当前电压查表得到一个容量值然后把这个值作为库仑计的新起点。这样即使库仑计有累积误差也会被定期修正。4. 从原始ADC数据到可用电量百分比的完整链路4.1 分压电路设计与ADC输入阻抗匹配电池电压通常高于MCU的ADC参考电压所以需要分压。比如4.2V的电池用两个等值电阻分压后是2.1V在3.3V参考范围内。但分压电阻的选型有几个坑。阻值不能太大否则ADC采样时的输入电流会导致电压跌落。STM32的ADC输入阻抗在采样期间不是无穷大采样电容需要充电。如果分压电阻太大比如用1M欧加1M欧采样电容充电时间不够读数会偏低。一般建议分压电阻总阻值在100k欧以内同时加一个100nF的滤波电容在ADC输入端。阻值也不能太小否则会持续消耗电池电量。两个100k欧电阻分压4.2V下电流是21微安一年消耗约184mAh对于2600mAh的电池来说不算小。如果设备长期待机这个功耗要考虑进去。折中方案是用1M欧加1M欧但在ADC输入端加一个电压跟随器用运放做阻抗变换。分压电阻的精度和温漂也会影响电压测量。普通1%精度的电阻分压比误差就有2%对应电压测量误差也是2%。如果电量估算依赖电压这个误差会直接传递过去。建议用0.1%精度的电阻温漂25ppm以内。4.2 去直流与归一化处理的实际操作ADC采回来的原始数据往往包含直流偏置和噪声。去直流和归一化是信号处理里的标准操作但在电量估算场景下有一些特殊考虑。去直流通常是指减去一个固定的偏置值。这个偏置可能来自ADC的零点误差也可能来自分压电路的静态偏置。实际操作中可以在电池断开的情况下采一组数据取平均作为零点偏置然后在后续采样中减去这个值。归一化则是把ADC码值转换成实际电压。公式是电压等于ADC码值乘以参考电压除以满量程码值再乘以分压比。这里参考电压的准确性很关键。如果直接用MCU的VDDA作为参考而VDDA又来自一个普通的LDO精度可能只有2%到3%。更好的做法是用外部基准芯片比如REF3033精度0.2%温漂50ppm。滤波也是必不可少的。电池电压本身比较干净但ADC采样会引入噪声。简单的做法是多次采样取平均比如采16次去掉最大最小值再平均。如果MCU资源允许可以用一阶低通滤波截止频率设在1Hz左右既能滤掉噪声又不会对电池电压的真实变化造成太大延迟。4.3 电压-容量查找表的构建与插值方法查找表是电压查表法的核心。构建一张好的查找表需要实测数据不能直接抄规格书。我的做法是拿一颗全新的18650在25度环境下先用0.5C恒流充电到4.2V转恒压充电到电流小于0.05C静置2小时。然后以0.2C恒流放电每释放5%容量静置30分钟记录开路电压。这样得到一张放电方向的OCV-SOC表。充电方向同样测一遍得到充电方向的表。两张表取平均或者根据当前是充电还是放电状态选择对应的表。查找表的分辨率不需要太高通常5%一个点就够了中间用线性插值。比如3.7V在表中对应50%和55%之间那就按电压比例插值。插值公式很简单但要注意表的单调性。如果实测数据有非单调的点需要手动修正否则插值会出现异常。温度补偿是另一个维度。可以在不同温度下各测一张表比如零下10度、0度、25度、45度。实际使用时根据温度传感器读数选择对应的表或者在两张表之间插值。如果不想做那么细至少要在低温时给电压加一个补偿量比如零下10度时电压读数加50mV再查表。5. 没有专业电量计芯片时的工程折中方案5.1 电压法与库仑计法的融合策略单独用电压法或单独用库仑计法都有明显缺陷实际项目里通常是两者融合。融合的基本思路是库仑计负责短期估算提供实时的电量变化OCV法负责长期校准在合适时机修正库仑计的累积误差。具体实现上可以维护两个变量一个是库仑计累积的剩余容量一个是OCV查表得到的参考容量。当两者偏差超过一定阈值比如5%并且当前满足静置条件就用OCV的值去修正库仑计。修正的时机很关键。设备开机时是一个好时机因为通常已经静置了一段时间。充电结束时也是好时机因为充电到截止后电池电压稳定OCV查表比较准。设备进入低功耗待机一段时间后也可以尝试修正。修正的幅度需要平滑不能直接跳变。可以用一阶滤波让显示电量在几秒到几十秒内缓慢过渡到新值避免用户看到电量突然跳变。5.2 低电量预警与截止电压的动态调整低电量预警是电量估算里最实用的功能之一。用户不一定关心当前是73%还是75%但一定关心还能用多久。18650在陡降区的电压下降很快从3.5V到3.3V可能只有几分钟到十几分钟。如果等到3.3V才预警用户可能来不及保存数据或找到充电器。我的做法是在3.5V左右就开始预警提示低电量然后在3.4V时强制进入省电模式3.3V时准备关机。截止电压也不能写死。大电流放电时内阻压降大端电压到3.3V时实际开路电压可能还有3.5V此时关机就浪费了容量。小电流放电时端电压到3.3V时开路电压也接近3.3V此时关机是合理的。所以截止电压应该根据当前电流动态调整公式是截止电压等于基础截止电压加上电流乘以内阻。内阻可以事先测出来比如50毫欧1A放电时截止电压就设成3.35V。5.3 实测数据对比线性映射与查表法的差距我用同一颗2600mAh的18650做了一组对比测试。设备以0.3C恒流放电分别用线性映射和查表法估算电量记录实际容量和显示电量的偏差。线性映射的代码很简单电压3.0V对应0%4.2V对应100%中间线性插值。查表法用前面说的实测OCV表配合库仑计修正。测试结果如下表实际剩余容量线性映射显示查表法显示线性映射误差查表法误差100%100%100%0%0%80%88%82%8%2%60%72%62%12%2%40%52%41%12%1%20%28%21%8%1%10%15%11%5%1%5%8%6%3%1%线性映射在中间段误差最大达到12%这意味着用户看到还有52%电量时实际只剩40%如果按显示电量规划使用时间很可能中途断电。查表法配合库仑计修正后误差控制在2%以内实用性大大提高。这个测试也说明电量估算的精度不是靠复杂的算法堆出来的而是靠对电池特性的准确理解和实测数据的积累。一张好的查找表比任何花哨的滤波算法都管用。6. 温度、老化与批次差异带来的长期挑战6.1 低温环境下电压平台的偏移与补偿低温是电量估算的噩梦。零下十度时18650的电解液粘度增大锂离子扩散变慢内阻可能增大到常温的三到五倍。端电压在负载下会大幅跌落但开路电压的偏移相对小一些。我实测过一颗电芯在零下十度和25度下的OCV-SOC曲线。在50%容量点25度时OCV是3.68V零下十度时是3.62V差了60mV。如果代码里没有温度补偿零下十度时按25度的表查50%容量会被误判为40%左右。补偿的方法有两种。一种是维护多张温度下的查找表根据温度传感器读数选择或插值。另一种是给电压加一个温度补偿量公式可以简化为补偿量等于温度系数乘以温度差。温度系数可以从实测数据拟合通常在零下十度到25度范围内每度补偿2mV到4mV。低温下还有一个问题是电池可用容量本身会减少。零下十度时2600mAh的电池可能只能放出2000mAh。这个容量损失也需要在估算里体现否则满电显示100%实际只能用到80%就关机了。6.2 循环老化对容量和曲线的改变18650在循环几百次后容量会衰减放电曲线也会变形。平台区会略微下移陡降区会提前。如果电量估算代码里写死了2600mAh的满容量老化后实际容量只有2200mAh那电量显示会系统性偏高。用户看到20%电量实际可能只剩10%。解决办法是让系统能够学习满容量。每次从满电放到截止库仑计累积的总电荷就是当前的实际满容量。把这个值更新到系统里下次估算就用新的满容量。这样即使电池老化电量显示依然准确。学习满容量需要一次完整的充放电循环。在实际设备里用户可能很少把电池完全放空再充满。所以学习过程可能需要跨多次使用逐步修正。可以设置一个标志位记录上次学习到的满容量每次放电深度超过80%时更新一次。6.3 不同品牌电芯的曲线差异与适配不同品牌的18650甚至同一品牌不同批次的电芯放电曲线都有差异。三星、松下、LG、索尼的曲线各有特点国产电芯的差异更大。我在项目里用过三星30Q、松下NCR18650B、LG HG2和一款国产2600mAh。在50%容量点四者的OCV分别是3.65V、3.68V、3.63V和3.60V最大差了80mV。如果查找表是按三星做的换国产电芯后电量显示会偏低。所以查找表必须和电芯绑定。如果产品会换电芯供应商要么重新测表要么在代码里做电芯型号识别加载对应的表。识别可以通过读取电池上的ID电阻或者让生产环节写入配置。对于小批量项目如果不想每个电芯都测至少要用同一批次的电芯测一张表。不同批次之间的一致性通常比不同品牌之间好很多。7. 嵌入式实现中的代码组织与调试手段7.1 电量估算模块的接口设计电量估算模块应该和其他业务逻辑解耦提供清晰的接口。我通常设计这几个函数初始化、更新、获取电量、获取健康状态。初始化函数负责加载查找表、设置初始容量、校准ADC零点。更新函数周期性调用传入当前电压、电流、温度内部完成积分、查表、修正。获取电量返回0到100的百分比。获取健康状态返回满容量、循环次数、内阻等。更新函数的调用周期要固定比如100ms或1s。如果调用周期不固定积分计算会出错。可以在函数内部用系统tick计算实际时间间隔而不是假设固定周期。数据结构上用一个结构体保存所有状态变量包括累积电荷、上次电压、上次电流、当前温度、满容量、健康状态等。这样模块可以实例化多个如果设备有多颗电池。7.2 用串口输出调试电量估算过程电量估算的调试离不开数据记录。我习惯在更新函数里把关键变量通过串口输出格式化成CSV方便后续用Excel或Python分析。输出的字段包括时间戳、电压、电流、温度、库仑计累积容量、查表容量、最终显示电量。跑一次完整的充放电循环把数据导出来画图就能直观看到估算的偏差在哪里。如果串口带宽有限可以降低输出频率比如每秒输出一次。或者用环形缓冲区暂存等设备空闲时批量输出。调试时还可以加入一些断言比如电压超出合理范围时报警电流方向异常时报警。这些断言在开发阶段能帮助快速定位问题。7.3 常见异常现象与排查思路电量估算的异常现象通常有几类电量跳变、电量不更新、电量始终100%或0%、充电时电量下降。电量跳变最常见的原因是负载变化导致电压突变而估算代码没有做负载补偿或滤波。排查时先看电流数据如果电流突变时电量跟着跳那就是这个问题。电量不更新可能是积分没有执行或者电流采样始终为零。检查ADC读数是否正常采样电阻是否焊接良好。电量始终100%或0%通常是查找表或边界条件有问题。比如电压高于4.2V时直接返回100%如果分压电阻误差导致读数偏高就会一直显示100%。充电时电量下降是电流方向判断反了。充电时电流应该为正如果代码里符号搞反积分就会往负方向走。排查这些问题最有效的手段还是记录数据、画图、对比。凭感觉猜往往事倍功半。8. 从项目实践里攒下来的几条硬经验做电量估算这几年踩过的坑比写过的代码还多。有几条经验我觉得值得单独拎出来说。第一条永远不要相信规格书上的曲线能直接用在你的项目里。规格书的测试条件和你实际的使用条件差很远截止电压、放电倍率、温度都可能不一样。花半天时间实测一张自己的曲线比调一周代码都管用。第二条ADC的精度比分辨率重要得多。很多人选MCU时看ADC是多少位12位、16位但实际精度可能只有10位。参考电压的稳定性、PCB布局、地线处理这些对精度的影响比位数大。我在一个项目里换了低噪声LDO做参考电量估算的稳定性直接上了一个台阶。第三条库仑计没有校准就是耍流氓。累积误差是必然的关键是设计好校准机制。开机校准、充电结束校准、定期强制校准三管齐下才能保证长期准确。第四条温度补偿不是可选项。如果你的设备工作温度范围超过20度不做温度补偿电量显示在极端温度下会离谱到用户想砸设备。第五条留出足够的调试接口。电量估算涉及电池、硬件、软件多个环节出问题时如果只能靠猜效率极低。串口输出、数据记录、在线参数调整这些调试手段在项目初期就要规划好。最后说一个具体的技巧。如果你用的是STM32ADC采样电池电压时建议用DMA加定时器触发让采样时刻和系统其他周期性操作错开。我遇到过ADC采样和PWM同步导致读数周期性波动的情况改成定时器触发后问题就消失了。这个坑花了我两天时间才找到希望你能避开。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。