Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: threshold ranges on ThinkPads #97

Open
SylChamber opened this issue Aug 14, 2024 · 15 comments
Open

bug: threshold ranges on ThinkPads #97

SylChamber opened this issue Aug 14, 2024 · 15 comments
Assignees

Comments

@SylChamber
Copy link

Computer: Lenovo ThinkPad T14 Gen 1 AMD (manufactured in 2021)
CPU: AMD Ryzen PRO 7 4750U
OS: Ubuntu 24.04

I could not set a battery threshold on my Lenovo ThinkPad T14 Gen1 (while it works on my Asus ROG Strix G15 2021). I got the following error:

$ sudo bat threshold 80
A fatal error occurred. Please rerun the command with the `--debug` flag enabled
and file an issue with the resulting output at the following address
https://github.com/tshakalekholoane/bat/issues/new.

with the debug flag:

$ sudo bat threshold 80 --debug
write /sys/class/power_supply/BAT0/charge_control_end_threshold: invalid argument

goroutine 1 [running]:
runtime/debug.Stack()
	/opt/homebrew/Cellar/go/1.22.0/libexec/src/runtime/debug/stack.go:24 +0x5e
main.main.func1()
	/Users/tshaka/x/bat/main_linux.go:111 +0x57
panic({0x5383a0?, 0xc000124270?})
	/opt/homebrew/Cellar/go/1.22.0/libexec/src/runtime/panic.go:770 +0x132
main.main()
	/Users/tshaka/x/bat/main_linux.go:247 +0x1125

When searching on the battery system path, I found the UbuntuHandbook page on setting battery threshold. Trying to set the end threshold manually failed as well:

$ sudo sh -c "echo 80 > /sys/class/power_supply/BAT0/charge_control_end_threshold"
sh: 1: echo: echo: I/O error

It led me to try manually setting the lower charging threshold to a lower value than the end value:

sudo sh -c "echo 20 > /sys/class/power_supply/BAT0/charge_control_start_threshold"

Which I unfortunately did before trying to read the current value. :-( I don't know what it was before. Afterwards, I could set the end threshold, manually or with bat.

I gather that the end threshold must not be lower than the start threshold.

@SylChamber
Copy link
Author

Uh... actually, I think I got the threshold backwards. I'm comparing with values on my Asus ROG Strix G15. It only has one value: charge_control_end_threshold. And I set it to 80. There is no start threshold.

My Lenovo ThinkPad T14 G1 has two thresholds:

  • charge_control_end_threshold
  • charge_control_start_threshold

as well as two legacy APIs that are supposedly synchronized with those two.

@pepa65
Copy link
Collaborator

pepa65 commented Aug 14, 2024

Thank you for reporting this. Do you have any idea how charge_control_start_threshold should be handled? It seems like it could be set by the user, but maybe there is a sane default, depending on charge_control_end_threshold..?

@SylChamber
Copy link
Author

Yes, I found the way it works in the Device Compatibility section on ThinkPad in the Battery Health Charging GNOME extension documentation. It depends on the direction of the movement of the thresholds: up or down. The threshold closest to the target must be modified first. That's why bat failed to lower my ThinkPad's threshold from 100 to 80. It was decreasing the end threshold to a lower value than the start. And manually setting the start threshold to a lower value allowed bat to set the end threshold.

Battery Health Charging supports 3 profiles and their defaults define 5 percent windows with the sart/end thresholds:

  • Maximum Lifespan: 55-60
  • Balanced: 75-80
  • Full Capacity: 95-100

If the thresholds are decreased (e.g. from 100 to 60), then charge_control_start_threshold must be set first (e.g. to 55), then charge_control_end_threshold (e.g. to 60):

echo '55' | sudo tee /sys/class/power_supply/BAT0/charge_control_start_threshold
echo '60' | sudo tee /sys/class/power_supply/BAT0/charge_control_end_threshold

If the thresholds are increased (e.g. from 60 to 80), then charge_control_end_threshold must be set first (e.g. to 80), then charge_control_start_threshold (e.g. to 75):

echo '80' | pkexec tee /sys/class/power_supply/BAT0/charge_control_end_threshold
echo '75' | pkexec tee /sys/class/power_supply/BAT0/charge_control_start_threshold

@pepa65
Copy link
Collaborator

pepa65 commented Aug 14, 2024

OK, I think just set the start value 5 lower than the end, and check which one needs to be set first.

@SylChamber
Copy link
Author

I learned Go these last few months (I heartily approve of your choice of language 😉), so I'll prepare a pull request with a fix.

@tshakalekholoane tshakalekholoane changed the title Error setting (end) threshold on Lenovo ThinkPad T14 Gen1 when the start threshold is higher bug: threshold ranges on ThinkPads Dec 12, 2024
@tshakalekholoane
Copy link
Owner

tshakalekholoane commented Dec 16, 2024

I had a thought about how this could be implemented without breaking changes in the API.

We could change the threshold argument to accept a range such that the user could pass a range to the threshold subcommand e.g.,

bat threshold 55,60

To maintain backwards compatibility, setting a single value would imply 0 as a lower bound, on devices that have a start threshold setting.

# The following are equivalent.
bat threshold 60
bat threshold 0,60

What do you think?

@pepa65
Copy link
Collaborator

pepa65 commented Dec 16, 2024

I don't even see the point of the start threshold, what does it mean? If the charge is below it, charge, if the charge is between start and end: don't charge? In that case it needs to be slightly below the end threshold, and I would not allow it to be set by the user, just always set it 5 below end, before adjusting the end threshold.

But if it doesn't charge below the start threshold and only charges above it, then I say: always set it to 0. (I hope it is like that, because then we can ignore the start, and always set it to 0 and don't offer a way to modify it.)

