A couple of tools to read and control the battery of the PinePhone Keyboard Case, including automatic power management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Phalio 05b6f97412
readme: ppkbbat-d systemd clarifications
4 weeks ago
aur-ppkbbat-tools-git@4e60994fd2 added aur-ppkbbat-tools-git as submodule 7 months ago
.gitmodules added aur-ppkbbat-tools-git as submodule 7 months ago
LICENSE Initial commit 10 months ago
README.md readme: ppkbbat-d systemd clarifications 4 weeks ago
ppkbbat-d fix: voltage_ocv not found 5 months ago
ppkbbat-info ppkbbat-info: forgot to remove the pp ocv testing thing 5 months ago
ppkbbat-notif ppkbbat-notif: improved notification display 5 months ago
ppkbbat-setlimit setlimit: added config file support, changed default limits 9 months ago
ppkbbat-toggle ppkbbat-toggle: made it not attempt to toggle while kb is charging 7 months ago

README.md

ppkbbat-tools

A couple of tools to read and control the battery of the PinePhone Keyboard Case, including automatic power management.

If you need any help, feel free to contact me via any of these methods.

If you find this helpful, you have the option of donating to me here. Any amount is highly appreciated :)

Content

  1. Important Notices
  2. Introduction
  3. Usage
    1. ppkbbat-d
      1. General Usage
      2. Examples
      3. Running as a Background Service
        1. Keyboard Battery Output During Suspension
      4. Charge Mode Explanation
      5. Parallel Charging
      6. Sequential Charging
    2. ppkbbat-info
    3. ppkbbat-setlimit
      1. General Usage
      2. Permanent Limit
    4. ppkbbat-notif
    5. ppkbbat-toggle
    6. Config File
  4. Troubleshooting
    1. Charging not working
    2. Error#1, Error#2: Charging stops when plugged in
    3. Error#3: The Phone is not charging because the pins are not connecting
    4. Automatic suspension is not working while the keyboard is attached and on
    5. OG PP current is always positive
    6. Modifying the online value breaks reading/writing values
    7. Wrong keyboard current while charging
  5. Further Reading

Important Notices

Previously it was advised not to use the phones USB port at all when the Keyboard Case is attached.1 2 3 4 However, Megi has done some tests and concluded that using either port by itself should be safe, only using both at once has to be avoided.5 This means that plugging a power supply into the phone to only charge its battery as well as using a (powered) dock is possible after all.

Use a 5V 3A power supply if possible.6 If you plug a power supply into the keyboard and your phone reports that it alternates between being charged and not being charged, the power supply is supplying too much power and the keyboard is shutting off as a safety measure. Using power supplies supplying too little power (like ≤ 5V 1.5A) could have the supply run too hot and/or break.

Megi is working on proper PPKB power management that will be integrated into the kernel. Keep an eye out for announcements on Megis blog. Once its done, all of this wont be necessary anymore, at least if you use a distro with an up-to-date kernel. Those distros with older kernels will still require ppkbbat-d or a Permanent Limit until they update.

kbpwrd is another tool for automatic power management like ppkbbat-d and most likely more efficient, you should give it a try as well.

Introduction

The default behaviour of the PinePhone Keyboard battery is not optimal and presents the user with some issues. These are mostly caused by two things: The charging priority which is KB battery -> PP -> PP battery and the input current limits which are only 0.5A for the PP and 2.3A for the KB. This results in the phone receiving very little power from the KB battery or power supplies, and even when this is modified, the aforementioned order of priorities still makes especially charging with power supplies very difficult. The keyboard battery will take up 2.3A first and only pass the remainder through to the phone. Only when the keyboard battery is full will the priority switch to the phone and supply it with the full amount the power supply can provide. So, especially with the unchanged default behaviour, a power supply as recommended, 5V 3A, is a minimum. Supplying 3A will leave about 0.6A for the phone while the Keyboard battery is charging and has priority, which it will have for a couple of hours due to its high capacity. Power supplies with less power may be used but definitely require power management as provided by ppkbbat-d.

Now imagine the situation of both batteries being low. You plug a 5V 3A power supply into the keyboards USB port. The keyboard battery takes priority as it is not full and receives 2.3A, leaving the phone with the remaining 0.6A from the 3A power supply. 0.6A is about what a PinePhone uses if not doing anything too power intensive. This means, in the best scenario, the PinePhones battery will stay constant for a few hours until the keyboard battery is full, and only then start charging. But if the phone uses more power, the percentage will continue to go down for those few hours, possibly reaching 0%. And if you have a power supply with only 1A or 2A, the phone wont get anything until the keyboard battery has fully charged, and on top of that it will take a lot longer for the keyboard battery to become full, so the phone will most likely go down to 0% first.

Its currently not possible to influence the charging priority. It is possible to change the input current limits for the keyboard battery and phone battery. Adjusting them dynamically according to the current situation achieves a similar effect, for example setting the keyboard batterys input limit to the minimum passes more power from a connected power supply through to the phone.

