UBports Robot Logo UBports Forum
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Register
    • Login

    Guide to charge limiting your Fairphone 5

    Scheduled Pinned Locked Moved Fairphone 5
    15 Posts 3 Posters 720 Views 2 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
      Reply
      • Reply as topic
      Log in to reply
      This topic has been deleted. Only users with topic management privileges can see it.
      • C Offline
        ChromiumOS-Guy
        last edited by ChromiumOS-Guy

        I AM NOT RESPONSIBLE FOR ANY DAMAGE WHATSOEVER TO THE EXTENT LAW PERMITS.

        EDIT: there is a edge case that lets the battery continue charging it seems easy to fix so I'll do so tomorrow, for now just use slow chargers. (or make sure to unplug/replug the phone after it stops charging from there it will work fine)

        I'll start by saying I have no idea if this works for Focal but I haven't tried so it may work.
        also this is a proof of concept you may want to refine this by using a udev rule or whatever else this is just how I got it working the first time so its a known good.

        essentially there is something called user_fcc my take is that the fcc part is "full charge capacity" you can essentially tell the device that it actually has a smaller/bigger battery with this, I did tests on this however and either its using different units then charge_full (which is how you get the battery capacity) or its something else entirely, the point is that if set to 0 battery stops charging if set to big number like 10^6 battery charges again.

        so... heres my setup I did for the proof of concept.

        first start by running:

        sudo mount -o remount,rw /
        

        this is to remount read-only root as read/write.

        make a file and name it charge-control.sh and put it in the /usr/bin directory ( /usr/bin/charge-control.sh)
        change THRESHOLD to whatever percent you want to stop charging at, I put it on 80%

        #!/usr/bin/env bash
        
        # Path to capacity file (adjust if needed)
        CAP_FILE="/sys/class/power_supply/battery/capacity"
        UFCC_FILE="/sys/class/power_supply/battery/user_fcc"
        FULL_CAP_FILE="/sys/class/power_supply/battery/charge_full"
        
        # Threshold to compare against (integer 0-100)
        THRESHOLD=80
        
        # Commands to run
        ON_GE="echo 0 > ${UFCC_FILE}" #echo Battery >= threshold: do X here
        ON_LT="echo `cat ${FULL_CAP_FILE}` > ${UFCC_FILE}" #echo Battery < threshold: do Y here
        
        # Trim whitespace and ensure integer
        capacity=$(tr -d ' \t\n\r' < "$CAP_FILE")
        if ! [[ $capacity =~ ^[0-9]+$ ]]; then
          echo "Error: capacity value is not an integer: '$capacity'" >&2
          exit 3
        fi
        
        # Compare as integers
        if (( capacity >= THRESHOLD )); then
          eval "$ON_GE" && sleep 10 && "$ON_GE"
        else
          eval "$ON_LT"
        fi
        
        exit 0
        

        make sure you set executable permissions sudo chmod +x /usr/bin/charge-control.sh

        now we make a system service to start this script, make a file called charge-control.service at /etc/systemd/system (/etc/systemd/system/charge-control.service)
        and put this into it

        [Unit]
        Description=Battery charge control script
        
        [Service]
        Type=oneshot
        ExecStart=/usr/bin/charge_control.sh
        User=root
        

        now we create a timer to run this every minute because we want it to enable/disable battery charging without us running the service manually.
        so create a file named charge-control.timer in the same directory (/etc/systemd/system/charge-control.timer)
        and put this into it

        [Unit]
        Description=Run charge_control every 1 minute
        
        [Timer]
        OnBootSec=1min
        OnUnitActiveSec=1min
        Persistent=false
        
        [Install]
        WantedBy=timers.target
        

        then enable the timer by running these commands:

        sudo systemctl daemon-reload
        sudo systemctl enable --now charge_control.timer
        

        you may also check that it is working with these commands if you want

        sudo systemctl status charge_control.timer
        sudo systemctl list-timers --all | grep charge_control
        sudo journalctl -u charge_control.service
        

        hope this helps y'all manage you're battery health better.

        G 1 Reply Last reply Reply Quote 2
        • G Offline
          gpatel-fr @ChromiumOS-Guy
          last edited by

          @ChromiumOS-Guy

          thanks, may I ask why you are remounting the root fs r/w ? It's possible to create a systemd unit without it.

          C 1 Reply Last reply Reply Quote 0
          • C Offline
            ChromiumOS-Guy @gpatel-fr
            last edited by

            @gpatel-fr don't want the bash script in the user directory.
            this is because I mess with the user directory a lot, I didn't change it for the guide because this is a proof of concept and if I have a known good I will use it.

            I opened an Issue on this for indicator-upower fork, paulcarroty (the developer) is aware.
            and I am mostly counting on him to make this into something useful because he already has an app for it.

            G 1 Reply Last reply Reply Quote 1
            • G Offline
              gpatel-fr @ChromiumOS-Guy
              last edited by

              @ChromiumOS-Guy

              I have looked at the kernel sources, the 'user_fcc' is a limit value for the charging current (in micro amperes). If you set it at 0, well, current_now goes to 0 (logical) and the battery charging indicator disappears. If you set it to infinity, well, the result is unclear to me. It would seem logical that the maximum amount that can be tolerated by the battery is set if user_fcc is higher.
              Since the user_fcc value is aimed at setting an artificial low value when people are connecting a high powered charged (fast charger), I'd be wary of setting a very high value myself. It could work or maybe have unfortunate consequences. Setting it to 0 seems safe though.

              C 1 Reply Last reply Reply Quote 0
              • T Offline
                TheTrench
                last edited by

                Interesting, this general approach should work (at least extremely similar if not exactly the same) on most devices, as this is very close to how I manage charge level on Arch on my thinkpad laptop. The exact sysfs path is different, (it's got BAT0 in there somewhere, iirc), but the fact that it's THAT close between an AMD64 machine and the fairphone means it may be scriptable to search and locate the appropriate sysfs files on multiple devices.

                This sounds like something that could be integrated into the Lorimi settings UI pretty easily as well, i'll have to see about trying to write a patch for that, get my hands dirty etc.

                C 1 Reply Last reply Reply Quote 0
                • C Offline
                  ChromiumOS-Guy @gpatel-fr
                  last edited by ChromiumOS-Guy

                  @gpatel-fr thanks a lot! after classes I'll make it safe by reading the maximum first from wherever thats stored.

                  EDIT: at least on FP5 it seems to draw the same amount if I set it to a large value then if I restart (resets it) so FP5 should be safe currently, again will make it safe though I do not like to trust developers edge case fallbacks to not blow up my phone.

                  G 1 Reply Last reply Reply Quote 0
                  • C Offline
                    ChromiumOS-Guy @TheTrench
                    last edited by

                    @TheTrench said in Guide to charge limiting your Fairphone 5:

                    ld work (at least extremely similar if not exactly the same) on most devices, as this is very close to how I manage charge level on Arch on my thinkpad laptop. The exact sysfs path is different, (it's got BAT0 in the

                    i'd need to do some testing yes, but this could be implemented as a sort of universal way to charge limit UT devices, if its that wide-spread I might just add this feature in lomiri system settings under battery because this has actually come up during a devsync.

                    T 1 Reply Last reply Reply Quote 0
                    • T Offline
                      TheTrench @ChromiumOS-Guy
                      last edited by

                      @ChromiumOS-Guy I'm pretty sure it is, I think that it might even vary more by kernel version than device, meaning that you may want to switch on kernel version before device information, if you even need to check different locations. I would expect devices like the PinePhone to possibly be quite different since they don't use Hallium, iirc, but even thats a guess based on my experiences with the sysfs on various laptops.

                      I believe the kernel docs specify where to look generally, so 4.19 kernels should be (somewhat) consistent. (however most of my knowledge is based on the 6.1, 6.6, and 6.12 LTS kernels, take my recollections with a grain of salt)

                      That said, this is if you're accessing this sort of stuff through the sysfs, instead of using direct system calls, that may be rather different for all I know.

                      1 Reply Last reply Reply Quote 0
                      • T Offline
                        TheTrench
                        last edited by

                        oh, btw, theres an existing systemd service I use on Arch and Debian to manage this nowadays, might be worth examining if it already works for the most part and forking that if necessary.

                        1 Reply Last reply Reply Quote 1
                        • G Offline
                          gpatel-fr @ChromiumOS-Guy
                          last edited by

                          @ChromiumOS-Guy said in Guide to charge limiting your Fairphone 5:

                          on FP5 it seems to draw the same amount if I set it to a large value then if I restart

                          well, my main concern is what could happen for people following your advice with a more powerful (fast) charger.
                          If I understand correctly, the kernel limits to 6 amperes whatever, from kernel-fairphone-qcm6490/drivers/power/supply/qti_battery_charger.c;

                          #ifdef CHARGE_MODE_FCC_SUPPORT
                          #define SLOW_MODE_FCC 1000000 // 2A
                          #define NORMAL_MODE_FCC 6000000 // 6A
                          static int battery_psy_set_charge_current_by_chgmode(struct battery_chg_dev *bcdev, int val)
                          {
                          int rc = 0;
                          u32 fcc_ua = ((val == SLOW_MODE_FCC) ? SLOW_MODE_FCC : NORMAL_MODE_FCC);
                          rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_BATTERY], BATT_CHGMODE_FCC, fcc_ua);

                          I don't know if the FP5 battery can support 6 amps without problems.

                          If I would use your system, I'd try to keep safe and set user_fcc to 1000000 (notice how the comment seems wrong, how can 1000000 mean 2 amp and 6000000 6 amp ?)

                          Re: different kernels, well, if I understand correctly, if the battery driver supports it, you'll find the appropriate values in the /sys/class/power_supply/ that are referred everywhere on the web: charge_control_start_threshold and charge_control_end_threshold, there should be no need for a script that will wake up the Cpu every minute (hardly a good thing to save power).

                          It don't concern FP5 (although the kernel is recent enough... I wonder if the kernel in Android 14 has a more recent driver that supports this feature or if there is some script to support it, but what's sure is that control up to 80% charge is supported on Android and FP5).

                          T 1 Reply Last reply Reply Quote 0
                          • T Offline
                            TheTrench @gpatel-fr
                            last edited by

                            @gpatel-fr Is that code specifically referring to input from the wall, or output to the battery amperage? My understanding is that at 30W charging, at a nominal voltage of 4.2 V, we're already looking at over 7A.

                            And 30W is just fully supported by FP natively. Also note that the input voltage at 30W is probably 9V or 12V, bringing the actual amperage down on the input side. Why, I have a 120V USB PD charger that doesn't go over 5A because it just ramps up the voltage.

                            I suspect that the "6A" unit in the kernel may be a pseudo unit that the BMC takes, pretending that the actual output voltage to the battery is always 5V, meaning it's actually describing wattage, specifically the natively supported 30W charging.

                            G 1 Reply Last reply Reply Quote 0
                            • G Offline
                              gpatel-fr @TheTrench
                              last edited by

                              @TheTrench

                              that's all very well and FP5 is probably safe, however with things that can go as high as 500 degrees Celsius when angry, I'd prefer 'surely' over 'probably' myself. I have tried to get the full spec of the battery from https://www.kayobattery.com, given that all I have from Fairphone is:

                              Capacity : 4200 mAh
                              Nominal Voltage: 3.87 V
                              Cut off Voltage: 3.0 V
                              Charging Voltage: 4.45 V
                              Dimensions: 77.4 x 60.45 x 6.2 mm
                              DC Internal Impedance < 130 mΩ
                              Standard discharge: Continuous 0.2 to 3.0 V
                              Operational Charging Temperature Range: 0-60 ℃
                              Operational Discharge Temperature Range: -20 - 60 ℃
                              Recommend full charge & discharge cycle once every 3-6
                              months.
                              

                              but the site is a joke. Note that according to the Fairphone specs, charging is supposed to occur at 4.45V, not 5V. The 'full charge and discharge cycle once every 3-6 months' is baffling for a lithium-ion battery.

                              There is a second point that concerns me, if you don't know how adventurous users can be, I know and I can already see a post saying: << I have taken the code on this topic [this one] and applied on my phone [another model, not a FP5 or even not a Fairphone at all] and now bad things have happened.>>

                              T 1 Reply Last reply Reply Quote 0
                              • T Offline
                                TheTrench @gpatel-fr
                                last edited by

                                @gpatel-fr yeah, that site is absurd.

                                All I'm saying is that a mere 30W at 4.2V puts us far over the 6A point anyway, and since the battery is what puts a specific amperage load on the BMC, the only "lever" we can even have in the first place is actually the voltage being used to charge the battery.

                                While we may be able to control the battery charge rate and therefore amperage that its pulling, the BMC can only actually do so by changing its output voltage.

                                Basically, while we might be putting an amperage in somewhere in the sysfs, even if that is somehow being sent to the BMC, at some point that has to be getting calculated into a voltage to achieve the desired charge rate, and no matter what, when android is charging the battery, we already know its exceeding the 6A value in that code when the battery is low.

                                Something doesn't add (or rather multiply) up with the nunbers, that's all I'm saying.

                                G 1 Reply Last reply Reply Quote 0
                                • G Offline
                                  gpatel-fr @TheTrench
                                  last edited by

                                  @TheTrench said in Guide to charge limiting your Fairphone 5:

                                  a mere 30W at 4.2V puts us far over the 6A point anyway

                                  the actual voltage limit according to the official spec (that one from Fairphone since we don't have anything more specific) is 4.5 V, so loading at 6A should get us 27W instead of the advertised 30.

                                  I'd say that from a business having successfully sold a phone with a screen said to be 6.46" hence 16.4cm while the phone itself (screen and border) measures 16cm it would not be particularly surprising. Unless the official charger from Fairphone, as advertised, loads the battery with a voltage exceeding Fairphone specs. I'm certainly not qualified to appreciate the risks.

                                  C 1 Reply Last reply Reply Quote 0
                                  • C Offline
                                    ChromiumOS-Guy @gpatel-fr
                                    last edited by

                                    @gpatel-fr yeah, I have things to do but in the weekend I'll refine this more the only reason I'm not taking this down is because I'm doing it on mt FP5 and it has not exploded yet... so I may be good until the weekend.

                                    1 Reply Last reply Reply Quote 0
                                    • First post
                                      Last post