2009-12-04 10:42:21

by Linus Walleij

[permalink] [raw]
Subject: [POWER] battery calibration parameters from sysfs

Hi,

we're working on battery charging support for ST-Ericsson MFD ASICs
like AB3100 and later series. I have this issue about battery
calibration
parameters that I need advice on, and more specifically on how to use
sysfs to get that data in.

Most devices of this kind does not need the stuff we're doing so we're
the odd bird here. Other batteries are "smart" (contain factory
calibration inside of them) or get calibration from some BIOS or such.

In our code we have a number of (x,y) pair tables like this:

/* Vbat mV to Battery capacity % */
struct voltage_vs_capacity {
int voltage;
int capacity;
};

/*
* Default calibration table for voltage vs battery capacity.
* Voltage in millivolts, capacity given in permil.
*/
struct voltage_vs_capacity voltage_to_battery_capacity_init[] = {
{ 4177, 1000 },
{ 4070, 900 },
{ 3988, 800 },
{ 3834, 570 },
{ 3797, 470 },
{ 3768, 320 },
{ 3721, 190 },
{ 3633, 60 },
{ 3523, 30 },
{ 3200, 0 },
};

We then interpolate between two subsequent (xn,yn),(xn+1,yn+1)
pairs to get a calibrated capacity value from the voltage
level measured.

This is all good as long as you compile the calibration into the kernel
like this.

However we want to override the default table with one fed in
though e.g. sysfs, so calibration data for the battery can reside
in the file system. NOTE: this table is NOT of fixed length, i.e.
we don't know how many (x,y) pairs will be passed in.

Whereas the rule for sysfs is one value per file, creating an arbitrary
large hirarchy like this:

/sys/.../v_vs_cap/x0
/sys/.../v_vs_cap/y0
/sys/.../v_vs_cap/x1
/sys/.../v_vs_cap/y2
...
/sys/.../v_vs_cap/xN
/sys/.../v_vs_cap/yN

Is probably not very elegant. (Or is it?) Would it be permissible to
pass in a table like:

cat >/sys/.../v_vs_cap <<EOF
x0,y0
x1,y1
x2,y2
EOF

And have the kernel parse x,y pairs up to EOF?

Or would it be preferable to do this thing by creating some
misc device node like /dev/battery0 and a custom ioctl()?

Or is there some other way I haven't thought of?

Yours,
Linus Walleij
ST-Ericsson


2009-12-04 10:49:32

by Mark Brown

[permalink] [raw]
Subject: Re: [POWER] battery calibration parameters from sysfs

On Fri, Dec 04, 2009 at 11:42:22AM +0100, Linus Walleij wrote:

> Most devices of this kind does not need the stuff we're doing so we're
> the odd bird here. Other batteries are "smart" (contain factory
> calibration inside of them) or get calibration from some BIOS or such.

> In our code we have a number of (x,y) pair tables like this:

> /* Vbat mV to Battery capacity % */
> struct voltage_vs_capacity {
> int voltage;
> int capacity;
> };

Isn't the standard thing here to handle this voltage to capacity mapping
in userspace if we're just extrapolating from experimental results?
Even with the "smart" batteries in PCs there are some accuracy concerns
and obviously the performance of the battery will change over time.

2009-12-04 12:08:31

by Alexander Clouter

[permalink] [raw]
Subject: Re: [POWER] battery calibration parameters from sysfs

Linus Walleij <[email protected]> wrote:
>
> [snipped]
>
> Is probably not very elegant. (Or is it?) Would it be permissible to
> pass in a table like:
>
> cat >/sys/.../v_vs_cap <<EOF
> x0,y0
> x1,y1
> x2,y2
> EOF
>
> And have the kernel parse x,y pairs up to EOF?
>
> Or would it be preferable to do this thing by creating some
> misc device node like /dev/battery0 and a custom ioctl()?
>
> Or is there some other way I haven't thought of?
>
Although I'm a 'nobody' I would probably go for:
----
echo x0,y0:x1,y1:....
----

Pairs are seperated by ':' whilst values with ','. I guess you could
just use comma's all the way but I personally say that reduces
readability...also means that maybe one day you want to pass only one or
three values...the format could still work.

Easy to parse, a one liner, no fixed length, fits in with the existing
use, etc etc.

Cheers

--
Alexander Clouter
.sigmonster says: You'll be sorry...

2009-12-04 14:17:31

by Mark Brown

[permalink] [raw]
Subject: Re: [POWER] battery calibration parameters from sysfs

On Fri, Dec 04, 2009 at 10:49:31AM +0000, Mark Brown wrote:

> Isn't the standard thing here to handle this voltage to capacity mapping
> in userspace if we're just extrapolating from experimental results?
> Even with the "smart" batteries in PCs there are some accuracy concerns
> and obviously the performance of the battery will change over time.

Actually, one further thing here - if this functionality is implemented
in kernel then shouldn't it be a generic feature rather than part of the
driver? The idea of mapping battery voltages to capacity percentages
isn't specific to a given charger and will apply to all batteries using
the same technology.

2009-12-05 13:08:26

by Linus Walleij

[permalink] [raw]
Subject: RE: [POWER] battery calibration parameters from sysfs

Thanks Mark, prompt answers as always.

[Mark Brown]
> [Linus Walleij]
> > In our code we have a number of (x,y) pair tables like this:
>
> > /* Vbat mV to Battery capacity % */
> > struct voltage_vs_capacity {
> > int voltage;
> > int capacity;
> > };
>
> Isn't the standard thing here to handle this voltage to
> capacity mapping in userspace if we're just extrapolating
> from experimental results?

That's an easy solution of course, but then the sysfs files
specified by the power subsystem, i.e. all "charge_*",
"energy_*", "capacity" and "time_to_*" loose their meaning
and must be ignored by userspace.

