798
+ − 1 /**
+ − 2 ******************************************************************************
+ − 3 * @file uartProtocol_Co2.c
+ − 4 * @author heinrichs weikamp gmbh
+ − 5 * @version V0.0.1
+ − 6 * @date 31-Jul-2023
+ − 7 * @brief Interface functionality to external, UART based CO2 sensors
+ − 8 *
+ − 9 @verbatim
+ − 10
+ − 11
+ − 12 @endverbatim
+ − 13 ******************************************************************************
+ − 14 * @attention
+ − 15 *
+ − 16 * <h2><center>© COPYRIGHT(c) 2023 heinrichs weikamp</center></h2>
+ − 17 *
+ − 18 ******************************************************************************
+ − 19 */
+ − 20 /* Includes ------------------------------------------------------------------*/
+ − 21
+ − 22 #include <string.h>
+ − 23 #include <uartProtocol_Co2.h>
+ − 24 #include "uart.h"
+ − 25 #include "externalInterface.h"
+ − 26
+ − 27 #ifdef ENABLE_CO2_SUPPORT
+ − 28 static uint8_t CO2Connected = 0; /* Binary indicator if a sensor is connected or not */
842
+ − 29 static receiveStateCO2_t rxState = CO2RX_Ready;
798
+ − 30
+ − 31
+ − 32
+ − 33 float LED_Level = 0.0; /* Normalized LED value which may be used as indication for the health status of the sensor */
+ − 34 float LED_ZeroOffset = 0.0;
+ − 35 float pCO2 = 0.0;
+ − 36
+ − 37
+ − 38
+ − 39 void uartCo2_SendCmd(uint8_t CO2Cmd, uint8_t *cmdString, uint8_t *cmdLength)
+ − 40 {
809
+ − 41 *cmdLength = 0;
+ − 42
798
+ − 43 switch (CO2Cmd)
+ − 44 {
+ − 45 case CO2CMD_MODE_POLL: *cmdLength = snprintf((char*)cmdString, 10, "K 2\r\n");
+ − 46 break;
+ − 47 case CO2CMD_MODE_STREAM: *cmdLength = snprintf((char*)cmdString, 10, "K 1\r\n");
+ − 48 break;
+ − 49 case CO2CMD_CALIBRATE: *cmdLength = snprintf((char*)cmdString, 10, "G\r\n");
+ − 50 break;
+ − 51 case CO2CMD_GETDATA: *cmdLength = snprintf((char*)cmdString, 10, "Q\r\n");
+ − 52 break;
+ − 53 case CO2CMD_GETSCALE: *cmdLength = snprintf((char*)cmdString, 10, ".\r\n");
+ − 54 break;
+ − 55 default: *cmdLength = 0;
+ − 56 break;
+ − 57 }
+ − 58 if(cmdLength != 0)
+ − 59 {
+ − 60 UART_SendCmdString(cmdString);
+ − 61 }
+ − 62 }
+ − 63
+ − 64
+ − 65 void uartCo2_Control(void)
+ − 66 {
+ − 67 static uint8_t cmdString[10];
+ − 68 static uint8_t cmdLength = 0;
+ − 69 static uint8_t lastComState = 0;
+ − 70
+ − 71 uint8_t activeSensor = externalInterface_GetActiveUartSensor();
+ − 72 uartCO2Status_t localComState = externalInterface_GetSensorState(activeSensor + EXT_INTERFACE_MUX_OFFSET);
+ − 73
+ − 74 uint8_t *pmap = externalInterface_GetSensorMapPointer(0);
+ − 75
+ − 76
+ − 77 if(localComState == UART_CO2_ERROR)
+ − 78 {
+ − 79 localComState = lastComState;
+ − 80 }
+ − 81
+ − 82 if(localComState == UART_CO2_INIT)
+ − 83 {
809
+ − 84 CO2Connected = 0;
798
+ − 85 externalInterface_SetCO2Scale(0.0);
932
+ − 86 UART_clearRxBuffer(&Uart1Ctrl);
+ − 87 UART_StartDMA_Receiption(&Uart1Ctrl);
798
+ − 88 localComState = UART_CO2_SETUP;
+ − 89 }
+ − 90 if(localComState == UART_CO2_SETUP)
+ − 91 {
+ − 92 if(externalInterface_GetCO2Scale() == 0.0)
+ − 93 {
+ − 94 uartCo2_SendCmd(CO2CMD_GETSCALE, cmdString, &cmdLength);
+ − 95 }
+ − 96 else
+ − 97 {
+ − 98 localComState = UART_CO2_IDLE;
+ − 99 }
+ − 100 }
+ − 101 else
+ − 102 {
+ − 103 if(localComState == UART_CO2_CALIBRATE)
+ − 104 {
+ − 105 uartCo2_SendCmd(CO2CMD_CALIBRATE, cmdString, &cmdLength);
809
+ − 106 localComState = UART_CO2_IDLE;
798
+ − 107 }
+ − 108 else if(pmap[EXT_INTERFACE_SENSOR_CNT-1] == SENSOR_MUX) /* sensor is working in polling mode if mux is connected to avoid interference with other sensors */
+ − 109 {
+ − 110 //if(cmdLength == 0) /* poll data */
+ − 111 if(localComState == UART_CO2_IDLE)
+ − 112 {
+ − 113 uartCo2_SendCmd(CO2CMD_GETDATA, cmdString, &cmdLength);
+ − 114 localComState = UART_CO2_OPERATING;
+ − 115 }
+ − 116 else /* resend last command */
+ − 117 {
+ − 118 UART_SendCmdString(cmdString);
+ − 119 cmdLength = 0;
+ − 120 }
+ − 121 }
+ − 122 else
+ − 123 {
+ − 124 localComState = UART_CO2_OPERATING; /* sensor in streaming mode if not connected to mux => operating */
932
+ − 125 UART_StartDMA_Receiption(&Uart1Ctrl);
798
+ − 126 }
+ − 127 }
+ − 128 lastComState = localComState;
+ − 129 externalInterface_SetSensorState(activeSensor + EXT_INTERFACE_MUX_OFFSET,localComState);
+ − 130 }
+ − 131
+ − 132
+ − 133 void uartCo2_ProcessData(uint8_t data)
+ − 134 {
+ − 135 static uint8_t dataType = 0;
+ − 136 static uint32_t dataValue = 0;
+ − 137 uint8_t activeSensor = externalInterface_GetActiveUartSensor();
+ − 138 uartCO2Status_t localComState = externalInterface_GetSensorState(activeSensor + EXT_INTERFACE_MUX_OFFSET);
+ − 139
842
+ − 140 if(rxState == CO2RX_Ready) /* identify data content */
798
+ − 141 {
+ − 142 switch(data)
+ − 143 {
+ − 144 case 'G':
+ − 145 case 'l':
+ − 146 case 'D':
+ − 147 case 'Z':
+ − 148 case '.': dataType = data;
842
+ − 149 rxState = CO2RX_Data0;
798
+ − 150 dataValue = 0;
+ − 151 break;
+ − 152 case '?': localComState = UART_CO2_ERROR;
+ − 153 break;
+ − 154 default: /* unknown or corrupted => ignore */
+ − 155 break;
+ − 156 }
+ − 157 }
+ − 158 else if((data >= '0') && (data <= '9'))
+ − 159 {
842
+ − 160 if((rxState >= CO2RX_Data0) && (rxState <= CO2RX_Data4))
798
+ − 161 {
+ − 162 dataValue = dataValue * 10 + (data - '0');
+ − 163 rxState++;
842
+ − 164 if(rxState == CO2RX_Data5)
798
+ − 165 {
842
+ − 166 rxState = CO2RX_DataComplete;
798
+ − 167 }
+ − 168 }
+ − 169 else /* protocol error data has max 5 digits */
+ − 170 {
842
+ − 171 if(rxState != CO2RX_DataComplete) /* commands will not answer with number values */
809
+ − 172 {
842
+ − 173 rxState = CO2RX_Ready;
809
+ − 174 }
798
+ − 175 }
+ − 176 }
916
+ − 177 else if((data == ' ') || (data == '\n')) /* Abort data detection */
798
+ − 178 {
842
+ − 179 if(rxState == CO2RX_DataComplete)
798
+ − 180 {
809
+ − 181 CO2Connected = 1;
+ − 182 if(localComState == UART_CO2_SETUP)
+ − 183 {
+ − 184 if(dataType == '.')
+ − 185 {
+ − 186 localComState = UART_CO2_IDLE;
+ − 187 }
+ − 188 }
+ − 189 else
+ − 190 {
+ − 191 localComState = UART_CO2_IDLE;
+ − 192 }
798
+ − 193 if(externalInterface_GetCO2State() == 0)
+ − 194 {
+ − 195 externalInterface_SetCO2State(EXT_INTERFACE_33V_ON);
+ − 196 }
+ − 197 switch(dataType)
+ − 198 {
+ − 199 case 'D': externalInterface_SetCO2SignalStrength(dataValue);
+ − 200 break;
+ − 201 case 'l': LED_ZeroOffset = dataValue;
+ − 202 break;
+ − 203 case 'Z': externalInterface_SetCO2Value(dataValue);
+ − 204 break;
+ − 205 case '.': externalInterface_SetCO2Scale(dataValue);
+ − 206 break;
842
+ − 207 default: rxState = CO2RX_Ready;
798
+ − 208 break;
+ − 209 }
+ − 210 }
842
+ − 211 if(rxState != CO2RX_Data0) /* reset state machine because message in wrong format */
798
+ − 212 {
842
+ − 213 rxState = CO2RX_Ready;
798
+ − 214 }
+ − 215 }
916
+ − 216 else
+ − 217 {
+ − 218 if((rxState >= CO2RX_Data0) && (rxState <= CO2RX_Data4))
+ − 219 {
+ − 220 rxState = CO2RX_Ready; /* numerical data expected => abort */
+ − 221 }
+ − 222 }
798
+ − 223 externalInterface_SetSensorState(activeSensor + EXT_INTERFACE_MUX_OFFSET,localComState);
+ − 224 }
+ − 225
+ − 226 uint8_t uartCo2_isSensorConnected()
+ − 227 {
+ − 228 return CO2Connected;
+ − 229 }
+ − 230
+ − 231 #endif
+ − 232