Control battery charging

Switching from the Xperia X to the 10 II, I played around with the options in /sys/class/power_supply/battery/.

I observed that the 10 II only has /sys/class/power_supply/battery/charging_enabled to really stop battery charging before the battery is full.
Unfortunately, this also prevents the device from using any power coming in via USB. Instead, it starts to drain the battery even while it is connected to a charger!

The Xperia X features /sys/class/power_supply/battery/battery_charging_enabled, which allows to stop charging but continue to run with the energy from the external source.
→ As long as the energy consumption is not more than provided via USB, the battery is not drained.

Glancing at the kernel (GitHub - sailfishos/kernel-adaptation-pc , GitHub - sonyxperiadev/kernel , Index of /sources/ , did I miss some repo?) this nice feature is indeed gone on the Xperia 10 II.

Is this a hardware limitation or can this be fixed in software?

In case it’s the hardware, is there a place where I can find out what is actually possible? The closest docs I could find is https://developer.sony.com/develop/open-devices/get-started/supported-devices-and-functionality/current-platform-functionality-maintained/ but this list does not contain all devices…

9 Likes

Okay, I figured it out :smiley:

Yes, this can be fixed in software.

Turns out that the needed functionality was already in the kernel of the Xperia X (and possibly all devices?):

echo 1 > lrc_enable and echo 70 > lrc_socmax instructs the kernel to stop charging at 70%.
On both devices the charging current falls to 0 when this limit is reached → battery is neither drained nor charged while being connected to a charger.
At least as long as the device does not draw more power than provided by the charger.
See takimata / harbour-battery-charging-control · GitLab more details and an app automating this.

So the fact that echo 0 > charging_enabled starts to drain the battery on the 10 II is only a kernel quirk. But the LRC charging was the stuff I wanted right from the start, so I’m not that eager to fix the kernel any more :slight_smile:

7 Likes

Thanks, nice find!

I’ll try to add this to Battery Buddy at some point :slight_smile:

7 Likes

It’s a bit unfortunate that we have two apps doing essentially the same thing.
Battery Buddy didn’t exist back in 2018 when I first started working on that topic, so I’ve built my own app for this.

But it’s still great to see that having this stuff documented helps people :slight_smile:

Unfortunately the XA2 has no lrc_enable / lrc_socmax options. Haven’t found an alternative. Which is weird, as it all qualcomm and the even the JP1-SOC had this option.

I guess you’ve already checked all subdirectories in /sys/class/power_supply/?
Maybe it’s part of the BMS (Battery Management System) or some other component on the XA2…

Yes. There are many things, but no lrc-stuff. There might be alternatives, but I don’t think it’s wise to start writing some numbers to all those options, hoping it helps.

Hmm, interesting.
Could you post a full ( ls -lah ) directory listing for battery/ (and battery_ext, if present)?

The Xperia X and 10 II both allow to set the charging current, at least to some extent.
So you could disable charging that way, if possible.

Or at least slow down charging a lot. But I’m unsure about the effects of a low but still nonzero charging current in the long term. This approach might also be more inefficient in case the internal circuitry just burns the unwanted energy…

