# HG changeset patch # User Ideenmodellierer # Date 1666982961 -7200 # Node ID f1b40364b0af8b4b2aaaefdcc1c23e34f6965cde # Parent 2f457024049b8d4b0071bb77a23d80109a014a1d Added protocol functions for UART DiveO2 sensor: The code has been modified to support the handling of several protocols (including baud rate changes). The data is requested by polling and passed via DMA into a ringbuffer which is then parsed by a cyclic function call in the main loop. At the moment only the O2 values are forwarded but because the sensor send several types of data within a signle message already more is extracted but yet discarded. diff -r 2f457024049b -r f1b40364b0af Small_CPU/Inc/externalInterface.h --- a/Small_CPU/Inc/externalInterface.h Fri Oct 28 20:32:24 2022 +0200 +++ b/Small_CPU/Inc/externalInterface.h Fri Oct 28 20:49:21 2022 +0200 @@ -43,8 +43,10 @@ uint8_t setExternalInterfaceChannel(uint8_t channel, float value); void externalInterface_SwitchPower33(uint8_t state); void externalInterface_SwitchADC(uint8_t state); +void externalInterface_SwitchUART(uint8_t protocol); uint8_t externalInterface_isEnabledPower33(void); uint8_t externalInterface_isEnabledADC(void); +uint8_t externalInterface_GetUARTProtocol(); void externalInterface_SetCO2Value(uint16_t CO2_ppm); void externalInterface_SetCO2SignalStrength(uint16_t LED_qa); diff -r 2f457024049b -r f1b40364b0af Small_CPU/Inc/uart.h --- a/Small_CPU/Inc/uart.h Fri Oct 28 20:32:24 2022 +0200 +++ b/Small_CPU/Inc/uart.h Fri Oct 28 20:49:21 2022 +0200 @@ -46,6 +46,31 @@ RX_DataComplete } receiveState_t; + typedef enum + { + UART_O2_INIT = 0, + UART_O2_CHECK, /* send blink command and check if sensor answers */ + UART_O2_REQ_INFO, /* request information about available internal sensors of sensor */ + UART_O2_REQ_ID, /* request ID of sensor */ + UART_O2_IDLE, /* sensor detected and no communication pending */ + UART_O2_REQ_O2, /* O2 value has been requested and is in receiption progress */ + UART_O2_ERROR /* Error state which could not be resolved => only exit via de-/activation cycle */ + } uartO2Status_t; + + + typedef enum + { + O2RX_IDLE = 0, /* no receiption pending */ + O2RX_CONFIRM, /* check the command echo */ + O2RX_GETNR, /* extract the sensor number */ + O2RX_GETO2, /* extract the ppo2 */ + O2RX_GETTEMP, /* extract the temperature */ + O2RX_GETSTATUS, /* extract the sensor status */ + O2RX_GETTYPE, /* extract the sensor type (should be 8) */ + O2RX_GETCHANNEL, /* extract the number of sensor channels (should be 1) */ + O2RX_GETVERSION, /* extract the sensor version */ + O2RX_GETSUBSENSORS /* extract the available measures (O2, temperature, humidity etc) */ + } uartO2RxState_t; void MX_USART1_UART_Init(void); void MX_USART1_UART_DeInit(void); @@ -57,6 +82,8 @@ #ifdef ENABLE_SENTINEL_MODE void HandleUARTSentinelData(void); #endif +void HandleUARTDigitalO2(void); + #ifdef __cplusplus } #endif diff -r 2f457024049b -r f1b40364b0af Small_CPU/Src/baseCPU2.c --- a/Small_CPU/Src/baseCPU2.c Fri Oct 28 20:32:24 2022 +0200 +++ b/Small_CPU/Src/baseCPU2.c Fri Oct 28 20:49:21 2022 +0200 @@ -422,7 +422,7 @@ SPI_synchronize_with_Master(); MX_DMA_Init(); MX_SPI1_Init(); - MX_USART1_UART_Init(); + externalInterface_SwitchUART(externalInterface_GetUARTProtocol()); SPI_Start_single_TxRx_with_Master(); /* be prepared for the first data exchange */ Scheduler_Request_sync_with_SPI(SPI_SYNC_METHOD_HARD); EXTI_Test_Button_Init(); diff -r 2f457024049b -r f1b40364b0af Small_CPU/Src/externalInterface.c --- a/Small_CPU/Src/externalInterface.c Fri Oct 28 20:32:24 2022 +0200 +++ b/Small_CPU/Src/externalInterface.c Fri Oct 28 20:49:21 2022 +0200 @@ -57,6 +57,7 @@ float externalChannel_mV[MAX_ADC_CHANNEL]; static uint8_t externalV33_On = 0; static uint8_t externalADC_On = 0; +static uint8_t externalUART_Protocol = 0; static uint16_t externalCO2Value; static uint16_t externalCO2SignalStrength; static uint16_t externalCO2Status = 0; @@ -111,7 +112,14 @@ activeChannel++; if(activeChannel == MAX_ADC_CHANNEL) { - activeChannel = 0; + if(externalUART_Protocol == (EXT_INTERFACE_UART_O2 >> 8)) /* mixed mode digital and analog o2 sensors => channel 0 is reserved for digital sensor */ + { + activeChannel = 1; + } + else + { + activeChannel = 0; + } } externalInterface_StartConversion(activeChannel); timeoutCnt = 0; @@ -218,6 +226,11 @@ return externalADC_On; } +uint8_t externalInterface_GetUARTProtocol() +{ + return externalUART_Protocol; +} + void externalInterface_SwitchPower33(uint8_t state) { if(state != externalV33_On) @@ -226,7 +239,6 @@ { HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_RESET); externalV33_On = 1; - MX_USART1_UART_Init(); } else { @@ -234,7 +246,6 @@ externalV33_On = 0; externalInterface_SetCO2Value(0); externalInterface_SetCO2SignalStrength(0); - MX_USART1_UART_DeInit(); } } } @@ -251,6 +262,19 @@ } } +void externalInterface_SwitchUART(uint8_t protocol) +{ + if(protocol < 0x08) + { + externalUART_Protocol = protocol; + MX_USART1_UART_DeInit(); + if( protocol != 0) + { + MX_USART1_UART_Init(); + } + } +} + void externalInterface_SetCO2Value(uint16_t CO2_ppm) { externalCO2Value = CO2_ppm; diff -r 2f457024049b -r f1b40364b0af Small_CPU/Src/scheduler.c --- a/Small_CPU/Src/scheduler.c Fri Oct 28 20:32:24 2022 +0200 +++ b/Small_CPU/Src/scheduler.c Fri Oct 28 20:49:21 2022 +0200 @@ -318,6 +318,10 @@ externalInterface_SwitchADC(global.dataSendToSlave.data.externalInterface_Cmd && EXT_INTERFACE_ADC_ON); } + if(((global.dataSendToSlave.data.externalInterface_Cmd >> 8) & 0x0F) != externalInterface_GetUARTProtocol()) + { + externalInterface_SwitchUART((global.dataSendToSlave.data.externalInterface_Cmd >> 8) & 0x0F); + } if(global.dataSendToSlave.data.externalInterface_Cmd & 0x00FF) /* lowest nibble for commands */ { @@ -523,7 +527,10 @@ HandleUARTSentinelData(); } #endif - + if(global.dataSendToSlave.data.externalInterface_Cmd & EXT_INTERFACE_UART_O2) + { + HandleUARTDigitalO2(); + } if(ticksdiff >= Scheduler.counterSPIdata100msec * 100 + 10) { @@ -843,6 +850,11 @@ } #endif + if(global.dataSendToSlave.data.externalInterface_Cmd & EXT_INTERFACE_UART_O2) + { + HandleUARTDigitalO2(); + } + /* Evaluate received data at 10 ms, 110 ms, 210 ms,... duration ~<1ms */ if(ticksdiff >= Scheduler.counterSPIdata100msec * 100 + 10) { diff -r 2f457024049b -r f1b40364b0af Small_CPU/Src/uart.c --- a/Small_CPU/Src/uart.c Fri Oct 28 20:32:24 2022 +0200 +++ b/Small_CPU/Src/uart.c Fri Oct 28 20:49:21 2022 +0200 @@ -22,6 +22,7 @@ #include "uart.h" #include "externalInterface.h" #include "data_exchange.h" +#include /* memset */ /* Private variables ---------------------------------------------------------*/ @@ -37,6 +38,13 @@ static uint8_t lastCmdIndex; /* Index of last command which has not been completly received */ static uint8_t dmaActive; /* Indicator if DMA receiption needs to be started */ +char tmpRxBuf[30]; +uint8_t tmpRxIdx = 0; + +static uartO2Status_t Comstatus_O2 = UART_O2_INIT; + +static uint32_t DigitalO2ID = 0; + float LED_Level = 0.0; /* Normalized LED value which may be used as indication for the health status of the sensor */ float LED_ZeroOffset = 0.0; float pCO2 = 0.0; @@ -47,7 +55,16 @@ /* regular init */ huart1.Instance = USART1; - huart1.Init.BaudRate = 9600; + + if(externalInterface_GetUARTProtocol() == 0x04) + { + huart1.Init.BaudRate = 19200; + Comstatus_O2 = UART_O2_INIT; + } + else + { + huart1.Init.BaudRate = 9600; + } huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; @@ -57,14 +74,18 @@ HAL_UART_Init(&huart1); + MX_USART1_DMA_Init(); + rxReadIndex = 0; lastCmdIndex = 0; rxWriteIndex = 0; dmaActive = 0; + Comstatus_O2 = UART_O2_INIT; } void MX_USART1_UART_DeInit(void) { + HAL_DMA_Abort(&hdma_usart1_rx); HAL_DMA_DeInit(&hdma_usart1_rx); HAL_UART_DeInit(&huart1); } @@ -356,6 +377,228 @@ } #endif +void DigitalO2_SetupCmd(uint8_t O2State, uint8_t *cmdString, uint8_t *cmdLength) +{ + switch (O2State) + { + case UART_O2_CHECK: *cmdLength = snprintf((char*)cmdString, 10, "#LOGO"); + break; + case UART_O2_REQ_INFO: *cmdLength = snprintf((char*)cmdString, 10, "#VERS"); + break; + case UART_O2_REQ_ID: *cmdLength = snprintf((char*)cmdString, 10, "#IDNR"); + break; + case UART_O2_REQ_O2: *cmdLength = snprintf((char*)cmdString, 10, "#DOXY"); + break; + + default: *cmdLength = 0; + break; + } + if(*cmdLength != 0) + { + cmdString[*cmdLength] = 0x0D; + *cmdLength = *cmdLength + 1; + } +} + +void StringToInt(char *pstr, uint32_t *pInt) +{ + uint8_t index = 0; + uint32_t result = 0; + while((pstr[index] >= '0') && (pstr[index] <= '9')) + { + result *=10; + result += pstr[index] - '0'; + index++; + } + *pInt = result; +} + +void HandleUARTDigitalO2(void) +{ + static uint32_t lastO2ReqTick = 0; + + static uartO2RxState_t rxState = O2RX_IDLE; + static uint32_t lastReceiveTick = 0; + static uint8_t lastAlive = 0; + static uint8_t curAlive = 0; + + static uint8_t cmdLength = 0; + static uint8_t cmdString[10]; + static uint8_t cmdReadIndex = 0; + + uint32_t tmpO2 = 0; + uint32_t tmpData = 0; + uint8_t localRX = rxReadIndex; + uint32_t tick = HAL_GetTick(); + + + if(Comstatus_O2 == UART_O2_INIT) + { + memset((char*)&rxBuffer[rxWriteIndex],(int)0,CHUNK_SIZE); + lastAlive = 0; + curAlive = 0; + + Comstatus_O2 = UART_O2_CHECK; + DigitalO2_SetupCmd(Comstatus_O2,cmdString,&cmdLength); + HAL_UART_Transmit(&huart1,cmdString,cmdLength,10); + + rxState = O2RX_CONFIRM; + cmdReadIndex = 0; + lastO2ReqTick = tick; + + if(HAL_OK == HAL_UART_Receive_DMA (&huart1, &rxBuffer[rxWriteIndex], CHUNK_SIZE)) + { + dmaActive = 1; + } + } + if(time_elapsed_ms(lastO2ReqTick,tick) > 1000) /* repeat request once per second */ + { + lastO2ReqTick = tick; + if(Comstatus_O2 == UART_O2_IDLE) /* cyclic request of o2 value */ + { + Comstatus_O2 = UART_O2_REQ_O2; + rxState = O2RX_CONFIRM; + } + DigitalO2_SetupCmd(Comstatus_O2,cmdString,&cmdLength); + + HAL_UART_Transmit(&huart1,cmdString,cmdLength,10); + } + + while((rxBuffer[localRX]!=0)) + { + + lastReceiveTick = tick; + switch(rxState) + { + case O2RX_CONFIRM: if(rxBuffer[localRX] == '#') + { + cmdReadIndex = 0; + } + if(rxBuffer[localRX] == cmdString[cmdReadIndex]) + { + cmdReadIndex++; + if(cmdReadIndex == cmdLength - 1) + { + tmpRxIdx = 0; + memset((char*) tmpRxBuf, 0, sizeof(tmpRxBuf)); + switch (Comstatus_O2) + { + case UART_O2_CHECK: Comstatus_O2 = UART_O2_REQ_INFO; + DigitalO2_SetupCmd(Comstatus_O2,cmdString,&cmdLength); + HAL_UART_Transmit(&huart1,cmdString,cmdLength,10); + break; + case UART_O2_REQ_ID: rxState = O2RX_GETNR; + break; + case UART_O2_REQ_INFO: rxState = O2RX_GETTYPE; + break; + case UART_O2_REQ_O2: rxState = O2RX_GETO2; + break; + default: Comstatus_O2 = UART_O2_IDLE; + rxState = O2RX_IDLE; + break; + } + } + } + break; + + case O2RX_GETSTATUS: + case O2RX_GETTEMP: + case O2RX_GETTYPE: + case O2RX_GETVERSION: + case O2RX_GETCHANNEL: + case O2RX_GETSUBSENSORS: + case O2RX_GETO2: + case O2RX_GETNR: if(rxBuffer[localRX] != 0x0D) + { + if(rxBuffer[localRX] != ' ') + { + tmpRxBuf[tmpRxIdx++] = rxBuffer[localRX]; + } + else + { + if(tmpRxIdx != 0) + { + switch(rxState) + { + case O2RX_GETCHANNEL: StringToInt(tmpRxBuf,&tmpData); + rxState = O2RX_GETVERSION; + break; + case O2RX_GETVERSION: StringToInt(tmpRxBuf,&tmpData); + rxState = O2RX_GETSUBSENSORS; + break; + case O2RX_GETTYPE: StringToInt(tmpRxBuf,&tmpData); + rxState = O2RX_GETCHANNEL; + break; + + case O2RX_GETO2: StringToInt(tmpRxBuf,&tmpO2); + setExternalInterfaceChannel(0,(float)(tmpO2 / 10000.0)); + rxState = O2RX_GETTEMP; + break; + case O2RX_GETTEMP: rxState = O2RX_GETSTATUS; + break; + default: + break; + } + memset((char*) tmpRxBuf, 0, tmpRxIdx); + tmpRxIdx = 0; + } + } + } + else + { + switch (rxState) + { + case O2RX_GETSTATUS: StringToInt(tmpRxBuf,&tmpData); + Comstatus_O2 = UART_O2_IDLE; + rxState = O2RX_IDLE; + break; + case O2RX_GETSUBSENSORS: StringToInt(tmpRxBuf,&tmpData); + Comstatus_O2 = UART_O2_IDLE; + rxState = O2RX_IDLE; + break; + case O2RX_GETNR: StringToInt((char*)rxBuffer,&DigitalO2ID); + /* no break */ + default: Comstatus_O2 = UART_O2_IDLE; + rxState = O2RX_IDLE; + break; + } + } + break; + default: rxState = O2RX_IDLE; + break; + + } + + localRX++; + rxReadIndex++; + if(rxReadIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER) + { + localRX = 0; + rxReadIndex = 0; + } + } + + if(time_elapsed_ms(lastReceiveTick,HAL_GetTick()) > 4000) /* check for communication timeout */ + { + if(curAlive == lastAlive) + { + setExternalInterfaceChannel(0,0.0); + setExternalInterfaceChannel(1,0.0); + setExternalInterfaceChannel(2,0.0); + } + lastAlive = curAlive; + } + + if((dmaActive == 0) && (externalInterface_isEnabledPower33())) /* Should never happen in normal operation => restart in case of communication error */ + { + if(HAL_OK == HAL_UART_Receive_DMA (&huart1, &rxBuffer[rxWriteIndex], CHUNK_SIZE)) + { + dmaActive = 1; + } + } +} + + void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart == &huart1) @@ -370,6 +613,7 @@ { if(externalInterface_isEnabledPower33()) { + memset((char*)&rxBuffer[rxWriteIndex],(int)0,CHUNK_SIZE); if(HAL_OK == HAL_UART_Receive_DMA (&huart1, &rxBuffer[rxWriteIndex], CHUNK_SIZE)) { dmaActive = 1;