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