Now, ppkbbat-tools gives you two main options for this: You can either use ppkbbat-d to have the limits adjusted automatically as needed, or you can use ppkbbat-setlimit to permanently set the PP and KB limit to something that works well enough for you in all cases. The minimum you should do is set the PP limit to something higher than the default 0.5A since that is barely enough to keep up with what the phone uses and not enough to properly charge it. Additionally, if you not use Sxmo but something like Plasma Mobile or Phosh, you have to enable automatic suspension while charging.

You should also note that the power part and keyboard part of the PPKB are entirely separate. The button on the side only turns the charging and battery mechanisms off, the keyboard part is always on and derives its power from the phone, not from the keyboard battery.

For Arch users, a PKGBUILD by Edgar Vincent is available at https://git.sr.ht/~e-v/aur-ppkbbat-tools-git that includes the recommended systemd setup for automatic power management. Enable ppkbbat-d.timer after installation. If you dont use Sxmo, you also have to activate automatic suspension while charging as described here. The PKGBUILD does not include the optional but useful additional systemd service to turn the keyboard battery off during suspension as Ive been unable to get it to work universally and it has an unintended side-effect. Read this to manually set that up.

git clone https://git.sr.ht/~e-v/aur-ppkbbat-tools-git
cd aur-ppkbbat-tools-git/
makepkg -si
sudo systemctl enable --now ppkbbat-d.timer

Lastly I would like to thank Megi for all of his work regarding the PinePhone Keyboard, and of course the PinePhone in general. You can donate to him at https://xnux.eu/contribute.html.

I recommend setting up ppkbbat-d as described in Running as a Background Service.

Usage

ppkbbat-d

The main goals of this tool are to fix the suboptimal default battery and charging behaviours and to make battery handling fully automatic, eliminating the need for the side button to be pressed. With it you only have to use the side button to turn the keyboard power mechanism on if it fails to do so automatically, to turn it off if you plan to entirely power down the phone for a longer period of time or to turn it off while youre plugging a charger or powered dock into the phones USB port (not required but it wastes keyboard battery charge otherwise).

This tool recognises the current power state and automatically sets the input limits to achieve the best behaviour. When connected to a power supply, it charges both batteries at once relative to their maximum capacity so that both become full at roughly the same time (alternatively it charges the phone battery first and the keyboard battery second). When discharging, it discharges both batteries by roughly the same relative amount but will make sure the phone battery doesnt fully discharge if the keyboard battery still holds power. When the phone has an increased power need due to power intensive things running, it will make sure to provide the phone with more power. Keyboard battery -> phone charging is never entirely deactivated, it always provides the phone with a little power. This means that only the keyboard battery will slowly discharge when the phone uses very little power or it might even charge the phone battery very slowly. Balancing charging as well as discharging between both batteries at the same time is better for battery life than charging/discharging only one at a time at full power, while still retaining the maximum charge speed of a power supply.

General Usage

ppkbbat-d [options] <interval>

  <interval>  The update interval in seconds. Default is 1. Use 0 to run once.

Options:

  -q  Sequential charge mode (charge PP first, then KB), default is parallel charge mode.
  -s  Silent mode that prints no log messages.

You can just use it in a terminal to see if it works, what it does and to just play around with it. To have it always manage your batteries, read Running as a Background Service. If you dont use Sxmo as your desktop environment but instead any other one like Phosh or Plasma Mobile, you also have to enable automatic suspension while charging.

ppkbbat-d features two charge modes: Parallel (default) and sequential (-q). Parallel charging is most likely the better choice. If you dont use a 5V 3A charger, you will have to make an adjustment in the config file as described below under Parallel Charging (default) or Sequential Charging, depending on what you use. No matter what mode or custom config you use, it will always make sure the PP is not losing charge when a power supply is connected.

Examples

[amarizo@squirtle:~]$ sudo ppkbbat-d
21:40:31 Discharging, low usage: Low KB->PP powering
[…]
22:18:13 Discharging, high usage: Medium KB->PP powering
[…]
22:36:26 Discharging, PP low: Keep PP above 25%
[…]
16:36:47 KB off/empty: Ready for power supply
[…]
16:10:42 Charging: Charge both
[…]
16:18:61 Charging, high usage: Max PP powering
[…]
20:10:42 Charging, KB full: Charge PP
[…]
[lily@nefēly:~]$ sudo ppkbbat-d -q
16:10:42 Charging: Charge PP first
[…]
16:48:48 Charging, PP full, low usage: Charge KB
[…]
16:51:53 Charging, PP full, high usage: Charge KB a bit
[…]
20:10:42 Charging, KB full: Charge PP
[…]

Running as a Background Service

You can have ppkbbat-d running automatically in the background to always manage the limits for you, for example using a systemd service. Keeping ppkbbat-d active even for short durations has the potential of causing this bug, no matter the update interval specified, like ppkbbat-d 600. For some reason, periodically starting ppkbbat-d once by specifying an interval of 0 seems to reliably prevent any issues, so I recommend setting it up this way, like using a systemd timer that periodically activates ppkbbat-d 0 as described below. If your power supply provides less than 5V 3A, you might also want to lower the parallel_kb_charge_limit as described in Parallel Charging.

