safety state and input error detection
This commit is contained in:
218
main/inputs.c
218
main/inputs.c
@ -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,168 +122,133 @@ 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)
|
||||
{
|
||||
sBurnerErrorState = FAULT;
|
||||
}
|
||||
else
|
||||
{
|
||||
sBurnerErrorState = NO_ERROR;
|
||||
}
|
||||
|
||||
if (ds18x20_scan_devices(uDS18B20Pin, uOneWireAddresses, MAX_DN18B20_SENSORS, &sSensorCount) != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "1-Wire device scan error!");
|
||||
}
|
||||
|
||||
if (!sSensorCount)
|
||||
{
|
||||
ESP_LOGW(TAG, "No 1-Wire devices detected!");
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG, "%d 1-Wire devices detected", sSensorCount);
|
||||
|
||||
if (sSensorCount > MAX_DN18B20_SENSORS)
|
||||
if (gpio_get_level(uBurnerFaultPin) == 1)
|
||||
{
|
||||
sSensorCount = MAX_DN18B20_SENSORS;
|
||||
ESP_LOGW(TAG, "More 1-Wire devices found than expected!");
|
||||
}
|
||||
|
||||
if (ds18x20_measure_and_read_multi(uDS18B20Pin, uOneWireAddresses, sSensorCount, fDS18B20Temps) != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "1-Wire devices read error");
|
||||
sBurnerErrorState = FAULT;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int j = 0; j < sSensorCount; j++)
|
||||
sBurnerErrorState = NO_ERROR;
|
||||
}
|
||||
|
||||
if (ds18x20_scan_devices(uDS18B20Pin, uOneWireAddresses, MAX_DN18B20_SENSORS, &sSensorCount) != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "1-Wire device scan error!");
|
||||
}
|
||||
|
||||
if (!sSensorCount)
|
||||
{
|
||||
ESP_LOGW(TAG, "No 1-Wire devices detected!");
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG, "%d 1-Wire devices detected", sSensorCount);
|
||||
|
||||
if (sSensorCount > MAX_DN18B20_SENSORS)
|
||||
{
|
||||
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)
|
||||
sSensorCount = MAX_DN18B20_SENSORS;
|
||||
ESP_LOGW(TAG, "More 1-Wire devices found than expected!");
|
||||
}
|
||||
|
||||
if (ds18x20_measure_and_read_multi(uDS18B20Pin, uOneWireAddresses, sSensorCount, fDS18B20Temps) != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "1-Wire devices read error");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int j = 0; j < sSensorCount; j++)
|
||||
{
|
||||
float temp_c = fDS18B20Temps[j];
|
||||
ESP_LOGI(TAG, "Sensor: %08" PRIx64 " reports %lf°C", (uint64_t)uOneWireAddresses[j], temp_c);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
Reference in New Issue
Block a user