Individual O2 sensor readings

Anton Lundin glance at acc.umu.se
Wed Aug 26 14:24:33 PDT 2015


Sorry for not getting around to comment on this. Lots of random things
came in the way, but now i finally have some time to write you a anser.

On 01 July, 2015 - Jef Driesen wrote:

> On 2015-06-27 12:41, Anton Lundin wrote:
> >On 26 June, 2015 - Jef Driesen wrote:
> >>In order to support multiple values, we have to introduce some
> >>new structure
> >>that carries a sensor id (similar to DC_SAMPLE_PRESSURE):
> >>
> >>struct ppo2 {
> >>    unsigned int sensor;
> >>    double value;
> >>};
> >>
> >>And then we can easily deliver multiple DC_SAMPLE_PPO2 values,
> >>each with a
> >>different sensor id, to the application. But this obviously
> >>breaks backwards
> >>compatibility.
> >
> >I think we should _add_ a struct o2_sensor which contains sensor-id,
> >ppo2-value and mV-value, and keep the current double ppo2.
> 
> For the long term solution, I certainly agree a custom struct is the
> way to go. But what I would like to avoid is that we now add a new
> DC_SAMPLE_PPO2_SENSOR in order to not break backwards compatibility.
> But once v0.5 is out, I would like to start cleaning up mistake like
> this one. So it's not unlikely we'll be removing
> DC_SAMPLE_PPO2_SENSOR again and use our new struct in combination
> with the original DC_SAMPLE_PPO2 type. (Before you started this
> discussion, I planned to simply replace the single ppo2 field with a
> struct after the v0.5 release. That's why I didn't apply the ostc
> patch yet.)
> 

I saw that you pushed ppo2 code for the OSTC's. I don't really think
thats the best way to do it, and ill try to explain why i think so.

I think mixing the voted/consensus/average/real ppo2 with values from
individual sensors are confusing at best, and plain wrong at worst.

Eg. subsurface would currently grab and store the last callback value of
DC_SAMPLE_PPO2.

Think about the case where sensor 1 gives you 1.30 bar, sensor 2 gives
you 1.32 bar and sensor 3 whould say 0.40 bar.

In that case the voting would clearly say that sensor 3 is faulty, and
the true ppo2 would be calculated to be 1.31 bar, but the current code
whould trick subsurface into storing the last value, 0.40 bar, which is
plain wrong.

> Just out of curiosity, how do people use the millivolt value? That's
> something that depends on the sensor, which means you can't compare
> between different dive computers, right? I would expect that it's
> the ppo2 value you're interested in, because that's what you're
> really trying to measure. The fact that this corresponds to a
> certain millivolt value seems like some internal detail. Just like I
> want depth in meters (or millibar) and not some meaningless voltage.
> But I'm not a rebreather diver :-)

Those sensors are galvanic and give you a millivolt value as their
response to oxygen. With the calibration data that value is converted
into a ppo2 value, and the response in mV for certain ppo2 of o2 will
differ between sensors, even sensors who are from the same batch and
spent their hole life together in the same rebreather.


The mV value for a certan ppo2 will drop over time, as the cell grows
older. My grand plan was to play with some statistics once i had the
data to see of one could predict when a censor is about to fail, when
you have lots of samples from it over time.

> 
> >That way we keep backwards compability, and let the double ppo2
> >represent the calculated/voted "true" ppo2, and let the struct
> >o2_sensor represent the individual sensors.
> 
> Having two different ways to represent two types of ppo2 might be
> confusing. How about using a special id (e.g. DC_SENSOR_NONE) for
> the calculated/voted ppo2? That way way we don't need a different
> struct, and there is no ambiguity in interpretation:
> 
> <sample>
>    <ppo2 sensor="0">xxx</ppo2>
>    <ppo2 sensor="1">xxx</ppo2>
>    <ppo2 sensor="2">xxx</ppo2>
>    <ppo2 sensor="none">xxx</ppo2>
> <sample>
> 
> BTW, we already do that for tanks with the special DC_GASMIX_UNKNOWN id.
> 

I'd say that the concepts are so far apart that it would just be
confusing to mix them. Let the calculated/voted "true" ppo2 just be and
handle the individual sensors on the side.

Most times you wouldn't care about the real sensors, its just when trying
to do sensor analytics they become interesting.

> >>The alternative is to keep the current "double ppo2" field, and
> >>just relax
> >>the assumption that there can be only one DC_SAMPLE_PPO2 value
> >>per sample.
> >>That's what I did in the attached patch. Applications that are
> >>not prepared
> >>for multiple values, will automatically use only one of them
> >>(probably the
> >>last one). So I think that's a reasonable solution for now.
> >
> >You need the id<->value mapping to make something useful out of the
> >individual values.
> >
> >Eg. If one sensor goes bad and starts returning bogus values, you would
> >like to know which id that is, and not just some-id.
> 
> The mapping won't be lost. Because the order and number of the
> DC_SAMPLE_PPO2 values per sample will always be the same, the sensor
> id is equivalent to the index of the DC_SAMPLE_PPO2 value. So on the
> application side you can do something like this:
> 
> switch (type) {
> case DC_SAMPLE_TIME:
>     nsensors = 0; /⁠* New sample, reset the counter. */⁠
>     break;
> case DC_SAMPLE_PPO2:
>     fprintf (sampledata->fp, "   <ppo2 sensor=\"%u\">%.2f</ppo2>\n",
> nsensors, value.ppo2);
>     nsensors++;
>     break;
> }
> 

