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);
976
+ − 86 UART_ReadData(SENSOR_CO2, 1); /* flush buffer */
932
+ − 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 {
976
+ − 113 if(externalInterface_GetCO2Scale() == 0.0)
+ − 114 {
+ − 115 uartCo2_SendCmd(CO2CMD_GETSCALE, cmdString, &cmdLength);
+ − 116 localComState = UART_CO2_SETUP;
+ − 117 }
+ − 118 else
+ − 119 {
+ − 120 uartCo2_SendCmd(CO2CMD_GETDATA, cmdString, &cmdLength);
+ − 121 localComState = UART_CO2_OPERATING;
+ − 122 }
798
+ − 123 }
+ − 124 else /* resend last command */
+ − 125 {
+ − 126 UART_SendCmdString(cmdString);
+ − 127 cmdLength = 0;
+ − 128 }
+ − 129 }
+ − 130 else
+ − 131 {
+ − 132 localComState = UART_CO2_OPERATING; /* sensor in streaming mode if not connected to mux => operating */
932
+ − 133 UART_StartDMA_Receiption(&Uart1Ctrl);
798
+ − 134 }
+ − 135 }
+ − 136 lastComState = localComState;
+ − 137 externalInterface_SetSensorState(activeSensor + EXT_INTERFACE_MUX_OFFSET,localComState);
+ − 138 }
+ − 139
+ − 140
+ − 141 void uartCo2_ProcessData(uint8_t data)
+ − 142 {
+ − 143 static uint8_t dataType = 0;
+ − 144 static uint32_t dataValue = 0;
+ − 145 uint8_t activeSensor = externalInterface_GetActiveUartSensor();
+ − 146 uartCO2Status_t localComState = externalInterface_GetSensorState(activeSensor + EXT_INTERFACE_MUX_OFFSET);
+ − 147
842
+ − 148 if(rxState == CO2RX_Ready) /* identify data content */
798
+ − 149 {
+ − 150 switch(data)
+ − 151 {
+ − 152 case 'G':
+ − 153 case 'l':
+ − 154 case 'D':
+ − 155 case 'Z':
+ − 156 case '.': dataType = data;
842
+ − 157 rxState = CO2RX_Data0;
798
+ − 158 dataValue = 0;
+ − 159 break;
+ − 160 case '?': localComState = UART_CO2_ERROR;
+ − 161 break;
+ − 162 default: /* unknown or corrupted => ignore */
+ − 163 break;
+ − 164 }
+ − 165 }
+ − 166 else if((data >= '0') && (data <= '9'))
+ − 167 {
842
+ − 168 if((rxState >= CO2RX_Data0) && (rxState <= CO2RX_Data4))
798
+ − 169 {
+ − 170 dataValue = dataValue * 10 + (data - '0');
+ − 171 rxState++;
842
+ − 172 if(rxState == CO2RX_Data5)
798
+ − 173 {
842
+ − 174 rxState = CO2RX_DataComplete;
798
+ − 175 }
+ − 176 }
+ − 177 else /* protocol error data has max 5 digits */
+ − 178 {
842
+ − 179 if(rxState != CO2RX_DataComplete) /* commands will not answer with number values */
809
+ − 180 {
842
+ − 181 rxState = CO2RX_Ready;
809
+ − 182 }
798
+ − 183 }
+ − 184 }
916
+ − 185 else if((data == ' ') || (data == '\n')) /* Abort data detection */
798
+ − 186 {
842
+ − 187 if(rxState == CO2RX_DataComplete)
798
+ − 188 {
809
+ − 189 CO2Connected = 1;
+ − 190 if(localComState == UART_CO2_SETUP)
+ − 191 {
+ − 192 if(dataType == '.')
+ − 193 {
+ − 194 localComState = UART_CO2_IDLE;
+ − 195 }
+ − 196 }
+ − 197 else
+ − 198 {
+ − 199 localComState = UART_CO2_IDLE;
+ − 200 }
798
+ − 201 if(externalInterface_GetCO2State() == 0)
+ − 202 {
+ − 203 externalInterface_SetCO2State(EXT_INTERFACE_33V_ON);
+ − 204 }
+ − 205 switch(dataType)
+ − 206 {
+ − 207 case 'D': externalInterface_SetCO2SignalStrength(dataValue);
+ − 208 break;
+ − 209 case 'l': LED_ZeroOffset = dataValue;
+ − 210 break;
+ − 211 case 'Z': externalInterface_SetCO2Value(dataValue);
+ − 212 break;
+ − 213 case '.': externalInterface_SetCO2Scale(dataValue);
+ − 214 break;
842
+ − 215 default: rxState = CO2RX_Ready;
798
+ − 216 break;
+ − 217 }
976
+ − 218 rxState = CO2RX_Ready;
798
+ − 219 }
842
+ − 220 if(rxState != CO2RX_Data0) /* reset state machine because message in wrong format */
798
+ − 221 {
842
+ − 222 rxState = CO2RX_Ready;
798
+ − 223 }
+ − 224 }
916
+ − 225 else
+ − 226 {
+ − 227 if((rxState >= CO2RX_Data0) && (rxState <= CO2RX_Data4))
+ − 228 {
+ − 229 rxState = CO2RX_Ready; /* numerical data expected => abort */
+ − 230 }
+ − 231 }
798
+ − 232 externalInterface_SetSensorState(activeSensor + EXT_INTERFACE_MUX_OFFSET,localComState);
+ − 233 }
+ − 234
+ − 235 uint8_t uartCo2_isSensorConnected()
+ − 236 {
+ − 237 return CO2Connected;
+ − 238 }
+ − 239
+ − 240 #endif
+ − 241