電池管理優(yōu)化:放電曲線標(biāo)定與庫倫值校準(zhǔn)實(shí)戰(zhàn))
1. 電池管理優(yōu)化的整體設(shè)計(jì)思路1.1 為什么MTK平臺(tái)的電池管理值得單獨(dú)拿出來講做Android底層開發(fā)的人都有一個(gè)共識(shí)電池管理是用戶體驗(yàn)最敏感、但調(diào)試信息最不透明的模塊之一。尤其是MTK平臺(tái)它的電池管理框架和原生Android的Healthd/HAL層有比較大的差異很多在Qualcomm平臺(tái)上跑得很順的調(diào)試方法換到MTK上就完全對(duì)不上號(hào)。MTK的電池管理核心邏輯集中在mtk_battery.c、mtk_charger.c以及fuel_gauge相關(guān)的驅(qū)動(dòng)里上層通過healthd或battery service讀取/sys/class/power_supply/battery/下的節(jié)點(diǎn)。問題在于MTK的Fuel Gauge電量計(jì)算法是半封閉的很多參數(shù)以二進(jìn)制表的形式燒錄在NV分區(qū)里你沒法直接改源碼就完事。這就導(dǎo)致一個(gè)很現(xiàn)實(shí)的問題電量跳變、放電曲線非線性、關(guān)機(jī)電壓不準(zhǔn)、庫倫值累積誤差這些毛病在MTK機(jī)器上出現(xiàn)的概率明顯偏高。我接觸過的項(xiàng)目里最常見的就是用戶反饋“20%電量突然關(guān)機(jī)”或者“充到100%拔掉線兩分鐘就掉到95%”。這類問題追根溯源八成以上都指向兩個(gè)東西放電曲線Discharge Curve標(biāo)定不準(zhǔn)和庫倫值Coulomb Counter校準(zhǔn)偏移。這兩個(gè)概念聽起來很專業(yè)但說白了就是電池在不同溫度、不同負(fù)載下電壓和剩余電量的對(duì)應(yīng)關(guān)系變了而系統(tǒng)還在用一套老舊的映射表去估算自然算不準(zhǔn)。這篇內(nèi)容適合誰看如果你是Android系統(tǒng)工程師、BSP工程師、或者做電池驅(qū)動(dòng)調(diào)試的同行尤其是手上正好有MTK平臺(tái)的項(xiàng)目那這篇東西應(yīng)該能幫你省下不少翻vendor文檔和試錯(cuò)的時(shí)間。如果你只是對(duì)電池管理好奇也可以看看我會(huì)盡量用生活化的類比把原理講清楚。1.2 放電曲線和庫倫值到底在管什么先打個(gè)比方。放電曲線就像一張“電壓-電量對(duì)照表”。你拿一塊電池從滿電開始以恒定電流放電每隔一段時(shí)間記錄電壓和剩余容量最后畫出一條曲線。系統(tǒng)運(yùn)行時(shí)Fuel Gauge讀到當(dāng)前電壓是3.7V就去查這張表告訴你“還剩45%”。但這張表是在實(shí)驗(yàn)室25°C、0.2C放電條件下測(cè)的你實(shí)際用手機(jī)時(shí)可能在零下10°C室外拍照也可能在40°C車?yán)飳?dǎo)航這時(shí)候電壓和電量的對(duì)應(yīng)關(guān)系完全變了。如果系統(tǒng)還按25°C的表去查就會(huì)出現(xiàn)“電壓看著還有3.6V但實(shí)際電量已經(jīng)快空了”的情況于是突然關(guān)機(jī)。庫倫值則是另一種思路。它不查表而是直接“數(shù)電流”。電池放電時(shí)電流流過采樣電阻Fuel Gauge芯片比如MTK常用的bq27541、da9150或者M(jìn)TK自家的mt6357內(nèi)置FG會(huì)以很高的頻率對(duì)電流做積分累加出“已經(jīng)放出了多少mAh”。理論上如果初始電量是1000mAh你放出了600mAh那剩余就是400mAh。聽起來很準(zhǔn)對(duì)吧但問題在于積分會(huì)漂移。采樣電阻有溫漂ADC有零點(diǎn)偏移靜態(tài)電流估計(jì)不準(zhǔn)時(shí)間一長(zhǎng)庫倫值累積的誤差可能達(dá)到10%甚至更多。這時(shí)候就需要“校準(zhǔn)”——用電壓查表的結(jié)果去修正庫倫值或者反過來。MTK的框架里這兩者是互補(bǔ)的。庫倫值負(fù)責(zé)短時(shí)間內(nèi)的精確跟蹤放電曲線負(fù)責(zé)長(zhǎng)時(shí)間尺度的絕對(duì)錨定。任何一個(gè)出問題電量顯示就會(huì)“發(fā)瘋”。所以優(yōu)化電池管理本質(zhì)上就是讓這兩套機(jī)制協(xié)同工作而不是各跑各的。1.3 整體優(yōu)化方案的選型考量在MTK平臺(tái)上做電池管理優(yōu)化有三條路可以走純軟件層修正在healthd或BatteryService里加濾波、做平滑改battery_profile表。優(yōu)點(diǎn)是改動(dòng)小、不用動(dòng)NV缺點(diǎn)是治標(biāo)不治本底層FG算錯(cuò)了上層再怎么平滑也只是“看起來穩(wěn)”。驅(qū)動(dòng)層參數(shù)調(diào)優(yōu)改mtk_battery.c里的CAR_TUNE_VALUE、Q_MAX、SHUTDOWN_VOLTAGE等參數(shù)配合MTK提供的battery_log工具抓數(shù)據(jù)。這是最常用的路子能解決大部分精度問題。NV項(xiàng)重標(biāo)定用MTK的Meta工具或者nvram接口重新寫入放電曲線表、內(nèi)阻表、溫度補(bǔ)償系數(shù)。這是最徹底的但需要實(shí)驗(yàn)室設(shè)備電子負(fù)載、恒溫箱和MTK的授權(quán)工具門檻最高。我的建議是先做驅(qū)動(dòng)層參數(shù)調(diào)優(yōu)把能改的軟件參數(shù)改到位再根據(jù)實(shí)測(cè)數(shù)據(jù)決定要不要?jiǎng)覰V。大部分項(xiàng)目做完第二步電量精度就能從“能用”提升到“好用”。NV重標(biāo)定是最后的手段除非你的電池供應(yīng)商換了電芯或者硬件設(shè)計(jì)有重大變更否則沒必要大動(dòng)干戈。下面這張表對(duì)比了三種方案的核心差異方案改動(dòng)位置所需工具精度提升幅度風(fēng)險(xiǎn)軟件層修正healthd/BatteryService無特殊低5%以內(nèi)低驅(qū)動(dòng)層調(diào)優(yōu)mtk_battery.c / dtsbattery_log、adb中可到2-3%中NV重標(biāo)定NV分區(qū)Meta工具、電子負(fù)載高可到1%高選哪條路取決于你的項(xiàng)目階段和手頭資源。量產(chǎn)前的機(jī)器建議直接上NV重標(biāo)定已經(jīng)出貨的機(jī)器驅(qū)動(dòng)層調(diào)優(yōu)更現(xiàn)實(shí)。2. 核心細(xì)節(jié)解析與實(shí)操要點(diǎn)2.1 MTK Fuel Gauge的工作機(jī)制拆解MTK平臺(tái)的Fuel Gauge有兩種形態(tài)一種是內(nèi)置在PMIC里的FG比如MT6357、MT6358、MT6359另一種是外置的獨(dú)立FG芯片比如bq27541。內(nèi)置FG成本低但精度和靈活性差一些外置FG精度高但需要額外的I2C通信和驅(qū)動(dòng)適配。以MT6357為例它的FG模塊核心是一個(gè)16位ADC采樣電池電壓和電流。電流采樣靠的是一個(gè)10mΩ的采樣電阻有些設(shè)計(jì)用5mΩADC讀到的電壓差除以電阻就是電流。然后FG內(nèi)部有一個(gè)累加器以大約1Hz的頻率對(duì)電流做積分得到庫倫值。關(guān)鍵參數(shù)有這么幾個(gè)CAR_TUNE_VALUE庫倫值的校準(zhǔn)系數(shù)。默認(rèn)值通常是1000代表“實(shí)際容量/理論容量”的比例。如果你發(fā)現(xiàn)電量掉得比實(shí)際快可以適當(dāng)調(diào)大這個(gè)值。Q_MAX電池的最大化學(xué)容量單位是mAh。這個(gè)值如果設(shè)得比實(shí)際容量大電量會(huì)“虛高”設(shè)小了電量會(huì)“虛低”。SHUTDOWN_VOLTAGE關(guān)機(jī)電壓通常是3.4V或3.3V。這個(gè)值設(shè)高了電池還沒放完就關(guān)機(jī)設(shè)低了可能過放損傷電池。DIFFERENCE_FULLOCV_ITH滿電判斷電流閾值。充電時(shí)電流降到這個(gè)值以下才認(rèn)為真正充滿了。這些參數(shù)在mtk_battery.c的battery_profile_t結(jié)構(gòu)體里定義或者通過DTSDevice Tree傳入。我見過不少項(xiàng)目直接抄了參考設(shè)計(jì)的參數(shù)結(jié)果電池型號(hào)一換電量就完全不準(zhǔn)了。參數(shù)必須根據(jù)實(shí)際電池的規(guī)格書來調(diào)這是鐵律。2.2 放電曲線的標(biāo)定邏輯與常見誤區(qū)放電曲線的標(biāo)定核心是回答一個(gè)問題在特定溫度和負(fù)載下電池電壓對(duì)應(yīng)多少剩余容量MTK的框架里放電曲線通常以battery_profile數(shù)組的形式存在每個(gè)元素包含voltage和capacity兩個(gè)字段。比如static const struct battery_profile battery_profile[] { { 3400, 0 }, { 3500, 5 }, { 3600, 15 }, { 3700, 35 }, { 3800, 55 }, { 3900, 75 }, { 4000, 90 }, { 4100, 95 }, { 4200, 100 }, };這個(gè)表的意思是電壓3.4V時(shí)電量0%3.5V時(shí)5%以此類推。系統(tǒng)運(yùn)行時(shí)FG讀到電壓3.75V就線性插值算出大約45%的電量。但這里有幾個(gè)坑第一個(gè)坑溫度補(bǔ)償缺失。上面這個(gè)表是25°C的。低溫下電池內(nèi)阻增大同樣的電量電壓會(huì)低很多。比如0°C時(shí)電量還有30%電壓可能只有3.5V按表查出來只有5%用戶就會(huì)覺得“怎么突然掉電這么快”。MTK的框架支持溫度補(bǔ)償?shù)枰阍赽attery_profile里為不同溫度段定義不同的表或者用temperature_tbl做插值。很多項(xiàng)目為了省事只寫一張表結(jié)果冬天戶外使用體驗(yàn)極差。第二個(gè)坑負(fù)載補(bǔ)償缺失。手機(jī)玩游戲時(shí)電流可能到1.5A待機(jī)時(shí)只有幾mA。大電流下電池內(nèi)阻上的壓降會(huì)拉低端電壓。比如實(shí)際電量50%待機(jī)電壓3.8V玩游戲時(shí)電壓可能掉到3.6V按表查出來只有15%。這就是為什么很多手機(jī)玩游戲時(shí)電量“唰唰往下掉”一退出游戲又“漲回來”。MTK的FG有IR補(bǔ)償機(jī)制但補(bǔ)償系數(shù)R_IR需要根據(jù)電池內(nèi)阻來調(diào)。內(nèi)阻大的電池補(bǔ)償系數(shù)要調(diào)大否則壓降影響太明顯。第三個(gè)坑曲線非線性。鋰電池的放電曲線不是直線在3.7V到3.9V之間有一個(gè)很平的平臺(tái)區(qū)。這個(gè)區(qū)間里電壓變化很小但電量變化很大。如果你的表在這個(gè)區(qū)間采樣點(diǎn)太少插值誤差就會(huì)很大。我一般建議在平臺(tái)區(qū)至少放5-6個(gè)點(diǎn)確保精度。2.3 庫倫值校準(zhǔn)的關(guān)鍵參數(shù)與計(jì)算過程庫倫值校準(zhǔn)的核心是CAR_TUNE_VALUE。這個(gè)值的計(jì)算邏輯是這樣的假設(shè)電池標(biāo)稱容量是3000mAh你從滿電放電到關(guān)機(jī)FG累計(jì)放出了2850mAh。那么CAR_TUNE_VALUE (實(shí)際放出容量 / 標(biāo)稱容量) × 1000 (2850 / 3000) × 1000 950如果這個(gè)值是950說明FG少算了50mAh你需要把CAR_TUNE_VALUE從默認(rèn)的1000調(diào)到950讓FG“多算一點(diǎn)”。反過來如果FG累計(jì)放出了3150mAh那CAR_TUNE_VALUE就是1050。但這里有個(gè)問題你怎么知道“實(shí)際放出容量”是多少實(shí)驗(yàn)室里可以用電子負(fù)載精確測(cè)量但產(chǎn)線上不可能每臺(tái)機(jī)器都測(cè)。所以MTK的做法是在battery_profile里定義一個(gè)Q_MAX然后通過多次充放電循環(huán)讓FG自己學(xué)習(xí)。學(xué)習(xí)的結(jié)果存在NV里下次開機(jī)直接讀。實(shí)操中我一般會(huì)這樣做用adb shell cat /sys/class/power_supply/battery/下的節(jié)點(diǎn)抓取charge_counter、voltage_now、current_now等數(shù)據(jù)。寫一個(gè)腳本每10秒記錄一次持續(xù)放電到關(guān)機(jī)。把數(shù)據(jù)導(dǎo)入Excel畫出電壓-時(shí)間曲線和電量-時(shí)間曲線。對(duì)比兩條曲線找出偏差最大的區(qū)間。調(diào)整CAR_TUNE_VALUE和battery_profile重新測(cè)試。這個(gè)過程通常需要2-3輪迭代才能把誤差壓到3%以內(nèi)。2.4 實(shí)操中的注意事項(xiàng)與禁忌注意修改mtk_battery.c之前一定要備份原始文件。MTK的驅(qū)動(dòng)代碼耦合度很高改錯(cuò)一個(gè)參數(shù)可能導(dǎo)致充電異常甚至無法開機(jī)。幾個(gè)我踩過的坑不要同時(shí)改多個(gè)參數(shù)。每次只改一個(gè)測(cè)完再改下一個(gè)。否則出了問題你根本不知道是哪個(gè)參數(shù)導(dǎo)致的。SHUTDOWN_VOLTAGE不要低于3.3V。鋰電池過放到3.0V以下會(huì)永久損傷而且MTK的PMIC在3.3V左右就會(huì)觸發(fā)低電壓保護(hù)你設(shè)再低也沒用。Q_MAX不要設(shè)得比實(shí)際容量大太多。有些工程師為了讓電量“看起來耐用”把Q_MAX調(diào)大10%結(jié)果就是電量顯示100%但實(shí)際只有90%用戶充到100%拔線后很快掉到90%體驗(yàn)更差。溫度補(bǔ)償表要覆蓋實(shí)際使用溫度范圍。至少覆蓋-10°C到50°C每10°C一個(gè)點(diǎn)。如果項(xiàng)目只在國內(nèi)南方賣可以適當(dāng)放寬低溫范圍但高溫一定要覆蓋。3. 實(shí)操過程與核心環(huán)節(jié)實(shí)現(xiàn)3.1 環(huán)境準(zhǔn)備與工具鏈搭建在開始調(diào)優(yōu)之前你需要準(zhǔn)備這些東西一臺(tái)MTK平臺(tái)的工程機(jī)最好有root權(quán)限和adb調(diào)試權(quán)限。MTK的battery_log工具。這個(gè)工具通常在vendor目錄下或者可以從MTK的onlinine支持網(wǎng)站下載。它的作用是實(shí)時(shí)抓取FG的原始數(shù)據(jù)包括電壓、電流、庫倫值、溫度、SOC等。一個(gè)可調(diào)電子負(fù)載如果要做精確標(biāo)定。沒有的話用手機(jī)跑高負(fù)載游戲也能湊合但精度差一些。Excel或Python用來做數(shù)據(jù)分析和曲線擬合。battery_log的用法很簡(jiǎn)單adb shell battery_log它會(huì)輸出類似這樣的數(shù)據(jù)[ 1234.567] V3850 I250 SOC45 T25 C1350其中V是電壓mVI是電流mASOC是系統(tǒng)估算的電量T是溫度C是庫倫值mAh。我一般會(huì)把這個(gè)輸出重定向到文件然后每5秒采樣一次持續(xù)到關(guān)機(jī)adb shell while true; do battery_log; sleep 5; done battery_log.txt3.2 放電曲線數(shù)據(jù)的采集與處理采集放電曲線數(shù)據(jù)最理想的條件是恒流放電。但手機(jī)的實(shí)際負(fù)載是變化的所以我們需要做兩件事第一盡量讓負(fù)載穩(wěn)定??梢躁P(guān)掉所有后臺(tái)應(yīng)用屏幕亮度固定50%開飛行模式然后播放本地視頻。這樣負(fù)載大概在300-500mA之間比較穩(wěn)定。第二記錄負(fù)載電流。因?yàn)椴煌娏飨碌姆烹娗€不一樣你需要知道你的數(shù)據(jù)是在什么電流下測(cè)的。如果電流波動(dòng)太大可以在數(shù)據(jù)處理時(shí)做電流歸一化。采集到的原始數(shù)據(jù)大概長(zhǎng)這樣時(shí)間(s)電壓(mV)電流(mA)庫倫值(mAh)SOC(%)04200-45001003004150-46037986004100-4557596...............處理的時(shí)候我會(huì)把庫倫值作為“真實(shí)電量”的參考假設(shè)FG的庫倫積分是準(zhǔn)的然后畫出電壓-庫倫值曲線。這條曲線就是你的放電曲線。接下來把這條曲線和當(dāng)前的battery_profile做對(duì)比。如果發(fā)現(xiàn)某個(gè)電壓點(diǎn)對(duì)應(yīng)的電量偏差超過5%就需要調(diào)整。3.3 庫倫值校準(zhǔn)的完整操作流程庫倫值校準(zhǔn)的完整流程我把它分成五步第一步滿電靜置。充電到100%后不要拔線繼續(xù)充30分鐘讓電池真正飽和。然后拔線靜置2小時(shí)讓電壓穩(wěn)定。第二步記錄初始庫倫值。用battery_log讀取當(dāng)前的charge_counter記為C_initial。第三步恒流放電到關(guān)機(jī)。用電子負(fù)載以0.2C比如3000mAh電池用600mA放電直到電壓降到SHUTDOWN_VOLTAGE。記錄放出的總?cè)萘緾_discharge。第四步計(jì)算校準(zhǔn)系數(shù)。如果C_discharge和C_initial的偏差超過3%就需要調(diào)整CAR_TUNE_VALUE新CAR_TUNE_VALUE 舊值 × (C_discharge / C_initial)第五步寫入?yún)?shù)并驗(yàn)證。把新值寫回mtk_battery.c或DTS重新編譯內(nèi)核刷機(jī)重復(fù)第一步到第三步確認(rèn)偏差在可接受范圍內(nèi)。這個(gè)過程聽起來簡(jiǎn)單但實(shí)際操作中靜置時(shí)間不夠是最常見的錯(cuò)誤。電池從充電狀態(tài)切換到放電狀態(tài)電壓需要很長(zhǎng)時(shí)間才能穩(wěn)定。我見過有人充完電直接拔線就開始測(cè)結(jié)果電壓虛高算出來的曲線完全不對(duì)。3.4 溫度補(bǔ)償表的生成與寫入溫度補(bǔ)償表的生成需要在不同溫度下重復(fù)上面的放電測(cè)試。通常至少做三個(gè)溫度點(diǎn)-10°C、25°C、45°C。如果項(xiàng)目要求高可以做到五個(gè)點(diǎn)-20°C、-10°C、0°C、25°C、45°C。每個(gè)溫度點(diǎn)測(cè)出一條放電曲線然后把它們整合成一個(gè)二維表。MTK的框架里溫度補(bǔ)償通常通過temperature_tbl數(shù)組實(shí)現(xiàn)static const struct temperature_tbl temp_tbl[] { { -10, 0, 5, 15, 35, 55, 75, 90, 95, 100 }, { 0, 0, 3, 12, 30, 50, 70, 88, 94, 100 }, { 25, 0, 5, 15, 35, 55, 75, 90, 95, 100 }, { 45, 0, 8, 20, 40, 60, 80, 92, 96, 100 }, };每一行對(duì)應(yīng)一個(gè)溫度每一列對(duì)應(yīng)一個(gè)電壓點(diǎn)。系統(tǒng)運(yùn)行時(shí)根據(jù)當(dāng)前溫度插值出對(duì)應(yīng)的電量。寫入這個(gè)表的時(shí)候要注意電壓點(diǎn)的選取。我一般會(huì)在3.4V到4.2V之間取10個(gè)點(diǎn)平臺(tái)區(qū)3.7V-3.9V加密到5個(gè)點(diǎn)兩端各2-3個(gè)點(diǎn)。這樣既能保證精度又不會(huì)讓表太大。4. 常見問題與排查技巧實(shí)錄4.1 電量跳變問題的排查思路電量跳變是最常見的問題表現(xiàn)是電量顯示突然從30%掉到15%或者從50%跳到70%。排查的時(shí)候我一般按這個(gè)順序來先看是不是溫度問題。如果跳變發(fā)生在溫度劇烈變化時(shí)比如從空調(diào)房走到室外那八成是溫度補(bǔ)償沒做好。用battery_log抓一下跳變前后的溫度數(shù)據(jù)看看溫度補(bǔ)償表有沒有覆蓋到那個(gè)區(qū)間。再看是不是負(fù)載問題。如果跳變發(fā)生在打開大型游戲或相機(jī)時(shí)那是IR補(bǔ)償不夠。檢查R_IR參數(shù)適當(dāng)調(diào)大。MTK的FG里R_IR通常是一個(gè)固定值但有些平臺(tái)支持動(dòng)態(tài)調(diào)整。最后看是不是庫倫值漂移。如果跳變沒有明顯規(guī)律那可能是庫倫值累積誤差太大了。這時(shí)候需要重新校準(zhǔn)CAR_TUNE_VALUE或者檢查采樣電阻的焊接有沒有問題。下面這張表是我整理的常見問題速查現(xiàn)象可能原因排查方法解決措施20%突然關(guān)機(jī)放電曲線尾部不準(zhǔn)對(duì)比實(shí)際放電數(shù)據(jù)調(diào)整3.4V-3.6V區(qū)間的曲線充電到100%很快掉到95%滿電判斷閾值太松檢查DIFFERENCE_FULLOCV_ITH調(diào)小閾值延長(zhǎng)涓流充電玩游戲電量掉得快IR補(bǔ)償不足對(duì)比待機(jī)和負(fù)載電壓調(diào)大R_IR低溫電量虛低溫度補(bǔ)償缺失檢查低溫段曲線補(bǔ)充-10°C曲線電量長(zhǎng)期不準(zhǔn)庫倫值漂移對(duì)比充放電循環(huán)數(shù)據(jù)重新校準(zhǔn)CAR_TUNE_VALUE4.2 充電異常與滿電判斷的坑充電異常通常表現(xiàn)為充不滿、充電慢、或者充滿后很快掉電。充不滿最常見的原因是DIFFERENCE_FULLOCV_ITH設(shè)得太小。這個(gè)參數(shù)是滿電判斷電流閾值如果設(shè)成50mA但你的充電器在涓流階段只能降到80mA那系統(tǒng)永遠(yuǎn)認(rèn)為沒充滿。我一般會(huì)把它設(shè)成100mA左右具體看充電IC的規(guī)格。充電慢可能是CHARGING_FULL_CURRENT設(shè)得太小或者充電IC的限流電阻選大了。MTK的充電框架里ac_charger_current和usb_charger_current分別控制AC和USB充電電流。如果這兩個(gè)值設(shè)得比充電IC的實(shí)際能力小充電就會(huì)慢。充滿后很快掉電除了滿電判斷閾值的問題還可能是Q_MAX設(shè)得比實(shí)際容量大。系統(tǒng)以為電池有3000mAh實(shí)際只有2800mAh那充到100%后前200mAh是“虛”的一用就掉。提示修改充電參數(shù)時(shí)一定要用示波器或電流表實(shí)測(cè)充電電流不要只看代碼里的值。很多充電IC的實(shí)際輸出和寄存器配置有偏差。4.3 獨(dú)家避坑技巧與經(jīng)驗(yàn)總結(jié)說幾個(gè)文檔里不會(huì)寫、但實(shí)際調(diào)試中非常管用的技巧技巧一用dumpsys battery快速看狀態(tài)。這個(gè)命令比battery_log更輕量適合快速檢查adb shell dumpsys battery輸出里會(huì)顯示level、voltage、temperature、charge_counter等關(guān)鍵信息。我一般在修改參數(shù)后先用這個(gè)命令確認(rèn)基本狀態(tài)再用battery_log做詳細(xì)分析。技巧二用/sys/class/power_supply/battery/下的節(jié)點(diǎn)做實(shí)時(shí)監(jiān)控。比如adb shell cat /sys/class/power_supply/battery/voltage_now adb shell cat /sys/class/power_supply/battery/current_now adb shell cat /sys/class/power_supply/battery/charge_counter這些節(jié)點(diǎn)是FG驅(qū)動(dòng)直接暴露的比上層API更實(shí)時(shí)、更準(zhǔn)確。技巧三放電曲線不要一次改太多。我見過有人把整張表重寫結(jié)果電量顯示完全亂套。正確的做法是先改偏差最大的那個(gè)點(diǎn)測(cè)一輪再改下一個(gè)。每次只動(dòng)一個(gè)點(diǎn)最多動(dòng)兩個(gè)。技巧四保留原始參數(shù)備份。在mtk_battery.c里把原始參數(shù)用注釋保留下來方便回滾。比如// Original: 1000 #define CAR_TUNE_VALUE 950這樣萬一改出問題可以快速恢復(fù)。技巧五用Python做曲線擬合。手動(dòng)調(diào)表效率太低我一般用Python的scipy.interpolate做插值自動(dòng)生成新的battery_profile。比如import numpy as np from scipy.interpolate import interp1d voltage np.array([3400, 3500, 3600, 3700, 3800, 3900, 4000, 4100, 4200]) capacity np.array([0, 5, 15, 35, 55, 75, 90, 95, 100]) f interp1d(voltage, capacity, kindcubic) new_capacity f(voltage) print(new_capacity)這樣生成的曲線更平滑比手動(dòng)調(diào)點(diǎn)準(zhǔn)得多。4.4 驗(yàn)證與回歸測(cè)試的要點(diǎn)改完參數(shù)后一定要做完整的回歸測(cè)試。我一般會(huì)做這幾項(xiàng)充放電循環(huán)測(cè)試至少做3次完整的充放電循環(huán)確認(rèn)電量曲線一致。溫度測(cè)試在-10°C、25°C、45°C下各做一次放電測(cè)試確認(rèn)溫度補(bǔ)償有效。負(fù)載測(cè)試待機(jī)、視頻、游戲三種負(fù)載下各測(cè)一次確認(rèn)IR補(bǔ)償有效。關(guān)機(jī)電壓測(cè)試確認(rèn)關(guān)機(jī)電壓準(zhǔn)確不會(huì)過放。滿電測(cè)試確認(rèn)充滿后靜置2小時(shí)電量不會(huì)明顯下降。這些測(cè)試做完基本就能保證電量顯示“穩(wěn)如老狗”了。我在實(shí)際項(xiàng)目里從開始調(diào)到最終驗(yàn)收通常需要2-3周時(shí)間。如果電池供應(yīng)商配合得好能提供準(zhǔn)確的規(guī)格書和測(cè)試數(shù)據(jù)時(shí)間可以縮短到1周左右。最后再分享一個(gè)小技巧MTK的FG有一個(gè)“學(xué)習(xí)”機(jī)制在多次充放電循環(huán)后它會(huì)自動(dòng)修正Q_MAX和CAR_TUNE_VALUE。所以如果你不確定參數(shù)怎么調(diào)可以先讓機(jī)器跑幾個(gè)循環(huán)然后讀NV里的學(xué)習(xí)結(jié)果作為調(diào)參的參考。這個(gè)機(jī)制在mtk_battery.c里通過fg_learning相關(guān)的函數(shù)實(shí)現(xiàn)具體可以看mtk_charger.c里的charger_learning流程。