Battery Longevity

I switched to a Lenovo X1 Carbon (3rd gen) in January, and one of the delights of a new laptop was a new laptop battery. I chuckle when I get a stern notification that my battery is running low: it’s fallen to 20% charge! And it can only last for another… two hours and ten minutes. Well, I’m not in a big hurry to find a plug when I see that.

In September I read a story titled The Life and Death of a Laptop Battery, with a grim chart of a laptop battery losing charging capacity:

grim graph

That only covers two years!

The lifetime of a lithium ion battery is reduced by the cycle of charge and discharge… but also by being completely discharged, and by being completely charged. (Older readers may remember being told to occasionally completely discharge batteries — that was Nickel-metal Hydride Batteries that had a memory effect; it’s bad for modern batteries.) Manufacturers put a circuit in to stop discharge shortly before hitting 0% charge (though they present this stop point as 0%), but with every reviewer judging devices based on battery life they’ll charge the battery as high as possible.

I wanted a graph to track my battery status, so I installed Petter Reinholdtsen’s battery-status package to my home directory, tweaking the battery-status-collect and battery-status-graph to point to a log file in my home directory, and the sleep.d config files to point to my personal install, like 20_hjemmenett-battery-status:

 
#!/bin/sh
# Action script to collect battery status just before and just after
# going to sleep.
#
# Copyright: Copyright (c) 2013 Petter Reinholdtsen
# License:   GPL-2+
#
 
PATH=/sbin:/usr/sbin:/bin:/usr/bin
 
case "1" in
        hibernate|resume|thaw)
		if [ -x /home/pushcx/.bin/battery-status-collect ]; then
		    /home/pushcx/.bin/battery-status-collect
		fi
                ;;
esac

All-in-all that required three config files to make sure the battery status is recorded regularly as the machine sleeps and wakes (and one fiddly bit of debugging):

  1. /etc/pm/power.d/20_hjemmenett-battery-status
  2. /etc/pm/sleep.d/20_hjemmenett-battery-status
  3. /etc/pm/utils/sleep.d/20_hjemmenett-battery-status

That’s it for monitoring.

My next step was to reduce charge cycling and time spent at maximum charge. For my Lenovo X1 Carbon 3rd Gen, I had to install tpacpi-bat and its system dependency acpi_call.

I installed tpacpi-bat from AUR using aura:

 
$ sudo aura -A tpacpi-bat

Then I tweaked /usr/lib/systemd/system/tpacpi-bat.service to add two ExecStop lines so that stopping the service sets the battery to immediately charge fully. I switched to Arch to get back in touch with low-level system settings, so this was a nice excuse to learn more about systemd unit files. (I found “ExecStop” in the man page for systemd.unit.)

[Unit]
Description=sets battery thresholds

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/tpacpi-bat -s ST 0 40
ExecStart=/usr/bin/tpacpi-bat -s SP 0 80
ExecStop=/usr/bin/tpacpi-bat -s ST 0 0
ExecStop=/usr/bin/tpacpi-bat -s SP 0 0

[Install]
WantedBy=multi-user.target

Finally, I enabled it at startup and started it:

 
$ sudo systemctl enable tpacpi-bat
$ sudo systemctl start tpacpi-bat

One quirk: when the laptop is running off the charger but not charging the battery, acpi -s and cbatticon both say the battery status is “Unknown” instead of the usual “Charging” or “Discharging”. I haven’t looked into patching those to say “Not charging” or “Powered” or something.

Otherwise, it’s worked great the last 8 weeks. You can see near the left side of the graph where I started using tpacpi-bat and two periods in the middle where I had it off for maximum charge:

my battery graph

There’s a lot of noise in the red battery capacity line, but I hope it’ll stay quite level. Unfortunately this is an experiment with no control group: I don’t know what it would look like if I’d never made this change. But charging to 80% is only a minor inconvenience and charging fully, mostly for plane flights, is one command (sudo systemctl stop tpacpi-bat), so it will very likely be worth it over the next few years.

Want more? I'm not as good at forgetting to update @pushcx on Twitter.