comparison Small_CPU/Src/externalInterface.c @ 1065:1f2067cad41b Icon_Integration

Mixed sensor operation improvment: A peak detector has been added to the adc measurement to avoid interferance while UART sensor are taking measurement while adc is active. The previous approach to shift adc into time windows where no UART were active had to be replaced because for the CO2 sensor is continously taking samples without providing a sync signal. In addition the UART MUX switching behavior has been improved (potential rx data received from previous sensor is discarded during channel switch etc.)
author Ideenmodellierer
date Mon, 16 Feb 2026 21:27:26 +0100
parents a3f42192da0f
children e0ba2b29dc1f
comparison
equal deleted inserted replaced
1064:449e0f8f23d0 1065:1f2067cad41b
73 static uint8_t externalInterfacePresent = 0; 73 static uint8_t externalInterfacePresent = 0;
74 static uint8_t delayAdcConversion = 0; 74 static uint8_t delayAdcConversion = 0;
75 static uint32_t startTickADC = 0; 75 static uint32_t startTickADC = 0;
76 76
77 float externalChannel_mV[MAX_ADC_CHANNEL]; 77 float externalChannel_mV[MAX_ADC_CHANNEL];
78 float externalChannel_History_mV[MAX_ADC_CHANNEL][3];
78 static uint8_t externalV33_On = 0; 79 static uint8_t externalV33_On = 0;
79 static uint8_t externalADC_On = 0; 80 static uint8_t externalADC_On = 0;
80 static uint8_t externalUART_Protocol = 0; 81 static uint8_t externalUART_Protocol = 0;
81 static uint16_t externalCO2Value; 82 static uint16_t externalCO2Value;
82 static uint16_t externalCO2SignalStrength; 83 static uint16_t externalCO2SignalStrength;
146 externalAutoDetect = DETECTION_OFF; 147 externalAutoDetect = DETECTION_OFF;
147 148
148 for(index = 0; index < MAX_ADC_CHANNEL; index++) 149 for(index = 0; index < MAX_ADC_CHANNEL; index++)
149 { 150 {
150 externalChannel_mV[index] = 0.0; 151 externalChannel_mV[index] = 0.0;
152 externalChannel_History_mV[index][0] = 0.0;
153 externalChannel_History_mV[index][1] = 0.0;
154 externalChannel_History_mV[index][2] = 0.0;
151 } 155 }
152 memset(externalInterface_SensorState,UART_COMMON_INIT,sizeof(externalInterface_SensorState)); 156 memset(externalInterface_SensorState,UART_COMMON_INIT,sizeof(externalInterface_SensorState));
153 externalInface_MapUartToLegacyADC(SensorMap); 157 externalInface_MapUartToLegacyADC(SensorMap);
154 activeUartChannel = 0xFF; 158 activeUartChannel = 0xFF;
155 } 159 }
180 { 184 {
181 if(time_elapsed_ms(startTickADC, HAL_GetTick()) > ADC_CYCLE_INTERVAL_MS) 185 if(time_elapsed_ms(startTickADC, HAL_GetTick()) > ADC_CYCLE_INTERVAL_MS)
182 { 186 {
183 if(delayAdcConversion) 187 if(delayAdcConversion)
184 { 188 {
185 if(UART_isComActive(activeUartChannel) == 0) 189 externalInterface_StartConversion(activeChannel);
186 { 190 delayAdcConversion = 0;
187 externalInterface_StartConversion(activeChannel); 191 timeoutCnt = 0;
188 delayAdcConversion = 0;
189 }
190 } 192 }
191 else if(I2C_Master_Receive(DEVICE_EXTERNAL_ADC, recBuf, ADC_ANSWER_LENGTH) == HAL_OK) 193 else if(I2C_Master_Receive(DEVICE_EXTERNAL_ADC, recBuf, ADC_ANSWER_LENGTH) == HAL_OK)
192 { 194 {
193 if((recBuf[ANSWER_CONFBYTE_INDEX] & ADC_START_CONVERSION) == 0) /* !ready set => received data contains new value */ 195 if((recBuf[ANSWER_CONFBYTE_INDEX] & ADC_START_CONVERSION) == 0) /* !ready set => received data contains new value */
194 { 196 {
197 if(nextChannel == MAX_ADC_CHANNEL) 199 if(nextChannel == MAX_ADC_CHANNEL)
198 { 200 {
199 nextChannel = 0; 201 nextChannel = 0;
200 } 202 }
201 203
202 while((psensorMap[nextChannel] != SENSOR_ANALOG) && (nextChannel != activeChannel)) 204 while((psensorMap[nextChannel] != SENSOR_ANALOG) && (nextChannel != 0))
203 { 205 {
204 if(nextChannel == MAX_ADC_CHANNEL) 206 if(nextChannel == MAX_ADC_CHANNEL)
205 { 207 {
206 nextChannel = 0; 208 nextChannel = 0;
207 startTickADC = HAL_GetTick(); 209 break;
208 } 210 }
209 else 211 else
210 { 212 {
211 nextChannel++; 213 nextChannel++;
212 } 214 }
213 } 215 }
214 216
215 activeChannel = nextChannel; 217 activeChannel = nextChannel;
216 if(activeChannel == 0) 218 if(activeChannel == 0)
217 { 219 {
220 startTickADC = HAL_GetTick();
218 delayAdcConversion = 1; /* wait for next cycle interval */ 221 delayAdcConversion = 1; /* wait for next cycle interval */
219 } 222 }
220 else 223 else
221 { 224 {
222 if(UART_isComActive(activeUartChannel) == 0) 225 externalInterface_StartConversion(activeChannel);
223 {
224 externalInterface_StartConversion(activeChannel);
225 }
226 else
227 {
228 delayAdcConversion = 1;
229 }
230 } 226 }
231 timeoutCnt = 0; 227 timeoutCnt = 0;
232 } 228 }
233 } 229
234 230 if(timeoutCnt++ >= ADC_TIMEOUT)
235 if(timeoutCnt++ >= ADC_TIMEOUT) 231 {
236 { 232 externalInterface_StartConversion(activeChannel);
237 externalInterface_StartConversion(activeChannel); 233 delayAdcConversion = 0;
238 delayAdcConversion = 0; 234 timeoutCnt = 0;
239 timeoutCnt = 0; 235 }
240 } 236 }
241 } 237 }
242 } 238 }
243 return retval; 239 return retval;
244 } 240 }
245 float externalInterface_CalculateADCValue(uint8_t channel) 241 float externalInterface_CalculateADCValue(uint8_t channel)
246 { 242 {
247 int32_t rawvalue = 0; 243 int32_t rawvalue = 0;
248 float retValue = 0.0; 244 float retValue = 0.0;
245 float newValue = 0.0;
249 if(channel < MAX_ADC_CHANNEL) 246 if(channel < MAX_ADC_CHANNEL)
250 { 247 {
251 248
252 rawvalue = ((recBuf[0] << 16) | (recBuf[1] << 8) | (recBuf[2])); 249 rawvalue = ((recBuf[0] << 16) | (recBuf[1] << 8) | (recBuf[2]));
253 250
260 } 257 }
261 else 258 else
262 { 259 {
263 rawvalue &= 0x0000FFFF; 260 rawvalue &= 0x0000FFFF;
264 } 261 }
265 externalChannel_mV[channel] = ADC_REF_VOLTAGE_MV * 2.0 / (float) pow(2,ADC_RESOLUTION_16BIT_VALUE); /* calculate bit resolution */ 262 newValue = ADC_REF_VOLTAGE_MV * 2.0 / (float) pow(2,ADC_RESOLUTION_16BIT_VALUE); /* calculate bit resolution */
266 break; 263 break;
267 case ADC_RESOLUTION_18BIT: if(rawvalue & (0x1 << (ADC_RESOLUTION_18BIT_VALUE-1))) /* MSB set => negative number */ 264 case ADC_RESOLUTION_18BIT: if(rawvalue & (0x1 << (ADC_RESOLUTION_18BIT_VALUE-1))) /* MSB set => negative number */
268 { 265 {
269 rawvalue |= 0xFFFE0000; /* set MSB for int32 */ 266 rawvalue |= 0xFFFE0000; /* set MSB for int32 */
270 } 267 }
271 externalChannel_mV[channel] = ADC_REF_VOLTAGE_MV * 2.0 / (float) pow(2,ADC_RESOLUTION_18BIT_VALUE); /* calculate bit resolution */ 268 newValue = ADC_REF_VOLTAGE_MV * 2.0 / (float) pow(2,ADC_RESOLUTION_18BIT_VALUE); /* calculate bit resolution */
272 break; 269 break;
273 default: rawvalue = 0; 270 default: rawvalue = 0;
274 break; 271 break;
275 } 272 }
276 externalChannel_mV[channel] = externalChannel_mV[channel] * rawvalue / ADC_GAIN_8_VALUE; 273 newValue = newValue * rawvalue / ADC_GAIN_8_VALUE;
274
275 externalChannel_History_mV[channel][0] = externalChannel_History_mV[channel][1]; /* oldest value */
276 externalChannel_History_mV[channel][1] = externalChannel_History_mV[channel][2]; /* return value */
277 externalChannel_History_mV[channel][2] = newValue;
278
279 if((externalChannel_History_mV[channel][1] > externalChannel_History_mV[channel][0]) && (externalChannel_History_mV[channel][1] > externalChannel_History_mV[channel][2])) /* peak condition */
280 {
281 externalChannel_History_mV[channel][1] = (externalChannel_History_mV[channel][0] + externalChannel_History_mV[channel][2]) / 2.0; /* build avarage as replacement value */
282 }
283 externalChannel_mV[channel] = externalChannel_History_mV[channel][1];
277 retValue = externalChannel_mV[channel]; 284 retValue = externalChannel_mV[channel];
278 } 285 }
279 return retValue; 286 return retValue;
280 } 287 }
281 float getExternalInterfaceChannel(uint8_t channel) 288 float getExternalInterfaceChannel(uint8_t channel)
452 } 459 }
453 460
454 /* The supported sensors from GSS have different scaling factors depending on their accuracy. The factor may be read out of the sensor */ 461 /* The supported sensors from GSS have different scaling factors depending on their accuracy. The factor may be read out of the sensor */
455 void externalInterface_SetCO2Scale(float CO2Scale) 462 void externalInterface_SetCO2Scale(float CO2Scale)
456 { 463 {
457 if((CO2Scale == 10) || (CO2Scale == 100)) 464 if((CO2Scale == 0.0) || (CO2Scale == 10.0) || (CO2Scale == 100.0))
458 { 465 {
459 externalCO2Scale = CO2Scale; 466 externalCO2Scale = CO2Scale;
460 } 467 }
461 } 468 }
462 float externalInterface_GetCO2Scale() 469 float externalInterface_GetCO2Scale()
498 } 505 }
499 506
500 uint16_t externalInterface_GetCO2SignalStrength(void) 507 uint16_t externalInterface_GetCO2SignalStrength(void)
501 { 508 {
502 return externalCO2SignalStrength; 509 return externalCO2SignalStrength;
503 }
504
505
506 void externalInterface_SetCO2State(uint16_t state)
507 {
508 externalCO2Status = state;
509 }
510
511 uint16_t externalInterface_GetCO2State(void)
512 {
513 return externalCO2Status;
514 } 510 }
515 511
516 void externalInterface_SetBottlePressure(uint8_t bottle, uint8_t bar) 512 void externalInterface_SetBottlePressure(uint8_t bottle, uint8_t bar)
517 { 513 {
518 if(bottle < PRESSURE_BOTTLE_CNT) 514 if(bottle < PRESSURE_BOTTLE_CNT)
700 #endif 696 #endif
701 uint8_t index = 0; 697 uint8_t index = 0;
702 698
703 uint8_t cntSensor = 0; 699 uint8_t cntSensor = 0;
704 uint8_t cntUARTSensor = 0; 700 uint8_t cntUARTSensor = 0;
705 #ifdef ENABLE_CO2_SUPPORT
706 uint8_t cmdString[10];
707 uint8_t cmdLength = 0;
708 #endif
709 701
710 if(externalAutoDetect != DETECTION_OFF) 702 if(externalAutoDetect != DETECTION_OFF)
711 { 703 {
712 switch(externalAutoDetect) 704 switch(externalAutoDetect)
713 { 705 {
834 tmpSensorMap[uartMuxChannel - 1 + EXT_INTERFACE_MUX_OFFSET] = SENSOR_NONE; 826 tmpSensorMap[uartMuxChannel - 1 + EXT_INTERFACE_MUX_OFFSET] = SENSOR_NONE;
835 uartMuxChannel = 1; 827 uartMuxChannel = 1;
836 tmpSensorMap[EXT_INTERFACE_MUX_OFFSET] = SENSOR_CO2; 828 tmpSensorMap[EXT_INTERFACE_MUX_OFFSET] = SENSOR_CO2;
837 externalInterface_SensorState[EXT_INTERFACE_MUX_OFFSET] = UART_COMMON_INIT; 829 externalInterface_SensorState[EXT_INTERFACE_MUX_OFFSET] = UART_COMMON_INIT;
838 externalInterface_CheckBaudrate(SENSOR_CO2); 830 externalInterface_CheckBaudrate(SENSOR_CO2);
839 uartCo2_SendCmd(CO2CMD_MODE_POLL, cmdString, &cmdLength);
840 } 831 }
841 break; 832 break;
842 case DETECTION_CO2_0: 833 case DETECTION_CO2_0:
843 case DETECTION_CO2_1: 834 case DETECTION_CO2_1:
844 case DETECTION_CO2_2: 835 case DETECTION_CO2_2:
858 activeUartChannel = uartMuxChannel; 849 activeUartChannel = uartMuxChannel;
859 tmpSensorMap[uartMuxChannel - 1 + EXT_INTERFACE_MUX_OFFSET] = SENSOR_NONE; 850 tmpSensorMap[uartMuxChannel - 1 + EXT_INTERFACE_MUX_OFFSET] = SENSOR_NONE;
860 tmpSensorMap[EXT_INTERFACE_MUX_OFFSET + uartMuxChannel] = SENSOR_CO2; 851 tmpSensorMap[EXT_INTERFACE_MUX_OFFSET + uartMuxChannel] = SENSOR_CO2;
861 externalInterface_SensorState[EXT_INTERFACE_MUX_OFFSET + uartMuxChannel] = UART_COMMON_INIT; 852 externalInterface_SensorState[EXT_INTERFACE_MUX_OFFSET + uartMuxChannel] = UART_COMMON_INIT;
862 externalInterface_CheckBaudrate(SENSOR_CO2); 853 externalInterface_CheckBaudrate(SENSOR_CO2);
863 uartCo2_SendCmd(CO2CMD_MODE_POLL, cmdString, &cmdLength);
864 externalAutoDetect++; 854 externalAutoDetect++;
865 uartMuxChannel++; 855 uartMuxChannel++;
866 } 856 }
867 else 857 else
868 { 858 {
1150 uint8_t index = 0; 1140 uint8_t index = 0;
1151 static uint8_t timeToTrigger = 0; 1141 static uint8_t timeToTrigger = 0;
1152 uint32_t tick = HAL_GetTick(); 1142 uint32_t tick = HAL_GetTick();
1153 uint8_t *pmap = externalInterface_GetSensorMapPointer(0); 1143 uint8_t *pmap = externalInterface_GetSensorMapPointer(0);
1154 uint8_t forceMuxChannel = 0; 1144 uint8_t forceMuxChannel = 0;
1145 static uint8_t flushUART = 0;
1155 1146
1156 1147
1157 if(externalInterfaceMuxReqIntervall != 0xFFFF) 1148 if(externalInterfaceMuxReqIntervall != 0xFFFF)
1158 { 1149 {
1159 if(activeUartChannel == 0xFF) 1150 if(activeUartChannel == 0xFF)
1179 } 1170 }
1180 } 1171 }
1181 1172
1182 if(externalInterface_SensorState[activeSensorId] != UART_COMMON_INIT) 1173 if(externalInterface_SensorState[activeSensorId] != UART_COMMON_INIT)
1183 { 1174 {
1184 UART_ReadData(pmap[activeSensorId], 0); 1175 UART_ReadData(pmap[activeSensorId], flushUART);
1185 UART_WriteData(&Uart1Ctrl); 1176 UART_WriteData(&Uart1Ctrl);
1177 flushUART = 0;
1186 } 1178 }
1187 if(externalInterface_SensorState[activeSensorId] == UART_COMMON_INIT) 1179 if(externalInterface_SensorState[activeSensorId] == UART_COMMON_INIT)
1188 { 1180 {
1189 lastRequestTick = tick; 1181 lastRequestTick = tick;
1190 TriggerTick = tick - 10; /* just to make sure control is triggered */ 1182 TriggerTick = tick - 10; /* just to make sure control is triggered */
1191 timeToTrigger = 1; 1183 timeToTrigger = 1;
1192 retryRequest = 0; 1184 retryRequest = 0;
1193 } 1185 }
1194 else if(((retryRequest == 0) && (pmap[activeUartChannel + EXT_INTERFACE_MUX_OFFSET] != SENSOR_SENTINEL) /* timeout or error */ 1186 else if(((retryRequest == 0) && (pmap[activeUartChannel + EXT_INTERFACE_MUX_OFFSET] != SENSOR_SENTINEL)) /* timeout or error */
1195 && (((time_elapsed_ms(lastRequestTick,tick) > (TIMEOUT_SENSOR_ANSWER)) && (externalInterface_SensorState[activeSensorId] != UART_O2_IDLE)) /* retry if no answer after half request interval */ 1187 && (((time_elapsed_ms(lastRequestTick,tick) > (TIMEOUT_SENSOR_ANSWER)) && (externalInterface_SensorState[activeSensorId] != UART_COMMON_IDLE)) /* retry if no answer after half request interval */
1196 || (externalInterface_SensorState[activeSensorId] == UART_O2_ERROR)))) 1188 || (externalInterface_SensorState[activeSensorId] == UART_COMMON_ERROR)))
1197 { 1189 {
1198 /* The channel switch will cause the sensor to respond with an error message. */ 1190 /* The channel switch will cause the sensor to respond with an error message. */
1199 /* The sensor needs ~30ms to recover before he is ready to receive the next command => transmission delay needed */ 1191 /* The sensor needs ~30ms to recover before he is ready to receive the next command => transmission delay needed */
1200 1192
1201 TriggerTick = tick; 1193 TriggerTick = tick;
1222 switch(pmap[activeSensorId]) 1214 switch(pmap[activeSensorId])
1223 { 1215 {
1224 case SENSOR_DIGO2: setExternalInterfaceChannel(activeSensorId,0.0); 1216 case SENSOR_DIGO2: setExternalInterfaceChannel(activeSensorId,0.0);
1225 break; 1217 break;
1226 case SENSOR_CO2: externalInterface_SetCO2Value(0.0); 1218 case SENSOR_CO2: externalInterface_SetCO2Value(0.0);
1227 externalInterface_SetCO2State(0); 1219 externalInterface_SetCO2SignalStrength(0);
1228 break; 1220 break;
1229 case SENSOR_SENTINEL: setExternalInterfaceChannel(0,0.0); 1221 case SENSOR_SENTINEL: setExternalInterfaceChannel(0,0.0);
1230 setExternalInterfaceChannel(1,0.0); 1222 setExternalInterfaceChannel(1,0.0);
1231 setExternalInterfaceChannel(2,0.0); 1223 setExternalInterfaceChannel(2,0.0);
1232 externalInterface_SetBottlePressure(0,0); 1224 externalInterface_SetBottlePressure(0,0);
1243 } 1235 }
1244 1236
1245 1237
1246 if(pmap[EXT_INTERFACE_SENSOR_CNT-1] == SENSOR_MUX) /* select next sensor if mux is connected */ 1238 if(pmap[EXT_INTERFACE_SENSOR_CNT-1] == SENSOR_MUX) /* select next sensor if mux is connected */
1247 { 1239 {
1240
1248 if(activeUartChannel < MAX_MUX_CHANNEL) 1241 if(activeUartChannel < MAX_MUX_CHANNEL)
1249 { 1242 {
1250 index = ExternalInterface_SelectUsedMuxChannel(activeUartChannel); 1243 index = ExternalInterface_SelectUsedMuxChannel(activeUartChannel);
1251 if((index != activeUartChannel) || (forceMuxChannel)) 1244 if((index != activeUartChannel) || (forceMuxChannel))
1252 { 1245 {
1253 forceMuxChannel = 0; 1246 forceMuxChannel = 0;
1254 timeToTrigger = 100; 1247 timeToTrigger = 100;
1248 lastRequestTick = tick;
1255 activeUartChannel = index; 1249 activeUartChannel = index;
1250 flushUART = 1; /* discard data which might be received while switching to new channel */
1256 switch(pmap[index + EXT_INTERFACE_MUX_OFFSET]) 1251 switch(pmap[index + EXT_INTERFACE_MUX_OFFSET])
1257 { 1252 {
1258 case SENSOR_DIGO2: uartO2_SetChannel(activeUartChannel); 1253 case SENSOR_DIGO2: uartO2_SetChannel(activeUartChannel);
1259 /* no break */ 1254 /* no break */
1260 case SENSOR_CO2: 1255 case SENSOR_CO2: