safety state and input error detection

This commit is contained in:
Hendrik Schutter 2024-12-13 19:26:16 +01:00
parent a7f6973efd
commit 8205253b5a
6 changed files with 236 additions and 196 deletions

View File

@ -12,7 +12,12 @@
"inputs.h": "c",
"cstdlib": "c",
"typeinfo": "c",
"limits": "c"
"limits": "c",
"bit": "c",
"type_traits": "c",
"cmath": "c",
"*.tcc": "c",
"*.inc": "c"
},
"idf.openOcdConfigs": [
"board/esp32-wrover-kit-3.3v.cfg"

View File

@ -6,27 +6,8 @@
#include "inputs.h"
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MAX_DN18B20_SENSORS 4U
#define PERIODIC_INTERVAL 1U // read and compute the inputs every 1sec
#define AVG10_SAMPLE_SIZE 10U
#define AVG60_SAMPLE_SIZE 60U
typedef struct _Average
{
float value;
float samples[MAX(AVG10_SAMPLE_SIZE, AVG60_SAMPLE_SIZE)];
size_t bufferIndex;
size_t bufferCount;
} sAverage;
typedef struct _Measurement
{
float value;
sAverage average10s;
sAverage average60s;
} sMeasurement;
static const char *TAG = "smart-oil-heater-control-system-inputs";
const uint8_t uBurnerFaultPin = 19U;
@ -43,10 +24,10 @@ size_t sSensorCount = 0U;
static SemaphoreHandle_t xMutexAccessInputs = NULL;
static eBurnerErrorState sBurnerErrorState;
static sMeasurement fChamperTemperature;
static sMeasurement fOutdoorTemperature;
static sMeasurement fInletFlowTemperature;
static sMeasurement fReturnFlowTemperature;
static sMeasurement sChamperTemperature;
static sMeasurement sOutdoorTemperature;
static sMeasurement sInletFlowTemperature;
static sMeasurement sReturnFlowTemperature;
void taskInput(void *pvParameters);
void updateAverage(sMeasurement *pMeasurement);
@ -92,7 +73,7 @@ void initInputs(void)
void updateAverage(sMeasurement *pMeasurement)
{ /* Average form the last 10sec */
pMeasurement->average10s.samples[pMeasurement->average10s.bufferIndex] = pMeasurement->value;
pMeasurement->average10s.samples[pMeasurement->average10s.bufferIndex] = pMeasurement->fCurrentValue;
pMeasurement->average10s.bufferIndex = (pMeasurement->average10s.bufferIndex + 1) % AVG10_SAMPLE_SIZE;
if (pMeasurement->average10s.bufferCount < AVG10_SAMPLE_SIZE)
@ -102,7 +83,7 @@ void updateAverage(sMeasurement *pMeasurement)
if (pMeasurement->average10s.bufferCount == 0U)
{
pMeasurement->average10s.value = pMeasurement->value;
pMeasurement->average10s.fValue = pMeasurement->fCurrentValue;
}
float sum = 0.0;
@ -111,10 +92,10 @@ void updateAverage(sMeasurement *pMeasurement)
sum += pMeasurement->average10s.samples[i];
}
pMeasurement->average10s.value = sum / pMeasurement->average10s.bufferCount;
pMeasurement->average10s.fValue = sum / pMeasurement->average10s.bufferCount;
/* Average form the last 60sec */
pMeasurement->average60s.samples[pMeasurement->average60s.bufferIndex] = pMeasurement->value;
pMeasurement->average60s.samples[pMeasurement->average60s.bufferIndex] = pMeasurement->fCurrentValue;
pMeasurement->average60s.bufferIndex = (pMeasurement->average60s.bufferIndex + 1) % AVG60_SAMPLE_SIZE;
if (pMeasurement->average60s.bufferCount < AVG60_SAMPLE_SIZE)
@ -124,7 +105,7 @@ void updateAverage(sMeasurement *pMeasurement)
if (pMeasurement->average60s.bufferCount == 0U)
{
pMeasurement->average60s.value = pMeasurement->value;
pMeasurement->average60s.fValue = pMeasurement->fCurrentValue;
}
sum = 0.0;
@ -133,7 +114,7 @@ void updateAverage(sMeasurement *pMeasurement)
sum += pMeasurement->average60s.samples[i];
}
pMeasurement->average60s.value = sum / pMeasurement->average60s.bufferCount;
pMeasurement->average60s.fValue = sum / pMeasurement->average60s.bufferCount;
}
void taskInput(void *pvParameters)
@ -141,6 +122,12 @@ void taskInput(void *pvParameters)
while (1)
{
vTaskDelay(PERIODIC_INTERVAL * 1000U / portTICK_PERIOD_MS);
if (xSemaphoreTake(xMutexAccessInputs, portMAX_DELAY) == pdTRUE)
{
sChamperTemperature.state = MEASUREMENT_FAULT;
sOutdoorTemperature.state = MEASUREMENT_FAULT;
sInletFlowTemperature.state = MEASUREMENT_FAULT;
sReturnFlowTemperature.state = MEASUREMENT_FAULT;
if (gpio_get_level(uBurnerFaultPin) == 1)
{
@ -180,129 +167,88 @@ void taskInput(void *pvParameters)
{
float temp_c = fDS18B20Temps[j];
ESP_LOGI(TAG, "Sensor: %08" PRIx64 " reports %lf°C", (uint64_t)uOneWireAddresses[j], temp_c);
if (xSemaphoreTake(xMutexAccessInputs, portMAX_DELAY) == pdTRUE)
{
switch ((uint64_t)uOneWireAddresses[j])
{
case ((uint64_t)uChamperTempSensorAddr):
fChamperTemperature.value = temp_c;
updateAverage(&fChamperTemperature);
sChamperTemperature.fCurrentValue = temp_c;
sChamperTemperature.state = MEASUREMENT_NO_ERROR;
updateAverage(&sChamperTemperature);
break;
case ((uint64_t)uOutdoorTempSensorAddr):
fOutdoorTemperature.value = temp_c;
updateAverage(&fOutdoorTemperature);
sOutdoorTemperature.fCurrentValue = temp_c;
sOutdoorTemperature.state = MEASUREMENT_NO_ERROR;
updateAverage(&sOutdoorTemperature);
break;
case ((uint64_t)uInletFlowTempSensorAddr):
fInletFlowTemperature.value = temp_c;
updateAverage(&fInletFlowTemperature);
sInletFlowTemperature.fCurrentValue = temp_c;
sInletFlowTemperature.state = MEASUREMENT_NO_ERROR;
updateAverage(&sInletFlowTemperature);
break;
case ((uint64_t)uReturnFlowTempSensorAddr):
fReturnFlowTemperature.value = temp_c;
updateAverage(&fReturnFlowTemperature);
sReturnFlowTemperature.fCurrentValue = temp_c;
sReturnFlowTemperature.state = MEASUREMENT_NO_ERROR;
updateAverage(&sReturnFlowTemperature);
break;
default:
break;
}
}
}
}
xSemaphoreGive(xMutexAccessInputs);
}
}
}
}
}
}
float getChamberTemperature(eMeasurementMode mode)
sMeasurement getChamberTemperature(void)
{
float ret = 0.0f;
sMeasurement ret;
ret.state = MEASUREMENT_FAULT;
if (xSemaphoreTake(xMutexAccessInputs, portMAX_DELAY) == pdTRUE)
{
switch (mode)
{
case CURRENT:
ret = fChamperTemperature.value;
break;
case AVERAGE_10S:
ret = fChamperTemperature.average10s.value;
break;
case AVERAGE_60S:
ret = fChamperTemperature.average60s.value;
break;
default:
break;
}
ret = sChamperTemperature;
xSemaphoreGive(xMutexAccessInputs);
}
return ret;
}
float getOutdoorTemperature(eMeasurementMode mode)
sMeasurement getOutdoorTemperature(void)
{
float ret = 0.0f;
sMeasurement ret;
ret.state = MEASUREMENT_FAULT;
if (xSemaphoreTake(xMutexAccessInputs, portMAX_DELAY) == pdTRUE)
{
switch (mode)
{
case CURRENT:
ret = fOutdoorTemperature.value;
break;
case AVERAGE_10S:
ret = fOutdoorTemperature.average10s.value;
break;
case AVERAGE_60S:
ret = fOutdoorTemperature.average60s.value;
break;
default:
break;
}
ret = sOutdoorTemperature;
xSemaphoreGive(xMutexAccessInputs);
}
return ret;
}
float getInletFlowTemperature(eMeasurementMode mode)
sMeasurement getInletFlowTemperature(void)
{
float ret = 0.0f;
sMeasurement ret;
ret.state = MEASUREMENT_FAULT;
if (xSemaphoreTake(xMutexAccessInputs, portMAX_DELAY) == pdTRUE)
{
switch (mode)
{
case CURRENT:
ret = fInletFlowTemperature.value;
break;
case AVERAGE_10S:
ret = fInletFlowTemperature.average10s.value;
break;
case AVERAGE_60S:
ret = fInletFlowTemperature.average60s.value;
break;
default:
break;
}
ret = sInletFlowTemperature;
xSemaphoreGive(xMutexAccessInputs);
}
return ret;
}
float getReturnFlowTemperature(eMeasurementMode mode)
sMeasurement getReturnFlowTemperature(void)
{
float ret = 0.0f;
sMeasurement ret;
ret.state = MEASUREMENT_FAULT;
if (xSemaphoreTake(xMutexAccessInputs, portMAX_DELAY) == pdTRUE)
{
switch (mode)
{
case CURRENT:
ret = fReturnFlowTemperature.value;
break;
case AVERAGE_10S:
ret = fReturnFlowTemperature.average10s.value;
break;
case AVERAGE_60S:
ret = fReturnFlowTemperature.average60s.value;
break;
default:
break;
}
ret = sReturnFlowTemperature;
xSemaphoreGive(xMutexAccessInputs);
}
return ret;
}
eBurnerErrorState getBurnerError(void)
{
eBurnerErrorState ret = FAULT;

View File

@ -1,21 +1,40 @@
#pragma once
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define AVG10_SAMPLE_SIZE 10U
#define AVG60_SAMPLE_SIZE 60U
typedef enum _BurnerErrorState
{
NO_ERROR,
FAULT
} eBurnerErrorState;
typedef enum _MeasurementMode
typedef enum _MeasurementErrorState
{
CURRENT,
AVERAGE_10S,
AVERAGE_60S
} eMeasurementMode;
MEASUREMENT_NO_ERROR,
MEASUREMENT_FAULT
} eMeasurementErrorState;
typedef struct _Average
{
float fValue;
float samples[MAX(AVG10_SAMPLE_SIZE, AVG60_SAMPLE_SIZE)];
size_t bufferIndex;
size_t bufferCount;
} sAverage;
typedef struct _Measurement
{
float fCurrentValue;
sAverage average10s;
sAverage average60s;
eMeasurementErrorState state;
} sMeasurement;
void initInputs(void);
float getChamberTemperature(eMeasurementMode mode);
float getOutdoorTemperature(eMeasurementMode mode);
float getInletFlowTemperature(eMeasurementMode mode);
float getReturnFlowTemperature(eMeasurementMode mode);
sMeasurement getChamberTemperature(void);
sMeasurement getOutdoorTemperature(void);
sMeasurement getInletFlowTemperature(void);
sMeasurement getReturnFlowTemperature(void);
eBurnerErrorState getBurnerError(void);

View File

@ -19,6 +19,7 @@
#include "metrics.h"
#include "outputs.h"
#include "inputs.h"
#include "safety.h"
static EventGroupHandle_t s_wifi_event_group;
@ -42,7 +43,7 @@ void initMetrics(void)
BaseType_t taskCreated = xTaskCreate(
taskMetrics, // Function to implement the task
"taskMetrics", // Task name
4096, // Stack size (in words, not bytes)
16384, // Stack size (in words, not bytes)
NULL, // Parameters to the task function (none in this case)
5, // Task priority (higher number = higher priority)
NULL // Task handle (optional)
@ -123,62 +124,78 @@ void taskMetrics(void *pvParameters)
/*Chamber Temperature*/
strcpy(aMetrics[u16MetricCounter].caMetricName, "chamber_temperature");
aMetrics[u16MetricCounter].fMetricValue = getChamberTemperature(CURRENT);
aMetrics[u16MetricCounter].fMetricValue = getChamberTemperature().fCurrentValue;
u16MetricCounter++;
/*Outdoor Temperature*/
strcpy(aMetrics[u16MetricCounter].caMetricName, "outdoor_temperature");
aMetrics[u16MetricCounter].fMetricValue = getOutdoorTemperature(CURRENT);
aMetrics[u16MetricCounter].fMetricValue = getOutdoorTemperature().fCurrentValue;
u16MetricCounter++;
/*Chamber Temperature*/
strcpy(aMetrics[u16MetricCounter].caMetricName, "inlet_flow_temperature");
aMetrics[u16MetricCounter].fMetricValue = getInletFlowTemperature(CURRENT);
aMetrics[u16MetricCounter].fMetricValue = getInletFlowTemperature().fCurrentValue;
u16MetricCounter++;
/*Chamber Temperature*/
strcpy(aMetrics[u16MetricCounter].caMetricName, "return_flow_temperature");
aMetrics[u16MetricCounter].fMetricValue = getReturnFlowTemperature(CURRENT);
aMetrics[u16MetricCounter].fMetricValue = getReturnFlowTemperature().fCurrentValue;
u16MetricCounter++;
/*Chamber Temperature Average 10s*/
strcpy(aMetrics[u16MetricCounter].caMetricName, "chamber_temperature_avg10");
aMetrics[u16MetricCounter].fMetricValue = getChamberTemperature(AVERAGE_10S);
aMetrics[u16MetricCounter].fMetricValue = getChamberTemperature().average10s.fValue;
u16MetricCounter++;
/*Outdoor Temperature Average 10s*/
strcpy(aMetrics[u16MetricCounter].caMetricName, "outdoor_temperature_avg10");
aMetrics[u16MetricCounter].fMetricValue = getOutdoorTemperature(AVERAGE_10S);
aMetrics[u16MetricCounter].fMetricValue = getOutdoorTemperature().average10s.fValue;
u16MetricCounter++;
/*Chamber Temperature Average 10s*/
strcpy(aMetrics[u16MetricCounter].caMetricName, "inlet_flow_temperature_avg10");
aMetrics[u16MetricCounter].fMetricValue = getInletFlowTemperature(AVERAGE_10S);
aMetrics[u16MetricCounter].fMetricValue = getInletFlowTemperature().average10s.fValue;
u16MetricCounter++;
/*Chamber Temperature Average 10s*/
strcpy(aMetrics[u16MetricCounter].caMetricName, "return_flow_temperature_avg10");
aMetrics[u16MetricCounter].fMetricValue = getReturnFlowTemperature(AVERAGE_10S);
aMetrics[u16MetricCounter].fMetricValue = getReturnFlowTemperature().average10s.fValue;
u16MetricCounter++;
/*Chamber Temperature Average 60s*/
strcpy(aMetrics[u16MetricCounter].caMetricName, "chamber_temperature_avg60");
aMetrics[u16MetricCounter].fMetricValue = getChamberTemperature(AVERAGE_60S);
aMetrics[u16MetricCounter].fMetricValue = getChamberTemperature().average60s.fValue;
u16MetricCounter++;
/*Outdoor Temperature Average 60s*/
strcpy(aMetrics[u16MetricCounter].caMetricName, "outdoor_temperature_avg60");
aMetrics[u16MetricCounter].fMetricValue = getOutdoorTemperature(AVERAGE_60S);
aMetrics[u16MetricCounter].fMetricValue = getOutdoorTemperature().average60s.fValue;
u16MetricCounter++;
/*Chamber Temperature Average 60s*/
strcpy(aMetrics[u16MetricCounter].caMetricName, "inlet_flow_temperature_avg60");
aMetrics[u16MetricCounter].fMetricValue = getInletFlowTemperature(AVERAGE_60S);
aMetrics[u16MetricCounter].fMetricValue = getInletFlowTemperature().average60s.fValue;
u16MetricCounter++;
/*Chamber Temperature Average 60s*/
strcpy(aMetrics[u16MetricCounter].caMetricName, "return_flow_temperature_avg60");
aMetrics[u16MetricCounter].fMetricValue = getReturnFlowTemperature(AVERAGE_60S);
aMetrics[u16MetricCounter].fMetricValue = getReturnFlowTemperature().average60s.fValue;
u16MetricCounter++;
/*Sensor status*/
sSensorSanityCheck aChecks[NUMBER_OF_SENSOR_SANITY_CHECKS];
getSensorSanityStates(aChecks);
for (size_t i = 0; i < NUMBER_OF_SENSOR_SANITY_CHECKS; i++)
{
strcpy(aMetrics[u16MetricCounter].caMetricName, aChecks[i].name);
strcat(aMetrics[u16MetricCounter].caMetricName, "_status");
aMetrics[u16MetricCounter].fMetricValue = aChecks[i].status;
u16MetricCounter++;
}
/*Safety state*/
strcpy(aMetrics[u16MetricCounter].caMetricName, "safety_state");
aMetrics[u16MetricCounter].fMetricValue = getSafetyState();
u16MetricCounter++;
vSetMetrics(aMetrics, u16MetricCounter);

View File

@ -1,6 +1,7 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include <string.h>
#include "safety.h"
#define PERIODIC_INTERVAL 1U // run safety checks every 1sec
@ -8,11 +9,12 @@
static const char *TAG = "smart-oil-heater-control-system-safety";
static SemaphoreHandle_t xMutexAccessSafety = NULL;
sSensorSanityCheck sanityChecks[NUMBER_OF_SENSOR_SANITY_CHECKS] = {
{0U, "chamber_temperature", {95.0f, -10.0f}, 0.0f, 0U, getChamberTemperature},
{0U, "outdoor_temperature", {45.0f, -20.0f}, 0.0f, 0U, getOutdoorTemperature},
{0U, "inlet_flow_temperature", {95.0f, -10.0f}, 0.0f, 0U, getInletFlowTemperature},
{0U, "return_flow_temperature", {95.0f, -10.0f}, 0.0f, 0U, getReturnFlowTemperature}};
static sSensorSanityCheck sanityChecks[NUMBER_OF_SENSOR_SANITY_CHECKS] = {
{SENSOR_NO_ERROR, "chamber_temperature", {95.0f, -10.0f}, 0.0f, 0U, getChamberTemperature},
{SENSOR_NO_ERROR, "outdoor_temperature", {45.0f, -20.0f}, 0.0f, 0U, getOutdoorTemperature},
{SENSOR_NO_ERROR, "inlet_flow_temperature", {95.0f, -10.0f}, 0.0f, 0U, getInletFlowTemperature},
{SENSOR_NO_ERROR, "return_flow_temperature", {95.0f, -10.0f}, 0.0f, 0U, getReturnFlowTemperature}};
static eSafetyState sSafetyState = SAFETY_NO_ERROR;
void taskSafety(void *pvParameters);
void checkSensorSanity(void);
@ -30,7 +32,7 @@ void initSafety(void)
BaseType_t taskCreated = xTaskCreate(
taskSafety, // Function to implement the task
"taskSafety", // Task name
2048, // Stack size (in words, not bytes)
4096, // Stack size (in words, not bytes)
NULL, // Parameters to the task function (none in this case)
5, // Task priority (higher number = higher priority)
NULL // Task handle (optional)
@ -52,13 +54,18 @@ void taskSafety(void *pvParameters)
{
vTaskDelay(PERIODIC_INTERVAL * 1000U / portTICK_PERIOD_MS);
if (xSemaphoreTake(xMutexAccessSafety, portMAX_DELAY) == pdTRUE)
{
checkSensorSanity();
xSemaphoreGive(xMutexAccessSafety);
}
}
}
void checkSensorSanity(void)
{
sSafetyState = SAFETY_NO_ERROR;
for (int i = 0; i < NUMBER_OF_SENSOR_SANITY_CHECKS; i++)
{
// printf("Check sanity of sensor %s:\n", sanityChecks[i].name);
@ -66,34 +73,47 @@ void checkSensorSanity(void)
// printf(" Sensor Limits: Max = %.2f, Min = %.2f\n", sanityChecks[i].sSensorLimit.max, sanityChecks[i].sSensorLimit.min);
// printf(" Last Sensor Temperature: %.2f\n", sanityChecks[i].fSensorTemperatureLast);
const float fSensorTemperatureCurrent = sanityChecks[i].getSensor(CURRENT);
if (fSensorTemperatureCurrent == sanityChecks[i].fSensorTemperatureLast)
const sMeasurement sCurrentMeasurement = sanityChecks[i].getSensor();
if (sCurrentMeasurement.state == MEASUREMENT_FAULT)
{
ESP_LOGE(TAG, "%s Sensor not found!", sanityChecks[i].name);
sanityChecks[i].status = SENSOR_NOT_FOUND;
sSafetyState = SAFETY_SENSOR_ERROR;
}
else
{
if (sCurrentMeasurement.fCurrentValue == sanityChecks[i].fSensorTemperatureLast)
{
sanityChecks[i].uUnchangedCounter++;
if (sanityChecks[i].uUnchangedCounter >= (SENSOR_GRACE_PERIOD / PERIODIC_INTERVAL))
{
ESP_LOGE(TAG, "%s Sensor reported unchanged value! %lf == %lf", sanityChecks[i].name, fSensorTemperatureCurrent, sanityChecks[i].fSensorTemperatureLast);
sanityChecks[i].status = 1U;
ESP_LOGE(TAG, "%s Sensor reported unchanged value! %lf == %lf", sanityChecks[i].name, sCurrentMeasurement.fCurrentValue, sanityChecks[i].fSensorTemperatureLast);
sanityChecks[i].status = SENSOR_UNCHANGED;
sSafetyState = SAFETY_SENSOR_ERROR;
}
}
else
{
sanityChecks[i].fSensorTemperatureLast = fSensorTemperatureCurrent;
sanityChecks[i].fSensorTemperatureLast = sCurrentMeasurement.fCurrentValue;
if (fSensorTemperatureCurrent > sanityChecks[i].sSensorLimit.max)
if (sCurrentMeasurement.fCurrentValue > sanityChecks[i].sSensorLimit.max)
{
ESP_LOGE(TAG, "%s Sensor reported too high value! %lf > %lf", sanityChecks[i].name, fSensorTemperatureCurrent, sanityChecks[i].sSensorLimit.max);
sanityChecks[i].status = 1U;
ESP_LOGE(TAG, "%s Sensor reported too high value! %lf > %lf", sanityChecks[i].name, sCurrentMeasurement.fCurrentValue, sanityChecks[i].sSensorLimit.max);
sanityChecks[i].status = SENSOR_TOO_HIGH;
sSafetyState = SAFETY_SENSOR_ERROR;
}
else if (fSensorTemperatureCurrent < sanityChecks[i].sSensorLimit.min)
else if (sCurrentMeasurement.fCurrentValue < sanityChecks[i].sSensorLimit.min)
{
ESP_LOGE(TAG, "%s Sensor reported too low value! %lf < %lf", sanityChecks[i].name, fSensorTemperatureCurrent, sanityChecks[i].sSensorLimit.min);
sanityChecks[i].status = 1U;
ESP_LOGE(TAG, "%s Sensor reported too low value! %lf < %lf", sanityChecks[i].name, sCurrentMeasurement.fCurrentValue, sanityChecks[i].sSensorLimit.min);
sanityChecks[i].status = SENSOR_TOO_LOW;
sSafetyState = SAFETY_SENSOR_ERROR;
}
else
{
sanityChecks[i].uUnchangedCounter = 0U;
sanityChecks[i].status = 0U;
sanityChecks[i].status = SENSOR_NO_ERROR;
}
}
}
// printf(" Status: %u\n", sanityChecks[i].status);
@ -106,9 +126,27 @@ void setSafeState(void)
setBurnerState(DISABLED);
}
/*
sSafetyStateElement *getSafetyStates(void)
void getSensorSanityStates(sSensorSanityCheck *pSensorSanityChecks)
{
return safetyStates;
if (xSemaphoreTake(xMutexAccessSafety, portMAX_DELAY) == pdTRUE)
{
for (size_t i = 0; i < NUMBER_OF_SENSOR_SANITY_CHECKS; i++)
{
// Copy only the needed attributes
pSensorSanityChecks[i].status = sanityChecks[i].status;
strcpy(pSensorSanityChecks[i].name, sanityChecks[i].name);
}
xSemaphoreGive(xMutexAccessSafety);
}
}
eSafetyState getSafetyState(void)
{
eSafetyState state = SAFETY_NO_ERROR;
if (xSemaphoreTake(xMutexAccessSafety, portMAX_DELAY) == pdTRUE)
{
state = sSafetyState;
xSemaphoreGive(xMutexAccessSafety);
}
return state;
}
*/

View File

@ -6,7 +6,22 @@
#define MAX_ERROR_STRING_SIZE 64U
#define NUMBER_OF_SENSOR_SANITY_CHECKS 4U
typedef float (*GetSensorValue)(eMeasurementMode);
typedef enum _SensorErrorState
{
SENSOR_NO_ERROR,
SENSOR_TOO_HIGH,
SENSOR_TOO_LOW,
SENSOR_UNCHANGED,
SENSOR_NOT_FOUND
} eSensorErrorState;
typedef enum _SafetyState
{
SAFETY_NO_ERROR,
SAFETY_SENSOR_ERROR,
} eSafetyState;
typedef sMeasurement (*GetSensorValue)();
typedef struct _TemperatureSensorLimit
{
float max; // Maximum temperature limit
@ -14,7 +29,7 @@ typedef struct _TemperatureSensorLimit
} sTemperatureSensorLimit;
typedef struct _SensorSanityCheck
{
uint8_t status;
eSensorErrorState status;
char name[MAX_ERROR_STRING_SIZE];
sTemperatureSensorLimit sSensorLimit;
float fSensorTemperatureLast;
@ -23,5 +38,5 @@ typedef struct _SensorSanityCheck
} sSensorSanityCheck;
void initSafety(void);
//sSensorSanityCheck *getSafetyStates(void);
void getSensorSanityStates(sSensorSanityCheck *pSensorSanityChecks);
eSafetyState getSafetyState(void);