Sxmo has a very short idle suspend time of 8 seconds. If you just plug a charging cable into your device and then let the phone go to sleep, there is a high chance that it will suspend before the minutely systemd service as below has set the limits correctly for charging. Additionally setting up a permanent limit fixes this as it will set these limits once every time and as soon as a charger is plugged in. If you use a power supply with less than 5V 3A, you have to set the setlimit_kb value in the config file to the same value as the parallel_kb_charge_limit mentioned in the last paragraph.

systemd:

If you used the PKGBUILD as described at the end of Introduction, the following two systemd files have already been created and set up for you. You only have to activate the timer as described below after the second code block.

Create the file /etc/systemd/system/ppkbbat-d.service with the following content (adjust the path to ppkbbat-d to fit yours):

[Unit]
Description=PinePhone Keyboard battery power management
Wants=ppkbbat-d.timer

[Service]
Type=simple
ExecStart=/home/alarm/git/ppkbbat-tools/ppkbbat-d 0

[Install]
WantedBy=default.target

If you dont need the log messages and youre bothered by it spamming your journal, use ppkbbat-d -s 0 instead.

Then add the timer that will periodically activate this service by creating /etc/systemd/system/ppkbbat-d.timer with the following content:

[Unit]
Description=PinePhone Keyboard battery power management

[Timer]
OnCalendar=minutely
Persistent=true

[Install]
WantedBy=timers.target

Activate the timer (not the service!) by using sudo systemctl enable --now ppkbbat-d.timer. Now the limits will be adjusted once per minute. To access the log messages when it runs via systemd, use journalctl -f | grep "$HOSTNAME ppkbbat-d". Omit the -f for journalctl to see the entire log history instead of a live view.

cron:

Use sudo crontab -e to open the crontab for the root user and add the following line:

* * * * * /home/alarm/git/ppkbbat-tools/ppkbbat-d 0

Adjust the path to ppkbbat-d to fit yours. Now the limits will be adjusted once per minute.

The keyboard battery should also be automatically turned off with ppkb-i2c-charger-ctl during suspension and turned on again after waking up as described in the second half of the systemd section. I dont know how to do this without systemd (apart from Sxmo, see Sxmo) but there surely is a way. Its not necessary but better for the batteries and otherwise the batteries will produce heat while suspended which may be uncomfortable in your pocket.

Keyboard Battery Output During Suspension

Disclaimer: At least for me, this has the unintended side-effect of the keyboard battery occasionally fully shutting itself off when unplugging a charging cable. If you use what is described in this paragraph, you should pay attention to your battery indicator when unplugging a charging cable to check if the keyboard battery goes offline and if it does, press the keyboards side button once to activate it again. Or just always press the button after unplugging.

When the phone suspends after being idle, the internal battery only has to provide a very small amount of power and the keyboard battery will therefore charge the phone. This wastes charge, is suboptimal for battery life and creates heat in your pocket. The following two additional systemd services disable keyboard battery output during suspension. Its not necessary but highly recommended to use them along with ppkbbat-d.

The following systemd services require ppkb-i2c-charger-ctl from Megis PinePhone Keyboard Tools. If you already have them, skip this paragraph. On DanctNIX Arch, you can simply use sudo pacman -S ppkb-tools. On any Arch-based system including Manjaro, you can get them from the AUR as pinephone-keyboard-git. To compile them manually (make sure you have make, gcc and php installed), use git clone https://megous.com/git/pinephone-keyboard, cd pinephone-keyboard and make. ppkb-i2c-charger-ctl is then located in the build subfolder, like in the example path of the systemd services below.

These services seem not to work with Sxmos auto suspend for some reason. If you use Sxmo, dont use them and follow these instructions instead.

Create the following two files with sudo and adjust both paths to ppkb-i2c-charger-ctl to fit yours (if you installed it with a package manager or via the AUR, you can find its location with which ppkb-i2c-charger-ctl):

/etc/systemd/system/ppkbbat-suspend.service

[Unit]
Description=Shut off PPKB battery before suspend
Before=suspend.target

[Service]
Type=simple
ExecStart=/bin/bash -c 'if [ "$(cat /sys/class/power_supply/ip5xxx-battery/status)" = "Discharging" ]; then /home/alarm/git/pinephone-keyboard/build/ppkb-i2c-charger-ctl power-off; fi'

[Install]
WantedBy=suspend.target

/etc/systemd/system/ppkbbat-wake.service

[Unit]
Description=Turn on PPKB battery after suspend
After=suspend.target

[Service]
Type=simple
ExecStart=/bin/bash -c 'if [ "$(cat /sys/class/power_supply/ip5xxx-battery/status)" = "Discharging" ]; then /home/alarm/git/pinephone-keyboard/build/ppkb-i2c-charger-ctl power-on; fi'

[Install]
WantedBy=suspend.target