Also this was just an example, we have similar calibration
for the temperature sensor, and thus the "temp" sysfs file
also loose its meaning.

Since there is a plethora of userspace apps that just
interface these files directly (gnome-power-manager and
the Android stack come to mind) all these will have to
be patches to accept a calibrated value from somewhere
else if we shall use them with our hardware.

But as you say:

> Even with the "smart" batteries in PCs there are some
> accuracy concerns and obviously the performance of the
> battery will change over time.
> ...
> Actually, one further thing here - if this functionality
> is implemented in kernel then shouldn't it be a generic
> feature rather than part of the driver? The idea of
> mapping battery voltages to capacity percentages isn't
> specific to a given charger and will apply to all
> batteries using the same technology.

Surely, we'd be happy to do it that way if desired.
What about drivers/power/battery_lib.c?

(And getting algorithms in place for gradually
adjusting the capacity levels as compared to factory
settings for PC batteries would perhaps end up in the
same place then.)

We have other odd code. Actually we have full software-
controlled CC/CV charging in our driver, and that
would *definately* go in such a library if it was
to end up in kernelspace. We have actually
pushed that to userspace, while I still tend to think
that the kernel (with right parameters) should be able
to charge a battery. But, well.

As for the calibration format, after reading up on the
latest sysfs doc I saw:

Documentation/filesystems/sysfs.txt:
"Attributes should be ASCII text files, preferably with
only one value per file. It is noted that it may not be
efficient to contain only one value per file, so it is
socially acceptable to express an array of values of the
same type."

This is close to that, an array of two types (x,y)(x,y)
voltage,capacity,voltage,capacity etc. Pushing them in
two files

/sys/.../v_vs_cap_v
/sys/.../v_vs_cap_cap

and then make sure we write as many values to each array
is uglier IMHO.


Yours,
Linus Walleij

2009-12-05 17:45:36

by Mark Brown

[permalink] [raw]
Subject: Re: [POWER] battery calibration parameters from sysfs

On Sat, Dec 05, 2009 at 02:08:11PM +0100, Linus Walleij wrote:
> [Mark Brown]
> > [Linus Walleij]

> > Isn't the standard thing here to handle this voltage to
> > capacity mapping in userspace if we're just extrapolating
> > from experimental results?

> That's an easy solution of course, but then the sysfs files
> specified by the power subsystem, i.e. all "charge_*",
> "energy_*", "capacity" and "time_to_*" loose their meaning
> and must be ignored by userspace.

I'd not expect them to be there at all in this case - certainly existing
drivers aren't reporting all these properties, even for relatively smart
batteries with embedded controllers like those in laptops. For example,
the laptop I'm typing this on only reports charge, current and voltage
properties and doesn't have capacity, enegy or time to information.

> Also this was just an example, we have similar calibration
> for the temperature sensor, and thus the "temp" sysfs file
> also loose its meaning.

Sure, there's an awful lot of performance information that isn't
available from hardware and has to be interpolated.

> Since there is a plethora of userspace apps that just
> interface these files directly (gnome-power-manager and
> the Android stack come to mind) all these will have to
> be patches to accept a calibrated value from somewhere
> else if we shall use them with our hardware.

I was under the impression that at least GNOME was already working on
doing this themselves, based on data gathered at runtime rather than
pre-provided data tables, but I'm not turning anything up right now so I
might be imagining things. If a userspace implementation is done right
I'd expect that it'd be possible to share the heavy lifting between the
various applications, and even with an in-kernel implementaiton we'll
need userspace to know to save and restore any data that needs to
persist over reboots.

> But as you say:

> > Even with the "smart" batteries in PCs there are some
> > accuracy concerns and obviously the performance of the
> > battery will change over time.
> > ...
> > Actually, one further thing here - if this functionality
> > is implemented in kernel then shouldn't it be a generic
> > feature rather than part of the driver? The idea of
> > mapping battery voltages to capacity percentages isn't
> > specific to a given charger and will apply to all
> > batteries using the same technology.

> Surely, we'd be happy to do it that way if desired.
> What about drivers/power/battery_lib.c?

I guess. Probably if it's going to be in the kernel ought to just be
part of the power core and kick in automatically if properties it can
estimate aren't supplied by the driver.

> (And getting algorithms in place for gradually
> adjusting the capacity levels as compared to factory
> settings for PC batteries would perhaps end up in the
> same place then.)

I'm still not entirely seeing why this needs to be in the kernel. It
sounds like the main push here is to fit in with existing applications
but given that these properties aren't reliably available at on current
systems I'd be a bit surprised if applications were relying on this
interface already. Are there reasons for doing things this way other
than existing applications?

> As for the calibration format, after reading up on the
> latest sysfs doc I saw:

...

> This is close to that, an array of two types (x,y)(x,y)
> voltage,capacity,voltage,capacity etc. Pushing them in
> two files

> /sys/.../v_vs_cap_v
> /sys/.../v_vs_cap_cap

> and then make sure we write as many values to each array
> is uglier IMHO.

TBH I don't think there's going to be a nice way of doing this via
sysfs. I'm not sure if one of the other filesystems such as configfs
might be a bit more suitable for this application. The difficulty in
defining an ABI is another thing that makes it seem like doing this in
the kernel is the wrong approach.

2009-12-06 21:01:58

by Greg KH

[permalink] [raw]
Subject: Re: [POWER] battery calibration parameters from sysfs

On Fri, Dec 04, 2009 at 11:42:22AM +0100, Linus Walleij wrote:
> However we want to override the default table with one fed in
> though e.g. sysfs, so calibration data for the battery can reside
> in the file system. NOTE: this table is NOT of fixed length, i.e.
> we don't know how many (x,y) pairs will be passed in.
>
> Whereas the rule for sysfs is one value per file, creating an arbitrary
> large hirarchy like this:
>
> /sys/.../v_vs_cap/x0
> /sys/.../v_vs_cap/y0
> /sys/.../v_vs_cap/x1
> /sys/.../v_vs_cap/y2
> ...
> /sys/.../v_vs_cap/xN
> /sys/.../v_vs_cap/yN
>
> Is probably not very elegant. (Or is it?) Would it be permissible to
> pass in a table like:
>
> cat >/sys/.../v_vs_cap <<EOF
> x0,y0
> x1,y1
> x2,y2
> EOF
>
> And have the kernel parse x,y pairs up to EOF?

