Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Windows calculate remaining time on battery?

I'm testing an app to let users know when to plug and unplug their laptop to get the most life out of their laptop battery. As well as this I'm trying to replicate the tooltip from the Windows power meter.

It's fairly successful so far with a couple of differences.

  1. The Windows time remaining notification, e.g. "X hr XX min (XX%) remaining", doesn't show up until after around a minute.
  2. The Windows time remaining seems more stable under changing battery loads

These lead me to think that the Windows time remaining algorithm is averaging over the past minute or so but I can't find any documentation of that. Does anyone know exactly what it does so I can reproduce it?

Here's my implementation (in Python but the question is language-agnostic). I'm thinking I'll need to average the most recent x discharge rates from polling every y seconds but need to know the values for x and y.

t = wmi.WMI(moniker = "//./root/wmi")
batts = t.ExecQuery('Select * from BatteryStatus where Voltage > 0')

time_left = 0
for _i, b in enumerate(batts):
    time_left += float(b.RemainingCapacity) / float(b.DischargeRate)

hours = int(time_left)
mins = 60 * (time_left % 1.0)
return '%i hr %i min' % (hours, mins)
like image 590
Jamie Bull Avatar asked Feb 06 '14 19:02

Jamie Bull


1 Answers

Windows follows the ACPI specification, and given the specification gives a method of calculating remaining battery time, I'd assume this would be how they'd do it.

Edit: Found a somewhat confirming source.

I'm referring specifically to chapter 3.9.3 "Battery Gas Gauge".

Remaining Battery Percentage[%] = Battery Remaining Capacity [mAh/mWh] / Last Full Charged Capacity [mAh/mWh]* 100

if you need that in hours:

Remaining Battery Life [h]= Battery Remaining Capacity [mAh/mWh] / Battery Present Drain Rate [mA/mW]

This essentially represents the current rate of change in charge capacity per unit time, you'll need to look at the ACPI spec to see how Windows implements it specifically.

The variables in question I'd assume would have to be queried from the battery controller and I'd let Windows handle all the compatibility issues there. For this there exists the Windows Management Instrumentation classes Win32_Battery and (probably more appropriate) Win32_PortableBattery. Upon some further digging, it seems like these classes calculate the remaining time for you and don't expose the current charge of the battery (probably to encourage people to have it calculated only one way/rounding issues, etc). The closest "cool" thing you can do is estimate/calculate battery wear by FullChargeCapacity / DesignCapacity. The next best thing I could find appears to be a lower level API exposed through IOCTL_BATTERY_QUERY_INFORMATION, but that seems like it also doesn't give current charge capacity in milliWatt-Hours. tl;dr Use the remaining times and percentages calculated for you by the above classes if possible :/


As an aside, some laptop manufacturers bundle their own tools to calculate time remaining and query specific micro controller implementations in their own batteries and are able to make a more informed/non-linear guestimate about remaining battery.
like image 58
lberezy Avatar answered Oct 29 '22 17:10

lberezy