From 9caf5c05e7e408c7192e689e4ed5fe2735bb2995 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Thu, 30 Jan 2020 03:24:43 -0600 Subject: [PATCH] Refactor heater watch, job timer auto-start (#16725) --- Marlin/src/feature/pause.cpp | 4 +- Marlin/src/gcode/temperature/M104_M109.cpp | 30 +++++------ Marlin/src/gcode/temperature/M140_M190.cpp | 11 +++- Marlin/src/gcode/temperature/M141_M191.cpp | 9 +++- Marlin/src/lcd/extensible_ui/ui_api.cpp | 4 +- Marlin/src/module/temperature.cpp | 61 +++++++++++++--------- Marlin/src/module/temperature.h | 51 ++++++++++++++---- 7 files changed, 113 insertions(+), 57 deletions(-) diff --git a/Marlin/src/feature/pause.cpp b/Marlin/src/feature/pause.cpp index 10a1ba6a9..6a2f148ea 100644 --- a/Marlin/src/feature/pause.cpp +++ b/Marlin/src/feature/pause.cpp @@ -564,7 +564,7 @@ void wait_for_confirmation(const bool is_reload/*=false*/, const int8_t max_beep #endif // Re-enable the heaters if they timed out - HOTEND_LOOP() thermalManager.reset_heater_idle_timer(e); + HOTEND_LOOP() thermalManager.reset_hotend_idle_timer(e); // Wait for the heaters to reach the target temperatures ensure_safe_temperature(); @@ -633,7 +633,7 @@ void resume_print(const float &slow_load_length/*=0*/, const float &fast_load_le bool nozzle_timed_out = false; HOTEND_LOOP() { nozzle_timed_out |= thermalManager.hotend_idle[e].timed_out; - thermalManager.reset_heater_idle_timer(e); + thermalManager.reset_hotend_idle_timer(e); } if (nozzle_timed_out || thermalManager.hotEnoughToExtrude(active_extruder)) // Load the new filament diff --git a/Marlin/src/gcode/temperature/M104_M109.cpp b/Marlin/src/gcode/temperature/M104_M109.cpp index 8c5827e83..8dbb3af23 100644 --- a/Marlin/src/gcode/temperature/M104_M109.cpp +++ b/Marlin/src/gcode/temperature/M104_M109.cpp @@ -20,6 +20,12 @@ * */ +/** + * gcode/temperature/M104_M109.cpp + * + * Hotend target temperature control + */ + #include "../../inc/MarlinConfigPre.h" #if EXTRUDERS @@ -73,14 +79,11 @@ void GcodeSuite::M104() { #if ENABLED(PRINTJOB_TIMER_AUTOSTART) /** * Stop the timer at the end of print. Start is managed by 'heat and wait' M109. - * We use half EXTRUDE_MINTEMP here to allow nozzles to be put into hot - * standby mode, for instance in a dual extruder setup, without affecting - * the running print timer. + * Hotends use EXTRUDE_MINTEMP / 2 to allow nozzles to be put into hot standby + * mode, for instance in a dual extruder setup, without affecting the running + * print timer. */ - if (temp <= (EXTRUDE_MINTEMP) / 2) { - print_job_timer.stop(); - ui.reset_status(); - } + thermalManager.check_timer_autostart(false, true); #endif } @@ -90,8 +93,10 @@ void GcodeSuite::M104() { } /** - * M109: Sxxx Wait for extruder(s) to reach temperature. Waits only when heating. - * Rxxx Wait for extruder(s) to reach temperature. Waits when heating and cooling. + * M109: Sxxx Wait for hotend(s) to reach temperature. Waits only when heating. + * Rxxx Wait for hotend(s) to reach temperature. Waits when heating and cooling. + * + * With PRINTJOB_TIMER_AUTOSTART also start the job timer on heating and stop it if turned off. */ void GcodeSuite::M109() { @@ -125,12 +130,7 @@ void GcodeSuite::M109() { * standby mode, (e.g., in a dual extruder setup) without affecting * the running print timer. */ - if (parser.value_celsius() <= (EXTRUDE_MINTEMP) / 2) { - print_job_timer.stop(); - ui.reset_status(); - } - else - startOrResumeJob(); + thermalManager.check_timer_autostart(true, true); #endif #if HAS_DISPLAY diff --git a/Marlin/src/gcode/temperature/M140_M190.cpp b/Marlin/src/gcode/temperature/M140_M190.cpp index d6386cef5..f5c3d3683 100644 --- a/Marlin/src/gcode/temperature/M140_M190.cpp +++ b/Marlin/src/gcode/temperature/M140_M190.cpp @@ -20,6 +20,12 @@ * */ +/** + * gcode/temperature/M140_M190.cpp + * + * Bed target temperature control + */ + #include "../../inc/MarlinConfig.h" #if HAS_HEATED_BED @@ -50,6 +56,8 @@ void GcodeSuite::M140() { /** * M190: Sxxx Wait for bed current temp to reach target temp. Waits only when heating * Rxxx Wait for bed current temp to reach target temp. Waits when heating and cooling + * + * With PRINTJOB_TIMER_AUTOSTART also start the job timer on heating. */ void GcodeSuite::M190() { if (DEBUGGING(DRYRUN)) return; @@ -58,8 +66,7 @@ void GcodeSuite::M190() { if (no_wait_for_cooling || parser.seenval('R')) { thermalManager.setTargetBed(parser.value_celsius()); #if ENABLED(PRINTJOB_TIMER_AUTOSTART) - if (parser.value_celsius() > BED_MINTEMP) - startOrResumeJob(); + thermalManager.check_timer_autostart(true, false); #endif } else return; diff --git a/Marlin/src/gcode/temperature/M141_M191.cpp b/Marlin/src/gcode/temperature/M141_M191.cpp index 12eaa24bf..3c9934659 100644 --- a/Marlin/src/gcode/temperature/M141_M191.cpp +++ b/Marlin/src/gcode/temperature/M141_M191.cpp @@ -20,6 +20,12 @@ * */ +/** + * gcode/temperature/M141_M191.cpp + * + * Chamber target temperature control + */ + #include "../../inc/MarlinConfig.h" #if HAS_HEATED_CHAMBER @@ -59,8 +65,7 @@ void GcodeSuite::M191() { if (no_wait_for_cooling || parser.seenval('R')) { thermalManager.setTargetChamber(parser.value_celsius()); #if ENABLED(PRINTJOB_TIMER_AUTOSTART) - if (parser.value_celsius() > CHAMBER_MINTEMP) - startOrResumeJob(); + thermalManager.check_timer_autostart(true, false); #endif } else return; diff --git a/Marlin/src/lcd/extensible_ui/ui_api.cpp b/Marlin/src/lcd/extensible_ui/ui_api.cpp index 8c8133f22..5e053b670 100644 --- a/Marlin/src/lcd/extensible_ui/ui_api.cpp +++ b/Marlin/src/lcd/extensible_ui/ui_api.cpp @@ -171,7 +171,7 @@ namespace ExtUI { void enableHeater(const extruder_t extruder) { #if HOTENDS && HEATER_IDLE_HANDLER - thermalManager.reset_heater_idle_timer(extruder - E0); + thermalManager.reset_hotend_idle_timer(extruder - E0); #else UNUSED(extruder); #endif @@ -190,7 +190,7 @@ namespace ExtUI { #endif default: #if HOTENDS - thermalManager.reset_heater_idle_timer(heater - H0); + thermalManager.reset_hotend_idle_timer(heater - H0); #endif break; } diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index 559b3d5a1..61ed04aae 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -220,10 +220,10 @@ Temperature thermalManager; #endif // FAN_COUNT > 0 #if WATCH_HOTENDS - heater_watch_t Temperature::watch_hotend[HOTENDS]; // = { { 0 } } + hotend_watch_t Temperature::watch_hotend[HOTENDS]; // = { { 0 } } #endif #if HEATER_IDLE_HANDLER - heater_idle_t Temperature::hotend_idle[HOTENDS]; // = { { 0 } } + hotend_idle_t Temperature::hotend_idle[HOTENDS]; // = { { 0 } } #endif #if HAS_HEATED_BED @@ -236,13 +236,13 @@ Temperature thermalManager; int16_t Temperature::maxtemp_raw_BED = HEATER_BED_RAW_HI_TEMP; #endif #if WATCH_BED - heater_watch_t Temperature::watch_bed; // = { 0 } + bed_watch_t Temperature::watch_bed; // = { 0 } #endif #if DISABLED(PIDTEMPBED) millis_t Temperature::next_bed_check_ms; #endif #if HEATER_IDLE_HANDLER - heater_idle_t Temperature::bed_idle; // = { 0 } + hotend_idle_t Temperature::bed_idle; // = { 0 } #endif #endif // HAS_HEATED_BED @@ -256,7 +256,7 @@ Temperature thermalManager; int16_t Temperature::maxtemp_raw_CHAMBER = HEATER_CHAMBER_RAW_HI_TEMP; #endif #if WATCH_CHAMBER - heater_watch_t Temperature::watch_chamber{0}; + chamber_watch_t Temperature::watch_chamber{0}; #endif millis_t Temperature::next_chamber_check_ms; #endif // HAS_HEATED_CHAMBER @@ -1974,12 +1974,7 @@ void Temperature::init() { */ void Temperature::start_watching_hotend(const uint8_t E_NAME) { const uint8_t ee = HOTEND_INDEX; - if (degTargetHotend(ee) && degHotend(ee) < degTargetHotend(ee) - (WATCH_TEMP_INCREASE + TEMP_HYSTERESIS + 1)) { - watch_hotend[ee].target = degHotend(ee) + WATCH_TEMP_INCREASE; - watch_hotend[ee].next_ms = millis() + (WATCH_TEMP_PERIOD) * 1000UL; - } - else - watch_hotend[ee].next_ms = 0; + watch_hotend[ee].restart(degHotend(ee), degTargetHotend(ee)); } #endif @@ -1990,12 +1985,7 @@ void Temperature::init() { * This is called when the temperature is set. (M140, M190) */ void Temperature::start_watching_bed() { - if (degTargetBed() && degBed() < degTargetBed() - (WATCH_BED_TEMP_INCREASE + TEMP_BED_HYSTERESIS + 1)) { - watch_bed.target = degBed() + WATCH_BED_TEMP_INCREASE; - watch_bed.next_ms = millis() + (WATCH_BED_TEMP_PERIOD) * 1000UL; - } - else - watch_bed.next_ms = 0; + watch_bed.restart(degBed(), degTargetBed()); } #endif @@ -2006,12 +1996,7 @@ void Temperature::init() { * This is called when the temperature is set. (M141, M191) */ void Temperature::start_watching_chamber() { - if (degChamber() < degTargetChamber() - (WATCH_CHAMBER_TEMP_INCREASE + TEMP_CHAMBER_HYSTERESIS + 1)) { - watch_chamber.target = degChamber() + WATCH_CHAMBER_TEMP_INCREASE; - watch_chamber.next_ms = millis() + (WATCH_CHAMBER_TEMP_PERIOD) * 1000UL; - } - else - watch_chamber.next_ms = 0; + watch_chamber.restart(degChamber(), degTargetChamber()); } #endif @@ -2154,6 +2139,34 @@ void Temperature::disable_all_heaters() { #endif } +#if ENABLED(PRINTJOB_TIMER_AUTOSTART) + + bool Temperature::over_autostart_threshold() { + #if HOTENDS + HOTEND_LOOP() if (degTargetHotend(e) < (EXTRUDE_MINTEMP) / 2) return true; + #endif + #if HAS_HEATED_BED + if (degTargetBed() > BED_MINTEMP) return true; + #endif + #if HAS_HEATED_CHAMBER + if (degTargetChamber() > CHAMBER_MINTEMP) return true; + #endif + return false; + } + + void Temperature::check_timer_autostart(const bool can_start, const bool can_stop) { + if (over_autostart_threshold()) { + if (can_start) startOrResumeJob(); + } + else if (can_stop) { + print_job_timer.stop(); + ui.reset_status(); + } + } + +#endif + + #if ENABLED(PROBING_HEATERS_OFF) void Temperature::pause(const bool p) { @@ -2166,7 +2179,7 @@ void Temperature::disable_all_heaters() { #endif } else { - HOTEND_LOOP() reset_heater_idle_timer(e); + HOTEND_LOOP() reset_hotend_idle_timer(e); #if HAS_HEATED_BED reset_bed_idle_timer(); #endif diff --git a/Marlin/src/module/temperature.h b/Marlin/src/module/temperature.h index da73ed37a..a360394f2 100644 --- a/Marlin/src/module/temperature.h +++ b/Marlin/src/module/temperature.h @@ -228,15 +228,38 @@ typedef struct { 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; +} hotend_idle_t; // Heater watch handling -typedef struct { +template +struct HeaterWatch { uint16_t target; millis_t next_ms; inline bool elapsed(const millis_t &ms) { return next_ms && ELAPSED(ms, next_ms); } inline bool elapsed() { return elapsed(millis()); } -} heater_watch_t; + + inline void restart(const int16_t curr, const int16_t tgt) { + if (tgt) { + const int16_t newtarget = curr + INCREASE; + if (newtarget < tgt - HYSTERESIS - 1) { + target = newtarget; + next_ms = millis() + PERIOD * 1000UL; + return; + } + } + next_ms = 0; + } +}; + +#if WATCH_HOTENDS + typedef struct HeaterWatch hotend_watch_t; +#endif +#if WATCH_BED + typedef struct HeaterWatch bed_watch_t; +#endif +#if WATCH_CHAMBER + typedef struct HeaterWatch chamber_watch_t; +#endif // Temperature sensor read value ranges typedef struct { int16_t raw_min, raw_max; } raw_range_t; @@ -345,12 +368,12 @@ class Temperature { FORCE_INLINE static bool targetHotEnoughToExtrude(const uint8_t e) { return !targetTooColdToExtrude(e); } #if HEATER_IDLE_HANDLER - static heater_idle_t hotend_idle[HOTENDS]; + static hotend_idle_t hotend_idle[HOTENDS]; #if HAS_HEATED_BED - static heater_idle_t bed_idle; + static hotend_idle_t bed_idle; #endif #if HAS_HEATED_CHAMBER - static heater_idle_t chamber_idle; + static hotend_idle_t chamber_idle; #endif #endif @@ -363,7 +386,7 @@ class Temperature { static volatile bool raw_temps_ready; #if WATCH_HOTENDS - static heater_watch_t watch_hotend[HOTENDS]; + static hotend_watch_t watch_hotend[HOTENDS]; #endif #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT) @@ -382,7 +405,7 @@ class Temperature { #if HAS_HEATED_BED #if WATCH_BED - static heater_watch_t watch_bed; + static bed_watch_t watch_bed; #endif #if DISABLED(PIDTEMPBED) static millis_t next_bed_check_ms; @@ -397,7 +420,7 @@ class Temperature { #if HAS_HEATED_CHAMBER #if WATCH_CHAMBER - static heater_watch_t watch_chamber; + static chamber_watch_t watch_chamber; #endif static millis_t next_chamber_check_ms; #ifdef CHAMBER_MINTEMP @@ -736,6 +759,14 @@ class Temperature { */ static void disable_all_heaters(); + #if ENABLED(PRINTJOB_TIMER_AUTOSTART) + /** + * Methods to check if heaters are enabled, indicating an active job + */ + static bool over_autostart_threshold(); + static void check_timer_autostart(const bool can_start, const bool can_stop); + #endif + /** * Perform auto-tuning for hotend or bed in response to M303 */ @@ -768,7 +799,7 @@ class Temperature { #if HEATER_IDLE_HANDLER - static void reset_heater_idle_timer(const uint8_t E_NAME) { + static void reset_hotend_idle_timer(const uint8_t E_NAME) { hotend_idle[HOTEND_INDEX].reset(); start_watching_hotend(HOTEND_INDEX); }