No, please don't do this through sysfs, it is not set up to handle this
(hint, what happens if you put more than one PAGE_SIZE of data to the
file?)

Use configfs instead, that is what it is there for.

Or use userspace to handle the mapping table, that would be preferable
than to parse anything within the kernel.

thanks,

greg k-h

2009-12-07 11:48:22

by Mark Brown

[permalink] [raw]
Subject: Re: [POWER] battery calibration parameters from sysfs

On Sat, Dec 05, 2009 at 02:08:11PM +0100, Linus Walleij wrote:
> [Mark Brown]

> > Isn't the standard thing here to handle this voltage to
> > capacity mapping in userspace if we're just extrapolating
> > from experimental results?

> That's an easy solution of course, but then the sysfs files
> specified by the power subsystem, i.e. all "charge_*",
> "energy_*", "capacity" and "time_to_*" loose their meaning
> and must be ignored by userspace.

These files should only be present if we have data for them. Userspace
can't be reliant on them at present since relatively few systems seem to
implement them, for example none of my laptops have time_to, energy_ or
capacity attributes.

> Also this was just an example, we have similar calibration
> for the temperature sensor, and thus the "temp" sysfs file
> also loose its meaning.

Sure, and with temperature sensors tables of design based information
might be more appropriate since it's not possible to gain experimenal
data from the running system in the way we can for batteries.

> Since there is a plethora of userspace apps that just
> interface these files directly (gnome-power-manager and
> the Android stack come to mind) all these will have to
> be patches to accept a calibrated value from somewhere
> else if we shall use them with our hardware.

At least GNOME seems to already be collecting historical statistics on
the battery performance. I believe it's factoring the results into the
values reported through the UI but I'd need to check.

> > Actually, one further thing here - if this functionality
> > is implemented in kernel then shouldn't it be a generic
> > feature rather than part of the driver? The idea of

> Surely, we'd be happy to do it that way if desired.
> What about drivers/power/battery_lib.c?

If we're going to do it at all. Ideally it'd just kick in automatically
when data isn't available so possibly it ought to be core code rather
than a library used by drivers.

> (And getting algorithms in place for gradually
> adjusting the capacity levels as compared to factory
> settings for PC batteries would perhaps end up in the
> same place then.)

I'm still not convinced that it's a good idea to put this into the
kernel.

So far as I can see the main case for doing it in kernel is existing
userspace - is there any other motivation I've overlooked? Like I say
I'd be somewhat surprised if userspace were relying on this data given
that we're not currently generating it and it's going to need at least
some userspace work to save and restore the data. There's also policy
issues about how often you do the monitoring and so on.

> We have other odd code. Actually we have full software-
> controlled CC/CV charging in our driver, and that
> would *definately* go in such a library if it was
> to end up in kernelspace. We have actually
> pushed that to userspace, while I still tend to think
> that the kernel (with right parameters) should be able
> to charge a battery. But, well.

As was previously discussed (in another thread) I do think there needs
to be at least some in kernel part to charger code like this in order to
ensure that we're robust against userspace failure and cope well with
suspend and resume. There's the potential for serious hardware damage
if the battery is mistreated.

> As for the calibration format, after reading up on the
> latest sysfs doc I saw:

There's other kernel filesystems that might be more approprite for this
sort of stuff, trying to fit this into sysfs really does feel like far
too much pain to be right.

2009-12-07 14:22:11

by Linus Walleij

[permalink] [raw]
Subject: RE: [POWER] battery calibration parameters from sysfs

Thanks for all the great attention Mark!

[Mark wrote]
> On Sat, Dec 05, 2009 at 02:08:11PM +0100, Linus Walleij wrote:
> > (...)
> > That's an easy solution of course, but then the sysfs files
> > specified by the power subsystem, i.e. all "charge_*",
> > "energy_*", "capacity" and "time_to_*" loose their meaning
> > and must be ignored by userspace.
>
> These files should only be present if we have data for them.
> Userspace can't be reliant on them at present since relatively few
> systems seem to implement them, for example none of my laptops
> have time_to, energy_ or capacity attributes.

