Reshuffle CCR voting logic and minor clean ups

Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Robert C. Helling 2014-10-14 10:46:40 +02:00 committed by Dirk Hohndel
parent 4cdb80c4cd
commit 34bb461c3d
2 changed files with 36 additions and 69 deletions

6
dive.c
View file

@ -1537,12 +1537,14 @@ int gasmix_distance(const struct gasmix *a, const struct gasmix *b)
extern void fill_pressures(struct gas_pressures *pressures, const double amb_pressure, const struct gasmix *mix, double po2) extern void fill_pressures(struct gas_pressures *pressures, const double amb_pressure, const struct gasmix *mix, double po2)
{ {
if (po2) { // This is probably a CCR dive where pressures->o2 is defined if (po2) { // This is probably a CCR dive where pressures->o2 is defined
if (po2 >= amb_pressure || get_o2(mix) == 1000) if (po2 >= amb_pressure || get_o2(mix) == 1000) {
pressures->o2 = amb_pressure; pressures->o2 = amb_pressure;
else pressures->n2 = pressures->he = 0.0;
} else {
pressures->o2 = po2; pressures->o2 = po2;
pressures->he = (amb_pressure - pressures->o2) * (double)get_he(mix) / (1000 - get_o2(mix)); pressures->he = (amb_pressure - pressures->o2) * (double)get_he(mix) / (1000 - get_o2(mix));
pressures->n2 = amb_pressure - pressures->o2 - pressures->he; pressures->n2 = amb_pressure - pressures->o2 - pressures->he;
}
} else { } else {
// Open circuit dives: no gas pressure values available, they need to be calculated // Open circuit dives: no gas pressure values available, they need to be calculated
pressures->o2 = get_o2(mix) / 1000.0 * amb_pressure; // These calculations are also used if the CCR calculation above.. pressures->o2 = get_o2(mix) / 1000.0 * amb_pressure; // These calculations are also used if the CCR calculation above..

View file

@ -4,6 +4,7 @@
#include "gettext.h" #include "gettext.h"
#include <limits.h> #include <limits.h>
#include <string.h> #include <string.h>
#include <assert.h>
#include "dive.h" #include "dive.h"
#include "display.h" #include "display.h"
@ -832,76 +833,40 @@ void calculate_deco_information(struct dive *dive, struct divecomputer *dc, stru
* there are and the differences among the readings from these sensors. * there are and the differences among the readings from these sensors.
*/ */
double calculate_ccr_po2(struct plot_data *entry, struct divecomputer *dc) { double calculate_ccr_po2(struct plot_data *entry, struct divecomputer *dc) {
double sensor_j, sump, midp, minp, maxp; double sump = 0.0, midp, minp = 999.9, maxp = -999.9;
double diff_limit = 100; // The limit beyond which O2 sensor differences are considered significant (default = 100 mbar) double diff_limit = 100; // The limit beyond which O2 sensor differences are considered significant (default = 100 mbar)
int num_of_diffs; // The number of unacceptable differences among the ogygen sensor partial pressure measurements int i, j, np = 0;
int i, j, np;
bool maxdif = false, mindif = false;
struct gas_pressures *pressures = &(entry->pressures);
// Estimate the most reliable PO2, given the different oxygen partial pressure values from the O2 sensors for (i=0; i < dc->no_o2sensors; i++)
switch (dc->no_o2sensors) { if (entry->o2sensor[i]) { // Valid reading
case 2: { // For 2 sensors: take the mean value of the two partial pressure sensors. ++np;
for (np = 0, sump = 0, j = 0; j < 2; j++) { // This calculation allows that for some samples sump += entry->o2sensor[i];
if (entry->o2sensor[j]) { // (especially at start of dive) with an inactive sensor,the minp = MIN(minp, entry->o2sensor[i]);
np++; // sensor(s) with zero values are not used. maxp = MAX(maxp, entry->o2sensor[i]);
sump = sump + entry->o2sensor[j];
} }
} switch (np) {
if (np > 0) // if there is at least one sensor value case 0: // Uhoh
return (sump / np); // then calculate the mean, else return entry->o2setpoint;
case 1: // Return what we have
return sump;
case 2: // Take the average
return sump / 2;
case 3: // Voting logic
if (2 * maxp - sump + minp < diff_limit) { // Upper difference acceptable...
if (2 * minp - sump + maxp) // ...and lower difference acceptable
return sump / 3;
else else
return 0; // if there are no valid sensor values, calculate po2 on the basis of depth. return (sump - minp) / 2;
break; } else {
} if (2 * minp - sump + maxp) // ...but lower difference acceptable
case 3: { /* For 3 sensors: diff_limit is the critical limit indicating unacceptable difference (default = 100 mbar). return (sump - maxp) / 2;
* a) If all three readings are within a range of diff_limit, then take the mean value. This
* includes the case where reading 1 is within diff_limit of reading 2; and reading 2 is
* within diff_limit of reading 3, but readings 1 and 3 differ by more than diff_limit.
* b) If one sensor differs by more than diff-limit from the other two, then take the mean
* of the closer two sensors and disregard the 3rd sensor, considered as an outlier.
* c) If all 3 sensors differ by more than diff_limit then take the mean of the 3 readings. */
for (minp = 9999999999, maxp = -1, sump = 0, j = 0; j < 3; j++) {
sensor_j = entry->o2sensor[j];
if (sensor_j < minp)
minp = sensor_j;
if (sensor_j > maxp)
maxp = sensor_j;
sump = sump + sensor_j; // Find min, max and mid of p-values
}
midp = sump - minp - maxp;
num_of_diffs = 0;
if ((maxp - midp) > diff_limit) {
num_of_diffs++;
maxdif = true;
}
if ((midp - minp) > diff_limit) {
num_of_diffs++;
mindif = true; // Find no of unacceptable differences
}
switch (num_of_diffs) {
case 0:
;
case 2: {
return (sump / 3); // 0 or 2 unacceptable differences: find mean of three values.
break;
}
case 1: {
if (maxdif) // 1 unacceptable difference: find mean of two closer values
return ((minp + midp) / 2);
else if (mindif)
return ((maxp + midp) / 2);
break;
}
} //switch no_of_diffs
}
default: { // if # of sensors is 1 or unknown, simply take the value of the first sensor
if (entry->o2sensor[0])
return (entry->o2sensor[0]);
else else
return 0; // if no sensor value found, then go to next section, esimating PO2 using depth. return sump / 3;
}
default: // This should not happen
assert(np <= 3);
return 0.0;
} }
} // switch
} }
static void calculate_gas_information_new(struct dive *dive, struct plot_info *pi) static void calculate_gas_information_new(struct dive *dive, struct plot_info *pi)