diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index c993bf80039c..c51b0ed5ef12 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -1610,7 +1610,8 @@ // with NOZZLE_AS_PROBE this can be negative for a wider probing area. #define PROBING_MARGIN 10 -// X and Y axis travel speed (mm/min) between probes +// X and Y axis travel speed (mm/min) between probes. +// Leave undefined to use the average of the current XY homing feedrate. #define XY_PROBE_FEEDRATE (133*60) // Feedrate (mm/min) for the first approach when double-probing (MULTIPLE_PROBING == 2) @@ -2304,6 +2305,9 @@ // Homing speeds (linear=mm/min, rotational=°/min) #define HOMING_FEEDRATE_MM_M { (50*60), (50*60), (4*60) } +// Edit homing feedrates with M210 and MarlinUI menu items +//#define EDITABLE_HOMING_FEEDRATE + // Validate that endstops are triggered on homing moves #define VALIDATE_HOMING_ENDSTOPS diff --git a/Marlin/src/core/language.h b/Marlin/src/core/language.h index 2736a7833ed5..e641a1431b4b 100644 --- a/Marlin/src/core/language.h +++ b/Marlin/src/core/language.h @@ -290,6 +290,7 @@ #define STR_MAX_ACCELERATION "Max Acceleration (units/s2)" #define STR_MAX_FEEDRATES "Max feedrates (units/s)" #define STR_ACCELERATION_P_R_T "Acceleration (units/s2) (P R T)" +#define STR_HOMING_FEEDRATE "Homing Feedrate" #define STR_TOOL_CHANGING "Tool-changing" #define STR_HOTEND_OFFSETS "Hotend offsets" #define STR_SERVO_ANGLES "Servo Angles" @@ -323,6 +324,37 @@ #define STR_USER_THERMISTORS "User thermistors" #define STR_DELAYED_POWEROFF "Delayed poweroff" +// +// General axis names +// +#if HAS_X_AXIS + #define AXIS1_NAME 'X' +#endif +#if HAS_Y_AXIS + #define AXIS2_NAME 'Y' +#endif +#if HAS_Z_AXIS + #define AXIS3_NAME 'Z' +#endif +#define STR_X "X" +#define STR_Y "Y" +#define STR_Z "Z" +#define STR_E "E" +#if IS_KINEMATIC + #define STR_A "A" + #define STR_B "B" + #define STR_C "C" +#else + #define STR_A STR_X + #define STR_B STR_Y + #define STR_C STR_Z +#endif +#define STR_X2 STR_A "2" +#define STR_Y2 STR_B "2" +#define STR_Z2 STR_C "2" +#define STR_Z3 STR_C "3" +#define STR_Z4 STR_C "4" + // // Endstop Names used by Endstops::report_states // @@ -354,29 +386,8 @@ #define STR_Z_PROBE "z_probe" #define STR_PROBE_EN "probe_en" #define STR_FILAMENT "filament" - #define STR_CALIBRATION "calibration" -// General axis names -#define STR_X "X" -#define STR_Y "Y" -#define STR_Z "Z" -#define STR_E "E" -#if IS_KINEMATIC - #define STR_A "A" - #define STR_B "B" - #define STR_C "C" -#else - #define STR_A "X" - #define STR_B "Y" - #define STR_C "Z" -#endif -#define STR_X2 "X2" -#define STR_Y2 "Y2" -#define STR_Z2 "Z2" -#define STR_Z3 "Z3" -#define STR_Z4 "Z4" - // Extra Axis and Endstop Names #if HAS_I_AXIS #if AXIS4_NAME == 'A' diff --git a/Marlin/src/gcode/calibrate/G28.cpp b/Marlin/src/gcode/calibrate/G28.cpp index 03fd2c80ed9d..ac90756ded8d 100644 --- a/Marlin/src/gcode/calibrate/G28.cpp +++ b/Marlin/src/gcode/calibrate/G28.cpp @@ -322,9 +322,9 @@ void GcodeSuite::G28() { #else // !DELTA && !AXEL_TPARA - #define _UNSAFE(A) TERN0(Z_SAFE_HOMING, homeZ && axis_should_home(_AXIS(A))) + #define _UNSAFE(A) TERN0(Z_SAFE_HOMING, homeZZ && axis_should_home(_AXIS(A))) - const bool homeZ = TERN0(HAS_Z_AXIS, parser.seen_test('Z')), + const bool homeZZ = TERN0(HAS_Z_AXIS, parser.seen_test('Z')), NUM_AXIS_LIST_( // Other axes should be homed before Z safe-homing needX = _UNSAFE(X), needY = _UNSAFE(Y), needZ = false, // UNUSED needI = _UNSAFE(I), needJ = _UNSAFE(J), needK = _UNSAFE(K), @@ -333,7 +333,7 @@ void GcodeSuite::G28() { NUM_AXIS_LIST_( // Home each axis if needed or flagged homeX = needX || parser.seen_test('X'), homeY = needY || parser.seen_test('Y'), - homeZZ = homeZ, + homeZ = homeZZ, homeI = needI || parser.seen_test(AXIS4_NAME), homeJ = needJ || parser.seen_test(AXIS5_NAME), homeK = needK || parser.seen_test(AXIS6_NAME), homeU = needU || parser.seen_test(AXIS7_NAME), homeV = needV || parser.seen_test(AXIS8_NAME), homeW = needW || parser.seen_test(AXIS9_NAME) @@ -355,7 +355,7 @@ void GcodeSuite::G28() { #if HAS_Z_AXIS - UNUSED(needZ); UNUSED(homeZZ); + UNUSED(needZ); // Z may home first, e.g., when homing away from the bed. // This is also permitted when homing with a Z endstop. @@ -439,8 +439,7 @@ void GcodeSuite::G28() { #if HAS_Y_AXIS // Home Y (after X) - if (DISABLED(HOME_Y_BEFORE_X) && doY) - homeaxis(Y_AXIS); + if (DISABLED(HOME_Y_BEFORE_X) && doY) homeaxis(Y_AXIS); #endif #if ALL(FOAMCUTTER_XYUV, HAS_J_AXIS) diff --git a/Marlin/src/gcode/config/M210.cpp b/Marlin/src/gcode/config/M210.cpp new file mode 100644 index 000000000000..99c750bd2593 --- /dev/null +++ b/Marlin/src/gcode/config/M210.cpp @@ -0,0 +1,100 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2024 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 . + * + */ + +#include "../../inc/MarlinConfigPre.h" + +#if ENABLED(EDITABLE_HOMING_FEEDRATE) + +#include "../gcode.h" +#include "../../module/motion.h" + +/** + * M210 - Set homing feedrate for one or more axes + * in current units (in/mm) per minute + * + * X[feedrate] Set X axis homing feedrate + * Y[feedrate] Set Y axis homing feedrate + * Z[feedrate] Set Z axis homing feedrate + * A[feedrate] Set I axis homing feedrate (configured axis name applies) + * B[feedrate] Set J axis homing feedrate (configured axis name applies) + * C[feedrate] Set K axis homing feedrate (configured axis name applies) + * U[feedrate] Set U axis homing feedrate (configured axis name applies) + * V[feedrate] Set V axis homing feedrate (configured axis name applies) + * W[feedrate] Set W axis homing feedrate (configured axis name applies) + * + * With no arguments, report the current offsets. + */ +void GcodeSuite::M210() { + if (!parser.seen_any()) + return M210_report(); + + #if HAS_X_AXIS + if (parser.floatval('X') > 0) homing_feedrate_mm_m.x = parser.value_axis_units(X_AXIS); + #endif + #if HAS_Y_AXIS + if (parser.floatval('Y') > 0) homing_feedrate_mm_m.y = parser.value_axis_units(Y_AXIS); + #endif + #if HAS_Z_AXIS + if (parser.floatval('Z') > 0) homing_feedrate_mm_m.z = parser.value_axis_units(Z_AXIS); + #endif + #if HAS_I_AXIS + if (parser.floatval(AXIS4_NAME) > 0) homing_feedrate_mm_m.i = parser.value_axis_units(I_AXIS); + #endif + #if HAS_J_AXIS + if (parser.floatval(AXIS5_NAME) > 0) homing_feedrate_mm_m.j = parser.value_axis_units(J_AXIS); + #endif + #if HAS_K_AXIS + if (parser.floatval(AXIS6_NAME) > 0) homing_feedrate_mm_m.k = parser.value_axis_units(K_AXIS); + #endif + #if HAS_U_AXIS + if (parser.floatval(AXIS7_NAME) > 0) homing_feedrate_mm_m.u = parser.value_axis_units(U_AXIS); + #endif + #if HAS_V_AXIS + if (parser.floatval(AXIS8_NAME) > 0) homing_feedrate_mm_m.v = parser.value_axis_units(V_AXIS); + #endif + #if HAS_W_AXIS + if (parser.floatval(AXIS9_NAME) > 0) homing_feedrate_mm_m.w = parser.value_axis_units(W_AXIS); + #endif +} + +void GcodeSuite::M210_report(const bool forReplay/*=true*/) { + TERN_(MARLIN_SMALL_BUILD, return); + + report_heading_etc(forReplay, F(STR_HOMING_FEEDRATE)); + + SERIAL_ECHOPGM(" M210"); + SERIAL_ECHOLNPGM_P( + LIST_N(DOUBLE(NUM_AXES) + , SP_X_STR, X_AXIS_UNIT(homing_feedrate_mm_m.x) + , SP_Y_STR, Y_AXIS_UNIT(homing_feedrate_mm_m.y) + , SP_Z_STR, Z_AXIS_UNIT(homing_feedrate_mm_m.z) + , SP_I_STR, I_AXIS_UNIT(homing_feedrate_mm_m.i) + , SP_J_STR, J_AXIS_UNIT(homing_feedrate_mm_m.j) + , SP_K_STR, K_AXIS_UNIT(homing_feedrate_mm_m.k) + , SP_U_STR, U_AXIS_UNIT(homing_feedrate_mm_m.u) + , SP_V_STR, V_AXIS_UNIT(homing_feedrate_mm_m.v) + , SP_W_STR, W_AXIS_UNIT(homing_feedrate_mm_m.w) + ) + ); +} + +#endif // EDITABLE_HOMING_FEEDRATE diff --git a/Marlin/src/gcode/gcode.cpp b/Marlin/src/gcode/gcode.cpp index 1ccb10753cbc..32125752554b 100644 --- a/Marlin/src/gcode/gcode.cpp +++ b/Marlin/src/gcode/gcode.cpp @@ -200,9 +200,10 @@ void GcodeSuite::get_destination_from_command() { #endif if (parser.floatval('F') > 0) { - feedrate_mm_s = parser.value_feedrate(); + const float fr_mm_min = parser.value_linear_units(); + feedrate_mm_s = MMM_TO_MMS(fr_mm_min); // Update the cutter feed rate for use by M4 I set inline moves. - TERN_(LASER_FEATURE, cutter.feedrate_mm_m = MMS_TO_MMM(feedrate_mm_s)); + TERN_(LASER_FEATURE, cutter.feedrate_mm_m = fr_mm_min); } #if ALL(PRINTCOUNTER, HAS_EXTRUDERS) @@ -742,6 +743,10 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) { #endif #endif + #if ENABLED(EDITABLE_HOMING_FEEDRATE) + case 210: M210(); break; // M210: Set the homing feedrate + #endif + #if HAS_SOFTWARE_ENDSTOPS case 211: M211(); break; // M211: Enable, Disable, and/or Report software endstops #endif diff --git a/Marlin/src/gcode/gcode.h b/Marlin/src/gcode/gcode.h index 421dda9aec0f..2f725649971a 100644 --- a/Marlin/src/gcode/gcode.h +++ b/Marlin/src/gcode/gcode.h @@ -195,6 +195,7 @@ * M208 - Set Recover (unretract) Additional (!) Length: S and Feedrate: F. (Requires FWRETRACT) * M209 - Turn Automatic Retract Detection on/off: S<0|1> (For slicers that don't support G10/11). (Requires FWRETRACT_AUTORETRACT) Every normal extrude-only move will be classified as retract depending on the direction. + * M210 - Set or Report the homing feedrate (Requires EDITABLE_HOMING_FEEDRATE) * M211 - Enable, Disable, and/or Report software endstops: S<0|1> (Requires MIN_SOFTWARE_ENDSTOPS or MAX_SOFTWARE_ENDSTOPS) * M217 - Set filament swap parameters: "M217 S P R". (Requires SINGLENOZZLE) * M218 - Set/get a tool offset: "M218 T X Y". (Requires 2 or more extruders) @@ -897,8 +898,15 @@ class GcodeSuite { #endif #endif - static void M211(); - static void M211_report(const bool forReplay=true); + #if ENABLED(EDITABLE_HOMING_FEEDRATE) + static void M210(); + static void M210_report(const bool forReplay=true); + #endif + + #if HAS_SOFTWARE_ENDSTOPS + static void M211(); + static void M211_report(const bool forReplay=true); + #endif #if HAS_MULTI_EXTRUDER static void M217(); diff --git a/Marlin/src/gcode/parser.h b/Marlin/src/gcode/parser.h index 51ecaf15e9ad..9423b2380cfd 100644 --- a/Marlin/src/gcode/parser.h +++ b/Marlin/src/gcode/parser.h @@ -347,6 +347,9 @@ class GCodeParser { #define LINEAR_UNIT(V) parser.mm_to_linear_unit(V) #define VOLUMETRIC_UNIT(V) parser.mm_to_volumetric_unit(V) + #define X_AXIS_UNIT LINEAR_UNIT + #define Y_AXIS_UNIT LINEAR_UNIT + #define Z_AXIS_UNIT LINEAR_UNIT #define I_AXIS_UNIT(V) TERN(AXIS4_ROTATES, (V), LINEAR_UNIT(V)) #define J_AXIS_UNIT(V) TERN(AXIS5_ROTATES, (V), LINEAR_UNIT(V)) #define K_AXIS_UNIT(V) TERN(AXIS6_ROTATES, (V), LINEAR_UNIT(V)) diff --git a/Marlin/src/lcd/language/language_en.h b/Marlin/src/lcd/language/language_en.h index 1bd5c6314901..ad83797a41fb 100644 --- a/Marlin/src/lcd/language/language_en.h +++ b/Marlin/src/lcd/language/language_en.h @@ -99,6 +99,8 @@ namespace LanguageNarrow_en { LSTR MSG_ENDSTOP_TEST = _UxGT("Endstop Test"); LSTR MSG_Z_PROBE = _UxGT("Z Probe"); LSTR MSG_HOMING = _UxGT("Homing"); + LSTR MSG_HOMING_FEEDRATE = _UxGT("Homing Feedrate"); + LSTR MSG_HOMING_FEEDRATE_N = _UxGT("@ Homing FR"); LSTR MSG_AUTO_HOME = _UxGT("Auto Home"); LSTR MSG_HOME_ALL = _UxGT("Home All"); LSTR MSG_AUTO_HOME_N = _UxGT("Home @"); @@ -1094,6 +1096,7 @@ namespace LanguageWide_en { LSTR MSG_INFO_PRINT_TIME = _UxGT("Print Time"); LSTR MSG_INFO_PRINT_LONGEST = _UxGT("Longest Job Time"); LSTR MSG_INFO_PRINT_FILAMENT = _UxGT("Extruded Total"); + LSTR MSG_HOMING_FEEDRATE_N = _UxGT("@ Homing Feedrate"); #endif } diff --git a/Marlin/src/lcd/menu/menu_configuration.cpp b/Marlin/src/lcd/menu/menu_configuration.cpp index e8db64ac9064..d7eeab3cb3d2 100644 --- a/Marlin/src/lcd/menu/menu_configuration.cpp +++ b/Marlin/src/lcd/menu/menu_configuration.cpp @@ -395,7 +395,40 @@ void menu_advanced_settings(); END_MENU(); } -#endif +#endif // FWRETRACT + +#if ENABLED(EDITABLE_HOMING_FEEDRATE) + + #include "../../module/motion.h" + #include "../../module/planner.h" + #include "../../gcode/parser.h" + + // Edit homing feedrates in inches- or degrees- or mm-per-minute + void menu_homing_feedrate() { + START_MENU(); + BACK_ITEM(MSG_HOMING_FEEDRATE); + + #if ENABLED(MENUS_ALLOW_INCH_UNITS) + #define _EDIT_HOMING_FR(A) do{ \ + const float maxfr = MMS_TO_MMM(planner.settings.max_feedrate_mm_s[_AXIS(A)]); \ + editable.decimal = A##_AXIS_UNIT(homing_feedrate_mm_m.A); \ + EDIT_ITEM(float5, MSG_HOMING_FEEDRATE_N, &editable.decimal, \ + A##_AXIS_UNIT(10), A##_AXIS_UNIT(maxfr), []{ \ + homing_feedrate_mm_m.A = parser.axis_value_to_mm(_AXIS(A), editable.decimal); \ + }); \ + }while(0); + #else + #define _EDIT_HOMING_FR(A) do{ \ + EDIT_ITEM(float5, MSG_HOMING_FEEDRATE_N, &homing_feedrate_mm_m.A, 10, MMS_TO_MMM(planner.settings.max_feedrate_mm_s[_AXIS(A)])); \ + }while(0); + #endif + + MAIN_AXIS_MAP(_EDIT_HOMING_FR); + + END_MENU(); + } + +#endif // EDITABLE_HOMING_FEEDRATE #if HAS_PREHEAT && DISABLED(SLIM_LCD_MENUS) @@ -424,7 +457,7 @@ void menu_advanced_settings(); END_MENU(); } -#endif +#endif // HAS_PREHEAT && !SLIM_LCD_MENUS #if ENABLED(CUSTOM_MENU_CONFIG) @@ -623,6 +656,10 @@ void menu_configuration() { #endif #endif + #if ENABLED(EDITABLE_HOMING_FEEDRATE) + SUBMENU(MSG_HOMING_FEEDRATE, menu_homing_feedrate); + #endif + #if ENABLED(FWRETRACT) SUBMENU(MSG_RETRACT, menu_config_retract); #endif diff --git a/Marlin/src/module/motion.cpp b/Marlin/src/module/motion.cpp index af26cfff02ac..10be020680d4 100644 --- a/Marlin/src/module/motion.cpp +++ b/Marlin/src/module/motion.cpp @@ -146,6 +146,9 @@ xyze_pos_t destination; // {0} #endif feedRate_t feedrate_mm_s = MMM_TO_MMS(DEFAULT_FEEDRATE_MM_M); int16_t feedrate_percentage = 100; +#if ENABLED(EDITABLE_HOMING_FEEDRATE) + xyz_feedrate_t homing_feedrate_mm_m = HOMING_FEEDRATE_MM_M; +#endif // Cartesian conversion result goes here: xyz_pos_t cartes; diff --git a/Marlin/src/module/motion.h b/Marlin/src/module/motion.h index ef3a1026e033..6d3bfaed0dc5 100644 --- a/Marlin/src/module/motion.h +++ b/Marlin/src/module/motion.h @@ -79,7 +79,12 @@ extern xyz_pos_t cartes; * Feed rates are often configured with mm/m * but the planner and stepper like mm/s units. */ -constexpr xyz_feedrate_t homing_feedrate_mm_m = HOMING_FEEDRATE_MM_M; +#if ENABLED(EDITABLE_HOMING_FEEDRATE) + extern xyz_feedrate_t homing_feedrate_mm_m; +#else + constexpr xyz_feedrate_t homing_feedrate_mm_m = HOMING_FEEDRATE_MM_M; +#endif + FORCE_INLINE feedRate_t homing_feedrate(const AxisEnum a) { float v = TERN0(HAS_Z_AXIS, homing_feedrate_mm_m.z); #if DISABLED(DELTA) diff --git a/Marlin/src/module/settings.cpp b/Marlin/src/module/settings.cpp index a1dc52d989e8..fa7b5d1f139b 100644 --- a/Marlin/src/module/settings.cpp +++ b/Marlin/src/module/settings.cpp @@ -462,6 +462,13 @@ typedef struct SettingsDataStruct { fwretract_settings_t fwretract_settings; // M207 S F Z W, M208 S F W R bool autoretract_enabled; // M209 S + // + // EDITABLE_HOMING_FEEDRATE + // + #if ENABLED(EDITABLE_HOMING_FEEDRATE) + xyz_feedrate_t homing_feedrate_mm_m; // M210 X Y Z I J K U V W + #endif + // // !NO_VOLUMETRIC // @@ -1333,6 +1340,14 @@ void MarlinSettings::postprocess() { EEPROM_WRITE(TERN(FWRETRACT_AUTORETRACT, fwretract.autoretract_enabled, autoretract_enabled)); } + // + // Homing Feedrate + // + #if ENABLED(EDITABLE_HOMING_FEEDRATE) + _FIELD_TEST(homing_feedrate_mm_m); + EEPROM_WRITE(homing_feedrate_mm_m); + #endif + // // Volumetric & Filament Size // @@ -2421,6 +2436,14 @@ void MarlinSettings::postprocess() { #endif } + // + // Homing Feedrate + // + #if ENABLED(EDITABLE_HOMING_FEEDRATE) + _FIELD_TEST(homing_feedrate_mm_m); + EEPROM_READ(homing_feedrate_mm_m); + #endif + // // Volumetric & Filament Size // @@ -3649,6 +3672,11 @@ void MarlinSettings::reset() { // TERN_(FWRETRACT, fwretract.reset()); + // + // Homing Feedrate + // + TERN_(EDITABLE_HOMING_FEEDRATE, homing_feedrate_mm_m = xyz_feedrate_t(HOMING_FEEDRATE_MM_M)); + // // Volumetric & Filament Size // @@ -4049,6 +4077,11 @@ void MarlinSettings::reset() { TERN_(FWRETRACT_AUTORETRACT, gcode.M209_report(forReplay)); #endif + // + // Homing Feedrate + // + TERN_(EDITABLE_HOMING_FEEDRATE, gcode.M210_report(forReplay)); + // // Probe Offset // diff --git a/buildroot/tests/mega1280 b/buildroot/tests/mega1280 index 1d65b5ebf332..1b1a8f86b786 100755 --- a/buildroot/tests/mega1280 +++ b/buildroot/tests/mega1280 @@ -19,7 +19,7 @@ restore_configs opt_set LCD_LANGUAGE an \ POWER_MONITOR_CURRENT_PIN 14 POWER_MONITOR_VOLTAGE_PIN 15 \ CLOSED_LOOP_ENABLE_PIN 44 CLOSED_LOOP_MOVE_COMPLETE_PIN 45 -opt_enable SPINDLE_FEATURE ULTIMAKERCONTROLLER LCD_BED_LEVELING \ +opt_enable SPINDLE_FEATURE ULTIMAKERCONTROLLER LCD_BED_LEVELING EDITABLE_HOMING_FEEDRATE \ EEPROM_SETTINGS EEPROM_BOOT_SILENT EEPROM_AUTO_INIT \ SENSORLESS_BACKOFF_MM HOMING_BACKOFF_POST_MM HOME_Y_BEFORE_X CODEPENDENT_XY_HOMING \ MESH_BED_LEVELING ENABLE_LEVELING_FADE_HEIGHT MESH_G28_REST_ORIGIN \ diff --git a/ini/features.ini b/ini/features.ini index 420ba8e131f7..c6a657e30537 100644 --- a/ini/features.ini +++ b/ini/features.ini @@ -285,6 +285,7 @@ SKEW_CORRECTION_GCODE = build_src_filter=+ + PINS_DEBUGGING = build_src_filter=+ EDITABLE_STEPS_PER_UNIT = build_src_filter=+ +EDITABLE_HOMING_FEEDRATE = build_src_filter=+ HAS_MULTI_EXTRUDER = build_src_filter=+ HAS_HOTEND_OFFSET = build_src_filter=+ EDITABLE_SERVO_ANGLES = build_src_filter=+