@tshakalekholoane
Copy link
Owner

Right. I am confused now.

I took it to mean that it will only charge when the current level is within the range specified by start ..= end but the linked article seems to suggest otherwise.

"For example, set the battery start charging level to 80. So, when power supply is plugged in, it only starts charging when battery is lower than 80%."

I also can't decipher how it works from the commit but if that's how it works then we should probably go with preset offset of around 5.

I also don't have any strong opinions about whether or not we should expose the full functionality to the user.

If we can confirm how it works then either is fine with me.

@SylChamber
Copy link
Author

Personnally, I don't see the point of the start threshold either. I've been using the Battery Health Charging extension in GNOME for a few months and I never felt the need to customize the thresholds. I use the built-ins 60, 80 and 100, which set 55, 75 and 95 start thresholds on my ThinkPad T14. I would always set the start threshold 5 points below the end threshold.

I'm going to do some tests with that start threshold on my ThinkPad T14 because I don't understand what it does either.

By the way, I recently wrote over Ubuntu on that ThinkPad with another distro I wanted to try out, and I was suprised to see that the thresholds had persisted after the whole disk erasure. And I still could change them manually. Where could they be stored? In the TPM chip?

@pepa65
Copy link
Collaborator

pepa65 commented Dec 17, 2024

They get reset to 100/0 (no end threshold) when the module loads. When the module never loads again, the value must get stored somewhere in the UEFI/BIOS area.

@SylChamber
Copy link
Author

SylChamber commented Dec 17, 2024

Concerning the start threshold, the TLP documentation mentions that it's the level below which charging will begin when connecting the charger. So if we set it to 0, in principle, it will never charge.

In reality, when I try setting it to 0, it is set to 95. (It must be the default value.) Even though the end threshold is set to 80. 1 is the minimum value I can set it.

I confirm that if I set it to a lower value than the actual charge, charging stops. My battery is at 67, I set the start threshold to 20, and when I plugged the power, charging stopped after a second. When I set it back to its previous value of 75, charging began again after a couple of seconds.

BTW, 0 is an invalid value for the end threshold on the ThinkPad T14.

@pepa65
Copy link
Collaborator

pepa65 commented Dec 18, 2024

OK, then start has to be set a little bit lower than end.

@pepa65
Copy link
Collaborator

pepa65 commented Dec 18, 2024

You can try the batlimit binary here to see if this works: https://github.com/pepa65/batlimit/releases/tag/0.7.0

@SylChamber
Copy link
Author

I noticed in the Makefile that you use gofumpt for formatting, and it requires go 1.22, yet the go.mod file specifies version 1.21. Which version of go should I be using?

@tshakalekholoane
Copy link
Owner

You can disregard the requirements of gofumpt or any other tool in the Makefile. For the application, any version >= 1.18 should be fine and you're welcome to bump it to a later version if you need to.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants