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