mirror of
https://github.com/MarlinFirmware/Marlin.git
synced 2025-01-19 08:08:25 +00:00
🚸 M86-M87 Hotend Idle Timeout (#25015)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
This commit is contained in:
parent
0138aff890
commit
402c4ef5d3
13 changed files with 199 additions and 20 deletions
|
@ -37,20 +37,25 @@
|
|||
#include "../module/planner.h"
|
||||
#include "../lcd/marlinui.h"
|
||||
|
||||
extern HotendIdleProtection hotend_idle;
|
||||
HotendIdleProtection hotend_idle;
|
||||
|
||||
millis_t HotendIdleProtection::next_protect_ms = 0;
|
||||
hotend_idle_settings_t HotendIdleProtection::cfg; // Initialized by settings.load()
|
||||
|
||||
void HotendIdleProtection::check_hotends(const millis_t &ms) {
|
||||
const bool busy = (TERN0(HAS_RESUME_CONTINUE, wait_for_user) || planner.has_blocks_queued());
|
||||
bool do_prot = false;
|
||||
HOTEND_LOOP() {
|
||||
const bool busy = (TERN0(HAS_RESUME_CONTINUE, wait_for_user) || planner.has_blocks_queued());
|
||||
if (thermalManager.degHotend(e) >= (HOTEND_IDLE_MIN_TRIGGER) && !busy) {
|
||||
do_prot = true; break;
|
||||
if (!busy && cfg.timeout != 0) {
|
||||
HOTEND_LOOP() {
|
||||
if (thermalManager.degHotend(e) >= cfg.trigger) {
|
||||
do_prot = true; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bool(next_protect_ms) != do_prot)
|
||||
next_protect_ms = do_prot ? ms + hp_interval : 0;
|
||||
if (!do_prot)
|
||||
next_protect_ms = 0; // No hotends are hot so cancel timeout
|
||||
else if (!next_protect_ms) // Timeout is possible?
|
||||
next_protect_ms = ms + cfg.timeout * 1000; // Start timeout if not already set
|
||||
}
|
||||
|
||||
void HotendIdleProtection::check_e_motion(const millis_t &ms) {
|
||||
|
@ -58,7 +63,7 @@ void HotendIdleProtection::check_e_motion(const millis_t &ms) {
|
|||
if (old_e_position != current_position.e) {
|
||||
old_e_position = current_position.e; // Track filament motion
|
||||
if (next_protect_ms) // If some heater is on then...
|
||||
next_protect_ms = ms + hp_interval; // ...delay the timeout till later
|
||||
next_protect_ms = ms + cfg.timeout * 1000; // ...delay the timeout till later
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,12 +84,12 @@ void HotendIdleProtection::timed_out() {
|
|||
SERIAL_ECHOLNPGM("Hotend Idle Timeout");
|
||||
LCD_MESSAGE(MSG_HOTEND_IDLE_TIMEOUT);
|
||||
HOTEND_LOOP() {
|
||||
if ((HOTEND_IDLE_NOZZLE_TARGET) < thermalManager.degTargetHotend(e))
|
||||
thermalManager.setTargetHotend(HOTEND_IDLE_NOZZLE_TARGET, e);
|
||||
if (cfg.nozzle_target < thermalManager.degTargetHotend(e))
|
||||
thermalManager.setTargetHotend(cfg.nozzle_target, e);
|
||||
}
|
||||
#if HAS_HEATED_BED
|
||||
if ((HOTEND_IDLE_BED_TARGET) < thermalManager.degTargetBed())
|
||||
thermalManager.setTargetBed(HOTEND_IDLE_BED_TARGET);
|
||||
if (cfg.bed_target < thermalManager.degTargetBed())
|
||||
thermalManager.setTargetBed(cfg.bed_target);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -21,13 +21,26 @@
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../core/millis_t.h"
|
||||
#include "../inc/MarlinConfig.h"
|
||||
|
||||
typedef struct {
|
||||
int16_t timeout, trigger, nozzle_target;
|
||||
#if HAS_HEATED_BED
|
||||
int16_t bed_target;
|
||||
#endif
|
||||
void set_defaults() {
|
||||
timeout = HOTEND_IDLE_TIMEOUT_SEC;
|
||||
trigger = HOTEND_IDLE_MIN_TRIGGER;
|
||||
nozzle_target = HOTEND_IDLE_NOZZLE_TARGET;
|
||||
bed_target = HOTEND_IDLE_BED_TARGET;
|
||||
}
|
||||
} hotend_idle_settings_t;
|
||||
|
||||
class HotendIdleProtection {
|
||||
public:
|
||||
static void check();
|
||||
static hotend_idle_settings_t cfg;
|
||||
private:
|
||||
static constexpr millis_t hp_interval = SEC_TO_MS(HOTEND_IDLE_TIMEOUT_SEC);
|
||||
static millis_t next_protect_ms;
|
||||
static void check_hotends(const millis_t &ms);
|
||||
static void check_e_motion(const millis_t &ms);
|
||||
|
|
|
@ -658,8 +658,15 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
|
|||
case 82: M82(); break; // M82: Set E axis normal mode (same as other axes)
|
||||
case 83: M83(); break; // M83: Set E axis relative mode
|
||||
#endif
|
||||
|
||||
case 18: case 84: M18_M84(); break; // M18/M84: Disable Steppers / Set Timeout
|
||||
case 85: M85(); break; // M85: Set inactivity stepper shutdown timeout
|
||||
|
||||
#if ENABLED(HOTEND_IDLE_TIMEOUT)
|
||||
case 86: M86(); break; // M86: Set Hotend Idle Timeout
|
||||
case 87: M87(); break; // M87: Cancel Hotend Idle Timeout
|
||||
#endif
|
||||
|
||||
case 92: M92(); break; // M92: Set the steps-per-unit for one or more axes
|
||||
case 114: M114(); break; // M114: Report current position
|
||||
case 115: M115(); break; // M115: Report capabilities
|
||||
|
|
|
@ -711,6 +711,13 @@ private:
|
|||
#endif
|
||||
|
||||
static void M85();
|
||||
|
||||
#if ENABLED(HOTEND_IDLE_TIMEOUT)
|
||||
static void M86();
|
||||
static void M86_report(const bool forReplay=true);
|
||||
static void M87();
|
||||
#endif
|
||||
|
||||
static void M92();
|
||||
static void M92_report(const bool forReplay=true, const int8_t e=-1);
|
||||
|
||||
|
|
79
Marlin/src/gcode/temp/M86-M87.cpp
Normal file
79
Marlin/src/gcode/temp/M86-M87.cpp
Normal file
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* gcode/temp/M86-M87.cpp
|
||||
*
|
||||
* Hotend Idle Timeout
|
||||
*/
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
|
||||
#if ENABLED(HOTEND_IDLE_TIMEOUT)
|
||||
|
||||
#include "../gcode.h"
|
||||
#include "../../feature/hotend_idle.h"
|
||||
|
||||
void GcodeSuite::M86_report(const bool forReplay/*=true*/) {
|
||||
hotend_idle_settings_t &c = hotend_idle.cfg;
|
||||
report_heading(forReplay, F("Hotend Idle Timeout"));
|
||||
SERIAL_ECHOLNPGM(" M86"
|
||||
#if HAS_HEATED_BED
|
||||
" B", c.bed_target,
|
||||
#endif
|
||||
" E", c.nozzle_target,
|
||||
" S", c.timeout,
|
||||
" T", c.trigger
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* M86: Set / Report Hotend Idle Timeout
|
||||
*
|
||||
* Parameters
|
||||
* S<seconds> : Idle timeout. Set to 0 to disable.
|
||||
* E<temp> : Extruder idle temperature to set on timeout
|
||||
* B<temp> : Bed idle temperature to set on timeout
|
||||
* T<temp> : Minimum extruder temperature to consider for timeout (> idle temperature)
|
||||
*/
|
||||
void GcodeSuite::M86() {
|
||||
if (!parser.seen_any()) return M86_report();
|
||||
hotend_idle_settings_t &c = hotend_idle.cfg;
|
||||
if (parser.seenval('S')) c.timeout = parser.value_ushort();
|
||||
if (parser.seenval('T')) c.trigger = parser.value_celsius();
|
||||
if (parser.seenval('E')) c.nozzle_target = parser.value_celsius();
|
||||
#if HAS_HEATED_BED
|
||||
if (parser.seenval('B')) c.bed_target = parser.value_celsius();
|
||||
#endif
|
||||
const celsius_t min_trigger = c.nozzle_target + TEMP_HYSTERESIS;
|
||||
if (c.trigger <= min_trigger)
|
||||
SERIAL_ECHOLNPGM("?Idle Timeout (T) trigger temperature should be over ", min_trigger, "C.");
|
||||
}
|
||||
|
||||
/**
|
||||
* M86: Cancel Hotend Idle Timeout (by setting the timeout period to 0)
|
||||
*/
|
||||
void GcodeSuite::M87() {
|
||||
hotend_idle.cfg.timeout = 0;
|
||||
}
|
||||
|
||||
#endif // HOTEND_IDLE_TIMEOUT
|
|
@ -343,7 +343,7 @@ namespace Language_de {
|
|||
LSTR MSG_PID_AUTOTUNE_FAILED = _UxGT("PID Autotune fehlge.!");
|
||||
LSTR MSG_BAD_HEATER_ID = _UxGT("ungültiger Extruder.");
|
||||
LSTR MSG_TEMP_TOO_HIGH = _UxGT("Temperatur zu hoch.");
|
||||
LSTR MSG_TIMEOUT = _UxGT("Timeout.");
|
||||
LSTR MSG_TIMEOUT = _UxGT("Timeout");
|
||||
LSTR MSG_PID_BAD_HEATER_ID = _UxGT("Autotune fehlge.! Ungültiger Extruder");
|
||||
LSTR MSG_PID_TEMP_TOO_HIGH = _UxGT("Autotune fehlge.! Temperatur zu hoch.");
|
||||
LSTR MSG_PID_TIMEOUT = _UxGT("Autotune fehlge.! Timeout.");
|
||||
|
|
|
@ -370,7 +370,7 @@ namespace Language_en {
|
|||
LSTR MSG_PID_AUTOTUNE_FAILED = _UxGT("Autotune failed!");
|
||||
LSTR MSG_BAD_HEATER_ID = _UxGT("Bad extruder.");
|
||||
LSTR MSG_TEMP_TOO_HIGH = _UxGT("Temperature too high.");
|
||||
LSTR MSG_TIMEOUT = _UxGT("Timeout.");
|
||||
LSTR MSG_TIMEOUT = _UxGT("Timeout");
|
||||
LSTR MSG_PID_BAD_HEATER_ID = _UxGT("Autotune failed! Bad extruder.");
|
||||
LSTR MSG_PID_TEMP_TOO_HIGH = _UxGT("Autotune failed! Temperature too high.");
|
||||
LSTR MSG_PID_TIMEOUT = _UxGT("Autotune failed! Timeout.");
|
||||
|
@ -680,6 +680,9 @@ namespace Language_en {
|
|||
LSTR MSG_INFO_RUNAWAY_OFF = _UxGT("Runaway Watch: OFF");
|
||||
LSTR MSG_INFO_RUNAWAY_ON = _UxGT("Runaway Watch: ON");
|
||||
LSTR MSG_HOTEND_IDLE_TIMEOUT = _UxGT("Hotend Idle Timeout");
|
||||
LSTR MSG_HOTEND_IDLE_DISABLE = _UxGT("Disable Timeout");
|
||||
LSTR MSG_HOTEND_IDLE_NOZZLE_TARGET = _UxGT("Nozzle Idle Temp");
|
||||
LSTR MSG_HOTEND_IDLE_BED_TARGET = _UxGT("Bed Idle Temp");
|
||||
LSTR MSG_FAN_SPEED_FAULT = _UxGT("Fan speed fault");
|
||||
|
||||
LSTR MSG_CASE_LIGHT = _UxGT("Case Light");
|
||||
|
|
|
@ -364,7 +364,7 @@ namespace Language_it {
|
|||
LSTR MSG_PID_AUTOTUNE_FAILED = _UxGT("Calibr.PID fallito!");
|
||||
LSTR MSG_BAD_HEATER_ID = _UxGT("Estrusore invalido.");
|
||||
LSTR MSG_TEMP_TOO_HIGH = _UxGT("Temp.troppo alta.");
|
||||
LSTR MSG_TIMEOUT = _UxGT("Tempo scaduto.");
|
||||
LSTR MSG_TIMEOUT = _UxGT("Tempo scaduto");
|
||||
LSTR MSG_PID_BAD_HEATER_ID = _UxGT("Calibrazione fallita! Estrusore errato.");
|
||||
LSTR MSG_PID_TEMP_TOO_HIGH = _UxGT("Calibrazione fallita! Temperatura troppo alta.");
|
||||
LSTR MSG_PID_TIMEOUT = _UxGT("Calibrazione fallita! Tempo scaduto.");
|
||||
|
|
|
@ -363,7 +363,7 @@ namespace Language_sk {
|
|||
LSTR MSG_PID_AUTOTUNE_FAILED = _UxGT("Kal. PID zlyhala!");
|
||||
LSTR MSG_BAD_HEATER_ID = _UxGT("Zlý extrudér");
|
||||
LSTR MSG_TEMP_TOO_HIGH = _UxGT("Príliš vysoká tepl.");
|
||||
LSTR MSG_TIMEOUT = _UxGT("Čas vypršal.");
|
||||
LSTR MSG_TIMEOUT = _UxGT("Čas vypršal");
|
||||
LSTR MSG_PID_BAD_HEATER_ID = _UxGT("Auto-kal. zlyhala! Zlý extrúder.");
|
||||
LSTR MSG_PID_TEMP_TOO_HIGH = _UxGT("Auto-kal. zlyhala! Príliš vysoká tepl.");
|
||||
LSTR MSG_PID_TIMEOUT = _UxGT("Auto-kal. zlyhala! Čas vypršal.");
|
||||
|
|
|
@ -59,6 +59,10 @@
|
|||
#include "../../libs/buzzer.h"
|
||||
#endif
|
||||
|
||||
#if ENABLED(HOTEND_IDLE_TIMEOUT)
|
||||
#include "../../feature/hotend_idle.h"
|
||||
#endif
|
||||
|
||||
#if ANY(LCD_PROGRESS_BAR_TEST, LCD_ENDSTOP_TEST)
|
||||
#include "../lcdprint.h"
|
||||
#define HAS_DEBUG_MENU 1
|
||||
|
@ -277,6 +281,24 @@ void menu_advanced_settings();
|
|||
}
|
||||
#endif
|
||||
|
||||
#if ENABLED(HOTEND_IDLE_TIMEOUT)
|
||||
|
||||
void menu_hotend_idle() {
|
||||
hotend_idle_settings_t &c = hotend_idle.cfg;
|
||||
START_MENU();
|
||||
BACK_ITEM(MSG_BACK);
|
||||
|
||||
if (c.timeout) GCODES_ITEM(MSG_HOTEND_IDLE_DISABLE, F("M87"));
|
||||
EDIT_ITEM(int3, MSG_TIMEOUT, &c.timeout, 0, 999);
|
||||
EDIT_ITEM(int3, MSG_TEMPERATURE, &c.trigger, 0, HEATER_0_MAXTEMP);
|
||||
EDIT_ITEM(int3, MSG_HOTEND_IDLE_NOZZLE_TARGET, &c.nozzle_target, 0, HEATER_0_MAXTEMP);
|
||||
EDIT_ITEM(int3, MSG_HOTEND_IDLE_BED_TARGET, &c.bed_target, 0, BED_MAXTEMP);
|
||||
|
||||
END_MENU();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if ENABLED(DUAL_X_CARRIAGE)
|
||||
|
||||
void menu_idex() {
|
||||
|
@ -610,6 +632,10 @@ void menu_configuration() {
|
|||
#endif
|
||||
}
|
||||
|
||||
#if ENABLED(HOTEND_IDLE_TIMEOUT)
|
||||
SUBMENU(MSG_HOTEND_IDLE_TIMEOUT, menu_hotend_idle);
|
||||
#endif
|
||||
|
||||
//
|
||||
// Set single nozzle filament retract and prime length
|
||||
//
|
||||
|
|
|
@ -100,6 +100,10 @@ void menu_configuration();
|
|||
void menu_preheat_only();
|
||||
#endif
|
||||
|
||||
#if ENABLED(HOTEND_IDLE_TIMEOUT)
|
||||
void menu_hotend_idle();
|
||||
#endif
|
||||
|
||||
#if HAS_MULTI_LANGUAGE
|
||||
void menu_language();
|
||||
#endif
|
||||
|
|
|
@ -178,6 +178,10 @@
|
|||
#include "../lcd/extui/dgus/DGUSDisplayDef.h"
|
||||
#endif
|
||||
|
||||
#if ENABLED(HOTEND_IDLE_TIMEOUT)
|
||||
#include "../feature/hotend_idle.h"
|
||||
#endif
|
||||
|
||||
#pragma pack(push, 1) // No padding between variables
|
||||
|
||||
#if HAS_ETHERNET
|
||||
|
@ -623,6 +627,13 @@ typedef struct SettingsDataStruct {
|
|||
shaping_y_zeta; // M593 Y D
|
||||
#endif
|
||||
|
||||
//
|
||||
// HOTEND_IDLE_TIMEOUT
|
||||
//
|
||||
#if ENABLED(HOTEND_IDLE_TIMEOUT)
|
||||
hotend_idle_settings_t hotend_idle_config; // M86 S T E B
|
||||
#endif
|
||||
|
||||
} SettingsData;
|
||||
|
||||
//static_assert(sizeof(SettingsData) <= MARLIN_EEPROM_SIZE, "EEPROM too small to contain SettingsData!");
|
||||
|
@ -1702,7 +1713,7 @@ void MarlinSettings::postprocess() {
|
|||
|
||||
//
|
||||
// Input Shaping
|
||||
///
|
||||
//
|
||||
#if HAS_ZV_SHAPING
|
||||
#if ENABLED(INPUT_SHAPING_X)
|
||||
EEPROM_WRITE(stepper.get_shaping_frequency(X_AXIS));
|
||||
|
@ -1714,6 +1725,13 @@ void MarlinSettings::postprocess() {
|
|||
#endif
|
||||
#endif
|
||||
|
||||
//
|
||||
// HOTEND_IDLE_TIMEOUT
|
||||
//
|
||||
#if ENABLED(HOTEND_IDLE_TIMEOUT)
|
||||
EEPROM_WRITE(hotend_idle.cfg);
|
||||
#endif
|
||||
|
||||
//
|
||||
// Report final CRC and Data Size
|
||||
//
|
||||
|
@ -2781,6 +2799,13 @@ void MarlinSettings::postprocess() {
|
|||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// HOTEND_IDLE_TIMEOUT
|
||||
//
|
||||
#if ENABLED(HOTEND_IDLE_TIMEOUT)
|
||||
EEPROM_READ(hotend_idle.cfg);
|
||||
#endif
|
||||
|
||||
//
|
||||
// Validate Final Size and CRC
|
||||
//
|
||||
|
@ -3590,6 +3615,11 @@ void MarlinSettings::reset() {
|
|||
#endif
|
||||
#endif
|
||||
|
||||
//
|
||||
// Hotend Idle Timeout
|
||||
//
|
||||
TERN_(HOTEND_IDLE_TIMEOUT, hotend_idle.cfg.set_defaults());
|
||||
|
||||
postprocess();
|
||||
|
||||
#if ANY(EEPROM_CHITCHAT, DEBUG_LEVELING_FEATURE)
|
||||
|
@ -3845,6 +3875,11 @@ void MarlinSettings::reset() {
|
|||
//
|
||||
TERN_(HAS_ZV_SHAPING, gcode.M593_report(forReplay));
|
||||
|
||||
//
|
||||
// Hotend Idle Timeout
|
||||
//
|
||||
TERN_(HOTEND_IDLE_TIMEOUT, gcode.M86_report(forReplay));
|
||||
|
||||
//
|
||||
// Linear Advance
|
||||
//
|
||||
|
|
|
@ -140,7 +140,7 @@ HAS_FANMUX = build_src_filter=+<src/feature/fanmux.c
|
|||
FILAMENT_WIDTH_SENSOR = build_src_filter=+<src/feature/filwidth.cpp> +<src/gcode/feature/filwidth>
|
||||
FWRETRACT = build_src_filter=+<src/feature/fwretract.cpp> +<src/gcode/feature/fwretract>
|
||||
HOST_ACTION_COMMANDS = build_src_filter=+<src/feature/host_actions.cpp>
|
||||
HOTEND_IDLE_TIMEOUT = build_src_filter=+<src/feature/hotend_idle.cpp>
|
||||
HOTEND_IDLE_TIMEOUT = build_src_filter=+<src/feature/hotend_idle.cpp> +<src/gcode/temp/M86-M87.cpp>
|
||||
JOYSTICK = build_src_filter=+<src/feature/joystick.cpp>
|
||||
BLINKM = build_src_filter=+<src/feature/leds/blinkm.cpp>
|
||||
HAS_COLOR_LEDS = build_src_filter=+<src/feature/leds/leds.cpp> +<src/gcode/feature/leds/M150.cpp>
|
||||
|
|
Loading…
Reference in a new issue