Percent display battery level
Lithium batteries are used more and more widely, but how to convert the voltage data we can only collect into percentage power data? This article provides a simple algorithm.
platform
Hardware: Jetson-nano
Software: Ubuntu18.04
Sensor: Voltage sensor based on the principle of resistance divider, product link (https://detail.tmall.com/item.htm?id=520840133787)[https://detail.tmall .com/item.htm?id=520840133787]
sampling
- Only run the system, collect the voltage every ten seconds, assuming this process is uniform discharge
- From the fully charged start to run until the battery is too low to stop, the voltage sampling interval is [8.5, 12.5]
- Since the interval between 9.5 and 8.5 is only 10 minutes apart, 9.6V is selected as 1% of electricity
Percentage model
- The total discharge time is about 10 hours
- Set the voltage (12.5V) at the beginning of the first hour corresponding to 100% power
- Set the voltage at the end of the 10th hour (9.6V) to correspond to 1% of the battery
- The voltage at the end of the 5th hour is 50% battery
- By analogy, the progress of the discharge time is used as the percentage of the power to correspond to the sampled voltage value
- The accuracy of the voltage value is 1 digit after the decimal point, a total of 30 different sampling values, the sampling time corresponding to different sampling values can be counted
- This article selects the maximum sampling time (that is, the first sampling time) as the battery power percentage corresponding to the voltage value
simulation
- Use Matlab to view the relationship between voltage and discharge progress
close all;clear;clc
% 载入数据
x = load('data/battery.txt');
x = x(1:3850)';
% 建立比例关系
y = [1:-1/3850:1/3850];
% 统计
data = [10 * (x - 9.5); y]';
data_sum = zeros(30, 1);
data_count = zeros(30, 1);
data_min = zeros(30, 1);
for i = 1:size(x,2)
idx = round(data(i,1));
data_sum(idx) = data_sum(idx) + data(i,2);
data_max(idx) = max([data_min(idx) data(i,2)])
data_count(idx) = data_count(idx) + 1;
end
data_avg = data_sum ./ data_count;
% 按平均值计算
pct = round(100*data_avg)
% 按最大值计算
pct_max = round(100*data_max)
% 拟合效果
figure(1)
plot(x, y)
figure(2)
m = [9.6:0.1:12.5];
plot(m, pct_max)
-
Sample map
-
Map after selecting the maximum value
-
Calculation results
[9.6-10.5]: 1, 1, 2, 4, 8, 11, 16, 19, 27, 34,
[10.6-11.5]: 45, 52, 55, 58, 62, 64, 68, 71, 76, 78,
[11.6-12.5]: 81, 84, 87, 92, 93, 98, 99, 100, 100, 100
- Voltage to power conversion
# 电池电压对应的电量百分比,对应: 9.6V-12.5V
battery_pct = (1, 1, 2, 4, 8, 11, 16, 19, 27, 34, 45, 52, 55, 58, 62, 64, 68, 71,
76, 78, 81, 84, 87, 92, 93, 98, 99, 100, 100, 100)
last_bat = 125
while alive:
# 电压转换为百分比
bat = round(get_battery())
if bat == 0:
continue
if bat < 96:
bat = 96
elif bat > 125:
bat = 125
if last_bat + 5> bat > last_bat:
bat = last_bat
else:
last_bat = bat
pct = battery_pct[bat - 96]
batstr = '%d%%' % pct
time.sleep(10)
Follow-up optimization plan
- Improve the sampling accuracy and sampling frequency, which can make the battery display more accurate and smooth
- Exclude outliers in statistics
- Low-pass filtering is added when converting voltage to electric quantity to eliminate some interference