Individual O2 sensor readings

Jef Driesen jef at libdivecomputer.org
Wed Jul 1 06:22:03 PDT 2015


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.)

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 :-)

> 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.

>> 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;
}

> 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.)

>> 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).

>> 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.
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)

> 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.

Jef


More information about the devel mailing list