5 5
zador.blood.stained

[WiP] axp209 mainline sysfs interface

Recommended Posts

Since my battery arrived I had the time to try out your latest changes on a Lime2. I tested/monitored a few different situations:

 
 
No battery, 5V through DC-IN:

battery/amperage: 0
battery/capacity: 127
battery/charge: 0
battery/charging: 0
battery/connected: 0
battery/power: 0
battery/ts_voltage: 800000
battery/voltage: 0
charger/amperage: 0
charger/cell_activation: 0
charger/charging: 0
charger/low_power: 0

Obviously wrong values that should be ignored. The only value that matters: "battery/connected: 0"
 
 
5V provided through DC-IN, battery starting to charge:

battery/amperage: 0
battery/capacity: 20
battery/charge: 0
battery/charging: 1
battery/connected: 1
battery/power: 0
battery/ts_voltage: 0
battery/voltage: 3979800
charger/amperage: 1341500
charger/cell_activation: 0
charger/charging: 1
charger/low_power: 0

battery/amperage: 0
battery/capacity: 21
battery/charge: 0
battery/charging: 1
battery/connected: 1
battery/power: 0
battery/ts_voltage: 0
battery/voltage: 3982000
charger/amperage: 1341500
charger/cell_activation: 0
charger/charging: 1
charger/low_power: 0

battery/amperage: 0
battery/capacity: 44
battery/charge: 0
battery/charging: 1
battery/connected: 1
battery/power: 0
battery/ts_voltage: 0
battery/voltage: 4050200
charger/amperage: 1271500
charger/cell_activation: 0
charger/charging: 1
charger/low_power: 0

battery/amperage: 0
battery/capacity: 99
battery/charge: 0
battery/charging: 1
battery/connected: 1
battery/power: 0
battery/ts_voltage: 0
battery/voltage: 4204200
charger/amperage: 167500
charger/cell_activation: 0
charger/charging: 1
charger/low_power: 0

battery/amperage: 0
battery/capacity: 100
battery/charge: 0
battery/charging: 1
battery/connected: 1
battery/power: 0
battery/ts_voltage: 0
battery/voltage: 4204200
charger/amperage: 164500
charger/cell_activation: 0
charger/charging: 1
charger/low_power: 0

In this mode AXP209 gets quite hot (up to +25°C when charging with high current rating compared to normal idle mode without charging a battery) and internal recorded 'total consumption' in my setup exceeded 6W when starting to charge the battery.
 
Total consumption is the read-out of DC-IN (V*A). Charging consumption is 'charger/amperage' multiplied with voltage from DC-IN -> ac/voltage (not battery/voltage !). Therefore the board's consumption can be calculated by subtracting the 'charge consumption' from 'total consumption'.
 
Fully charged:

battery/amperage: 0
battery/capacity: 100
battery/charge: 0
battery/charging: 0
battery/connected: 1
battery/power: 0
battery/ts_voltage: 0
battery/voltage: 4187700
charger/amperage: 0
charger/cell_activation: 0
charger/charging: 0
charger/low_power: 0

In this mode battery voltage doesn't matter that much. Consumption solely relies on the values that can be read out from DC-IN. But now 'battery/voltage' can be read out.
 
Disconnecting DC-IN and running on battery:

battery/amperage: 347000
battery/capacity: 100
battery/charge: 0
battery/charging: 0
battery/connected: 1
battery/power: 2096
battery/ts_voltage: 0
battery/voltage: 4147000
charger/amperage: 0
charger/cell_activation: 0
charger/charging: 0
charger/low_power: 0

Now 'battery/amperage' isn't 0 any more and board's consumption can be measured using battery/amperage * battery/voltage
 
Conclusion (with mainline it _looks_ simple):
  • if "battery/connected = 1" then a battery is present (and also the need to choose a different template and start a daemon approach to calculate total and charging consumption based on the variables below):
  • if "battery/charging = 1" then state is "charging" (board consumption is total - charging -- see above)
  • if "battery/charging = 0" and "battery/amperage = 0" then state is "charged" (board consumption calculated from battery/amperage * battery/voltage)
  • if "battery/amperage > 0" then state is "discharging" (board consumption is battery/amperage * battery/voltage)
TODO: 
  • Adjust RPi-Monitor templates to reflect the aforementioned stuff and to check whether there's more to consider by trying out charging/discharing with active monitoring.
  • Try this out with Lamobo R1 where 5V DC-IN is fed through battery connector.
  • Use powermeter to verify internal measurements
  • Check whether external components (SATA disk, USB peripherals) make a difference when reading out AXP209 internals
Unanswered questions:
  • Does logic/read-outs differ when power is provided through USB OTG instead of DC-IN?
  • How does the older driver for kernel 3.4 behaves?
  • In case with 3.4 drivers behaviour is different... better fix the driver or the code to detect 3.4 vs. mainline?
  • How does 'charger/low_power' behaves (and should we take care of)?
Edited by wildcat_paris
just added [spoiler] for better looking, easier reading

Share this post


Link to post
Share on other sites

Now 'battery/amperage' isn't 0 any more and board's consumption can be measured using battery/amperage * battery/voltage

 

Datasheet says that battery consumption is measured internally (battery/power, you are probably not using the latest version where I fixed multiplier for this value) Edit: Or I didn't fix it properly. Happens sometimes...

 

 

In this mode AXP209 gets quite hot (up to +25°C when charging with high current rating compared to normal idle mode without charging a battery) and internal recorded 'total consumption' in my setup exceeded 6W when starting to charge the battery.

Charge current can be controlled, but again, axp power driver isn't mainlined, so if _really_ needed, it can be exposed via sysfs by me.

 

When running on battery a connected SATA disk adds to the whole consumption (to be more precise: battery/amperage) on Lime2

Yes, boost converter input is connected to "ipsout" output here, so all current is going through axp209

Share this post


Link to post
Share on other sites

Unanswered questions:

  • Does logic/read-outs differ when power is provided through USB OTG instead of DC-IN?
  • How does the older driver for kernel 3.4 behaves?
  • In case with 3.4 drivers behaviour is different... better fix the driver or the code to detect 3.4 vs. mainline?
  • How does 'charger/low_power' behaves (and should we take care of)?

1. Is should (obviously vbus readings must be used instead of ac, and "used" properties show what sources axp is currently using)

2. To be tested

3. Detecting is easier, after I fixed battery status (connected) readings, I looked at 3.4 code. It can be fixed obviously, but it would look like poking a big pile of spaghetti with a fork and hoping nothing bad happens.

4. Datasheet says

Indicates the charging current is less than the expected current
0:The actual charge current equal to the desired current;
1:The actual charge current is less than the desired current
Once the battery voltage exceeds 3.0V, the charger enters constant current mode. If the charge current
is below 65% of the preset value, the system will send IRQ17 to indicate that “drive ability of external
power is insufficientâ€, as a result, the charge current is lower than the preset value, which may lead to
longer charge time, so stronger power is preferred, or power-consuming functions should be disabled to
shorten the charge time.

I guess this is mainly for charging while powered from OTG/VBUS, but it may detect weak AC IN supply too.

 

Edit: It's relatively easy to test with a regulated power supply.

Share this post


Link to post
Share on other sites

FYI: the first discharge cycle just finished at 16:44:

 

I connected the battery yesterday at 18:22, then it has been charged until 21:48 and at 21:53 I removed the DC-IN plug. This little beast provides power for ~19h being idle (with EVO840 SSD connected):

 

 

 

Bildschirmfoto%202016-01-23%20um%2017.51

 

Bildschirmfoto%202016-01-23%20um%2015.29

 

 

 

And here the read-outs. The last one before the PMU switched the Lime2 off:

 

 

battery/amperage: 450500
battery/capacity: 1
battery/charge: 0
battery/charging: 0
battery/connected: 1
battery/power: 2105
battery/ts_voltage: 0
battery/voltage: 2992000
charger/amperage: 0
charger/cell_activation: 0
charger/charging: 0
charger/low_power: 0 

 

 

 

And then it started again this way:

 

 

 