Activate both of them by using sudo systemctl enable ppkbbat-suspend.service and sudo systemctl enable ppkbbat-wake.service. Now the phone battery level should not go up while suspended without a charger plugged in and no heat should be produced during that time either.

Sxmo

If you havent already, copy the following two hooks to your home folder. If you dont have the directory in your home folder yet, create it first. Replace the device name pinephone-1.2 with yours if you use a different model, e.g. a pinephone-pro or an older regular PinePhone. neofetch can tell you the model name.

mkdir -p "~/.config/sxmo/hooks/pine64,pinephone-1.2/"
cp "/usr/share/sxmo/default_hooks/pine64,pinephone-1.2/sxmo_hook_presuspend.sh" "~/.config/sxmo/hooks/pine64,pinephone-1.2/"
cp "/usr/share/sxmo/default_hooks/pine64,pinephone-1.2/sxmo_hook_postwake.sh" "~/.config/sxmo/hooks/pine64\,pinephone-1.2/"

Edit ~/.config/sxmo/hooks/pine64,pinephone-1.2/sxmo_hook_presuspend.sh, create a new line after . sxmo_common.sh and paste the following into that line. Adjust the path to ppkb-i2c-charger-ctl to fit yours (if you installed it with a package manager or via the AUR, you can find its location with which ppkb-i2c-charger-ctl):

# Deactivate PPKB battery output if it holds power and is not charging
if [ "$(cat /sys/class/power_supply/ip5xxx-battery/status)" = "Discharging" ]; then
    sudo $HOME/code/pinephone-keyboard/build/ppkb-i2c-charger-ctl power-off
fi

Edit ~/.config/sxmo/hooks/pine64,pinephone-1.2/sxmo_hook_presuspend.sh, create a new line after # Add here whatever you want to do and paste the following into that line. Adjust the path to ppkb-i2c-charger-ctl to fit yours.

# Activate PPKB battery output if it holds power and is not charging
if [ "$(cat /sys/class/power_supply/ip5xxx-battery/status)" = "Discharging" ]; then
    sudo $HOME/code/pinephone-keyboard/build/ppkb-i2c-charger-ctl power-on
fi

Charge Mode Explanation

The default and recommended mode charges both batteries in parallel relative to their maximum capacities, so the KB receives about twice as much as the PP to have both reach 100% at roughly the same time. This allows suspending the device while charging (which Sxmo does by default) as there is no need to change priority from PP to KB, which ppkbbat-d cant do during suspend. It also improves battery life as slower charging is healthier and it is faster than sequential mode (about 4h instead of about 5h) and as fast as kernel-managed charging. I believe this has two reasons:

One factor is the batteries accepting less and less power as their percentages increase which ppkbbat-d does not account for. This results in less power from the power supply actually being used as the percentage increases, power that could and should be used by the other battery. But ppkbbat-d -q directs almost all power to one battery at a time until its nearly full instead of dynamically allocating the remainder to the other battery, as non-ppkbbat-d behaviour does.

The other factor, as the following theoretical calculations suggested before I tried parallel charging in practice, is related to the fact that charging one battery after the other allows the PP to charge at 1.2A and the KB to charge at up to 2.3A, while charging them together would charge the PP at about 0.8A (more or less of course depending on what the phone uses if not suspended) and the KB at 1.6A. If we assume that, for simplicity, the PP battery takes one hour to charge at 3A and the twice as big KB battery two hours at 3A, the hypothetical charge time when charging them one after the other with the aforementioned real current values would be:

PP_charge_time = (3A ÷ 1.2A) × 1h = 2.5h
KB_charge_time = (3A ÷ 2.3A) × 2h = 2.6h
total_charge_time = $PP_charge_time + $KB_charge_time = 5.1h

Charging them at the same time would mean the following, taking the longer of the two time spans as the total time since both occur at the same time:

PP_charge_time = (3A ÷ 0.8A) × 1h = 3.75h
KB_charge_time = (3A ÷ 1.6A) × 2h = 3.75h
total_charge_time = MAX ($PP_charge_time : $KB_charge_time) = 3.75h

Parallel charging in the above theory supplies both batteries with a total of 2.4A while sequential charging supplies an average of (1.2A + 2.3A + 2.3A) ÷ 3 = 1.93A (the actual value would be a bit higher since the non-prioritised battery also receives a little). Together they can make use of the full amount of power received by a power supply, but alone they can only take up to 1.2A/2.3A. Due to the behaviour as described and shown here, decreasing the KB limit appears to be lossy, as decreasing the KB limit by x increases the amount of power the phone gets by only x/2. Sequential charging can be improved a bit if using a 3A power supply since that is enough to provide a bit more power than what the PP can take, so the KB limit can be set a bit higher. I set this as the default (0.8A KB limit) since 3A power supplies should be used and this makes both modes work for 3A by default, but it means that people using power supplies with less than 3A will have to use the config file for sequential charging as well to decrease the KB limit to its minimum.

Parallel Charging

