Linux Battery Percentage Correction

February 07, 2019, Sam Erickson

catagories: linux useful-snippets

The problem

The problem I had in my initial arch linux installation on my macbook pro, was the battery. Fully charged it was showing 84%, and if I then immediately booted into macOS, it would show 100%. So what is going on there?

The fix

I did some digging, and found lots of forms where users were asking the same question, but with no real answer as to why or any solution. I started looking into how my computer was getting all the battery information.

In i3blocks, the command was cat /sys/class/power_supply/BAT0/capacity. Naturally, I cd into that directory to get a look at what is going on. I found the following files:

.
├── alarm
├── capacity
├── charge_full
├── charge_full_design
├── charge_now
├── current_avg
├── current_now
├── cycle_count
├── device -> ../../../ACPI0002:00
├── manufacturer
├── model_name
├── power/
├── present
├── status
├── subsystem -> ../../../../../../../../../../class/power_supply
├── technology
├── temp
├── type
├── uevent
├── voltage_min_design
└── voltage_now

The four files I was interested in are:

When you divide charge_now by charge_full_design you get capacity, and when you divide charge_now by charge_full you get what macOS displays as the current battery level.

So I changed the command in my i3blocks config to run the following script:

#!/bin/bash

charge_current="$(cat /sys/class/power_supply/BAT0/charge_now)"
charge_full="$(cat /sys/class/power_supply/BAT0/charge_full)"
current=$(echo "scale=2;$charge_current/$charge_full" | bc | cut -c 2-)

echo "$current%"

I will admit it is a little bit slow, and I later read the i3blocks documentation and found their suggested battery module code:

#!/bin/bash

BAT=$(acpi -b | grep -E -o '[0-9][0-9]?%')

# Full and short texts
echo "Battery: $BAT"
echo "BAT: $BAT"

# Set urgent flag below 5% or use orange below 20%
[ ${BAT%?} -le 5 ] && exit 33
[ ${BAT%?} -le 20 ] && echo "#FF8000"

exit 0

Which works just as well, but with no completion time difference, and one more dependency. This would have saved me a little bit of time, but I am happy with my fix for now.

Why is this the case?

Different versions of batteries have different strengths and weaknesses, in the case of rechargeable lithium-ion batteries, like those found in laptops, they are only designed for a certain amount of cycles before they are used up. With each charge, you lose effectiveness, the max charge from the factory does not match the actual max charge. This causes linux to provide an incorrect battery reading as the battery degrades.

This is helpful when you want to know the current life state of your battery, but not helpful if you want to know how much time you have before you need to recharge.

Summary

There are lots of ways to check the battery status in linux, you just need to find the one that suits your needs.