battery/amperage: 0
battery/capacity: 1
battery/charge: 559
battery/charging: 1
battery/connected: 1
battery/power: 0
battery/ts_voltage: 0
battery/voltage: 3529900
charger/amperage: 1341000
charger/cell_activation: 0
charger/charging: 1
charger/low_power: 0 

 

 

Share this post


Link to post
Share on other sites

Hmm... I reset coloumb counters, did a while discharge/charge cycle and now it looks like this:

 

battery_percentage_Lime2.png

 

What am I'm doing wrong (since if this is really the percentage curve to be expected it's not worth monitoring/displaying it, right?)

 

I will later (when discharge is done) check again if I use your latest version but am pretty sure I checked a few days ago.

 

 

EDIT: I was not using the latest version of your patches :(

MD5 (/Users/tk/Downloads/linux-image-dev-sunxi_4.83_armhf-2.deb) = 16d1b99ff801a226cbb099325973604d
MD5 (/Users/tk/Downloads/linux-image-dev-sunxi_4.83_armhf.deb) = 8ecb60f5304854505bfd4182f16c255d

Will replace now.
 

Share this post


Link to post
Share on other sites

I didn't touch percentage calculations in a while, especially since it reports directly from a register (we are talking about battery/capacity, right?). Last thing I modified - fixed units for battery/power, it should report consumption directly without having to multiply voltage and amperage.

 

Percentage curve is expected to be linear if system power consumption is constant, but I guess it's calculated based on current/min/max voltage, so it looks OK compared to googled images for "li-ion discharge curve".

 

It may be not worth to display it as a graph, but it still should be displayed as a numerical value and it's still good for implementing any kind of "safe shutdown" logic.

 

Also, I finally managed to connect a battery to my cubietruck, so I'll try to do my own experiments with monitoring.

 

 

Didn't manage to buy 18650 battery holder, so had to improvise... Looks scary, but works

cubie%20with%20battery.jpg

 

 

Share this post


Link to post
Share on other sites

I didn't touch percentage calculations in a while, especially since it reports directly from a register (we are talking about battery/capacity, right?)

 

Yes, I use this since it should be a percentage value (range between 0 and 100). I'm going to take a look on battery/charge also. Maybe this contains some useful values.

 

If battery/capacity is really just a "li-ion discharge curve" then we might be able to translate it by a formula into something user friendlyß From a technical point of view this type of curve is ok (showing already only 15% capacity after the half discharg time. But from an end user perspective at this time 50% should be displayed.

 

I'm still in the process of getting a clue what of these values is useful and what not. But got a bit stuck due too overload with normal work :(

Share this post


Link to post
Share on other sites

If battery/capacity is really just a "li-ion discharge curve" then we might be able to translate it by a formula into something user friendlyß From a technical point of view this type of curve is ok (showing already only 15% capacity after the half discharg time. But from an end user perspective at this time 50% should be displayed.

It's easy to test - just plot battery/voltage and battery/capacity on one chart, when you have some free time

Share this post


Link to post
Share on other sites

Ok, another try:

 

 

 

Bildschirmfoto%202016-01-28%20um%2010.32

 

 

 

BTW: I had a look at battery/power too (but not based on your latest fixes). Will comment on that after the next reboot. And I must also have a look how the 3.4 sysfs interface behaves since I wanted to use a single set of templates for both legacy/vanilla.

Share this post


Link to post
Share on other sites

Regarding battery/charge I simply added it right now to the template (statistics only) using the following:

 

 

 

dynamic.21.name=battery_charge
dynamic.21.source=/sys/power/axp_pmu/battery/charge
dynamic.21.regexp=(.*)
dynamic.21.postprocess=sprintf("%.2f", $1/1000)
dynamic.21.rrd=GAUGE

web.statistics.1.content.4.graph.6=battery_charge

web.statistics.1.content.4.ds_graph_options.battery_charge.label=Charge (WTF)

web.statistics.1.content.4.ds_graph_options.battery_charge.yaxis=2 

 

 

 

Battery already recharged. Let's see how it behaves when I start the next discharge/charge cycle. The last charge cycle looks like this:

 

Bildschirmfoto%202016-01-29%20um%2007.51

Share this post


Link to post
Share on other sites
web.statistics.1.content.4.ds_graph_options.battery_charge.label=Charge (WTF)

Charge (mAh) I suppose (after dividing it by 1000)?  :)

 

 

 

Attributes/properties detailed
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

~ ~ ~ ~ ~ ~ ~  Charge/Energy/Capacity - how to not confuse  ~ ~ ~ ~ ~ ~ ~
~                                                                       ~
~ Because both "charge" (µAh) and "energy" (µWh) represents "capacity"  ~
~ of battery, this class distinguish these terms. Don't mix them!       ~
~                                                                       ~
~ CHARGE_* attributes represents capacity in µAh only.                  ~
~ ENERGY_* attributes represents capacity in µWh only.                  ~
~ CAPACITY attribute represents capacity in *percents*, from 0 to 100.  ~
~                                                                       ~
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ 

 

 

 

Edit: Also

CHARGE_COUNTER - the current charge counter (in µAh).  This could easily
be negative; there is no empty or full value.  It is only useful for
relative, time-based measurements.

Share this post


Link to post
Share on other sites

Charge (mAh) I suppose (after dividing it by 1000)?  :)

 

While starting to discharge it remains the same. Let's see how it behaves later (will update in 24h -- this time I disconnected the SSD to get an idea how long an idle Lime2 can run on battery):

 

 

 

Bildschirmfoto%202016-01-29%20um%2010.37

 

 

Share this post


Link to post
Share on other sites

While starting to discharge it remains the same.

Registers weren't marked as volatile, so it was reading cached values. Should be fixed now, I uploaded new kernel version.

FYI It's based on 4.5-rc1, b53 driver in this version is broken (missing) in case anyone wants to test it on Lamobo-R1 later.

 

Another thing - can you test poweroff when powered from both battery and ac in? For me it results in reboot, even though shutdown/reboot logic should be different from legacy kernel. Also I will test unpatched kernel later in case it's caused by battery detection fix, but it's unlikely.

Nevermind, it's a kernel panic caused by usb gadget modules.

Share this post


Link to post
Share on other sites

Registers weren't marked as volatile, so it was reading cached values. Should be fixed now, I uploaded new kernel version.

 

Yeah, with the new version the value changes and looks interesting. Current idea: Use /etc/armbianmonitor/datasources/battery_charge symlinked to /sys/power/axp_pmu/battery/charge and /etc/armbianmonitor/datasources/battery_peak that contains the battery/charge peak value from the last charge cycle. Therefore battery_peak will be maintained by a daemon and remains always at the highest value when discharging starts. And then I try to use a simple forumula to calculate percentage:

 

 

 

dynamic.21.name=battery_peak
dynamic.21.source=/etc/armbianmonitor/datasources/battery_peak
dynamic.21.regexp=(.*)

dynamic.22.name=battery_percentage
dynamic.22.source=/etc/armbianmonitor/datasources/battery_charge
dynamic.22.regexp=(.*)
dynamic.22.postprocess=sprintf("%.0f", $1 * 100 / $this->{'dynamic'}->{'battery_peak'})
dynamic.22.rrd=GAUGE

...

web.statistics.1.content.4.graph.5=battery_percent
web.statistics.1.content.4.graph.6=battery_percentage
web.statistics.1.content.4.ds_graph_options.battery_percent.label=Li-On curve (%)
web.statistics.1.content.4.ds_graph_options.battery_percentage.label=Percentage (%) 

 

 

 

I disconnected DC-IN so let's see whether this data source behaves more like 'remaining percentage' or whether it's still necessary to combine it with other data sources. Thx for the fix and the provided kernel package (running out of spare time since 'normal work' has to have higher priority now -- I'm busy doing a PDF based archive workflow and some funny image metadata injections)

Share this post


Link to post
Share on other sites

As a note: I checked legacy driver for this value, and there coulomb counters are reset on boot, this version resets them too (it was simpler to test). I probably will disable resetting later.

Based on provided formula (and based on my tests) "battery/charge" works like this:

  • ADC samples charge current and discharge current, for example, at 100Hz rate,
  • Raw result for charge current is added to charge counter, raw result for discharge current is added to discharge counter.
  • "Charge" is calculated as: scale coefficient * (charge counter - discharge counter) / 3600 (seconds in hour) / ADC rate (samples per second) = value in mAh
  • Result value can be negative, i.e. if you reset when battery is full and unplug AC power

So it basically integrates current that goes to or from the battery.

 

This PMU (AXP202/209) doesn't maintain min or max value for charge and you can't calibrate the capacity meter unlike in axp288.

BTW, battery/capacity is certainly based on voltage, for me it fluctuates with spinning SATA HDD and goes up if I issue sleep command to HDD while discharging.

Share this post


Link to post
Share on other sites

Just a small update: I implemented the aforementioned approach (record the peak value of battery/charge and then use this and the actual value to calculate percentage) and at least it looks good:

 

Bildschirmfoto%202016-01-31%20um%2017.19

 

Discharging started at 9:50, at 10:00 I started a sysbench run and at 10:10 an iozone run on the connected SSD and sysbench in parallel (~4W consumption). When the value derived from my primitive formula fell below 49% I stopped the benchmarks to let the Lime2 being idle more or less. I'm curious how high the value is when the Lime2 shuts down due to battery being drained. Update this evening or tomorrow morning.

 

EDIT: The Lime2 was shutdown when the calculated remaining percentage was at 13% -- will post an updated graph later...

 

Bildschirmfoto%202016-02-01%20um%2014.16

 

When recharging the percentage value reaches 104% so this time the peak battery/charge value exceeds the one from yesterday (in case this formula is useful then the daemon approach to adjust the peak value while charging will prevent percentage to exceed 100%).

 

While this percentage value looks better I still doubt that it's useful without further corrections (implementing emergency shutdown if battery capacity falls below a certrain treshold and stuff like that).

Share this post


Link to post
Share on other sites

When recharging the percentage value reaches 104% so this time the peak battery/charge value exceeds the one from yesterday (in case this formula is useful then the daemon approach to adjust the peak value while charging will prevent percentage to exceed 100%).

Since this value is relative and by its nature is prone to drifting, I don't think it should be used as a main source for calculating percentage. And since there are no perfect solutions to do that with this hardware, I think percentage should be either raw battery/capacity or calculated manually from voltage.

 

While this percentage value looks better I still doubt that it's useful without further corrections (implementing emergency shutdown if battery capacity falls below a certrain treshold and stuff like that).

For emergency shutdown we already have voltage and voltage-based capacity. AXP shuts power down based on voltage too. 

Share this post


Link to post
Share on other sites

Ok, I went through another charge/discharge cycle (discharging took 25:30h -- booooooring):

 

 

 

Bildschirmfoto%202016-02-02%20um%2019.50

 

 

Bildschirmfoto%202016-02-02%20um%2019.52

 

 

 

This calculated percentage thing still looks nice ;) but I agree that it can not used to provide user feedback (maybe as one data source of many). Lime2 powered off when voltage was at 2.99V -- will this be the same for any battery that might be used together with AXP209? And at which voltage should an emergy shutdown be triggered. Loosing the last 0.3V is always pretty fast.

Share this post


Link to post
Share on other sites

Lime2 powered off when voltage was at 2.99V -- will this be the same for any battery that might be used together with AXP209?

Hard to say, default value is 2.9V, however I believe it can be changed by legacy driver (configurable in script.fex/script.bin) and changes may survive kernel switching, especially on devices with RTC battery. So unless mainline driver is patched to force this value, you can't rely on it.

 

And at which voltage should an emergy shutdown be triggered. Loosing the last 0.3V is always pretty fast.

Maybe use battery/capacity with threshold configurable by user (and default value of, maybe, 5%) while keeping in mind that it's recommended to not fully discharge Li-Ion batteries.

 

Edit: This should be interesting for you, looks like legacy driver may be using linear approximation (or something similar) to calculate capacity based on voltage with some reference points, though in our case voltage is not an OCV and it's affected by discharge current. I'll check the code later to see if this applies to AXP209.

 

Edit 2: Driver in legacy kernel writes these values to registers that aren't documented for AXP209...

 

Edit 3: Mainline AXP power driver (that wasn't merged) uses these too...  :unsure:

 

Edit 4: Yep... notes from mainline patch

> > > > Note: the OCV values seem to have some defaults build into the
> > > > PMIC though may need adjustment if the used battery has a different
> > > > open circuit voltage curve.
> > > > As far as understood (these values are set in vendor driver but not
> > > > mentioned in chip documentation) they represent charge percentage
> > > > for some predefined voltages.

but this doesn't help much since there is no proper interface to set these values for end users.

Share this post


Link to post
Share on other sites

Hmm... what a can of worms did we open?  :wacko:

 

Ok, back to the basics. Defining a configurable percentage to trigger emergency shutdown when monitoring is activated/running and using the 5% default seems like a good idea to me. Will try to implement that in armbianmonitor's daemon code next weekend.

 

Defining reference points to calculate remaining battery percentage seems like a good idea... from a vendor's point of view that produces an Android tablet and knows the batteries he uses in his devices. In case we could provide a way to configure these reference points with mainline kernel then this would be stuff for a tutorial (something like: "Wanna get more precise battery information? Do a charge/discharge cycle with the device being totally idle, activate monitoring, analyse voltages and eventually write the results to fex/dts")

Share this post


Link to post
Share on other sites

Defining reference points to calculate remaining battery percentage seems like a good idea... from a vendor's point of view that produces an Android tablet and knows the batteries he uses in his devices. In case we could provide a way to configure these reference points with mainline kernel then this would be stuff for a tutorial (something like: "Wanna get more precise battery information? Do a charge/discharge cycle with the device being totally idle, activate monitoring, analyse voltages and eventually write the results to fex/dts")

It's not that bad, but in the end making some type of calibration procedure for geeks is easy, for average people - not so much. I'll try do some tests to understand behaviour of these undocumented things later...

Share this post


Link to post
Share on other sites

Maybe use battery/capacity with threshold configurable by user (and default value of, maybe, 5%) while keeping in mind that it's recommended to not fully discharge Li-Ion batteries.

 

 

Beside your comment, I can see two scenarios and I guess there are others

1. Just a USP - in case you lose main power, secure shutdown

2. Run the device autonomously for a period of time, secure shutdown

Also to consider with aging the accu gets weaker. I don't know which steps you can set, but I would not go bleeding edge.

 

@TK - boring - does your Accu have too much capacity :-)  a good old P4 would be faster in draining :)

