Re: Sensor result representation.


Marcus Shawcroft <marcus.shawcroft@...>
 

Hi Bogdan,


My thoughts inline...

On 29 November 2016 at 11:41, Davidoaia, Bogdan M
<bogdan.m.davidoaia(a)intel.com> wrote:

As you pointed out, there is no fixed rule for sensor value type. The reason for the flexibility is that each driver computes values using their own formula, so it may be more convenient to use a certain type.

We didn't want to use double everywhere, because floating point operations come with a cost.
Indeed, on some platforms the use of double will come with a very
significant code size, performance and power implication.

However some sensors, such as the Grove temperature sensor uses logarithm to compute values, so doubles are needed.
Interresting. That sounds like a detail for the grove temperature
sensor driver to hide. If(f) temperature sensors were defined to
return a fixed point representation then a driver would if necessary
have the option of using floating point arithmetic internally (or
using a variety of other floating point avoidance strategies). (I
went looking for the driver to take a peek, but can;t find it, do we
have a driver this sensor yet?)

I'm reluctant to enforce a fixed type to be returned by the drivers, as this may result in some conversions and loss of precision if apps require types different from the default.
As a compromise, the sensor API could offer a function for converting a generic sensor_value struct to a specific value type. This way, the app can decide what type it wants to use, without having to write the code for converting between value types.

What are your thoughts on such an approach?
I'm concerned that there are drawbacks to this approach:

It has the effect of undermining application portability as a concept
in a platform OS. It offloads the responsibility to normalize results
presented in different formats to the application. Agreed such
formatting is straight forward and calling a helper to do the
formatting is trivial. But many application builders will neglect to
call the conversion helper, because they don't need to. They will
build their application against one set of devices and it just works!
When they switch devices, or someone else runs the application to
another platform it will break because they forgot to call the result
format futzing helper functions after getting results from the driver.

In effect the flexibility in the API makes it possible, (and even
encourages) applications that are not portable across zephyr
platforms.

Many drivers will be added to the tree that make un-necessary use of
potentially expensive operations (we have 4 examples already just
among the temperature drivers, see below). For folks that don't care
about power this is a none issue, for folks that do care, they have no
way around the issue.

Looking at the 4 temp drivers we currently have in tree that report
double results:

lsm6ds0: Converts an integer value to double performance a double /
and a double +
lps25hb: Converts integer->double, performs double / and double +
th02: Converts integer->double, performs double / and double +
lsm9ds0: Performs all internal computation in integer form then
converts to double to return the value.

None of these drivers actually need double arithmetic, and the last
one is only converting to double in order to present the result. All
of these drivers can be trivially be adjusted to avoid floating point
operations completely, returning INT_PLUS_MICRO with no loss of
precision and no impact from the implied loss of dynamic range.

We should try to keep the public facing APIs as simple and consistent
as possible in order to simplify applications and maximize their
portability (across boards/socs/devices).

Many (if not the majority) of IOT shaped applications are likely to be
sensitive to footprint and power. Folks building in that space, on
some platforms, are going to be sensitive to the unnecessary use of
floating point arithmetic. The folks who don't care about power,
won't mind (or notice) the additional conversion from fixed point to
floating point if they choose to build their application in floating
point.

For temperature, I'm struggling to see real work devices where
type_int__plus_micro does not provide sufficient precision or we need
the additional dynamic range of double. I suspect that if we looked at
each of the other channel types in detail we would find the same, ie
for most type_int_plus_micro is good enough and for the rest
type_double is necessary.

Aside from defining specific formats for specific channel types, there
are other simplifications possible:

We currently have 3 different fixed point representations and one
floating point representation, I think there are some straight forward
simplifications possible that result in no loss of precision, no loss
of dynamic range and are trivial in terms of additional conversion
cost compared to the cost of dealing with different representations:

1) TYPE_INT and TYPE_INT_PLUS_MICRO are identical except that TYPE_INT
indicates that the umicro part of TYPE_INT_PLUS_MICRO is 0. Hence we
can drop TYPE_INT and use TYPE_INT_PLUS_MICRO instead setting umicro
= 0 explicitily.

2) TYPE_INT_PLUS_MICRO and SENSOR_VALUE_TYPE_Q16_16 differ only in
precision. Both are passed in the same sized data structure. There
are no instances of the latter in master. We could drop Q16_16 from
sensor.h now and have all future need for a fixed point representation
use TYPE_INT_PLUS_MICRO

If we do 1 and 2 above we end up with 1 fixed point representation and
1 floating point representation. We get the benefit of simplifying
the interface and there is a trivial amount of code to change in the
process.


Cheers
/Marcus

Join devel@lists.zephyrproject.org to automatically receive all group messages.