✨ Temperature variance monitor (#23373)
This commit is contained in:
parent
b435487da7
commit
2ca1d844d7
|
@ -349,6 +349,10 @@
|
||||||
#define WATCH_COOLER_TEMP_INCREASE 3 // Degrees Celsius
|
#define WATCH_COOLER_TEMP_INCREASE 3 // Degrees Celsius
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ANY(THERMAL_PROTECTION_HOTENDS, THERMAL_PROTECTION_BED, THERMAL_PROTECTION_CHAMBER, THERMAL_PROTECTION_COOLER)
|
||||||
|
#define THERMAL_PROTECTION_VARIANCE_MONITOR // Detect a sensor malfunction preventing temperature updates
|
||||||
|
#endif
|
||||||
|
|
||||||
#if ENABLED(PIDTEMP)
|
#if ENABLED(PIDTEMP)
|
||||||
// Add an experimental additional term to the heater power, proportional to the extrusion speed.
|
// Add an experimental additional term to the heater power, proportional to the extrusion speed.
|
||||||
// A well-chosen Kc value should add just enough power to melt the increased material volume.
|
// A well-chosen Kc value should add just enough power to melt the increased material volume.
|
||||||
|
|
|
@ -240,6 +240,7 @@
|
||||||
#define STR_REDUNDANCY "Heater switched off. Temperature difference between temp sensors is too high !"
|
#define STR_REDUNDANCY "Heater switched off. Temperature difference between temp sensors is too high !"
|
||||||
#define STR_T_HEATING_FAILED "Heating failed"
|
#define STR_T_HEATING_FAILED "Heating failed"
|
||||||
#define STR_T_THERMAL_RUNAWAY "Thermal Runaway"
|
#define STR_T_THERMAL_RUNAWAY "Thermal Runaway"
|
||||||
|
#define STR_T_MALFUNCTION "Thermal Malfunction"
|
||||||
#define STR_T_MAXTEMP "MAXTEMP triggered"
|
#define STR_T_MAXTEMP "MAXTEMP triggered"
|
||||||
#define STR_T_MINTEMP "MINTEMP triggered"
|
#define STR_T_MINTEMP "MINTEMP triggered"
|
||||||
#define STR_ERR_PROBING_FAILED "Probing Failed"
|
#define STR_ERR_PROBING_FAILED "Probing Failed"
|
||||||
|
|
|
@ -2564,6 +2564,9 @@
|
||||||
#if BOTH(HAS_COOLER, THERMAL_PROTECTION_COOLER) && WATCH_COOLER_TEMP_PERIOD > 0
|
#if BOTH(HAS_COOLER, THERMAL_PROTECTION_COOLER) && WATCH_COOLER_TEMP_PERIOD > 0
|
||||||
#define WATCH_COOLER 1
|
#define WATCH_COOLER 1
|
||||||
#endif
|
#endif
|
||||||
|
#if NONE(THERMAL_PROTECTION_HOTENDS, THERMAL_PROTECTION_CHAMBER, THERMAL_PROTECTION_BED, THERMAL_PROTECTION_COOLER)
|
||||||
|
#undef THERMAL_PROTECTION_VARIANCE_MONITOR
|
||||||
|
#endif
|
||||||
#if (ENABLED(THERMAL_PROTECTION_HOTENDS) || !EXTRUDERS) \
|
#if (ENABLED(THERMAL_PROTECTION_HOTENDS) || !EXTRUDERS) \
|
||||||
&& (ENABLED(THERMAL_PROTECTION_BED) || !HAS_HEATED_BED) \
|
&& (ENABLED(THERMAL_PROTECTION_BED) || !HAS_HEATED_BED) \
|
||||||
&& (ENABLED(THERMAL_PROTECTION_CHAMBER) || !HAS_HEATED_CHAMBER) \
|
&& (ENABLED(THERMAL_PROTECTION_CHAMBER) || !HAS_HEATED_CHAMBER) \
|
||||||
|
|
|
@ -202,6 +202,7 @@ namespace Language_el {
|
||||||
LSTR MSG_HEATING_FAILED_LCD = _UxGT("Αποτυχία θέρμανσης");
|
LSTR MSG_HEATING_FAILED_LCD = _UxGT("Αποτυχία θέρμανσης");
|
||||||
LSTR MSG_ERR_REDUNDANT_TEMP = _UxGT("ΠΛΕΟΝΑΖΟΥΣΑ ΘΕΡΜΟΤΗΤΑ");
|
LSTR MSG_ERR_REDUNDANT_TEMP = _UxGT("ΠΛΕΟΝΑΖΟΥΣΑ ΘΕΡΜΟΤΗΤΑ");
|
||||||
LSTR MSG_THERMAL_RUNAWAY = _UxGT("ΘΕΡΜΙΚΗ ΔΙΑΦΥΓΗ");
|
LSTR MSG_THERMAL_RUNAWAY = _UxGT("ΘΕΡΜΙΚΗ ΔΙΑΦΥΓΗ");
|
||||||
|
LSTR MSG_TEMP_MALFUNCTION = _UxGT("ΘΕΡΜΙΚΗ ΔΥΣΛΕΙΤΟΥΡΓΙΑ");
|
||||||
LSTR MSG_ERR_MAXTEMP = _UxGT("ΠΕΡΙΤΤΗ ΘΕΡΜΟΚΡΑΣΙΑ");
|
LSTR MSG_ERR_MAXTEMP = _UxGT("ΠΕΡΙΤΤΗ ΘΕΡΜΟΚΡΑΣΙΑ");
|
||||||
LSTR MSG_ERR_MINTEMP = _UxGT("ΑΝΕΠΑΡΚΗΣ ΘΕΡΜΟΚΡΑΣΙΑ");
|
LSTR MSG_ERR_MINTEMP = _UxGT("ΑΝΕΠΑΡΚΗΣ ΘΕΡΜΟΚΡΑΣΙΑ");
|
||||||
LSTR MSG_HALTED = _UxGT("Εκτυπωτής διεκόπη");
|
LSTR MSG_HALTED = _UxGT("Εκτυπωτής διεκόπη");
|
||||||
|
|
|
@ -538,6 +538,7 @@ namespace Language_en {
|
||||||
LSTR MSG_HEATING_FAILED_LCD = _UxGT("Heating Failed");
|
LSTR MSG_HEATING_FAILED_LCD = _UxGT("Heating Failed");
|
||||||
LSTR MSG_ERR_REDUNDANT_TEMP = _UxGT("Err: REDUNDANT TEMP");
|
LSTR MSG_ERR_REDUNDANT_TEMP = _UxGT("Err: REDUNDANT TEMP");
|
||||||
LSTR MSG_THERMAL_RUNAWAY = _UxGT("THERMAL RUNAWAY");
|
LSTR MSG_THERMAL_RUNAWAY = _UxGT("THERMAL RUNAWAY");
|
||||||
|
LSTR MSG_TEMP_MALFUNCTION = _UxGT("TEMP MALFUNCTION");
|
||||||
LSTR MSG_THERMAL_RUNAWAY_BED = _UxGT("BED THERMAL RUNAWAY");
|
LSTR MSG_THERMAL_RUNAWAY_BED = _UxGT("BED THERMAL RUNAWAY");
|
||||||
LSTR MSG_THERMAL_RUNAWAY_CHAMBER = _UxGT("CHAMBER T. RUNAWAY");
|
LSTR MSG_THERMAL_RUNAWAY_CHAMBER = _UxGT("CHAMBER T. RUNAWAY");
|
||||||
LSTR MSG_THERMAL_RUNAWAY_COOLER = _UxGT("Cooler Runaway");
|
LSTR MSG_THERMAL_RUNAWAY_COOLER = _UxGT("Cooler Runaway");
|
||||||
|
|
|
@ -196,6 +196,7 @@
|
||||||
Temperature thermalManager;
|
Temperature thermalManager;
|
||||||
|
|
||||||
PGMSTR(str_t_thermal_runaway, STR_T_THERMAL_RUNAWAY);
|
PGMSTR(str_t_thermal_runaway, STR_T_THERMAL_RUNAWAY);
|
||||||
|
PGMSTR(str_t_temp_malfunction, STR_T_MALFUNCTION);
|
||||||
PGMSTR(str_t_heating_failed, STR_T_HEATING_FAILED);
|
PGMSTR(str_t_heating_failed, STR_T_HEATING_FAILED);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2570,14 +2571,30 @@ void Temperature::init() {
|
||||||
);
|
);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// If the heater idle timeout expires, restart
|
#if ENABLED(THERMAL_PROTECTION_VARIANCE_MONITOR)
|
||||||
if (TERN0(HEATER_IDLE_HANDLER, heater_idle[idle_index].timed_out)) {
|
if (state == TRMalfunction) { // temperature invariance may continue, regardless of heater state
|
||||||
state = TRInactive;
|
variance += ABS(current - last_temp); // no need for detection window now, a single change in variance is enough
|
||||||
running_temp = 0;
|
last_temp = current;
|
||||||
}
|
if (!NEAR_ZERO(variance)) {
|
||||||
else if (running_temp != target) { // If the target temperature changes, restart
|
variance_timer = millis() + SEC_TO_MS(period_seconds);
|
||||||
running_temp = target;
|
variance = 0.0;
|
||||||
state = target > 0 ? TRFirstHeating : TRInactive;
|
state = TRStable; // resume from where we detected the problem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (TERN1(THERMAL_PROTECTION_VARIANCE_MONITOR, state != TRMalfunction)) {
|
||||||
|
// If the heater idle timeout expires, restart
|
||||||
|
if (TERN0(HEATER_IDLE_HANDLER, heater_idle[idle_index].timed_out)) {
|
||||||
|
state = TRInactive;
|
||||||
|
running_temp = 0;
|
||||||
|
TERN_(THERMAL_PROTECTION_VARIANCE_MONITOR, variance_timer = 0);
|
||||||
|
}
|
||||||
|
else if (running_temp != target) { // If the target temperature changes, restart
|
||||||
|
running_temp = target;
|
||||||
|
state = target > 0 ? TRFirstHeating : TRInactive;
|
||||||
|
TERN_(THERMAL_PROTECTION_VARIANCE_MONITOR, variance_timer = 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
|
@ -2610,6 +2627,22 @@ void Temperature::init() {
|
||||||
|
|
||||||
const millis_t now = millis();
|
const millis_t now = millis();
|
||||||
|
|
||||||
|
#if ENABLED(THERMAL_PROTECTION_VARIANCE_MONITOR)
|
||||||
|
if (PENDING(now, variance_timer)) {
|
||||||
|
variance += ABS(current - last_temp);
|
||||||
|
last_temp = current;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (NEAR_ZERO(variance) && variance_timer) { // valid variance monitoring window
|
||||||
|
state = TRMalfunction;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
variance_timer = now + SEC_TO_MS(period_seconds);
|
||||||
|
variance = 0.0;
|
||||||
|
last_temp = current;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (current >= running_temp - hysteresis_degc) {
|
if (current >= running_temp - hysteresis_degc) {
|
||||||
timer = now + SEC_TO_MS(period_seconds);
|
timer = now + SEC_TO_MS(period_seconds);
|
||||||
break;
|
break;
|
||||||
|
@ -2622,6 +2655,12 @@ void Temperature::init() {
|
||||||
case TRRunaway:
|
case TRRunaway:
|
||||||
TERN_(HAS_DWIN_E3V2_BASIC, DWIN_Popup_Temperature(0));
|
TERN_(HAS_DWIN_E3V2_BASIC, DWIN_Popup_Temperature(0));
|
||||||
_temp_error(heater_id, FPSTR(str_t_thermal_runaway), GET_TEXT_F(MSG_THERMAL_RUNAWAY));
|
_temp_error(heater_id, FPSTR(str_t_thermal_runaway), GET_TEXT_F(MSG_THERMAL_RUNAWAY));
|
||||||
|
|
||||||
|
#if ENABLED(THERMAL_PROTECTION_VARIANCE_MONITOR)
|
||||||
|
case TRMalfunction:
|
||||||
|
TERN_(HAS_DWIN_E3V2_BASIC, DWIN_Popup_Temperature(0));
|
||||||
|
_temp_error(heater_id, FPSTR(str_t_temp_malfunction), GET_TEXT_F(MSG_TEMP_MALFUNCTION));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1041,12 +1041,18 @@ class Temperature {
|
||||||
return (RunawayIndex)_MAX(heater_id, 0);
|
return (RunawayIndex)_MAX(heater_id, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum TRState : char { TRInactive, TRFirstHeating, TRStable, TRRunaway };
|
enum TRState : char { TRInactive, TRFirstHeating, TRStable, TRRunaway
|
||||||
|
OPTARG(THERMAL_PROTECTION_VARIANCE_MONITOR, TRMalfunction)
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
millis_t timer = 0;
|
millis_t timer = 0;
|
||||||
TRState state = TRInactive;
|
TRState state = TRInactive;
|
||||||
float running_temp;
|
float running_temp;
|
||||||
|
#if ENABLED(THERMAL_PROTECTION_VARIANCE_MONITOR)
|
||||||
|
millis_t variance_timer = 0;
|
||||||
|
celsius_float_t last_temp = 0.0, variance = 0.0;
|
||||||
|
#endif
|
||||||
void run(const_celsius_float_t current, const_celsius_float_t target, const heater_id_t heater_id, const uint16_t period_seconds, const celsius_t hysteresis_degc);
|
void run(const_celsius_float_t current, const_celsius_float_t target, const heater_id_t heater_id, const uint16_t period_seconds, const celsius_t hysteresis_degc);
|
||||||
} tr_state_machine_t;
|
} tr_state_machine_t;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue