尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

ADC电压检测实现电池电量百分比显示

ADC电压检测实现电池电量百分比显示 目录1、使用一阶滞后滤波2、查表 分段判断3、结构体数组 插值法4、迟滞机制电量一直在跳是噪声干扰或负载波动导致电压抖动5、低功耗采样建议6、升级7、电压型迟滞回差Hysteresis电量判断四格电量显示核心参数代码示例1、使用一阶滞后滤波#define ALPHA 0.2f static float filtered_voltage 0.0f; filtered_voltage ALPHA * raw_voltage (1.0f - ALPHA) * filtered_voltage;2、查表 分段判断uint8_t Calculate_Battery_Level(float voltage) { if (voltage 4.15f) return 100; if (voltage 4.00f) return 90; if (voltage 3.90f) return 80; if (voltage 3.80f) return 70; if (voltage 3.70f) return 60; if (voltage 3.60f) return 50; if (voltage 3.50f) return 40; if (voltage 3.45f) return 30; if (voltage 3.40f) return 20; if (voltage 3.35f) return 10; if (voltage 3.30f) return 5; return 0; }3、结构体数组 插值法typedef struct { float voltage; uint8_t level; } soc_point_t; const soc_point_t battery_curve[] { {4.20f, 100}, {3.90f, 80}, {3.70f, 50}, {3.50f, 20}, {3.30f, 0} }; #define CURVE_SIZE (sizeof(battery_curve)/sizeof(battery_curve[0])) uint8_t interpolate_soc(float voltage) { if (voltage battery_curve[0].voltage) return 100; if (voltage battery_curve[CURVE_SIZE-1].voltage) return 0; for (int i 0; i CURVE_SIZE - 1; i) { if (voltage battery_curve[i1].voltage) { float ratio (voltage - battery_curve[i1].voltage) / (battery_curve[i].voltage - battery_curve[i1].voltage); return battery_curve[i1].level (uint8_t)(ratio * (battery_curve[i].level - battery_curve[i1].level)); } } return 0; }4、迟滞机制电量一直在跳是噪声干扰或负载波动导致电压抖动#define BATT_HYSTERESIS 2 // ±2%以内不更新 if (abs(new_level - displayed_level) BATT_HYSTERESIS) { Update_Display(new_level); displayed_level new_level; }5、低功耗采样建议用定时器触发ADC避免CPU轮询平时关闭ADC时钟采样时再开启在Stop Mode下通过RTC唤醒完成一次采样后继续睡眠、6、升级加NTC测温做温度补偿接入充电管理芯片的状态中断实现简易库仑积分用电流×时间估算耗电结合蓝牙上报历史电量曲线做健康度分析7、电压型迟滞回差Hysteresis电量判断四格电量显示简单一句话升档用高电压门槛降档用更低的电压门槛防止电压在临界点小幅抖动时电量格来回闪核心参数#define BATT_HYSTERESIS_MV 30U //回差30mV代码示例/** * brief 根据毫伏值获取电池格数 (0-4格)增加全域迟滞回差 H20mV * param voltage_mv 滤波之后毫伏值 (3000-4200mV) */ uint16_t textVbat 0; #define BATT_HYSTERESIS_MV 20U //回差 uint8_t Get_Battery_Levels(uint16_t voltage_mv) { // static保存上一次输出电量等级实现迟滞回差 static uint8_t last_level 0; const float K (47.0f 24.0f) / 24.0f; //电阻分压比 uint16_t real_vbat (uint16_t)(voltage_mv * K 0.5f); textVbat real_vbat; //升格阈值 const uint16_t LVL4_UP 3950; const uint16_t LVL3_UP 3700U; const uint16_t LVL2_UP 3450U; const uint16_t LVL1_UP 3200U; //降格阈值 升格阈值 - 回差 const uint16_t LVL4_DOWN LVL4_UP - BATT_HYSTERESIS_MV; const uint16_t LVL3_DOWN LVL3_UP - BATT_HYSTERESIS_MV;//3700U-203780U const uint16_t LVL2_DOWN LVL2_UP - BATT_HYSTERESIS_MV; const uint16_t LVL1_DOWN LVL1_UP - BATT_HYSTERESIS_MV; //先计算候选档位原始阈值 uint8_t candidate; if(real_vbat LVL4_UP) candidate 4; else if(real_vbat LVL3_UP) candidate 3; else if(real_vbat LVL2_UP) candidate 2; else if(real_vbat LVL1_UP) candidate 1; else candidate 0; uint8_t new_level last_level; //迟滞回差状态机 switch(last_level) { case 4: //4格往下掉必须小于LVL4_DOWN才允许降级 if(real_vbat LVL4_DOWN) { new_level candidate; } break; case 3: //可以升4格或者电压足够低才降级 if(real_vbat LVL4_UP) { new_level 4; } else if(real_vbat LVL3_DOWN) { new_level candidate; } break; case 2: if(real_vbat LVL3_UP) { new_level 3; } else if(real_vbat LVL2_DOWN) { new_level candidate; } break; case 1: if(real_vbat LVL2_UP) { new_level 2; } else if(real_vbat LVL1_DOWN) { new_level candidate; } break; case 0: if(real_vbat LVL1_UP) { new_level 1; } break; default: new_level candidate; break; } last_level new_level; return last_level; }
返回列表