comparison Small_CPU/Src/pressure.c @ 335:c11ce8c885d3 PressureMeasure_Improvment

Use average calculation for pressure: precondition was that pressure values jittered +- 10 HPa from one capture (once a second) to the other. Basically pressure is measured several times a second => using these values in an additional history calculation reduces the jitter down to +-1 per second Additionaly a similar function has been added to the surface pressure capture to further reduce the jitter in long therm measurements (once a minute)
author ideenmodellierer
date Tue, 13 Aug 2019 21:46:26 +0200
parents b4c578caaafb
children 37f45300bc2e
comparison
equal deleted inserted replaced
334:143fe85f82a2 335:c11ce8c885d3
47 #define CMD_PROM_RD 0xA0 // Prom read command 47 #define CMD_PROM_RD 0xA0 // Prom read command
48 48
49 #define PRESSURE_HISTORY_SIZE (8u) 49 #define PRESSURE_HISTORY_SIZE (8u)
50 #define PRESSURE_JUMP_VALID_MBAR (500.0f) /* values are measure several times a second => jumps > 5m very unlikely */ 50 #define PRESSURE_JUMP_VALID_MBAR (500.0f) /* values are measure several times a second => jumps > 5m very unlikely */
51 51
52 #define PRESSURE_SURFACE_QUE (30u) /* history buffer [minutes] for past pressure measurements */
53
52 static uint16_t get_ci_by_coef_num(uint8_t coef_num); 54 static uint16_t get_ci_by_coef_num(uint8_t coef_num);
53 //void pressure_calculation_new(void); 55 //void pressure_calculation_new(void);
54 //void pressure_calculation_old(void); 56 //void pressure_calculation_old(void);
55 static void pressure_calculation_AN520_004_mod_MS5803_30BA__09_2015(void); 57 static void pressure_calculation_AN520_004_mod_MS5803_30BA__09_2015(void);
56 static uint8_t crc4(uint16_t n_prom[]); 58 static uint8_t crc4(uint16_t n_prom[]);
77 */ 79 */
78 80
79 static float ambient_temperature = 0; 81 static float ambient_temperature = 0;
80 static float ambient_pressure_mbar = 1000.0; 82 static float ambient_pressure_mbar = 1000.0;
81 static float surface_pressure_mbar = 1000.0; 83 static float surface_pressure_mbar = 1000.0;
82 static float surface_ring_mbar[31] = { 0 }; 84 static float surface_ring_mbar[PRESSURE_SURFACE_QUE] = { 0 };
83 85
84 static float pressure_history_mbar[PRESSURE_HISTORY_SIZE]; 86 static float pressure_history_mbar[PRESSURE_HISTORY_SIZE];
85 87
86 uint8_t secondCounterSurfaceRing = 0; 88 uint8_t secondCounterSurfaceRing = 0;
87 89
101 } 103 }
102 104
103 105
104 void init_surface_ring(void) 106 void init_surface_ring(void)
105 { 107 {
106 surface_ring_mbar[0] = 0; 108 if(surface_ring_mbar[0] == 0) /* only initialize once. Keep value in place in case of an i2c recovery */
107 for(int i=1; i<31; i++) 109 {
108 surface_ring_mbar[i] = ambient_pressure_mbar; 110 for(int i=0; i<PRESSURE_SURFACE_QUE; i++)
109 surface_pressure_mbar = ambient_pressure_mbar; 111 surface_ring_mbar[i] = ambient_pressure_mbar;
112 surface_pressure_mbar = ambient_pressure_mbar;
113 }
110 } 114 }
111 115
112 void init_pressure_history(void) 116 void init_pressure_history(void)
113 { 117 {
114 for(int i=0; i<PRESSURE_HISTORY_SIZE; i++) 118 for(int i=0; i<PRESSURE_HISTORY_SIZE; i++)
115 { 119 {
116 pressure_history_mbar[i] = 1000.0; 120 pressure_history_mbar[i] = 1000.0;
117 } 121 }
118 } 122 }
119 123
120 /* the ring has one place with 0 124
121 * after that comes the oldest value
122 * the new pressure is written in this hole
123 * the oldest value is read and then the new hole
124 */
125 void update_surface_pressure(uint8_t call_rhythm_seconds) 125 void update_surface_pressure(uint8_t call_rhythm_seconds)
126 { 126 {
127 secondCounterSurfaceRing += call_rhythm_seconds; 127 static uint8_t writeIndex = 0; /* Reinitialization will reset all entries to the same value => no need to reinit write index */
128 128 static uint8_t avgCount = 0;
129 if(secondCounterSurfaceRing < 60) 129 static float runningAvg = 0;
130 return; 130
131
132 secondCounterSurfaceRing = 0;
133
134 if(is_init_pressure_done()) 131 if(is_init_pressure_done())
135 { 132 {
136 int hole; 133 runningAvg = (runningAvg * avgCount + ambient_pressure_mbar) / (avgCount +1);
137 for(hole=30;hole>0;hole--) 134 avgCount++;
138 if(surface_ring_mbar[hole] == 0) { break; } 135 secondCounterSurfaceRing += call_rhythm_seconds;
139 136
140 surface_ring_mbar[hole] = ambient_pressure_mbar; 137 if(secondCounterSurfaceRing >= 60)
141 138 {
142 hole++; 139 surface_ring_mbar[writeIndex] = runningAvg;
143 if(hole > 30) 140 writeIndex++; /* the write index is now pointing to the oldest value in the buffer which will be overwritten next time */
144 hole = 0; 141
145 surface_pressure_mbar = surface_ring_mbar[hole]; 142 if(writeIndex == PRESSURE_SURFACE_QUE)
146 surface_ring_mbar[hole] = 0; 143 {
144 writeIndex = 0;
145 }
146
147 surface_pressure_mbar = surface_ring_mbar[writeIndex]; /* 30 minutes old measurement */
148
149 secondCounterSurfaceRing = 0;
150 avgCount = 1; /* use the current value as starting point but restart the weight decrement of the measurements */
151 }
147 } 152 }
148 } 153 }
149 154
150 #ifdef DEMOMODE 155 #ifdef DEMOMODE
151 float demo_modify_temperature_helper(float bottom_mbar_diff_to_surface) 156 float demo_modify_temperature_helper(float bottom_mbar_diff_to_surface)
447 return retval; 452 return retval;
448 } 453 }
449 454
450 static void pressure_calculation_AN520_004_mod_MS5803_30BA__09_2015(void) 455 static void pressure_calculation_AN520_004_mod_MS5803_30BA__09_2015(void)
451 { 456 {
457 static float runningAvg = 0;
458 static uint8_t avgCnt = 0;
459
452 uint32_t local_D1; // ADC value of the pressure conversion 460 uint32_t local_D1; // ADC value of the pressure conversion
453 uint32_t local_D2; // ADC value of the temperature conversion 461 uint32_t local_D2; // ADC value of the temperature conversion
454 int32_t local_Px10; // compensated pressure value 462 int32_t local_Px10; // compensated pressure value
455 int32_t local_Tx100; // compensated temperature value 463 int32_t local_Tx100; // compensated temperature value
456 int64_t local_dT; // int32_t, difference between actual and measured temperature 464 int64_t local_dT; // int32_t, difference between actual and measured temperature
514 ambient_temperature = ((float)local_Tx100) / 100; 522 ambient_temperature = ((float)local_Tx100) / 100;
515 523
516 calc_pressure = ((float)local_Px10) / 10; 524 calc_pressure = ((float)local_Px10) / 10;
517 if(pressure_plausible(calc_pressure)) 525 if(pressure_plausible(calc_pressure))
518 { 526 {
519 ambient_pressure_mbar = calc_pressure; 527 runningAvg = (avgCnt * runningAvg + calc_pressure) / (avgCnt + 1);
528 if (avgCnt < 10) /* build an average considering the last measurements to a a weight "1 of 10" */
529 { /* Main reason for this is the jitter of up to +-10 HPa in surface mode which is caused */
530 avgCnt++; /* by the measurement range of the sensor which is focused on under water pressure measurement */
531 }
532 ambient_pressure_mbar = runningAvg;
520 } 533 }
521 } 534 }
522 535
523 536
524 /* 537 /*