Mercurial > public > ostc4
comparison Small_CPU/Src/pressure.c @ 345:4093ac18b25c FlightMode_Improvment
Added function to evaluate the state of the surface pressure history memory
Activation of the computer during or short after landing caused a switch into divemode which could then not be left.
To solve this the history memory is evaluated for significant pressure changes as the would not be expected in "normal" condition. In case of such a event (unstable) the pressure limit to enter dive mode is set to an absolute value (instead of relativ in normal mode)
author | ideenmodellierer |
---|---|
date | Thu, 03 Oct 2019 21:26:46 +0200 |
parents | 37f45300bc2e |
children | ba53ab77f059 |
comparison
equal
deleted
inserted
replaced
344:3f09b283d993 | 345:4093ac18b25c |
---|---|
44 #define CMD_ADC_1024 0x04 // ADC OSR=1024 | 44 #define CMD_ADC_1024 0x04 // ADC OSR=1024 |
45 #define CMD_ADC_2048 0x06 // ADC OSR=2056 | 45 #define CMD_ADC_2048 0x06 // ADC OSR=2056 |
46 #define CMD_ADC_4096 0x08 // ADC OSR=4096 | 46 #define CMD_ADC_4096 0x08 // ADC OSR=4096 |
47 #define CMD_PROM_RD 0xA0 // Prom read command | 47 #define CMD_PROM_RD 0xA0 // Prom read command |
48 | 48 |
49 #define PRESSURE_SURFACE_MAX_MBAR (1070.0f) /* It is very unlikely that pressure at surface is greater than this value => clip to it */ | 49 /* remove comment to use a predefined profile for pressure changes instead of real world data */ |
50 #define PRESSURE_HISTORY_SIZE (8u) | 50 /* #define SIMULATE_PRESSURE */ |
51 #define PRESSURE_JUMP_VALID_MBAR (500.0f) /* values are measure several times a second => jumps > 5m very unlikely */ | 51 |
52 | 52 #define PRESSURE_SURFACE_MAX_MBAR (1070.0f) /* It is very unlikely that pressure at surface is greater than this value => clip to it */ |
53 #define PRESSURE_SURFACE_QUE (30u) /* history buffer [minutes] for past pressure measurements */ | 53 #define PRESSURE_HISTORY_SIZE (8u) |
54 #define PRESSURE_JUMP_VALID_MBAR (500.0f) /* values are measure several times a second => jumps > 5m very unlikely */ | |
55 | |
56 #define PRESSURE_SURFACE_QUE (30u) /* history buffer [minutes] for past pressure measurements */ | |
57 #define PRESSURE_SURFACE_EVA_WINDOW (15u) /* Number of entries evaluated during instability test. Used to avoid detection while dive enters water */ | |
58 #define PRESSURE_SURFACE_STABLE_LIMIT (10u) /* Define pressure as stable if delta (mBar) is below this value */ | |
59 #define PRESSURE_SURFACE_DETECT_STABLE_CNT (5u) /* Event count to detect stable condition */ | |
60 #define PRESSURE_SURFACE_UNSTABLE_LIMIT (50u) /* Define pressure as not stable if delta (mBar) is larger than this value */ | |
61 #define PRESSURE_SURFACE_DETECT_UNSTABLE_CNT (3u) /* Event count to detect unstable condition */ | |
62 | |
54 | 63 |
55 static uint16_t get_ci_by_coef_num(uint8_t coef_num); | 64 static uint16_t get_ci_by_coef_num(uint8_t coef_num); |
56 //void pressure_calculation_new(void); | 65 //void pressure_calculation_new(void); |
57 //void pressure_calculation_old(void); | 66 //void pressure_calculation_old(void); |
58 static void pressure_calculation_AN520_004_mod_MS5803_30BA__09_2015(void); | 67 static void pressure_calculation_AN520_004_mod_MS5803_30BA__09_2015(void); |
84 static float ambient_temperature = 0; | 93 static float ambient_temperature = 0; |
85 static float ambient_pressure_mbar = 1000.0; | 94 static float ambient_pressure_mbar = 1000.0; |
86 static float surface_pressure_mbar = 1000.0; | 95 static float surface_pressure_mbar = 1000.0; |
87 static float surface_ring_mbar[PRESSURE_SURFACE_QUE] = { 0 }; | 96 static float surface_ring_mbar[PRESSURE_SURFACE_QUE] = { 0 }; |
88 | 97 |
98 static uint8_t surface_pressure_writeIndex = 0; | |
99 static float surface_pressure_stable_value = 0; | |
100 static uint8_t surface_pressure_stable = 0; | |
101 | |
89 static float pressure_history_mbar[PRESSURE_HISTORY_SIZE]; | 102 static float pressure_history_mbar[PRESSURE_HISTORY_SIZE]; |
90 | 103 |
91 static uint8_t secondCounterSurfaceRing = 0; | 104 static uint8_t secondCounterSurfaceRing = 0; |
92 static uint8_t avgCount = 0; | 105 static uint8_t avgCount = 0; |
93 static float runningAvg = 0; | 106 static float runningAvg = 0; |
117 runningAvg = 0; | 130 runningAvg = 0; |
118 | 131 |
119 for(int i=0; i<PRESSURE_SURFACE_QUE; i++) | 132 for(int i=0; i<PRESSURE_SURFACE_QUE; i++) |
120 surface_ring_mbar[i] = ambient_pressure_mbar; | 133 surface_ring_mbar[i] = ambient_pressure_mbar; |
121 surface_pressure_mbar = ambient_pressure_mbar; | 134 surface_pressure_mbar = ambient_pressure_mbar; |
135 surface_pressure_writeIndex = 0; /* index of the oldest value in the ring buffer */ | |
122 } | 136 } |
123 } | 137 } |
124 | 138 |
125 void init_pressure_history(void) | 139 void init_pressure_history(void) |
126 { | 140 { |
128 { | 142 { |
129 pressure_history_mbar[i] = 1000.0; | 143 pressure_history_mbar[i] = 1000.0; |
130 } | 144 } |
131 } | 145 } |
132 | 146 |
133 | 147 uint8_t is_surface_pressure_stable(void) |
148 { | |
149 return surface_pressure_stable; | |
150 } | |
151 | |
152 float set_last_surface_pressure_stable(void) | |
153 { | |
154 surface_pressure_mbar = surface_pressure_stable_value; | |
155 return surface_pressure_stable_value; | |
156 } | |
157 | |
158 /* iterate backward through the history memory and evaluate the changes pressure changes during the last 30 minutes */ | |
159 void evaluate_surface_pressure() | |
160 { | |
161 uint8_t index; | |
162 float lastvalue; | |
163 uint8_t stablecnt = 0; | |
164 uint8_t unstablecnt = 0; | |
165 uint8_t EvaluationWindow = PRESSURE_SURFACE_QUE - PRESSURE_SURFACE_EVA_WINDOW; /* do not use the latest 15 values to avoid unstable condition due to something like fin handling */ | |
166 uint8_t EvaluatedValues = 0; | |
167 | |
168 lastvalue = surface_ring_mbar[surface_pressure_writeIndex]; | |
169 surface_pressure_stable_value = surface_ring_mbar[surface_pressure_writeIndex]; /* default: if no stable value is found return the oldest value */ | |
170 index = surface_pressure_writeIndex; | |
171 surface_pressure_stable = 1; | |
172 | |
173 if(index == 0) | |
174 { | |
175 index = PRESSURE_SURFACE_QUE - 1; | |
176 } | |
177 else | |
178 { | |
179 index = index - 1; | |
180 } | |
181 do | |
182 { | |
183 if((EvaluatedValues < EvaluationWindow) && | |
184 (fabs(surface_pressure_stable_value - surface_ring_mbar[index]) > PRESSURE_SURFACE_UNSTABLE_LIMIT)) /* unusual change during last 30 minutes */ | |
185 { | |
186 unstablecnt++; | |
187 if(unstablecnt > PRESSURE_SURFACE_DETECT_UNSTABLE_CNT) | |
188 { | |
189 surface_pressure_stable = 0; | |
190 } | |
191 } | |
192 /* search for a value which does not change for several iterations */ | |
193 if (fabs(lastvalue - surface_ring_mbar[index]) < PRESSURE_SURFACE_STABLE_LIMIT) | |
194 { | |
195 stablecnt++; | |
196 } | |
197 else | |
198 { | |
199 stablecnt = 0; | |
200 } | |
201 if ((stablecnt >= PRESSURE_SURFACE_DETECT_STABLE_CNT) && (surface_pressure_stable == 0)&&(surface_pressure_stable_value == surface_ring_mbar[surface_pressure_writeIndex])) /* pressure is unstable => search for new stable value */ | |
202 { | |
203 surface_pressure_stable_value = surface_ring_mbar[index]; | |
204 unstablecnt = 0; | |
205 } | |
206 | |
207 lastvalue = surface_ring_mbar[index]; | |
208 | |
209 if(index == 0) | |
210 { | |
211 index = PRESSURE_SURFACE_QUE - 1; | |
212 } | |
213 else | |
214 { | |
215 index = index - 1; | |
216 } | |
217 EvaluatedValues++; | |
218 } while (index != surface_pressure_writeIndex); | |
219 } | |
134 void update_surface_pressure(uint8_t call_rhythm_seconds) | 220 void update_surface_pressure(uint8_t call_rhythm_seconds) |
135 { | 221 { |
136 static uint8_t writeIndex = 0; /* Reinitialization will reset all entries to the same value => no need to reinit write index */ | |
137 | 222 |
138 | 223 |
139 if(is_init_pressure_done()) | 224 if(is_init_pressure_done()) |
140 { | 225 { |
141 runningAvg = (runningAvg * avgCount + ambient_pressure_mbar) / (avgCount +1); | 226 runningAvg = (runningAvg * avgCount + ambient_pressure_mbar) / (avgCount +1); |
144 | 229 |
145 if(secondCounterSurfaceRing >= 60) | 230 if(secondCounterSurfaceRing >= 60) |
146 { | 231 { |
147 if(runningAvg < PRESSURE_SURFACE_MAX_MBAR) | 232 if(runningAvg < PRESSURE_SURFACE_MAX_MBAR) |
148 { | 233 { |
149 surface_ring_mbar[writeIndex] = runningAvg; | 234 surface_ring_mbar[surface_pressure_writeIndex] = runningAvg; |
150 } | 235 } |
151 else | 236 else |
152 { | 237 { |
153 surface_ring_mbar[writeIndex] = PRESSURE_SURFACE_MAX_MBAR; | 238 surface_ring_mbar[surface_pressure_writeIndex] = PRESSURE_SURFACE_MAX_MBAR; |
154 } | 239 } |
155 writeIndex++; /* the write index is now pointing to the oldest value in the buffer which will be overwritten next time */ | 240 surface_pressure_writeIndex++; /* the write index is now pointing to the oldest value in the buffer which will be overwritten next time */ |
156 | 241 |
157 if(writeIndex == PRESSURE_SURFACE_QUE) | 242 if(surface_pressure_writeIndex == PRESSURE_SURFACE_QUE) |
158 { | 243 { |
159 writeIndex = 0; | 244 surface_pressure_writeIndex = 0; |
160 } | 245 } |
161 | 246 |
162 surface_pressure_mbar = surface_ring_mbar[writeIndex]; /* 30 minutes old measurement */ | 247 surface_pressure_mbar = surface_ring_mbar[surface_pressure_writeIndex]; /* 30 minutes old measurement */ |
163 | 248 |
164 secondCounterSurfaceRing = 0; | 249 secondCounterSurfaceRing = 0; |
165 avgCount = 1; /* use the current value as starting point but restart the weight decrement of the measurements */ | 250 avgCount = 1; /* use the current value as starting point but restart the weight decrement of the measurements */ |
166 } | 251 } |
252 evaluate_surface_pressure(); | |
167 } | 253 } |
168 } | 254 } |
169 | 255 |
170 #ifdef DEMOMODE | 256 #ifdef DEMOMODE |
171 float demo_modify_temperature_helper(float bottom_mbar_diff_to_surface) | 257 float demo_modify_temperature_helper(float bottom_mbar_diff_to_surface) |
423 } | 509 } |
424 return statusReturn; | 510 return statusReturn; |
425 } | 511 } |
426 | 512 |
427 | 513 |
514 #ifdef SIMULATE_PRESSURE | |
515 void pressure_simulation() | |
516 { | |
517 static uint32_t tickstart = 0; | |
518 static float pressure_sim_mbar = 0; | |
519 static uint32_t passedSecond = 0; | |
520 static uint32_t secondtick = 0; | |
521 | |
522 uint32_t lasttick = 0; | |
523 | |
524 | |
525 | |
526 if( tickstart == 0) | |
527 { | |
528 tickstart = HAL_GetTick(); /* init time stamp */ | |
529 secondtick = tickstart; | |
530 pressure_sim_mbar = 1000; | |
531 } | |
532 | |
533 lasttick = HAL_GetTick(); | |
534 if(time_elapsed_ms(secondtick,lasttick) > 1000) /* one second passed since last tick */ | |
535 { | |
536 secondtick = lasttick; | |
537 passedSecond++; | |
538 | |
539 #ifdef DIVE_AFTER_LANDING | |
540 if(passedSecond < 10) pressure_sim_mbar = 1000.0; /* stay stable for 10 seconds */ | |
541 else if(passedSecond < 300) pressure_sim_mbar -= 1.0; /* decrease pressure in 5 minutes target 770mbar => delta 330 */ | |
542 else if(passedSecond < 900) pressure_sim_mbar += 0.0; /*stay stable 10 minutes*/ | |
543 else if(passedSecond < 1500) pressure_sim_mbar += 0.5; /* return to 1 bar in 10 Minutes*/ | |
544 else if(passedSecond < 1800) pressure_sim_mbar += 0.0; /* 5 minutes break */ | |
545 else if(passedSecond < 2000) pressure_sim_mbar += 10.0; /* start dive */ | |
546 else if(passedSecond < 2300) pressure_sim_mbar += 0.0; /* stay on depth */ | |
547 else if(passedSecond < 2500) pressure_sim_mbar -= 10.0; /* return to surface */ | |
548 else pressure_sim_mbar = 1000.0; /* final state */ | |
549 #else /* short dive */ | |
550 if(passedSecond < 10) pressure_sim_mbar = 1000.0; /* stay stable for 10 seconds */ | |
551 else if(passedSecond < 180) pressure_sim_mbar += 10.0; /* Start dive */ | |
552 else if(passedSecond < 300) pressure_sim_mbar += 0.0; /*stay on depth*/ | |
553 else if(passedSecond < 460) pressure_sim_mbar -= 10.0; /* return to surface */ | |
554 else if(passedSecond < 600) pressure_sim_mbar += 0.0; /* stay */ | |
555 else if(passedSecond < 610) pressure_sim_mbar = 1000.0; /* get ready for second dive */ | |
556 else if(passedSecond < 780) pressure_sim_mbar += 10.0; /* Start dive */ | |
557 else if(passedSecond < 900) pressure_sim_mbar += 0.0; /*stay on depth*/ | |
558 else if(passedSecond < 1060) pressure_sim_mbar -= 10.0; /* return to surface */ | |
559 else if(passedSecond < 1200) pressure_sim_mbar += 0.0; /* stay */ | |
560 else pressure_sim_mbar = 1000.0; /* final state */ | |
561 #endif | |
562 } | |
563 | |
564 | |
565 ambient_pressure_mbar = pressure_sim_mbar; | |
566 ambient_temperature = 25.0; | |
567 return; | |
568 } | |
569 | |
570 #endif | |
571 | |
428 void pressure_calculation(void) | 572 void pressure_calculation(void) |
429 { | 573 { |
430 if(global.I2C_SystemStatus != HAL_OK) | 574 if(global.I2C_SystemStatus != HAL_OK) |
431 return; | 575 return; |
432 | 576 |
577 #ifdef SIMULATE_PRESSURE | |
578 pressure_simulation(); | |
579 #else | |
433 pressure_calculation_AN520_004_mod_MS5803_30BA__09_2015(); | 580 pressure_calculation_AN520_004_mod_MS5803_30BA__09_2015(); |
581 #endif | |
434 } | 582 } |
435 | 583 |
436 static uint8_t pressure_plausible(float pressurevalue) | 584 static uint8_t pressure_plausible(float pressurevalue) |
437 { | 585 { |
438 static uint8_t pressurewriteindex = 0; | 586 static uint8_t pressurewriteindex = 0; |
550 avgCnt++; /* by the measurement range of the sensor which is focused on under water pressure measurement */ | 698 avgCnt++; /* by the measurement range of the sensor which is focused on under water pressure measurement */ |
551 } | 699 } |
552 ambient_pressure_mbar = runningAvg; | 700 ambient_pressure_mbar = runningAvg; |
553 } | 701 } |
554 } | 702 } |
555 | |
556 | |
557 /* | |
558 void pressure_calculation_new(void) | |
559 { | |
560 #define POW2_8 (256) | |
561 #define POW2_17 (131072) | |
562 #define POW2_6 (64) | |
563 #define POW2_16 (65536) | |
564 #define POW2_7 (128) | |
565 #define POW2_23 (8388608) | |
566 #define POW2_21 (2097152) | |
567 #define POW2_15 (32768) | |
568 #define POW2_13 (8192) | |
569 #define POW2_37 (137438953472) | |
570 #define POW2_4 (16) | |
571 #define POW2_33 (8589934592) | |
572 #define POW2_3 (8) | |
573 | |
574 int32_t P; // compensated pressure value | |
575 int32_t T; // compensated temperature value | |
576 int32_t dT; // difference between actual and measured temperature | |
577 int64_t OFF; // offset at actual temperature | |
578 int64_t SENS; | |
579 | |
580 int32_t T2; | |
581 int64_t OFF2; | |
582 int64_t SENS2; | |
583 | |
584 dT = ((int32_t)D2) - ((int32_t)C[5]) * POW2_8; | |
585 OFF = ((int64_t)C[2]) * POW2_16 + ((int64_t)dT) * ((int64_t)C[4]) / POW2_7; | |
586 SENS = ((int64_t)C[1]) * POW2_15 + ((int64_t)dT) * ((int64_t)C[3]) / POW2_8; | |
587 | |
588 T = 2000 + (dT * ((int32_t)C[6])) / POW2_23; | |
589 | |
590 | |
591 if(T < 2000) // low temperature | |
592 { | |
593 T2 = 3 * dT * dT; | |
594 T2 /= POW2_33; | |
595 OFF2 = ((int64_t)T) - 2000; | |
596 OFF2 *= OFF2; | |
597 OFF2 *= 3; | |
598 OFF2 /= 2; | |
599 SENS2 = ((int64_t)T) - 2000; | |
600 SENS2 *= SENS2; | |
601 SENS2 *= 5; | |
602 SENS2 /= POW2_3; | |
603 } | |
604 else // high temperature | |
605 { | |
606 T2 = 7 * dT * dT; | |
607 T2 /= POW2_37; | |
608 OFF2 = ((int64_t)T) - 2000; | |
609 OFF2 *= OFF2; | |
610 OFF2 /= POW2_4; | |
611 SENS2 = 0; | |
612 } | |
613 | |
614 T = T - T2; | |
615 OFF = OFF - OFF2; | |
616 SENS = SENS - SENS2; | |
617 | |
618 P = (int32_t)(((((int64_t)D1) * SENS) / POW2_21 - OFF) / POW2_13); | |
619 | |
620 ambient_temperature = ((float)T) / 100; | |
621 ambient_pressure_mbar = ((float)P) / 10; | |
622 } | |
623 */ | |
624 | |
625 /* | |
626 void pressure_calculation_old(void) { | |
627 // | |
628 double ambient_temperature_centigrad = 0; | |
629 double ambient_pressure_decimbar = 0; | |
630 | |
631 // static for debug | |
632 static int64_t dt = 0; | |
633 static int64_t temp = 0; | |
634 static int64_t ms_off = 0; | |
635 static int64_t sens = 0; | |
636 // | |
637 static int64_t ms_off2 = 0; | |
638 static int64_t sens2 = 0; | |
639 static int64_t t2 = 0; | |
640 | |
641 if((D2 == 0) || (D1 == 0)) | |
642 return; | |
643 // | |
644 | |
645 // dT = D2 - C[5] * POW2_8; | |
646 // T = 2000 + (dT * C[6]) / POW2_23; | |
647 dt = (int64_t)D2 - C5_x_2p8; | |
648 //temp ; // in 10 milliGrad Celcius | |
649 ambient_temperature_centigrad = 2000 + dt * C[6] / 8388608; | |
650 | |
651 | |
652 if(ambient_temperature_centigrad < 2000) // low temperature | |
653 { | |
654 t2 = 3 * dt; | |
655 t2 *= dt; | |
656 t2 /= 8589934592; | |
657 ms_off2 = ambient_temperature_centigrad - 2000; | |
658 ms_off2 *= ms_off2; | |
659 sens2 = ms_off2; | |
660 ms_off2 *= 3; | |
661 ms_off2 /= 2; | |
662 sens2 *= 5; | |
663 sens2 /= 8; | |
664 } | |
665 else // high temperature | |
666 { | |
667 t2 = 7 * dt; | |
668 t2 *= dt; | |
669 t2 /= 137438953472; | |
670 ms_off2 = ambient_temperature_centigrad - 2000; | |
671 ms_off2 *= ms_off2; | |
672 ms_off2 /= 16; | |
673 sens2 = 0; | |
674 } | |
675 | |
676 | |
677 // | |
678 | |
679 // pressure | |
680 // OFF = C[2] * POW2_16 + dT * C[4] / POW2_7; | |
681 // SENS = C[1] * POW2_15 + dT * C[3] / POW2_8; | |
682 ms_off = C[4] * dt; | |
683 ms_off /= 128; | |
684 ms_off += C2_x_2p16; | |
685 // | |
686 sens = C[3] * dt; | |
687 sens /= 256; | |
688 sens += C1_x_2p15; | |
689 | |
690 // 2nd order correction | |
691 ambient_temperature_centigrad -= t2; | |
692 ms_off -= ms_off2; | |
693 sens -= sens2; | |
694 | |
695 ambient_temperature = ambient_temperature_centigrad / 100; | |
696 // P = (D1 * SENS / POW2_21 - OFF) / POW2_13; | |
697 temp = D1 * sens; | |
698 temp /= 2097152; | |
699 temp -= ms_off; | |
700 temp /= 8192; | |
701 ambient_pressure_decimbar = temp; // to float/double | |
702 ambient_pressure_mbar = ambient_pressure_decimbar / 10; | |
703 } | |
704 */ | |
705 | 703 |
706 | 704 |
707 /* taken from AN520 by meas-spec.com dated 9. Aug. 2011 | 705 /* taken from AN520 by meas-spec.com dated 9. Aug. 2011 |
708 * short and int are both 16bit according to AVR/GCC google results | 706 * short and int are both 16bit according to AVR/GCC google results |
709 */ | 707 */ |