Improve temperature runaway, idle timeout (#19339)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
This commit is contained in:
@@ -40,7 +40,7 @@
|
||||
#define HOTEND_INDEX TERN(HAS_MULTI_HOTEND, e, 0)
|
||||
#define E_NAME TERN_(HAS_MULTI_HOTEND, e)
|
||||
|
||||
// Identifiers for other heaters
|
||||
// Heater identifiers. Positive values are hotends. Negative values are other heaters.
|
||||
typedef enum : int8_t {
|
||||
INDEX_NONE = -5,
|
||||
H_PROBE, H_REDUNDANT, H_CHAMBER, H_BED,
|
||||
@@ -211,16 +211,6 @@ struct PIDHeaterInfo : public HeaterInfo {
|
||||
typedef temp_info_t chamber_info_t;
|
||||
#endif
|
||||
|
||||
// Heater idle handling
|
||||
typedef struct {
|
||||
millis_t timeout_ms;
|
||||
bool timed_out;
|
||||
inline void update(const millis_t &ms) { if (!timed_out && timeout_ms && ELAPSED(ms, timeout_ms)) timed_out = true; }
|
||||
inline void start(const millis_t &ms) { timeout_ms = millis() + ms; timed_out = false; }
|
||||
inline void reset() { timeout_ms = 0; timed_out = false; }
|
||||
inline void expire() { start(0); }
|
||||
} hotend_idle_t;
|
||||
|
||||
// Heater watch handling
|
||||
template <int INCREASE, int HYSTERESIS, millis_t PERIOD>
|
||||
struct HeaterWatch {
|
||||
@@ -346,9 +336,38 @@ class Temperature {
|
||||
FORCE_INLINE static bool targetHotEnoughToExtrude(const uint8_t e) { return !targetTooColdToExtrude(e); }
|
||||
|
||||
#if HEATER_IDLE_HANDLER
|
||||
static hotend_idle_t hotend_idle[HOTENDS];
|
||||
TERN_(HAS_HEATED_BED, static hotend_idle_t bed_idle);
|
||||
TERN_(HAS_HEATED_CHAMBER, static hotend_idle_t chamber_idle);
|
||||
|
||||
// Heater idle handling. Marlin creates one per hotend and one for the heated bed.
|
||||
typedef struct {
|
||||
millis_t timeout_ms;
|
||||
bool timed_out;
|
||||
inline void update(const millis_t &ms) { if (!timed_out && timeout_ms && ELAPSED(ms, timeout_ms)) timed_out = true; }
|
||||
inline void start(const millis_t &ms) { timeout_ms = millis() + ms; timed_out = false; }
|
||||
inline void reset() { timeout_ms = 0; timed_out = false; }
|
||||
inline void expire() { start(0); }
|
||||
} heater_idle_t;
|
||||
|
||||
// Indices and size for the heater_idle array
|
||||
#define _ENUM_FOR_E(N) IDLE_INDEX_E##N,
|
||||
enum IdleIndex : uint8_t {
|
||||
REPEAT(HOTENDS, _ENUM_FOR_E)
|
||||
#if ENABLED(HAS_HEATED_BED)
|
||||
IDLE_INDEX_BED,
|
||||
#endif
|
||||
NR_HEATER_IDLE
|
||||
};
|
||||
#undef _ENUM_FOR_E
|
||||
|
||||
// Convert the given heater_id_t to idle array index
|
||||
static inline IdleIndex idle_index_for_id(const int8_t heater_id) {
|
||||
#if HAS_HEATED_BED
|
||||
if (heater_id == H_BED) return IDLE_INDEX_BED;
|
||||
#endif
|
||||
return (IdleIndex)_MAX(heater_id, 0);
|
||||
}
|
||||
|
||||
static heater_idle_t heater_idle[NR_HEATER_IDLE];
|
||||
|
||||
#endif
|
||||
|
||||
private:
|
||||
@@ -747,13 +766,13 @@ class Temperature {
|
||||
#if HEATER_IDLE_HANDLER
|
||||
|
||||
static void reset_hotend_idle_timer(const uint8_t E_NAME) {
|
||||
hotend_idle[HOTEND_INDEX].reset();
|
||||
heater_idle[HOTEND_INDEX].reset();
|
||||
start_watching_hotend(HOTEND_INDEX);
|
||||
}
|
||||
|
||||
#if HAS_HEATED_BED
|
||||
static void reset_bed_idle_timer() {
|
||||
bed_idle.reset();
|
||||
heater_idle[IDLE_INDEX_BED].reset();
|
||||
start_watching_bed();
|
||||
}
|
||||
#endif
|
||||
@@ -815,22 +834,47 @@ class Temperature {
|
||||
static void min_temp_error(const heater_id_t e);
|
||||
static void max_temp_error(const heater_id_t e);
|
||||
|
||||
#define HAS_THERMAL_PROTECTION (EITHER(THERMAL_PROTECTION_HOTENDS, THERMAL_PROTECTION_CHAMBER) || HAS_THERMALLY_PROTECTED_BED)
|
||||
#define HAS_THERMAL_PROTECTION ANY(THERMAL_PROTECTION_HOTENDS, THERMAL_PROTECTION_CHAMBER, HAS_THERMALLY_PROTECTED_BED)
|
||||
|
||||
#if HAS_THERMAL_PROTECTION
|
||||
|
||||
// Indices and size for the tr_state_machine array. One for each protected heater.
|
||||
#define _ENUM_FOR_E(N) RUNAWAY_IND_E##N,
|
||||
enum RunawayIndex : uint8_t {
|
||||
#if ENABLED(THERMAL_PROTECTION_HOTENDS)
|
||||
REPEAT(HOTENDS, _ENUM_FOR_E)
|
||||
#endif
|
||||
#if ENABLED(HAS_THERMALLY_PROTECTED_BED)
|
||||
RUNAWAY_IND_BED,
|
||||
#endif
|
||||
#if ENABLED(THERMAL_PROTECTION_CHAMBER)
|
||||
RUNAWAY_IND_CHAMBER,
|
||||
#endif
|
||||
NR_HEATER_RUNAWAY
|
||||
};
|
||||
#undef _ENUM_FOR_E
|
||||
|
||||
// Convert the given heater_id_t to runaway state array index
|
||||
static inline RunawayIndex runaway_index_for_id(const int8_t heater_id) {
|
||||
#if HAS_THERMALLY_PROTECTED_CHAMBER
|
||||
if (heater_id == H_CHAMBER) return RUNAWAY_IND_CHAMBER;
|
||||
#endif
|
||||
#if HAS_THERMALLY_PROTECTED_BED
|
||||
if (heater_id == H_BED) return RUNAWAY_IND_BED;
|
||||
#endif
|
||||
return (RunawayIndex)_MAX(heater_id, 0);
|
||||
}
|
||||
|
||||
enum TRState : char { TRInactive, TRFirstHeating, TRStable, TRRunaway };
|
||||
|
||||
typedef struct {
|
||||
millis_t timer = 0;
|
||||
TRState state = TRInactive;
|
||||
float running_temp;
|
||||
void run(const float ¤t, const float &target, const heater_id_t heater_id, const uint16_t period_seconds, const uint16_t hysteresis_degc);
|
||||
} tr_state_machine_t;
|
||||
|
||||
TERN_(THERMAL_PROTECTION_HOTENDS, static tr_state_machine_t tr_state_machine[HOTENDS]);
|
||||
TERN_(HAS_THERMALLY_PROTECTED_BED, static tr_state_machine_t tr_state_machine_bed);
|
||||
TERN_(THERMAL_PROTECTION_CHAMBER, static tr_state_machine_t tr_state_machine_chamber);
|
||||
|
||||
static void thermal_runaway_protection(tr_state_machine_t &state, const float ¤t, const float &target, const heater_id_t heater_id, const uint16_t period_seconds, const uint16_t hysteresis_degc);
|
||||
static tr_state_machine_t tr_state_machine[NR_HEATER_RUNAWAY];
|
||||
|
||||
#endif // HAS_THERMAL_PROTECTION
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user