Well, yeah, we're not exactly in the laptop business.
(But my HP laptop nc2400 has the "charge_*" attributes,
4990000 uAh in "charge_now" and this corresponds to
what is shown in g-p-m converted over to Wh, but I don't
know exactly where it's getting it from...)

One of the things we're facing is Android, which has
its userspace in plain Java JNI at the end of this link:
http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=s
ervices/jni/com_android_server_BatteryService.cpp;h=8e7cadc6b680fc420d34
1faa094c71922946fdab;hb=HEAD

If you browse down to line 275 you can see it parse the sysfs
attribute "capacity", then this propagates up to the battery
status indicator on *all* Android phones out there. So if
you want to run Android unmodified, this is what you need to
provide. They are effectively using the power sysfs as
their hardware abstraction layer in this case.

Note: I'm not claiming that Android is doing it right or that
we can't modify this code or so, it's just that this is the way
a few million Android devices out there are actually doing it.

> > We have other odd code. Actually we have full software-
> > controlled CC/CV charging in our driver, and that
> > would *definately* go in such a library if it was
> > to end up in kernelspace. We have actually
> > pushed that to userspace, while I still tend to think
> > that the kernel (with right parameters) should be able
> > to charge a battery. But, well.
>
> As was previously discussed (in another thread) I do think there needs
> to be at least some in kernel part to charger code like this
> in order to
> ensure that we're robust against userspace failure and cope well with
> suspend and resume. There's the potential for serious hardware damage
> if the battery is mistreated.

You're right of course. In our case we have a hardware
watchdog protecting against overcharging etc, and charging will
halt when the watchdog is not periodically fed. So actually
we're on the safe side here. (I think!)

> There's other kernel filesystems that might be more
> approprite for this
> sort of stuff, trying to fit this into sysfs really does feel like far
> too much pain to be right.

You're right GKH already pointed me to configfs so that's
where it's going to sit if we do this thing.

We'd better write up some code to show how this would
work instead so I'll be back with that sooner or later.

Yours,
Linus Walleij

2009-12-07 16:56:28

by Mark Brown

[permalink] [raw]
Subject: Re: [POWER] battery calibration parameters from sysfs

On Mon, Dec 07, 2009 at 03:07:15PM +0100, Linus Walleij wrote:
> [Mark wrote]

> > These files should only be present if we have data for them.
> > Userspace can't be reliant on them at present since relatively few
> > systems seem to implement them, for example none of my laptops
> > have time_to, energy_ or capacity attributes.

> Well, yeah, we're not exactly in the laptop business.
> (But my HP laptop nc2400 has the "charge_*" attributes,
> 4990000 uAh in "charge_now" and this corresponds to
> what is shown in g-p-m converted over to Wh, but I don't
> know exactly where it's getting it from...)

Looking at what PCs are doing is often a useful guide as to what the
desktop userspace stacks will be trying to use - if you can't get the
information from a Dell or whatever then the chances are they'll cope
fine without it. Of course, laptop batteries tend to be rather more
fancy in terms of their embedded controllers if nothing else.

> One of the things we're facing is Android, which has
> its userspace in plain Java JNI at the end of this link:
> http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=s
> ervices/jni/com_android_server_BatteryService.cpp;h=8e7cadc6b680fc420d34
> 1faa094c71922946fdab;hb=HEAD

Something word wrapped that link but I think I found the same code.

> If you browse down to line 275 you can see it parse the sysfs
> attribute "capacity", then this propagates up to the battery
> status indicator on *all* Android phones out there. So if
> you want to run Android unmodified, this is what you need to
> provide. They are effectively using the power sysfs as
> their hardware abstraction layer in this case.

Oh dear. Using the power sysfs as the hardware abstraction seems
perfectly reasonable but assuming that a given battery driver is going
to have this level of information doesn't match up with an awful lot of
actual charger hardware. My main concern here is that battery
performance monitoring has no pressing need to be in kernel and that
pushing it into the kernel creates a barrier to implementing more
advanced schemes in userspace, which is especially serious given how
involved this needs to be in order to be accurate.

I'm not sure how familiar you are with the issues surrounding trying to
do a voltage to charge mapping for a battery but it's much more complex
than a simple table if you want to get it accurate. There's a lot of
dependence on particular operating conditions and things do change as
the batteries age. There are systems out there that do the work
required to gather the information in hardware and it's definitely good
to report the information from them but that doesn't mean it's a good
idea to try to synthesise the information for other systems.

We should at least explore the possibility of getting Android to improve
their userspace code rather than put this sort of code into the kernel.
I've CCed Brian in in case he can comment on the possibility of doing
that.

> Note: I'm not claiming that Android is doing it right or that
> we can't modify this code or so, it's just that this is the way
> a few million Android devices out there are actually doing it.

I don't think the existing Android devices are much of an issue here,
it's not as though end users have the ability modify the firmware on
them (modulo the fairly small number of ADP devices). This is an issue
for people producing new devices who are already going to be doing some
development to get the kernel up and running on their hardware.

2009-12-08 05:27:22

by Brian Swetland

[permalink] [raw]
Subject: Re: [POWER] battery calibration parameters from sysfs

On Mon, Dec 7, 2009 at 8:56 AM, Mark Brown
<[email protected]> wrote:
>
>> One of the things we're facing is Android, which has
>> its userspace in plain Java JNI at the end of this link:
>> http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=s
>> ervices/jni/com_android_server_BatteryService.cpp;h=8e7cadc6b680fc420d34
>> 1faa094c71922946fdab;hb=HEAD
>
> Something word wrapped that link but I think I found the same code.
>
>> If you browse down to line 275 you can see it parse the sysfs
>> attribute "capacity", then this propagates up to the battery
>> status indicator on *all* Android phones out there. So if
>> you want to run Android unmodified, this is what you need to
>> provide. They are effectively using the power sysfs as
>> their hardware abstraction layer in this case.
>
> Oh dear.  Using the power sysfs as the hardware abstraction seems
> perfectly reasonable but assuming that a given battery driver is going
> to have this level of information doesn't match up with an awful lot of
> actual charger hardware.  My main concern here is that battery
> performance monitoring has no pressing need to be in kernel and that
> pushing it into the kernel creates a barrier to implementing more
> advanced schemes in userspace, which is especially serious given how
> involved this needs to be in order to be accurate.

We should tidy up the userspace side to have better abstraction for
this. On a number of devices we do obtain all the information
necessary from the kernel driver (or, in some cases battery monitoring
on the baseband side that the kernel driver chats with). On other
devices we don't (Motorola Droid, for example uses a userspace battery
daemon).

>> Note: I'm not claiming that Android is doing it right or that
>> we can't modify this code or so, it's just that this is the way
>> a few million Android devices out there are actually doing it.
>
> I don't think the existing Android devices are much of an issue here,
> it's not as though end users have the ability modify the firmware on
> them (modulo the fairly small number of ADP devices).  This is an issue
> for people producing new devices who are already going to be doing some
> development to get the kernel up and running on their hardware.

My preference, from an Android point of view, would be to make sure we
have some reasonable userspace abstraction and provide a default
implementation that will do the right thing with an intelligent
battery driver (our usual design for inhouse work). Then alternative
implementations can be plugged in, should that not be sufficient.

Brian

2009-12-08 10:28:09

by Mark Brown

[permalink] [raw]
Subject: Re: [POWER] battery calibration parameters from sysfs

On Mon, Dec 07, 2009 at 09:27:20PM -0800, Brian Swetland wrote:
> On Mon, Dec 7, 2009 at 8:56 AM, Mark Brown

> > I don't think the existing Android devices are much of an issue here,
> > it's not as though end users have the ability modify the firmware on
> > them (modulo the fairly small number of ADP devices). ?This is an issue
> > for people producing new devices who are already going to be doing some
> > development to get the kernel up and running on their hardware.

> My preference, from an Android point of view, would be to make sure we
> have some reasonable userspace abstraction and provide a default
> implementation that will do the right thing with an intelligent
> battery driver (our usual design for inhouse work). Then alternative
> implementations can be plugged in, should that not be sufficient.

It proably makes sense to have some of the performance tracking in there
by default - while there are some systems out there which are able to do
high quality battery tracking there's several previous generations of
monitoring technology out there which have substantial accuracy issues
(especially in the face of removable battery packs) but which will
report information to userspace. This makes it unwise to rely to
totally on the information you're getting from the kernel - the
smartness of a smart battery driver can vary greatly.

2009-12-13 13:19:33

by Pavel Machek

[permalink] [raw]
Subject: Re: [POWER] battery calibration parameters from sysfs

> One of the things we're facing is Android, which has
> its userspace in plain Java JNI at the end of this link:
> http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=s
> ervices/jni/com_android_server_BatteryService.cpp;h=8e7cadc6b680fc420d34
> 1faa094c71922946fdab;hb=HEAD
>
> If you browse down to line 275 you can see it parse the sysfs
> attribute "capacity", then this propagates up to the battery
> status indicator on *all* Android phones out there. So if
> you want to run Android unmodified, this is what you need to
> provide. They are effectively using the power sysfs as
> their hardware abstraction layer in this case.
>
> Note: I'm not claiming that Android is doing it right or that
> we can't modify this code or so, it's just that this is the way
> a few million Android devices out there are actually doing it.

Users can't modify them, so they don't count...

...but then there are all the systems that rely on /proc/apm
emulation, like openembedded popular on sharp zaurus...

Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2009-12-13 13:24:28

by Pavel Machek

[permalink] [raw]
Subject: Re: [POWER] battery calibration parameters from sysfs

Hi!

> > If you browse down to line 275 you can see it parse the sysfs
> > attribute "capacity", then this propagates up to the battery
> > status indicator on *all* Android phones out there. So if
> > you want to run Android unmodified, this is what you need to
> > provide. They are effectively using the power sysfs as
> > their hardware abstraction layer in this case.
>
> Oh dear. Using the power sysfs as the hardware abstraction seems
> perfectly reasonable but assuming that a given battery driver is going
> to have this level of information doesn't match up with an awful lot of
> actual charger hardware. My main concern here is that battery
> performance monitoring has no pressing need to be in kernel and that
> pushing it into the kernel creates a barrier to implementing more
> advanced schemes in userspace, which is especially serious given how
> involved this needs to be in order to be accurate.

Well, kernel provides /proc/apm emulation and many systems still rely
on it. So it would be nice to provide something halfway-decent there.

Plus you need to shutdown/suspend machine on battery critical. That
has to be in kernel and already needs those tricky parts.

(Sharp got it wrong in collie kernel, and you get 5hours instead of 10
with old battery :-(().

> I'm not sure how familiar you are with the issues surrounding trying to
> do a voltage to charge mapping for a battery but it's much more complex
> than a simple table if you want to get it accurate. There's a lot
> of

Well... current zaurus kernels use _huge_ table that maps voltage to
battery %... and that table is linear function :-(.

Do you have some papers on that?

> dependence on particular operating conditions and things do change as
> the batteries age. There are systems out there that do the work
> required to gather the information in hardware and it's definitely good
> to report the information from them but that doesn't mean it's a good
> idea to try to synthesise the information for other systems.

So... on zaurus I plan to:

1) provide better voltage -- %age map

2) estimate current

3) estimate internal battery resistance as constant

4) estimate internal battery volltage using ohm's law and base %age
estmate on that.

Now... I realize that internal resistance depends on charge left. Nasty
but probably can be ignored. Then it depends on temperature. Does
anyone have better idea how?

Then... I need a way to measure internal resistance. I know it is in
200mOhm to 400mOhm range, on my device. Is there easy way to measure
it more accurately?

Pavel
#!/bin/bash
#
# Copyright 2009 Pavel Machek <[email protected]>, GPLv2
#

getval() {
SETTLETIME=5
echo Run this on idle, unplugged system, with expansion cards
echo removed and backlight enabled
echo
echo 1 > /sys/class/backlight/corgi?bl/brightness
echo Backlight 1, waiting for power to settle
sleep $SETTLETIME
VBMIN=`cat /sys/class/power*/*battery/voltage_now`
VBMIN=$[$VBMIN/1000]
echo Voltage = $VBMIN mV

echo
echo 47 > /sys/class/backlight/corgi?bl/brightness
echo Backlight 47, waiting for power to settle
sleep $SETTLETIME
VBMAX=`cat /sys/class/power*/*battery/voltage_now`
VBMAX=$[$VBMAX/1000]
echo Voltage = $VBMAX mV

echo 1 > /sys/class/backlight/corgi?bl/brightness
}

fake1() {
# Very old 1000mAh battery from collie: 703 mOhm
VBMIN=3638
VBMAX=3543
}


fake2() {
# Old 2000mAh battery, nearly charged, 4C: 274 mOhm
VBMIN=3732
VBMAX=3695
}


