Nowadays Subsurface have a way to represent individual o2 sensor values, but none of the libdivecomputer backends export such.
The diverite_nitekq and shearwater_predator backends have support for exposing DC_SAMPLE_PPO2 samples, which looks to be the calculated / voted PPO2.
The hwOS-based HW computers have such sensor values stored, and probably the Shearwater ext devices to. I was thinking about implementing support for the hwOS based devices, and was thinking if anyone have some preference on how such values should be represented in libdivecomputer?
Should we go for DC_SAMPLE_PPO2_SENSOR1 or something like that to expose the individual sensor values? Or do anyone else have some other, better, idea?
//Anton
On 2015-06-25 10:28, Anton Lundin wrote:
Nowadays Subsurface have a way to represent individual o2 sensor values, but none of the libdivecomputer backends export such.
The diverite_nitekq and shearwater_predator backends have support for exposing DC_SAMPLE_PPO2 samples, which looks to be the calculated / voted PPO2.
The hwOS-based HW computers have such sensor values stored, and probably the Shearwater ext devices to. I was thinking about implementing support for the hwOS based devices, and was thinking if anyone have some preference on how such values should be represented in libdivecomputer?
Should we go for DC_SAMPLE_PPO2_SENSOR1 or something like that to expose the individual sensor values? Or do anyone else have some other, better, idea?
The DC_SAMPLE_PPO2 sample is intended for o2 sensors. But when we added this type, we didn't take into account the fact that there are typically multiple o2 sensors on a rebreather. That's why I haven't implemented this yet for the OSTC (I have the necessary code already lying around, see attached patch).
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.
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.
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.
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.
Jef
On 26 June, 2015 - Jef Driesen wrote:
On 2015-06-25 10:28, Anton Lundin wrote:
Nowadays Subsurface have a way to represent individual o2 sensor values, but none of the libdivecomputer backends export such.
The diverite_nitekq and shearwater_predator backends have support for exposing DC_SAMPLE_PPO2 samples, which looks to be the calculated / voted PPO2.
The hwOS-based HW computers have such sensor values stored, and probably the Shearwater ext devices to. I was thinking about implementing support for the hwOS based devices, and was thinking if anyone have some preference on how such values should be represented in libdivecomputer?
Should we go for DC_SAMPLE_PPO2_SENSOR1 or something like that to expose the individual sensor values? Or do anyone else have some other, better, idea?
The DC_SAMPLE_PPO2 sample is intended for o2 sensors. But when we added this type, we didn't take into account the fact that there are typically multiple o2 sensors on a rebreather. That's why I haven't implemented this yet for the OSTC (I have the necessary code already lying around, see attached patch).
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.
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.
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.
Also, you would like to know what the computer thought was the "true" ppo2, vs. the raw values.
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.
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.
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...
//Anton
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
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
On 26 August, 2015 - Anton Lundin wrote:
On 01 July, 2015 - Jef Driesen wrote:
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)
Btw. Where are the mV values stored?
And are there any fO2 calibration gas value stored anywhere?
The calibrations are done as a single point calibration, eg. This sensors gives a mV response of X for a known gas with a fO2 of Y at pressure Z.
From that the sensor is assumed to give a linear mV response to
different ppO2's.
//Anton
On 2015-08-26 23:24, Anton Lundin wrote:
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:
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.
Yes, you are absolutely right. The current OSTC implementation was only intended as a temporary solution, until we have a better way to deal with multiple O2 sensors (with a proper struct).
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 certainly sounds like an interesting research project, but what I'm trying to figure out is whether the average CCR diver would be interested in the mV values or not. The main target of libdivecomputer are logbook applications, not scientific research projects. That's why we return depths in meter, and not whatever value the underlying depth sensor gives you. So my question is: why should O2 sensors be treated different in this regard?
Just to be clear, this doesn't mean we can't include the mV values along with the ppO2 value. I'm just trying to get a better understanding of the need for this info.
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.
The idea behind my proposal was that in both cases we are dealing with ppO2. Only the source of the value is different: a value measured by an O2 sensor (CC), a voted value over the available sensors (CC), or even a calculated value based on depth and active gasmix (OC). Hence the use of the same type, but with an indicator for the source.
But I also understand that you want to make a very clear distinction between the measured values, and the calculated/voted value used for decompression calculations.
If you look at the existing DC_SAMPLE_XXX types, you can divide them into two distinct categories: data in the first group is obtained from a real sensor (e.g. depth, pressure, temperature, etc), while data in the second group is calculated by the dive computer (e.g. setpoint, cns, deco, etc). Originally, the DC_SAMPLE_PPO2 type was intended for sensor data.
Most times you wouldn't care about the real sensors, its just when trying to do sensor analytics they become interesting.
Are you referring to the mV values here, or the measured ppO2 in general?
I assumed the primary use case for having the individual sensor values was mainly to be able to spot defective sensors. An occasional outlier, is probably not a big deal. That's what the voting is for. But if one sensor is wrong too often, that's probably a good indication to replace it. Is that what you mean with sensor analytics? Or are you referring to the research about the degradation of the sensor over time?
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.
Well, I never said this was pretty :-) But as I said above, this was something for a temporary solution.
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.
Unlike other manufacturers, we have access to the firmware source code, so we can always do the voting ourselves :-)
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.
You could also say that for sample values like CNS and DECO. If you have your own deco model, you can easily calculate those yourself. But isn't the point here that you want to show the data reported by the dive computer? Because the deco model of the dive computer will not necessary be the same. On the other hand, calculating ppO2 is maybe not going to produce very different results. After all it's just: ppO2 = Pabs * fO2. That's something worth checking. If the value reported by the dive computer is always identical to the calculated value, then there is indeed very little reason to keep it.
In firmware v29 they introduced a two sensor mode. I wonder how they represent that.
I assume they just leave the third sensor to zero or 0xFFFF.
Jef