Parallel charging is specifically tuned for charging with 5V 3A supplies by default, so you might experience issues with lower-power supplies. Its supposed to charge the KB at twice the amount of current as the PP, since its maximum capacity is about twice as high. Use ppkbbat-info to check the current values while charging, and keep in mind that the PP will display lower net input currents if its doing something more power-intensive. You can customise the amount of power the KB and PP get to fit your needs if the currents are too far off a 1:2 ratio. Test this ratio while charging, with both batteries between 20% and 80% as well as being in average charge conditions (screen off or on depending on what it will usually be when you charge it and with nothing power-intensive running, unless you always run it). Edit the file /etc/ppkbbat-tools with sudo and add the following line:

parallel_kb_charge_limit=1500000

Adjust this number, restart ppkbbat-d and see how the current values change using ppkbbat-info. Lowering the number will decrease what the KB receives and therefore increase what the PP receives. With my 2.4A charging cable I currently use a limit of 1000000.

Sequential Charging

This mode charges the PP to full first and only then the KB. This is worse for battery life, it wont switch to KB charging when the PP becomes full during suspension (e.g. in Sxmo that suspends while charging by default) and it takes longer (see the table below). But it always makes sure the PP doesn't discharge when a power supply is plugged in and it could also be useful if you detach the keyboard a lot and you therefore want to make sure the PP itself is charged as quickly as possible first. Sequential charging is specifically tuned for charging with 5V 3A supplies by default, so you will experience issues with lower-power supplies. If you use a power supply with less than 3A, edit the file /etc/ppkbbat-tools with sudo and add the following line:

sequential_kb_charge_limit=500000

This will make sure that (almost) all power from the power supply goes to the PP first when it has to charge. The default value as defined in ppkbbat-d is 800000. Here are some test results of different sequential_kb_charge_limit values with a 5V 3A power supply, Arch Sxmo and the screen off (time to full is measured from pp 10% kb empty to both have reached status full):

sequential_kb_charge_limit PP current during KB priority KB current during priority Time to both full
2000000 0.6A 2.1A 4h (same as parallel mode)
500000 1.2A 0.14A 5.5h
700000 1.2A 0.44A 5h
800000 1.2A 0.78A 5h
900000 1.15A 0.89A 4.75h

I chose 800000 as the default value as its the first current limit value where the amount the KB actually gets corresponds to the limit, so it gets a fair amount while the PP should still also get its maximum 1.2A unless its doing something more power-intensive, although there seemed to have been not that much of a difference to the KB getting only 0.14A. But in any case, ppkbbat-d sequential mode is slower than parallel mode and parallel mode is as fast as charging managed by the kernel.

ppkbbat-info

This tool fetches all battery values and outputs them into a nice table (or one line), allowing you to monitor the batteries and debug charging/discharging behaviour.

ppkbbat-info [options] <interval>

  <interval>  The update interval in seconds. Default is 1. Use 0 to run once.

Options:

  -r  Refresh the output instead of printing new instances.
  -l  Log mode that outputs single lines instead of a fancy table.
  -m  Add Megi's ppkb-i2c-charger-ctl info values.

If you need them, Megis values of course also require ppkb-i2c-charger-ctl (also available on DanctNIX as ppkb-tools or the AUR as pinephone-keyboard-git) being present in your $PATH, as well as ppkbbat-info being run as root for i2c access. These values can be useful especially when the sysfs values are wrong as it once was with the KB current while charging, or if your distro doesnt have the PPKB kernel drivers at all.

To print the results to the terminal and also to a log file, append | tee path/to/file.log to the command, e.g. ppkbbat-info -l | tee ~/ppkbbat-info.log. To only write to a log file and not output to the terminal, append > path/to/file.log. Of course you dont have to use -l to log it to a file, you can log the default table mode as well. You might not want to use -r when writing to a log file since that will also only write one instance to the file and then update that, so you wont really have a log. All options can be combined in any way.

Examples

[phalio@tatl:~]$ ppkbbat-info
| 21:56:34 | PP Battery  | KB Battery  |
|----------+-------------+-------------|
| Current  |  -0.101000A |  -0.649753A |
| C. Limit |   1.200000A |   0.500000A |
| KB>PP L. |   0.500000A |             |
| Voltage  |   4.131000V |   3.966110V |
| OCV      |   4.148100V |   4.016330V |
| Capacity |         98% |         94% |
| Status   |    Charging | Discharging |
| Online   |           1 |           1 |
[phalio@tatl:~]$ ppkbbat-info -l
21:58:15 ppcurrent='-0.121'    kbcurrent='-0.648261' pplimit='1.2' kblimit='0.5' kb2pplimit='0.5' ppvoltage='4.127'    kbvoltage='3.9637'   ppocv='4.147'    kbocv='4.01418'  ppcapacity='98' kbcapacity='94' ppstatus='Charging'     kbstatus='Discharging'  pponline='1' kbonline='1' 
21:58:17 ppcurrent='-0.195'    kbcurrent='-0.651245' pplimit='1.2' kblimit='0.5' kb2pplimit='0.5' ppvoltage='4.115'    kbvoltage='3.96343'  ppocv='4.147'    kbocv='4.01418'  ppcapacity='98' kbcapacity='94' ppstatus='Charging'     kbstatus='Discharging'  pponline='1' kbonline='1'