[root@XperiaXA2 battery]# ls -lah
total 0      
drwxr-xr-x    3 root     root           0 Jul 17 21:11 .
drwxr-xr-x    7 root     root           0 Jul 17 21:11 ..
-rw-r--r--    1 root     root        4.0K Aug  8 14:34 capacity
-r--r--r--    1 root     root        4.0K Aug 10 13:30 charge_counter
-r--r--r--    1 root     root        4.0K Aug 10 23:38 charge_done
-r--r--r--    1 root     root        4.0K Aug 10 23:38 charge_type
-r--r--r--    1 root     root        4.0K Aug 10 23:38 charger_temp
-r--r--r--    1 root     root        4.0K Aug 10 23:38 charger_temp_max
-r--r--r--    1 root     root        4.0K Aug 10 23:38 constant_charge_current_max
-r--r--r--    1 root     root        4.0K Aug 10 13:30 current_now
-r--r--r--    1 root     root        4.0K Aug 10 23:38 current_qnovo
lrwxrwxrwx    1 root     root           0 Aug 10 23:38 device -> ../../../800f000.qcom,spmi:qcom,pm660@0:qcom,qpnp-smb2
-r--r--r--    1 root     root        4.0K Aug 10 23:38 die_health
-rw-r--r--    1 root     root        4.0K Aug 10 23:38 dp_dm
-r--r--r--    1 root     root        4.0K Aug  8 14:34 health
-rw-r--r--    1 root     root        4.0K Aug 10 23:38 input_current_limited
-rw-rw-rw-    1 root     root        4.0K Aug 10 16:00 input_suspend
-rw-r--r--    1 root     root        4.0K Aug 10 23:38 parallel_disable
drwxr-xr-x    2 root     root           0 Aug 10 23:38 power
-r--r--r--    1 root     root        4.0K Aug 10 13:30 present
-rw-r--r--    1 root     root        4.0K Aug 10 23:38 rerun_aicl
-r--r--r--    1 root     root        4.0K Aug 10 23:38 set_ship_mode
-r--r--r--    1 root     root        4.0K Aug  8 14:34 status
-rw-r--r--    1 root     root        4.0K Aug 10 23:38 step_charging_enabled
lrwxrwxrwx    1 root     root           0 Aug  8 14:34 subsystem -> ../../../../../../../../class/power_supply
-rw-r--r--    1 root     root        4.0K Aug 10 23:38 sw_jeita_enabled
-rw-r--r--    1 root     root        4.0K Jul 17 21:11 system_temp_level
-r--r--r--    1 root     root        4.0K Aug 10 13:30 technology
-r--r--r--    1 root     root        4.0K Aug  8 14:34 temp
-r--r--r--    1 root     root        4.0K Aug 10 23:38 type
-rw-r--r--    1 root     root        4.0K Aug  8 14:34 uevent
-r--r--r--    1 root     root        4.0K Aug 10 23:38 voltage_max
-r--r--r--    1 root     root        4.0K Aug 10 13:30 voltage_now
-r--r--r--    1 root     root        4.0K Aug 10 23:38 voltage_qnovo
[root@XperiaXA2 battery]# cd ../bms
[root@XperiaXA2 bms]# ls -lah
total 0      
drwxr-xr-x    3 root     root           0 Aug 10 23:39 .
drwxr-xr-x    3 root     root           0 Aug 10 23:39 ..
-r--r--r--    1 root     root        4.0K Aug 10 23:39 battery_type
-r--r--r--    1 root     root        4.0K Aug 10 23:39 capacity
-r--r--r--    1 root     root        4.0K Aug 10 23:39 capacity_raw
-rw-r--r--    1 root     root        4.0K Aug 10 23:39 cc_step
-rw-r--r--    1 root     root        4.0K Aug 10 23:39 cc_step_sel
-r--r--r--    1 root     root        4.0K Aug 10 23:39 charge_counter
-r--r--r--    1 root     root        4.0K Aug 10 23:39 charge_full
-r--r--r--    1 root     root        4.0K Aug 10 23:39 charge_full_design
-r--r--r--    1 root     root        4.0K Aug 10 23:39 charge_now
-r--r--r--    1 root     root        4.0K Aug 10 23:39 charge_now_raw
-rw-r--r--    1 root     root        4.0K Aug 10 23:39 constant_charge_voltage
-r--r--r--    1 root     root        4.0K Aug 10 23:39 current_now
-r--r--r--    1 root     root        4.0K Aug 10 23:39 cycle_count
-rw-r--r--    1 root     root        4.0K Aug 10 23:39 cycle_count_id
-r--r--r--    1 root     root        4.0K Aug 10 23:39 debug_battery
lrwxrwxrwx    1 root     root           0 Aug 10 23:39 device -> ../../../800f000.qcom,spmi:qcom,pm660@0:qpnp,fg
drwxr-xr-x    2 root     root           0 Aug 10 23:39 power
-r--r--r--    1 root     root        4.0K Aug 10 23:39 resistance
-r--r--r--    1 root     root        4.0K Aug 10 23:39 resistance_id
-r--r--r--    1 root     root        4.0K Aug 10 23:39 soc_reporting_ready
lrwxrwxrwx    1 root     root           0 Aug 10 23:39 subsystem -> ../../../../../../../../class/power_supply
-r--r--r--    1 root     root        4.0K Aug 10 23:39 temp
-r--r--r--    1 root     root        4.0K Aug 10 23:39 time_to_empty_avg
-r--r--r--    1 root     root        4.0K Aug 10 23:39 time_to_full_avg
-r--r--r--    1 root     root        4.0K Aug 10 23:39 type
-rw-r--r--    1 root     root        4.0K Aug 10 23:39 uevent
-r--r--r--    1 root     root        4.0K Aug 10 23:39 voltage_max_design
-r--r--r--    1 root     root        4.0K Aug 10 23:39 voltage_now
-r--r--r--    1 root     root        4.0K Aug 10 23:39 voltage_ocv

