teleshoes / tpacpi-bat

ThinkPad ACPI Battery Util
GNU General Public License v3.0
434 stars 43 forks source link

Force discharge for load balancing #64

Closed davidebasilio closed 8 years ago

davidebasilio commented 8 years ago

Hey there,

Thanks for the handy tool, it works fine on my T450. I was trying to figure out if there's a way to make force discharge work when not plugged to AC (i.e., when on battery). My laptop has two batteries and the default policy seems to be to totally drain one before switching to the other, but clearly this is far from ideal. Being able to set what battery to discharge would allow some load balancing.

Do you have any clue whether this is possible?

Thanks!

teleshoes commented 8 years ago

yea, thats actually why i made this. force discharge works on my w520 without being plugged into A/C. i wonder why it doesnt for you.

[rant] ITS SO STUPID THAT IT DOES THIS!!! plus a lenovo 'engineer' told me that being repeatedly drained to empty and left empty for a long time is good for lithium batteries, and that heat wasnt especially bad for them. this was after i had been sending angry emails and forum posts about it for weeks[/rant]

davidebasilio commented 8 years ago

OK, I will give it another try then, maybe I did something wrong.

Do you use a script or a daemon to manage the load balancing? Maybe could you share that so I can test it and report if it works?

Thanks for the fast answer btw!

davidebasilio commented 8 years ago

I tried again, I can confirm that force discharge does not work for me when not on AC:

$ sudo tpacpi-bat -g FD 1 no $ sudo tpacpi-bat -g FD 2 no $ sudo tpacpi-bat -s FD 1 1 $ sudo tpacpi-bat -g FD 1 no $ sudo tpacpi-bat -s FD 2 1 $ sudo tpacpi-bat -g FD 2 no

Am I doing something wrong?

teleshoes commented 8 years ago

that....looks right. are you sure its not working though? perhaps it doesnt report that its force-discharging, but does in fact discharge the correct battery anyway.

davidebasilio commented 8 years ago

It really looks like the battery that is currently discharging does not change, regardless of the calls to tpacpi-bat:

$ sudo tlp-stat -b | grep energy_now /sys/class/power_supply/BAT0/energy_now = 19830 [mWh] /sys/class/power_supply/BAT1/energy_now = 21920 [mWh] $ sudo tlp-stat -b | grep energy_now /sys/class/power_supply/BAT0/energy_now = 19830 [mWh] /sys/class/power_supply/BAT1/energy_now = 21910 [mWh] $ sudo tpacpi-bat -s FD 1 1 $ sudo tlp-stat -b | grep energy_now /sys/class/power_supply/BAT0/energy_now = 19830 [mWh] /sys/class/power_supply/BAT1/energy_now = 21870 [mWh] $ sudo tpacpi-bat -s FD 2 1 $ sudo tlp-stat -b | grep energy_now /sys/class/power_supply/BAT0/energy_now = 19830 [mWh] /sys/class/power_supply/BAT1/energy_now = 21850 [mWh]

BAT1 is always the one which is discharging (I'm not 100% sure about the mapping between BAT{0,1} and the {1,2} in tpacpi-bat, so I tried both).

teleshoes commented 8 years ago

as for scripts, my battery balancing scripts are part of my battery-display widget, called tpbattstat. (tpacpi-bat started out life as part of it).

it has a UI and a few text-only interfaces, and has several different balancing algorithms. (e.g.: brackets, where you specify a list of percentages like [0, 25, 50, 75, 100], and it charges/discharges the two batteries in turns by those brackets) if you wanted to just use the battery balancing, you could run it with --json in a terminal and ignore the output. https://github.com/teleshoes/tpbattstat

of course, if force discharge and inhibit charge dont work for you, tpbattstat wont either.

teleshoes commented 8 years ago

yea, sounds borked to me. its probably a subtle difference between the impls on t450 and the slightly older machines ive tried it on. then again. try doing tpacpit-bat -s FD 1 0 && tpacpi-bat -s FD 2 1 and vice-versa, to explicitly set the other one to 0. that helps sometimes.. also, does inhibit-charge work for you?

davidebasilio commented 8 years ago

Doing that didn't help for force discharge.

Charge inhibit works (and force discharge does work when on AC). Do you have a clue whether there's a way to understand what changed in the interface? The default behavior drives me crazy (see your rant above)..

teleshoes commented 8 years ago

heh. sorry, no. you can try poking around the interface, sending different values to it using acpi-call.

find out what the calls are for you with tpacpi-bat -v

wolke:~/Code/tpbattstat/src$ sudo tpacpi-bat -v -s FD 1 1
Call    : \_SB.PCI0.LPC.EC.HKEY.BDSS 0x101
Response: 0x0called
wolke:~/Code/tpbattstat/src$ sudo tpacpi-bat -v -s FD 2 0
Call    : \_SB.PCI0.LPC.EC.HKEY.BDSS 0x200
Response: 0x0called
wolke:~/Code/tpbattstat/src$ sudo tpacpi-bat -v -s FD 2 1
Call    : \_SB.PCI0.LPC.EC.HKEY.BDSS 0x201
Response: 0x0called
wolke:~/Code/tpbattstat/src$ sudo tpacpi-bat -v -s FD 1 0
Call    : \_SB.PCI0.LPC.EC.HKEY.BDSS 0x100
Response: 0x0called
wolke:~/Code/tpbattstat/src$ sudo tpacpi-bat -v -s FD 2 0
Call    : \_SB.PCI0.LPC.EC.HKEY.BDSS 0x200
Response: 0x0called

try running them with acpi-call, just to make sure they work

wolke:~/Code/tpbattstat/src$ sudo acpi-call '\_SB.PCI0.LPC.EC.HKEY.BDSS' 0x100
Calling : \_SB.PCI0.LPC.EC.HKEY.BDSS 0x100
Response: 0x0called
wolke:~/Code/tpbattstat/src$ sudo acpi-call '\_SB.PCI0.LPC.EC.HKEY.BDSS' 0x101
Calling : \_SB.PCI0.LPC.EC.HKEY.BDSS 0x101
Response: 0x0called
wolke:~/Code/tpbattstat/src$ sudo acpi-call '\_SB.PCI0.LPC.EC.HKEY.BDSS' 0x200
Calling : \_SB.PCI0.LPC.EC.HKEY.BDSS 0x200
Response: 0x0called
wolke:~/Code/tpbattstat/src$ sudo acpi-call '\_SB.PCI0.LPC.EC.HKEY.BDSS' 0x201
Calling : \_SB.PCI0.LPC.EC.HKEY.BDSS 0x201
Response: 0x0called

then try different values and see what they do: (apparently 0x0003 does something and returns 0 for success, while 0x0001 does nothing and gets 0x80000000 returned)

wolke:~/Code/tpbattstat/src$ sudo acpi-call '\_SB.PCI0.LPC.EC.HKEY.BDSS' 0x0001
Calling : \_SB.PCI0.LPC.EC.HKEY.BDSS 0x0001
Response: 0x80000000
wolke:~/Code/tpbattstat/src$ sudo acpi-call '\_SB.PCI0.LPC.EC.HKEY.BDSS' 0x0003
Calling : \_SB.PCI0.LPC.EC.HKEY.BDSS 0x0003
Response: 0x0called
davidebasilio commented 8 years ago

OK, I can give it a try when I find some time to experiment. So there's no documentation anywhere for the meaning of this register?

teleshoes commented 8 years ago

also, just so you know, acbreak doesnt work for me. running 'tpacpi -s FD 1 1 1' calls 0x102 and returns 0x800000000. you might want to try 0x102 and 0x202 for yourself

teleshoes commented 8 years ago

as for docs, all there is is battery_asl. (see 896c0571) pretty much every piece of information in it is also in tpacpi-bat -h

davidebasilio commented 8 years ago

OK, thanks. And that's for sandybridge laptops, as I see. May I ask you where you got that information? Do you think that there might be a way to get an updated version of it for newer laptops?

Thanks again for your time!

teleshoes commented 8 years ago

i got that through an unofficial channel by begging for it, in order to make tpacpi-bat. (i was helping to diagnose and test the horrible CPU bios bugs that plagued the w520 on its initial release).

there is no official documentation of the acpi interface, and the only way to make any headway whatsoever is to do near-impossible reverse engineering of the official windows tools.

remember when lenovo was cool and we had a SMAPI interface for battery balancing and no bizarre RAM whitelisting that doesnt include higher speeds supported by the CPU??? at least they finally got rid of those awful button-less touchpads...

davidebasilio commented 8 years ago

0x102 and 0x102 also return 0x800000000 for me. I think that randomly trying acpi-calls is quite hopeless..

Perhaps you could get in touch with that unofficial channel again and ask for updated information? That's probably the only way to make tpacpi support newer thinkpads..

BTW, do you know if the windows tools actually do load balancing on the two batteries?

teleshoes commented 8 years ago

i dont think they do load balancing, but i think they do explicit force discharge.

dont randomly try acpi-calls, try a few that you might expect to work, like 0x0[0123]0[0123]. thats only sixteen combos. find the ones that return 0x0, and then try experimenting with those 4 more carefully.

in my opinion, your chances of getting anything out of lenovo are quite slim, and unfortunately, i cannot help with that. good luck!

davidebasilio commented 8 years ago

Just reporting back in case someone might find this useful in the future.. None of the commands in 0x0[0123]0[0123] affect the currently discharging battery in any way (see log below).

root@davide /tmp # ./test-acpi.sh
/sys/class/power_supply/BAT0/power_now                      =      0 [mW]
/sys/class/power_supply/BAT1/power_now                      =   5657 [mW]
Calling \_SB.PCI0.LPC.EC.HKEY.BDSS 0x0000
0x80000000
/sys/class/power_supply/BAT0/power_now                      =      0 [mW]
/sys/class/power_supply/BAT1/power_now                      =   5579 [mW]

Calling \_SB.PCI0.LPC.EC.HKEY.BDSS 0x0001
0x80000000
/sys/class/power_supply/BAT0/power_now                      =      0 [mW]
/sys/class/power_supply/BAT1/power_now                      =   5592 [mW]

Calling \_SB.PCI0.LPC.EC.HKEY.BDSS 0x0002
0x0called
/sys/class/power_supply/BAT0/power_now                      =      0 [mW]
/sys/class/power_supply/BAT1/power_now                      =   5577 [mW]

Calling \_SB.PCI0.LPC.EC.HKEY.BDSS 0x0003
0x0called
/sys/class/power_supply/BAT0/power_now                      =      0 [mW]
/sys/class/power_supply/BAT1/power_now                      =   5551 [mW]

Calling \_SB.PCI0.LPC.EC.HKEY.BDSS 0x0100
0x0called
/sys/class/power_supply/BAT0/power_now                      =      0 [mW]
/sys/class/power_supply/BAT1/power_now                      =   5486 [mW]

Calling \_SB.PCI0.LPC.EC.HKEY.BDSS 0x0101
0x0called
/sys/class/power_supply/BAT0/power_now                      =      0 [mW]
/sys/class/power_supply/BAT1/power_now                      =   5476 [mW]

Calling \_SB.PCI0.LPC.EC.HKEY.BDSS 0x0102
0x80000000
/sys/class/power_supply/BAT0/power_now                      =      0 [mW]
/sys/class/power_supply/BAT1/power_now                      =   5541 [mW]

Calling \_SB.PCI0.LPC.EC.HKEY.BDSS 0x0103
0x80000000
/sys/class/power_supply/BAT0/power_now                      =      0 [mW]
/sys/class/power_supply/BAT1/power_now                      =   5555 [mW]

Calling \_SB.PCI0.LPC.EC.HKEY.BDSS 0x0200
0x0called
/sys/class/power_supply/BAT0/power_now                      =      0 [mW]
/sys/class/power_supply/BAT1/power_now                      =   5554 [mW]

Calling \_SB.PCI0.LPC.EC.HKEY.BDSS 0x0201
0x0called
/sys/class/power_supply/BAT0/power_now                      =      0 [mW]
/sys/class/power_supply/BAT1/power_now                      =   5564 [mW]

Calling \_SB.PCI0.LPC.EC.HKEY.BDSS 0x0202
0x80000000
/sys/class/power_supply/BAT0/power_now                      =      0 [mW]
/sys/class/power_supply/BAT1/power_now                      =   5518 [mW]

Calling \_SB.PCI0.LPC.EC.HKEY.BDSS 0x0203
0x80000000
/sys/class/power_supply/BAT0/power_now                      =      0 [mW]
/sys/class/power_supply/BAT1/power_now                      =   5517 [mW]

Calling \_SB.PCI0.LPC.EC.HKEY.BDSS 0x0300
0x80000000
/sys/class/power_supply/BAT0/power_now                      =      0 [mW]
/sys/class/power_supply/BAT1/power_now                      =   5563 [mW]

Calling \_SB.PCI0.LPC.EC.HKEY.BDSS 0x0301
0x80000000
/sys/class/power_supply/BAT0/power_now                      =      0 [mW]
/sys/class/power_supply/BAT1/power_now                      =   5575 [mW]

Calling \_SB.PCI0.LPC.EC.HKEY.BDSS 0x0302
0x80000000
/sys/class/power_supply/BAT0/power_now                      =      0 [mW]
/sys/class/power_supply/BAT1/power_now                      =   5599 [mW]

Calling \_SB.PCI0.LPC.EC.HKEY.BDSS 0x0303
0x80000000
/sys/class/power_supply/BAT0/power_now                      =      0 [mW]
/sys/class/power_supply/BAT1/power_now                      =   5595 [mW]

I think that unless we get some information from Lenovo, this is unlikely to ever work on newer thinkpads..

davidebasilio commented 8 years ago

Further update..

The replaceable battery is always the one that discharges first when not on AC.

I can successfully force the internal battery to discharge on AC, but when I plug AC off, it will immediately switch to discharging the other one.

There seems to be no way to change this behavior through this interface. Maybe there's another way, but go figure..

teleshoes commented 8 years ago

thanks for the update. i recommend trying more combinations of things you can do (doing them in a different order, maybe adding inhibit charge to the other battery, setting force discharge to ON and the OFF on the battery you DONT want to discharge, etc) also, i assume you waited at least 5s between each acpi call before reading the instantaneous current.

there is almost certainly no other avenue available whatsoever, aside from this interface. theres nothing TLP can do, since that is a high-level program (it doesnt deal with hardware directly at all, but instead aggregates many hardware interfaces into one coherent tool). also, lenovo apparently accepts money from microsoft to discourage linux use (as evidenced by lenovo officially recommending windows all over everything)

good luck!

teleshoes commented 8 years ago

oh one more thing, maybe, that you can test. IIRC, theres some lock or other on the battery that if you flick, will cause it to discharge the main battery. perhaps that will affect this, but probably not. at the least, if this lock exists, you can balance the battery manually, with programmatic alarms to remind you to flick it at intervals.