Merge pull request 'Add control loop state' (#7) from feature/control-status into main
Reviewed-on: #7
This commit is contained in:
commit
859611f991
96
README.md
96
README.md
@ -40,6 +40,7 @@ Sntp <|-- Metrics
|
|||||||
class Control{
|
class Control{
|
||||||
+taskControl()
|
+taskControl()
|
||||||
-timetable
|
-timetable
|
||||||
|
+getControlState()
|
||||||
}
|
}
|
||||||
|
|
||||||
class Safety{
|
class Safety{
|
||||||
@ -71,12 +72,91 @@ Sntp <|-- Metrics
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Hardware
|
### Prometheus Metrics
|
||||||
|
`curl http://X.X.X.X:9100/metrics`
|
||||||
|
#### Example
|
||||||
|
```
|
||||||
|
burner_fault_pending 1
|
||||||
|
circulation_pump_enabled 0
|
||||||
|
burner_enabled 1
|
||||||
|
safety_contact_enabled 1
|
||||||
|
chamber_temperature 21.812500
|
||||||
|
chamber_temperature_avg10 21.837500
|
||||||
|
chamber_temperature_avg60 21.825521
|
||||||
|
inlet_flow_temperature 22.437500
|
||||||
|
inlet_flow_temperature_avg10 22.437500
|
||||||
|
inlet_flow_temperature_avg60 22.434896
|
||||||
|
outdoor_temperature 21.937500
|
||||||
|
outdoor_temperature_avg10 21.937500
|
||||||
|
outdoor_temperature_avg60 21.933594
|
||||||
|
return_flow_temperature 22.375000
|
||||||
|
return_flow_temperature_avg10 22.375000
|
||||||
|
return_flow_temperature_avg60 22.375000
|
||||||
|
chamber_temperature_state 0
|
||||||
|
outdoor_temperature_state 0
|
||||||
|
inlet_flow_temperature_state 0
|
||||||
|
return_flow_temperature_state 0
|
||||||
|
safety_state 0
|
||||||
|
control_state 5
|
||||||
|
sntp_state 0
|
||||||
|
system_unixtime 1734814285
|
||||||
|
uptime_seconds 90
|
||||||
|
wifi_rssi -63
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Status Encoding
|
||||||
|
##### Digital Themperatur Sensor DS10B20
|
||||||
|
- chamber_temperature_state
|
||||||
|
- outdoor_temperature_state
|
||||||
|
- inlet_flow_temperature_state
|
||||||
|
- return_flow_temperature_state
|
||||||
|
|
||||||
|
| Enum eSensorErrorState in [safety.h](main/safety.h) | Value | Description |
|
||||||
|
|-----------------------------------------------------|-------|---------------------|
|
||||||
|
| SENSOR_NO_ERROR | 0 | |
|
||||||
|
| SENSOR_TOO_HIGH | 1 | Sanity check failed |
|
||||||
|
| SENSOR_TOO_LOW | 2 | Sanity check failed |
|
||||||
|
| SENSOR_UNCHANGED | 3 | Sanity check failed |
|
||||||
|
| SENSOR_NOT_FOUND | 4 | No Communication |
|
||||||
|
|
||||||
|
##### Safety Loop
|
||||||
|
- safety_state
|
||||||
|
|
||||||
|
| Enum eSafetyState in [safety.h](main/safety.h) | Value | Description |
|
||||||
|
|------------------------------------------------|-------|----------------------------|
|
||||||
|
| SAFETY_NO_ERROR | 0 | |
|
||||||
|
| SAFETY_SENSOR_ERROR | 1 | At least one sensor failed |
|
||||||
|
| SAFETY_INTERNAL_ERROR | 2 | Internal error |
|
||||||
|
|
||||||
|
##### Control Loop
|
||||||
|
- control_state
|
||||||
|
|
||||||
|
| Enum eControlState in [control.h](main/control.h) | Value | Description |
|
||||||
|
|---------------------------------------------------|-------|-----------------------|
|
||||||
|
| CONTROL_STARTING | 0 | |
|
||||||
|
| CONTROL_HEATING | 1 | Burner running |
|
||||||
|
| CONTROL_OUTDOOR_TOO_WARM | 2 | Heating not needed |
|
||||||
|
| CONTROL_RETURN_FLOW_TOO_WARM | 3 | Heating not needed |
|
||||||
|
| CONTROL_BURNER_FAULT | 4 | Burner reported fault |
|
||||||
|
| CONTROL_FAULT | 5 | Unable to control |
|
||||||
|
|
||||||
|
##### SNTP Client
|
||||||
|
- sntp_state
|
||||||
|
|
||||||
|
| Enum eSntpState in [sntp.h](main/sntp.h) | Value | Description |
|
||||||
|
|------------------------------------------|-------|-------------|
|
||||||
|
| SYNC_SUCCESSFUL | 0 | |
|
||||||
|
| SYNC_NOT_STARTED | 1 | |
|
||||||
|
| SYNC_FAILED | 2 | |
|
||||||
|
|
||||||
|
## Hardware
|
||||||
|
|
||||||
|
| Function | ESP32 | PLC ES32C14 |
|
||||||
|
|---------------------------------------|-------|-------------------|
|
||||||
|
| Output CirculationPump | IO27 | Relay 1 NC1 |
|
||||||
|
| Output Burner Fire Signal | IO14 | Relay 2 NC2 |
|
||||||
|
| Output Safety Contact (powers Burner) | IO12 | Relay 3 NC2 |
|
||||||
|
| Input Burner Fault | IO19 | Digital Input IN1 |
|
||||||
|
| Input Temperature DS10B20 | IO04 | 1-Wire |
|
||||||
|
|
||||||
|
|
||||||
| Function | ESP32 | PLC ES32C14 |
|
|
||||||
|---------------------------------------|-------|---------------------------|
|
|
||||||
| Output CirculationPump | IO27 | Relay 1 NC1 |
|
|
||||||
| Output Burner Fire Signal | IO14 | Relay 2 NC2 |
|
|
||||||
| Output Safety Contact (powers Burner) | IO12 | Relay 3 NC2 |
|
|
||||||
| Input Burner Fault | IO19 | Digital Input IN1 |
|
|
||||||
| Input Temperature DS10B20 | IO04 | 1-Wire |
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#define PERIODIC_INTERVAL 1U // run safety checks every 1sec
|
#define PERIODIC_INTERVAL 1U // run safety checks every 1sec
|
||||||
|
|
||||||
static const char *TAG = "smart-oil-heater-control-system-control";
|
static const char *TAG = "smart-oil-heater-control-system-control";
|
||||||
|
static eControlState sControlState = CONTROL_STARTING;
|
||||||
void taskControl(void *pvParameters);
|
void taskControl(void *pvParameters);
|
||||||
|
|
||||||
void initControl(void)
|
void initControl(void)
|
||||||
@ -44,12 +44,14 @@ void taskControl(void *pvParameters)
|
|||||||
if (getSafetyState() != SAFETY_NO_ERROR)
|
if (getSafetyState() != SAFETY_NO_ERROR)
|
||||||
{
|
{
|
||||||
ESP_LOGW(TAG, "Control not possible due to safety fault!");
|
ESP_LOGW(TAG, "Control not possible due to safety fault!");
|
||||||
|
sControlState = CONTROL_FAULT;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getSntpState() != SYNC_SUCCESSFUL)
|
if (getSntpState() != SYNC_SUCCESSFUL)
|
||||||
{
|
{
|
||||||
ESP_LOGW(TAG, "Control not possible due to sntp fault!");
|
ESP_LOGW(TAG, "Control not possible due to sntp fault!");
|
||||||
|
sControlState = CONTROL_FAULT;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,4 +60,9 @@ void taskControl(void *pvParameters)
|
|||||||
setBurnerState(ENABLED);
|
setBurnerState(ENABLED);
|
||||||
setSafetyControlState(ENABLED);
|
setSafetyControlState(ENABLED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eControlState getControlState(void)
|
||||||
|
{
|
||||||
|
return sControlState;
|
||||||
|
}
|
||||||
|
@ -1,3 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
void initControl(void);
|
typedef enum _ControlState
|
||||||
|
{
|
||||||
|
CONTROL_STARTING,
|
||||||
|
CONTROL_HEATING,
|
||||||
|
CONTROL_OUTDOOR_TOO_WARM,
|
||||||
|
CONTROL_RETURN_FLOW_TOO_WARM,
|
||||||
|
CONTROL_BURNER_FAULT,
|
||||||
|
CONTROL_FAULT,
|
||||||
|
} eControlState;
|
||||||
|
|
||||||
|
void initControl(void);
|
||||||
|
eControlState getControlState(void);
|
@ -12,6 +12,7 @@
|
|||||||
#include "inputs.h"
|
#include "inputs.h"
|
||||||
#include "safety.h"
|
#include "safety.h"
|
||||||
#include "sntp.h"
|
#include "sntp.h"
|
||||||
|
#include "control.h"
|
||||||
|
|
||||||
static const char *TAG = "smart-oil-heater-control-system-metrics";
|
static const char *TAG = "smart-oil-heater-control-system-metrics";
|
||||||
|
|
||||||
@ -181,15 +182,15 @@ void taskMetrics(void *pvParameters)
|
|||||||
aMetrics[u16MetricCounter].fMetricValue = getReturnFlowTemperature().average60s.fValue;
|
aMetrics[u16MetricCounter].fMetricValue = getReturnFlowTemperature().average60s.fValue;
|
||||||
u16MetricCounter++;
|
u16MetricCounter++;
|
||||||
|
|
||||||
/*Sensor status*/
|
/*Sensor State*/
|
||||||
sSensorSanityCheck aChecks[NUMBER_OF_SENSOR_SANITY_CHECKS];
|
sSensorSanityCheck aChecks[NUMBER_OF_SENSOR_SANITY_CHECKS];
|
||||||
getSensorSanityStates(aChecks);
|
getSensorSanityStates(aChecks);
|
||||||
for (size_t i = 0; i < NUMBER_OF_SENSOR_SANITY_CHECKS; i++)
|
for (size_t i = 0; i < NUMBER_OF_SENSOR_SANITY_CHECKS; i++)
|
||||||
{
|
{
|
||||||
strcpy(aMetrics[u16MetricCounter].caMetricName, aChecks[i].name);
|
strcpy(aMetrics[u16MetricCounter].caMetricName, aChecks[i].name);
|
||||||
strcat(aMetrics[u16MetricCounter].caMetricName, "_status");
|
strcat(aMetrics[u16MetricCounter].caMetricName, "_state");
|
||||||
aMetrics[u16MetricCounter].type = INTEGER_U8;
|
aMetrics[u16MetricCounter].type = INTEGER_U8;
|
||||||
aMetrics[u16MetricCounter].u8MetricValue = aChecks[i].status;
|
aMetrics[u16MetricCounter].u8MetricValue = aChecks[i].state;
|
||||||
u16MetricCounter++;
|
u16MetricCounter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,8 +200,14 @@ void taskMetrics(void *pvParameters)
|
|||||||
aMetrics[u16MetricCounter].u8MetricValue = getSafetyState();
|
aMetrics[u16MetricCounter].u8MetricValue = getSafetyState();
|
||||||
u16MetricCounter++;
|
u16MetricCounter++;
|
||||||
|
|
||||||
/*SNTP Status*/
|
/*Control State*/
|
||||||
strcpy(aMetrics[u16MetricCounter].caMetricName, "sntp_status");
|
strcpy(aMetrics[u16MetricCounter].caMetricName, "control_state");
|
||||||
|
aMetrics[u16MetricCounter].type = INTEGER_U8;
|
||||||
|
aMetrics[u16MetricCounter].u8MetricValue = getControlState();
|
||||||
|
u16MetricCounter++;
|
||||||
|
|
||||||
|
/*SNTP State*/
|
||||||
|
strcpy(aMetrics[u16MetricCounter].caMetricName, "sntp_state");
|
||||||
aMetrics[u16MetricCounter].type = INTEGER_U8;
|
aMetrics[u16MetricCounter].type = INTEGER_U8;
|
||||||
aMetrics[u16MetricCounter].u8MetricValue = getSntpState();
|
aMetrics[u16MetricCounter].u8MetricValue = getSntpState();
|
||||||
u16MetricCounter++;
|
u16MetricCounter++;
|
||||||
|
@ -77,7 +77,7 @@ void checkSensorSanity(void)
|
|||||||
for (int i = 0; i < NUMBER_OF_SENSOR_SANITY_CHECKS; i++)
|
for (int i = 0; i < NUMBER_OF_SENSOR_SANITY_CHECKS; i++)
|
||||||
{
|
{
|
||||||
// printf("Check sanity of sensor %s:\n", sanityChecks[i].name);
|
// printf("Check sanity of sensor %s:\n", sanityChecks[i].name);
|
||||||
// printf(" Status: %u\n", sanityChecks[i].status);
|
// printf(" state: %u\n", sanityChecks[i].state);
|
||||||
// printf(" Sensor Limits: Max = %.2f, Min = %.2f\n", sanityChecks[i].sSensorLimit.max, sanityChecks[i].sSensorLimit.min);
|
// 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);
|
// printf(" Last Sensor Temperature: %.2f\n", sanityChecks[i].fSensorTemperatureLast);
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ void checkSensorSanity(void)
|
|||||||
if (sCurrentMeasurement.state == MEASUREMENT_FAULT)
|
if (sCurrentMeasurement.state == MEASUREMENT_FAULT)
|
||||||
{
|
{
|
||||||
ESP_LOGE(TAG, "%s Sensor not found!", sanityChecks[i].name);
|
ESP_LOGE(TAG, "%s Sensor not found!", sanityChecks[i].name);
|
||||||
sanityChecks[i].status = SENSOR_NOT_FOUND;
|
sanityChecks[i].state = SENSOR_NOT_FOUND;
|
||||||
sSafetyState = SAFETY_SENSOR_ERROR;
|
sSafetyState = SAFETY_SENSOR_ERROR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -97,7 +97,7 @@ void checkSensorSanity(void)
|
|||||||
if (sanityChecks[i].uUnchangedCounter >= (SENSOR_GRACE_PERIOD / PERIODIC_INTERVAL))
|
if (sanityChecks[i].uUnchangedCounter >= (SENSOR_GRACE_PERIOD / PERIODIC_INTERVAL))
|
||||||
{
|
{
|
||||||
ESP_LOGE(TAG, "%s Sensor reported unchanged value! %lf == %lf", sanityChecks[i].name, sCurrentMeasurement.fCurrentValue, sanityChecks[i].fSensorTemperatureLast);
|
ESP_LOGE(TAG, "%s Sensor reported unchanged value! %lf == %lf", sanityChecks[i].name, sCurrentMeasurement.fCurrentValue, sanityChecks[i].fSensorTemperatureLast);
|
||||||
sanityChecks[i].status = SENSOR_UNCHANGED;
|
sanityChecks[i].state = SENSOR_UNCHANGED;
|
||||||
sSafetyState = SAFETY_SENSOR_ERROR;
|
sSafetyState = SAFETY_SENSOR_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,23 +108,23 @@ void checkSensorSanity(void)
|
|||||||
if (sCurrentMeasurement.fCurrentValue > 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, sCurrentMeasurement.fCurrentValue, sanityChecks[i].sSensorLimit.max);
|
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;
|
sanityChecks[i].state = SENSOR_TOO_HIGH;
|
||||||
sSafetyState = SAFETY_SENSOR_ERROR;
|
sSafetyState = SAFETY_SENSOR_ERROR;
|
||||||
}
|
}
|
||||||
else if (sCurrentMeasurement.fCurrentValue < 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, sCurrentMeasurement.fCurrentValue, sanityChecks[i].sSensorLimit.min);
|
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;
|
sanityChecks[i].state = SENSOR_TOO_LOW;
|
||||||
sSafetyState = SAFETY_SENSOR_ERROR;
|
sSafetyState = SAFETY_SENSOR_ERROR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sanityChecks[i].uUnchangedCounter = 0U;
|
sanityChecks[i].uUnchangedCounter = 0U;
|
||||||
sanityChecks[i].status = SENSOR_NO_ERROR;
|
sanityChecks[i].state = SENSOR_NO_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// printf(" Status: %u\n", sanityChecks[i].status);
|
// printf(" state: %u\n", sanityChecks[i].state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +142,7 @@ void getSensorSanityStates(sSensorSanityCheck *pSensorSanityChecks)
|
|||||||
for (size_t i = 0; i < NUMBER_OF_SENSOR_SANITY_CHECKS; i++)
|
for (size_t i = 0; i < NUMBER_OF_SENSOR_SANITY_CHECKS; i++)
|
||||||
{
|
{
|
||||||
// Copy only the needed attributes
|
// Copy only the needed attributes
|
||||||
pSensorSanityChecks[i].status = sanityChecks[i].status;
|
pSensorSanityChecks[i].state = sanityChecks[i].state;
|
||||||
strcpy(pSensorSanityChecks[i].name, sanityChecks[i].name);
|
strcpy(pSensorSanityChecks[i].name, sanityChecks[i].name);
|
||||||
}
|
}
|
||||||
xSemaphoreGiveRecursive(xMutexAccessSafety);
|
xSemaphoreGiveRecursive(xMutexAccessSafety);
|
||||||
|
@ -30,7 +30,7 @@ typedef struct _TemperatureSensorLimit
|
|||||||
} sTemperatureSensorLimit;
|
} sTemperatureSensorLimit;
|
||||||
typedef struct _SensorSanityCheck
|
typedef struct _SensorSanityCheck
|
||||||
{
|
{
|
||||||
eSensorErrorState status;
|
eSensorErrorState state;
|
||||||
char name[MAX_ERROR_STRING_SIZE];
|
char name[MAX_ERROR_STRING_SIZE];
|
||||||
sTemperatureSensorLimit sSensorLimit;
|
sTemperatureSensorLimit sSensorLimit;
|
||||||
float fSensorTemperatureLast;
|
float fSensorTemperatureLast;
|
||||||
|
Loading…
Reference in New Issue
Block a user