Doesn't look that clean to my eyes. I'd prefer different types, and that
also introduces the possibility to return mV values.

> >Also, you would like to know what the computer thought was the "true"
> >ppo2, vs. the raw values.
> 
> That's a good point, but right now this is a problem that does not
> exist yet. Right now there are dive computers that provide raw
> sensor data or a calculated value, but not both. (Unless we know how
> to translate the Shearwater's millivolt to ppo2.)
> 

Eh, doesn't the OSTC3 store both its "true" ppo2 and sensor data?

After reading the docco i think you're right. Wierd that they don't
store the ppo2 they used for their calculations anywhere.


> >>For the nitekq, I'm not 100% sure but I think it's indeed a
> >>calculated/voted
> >>ppo2 value. For the shearwater it's the average ppo2. I'm not
> >>sure whether
> >>that is an average over the o2 sensors, or a calculated value. I
> >>have the
> >>impression it depends on the dive mode, because the field contains a
> >>non-zero value for OC dives too.
> >
> >In subsurface we have a patch to not return those values in OC mode,
> >which i really think makes sense.
> 
> Or we need a type to indicate whether it's a calculated value (OC)
> vs a raw or voted value (CC)? Some people might argue they want the
> ppo2 value for OC dive too. But yes, your reasoning absolutely makes
> sense too. And this not only applies to ppo2 but also setpoint (for
> which I have a patch pending to implement this for the shearwaters).
> 

Hmm.. ppo2 values for OC dives are only intresting if you plan to run
your own deco model on the dive, and if you have a deco model that can
run on dc data, you can probably calculate that ppo2 yourself. Thats
what subsurface does.

I see no sane reason for exposing that ppo2 value on OC dives.

> >>The shearwaters do also record ppo2 data for up to three o2
> >>sensors, but the
> >>value is in millivolts, so it can't be directly interpreted as a
> >>ppo2 value.
> >>I assume it's possible to convert from millivolts to a ppo2
> >>value, because
> >>in the header there are several o2 sensor calibration fields
> >>present for
> >>each sensor (e.g. "Calibration status", "Calibration value" and "ADC
> >>Offset"). But I don't know how this calculation should be done.
> >>
> >
> >Its doable. ADC Offset is probably the offset in the Analog to
> >Digital chip,
> >and the Calibration status and Calibration value is probably the mV
> >response for a certain fO2 calibration gas.
> 
> This is the relevant info I have:
> 
> 16   O2 Sensor voting status.
> bit 0: Sensor 1
> bit1:  Sensor 2
> bit2:  Sensor 3
> 1 = voted in. 0 = voted out or not calibrated.
> 44   Is Single PPO2 Sensor. 1 = single sensor mode. 0 = Normal (3
> sensor) mode.

In firmware v29 they introduced a two sensor mode. I wonder how they
represent that.

> 86   Calibration Status (bit 0: Sensor 1, bit 1: Sensor 2, bit 2:
> Sensor 3). Bit set if sensor calibrated, bit is zero if calibration
> is failed or invalid.
> 87   Sensor 1 Calibration value: (Byte 1: MSB)
> 88   Sensor 1 Calibration value: (Byte 0: LSB)
> 89   Sensor 2 Calibration value: (Byte 1: MSB)
> 90   Sensor 2 Calibration value: (Byte 0: LSB)
> 91   Sensor 3 Calibration value: (Byte 1: MSB)
> 92   Sensor 3 Calibration value: (Byte 0: LSB)
> 93   Sensor 1 ADC Offset (Signed Integer)
> 94   Sensor 2 ADC Offset (Signed Integer)
> 95   Sensor 3 ADC Offset (Signed Integer)
> 

Do you might have some raw data available for me to take a look at?

Otherwise i might be able to hassle my good friend Rainer into dumping
some from his Petrel, but he's a sales guy so its a bit more work than
you sending me some raw data =)


Its my sort of fun figuring out how this works and produce some ppo2
values from this, and I think its doable.


> >I have hand some ideas about doing decay analyses on O2 sensors,
> >and for
> >that it would be great to follow how the mV value for the same ppo2
> >drops over time for a O2 sensor and thus being able to try to predict
> >when its time to replace it. I really don't know how feasible or
> >accurate such analysis would be but I would love to try to run the
> >numbers and see what i can come up with.
> >
> >Also trying to detect and warn about current limited sensors would be
> >an interesting project.
> >
> >So, id say a
> >struct o2_sensor {
> >	unsigned int sensors;
> >	double ppo2;
> >	double mV;
> >};
> >and a DC_SAMPLE_PPO2_SENSOR would make me a happy. Just set the
> >non-existant ppo2/mV to zero or -1.
> >
> >
> >The question is if libdivecomputer should just export the Shearwater
> >calibration data to the application and let it do any mV -> ppo2
> >calculations or if libdivecomputer should do those...
> 
> Assuming it's possible, I would say libdivecomputer should do this.
> Just like we convert depths stored in millibar or feet to meters.
> That's the only way to provide a consistent interface to the
> application.
> 

I'm fine with that.


//Anton


-- 
Anton Lundin	+46702-161604


More information about the devel mailing list