# HG changeset patch # User Ideenmodellierer # Date 1614190706 -3600 # Node ID 7c73f066cd16a868f9387e9d4d2d2fb87a7a688f # Parent 68d95049f11ae17fe23f7e468c27650d9b24fd40 Enable sensor check for Analog PPO2 mode: Checks which may trigger a fallback warning were not activated in previous versions. Beside enabling the checks the test logic has been changed. Before the change an avarage was build automatically using the remaining both sensors if one sensor failed. The scenario that also one of the remaining sensors may be out of bounds was not covered. The new implementation allows an out of bounds detection for all sensors in parallel. In that special case the last valid value will be used until the diver takes action (Fallback warning) diff -r 68d95049f11a -r 7c73f066cd16 Discovery/Src/check_warning.c --- a/Discovery/Src/check_warning.c Tue Feb 23 21:58:18 2021 +0100 +++ b/Discovery/Src/check_warning.c Wed Feb 24 19:18:26 2021 +0100 @@ -184,8 +184,8 @@ if(!get_HUD_battery_voltage_V()) pDiveState->warnings.sensorLinkLost = 1; } - test_O2_sensor_values_outOfBounds(&pDiveState->warnings.sensorOutOfBounds[0], &pDiveState->warnings.sensorOutOfBounds[1], &pDiveState->warnings.sensorOutOfBounds[2]); } + test_O2_sensor_values_outOfBounds(&pDiveState->warnings.sensorOutOfBounds[0], &pDiveState->warnings.sensorOutOfBounds[1], &pDiveState->warnings.sensorOutOfBounds[2]); return pDiveState->warnings.sensorLinkLost + pDiveState->warnings.sensorOutOfBounds[0] + pDiveState->warnings.sensorOutOfBounds[1] diff -r 68d95049f11a -r 7c73f066cd16 Discovery/Src/tCCR.c --- a/Discovery/Src/tCCR.c Tue Feb 23 21:58:18 2021 +0100 +++ b/Discovery/Src/tCCR.c Wed Feb 24 19:18:26 2021 +0100 @@ -34,6 +34,7 @@ #include "data_exchange.h" #include "check_warning.h" #include "configuration.h" +#include /* Private types -------------------------------------------------------------*/ typedef struct @@ -47,6 +48,14 @@ uint16_t checksum; } SIrLink; +typedef enum +{ + sensorOK = 0, + sensorSuspect, + SensorOutOfBounds +} sensorTrustState_t; + + #define HUD_BABBLING_IDIOT (30u) /* 30 Bytes received without break */ #define HUD_RX_FRAME_LENGTH (15u) /* Length of a HUD data frame */ #define HUD_RX_FRAME_BREAK_MS (100u) /* Time used to detect a gap between two byte receptions => frame start */ @@ -55,6 +64,8 @@ #define BOTTLE_SENSOR_TIMEOUT (6000u) /* signal pressure budget as not received after 10 minutes (6000 * 100ms) */ +#define MAX_SENSOR_COMPARE_DEVIATION (0.15f) /* max deviation between two sensors allowed before their results are rated as suspect */ + /* Private variables ---------------------------------------------------------*/ static SIrLink receiveHUD[2]; static uint8_t boolHUDdata = 0; @@ -132,6 +143,9 @@ { uint8_t sensorNotActiveBinary; uint8_t sensorActive[3]; + sensorTrustState_t sensorState[3]; + uint8_t index; + // test1: user deactivation sensorNotActiveBinary = stateUsed->diveSettings.ppo2sensors_deactivated; @@ -154,6 +168,8 @@ // test2: mV of remaining sensors for(int i=0;i<3;i++) { + sensorState[i] = sensorOK; + if(sensorActive[i]) { if( (stateUsed->lifeData.sensorVoltage_mV[i] < 8) || @@ -196,78 +212,50 @@ } else { - uint8_t sensor_id_ordered[3]; - float difference[2]; - - if((stateUsed->lifeData.ppO2Sensor_bar[1] > stateUsed->lifeData.ppO2Sensor_bar[0])) - { - sensor_id_ordered[0] = 0; - sensor_id_ordered[1] = 1; - } - else - { - sensor_id_ordered[0] = 1; - sensor_id_ordered[1] = 0; - } - if(stateUsed->lifeData.ppO2Sensor_bar[2] > stateUsed->lifeData.ppO2Sensor_bar[sensor_id_ordered[1]]) + /* Check two or more of Three */ + /* compare every sensor with each other. If there is only one mismatch the value might be OK. In case both comparisons fail the sensor is out of bounds */ + if(fabsf(stateUsed->lifeData.ppO2Sensor_bar[0] - stateUsed->lifeData.ppO2Sensor_bar[1]) > MAX_SENSOR_COMPARE_DEVIATION) { - sensor_id_ordered[2] = 2; + sensorState[0]++; + sensorState[1]++; } - else + if(fabsf(stateUsed->lifeData.ppO2Sensor_bar[0] - stateUsed->lifeData.ppO2Sensor_bar[2]) > MAX_SENSOR_COMPARE_DEVIATION) { - sensor_id_ordered[2] = sensor_id_ordered[1]; - if(stateUsed->lifeData.ppO2Sensor_bar[2] > stateUsed->lifeData.ppO2Sensor_bar[sensor_id_ordered[0]]) - { - sensor_id_ordered[1] = 2; - } - else - { - sensor_id_ordered[1] = sensor_id_ordered[0]; - sensor_id_ordered[0] = 2; - } + sensorState[0]++; + sensorState[2]++; + } + if(fabsf(stateUsed->lifeData.ppO2Sensor_bar[1] - stateUsed->lifeData.ppO2Sensor_bar[2]) > MAX_SENSOR_COMPARE_DEVIATION) + { + sensorState[1]++; + sensorState[2]++; } - - difference[0] = stateUsed->lifeData.ppO2Sensor_bar[sensor_id_ordered[1]]- stateUsed->lifeData.ppO2Sensor_bar[sensor_id_ordered[0]]; - difference[1] = stateUsed->lifeData.ppO2Sensor_bar[sensor_id_ordered[2]]- stateUsed->lifeData.ppO2Sensor_bar[sensor_id_ordered[1]]; - - if((difference[0] > difference[1]) && (difference[0] > 0.15)) /* was 15cBar ==> 0.15 bar */ + for(index = 0; index < 3; index++) { - switch(sensor_id_ordered[0]) - { - case 0: - *outOfBouds1 = 1; - break; - case 1: - *outOfBouds2 = 1; - break; - case 2: - *outOfBouds3 = 1; - break; - } - } - else - if((difference[0] < difference[1]) && (difference[1] > 0.15)) - { - switch(sensor_id_ordered[2]) - { - case 0: - *outOfBouds1 = 1; - break; - case 1: - *outOfBouds2 = 1; - break; - case 2: - *outOfBouds3 = 1; - break; - } + if(sensorState[index] == SensorOutOfBounds) + { + switch(index) + { + case 0: + *outOfBouds1 = 1; + break; + case 1: + *outOfBouds2 = 1; + break; + case 2: + *outOfBouds3 = 1; + break; + default: + break; + } + } } } - } uint8_t get_ppO2SensorWeightedResult_cbar(void) { + static uint8_t lastValidValue = 0; int8_t sensorOutOfBound[3]; uint16_t result = 0; uint8_t count = 0; @@ -283,13 +271,15 @@ count++; } } - if(count == 0) // all sensors out of bounds! + if(count == 0) /* all sensors out of bounds! => return last valid value as workaround till diver takes action */ { set_warning_fallback(); + retVal = lastValidValue; } else { retVal = (uint8_t)(result / count); + lastValidValue = retVal; } return retVal; }