Merge pull request #8497 from arijav/new_branch

Update thermostat controller with 2 new commands
This commit is contained in:
Theo Arends 2020-05-21 08:35:26 +02:00 committed by GitHub
commit f3a577d0fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 69 additions and 13 deletions

View File

@ -24,8 +24,8 @@
// Enable/disable debugging
//#define DEBUG_THERMOSTAT
// Enable/disable experimental PI auto-tuning inspired by the Arduino Autotune Library by
// Brett Beauregard <br3ttb@gmail.com> brettbeauregard.com
// Enable/disable experimental PI auto-tuning inspired by the Arduino
// Autotune Library by Brett Beauregard
//#define USE_PI_AUTOTUNING // (Ziegler-Nichols closed loop method)
#ifdef DEBUG_THERMOSTAT
@ -75,6 +75,8 @@
#define D_CMND_TIMEPIINTEGRREAD "TimePiIntegrRead"
#define D_CMND_TIMESENSLOSTSET "TimeSensLostSet"
#define D_CMND_DIAGNOSTICMODESET "DiagnosticModeSet"
#define D_CMND_CTRDUTYCYCLEREAD "CtrDutyCycleRead"
#define D_CMND_ENABLEOUTPUTSET "EnableOutputSet"
enum ThermostatModes { THERMOSTAT_OFF, THERMOSTAT_AUTOMATIC_OP, THERMOSTAT_MANUAL_OP, THERMOSTAT_MODES_MAX };
#ifdef USE_PI_AUTOTUNING
@ -100,7 +102,11 @@ enum ThermostatSupportedInputSwitches {
THERMOSTAT_INPUT_SWT1 = 1, // Buttons
THERMOSTAT_INPUT_SWT2,
THERMOSTAT_INPUT_SWT3,
THERMOSTAT_INPUT_SWT4
THERMOSTAT_INPUT_SWT4,
THERMOSTAT_INPUT_SWT5,
THERMOSTAT_INPUT_SWT6,
THERMOSTAT_INPUT_SWT7,
THERMOSTAT_INPUT_SWT8
};
enum ThermostatSupportedOutputRelays {
THERMOSTAT_OUTPUT_NONE,
@ -132,12 +138,12 @@ typedef union {
uint32_t counter_seconds : 6; // Second counter used to track minutes
uint32_t output_relay_number : 4; // Output relay number
uint32_t input_switch_number : 3; // Input switch number
uint32_t enable_output : 1; // Enables / disables the physical output
#ifdef USE_PI_AUTOTUNING
uint32_t autotune_flag : 1; // Enable/disable autotune
uint32_t autotune_perf_mode : 2; // Autotune performance mode
uint32_t free : 1; // Free bits
#else
uint32_t free : 4; // Free bits
uint32_t free : 3; // Free bits
#endif // USE_PI_AUTOTUNING
};
} ThermostatStateBitfield;
@ -168,7 +174,8 @@ const char kThermostatCommands[] PROGMEM = "|" D_CMND_THERMOSTATMODESET "|" D_CM
#endif // USE_PI_AUTOTUNING
D_CMND_TIMEMINACTIONSET "|" D_CMND_TIMEMINTURNOFFACTIONSET "|" D_CMND_TEMPRUPDELTINSET "|" D_CMND_TEMPRUPDELTOUTSET "|"
D_CMND_TIMERAMPUPMAXSET "|" D_CMND_TIMERAMPUPCYCLESET "|" D_CMND_TEMPRAMPUPPIACCERRSET "|" D_CMND_TIMEPIPROPORTREAD "|"
D_CMND_TIMEPIINTEGRREAD "|" D_CMND_TIMESENSLOSTSET "|" D_CMND_DIAGNOSTICMODESET;
D_CMND_TIMEPIINTEGRREAD "|" D_CMND_TIMESENSLOSTSET "|" D_CMND_DIAGNOSTICMODESET "|" D_CMND_CTRDUTYCYCLEREAD "|"
D_CMND_ENABLEOUTPUTSET;
void (* const ThermostatCommand[])(void) PROGMEM = {
&CmndThermostatModeSet, &CmndClimateModeSet, &CmndTempFrostProtectSet, &CmndControllerModeSet, &CmndInputSwitchSet,
@ -181,7 +188,8 @@ void (* const ThermostatCommand[])(void) PROGMEM = {
&CmndTimeMaxActionSet, &CmndTimeMinActionSet, &CmndTimeMinTurnoffActionSet, &CmndTempRupDeltInSet,
#endif // USE_PI_AUTOTUNING
&CmndTempRupDeltOutSet, &CmndTimeRampupMaxSet, &CmndTimeRampupCycleSet, &CmndTempRampupPiAccErrSet,
&CmndTimePiProportRead, &CmndTimePiIntegrRead, &CmndTimeSensLostSet, &CmndDiagnosticModeSet };
&CmndTimePiProportRead, &CmndTimePiIntegrRead, &CmndTimeSensLostSet, &CmndDiagnosticModeSet, &CmndCtrDutyCycleRead,
&CmndEnableOutputSet };
struct THERMOSTAT {
ThermostatStateBitfield status; // Bittfield including states as well as several flags
@ -268,6 +276,7 @@ void ThermostatInit(uint8_t ctr_output)
Thermostat[ctr_output].status.output_relay_number = (THERMOSTAT_RELAY_NUMBER + ctr_output);
Thermostat[ctr_output].status.input_switch_number = (THERMOSTAT_SWITCH_NUMBER + ctr_output);
Thermostat[ctr_output].status.use_input = INPUT_NOT_USED;
Thermostat[ctr_output].status.enable_output = IFACE_ON;
Thermostat[ctr_output].diag.output_inconsist_ctr = 0;
Thermostat[ctr_output].diag.diagnostic_mode = DIAGNOSTIC_ON;
#ifdef USE_PI_AUTOTUNING
@ -275,7 +284,9 @@ void ThermostatInit(uint8_t ctr_output)
Thermostat[ctr_output].status.autotune_perf_mode = AUTOTUNE_PERF_FAST;
#endif // USE_PI_AUTOTUNING
// Make sure the Output is OFF
ExecuteCommandPower(Thermostat[ctr_output].status.output_relay_number, POWER_OFF, SRC_THERMOSTAT);
if (Thermostat[ctr_output].status.enable_output == IFACE_ON) {
ExecuteCommandPower(Thermostat[ctr_output].status.output_relay_number, POWER_OFF, SRC_THERMOSTAT);
}
}
bool ThermostatMinuteCounter(uint8_t ctr_output)
@ -292,7 +303,7 @@ bool ThermostatMinuteCounter(uint8_t ctr_output)
inline bool ThermostatSwitchIdValid(uint8_t switchId)
{
return (switchId >= THERMOSTAT_INPUT_SWT1 && switchId <= THERMOSTAT_INPUT_SWT4);
return (switchId >= THERMOSTAT_INPUT_SWT1 && switchId <= THERMOSTAT_INPUT_SWT8);
}
inline bool ThermostatRelayIdValid(uint8_t relayId)
@ -366,7 +377,8 @@ void ThermostatSignalPreProcessingSlow(uint8_t ctr_output)
void ThermostatSignalPostProcessingSlow(uint8_t ctr_output)
{
// Increate counter when inconsistent output state exists
if (Thermostat[ctr_output].status.status_output != Thermostat[ctr_output].status.command_output) {
if ((Thermostat[ctr_output].status.status_output != Thermostat[ctr_output].status.command_output)
&&(Thermostat[ctr_output].status.enable_output == IFACE_ON)) {
Thermostat[ctr_output].diag.output_inconsist_ctr++;
}
else {
@ -540,7 +552,9 @@ void ThermostatEmergencyShutdown(uint8_t ctr_output)
// Emergency switch to THERMOSTAT_OFF
Thermostat[ctr_output].status.thermostat_mode = THERMOSTAT_OFF;
Thermostat[ctr_output].status.command_output = IFACE_OFF;
ThermostatOutputRelay(ctr_output, Thermostat[ctr_output].status.command_output);
if (Thermostat[ctr_output].status.enable_output == IFACE_ON) {
ThermostatOutputRelay(ctr_output, Thermostat[ctr_output].status.command_output);
}
}
void ThermostatState(uint8_t ctr_output)
@ -576,7 +590,9 @@ void ThermostatOutputRelay(uint8_t ctr_output, uint32_t command)
if ((command == IFACE_ON)
&& (Thermostat[ctr_output].status.status_output == IFACE_OFF)) {
//#ifndef DEBUG_THERMOSTAT
ExecuteCommandPower(Thermostat[ctr_output].status.output_relay_number, POWER_ON, SRC_THERMOSTAT);
if (Thermostat[ctr_output].status.enable_output == IFACE_ON) {
ExecuteCommandPower(Thermostat[ctr_output].status.output_relay_number, POWER_ON, SRC_THERMOSTAT);
}
//#endif // DEBUG_THERMOSTAT
Thermostat[ctr_output].status.status_output = IFACE_ON;
#ifdef DEBUG_THERMOSTAT
@ -588,7 +604,9 @@ void ThermostatOutputRelay(uint8_t ctr_output, uint32_t command)
// then switch output to OFF
else if ((command == IFACE_OFF) && (Thermostat[ctr_output].status.status_output == IFACE_ON)) {
//#ifndef DEBUG_THERMOSTAT
ExecuteCommandPower(Thermostat[ctr_output].status.output_relay_number, POWER_OFF, SRC_THERMOSTAT);
if (Thermostat[ctr_output].status.enable_output == IFACE_ON) {
ExecuteCommandPower(Thermostat[ctr_output].status.output_relay_number, POWER_OFF, SRC_THERMOSTAT);
}
//#endif // DEBUG_THERMOSTAT
Thermostat[ctr_output].timestamp_output_off = uptime;
Thermostat[ctr_output].status.status_output = IFACE_OFF;
@ -1917,6 +1935,44 @@ void CmndDiagnosticModeSet(void)
}
}
void CmndCtrDutyCycleRead(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) {
uint8_t ctr_output = XdrvMailbox.index - 1;
uint8_t value = 0;
if ( (Thermostat[ctr_output].status.controller_mode == CTR_PI)
|| ((Thermostat[ctr_output].status.controller_mode == CTR_HYBRID)
&&(Thermostat[ctr_output].status.phase_hybrid_ctr == CTR_HYBRID_PI))) {
value = Thermostat[ctr_output].time_total_pi / Thermostat[ctr_output].time_pi_cycle;
}
else if ( (Thermostat[ctr_output].status.controller_mode == CTR_RAMP_UP)
|| ((Thermostat[ctr_output].status.controller_mode == CTR_HYBRID)
&&(Thermostat[ctr_output].status.phase_hybrid_ctr == CTR_HYBRID_RAMP_UP))) {
if (Thermostat[ctr_output].status.status_output == IFACE_ON) {
value = 100;
}
else {
value = 0;
}
}
ResponseCmndNumber((int)value);
}
}
void CmndEnableOutputSet(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) {
uint8_t ctr_output = XdrvMailbox.index - 1;
if (XdrvMailbox.data_len > 0) {
uint8_t value = (uint8_t)(CharToFloat(XdrvMailbox.data));
if ((value >= IFACE_OFF) && (value <= IFACE_ON)) {
Thermostat[ctr_output].status.enable_output = value;
}
}
ResponseCmndNumber((int)Thermostat[ctr_output].status.enable_output);
}
}
/*********************************************************************************************\
* Interface
\*********************************************************************************************/