fake3() {
# Same old 2000mAh battery, nearly charged, 4C: 140 mOhm
# temp: 155.
VBMIN=3714
VBMAX=3695
# Next try: temp 151 -- little warmer: 422 mOhm.
# Next try: temp 151 -- little warmer: 1266 mOhm.
# Next try: temp 148 -- getting warmer: 281 mOhm.
# Next try: temp 148 -- getting warmer, full load: 422 mOhm.
# Next try: temp 148 -- getting warmer, full load: 140 mOhm.
# Next try: temp 148 -- getting warmer, full load: 422 mOhm.
# Next try: temp 138 -- getting warmer, full load: 422 mOhm.
# Next try: temp 139 -- getting warmer, full load: 422 mOhm.
# Next try: temp 136 -- getting warmer, full load: 562 mOhm.
# Next try: temp 132 -- getting warmer, full load: 703 mOhm.
# Next try: temp 132 -- getting warmer, full load: 281 mOhm.
# Next try: temp 134 -- getting warmer, full load: 281 mOhm.
# Next try: temp 134 -- getting warmer, full load: 562 mOhm.
# Next try: temp 129 -- getting warmer, full load: 562 mOhm.
# hugh, I''m getting n*140, wtf?
# ...voltmeters have sensitivity limits...
# temp 118 -- metro, venku zima -- full load: 281 mOhm.
# temp 118 -- metro, venku zima, baterie poloprazdna -- full load: 281 mOhm.
# temp 120 -- metro, venku zima, baterie poloprazdna -- full load: 281 mOhm.
# temp 120 -- metro, venku zima, baterie poloprazdna -- full load: 281 mOhm.
# temp 120 -- metro, venku zima, baterie poloprazdna -- full load: 414 mOhm.
# temp 120 -- metro, venku zima, baterie poloprazdna -- full load: 555 mOhm.
# temp 120 -- metro, venku zima, baterie poloprazdna -- full load: 422 mOhm.
# temp 124 -- metro, venku zima, baterie poloprazdna -- full load: 422 mOhm.
# temp 127 -- metro, venku zima, baterie poloprazdna -- full load: 422 mOhm.

}



getval
#fake1

BLDIFF=135
echo Assuming $BLDIFF mA difference

echo $VBMIN $VBMAX $BLDIFF

# With RESIST in mOhm
# VINSIDE = VBMIN + RESIST * BASECURRENT / 1000
# VINSIDE = VBMAX + RESIST * (BASECURRENT + BLDIFF) / 1000
# Therefore
# RESIST = 1000*(VBMIN-VBMAX)/BLDIFF

RESIST=$[(1000*($VBMIN-$VBMAX))/$BLDIFF]
echo Resistance is $RESIST mOhm

BASECURRENT=280
echo This should be equal:
echo During low backlight $[$VBMIN + ($RESIST * $BASECURRENT) / 1000] mV
echo During high backlight $[$VBMAX + ($RESIST * ($BASECURRENT + $BLDIFF)) / 1000] mV

--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2009-12-14 11:50:28

by Mark Brown

[permalink] [raw]
Subject: Re: [POWER] battery calibration parameters from sysfs

On Sun, Dec 13, 2009 at 02:19:22PM +0100, Pavel Machek wrote:

> ...but then there are all the systems that rely on /proc/apm
> emulation, like openembedded popular on sharp zaurus...

OpenEmbedded is a meta-distribution so doesn't use any particular
software here - I suspect you're referring to things like the GPE stack
which isn't so actively developed these days.

2009-12-14 11:58:34

by Pavel Machek

[permalink] [raw]
Subject: Re: [POWER] battery calibration parameters from sysfs

On Mon 2009-12-14 11:50:24, Mark Brown wrote:
> On Sun, Dec 13, 2009 at 02:19:22PM +0100, Pavel Machek wrote:
>
> > ...but then there are all the systems that rely on /proc/apm
> > emulation, like openembedded popular on sharp zaurus...
>
> OpenEmbedded is a meta-distribution so doesn't use any particular
> software here - I suspect you're referring to things like the GPE stack
> which isn't so actively developed these days.

Both Opie and GPE have the problem IIRC...
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2009-12-14 12:12:52

by Mark Brown

[permalink] [raw]
Subject: Re: [POWER] battery calibration parameters from sysfs

On Sun, Dec 13, 2009 at 02:24:14PM +0100, Pavel Machek wrote:

> > actual charger hardware. My main concern here is that battery
> > performance monitoring has no pressing need to be in kernel and that
> > pushing it into the kernel creates a barrier to implementing more
> > advanced schemes in userspace, which is especially serious given how
> > involved this needs to be in order to be accurate.

> Well, kernel provides /proc/apm emulation and many systems still rely
> on it. So it would be nice to provide something halfway-decent there.

Unfortunately that's really painful in kernel since you really need to
do state tracking over reboots, and even if you do that it's really
not trivial.

> Plus you need to shutdown/suspend machine on battery critical. That
> has to be in kernel and already needs those tricky parts.

Power failure detection based on voltage drop is much more reasonable
but it's a very different thing to general battery capacity estimation.

Normally you'd want to do the power failure detection separately anyway,
monitoring the system supply voltage rather than the battery voltage.
Supply failure is not only an issue in battery operation, it's also an
issue for example in systems systems powered over USB which may be
drawing more than the 500mA that USB delivers and need to supplement the
USB supply with the battery.

> > I'm not sure how familiar you are with the issues surrounding trying to
> > do a voltage to charge mapping for a battery but it's much more complex
> > than a simple table if you want to get it accurate. There's a lot
> > of