Share this post


Link to post
Share on other sites

Beside your comment, I can see two scenarios and I guess there are others

1. Just a USP - in case you lose main power, secure shutdown

2. Run the device autonomously for a period of time, secure shutdown

Also to consider with aging the accu gets weaker.

 

An older battery behaves exactly like a newer one just in less time. Voltage will decrease faster --> same happens with capacity read-out that's based somehow on voltage. And in my case with this new rather large battery and an uncalibrated capacity curve the time between reaching the 5% treshold and final shutdown was almost 5 hours:

 

 

Bildschirmfoto-2016-02-03-um-08.56.png

 

 

 

In case someone wants an immediatey shutdown when the system starts to run on battery he simply has to increase the treshold from 5% to 100% or 90% and he's already done. This is the more simple stuff for Readme.md (I would believe it will be much harder to explain why/how consumption read-outs differ when running on battery or DC-IN, why some/most A20 boards do not fully support UPS mode and why 'remaining capacity' will always be wrong more or less)

Share this post


Link to post
Share on other sites

An older battery behaves exactly like a newer one just in less time. 

Except for higher internal impedance (Rdc), which needs to be calibrated to minimize influence of discharge current on battery capacity readouts...

 

In case someone wants an immediatey shutdown when the system starts to run on battery he simply has to...

he simply has to implement interrupt handler and sysfs notify mechanism for AXP209 driver  :)

In other words - setting threshold to ~95% should be enough, plus it won't immediately shutdown system if power loss lasted only for 5-10 seconds.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
5 5