Open digitalcircuit opened 2 years ago
Hi.
It is possible to limit target battery voltage(with charger settings) and make another set of params for gauge(or leave gauge with current params). But in my opinion it's not worth it, but you are welcome to implement it. Shouldn't be very difficult.
Thank you for your feedback!
I understand it not being a priority. Knowing you're not opposed to accepting a pull request of sufficient quality, this might be a good opportunity for me to try to learn a manageable subset of every layer in the Flipper firmware (UI, abstractions, hardware control, etc).
Meanwhile, if anyone else sees this open issue, feel free to experiment - it likely will be a long while before I have the time to dig into this.
I've been pondering how to implement this in a way that reduces support requests from folks turning on the feature and forgetting about it.
So far, I've drafted the following change to the battery icon design when charge limiting is enabled:
In the above example, the charge is limited to 80% (i.e. 20% of the battery is "grayed out"). This would be drawn inside power_draw_battery_callback()
alongside the call to canvas_draw_box()
whenever charge limiting is turned on using something similar to view_display_test_draw_callback_check()
.
I'll dig into the code side when I have time to set up the build environment and tinker - I'm expecting to change the charging profile (translating the percentage limit into a reduced battery voltage limit), but not change the charge gauge.
There's two reasonable methods I've managed to come up with to implement battery charge limiting:
Set charge voltage for bq25896
and adjust charge voltage in bq27220
to know when charging is done
Pause charging in Flipper firmware upon reaching limit, adjust code to detect when charge is complete
Flipper developer team - what would you prefer?
I'm leaning towards option #2 given the complexity of #1 involving coordinating the charge limit via both the charging chip and the battery gauge chip, but I'm happy to try that option if preferred. I'm open to other methods, too.
It's quite possible I overlooked pros and cons in either solution!
The Linux kernel battery charge limit interface operates on start/stop percentages via charge_control_start_threshold
and charge_control_end_threshold
(the exact hardware implementation isn't specified).
System76 have implemented battery charge limiting in their open embedded controller firmware for their Linux laptops using battery charge percentage rather than directly setting the battery charge voltage.
This most closely matches option #2 - software/firmware charge limiting instead of hardware (IC) limiting.
NOTE: This does not apply for method #2, where the Flipper Zero firmware intervenes to limit charging below 100%.
Couple things:
In my opinion battery life prolongation in that way is not worth it.
Firstly, thank you for taking the time to read and respond! I appreciate all of you are very busy and the work y'all have done is awesome!
I've experimented further, successfully tested changing the charger configuration, and tried to better explain myself. I expected to be doing the work to implement this, I just want to make sure I'm pursuing the right path.
I agree with you for folks who are carrying their Flipper with them everywhere (akin to a mobile phone), and/or not paying as close attention to the battery level. The bigger concern for them is discharging the battery too far.
The current behavior is a good default!
In my case, though, I don't travel much, so I'd find it easier to leave the Flipper connected to USB power (via a charger or my computer for the serial console) and just disconnect when I go somewhere, ensuring I never have to think about keeping the battery from discharging too much.
However, with the current battery charging behavior, keeping the Flipper plugged in would try to continually keep the battery at near full charge - 4108mV to 4208mV (based on bq25896
's default strict 100mV recharge threshold with VRECHG
= 0). This does not seem to follow the typical usage pattern most cells are optimized for.
6+ years is a long time, but I tend to use electronic devices longer than average (e.g. I daily-drive a 2014 laptop where the battery has degraded to "70% health", which actually means "about 45 minutes usage at low brightness with little warning before hard shutdown"). If the Flipper battery was easily replaceable, I wouldn't be as concerned, but from watching a teardown video the battery appears to be buried in the middle of the device, with delicate components, plastic clips, tiny screws, and a bit of adhesive in the way.
Can you share the battery manufacturer and model so I may look up the cell datasheet? I couldn't find the details in the Flipper hardware documentation.
(I recognize you might not be allowed to share the actual datasheet, but I might be able to find it online.)
I ask since the datasheets for some well-regarded high capacity lithium-ion cells (see "18650 The good cells") make note of reducing charging voltage for use cases where staying charged is more common:
"As shipped from factory" storage charge is too low for daily use, but even a 3.8v charge - the lowest the bq25896
will allow - seems to provide over a full day of Flipper usage before it even reaches factory voltage.
Higher-end round cell chargers do have a "storage" mode that charges to about 3.8v - see "Store" near bottom.
With this in mind, and considering Table 4 on the more general Battery University page, it seems that limiting the charge to 4.00v or so if one frequently connects (or stays connected) to a charger could meaningfully increase the battery longevity.
Other device manufacturers have implemented methods to try to adapt to folks who tend to leave things plugged in:
Dell implemented an adaptive charging algorithm that tracks whether one tends to keep a Dell laptop plugged in versus unplugging and discharging often, and it will reduce the maximum charge if it's normally plugged in: Reddit link with linked photos, Dell support forums.
Apple implemented an automatic 80% charge limit that keeps their devices from charging to 100% overnight until right before when it'd normally be unplugged. Google implemented a less intelligent version that operates by scheduled alarms - see "Charge steadily overnight". Both Apple and Google also automatically detect when their devices are plugged in for a few days and limit the maximum charge.
An automatically adapting charging algorithm might be complicated to implement in the Flipper Zero firmware, but a simple way to express "I frequently leave my Flipper connected to the charger/USB so it's kept topped up" versus "I primarily use my Flipper on the go and frequently drain the battery" might be straightforward enough.
Your preference makes sense, and I'll focus on that.
In hindsight, I was overcomplicating matters. If combined with a generally applicable pull request to also check the charging IC if it says charging is done, it's very straightforward for me to hard-code a charging voltage limit:
@@ -56,6 +56,12 @@ void bq25896_init(FuriHalI2cBusHandle* handle) {
furi_hal_i2c_write_reg_8(
handle, BQ25896_ADDRESS, 0x02, *(uint8_t*)&bq25896_regs.r02, BQ25896_I2C_TIMEOUT);
+ // FIXME: Hard-coded hack to test, move this to an actual function later
+ // WARNING: Do NOT go above 0x17 (23 decimal) - that will overcharge the battery!
+ bq25896_regs.r06.VREG = 0x00; // Charge Voltage Limit: 3840 mV (offset: +3840mV)
+ furi_hal_i2c_write_reg_8(
+ handle, BQ25896_ADDRESS, 0x06, *(uint8_t*)&bq25896_regs.r06, BQ25896_I2C_TIMEOUT);
+
bq25896_regs.r07.WATCHDOG = WatchdogDisable;
furi_hal_i2c_write_reg_8(
handle, BQ25896_ADDRESS, 0x07, *(uint8_t*)&bq25896_regs.r07, BQ25896_I2C_TIMEOUT);
(Without the aforementioned pull request, this method of implementing the charging limit works, but the charging LED stays red instead of turning green to signal that the bq25896
chip has stopped charging.)
The question then becomes if enough folks prefer to keep their Flippers on a charger/controlled via USB for integrating this into the Flipper firmware.
I'm happy to put in the effort to add a setting, UI to control it, and some "charge voltage is limited" graphical interface indicator to minimize support hassle, plus going back-and-forth to ensure the code meets all standards.
However, I'd understand if you/Flipper team are not open to accepting any code that implements this - all code does have a maintenance burden.
It may also be reasonable to automatically disable the charging limit if the battery level ever reaches shutdown levels (power_check_low_battery()
in applications/power/power_service/power.c
). That way, if someone enables this feature then forgets to stay on top of charging, it'll revert back to a full charge the next time they plug in.
I'm taking another look at this since, after recent firmware changes, charge limiting is now the only reason I'm building my own firmware instead of using the official builds.
Following @skotopes 's advice, I've focused on adjusting the bq25896
's charging voltage. As such, it's not possible (nor desired) to match this up to specific battery charge percentages in the UI, so I've reworked my design drafts.
I'm open to feedback or suggestions.
I'll look at incrementally implementing this as a new pull request built on top of my pull request to also check the charging IC if it says charging is done.
Desktop
/battery icon when charging is limitedIf the battery charge voltage is modified, the charged portion of the battery bar will have a cross-hatch pattern in the middle.
This will indicate to anyone trying to provide support that charge limiting is activated (if they know), or something about the battery is modified (if they don't know).
NOTE: This was changed from the initial design as it's not possible to reliably determine what percentage of the battery is unavailable when limiting via reducing battery charging voltage.
Power
menu adds configurationEDIT 2022-8-18: This has been replaced with a new scene with explanatory text and graphics. Please see the following comment with design 2.1.
Battery Info
Reboot
Power OFF
Limit charging: < OFF >
In Settings
→ Power
, there will be a new menu option titled Limit charging
with the following settings:
OFF
4.2v
4.1v
4.0v
3.9v
3.8v
NOTE: Alternatively, this could be made into a new scene with explanatory text, graphics, and a warning to not let the battery fully discharge.
If the battery ever reaches a critical point (0% capacity remaining), Limit charging
will be automatically reset to OFF
so the next charge will go up to 4.2 volts as usual.
This helps ensure that if someone enables this feature then neglects to keep their Flipper charged, it won't risk damaging the battery further.
If someone enables this feature, it is expected that they will be charging their Flipper frequently.
Battery Info
reminds of charge limit when charged
Charged!
Limited to 3.8v
If charge limiting is enabled, the Battery Info
screen will add an additional line saying Limited to [charge voltage]
when charging is complete to remind the user that they enabled charge limiting.
This helps avoid confusion when the battery shows as charged despite not being 100% full.
I have implemented all the non-configuration graphical changes in my ft-batt-charge-config
branch on my flipperzero-firmware
fork.
As the settings aren't yet implemented, it is currently hard-coded to 3.888v
for testing purposes.
I'll try to look into creating a power settings configuration soon (it's more complicated than I initially expected). I'll also want to add the automatic disabling of charge limiting if the battery level ever drops to critical.
Here's some live screenshots:
Desktop
/battery icon when charging is limitedThe cross-hatch pattern only applies when the battery charging voltage is modified.
Battery Info
reminds of charge limit when charged
Charged!
Limited to
3.8V
If charge limiting is enabled, the Battery Info
screen adds an additional line saying Limited to [charge voltage]
when charging is complete to remind the user that they enabled charge limiting.
After further thought, this is a confusing setting to expose as just Limit charging: < voltage >
. I've drafted up a new configuration screen that better explains what this setting does and how to set it.
NOTE₁: I have not yet implemented this; the ft-batt-charge-config
branch on my fork still only implements the non-configuration UI.
Modifying the Power application to implement settings involves significant changes to the application (e.g. using a message queue, mimicking the Notification app which manages LED/LCD brightness), so I want to check if I'm going the right direction first.
I welcome any feedback on the preferred way to modify the Power app to support loading/saving /int/.power.settings
, especially if it differs from copying the Notification app implementation.
Limit battery charging: [slider with 4 selectable values]
3.9V
4.0V
4.1V
4.2V
[icon of an AC power cord] « — » [icon of a battery] Always on charger — Full charge, portable use
NOTE₂: The Limit battery charging:
text will be bold, like the text for Primary favorite app:
in the Desktop settings UI. I don't currently have a good computer approximation of the bold pixel font used by Flipper.
The Left
/Right
arrows will change the charging voltage. OK
will save changes and exit this menu, and Back
will exit this menu without saving changes (similar to the Primary favorite app
setting).
The AC power cord icon will be added as a new asset. The battery icon is copied from the Battery Info screen. This scene/view will involve custom canvas drawing calls, similar to the Battery Info
screen.
I removed the 3.8V
setting, so the lowest configurable charge level of 3.9V
ensures that half (40-60%) of the lithium-ion battery capacity will be available at minimum while still providing an estimated 6-8× increase in battery charge cycles.
Another contributor has already refactored the Power application to support saving/loading settings. If merged, their work would simplify my task as I'd just need to focus on the new UI and the new setting.
However, if the Flipper team decides that the minimum 4Kb internal storage cost to add two settings (that pull request plus my future pull request) is too expensive for the Flipper's limited internal storage, then this feature might not be practical for me to add. Without settings, it would only be a temporary change (being reset to 4.2v on every reboot).
I'll continue to plan and implement, but I might wait for the Flipper developer team to decide on whether they'll allow the storage cost of adding the /int/.power.settings
file before I get too far along.
Awesome work! Can you also add easy to trigger one-off option to charge Flipper fully? The use case would be pretty much same as yours, but also to easily prepare for a field trip with more battery time.
@D0han I think a one-off option to fully charge the Flipper while keeping charge limiting enabled is a good idea.
However, to help keep this task manageable, I don't think I'll be implementing that in my initial pull request.
When I've implemented the current design, it will be possible to manually set the charge limit to 4.2v to fully charge, then when you head off on the trip, set the limit back down when unplugging - no need to wait for the Flipper to discharge. Hopefully, the lack of the crosshatch pattern on the desktop battery capacity bar will help with remembering that the charge limit is not enabled.
For anyone following along, I've gotten everything except for the actual configuration UI implemented in PR #2063, "power: Add API to get/set battery charging voltage".
EDIT: the API pull request has been merged! Now the Power settings UI needs implemented.
If you build that pull request, you can then add and build your own custom tiny Flipper application or service (as described in the verification steps) to set the battery charging voltage limit. I'll add the integrated settings UI once PR #1647, "Automatic shutdown on idle" is merged, providing the settings loading/saving backend.
If you have the know-how to build the firmware yourself, help with testing would be appreciated.
@skorokithakis Since you asked, here's the details on charge voltage limiting:
Right now, it requires building either a service integrated to the system (my temporary approach), which will work on reboot but means maintaining your own builds, or you can write a standalone third-party Flipper App to call the API for you (not tested).
My changes for system-level integration are here, setting a quite reduced 3.9v (always plugged in): https://github.com/flipperdevices/flipperzero-firmware/compare/dev...digitalcircuit:flipperzero-firmware:ft-batt-charge-config
There's some old screenshots in the initial API PR: FuriHal, Power, UnitTests: battery charging voltage limit API (#2063)
Ah, I was hoping there would be a console command, but I will try to write an app, thanks!
Is your feature request related to a problem? Please describe. From what I understand, lithium batteries wear out over time, and using and storing lithium batteries at full charge (e.g. 4.2v) can result in the battery wearing out faster.
Since the Flipper Zero's battery is not easily replaceable (requires disassembly), I'd like to take steps to ensure it degrades as little as possible when I don't need the full battery capacity.
Describe the solution you'd like Provide an option in
Settings
→Power
to reduce the maximum allowed battery charge for sake of battery longevity.For example,
Charge limit: 100%
, adjustable down to60%
or so in 10% decrements.Alternatively, just provide a few charging profiles (
Full Charge
,Balanced
,Max Lifespan
) corresponding to 100%, 80%, and 60% or so (see System76's UI in additional context).Implementation details: Flipper's firmware currently can pause charging with
furi_hal_power_suppress_charge_enter()
andfuri_hal_power_suppress_charge_exit()
.Alternatively, it appears there may be a way to adjust the bq25896 regulator's voltage limit via
VREG
inREG06
. If feasible, lowering that may avoid requiring having the Flipper firmware actively toggle suppressing the charging circuitry.Either way, the Desktop UI's battery indicator should probably show that the battery charge is limited to avoid potentially confusing folks.
Describe alternatives you've considered
Additional context There's ongoing research around battery charge thresholds and various devices and software exists to control this on other platforms. It'd be nice if Flipper could integrate this without needing a third-party workaround.