There is no battery_ext directory. I guess the writable files are most interesting?

In general, yes. There are writeable files which are not effectively writeable, though.

Thanks for the list. Seems like LRC-like functionality is indeed missing. On the other hand, it probably isn’t that hard to patch the kernel to stop charging at some level, because all the needed infra (determining state of charge and disabling charging completely) is already there…

1 Like

Is there an installable package for the app?

You can manually download the RPM from Gitlab or install via Chum to automatically get updates.

For Chum, see GitHub - sailfishos-chum/main: Documentation and issues and Announcing sailfishos:chum .

From the data above, the app currently doesn’t work on the XA2 (yet). Please let me know if it doesn’t work for you!

In general, the functionality is similar to Battery Buddy, only my approach is different (more in the direction of less complexity/overhead and therefore less features).

Thanks. I was looking for that link. Works on 10 II, at least the battery meter stops advacing after the preset max charge is set. Hopefully it really does stop after that, i.e. it doesn’t just fix the “interface” part.

Come to think of it, that’s a great idea for an easter egg/april fools’ joke! I’m unsure on how to achieve that, but I’m sure that would make values beyond 100% possible :smiley:

Back to topic:

Recently I’ve observed that charging may not be resumed under very special conditions:

  1. Plug phone into a computer’s USB port and keep it plugged in all the time
  2. Put computer to sleep/suspend (no current is provided by the computer)
  3. Wait till phone looses a few percent points of charge so that it drops below the configured level
  4. Wake up the computer (USB power available again)
  5. Phone should start charging again, but actually doesn’t

Physically re-plugging the phone triggers charging again (if it’s below the charging level).

As I’m unsure whether that’s a fault on the side of the computer or phone, USB power negotiation, … I’m interested in user reports on this.

Hi! have also a look at old thread "charge management for battery health " on old sfos forum

@takimata I think it’s motherboard and OS-specific. For me it resumes charging after exiting standby.

It also doesn’t show the charging had stopped when the host is in sleep mode, even though the charging isn’t really occurring. Could be Sailfish interpreting any active USB connection as charging.

Which device are you using?

Hmm, I can’t reproduce that. Maybe you are using an USB port on a laptop which does some USB charging even when powered off (can be usually configured in the BIOS)?

Nevertheless, in general, you are right - any positive charging current is interpreted as charging - even when it’s just something like 50 mA, for which charging takes forever…

Xperia 10 II.
Testing on a regular desktop PC, not a notebook.

I did not tried this yet, however today I noticed that the threshold that are respected using a the battery charger are NOT respected when the smartphone is connected to the a USB laptop charging port on USB tethering mode:

mcetool | grep -i charg

Display on at charging start         3000 ms
Charger cable:                       connected
Charger state:                       on
Charging mode:                       apply-thresholds
Charging override:                   disabled
Charging enable limit:               95 (%)
Charging disable limit:              90 (%)

I am going to try the solution and I will report if also address this shortcoming. In particular these which need to set every boot:

echo 1 >/sys/class/power_supply/battery_ext/lrc_enable; 
echo 95 >/sys/class/power_supply/battery_ext/lrc_socmax; 
echo 90 >/sys/class/power_supply/battery_ext/lrc_socmin; 
echo 1 >/sys/class/power_supply/battery/lrc_enable

Unless a specific application is installed because this report nothing:

sysctl -a 2>/dev/null | grep -iE "lrc|batt|charg"

Update

After those commands above, the battery charge works as expected when the smartphone is connected to a laptop USB for tethering. The only part that is still missing is to write those values at boot time, but a simple solution is to install cron and make it run /etc/rc.local at each @reboot. A suggestion for a more stylish solution will be appreciated.

Can someone tell me the role of this kernel feature?

/sys/class/power_supply/battery_ext/lrc_not_startup

Zero by default.