As you may notice, there are three current limit values. The PP limit, the KB limit and the PP -> KB limit. Usually when I or others refer to the PP limit, we are referring to the PP -> KB limit that defines what the phone takes via the pins on the back. The PP limit itself seems to have little influence on anything when using the keyboard, however it does seem to also apply. Mostly charging seemed to always be limited to 1.2A, but under heavy loads it seemed to go above that. Maybe that limit only applies to the phones battery and during high usage the phone itself can also take more from the keyboard, making the total go above 1.2A. I have no idea. I included it in the table just to be save but you should mostly just ignore it.

ppkbbat-setlimit

This allows you to conveniently set both input current limits manually. You can also use it to define a permanent set of limits instead of using dynamic management.

General Usage

ppkbbat-setlimit <pp-limit> <kb-limit>

Limits are in µA. Not specifying a limit will set the PP to 1500000 and the KB to 1500000 unless other defaults are specified in the config file. The default unchanged value for the PP is 500000 and for the KB 2300000.

Both limits have limited predefined sets of values that they accept, so you cant specify any arbitrary value, but that also means that you dont have to worry about setting it too high. It will always go to the nearest allowed value. If you frequently use a specific set of values, you can change ppkbbat-setlimits default values by editing the file /etc/ppkbbat-tools with sudo and adding the following lines:

setlimit_pp=1500000
setlimit_kb=1500000

Setting both to 1500000 works well for 5V 3A power supplies, as explained in Parallel Charging. For power supplies supplying less power you should choose a lower KB limit.

To increase the amount of power the phone gets from power supplies while charging, lower the keyboard limit and increase the phone limit. You can take a look at the code of ppkbbat-d to get an understanding of what value pairs are useful in what situations.

Unfortunately, decreasing the keyboard limit by x ampere while charging does not increase the amount the phone gets by x ampere. Instead, it seems to be pretty much exactly x/2 as the following table from my experiments shows. Decreasing the keyboards current limit by 0.8A increased the phones current by only 0.4A and so on.

KB limit PP current KB current
KB off -0.35A 0A
2.3A 0.1A 2.4A
1.5A 0.5A (+0.4) 1.6A (-0.8)
0.5A 1.2A (+0.7) 0.2A (-1.4)

The values of the table above were taken with my USB cable that does not pass through the full 3A but instead about 2.4A. The PP current values while charging would be higher with full 3A being supplied: 0.4A, 0.8A, 1.2A; 1.2A is the limit as described in the last paragraph of ppkbbat-info examples

The minimum for both limits is 0.5A, but while setting the PP limit to 0.5 will make it receive 0.5A, setting the KB limit to 0.5A will make it receive a lot less, like 0.2A in the table above. Setting the KB limit to 0.8A is the first that will actually make the KB receive that value, as can be seen in the parallel charging table.

Permanent Limit

Setting the limits is not permanent. It resets not only after each boot but also each time a power supply is removed. The best way to set a permanent limit is to have something automatically set it when a power supply presence state has changed. Systemd unfortunately cant control services based on the presence of a power supply according to the Arch Wiki but udev rules work. A less elegant way would be to just have cron, systemd or the like set it periodically, just like described here for ppkbbat-d. If you dont use automatic power management like ppkbbat-d or kbpwrd, you at least have to set the phones limit to something higher than the default 0.5A as that is not enough to charge it. Having at least this or some other permanent limits set up also helps in case something goes wrong with automatic limit managers. You could also just set a pair of limits that provides a minimum amount of functionality in all states, like 1500000 for the PP to have it charge properly and something lower for the KB like 1500000 that would make sure the PP receives at least some power when connected to a power supply.

This is how you set limits permanently using a udev rule. I used this for the first months of having the PPKB.

Edit /etc/udev/rules.d/powersave.rules with sudo and add the following lines (adjust the path to ppkbbat-setlimit to fit yours):

SUBSYSTEM=="power_supply", ATTR{online}=="0", RUN+="/home/phalio/git/ppkbbat-tools/ppkbbat-setlimit true"
SUBSYSTEM=="power_supply", ATTR{online}=="1", RUN+="/home/phalio/git/ppkbbat-tools/ppkbbat-setlimit false"

ppkbbat-notif

This simply pops up a GUI notification telling you the percentages of both batteries as well as the keyboard batterys OCV. This is most useful for GUIs/distros that dont show the keyboards percentage in the top info bar. For convenience, you could call it via a keyboard shortcut. The OCV is also very useful, especially for distros that use an older kernel version that doesnt support reporting the keyboard batterys capacity in percentage, and at least right now also in general since the percentage appears to be not that reliable and extremely fluctuating. Around 4.21V is 100%, 3V is 0%.7

[kaddi@hal:~]$ ppkbbat-notif