> Well... current zaurus kernels use _huge_ table that maps voltage to
> battery %... and that table is linear function :-(.

> Do you have some papers on that?

Something like "Measure Battery Capacity Precisely in Medical Design"
by Bernd Krafthoefer in Power Electronics Technology Jan 2005 might be
useful here.

2009-12-14 12:14:14

by Mark Brown

[permalink] [raw]
Subject: Re: [POWER] battery calibration parameters from sysfs

On Mon, Dec 14, 2009 at 12:58:26PM +0100, Pavel Machek wrote:
> On Mon 2009-12-14 11:50:24, Mark Brown wrote:

> > OpenEmbedded is a meta-distribution so doesn't use any particular
> > software here - I suspect you're referring to things like the GPE stack
> > which isn't so actively developed these days.

> Both Opie and GPE have the problem IIRC...

Yeah, if you're working on older systems like that you'll probably have
to do some userspace work as well as kernel work.

2009-12-14 21:23:21

by Pavel Machek

[permalink] [raw]
Subject: Re: [POWER] battery calibration parameters from sysfs

Hi!

> > > I'm not sure how familiar you are with the issues surrounding trying to
> > > do a voltage to charge mapping for a battery but it's much more complex
> > > than a simple table if you want to get it accurate. There's a lot
> > > of
>
> > Well... current zaurus kernels use _huge_ table that maps voltage to
> > battery %... and that table is linear function :-(.
>
> > Do you have some papers on that?
>
> Something like "Measure Battery Capacity Precisely in Medical Design"
> by Bernd Krafthoefer in Power Electronics Technology Jan 2005 might be
> useful here.

Well, that would really require extensive hardware modifications: it
needs _way_ more accurate ADCs on battery for a start, and a way to
generate huge load.

--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2009-12-14 23:49:24

by Aras Vaichas

[permalink] [raw]
Subject: Re: [POWER] battery calibration parameters from sysfs

2009/12/15 Pavel Machek <[email protected]>:
> Hi!
>
>> > > I'm not sure how familiar you are with the issues surrounding trying to
>> > > do a voltage to charge mapping for a battery but it's much more complex
>> > > than a simple table if you want to get it accurate. ?There's a lot
>> > > of
>>
>> > Well... current zaurus kernels use _huge_ table that maps voltage to
>> > battery %... and that table is linear function :-(.
>>
>> > Do you have some papers on that?
>>
>> Something like "Measure Battery Capacity Precisely in Medical Design"
>> by Bernd Krafthoefer in Power Electronics Technology Jan 2005 might be
>> useful here.
>
> Well, that would really require extensive hardware modifications: it
> needs _way_ more accurate ADCs on battery for a start, and a way to
> generate huge load.

I've worked on several battery powered devices and battery monitoring
is very hard to achieve without a deep understanding of the chemistry,
circuitry and the algorithms. Large current loads can cause the
battery voltage to drop and therefore there can be a significant
voltage drop between measuring the quiescent and the loaded battery
voltages. I once did try to implement an algorithm which took into
account the different battery voltage during heavy current drain but
it's hard to know how to interpret that data. One of the RFID systems
I worked on could run the user interface for days on a low battery but
a single RFID read would cause the system to die due to the internal
resistance current drop ...

One of the easiest ways to monitor the battery is with a coulomb
counting method (accumulate current going into and out of the battery)
e.g. "LTC4150 - Coulomb Counter/Battery Gas Gauge"
http://www.linear.com/pc/productDetail.jsp?navId=H0,C1,C1003,C1037,C1134,P2354

As long as you aren't draining very large amounts of current from the
battery, the accumulated current measurement should be almost equal to
the amp-hour rating of the battery.

Unfortunately the simple coulomb counting chips have the disadvantage
that the CPU has to be running to accumulate the pulses. Of course,
the pulses could wake the CPU from a suspend mode, but I'd rather not
do that just to add "one" to a counter ...

Finally we decided on a fully integrated "smart" battery monitor
device like the DS2782
http://www.maxim-ic.com/quick_view2.cfm/qv_pk/4779. This chip has
Linux device driver support, I got the driver from Ryan Mallon at
Bluewater Systems. It was fairly complex to set up and calibrate but
we now use it in a commercial product.

I recommend having a look at the datasheet for the DS2782 to see what
methods they use for determining the remaining charge in a battery and
to get an idea of the complexity of the problem.

Good luck!

Aras Vaichas

2009-12-15 03:02:36

by Bill Gatliff

[permalink] [raw]
Subject: Re: [POWER] battery calibration parameters from sysfs

Aras Vaichas wrote:
> Unfortunately the simple coulomb counting chips have the disadvantage
> that the CPU has to be running to accumulate the pulses. Of course,
> the pulses could wake the CPU from a suspend mode, but I'd rather not
> do that just to add "one" to a counter ...
>

Could you have the coulomb-counting chip connected to a tiny
microcontroller, or even a dedicated hardware counter? Then the main
CPU wouldn't need to wake as often, it could just ask the
microcontroller over I2C, or read/reset the hardware counter.


b.g.

--
Bill Gatliff
[email protected]

2009-12-15 23:25:06

by Aras Vaichas

[permalink] [raw]
Subject: Re: [POWER] battery calibration parameters from sysfs

2009/12/15 Bill Gatliff <[email protected]>:
> Aras Vaichas wrote:
>> Unfortunately the simple coulomb counting chips have the disadvantage
>> that the CPU has to be running to accumulate the pulses. Of course,
>> the pulses could wake the CPU from a suspend mode, but I'd rather not
>> do that just to add "one" to a counter ...
>>
>
> Could you have the coulomb-counting chip connected to a tiny
> microcontroller, or even a dedicated hardware counter? ?Then the main
> CPU wouldn't need to wake as often, it could just ask the
> microcontroller over I2C, or read/reset the hardware counter.
>
> b.g.

Yes, but in that case you might as well just purchase a coulomb
counter with a built-in accumulator and an I2C/SPI/microwire interface
save yourself some PCB space and cost (maybe)

Google for, say, "coulomb counter i2c" and you'll get something like
this: http://eu.st.com/stonline/products/literature/ds/15269.pdf as an
example

The only time we used a pulse-and-polarity-output coulomb counter was
with an ATmega128. The CPU had to run all the time in order to
maintain its RTC so we could use it to accumulate pulses as well. It
wasn't a Linux project though.

Aras

2009-12-15 23:31:39

by Stanislav Brabec

[permalink] [raw]
Subject: Re: [POWER] battery calibration parameters from sysfs

Aras Vaichas wrote:

> Yes, but in that case you might as well just purchase a coulomb
> counter with a built-in accumulator and an I2C/SPI/microwire interface
> save yourself some PCB space and cost (maybe)

Well, Pavel attempts to implement a "poor man's Coulomb counter" or at
least "poor man's Ampere meter" for devices that are not equipped with
any of it.

- We know the time.
- We know the backlight power consumption, it's dependent only on
brightness.
- We know how much eats the HDD and how long it is on.
- We know how much eats the CPU and companion chips (it is not as
stable, but it eats less).
- We don't know, how much USB host eats, but we know how much USB
clients claim to eat.
- Well, and we don't know how much eats CF and SD.

=> We can guess how many Coulombs the device already consumed. If the
Coulomb counting would be inaccurate, we can at least correct voltage ->
remaining energy table using current power consumption guess.


________________________________________________________________________
Stanislav Brabec
http://www.penguin.cz/~utx/zaurus

2009-12-16 09:40:23

by Andy Green

[permalink] [raw]
Subject: Re: [POWER] battery calibration parameters from sysfs

On 12/15/09 23:32, Somebody in the thread at some point said:

Hi -

>> Yes, but in that case you might as well just purchase a coulomb
>> counter with a built-in accumulator and an I2C/SPI/microwire interface
>> save yourself some PCB space and cost (maybe)
>
> Well, Pavel attempts to implement a "poor man's Coulomb counter" or at
> least "poor man's Ampere meter" for devices that are not equipped with
> any of it.

I think the "poor man's Coulomb counter" is a loser, the errors will
overwhelm you too rapidly. The estimated rate of discharge could work,
based on what clocks, regulators and so on are running, but I am not
sure how useful that number is really given you can't realistically
integrate it due to the big error it is bound to have.

I didn't see it mentioned yet but the biggest problem I saw with battery
state monitoring by voltage alone is what happens during charging: the
charger is artificially raising the voltage by an amount depending on
current limit in the charger and battery capacity level. That's what
you see when you go and look at battery voltage during charging.

Otherwise for L-ion batteries, looking at the voltage level alone,
filtered to remove GSM transmit slots etc, is really quite workable for
estimating charge status.

-Andy

2009-12-16 22:53:42

by Pavel Machek

[permalink] [raw]
Subject: Re: [POWER] battery calibration parameters from sysfs

On Mon 2009-12-14 12:12:47, Mark Brown wrote:
> On Sun, Dec 13, 2009 at 02:24:14PM +0100, Pavel Machek wrote:
>
> > > actual charger hardware. My main concern here is that battery
> > > performance monitoring has no pressing need to be in kernel and that
> > > pushing it into the kernel creates a barrier to implementing more
> > > advanced schemes in userspace, which is especially serious given how
> > > involved this needs to be in order to be accurate.
>
> > Well, kernel provides /proc/apm emulation and many systems still rely
> > on it. So it would be nice to provide something halfway-decent there.
>
> Unfortunately that's really painful in kernel since you really need to
> do state tracking over reboots, and even if you do that it's really
> not trivial.

No, I do not want to get _that_ advanced. But I'd really like to get
beyond "battery %age is linear function of measured battery voltage".

> > Plus you need to shutdown/suspend machine on battery critical. That
> > has to be in kernel and already needs those tricky parts.
>
> Power failure detection based on voltage drop is much more reasonable
> but it's a very different thing to general battery capacity
> estimation.

Not sure...

> Normally you'd want to do the power failure detection separately anyway,
> monitoring the system supply voltage rather than the battery voltage.

Well, that way you'll discharge batteries too much and kill them
rather quickly, no? What is "system supply voltage" for PDA class
system, anyway? I don't think zaurus has ADCs on anything else than
thermistor, AC in voltage, battery voltage...

> Something like "Measure Battery Capacity Precisely in Medical Design"
> by Bernd Krafthoefer in Power Electronics Technology Jan 2005 might be
> useful here.

Thanks, it looks interesting. I'm not sure if it will be possible to
apply on zaurus, but... (While measuring voltage my underestimate the
old battery, I'm afraid they may overestimate it in bad conditions;
energy left is battery is useless if battery can't supply enough
current to keep CPU happy, because its too cold).
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2009-12-18 08:49:19

by Pavel Machek

[permalink] [raw]
Subject: Re: [POWER] battery calibration parameters from sysfs

Hi!1


>>> Yes, but in that case you might as well just purchase a coulomb
>>> counter with a built-in accumulator and an I2C/SPI/microwire interface
>>> save yourself some PCB space and cost (maybe)

Hardware is already given.

>> Well, Pavel attempts to implement a "poor man's Coulomb counter" or at
>> least "poor man's Ampere meter" for devices that are not equipped with
>> any of it.
>
> I think the "poor man's Coulomb counter" is a loser, the errors will
> overwhelm you too rapidly. The estimated rate of discharge could
>> work,

Actually android phones do "poor man's Coulomb counter", and it seems
to mostly work.

> based on what clocks, regulators and so on are running, but I am not
> sure how useful that number is really given you can't realistically
> integrate it due to the big error it is bound to have.
...
> Otherwise for L-ion batteries, looking at the voltage level alone,
> filtered to remove GSM transmit slots etc, is really quite workable for
> estimating charge status.

Well, you have to compensate for backlight power; and yes, that's what
I'm trying to do.
Pavel

--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html