Mercurial > public > ostc4
comparison Discovery/Src/tCCR.c @ 634:7c73f066cd16
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)
author | Ideenmodellierer |
---|---|
date | Wed, 24 Feb 2021 19:18:26 +0100 |
parents | 64bf41faab83 |
children | 66c8a4ff9fc4 |
comparison
equal
deleted
inserted
replaced
633:68d95049f11a | 634:7c73f066cd16 |
---|---|
32 #include "ostc.h" | 32 #include "ostc.h" |
33 #include "data_central.h" | 33 #include "data_central.h" |
34 #include "data_exchange.h" | 34 #include "data_exchange.h" |
35 #include "check_warning.h" | 35 #include "check_warning.h" |
36 #include "configuration.h" | 36 #include "configuration.h" |
37 #include <math.h> | |
37 | 38 |
38 /* Private types -------------------------------------------------------------*/ | 39 /* Private types -------------------------------------------------------------*/ |
39 typedef struct | 40 typedef struct |
40 { | 41 { |
41 uint8_t hud_firmwareVersion; | 42 uint8_t hud_firmwareVersion; |
45 uint8_t temp1; | 46 uint8_t temp1; |
46 uint16_t battery_voltage_mV; | 47 uint16_t battery_voltage_mV; |
47 uint16_t checksum; | 48 uint16_t checksum; |
48 } SIrLink; | 49 } SIrLink; |
49 | 50 |
51 typedef enum | |
52 { | |
53 sensorOK = 0, | |
54 sensorSuspect, | |
55 SensorOutOfBounds | |
56 } sensorTrustState_t; | |
57 | |
58 | |
50 #define HUD_BABBLING_IDIOT (30u) /* 30 Bytes received without break */ | 59 #define HUD_BABBLING_IDIOT (30u) /* 30 Bytes received without break */ |
51 #define HUD_RX_FRAME_LENGTH (15u) /* Length of a HUD data frame */ | 60 #define HUD_RX_FRAME_LENGTH (15u) /* Length of a HUD data frame */ |
52 #define HUD_RX_FRAME_BREAK_MS (100u) /* Time used to detect a gap between two byte receptions => frame start */ | 61 #define HUD_RX_FRAME_BREAK_MS (100u) /* Time used to detect a gap between two byte receptions => frame start */ |
53 #define HUD_RX_START_DELAY_MS (500u) /* Delay for start of RX function to avoid start of reception while a transmission is ongoing. */ | 62 #define HUD_RX_START_DELAY_MS (500u) /* Delay for start of RX function to avoid start of reception while a transmission is ongoing. */ |
54 /* Based on an assumed cycle time by the sensor of 1 second. Started at time of last RX */ | 63 /* Based on an assumed cycle time by the sensor of 1 second. Started at time of last RX */ |
55 | 64 |
56 #define BOTTLE_SENSOR_TIMEOUT (6000u) /* signal pressure budget as not received after 10 minutes (6000 * 100ms) */ | 65 #define BOTTLE_SENSOR_TIMEOUT (6000u) /* signal pressure budget as not received after 10 minutes (6000 * 100ms) */ |
57 | 66 |
67 #define MAX_SENSOR_COMPARE_DEVIATION (0.15f) /* max deviation between two sensors allowed before their results are rated as suspect */ | |
68 | |
58 /* Private variables ---------------------------------------------------------*/ | 69 /* Private variables ---------------------------------------------------------*/ |
59 static SIrLink receiveHUD[2]; | 70 static SIrLink receiveHUD[2]; |
60 static uint8_t boolHUDdata = 0; | 71 static uint8_t boolHUDdata = 0; |
61 static uint8_t data_old__lost_connection_to_HUD = 1; | 72 static uint8_t data_old__lost_connection_to_HUD = 1; |
62 | 73 |
130 | 141 |
131 void test_O2_sensor_values_outOfBounds(int8_t * outOfBouds1, int8_t * outOfBouds2, int8_t * outOfBouds3) | 142 void test_O2_sensor_values_outOfBounds(int8_t * outOfBouds1, int8_t * outOfBouds2, int8_t * outOfBouds3) |
132 { | 143 { |
133 uint8_t sensorNotActiveBinary; | 144 uint8_t sensorNotActiveBinary; |
134 uint8_t sensorActive[3]; | 145 uint8_t sensorActive[3]; |
146 sensorTrustState_t sensorState[3]; | |
147 uint8_t index; | |
148 | |
135 | 149 |
136 // test1: user deactivation | 150 // test1: user deactivation |
137 sensorNotActiveBinary = stateUsed->diveSettings.ppo2sensors_deactivated; | 151 sensorNotActiveBinary = stateUsed->diveSettings.ppo2sensors_deactivated; |
138 | 152 |
139 for(int i=0;i<3;i++) | 153 for(int i=0;i<3;i++) |
152 } | 166 } |
153 | 167 |
154 // test2: mV of remaining sensors | 168 // test2: mV of remaining sensors |
155 for(int i=0;i<3;i++) | 169 for(int i=0;i<3;i++) |
156 { | 170 { |
171 sensorState[i] = sensorOK; | |
172 | |
157 if(sensorActive[i]) | 173 if(sensorActive[i]) |
158 { | 174 { |
159 if( (stateUsed->lifeData.sensorVoltage_mV[i] < 8) || | 175 if( (stateUsed->lifeData.sensorVoltage_mV[i] < 8) || |
160 (stateUsed->lifeData.sensorVoltage_mV[i] > 250)) | 176 (stateUsed->lifeData.sensorVoltage_mV[i] > 250)) |
161 { | 177 { |
194 if(!sensorActive[2]) | 210 if(!sensorActive[2]) |
195 *outOfBouds3 = 1; | 211 *outOfBouds3 = 1; |
196 } | 212 } |
197 else | 213 else |
198 { | 214 { |
199 uint8_t sensor_id_ordered[3]; | 215 /* Check two or more of Three */ |
200 float difference[2]; | 216 /* 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 */ |
201 | 217 if(fabsf(stateUsed->lifeData.ppO2Sensor_bar[0] - stateUsed->lifeData.ppO2Sensor_bar[1]) > MAX_SENSOR_COMPARE_DEVIATION) |
202 if((stateUsed->lifeData.ppO2Sensor_bar[1] > stateUsed->lifeData.ppO2Sensor_bar[0])) | 218 { |
203 { | 219 sensorState[0]++; |
204 sensor_id_ordered[0] = 0; | 220 sensorState[1]++; |
205 sensor_id_ordered[1] = 1; | 221 } |
206 } | 222 if(fabsf(stateUsed->lifeData.ppO2Sensor_bar[0] - stateUsed->lifeData.ppO2Sensor_bar[2]) > MAX_SENSOR_COMPARE_DEVIATION) |
207 else | 223 { |
208 { | 224 sensorState[0]++; |
209 sensor_id_ordered[0] = 1; | 225 sensorState[2]++; |
210 sensor_id_ordered[1] = 0; | 226 } |
211 } | 227 if(fabsf(stateUsed->lifeData.ppO2Sensor_bar[1] - stateUsed->lifeData.ppO2Sensor_bar[2]) > MAX_SENSOR_COMPARE_DEVIATION) |
212 if(stateUsed->lifeData.ppO2Sensor_bar[2] > stateUsed->lifeData.ppO2Sensor_bar[sensor_id_ordered[1]]) | 228 { |
213 { | 229 sensorState[1]++; |
214 sensor_id_ordered[2] = 2; | 230 sensorState[2]++; |
215 } | 231 } |
216 else | 232 for(index = 0; index < 3; index++) |
217 { | 233 { |
218 sensor_id_ordered[2] = sensor_id_ordered[1]; | 234 if(sensorState[index] == SensorOutOfBounds) |
219 if(stateUsed->lifeData.ppO2Sensor_bar[2] > stateUsed->lifeData.ppO2Sensor_bar[sensor_id_ordered[0]]) | 235 { |
220 { | 236 switch(index) |
221 sensor_id_ordered[1] = 2; | 237 { |
222 } | 238 case 0: |
223 else | 239 *outOfBouds1 = 1; |
224 { | 240 break; |
225 sensor_id_ordered[1] = sensor_id_ordered[0]; | 241 case 1: |
226 sensor_id_ordered[0] = 2; | 242 *outOfBouds2 = 1; |
227 } | 243 break; |
228 } | 244 case 2: |
229 | 245 *outOfBouds3 = 1; |
230 difference[0] = stateUsed->lifeData.ppO2Sensor_bar[sensor_id_ordered[1]]- stateUsed->lifeData.ppO2Sensor_bar[sensor_id_ordered[0]]; | 246 break; |
231 difference[1] = stateUsed->lifeData.ppO2Sensor_bar[sensor_id_ordered[2]]- stateUsed->lifeData.ppO2Sensor_bar[sensor_id_ordered[1]]; | 247 default: |
232 | 248 break; |
233 if((difference[0] > difference[1]) && (difference[0] > 0.15)) /* was 15cBar ==> 0.15 bar */ | 249 } |
234 { | 250 } |
235 switch(sensor_id_ordered[0]) | 251 } |
236 { | 252 } |
237 case 0: | |
238 *outOfBouds1 = 1; | |
239 break; | |
240 case 1: | |
241 *outOfBouds2 = 1; | |
242 break; | |
243 case 2: | |
244 *outOfBouds3 = 1; | |
245 break; | |
246 } | |
247 } | |
248 else | |
249 if((difference[0] < difference[1]) && (difference[1] > 0.15)) | |
250 { | |
251 switch(sensor_id_ordered[2]) | |
252 { | |
253 case 0: | |
254 *outOfBouds1 = 1; | |
255 break; | |
256 case 1: | |
257 *outOfBouds2 = 1; | |
258 break; | |
259 case 2: | |
260 *outOfBouds3 = 1; | |
261 break; | |
262 } | |
263 } | |
264 } | |
265 | |
266 } | 253 } |
267 | 254 |
268 | 255 |
269 uint8_t get_ppO2SensorWeightedResult_cbar(void) | 256 uint8_t get_ppO2SensorWeightedResult_cbar(void) |
270 { | 257 { |
258 static uint8_t lastValidValue = 0; | |
271 int8_t sensorOutOfBound[3]; | 259 int8_t sensorOutOfBound[3]; |
272 uint16_t result = 0; | 260 uint16_t result = 0; |
273 uint8_t count = 0; | 261 uint8_t count = 0; |
274 uint8_t retVal = 0; | 262 uint8_t retVal = 0; |
275 | 263 |
281 { | 269 { |
282 result += stateUsed->lifeData.ppO2Sensor_bar[i] * 100.0; /* convert centibar used by HUB */ | 270 result += stateUsed->lifeData.ppO2Sensor_bar[i] * 100.0; /* convert centibar used by HUB */ |
283 count++; | 271 count++; |
284 } | 272 } |
285 } | 273 } |
286 if(count == 0) // all sensors out of bounds! | 274 if(count == 0) /* all sensors out of bounds! => return last valid value as workaround till diver takes action */ |
287 { | 275 { |
288 set_warning_fallback(); | 276 set_warning_fallback(); |
277 retVal = lastValidValue; | |
289 } | 278 } |
290 else | 279 else |
291 { | 280 { |
292 retVal = (uint8_t)(result / count); | 281 retVal = (uint8_t)(result / count); |
282 lastValidValue = retVal; | |
293 } | 283 } |
294 return retVal; | 284 return retVal; |
295 } | 285 } |
296 | 286 |
297 | 287 |