This creates a GUI notification that looks like this:

graph TD;
A(<b>Batteries</b><br>PP: 98%<br>KB: 94%, 4.016330V);

ppkbbat-toggle

This simply toggles keyboard battery -> phone charging on and off (not power supply -> phone), just like the physical button on the side of the keyboard, except that the keyboard still reports its values to the phone, so you dont lose the ability to see its percentage. Just like the button, this can be used to use the extra battery more like a power bank, as in charging the internal battery once its low. This is not the most optimal thing to do as it is a lossy process and requires manual control, however it it could be useful to circumvent issues with some distros/GUIs, for example if they refuse to suspend if the phone battery is in a charging state, which it always is with the keyboard battery supplying power. I used this for quite a while before I made ppkbbat-d, of course bound to a keyboard shortcut.

[alarm@tanz:~]$ sudo ppkbbat-toggle
PPKB battery output deactivated
[alarm@tanz:~]$ sudo ppkbbat-toggle
PPKB battery output activated

It uses Megis tools and therefore requires ppkb-i2c-charger-ctl (also available on the AUR as pinephone-keyboard-git) being present in your $PATH, as well as ppkbbat-toggle being run as root for i2c access. This is of course less optimal for keyboard shortcuts. To solve this, you can define ppkb-i2c-charger-ctl and ppkbbat-toggle to not require a password. Use sudo visudo (if you prefer a specific text editor, use e.g. sudo EDITOR=nano visudo and add the following line (replace the username and paths with yours):

phalio ALL=NOPASSWD: /home/phalio/git/pinephone-keyboard/ppkb-i2c-charger-ctl, /home/phalio/git/ppkbbat-tools/ppkbbat-toggle

Now they still require using sudo but you wont have to provide a password anymore.

Config File

You may create a config file at /etc/ppkbbat-tools to override certain predefined values. This is a list of all currently existing configurable variables with their default values. Read their related chapters in this readme for more details about when and how you should use them.

# ppkbbat-d parallel charging mode kb input current limit (lower this to make pp receive more)
parallel_kb_charge_limit=1500000
# ppkbbat-d sequential charging mode kb input current limit (lower this to make pp receive more)
sequential_kb_charge_limit=800000
# ppkbbat-d maximum current received by pp from kb
# can be set to 1500000 or 900000 for pp; to 1500000, 1250000, 1000000 or 850000 for ppp
# according to Megi, values above 1000000 could overheat the pins; so if you want to be safe, set it to 900000 for the pp or to 1000000 for the ppp
pp_current_max=1500000
# ppkbbat-setlimit limits when used with no arguments
# setlimit_pp can be set to 1500000, 900000 or 500000 for pp; to 1500000, 1250000, 1000000, 850000 or 450000 for ppp
# according to Megi, a setlimit_pp value above 1000000 could overheat the pins; so if you want to be safe, set it to 900000 for the pp or to 1000000 for the ppp
setlimit_pp=1500000
setlimit_kb=1500000

Troubleshooting

ppkbbat-d reporting a wrong state for one or a couple of seconds is normal and caused by seemingly random fluctuations of the values it observes to determine the current state and desired behaviour, especially during power state changes like plugging in a charging cable. Only consider longer periods of wrong states a bug. If you report a bug, it would be helpful if you can describe exactly what the circumstances were and possibly even provide a log of both ppkbbat-d and ppkbbat-info. You can log their outputs by using e.g. sudo ppkbbat-d | tee ~/ppkbbat-d.log and ppkbbat-info -l | tee ~/ppkbbat-info.log. If ppkbbat-d was running with systemd while the issue occurred, you can get the past log by using journalctl | grep "$HOSTNAME ppkbbat-d" > ~/ppkbbat-d.log. Some issues might be caused by ppkbbat-d, others seem to be outside of my/general control. Pray to the lord above (also known as Megi) that kernel PPKB power management will be done soon.

Below follows a condensed list of some bugs and undesired behaviours. If you encounter bugs not listed here or need any help, open an issue or contact me via any of these methods. Im always happy to help :)

Charging not working

See https://phal.io/tech/pinephone-keyboard#charging-not-working

Error#1, Error#2: Charging stops when plugged in

The symptoms of this bug are: A power supply is plugged into the KB and it either stops reporting any values (ppkbbat-d prints Error#1) or the KB status is Not charging (ppkbbat-d prints Error#2).

When I was using the old PPKB kernel driver + Manjaro + Plasma Mobile, while charging, both ppkbbat-d and kbpwrd caused the KB to stop accepting power, reporting the status Not charging. This seemingly bugged state will persist until the power supply is replugged and it happened at least once per charge, making either tool basically useless. There are also other similar bugs. The KB may stop reporting any values and either require re-plugging the charger or it might require using the button to shut it off and on again. Even using ppkbbat-d with a very slow update interval caused this bug happening just as often. The developer of kbpwrd apparently didnt experience any of this. Maybe its a per-device issue, maybe they use the PPP. I have no idea if its possible to fix this, but it must somehow be related to changing the values as it doesnt happen with no power management. Now using the new PPKB kernel driver + Arch + Sxmo, I believe Im experiencing the same/similar issues. Sometimes it works perfectly fine for an entire charge or discharge, sometimes it has one of these breaking bugs constantly. But it appears to happen less often. I also noticed that the PP itself apparently continues charging perfectly fine. If you experience any of this too often, you have these options:

  1. Convenient, good functionality: Instead of having ppkbbat-d running with a slow update interval, try having e.g. systemd or cron run it/kbpwrd once periodically as described here. Ive been using this for the past months with no issues and it is now the recommended setup.

  2. Inconvenient, good functionality: Run ppkbbat-d once manually whenever you need the limits to change, so at least to charge the PP, then to charge the KB (or once to charge both with the new parallel charging mode), then to discharge. I did that for a while with my lower-amp charging cable that required me to use limit management and it worked perfectly, albeit not the most conveniently. A keyboard shortcut might also make it more convenient.

  3. Convenient, minimal functionality: Dont use ppkbbat-d/kbpwrd and instead use a charger and USB cable that supply full 5V 3A so that the PP always receives at least 0.6A when charging and permanently increase the PP limit as described in Permanent Limit. Then just be careful not to have the PP consume too much power when its low and connected to a power supply and the KB still has charging priority, as to not have the PP go down to 0% before it has a chance to finally receive power.

Error#3: The Phone is not charging because the pins are not connecting

If the phone is discharging when it shouldnt be, i.e. ppkbbat-info reports the PP status as "Discharging" while it is below 90% (discharging above 90% is normal after becoming full) even though a power supply is plugged into the keyboard or the keyboard battery holds power and is not disabled, the issue likely is your pin connection. Many people, myself included, have experienced this issue. Read https://phal.io/tech/pinephone-keyboard#pogo-pin-connection for ways to fix this.

Automatic suspension is not working while the keyboard is attached and on

The keyboard battery itself charges the phone and therefore counts as a charger, even if no charger is plugged into any USB port. By default, most desktop environments like Plasma Mobile and Phosh (except for Sxmo which does not have this issue) dont suspend the device while a charger is connected. This will result in your phone never suspending while the keyboard battery holds power and was not shut off with the side button, wasting a lot of battery power. You have to enable automatic suspension for the plugged-in state as well. Like with regular computers, an option for this should be in your settings application.

Phosh

Open the Settings application and go to Power. Scroll down and tap Automatic Suspend. Activate the switch next to Plugged In and set the delay to the same value as the one above.

Plasma Mobile

Execute kcmshell5 powerdevilprofilesconfig. You can likely only scroll in it using the scroll bar on the side. In the On AC Power tab, activate Suspend session and set it to automatically sleep after the same time as its set to in the On Battery tab.

OG PP current is always positive

This is a known bug that has already been fixed in newer kernel versions. Ive never been so happy upon seeing a minus. ppkbbat-d has mechanisms that should make it work perfectly fine with the bugged current value with one exception: Recognising very high PP power demand during charging. Read the last paragraph of ppkbbat-d general usage for a workaround if your PP percentage goes down during high usage while charging and it is causing you problems.

Modifying the online value breaks reading/writing values

Setting the online value of the keyboard battery can make it shut off entirely like the physical button after a bit, making it unable to reconnect via software. It also has a chance to break reading the keyboard battery values via sysfs. In that case everything else will still work, but you cant read or modify the values anymore. Using ppkb-i2c-charger-ctl power-off to shut it off seems to work perfectly fine though. I used that many times early on and never had any issues with it breaking anything or with the keyboard shutting off entirely and requiring a physical button press to turn it on again.

Wrong keyboard current while charging

Occasionally while charging, the keyboard reports some very wrong negative current instead of the positive current it should report. Its not even just a wrong minus in front of the number, its completely wrong (ignore the obviously wrong KB capacity, that is common):

| 23:04:03 | PP Battery  | KB Battery  |
|----------+-------------+-------------|
| Current  |  -0.248000A |  -1.803380A |
| C. Limit |   1.200000A |   2.300000A |
| KB>PP L. |   0.500000A |             |
| Voltage  |   4.176000V |   4.222310V |
| OCV      |   4.217400V |   4.027070V |
| Capacity |        100% |        109% |
| Status   | Discharging |    Charging |
| Online   |           1 |           1 |

A power supply is connected and the keyboard limit is set to 2.3A, so it should receive +2.3A. Yet the sysfs value reports -1.8A. But when I also used ppkb-i2c-charger-ctl to check the current via i2c, it reported nearly the same number as the current limit, so everything is fine, only the sysfs value is bugged. As a result of this I added an option to ppkbbat-info that also displays the i2c values. This bug started happening as soon as I switched to Arch Sxmo with the new kernel driver in early May and it still happens now, mid June, albeit seemingly rarely. Now that Ive resumed my battery testing I believe this only happened once and I dont remember how I solved it. I believe it just fixed itself on its own after a while or something.

Further Reading