🐛 Fix some bad feedrates (#25672)

This commit is contained in:
Scott Lahteine
2023-04-14 01:08:51 -05:00
committed by GitHub
parent c3921bbf3f
commit 161b99cb54
14 changed files with 50 additions and 63 deletions

View File

@@ -71,7 +71,7 @@ void GcodeSuite::G61() {
if (!TEST(saved_slots[slot >> 3], slot & 0x07)) return; if (!TEST(saved_slots[slot >> 3], slot & 0x07)) return;
// Apply any given feedrate over 0.0 // Apply any given feedrate over 0.0
feedRate_t saved_feedrate = feedrate_mm_s; REMEMBER(saved, feedrate_mm_s);
const float fr = parser.linearval('F'); const float fr = parser.linearval('F');
if (fr > 0.0) feedrate_mm_s = MMM_TO_MMS(fr); if (fr > 0.0) feedrate_mm_s = MMM_TO_MMS(fr);
@@ -101,8 +101,6 @@ void GcodeSuite::G61() {
} }
#endif #endif
} }
feedrate_mm_s = saved_feedrate;
} }
#endif // SAVED_POSITIONS #endif // SAVED_POSITIONS

View File

@@ -157,7 +157,7 @@ void DGUSScreenHandler::HandleManualMove(DGUS_VP_Variable &var, void *val_ptr) {
} }
#endif #endif
char axiscode; char axiscode;
uint16_t speed = _mf[X_AXIS]; // Default feedrate for manual moves uint16_t speed = manual_feedrate_mm_m[X_AXIS]; // Default feedrate for manual moves
switch (var.VP) { switch (var.VP) {
default: return; default: return;
@@ -170,7 +170,7 @@ void DGUSScreenHandler::HandleManualMove(DGUS_VP_Variable &var, void *val_ptr) {
#if HAS_Y_AXIS #if HAS_Y_AXIS
case VP_MOVE_Y: case VP_MOVE_Y:
axiscode = 'Y'; axiscode = 'Y';
speed = _mf[Y_AXIS]; speed = manual_feedrate_mm_m[Y_AXIS];
if (!ExtUI::canMove(ExtUI::axis_t::Y)) goto cannotmove; if (!ExtUI::canMove(ExtUI::axis_t::Y)) goto cannotmove;
break; break;
#endif #endif
@@ -178,7 +178,7 @@ void DGUSScreenHandler::HandleManualMove(DGUS_VP_Variable &var, void *val_ptr) {
#if HAS_Z_AXIS #if HAS_Z_AXIS
case VP_MOVE_Z: case VP_MOVE_Z:
axiscode = 'Z'; axiscode = 'Z';
speed = _mf[Z_AXIS]; speed = manual_feedrate_mm_m[Z_AXIS];
if (!ExtUI::canMove(ExtUI::axis_t::Z)) goto cannotmove; if (!ExtUI::canMove(ExtUI::axis_t::Z)) goto cannotmove;
break; break;
#endif #endif

View File

@@ -157,7 +157,7 @@ void DGUSScreenHandler::HandleManualMove(DGUS_VP_Variable &var, void *val_ptr) {
} }
#endif #endif
char axiscode; char axiscode;
uint16_t speed = _mf[X_AXIS]; // Default feedrate for manual moves uint16_t speed = manual_feedrate_mm_m[X_AXIS]; // Default feedrate for manual moves
switch (var.VP) { switch (var.VP) {
default: return; default: return;
@@ -170,7 +170,7 @@ void DGUSScreenHandler::HandleManualMove(DGUS_VP_Variable &var, void *val_ptr) {
#if HAS_Y_AXIS #if HAS_Y_AXIS
case VP_MOVE_Y: case VP_MOVE_Y:
axiscode = 'Y'; axiscode = 'Y';
speed = _mf[Y_AXIS]; speed = manual_feedrate_mm_m[Y_AXIS];
if (!ExtUI::canMove(ExtUI::axis_t::Y)) goto cannotmove; if (!ExtUI::canMove(ExtUI::axis_t::Y)) goto cannotmove;
break; break;
#endif #endif
@@ -178,7 +178,7 @@ void DGUSScreenHandler::HandleManualMove(DGUS_VP_Variable &var, void *val_ptr) {
#if HAS_Z_AXIS #if HAS_Z_AXIS
case VP_MOVE_Z: case VP_MOVE_Z:
axiscode = 'Z'; axiscode = 'Z';
speed = _mf[Z_AXIS]; speed = manual_feedrate_mm_m[Z_AXIS];
if (!ExtUI::canMove(ExtUI::axis_t::Z)) goto cannotmove; if (!ExtUI::canMove(ExtUI::axis_t::Z)) goto cannotmove;
break; break;
#endif #endif

View File

@@ -739,7 +739,7 @@ void DGUSScreenHandler::HandleManualMove(DGUS_VP_Variable &var, void *val_ptr) {
return; return;
char axiscode; char axiscode;
uint16_t speed = _mf[X_AXIS]; // Default feedrate for manual moves uint16_t speed = manual_feedrate_mm_m[X_AXIS]; // Default feedrate for manual moves
switch (var.VP) { // switch X Y Z or Home switch (var.VP) { // switch X Y Z or Home
default: return; default: return;
@@ -751,7 +751,7 @@ void DGUSScreenHandler::HandleManualMove(DGUS_VP_Variable &var, void *val_ptr) {
#if HAS_Y_AXIS #if HAS_Y_AXIS
case VP_MOVE_Y: case VP_MOVE_Y:
axiscode = 'Y'; axiscode = 'Y';
speed = _mf[Y_AXIS]; speed = manual_feedrate_mm_m[Y_AXIS];
if (!ExtUI::canMove(ExtUI::axis_t::Y)) goto cannotmove; if (!ExtUI::canMove(ExtUI::axis_t::Y)) goto cannotmove;
break; break;
#endif #endif
@@ -759,7 +759,7 @@ void DGUSScreenHandler::HandleManualMove(DGUS_VP_Variable &var, void *val_ptr) {
#if HAS_Z_AXIS #if HAS_Z_AXIS
case VP_MOVE_Z: case VP_MOVE_Z:
axiscode = 'Z'; axiscode = 'Z';
speed = _mf[Z_AXIS]; speed = manual_feedrate_mm_m[Z_AXIS];
if (!ExtUI::canMove(ExtUI::axis_t::Z)) goto cannotmove; if (!ExtUI::canMove(ExtUI::axis_t::Z)) goto cannotmove;
break; break;
#endif #endif

View File

@@ -157,7 +157,7 @@ void DGUSScreenHandler::HandleManualMove(DGUS_VP_Variable &var, void *val_ptr) {
} }
#endif #endif
char axiscode; char axiscode;
uint16_t speed = _mf[X_AXIS]; // Default feedrate for manual moves uint16_t speed = manual_feedrate_mm_m[X_AXIS]; // Default feedrate for manual moves
switch (var.VP) { switch (var.VP) {
default: return; default: return;
@@ -170,7 +170,7 @@ void DGUSScreenHandler::HandleManualMove(DGUS_VP_Variable &var, void *val_ptr) {
#if HAS_Y_AXIS #if HAS_Y_AXIS
case VP_MOVE_Y: case VP_MOVE_Y:
axiscode = 'Y'; axiscode = 'Y';
speed = _mf[Y_AXIS]; speed = manual_feedrate_mm_m[Y_AXIS];
if (!ExtUI::canMove(ExtUI::axis_t::Y)) goto cannotmove; if (!ExtUI::canMove(ExtUI::axis_t::Y)) goto cannotmove;
break; break;
#endif #endif
@@ -178,7 +178,7 @@ void DGUSScreenHandler::HandleManualMove(DGUS_VP_Variable &var, void *val_ptr) {
#if HAS_Z_AXIS #if HAS_Z_AXIS
case VP_MOVE_Z: case VP_MOVE_Z:
axiscode = 'Z'; axiscode = 'Z';
speed = _mf[Z_AXIS]; speed = manual_feedrate_mm_m[Z_AXIS];
if (!ExtUI::canMove(ExtUI::axis_t::Z)) goto cannotmove; if (!ExtUI::canMove(ExtUI::axis_t::Z)) goto cannotmove;
break; break;
#endif #endif

View File

@@ -72,7 +72,7 @@ void MoveAxisScreen::onRedraw(draw_mode_t what) {
w.increments(); w.increments();
} }
bool BaseMoveAxisScreen::onTouchHeld(uint8_t tag) { bool BaseMoveAxisScreen::onTouchHeld(const uint8_t tag) {
#define UI_INCREMENT_AXIS(axis) setManualFeedrate(axis, increment); UI_INCREMENT(AxisPosition_mm, axis); #define UI_INCREMENT_AXIS(axis) setManualFeedrate(axis, increment); UI_INCREMENT(AxisPosition_mm, axis);
#define UI_DECREMENT_AXIS(axis) setManualFeedrate(axis, increment); UI_DECREMENT(AxisPosition_mm, axis); #define UI_DECREMENT_AXIS(axis) setManualFeedrate(axis, increment); UI_DECREMENT(AxisPosition_mm, axis);
const float increment = getIncrement(); const float increment = getIncrement();
@@ -120,20 +120,20 @@ void BaseMoveAxisScreen::raiseZtoTop() {
setAxisPosition_mm(Z_MAX_POS - 5, Z, homing_feedrate.z); setAxisPosition_mm(Z_MAX_POS - 5, Z, homing_feedrate.z);
} }
float BaseMoveAxisScreen::getManualFeedrate(uint8_t axis, float increment_mm) { float BaseMoveAxisScreen::getManualFeedrate(const uint8_t axis, const_float_t increment_mm) {
// Compute feedrate so that the tool lags the adjuster when it is // Compute feedrate so that the tool lags the adjuster when it is
// being held down, this allows enough margin for the planner to // being held down, this allows enough margin for the planner to
// connect segments and even out the motion. // connect segments and even out the motion.
constexpr xyze_feedrate_t max_manual_feedrate = MANUAL_FEEDRATE; constexpr xyze_feedrate_t max_manual_feedrate = MANUAL_FEEDRATE;
return min(max_manual_feedrate[axis] / 60.0f, ABS(increment_mm * (TOUCH_REPEATS_PER_SECOND) * 0.80f)); return min(MMM_TO_MMS(max_manual_feedrate[axis]), ABS(increment_mm * (TOUCH_REPEATS_PER_SECOND) * 0.80f));
} }
void BaseMoveAxisScreen::setManualFeedrate(ExtUI::axis_t axis, float increment_mm) { void BaseMoveAxisScreen::setManualFeedrate(const ExtUI::axis_t axis, const_float_t increment_mm) {
ExtUI::setFeedrate_mm_s(getManualFeedrate(X_AXIS + (axis - ExtUI::X), increment_mm)); ExtUI::setFeedrate_mm_s(getManualFeedrate(X_AXIS + (axis - ExtUI::X), increment_mm));
} }
#if HAS_EXTRUDERS #if HAS_EXTRUDERS
void BaseMoveAxisScreen::setManualFeedrate(ExtUI::extruder_t, float increment_mm) { void BaseMoveAxisScreen::setManualFeedrate(const ExtUI::extruder_t, const_float_t increment_mm) {
ExtUI::setFeedrate_mm_s(getManualFeedrate(E_AXIS, increment_mm)); ExtUI::setFeedrate_mm_s(getManualFeedrate(E_AXIS, increment_mm));
} }
#endif #endif

View File

@@ -32,14 +32,14 @@ struct MoveAxisScreenData {
class BaseMoveAxisScreen : public BaseNumericAdjustmentScreen { class BaseMoveAxisScreen : public BaseNumericAdjustmentScreen {
private: private:
static float getManualFeedrate(uint8_t axis, float increment_mm); static float getManualFeedrate(const uint8_t axis, const_float_t increment_mm);
public: public:
static void raiseZtoTop(); static void raiseZtoTop();
static void setManualFeedrate(ExtUI::axis_t, float increment_mm); static void setManualFeedrate(const ExtUI::axis_t, const_float_t increment_mm);
static void setManualFeedrate(ExtUI::extruder_t, float increment_mm); static void setManualFeedrate(const ExtUI::extruder_t, const_float_t increment_mm);
static void onEntry(); static void onEntry();
static bool onTouchHeld(uint8_t tag); static bool onTouchHeld(const uint8_t tag);
}; };
class MoveAxisScreen : public BaseMoveAxisScreen, public CachedScreen<MOVE_AXIS_SCREEN_CACHE> { class MoveAxisScreen : public BaseMoveAxisScreen, public CachedScreen<MOVE_AXIS_SCREEN_CACHE> {

View File

@@ -932,22 +932,21 @@ namespace ExtUI {
void moveToMeshPoint(const xy_uint8_t &pos, const_float_t z) { void moveToMeshPoint(const xy_uint8_t &pos, const_float_t z) {
#if EITHER(MESH_BED_LEVELING, AUTO_BED_LEVELING_UBL) #if EITHER(MESH_BED_LEVELING, AUTO_BED_LEVELING_UBL)
const feedRate_t old_feedrate = feedrate_mm_s; REMEMBER(fr, feedrate_mm_s);
const float x_target = MESH_MIN_X + pos.x * (MESH_X_DIST), const float x_target = MESH_MIN_X + pos.x * (MESH_X_DIST),
y_target = MESH_MIN_Y + pos.y * (MESH_Y_DIST); y_target = MESH_MIN_Y + pos.y * (MESH_Y_DIST);
if (x_target != current_position.x || y_target != current_position.y) { if (x_target != current_position.x || y_target != current_position.y) {
// If moving across bed, raise nozzle to safe height over bed // If moving across bed, raise nozzle to safe height over bed
feedrate_mm_s = Z_PROBE_FEEDRATE_FAST; feedrate_mm_s = MMM_TO_MMS(Z_PROBE_FEEDRATE_FAST);
destination.set(current_position.x, current_position.y, Z_CLEARANCE_BETWEEN_PROBES); destination.set(current_position.x, current_position.y, Z_CLEARANCE_BETWEEN_PROBES);
prepare_line_to_destination(); prepare_line_to_destination();
feedrate_mm_s = XY_PROBE_FEEDRATE; feedrate_mm_s = XY_PROBE_FEEDRATE_MM_S;
destination.set(x_target, y_target); destination.set(x_target, y_target);
prepare_line_to_destination(); prepare_line_to_destination();
} }
feedrate_mm_s = Z_PROBE_FEEDRATE_FAST; feedrate_mm_s = MMM_TO_MMS(Z_PROBE_FEEDRATE_FAST);
destination.z = z; destination.z = z;
prepare_line_to_destination(); prepare_line_to_destination();
feedrate_mm_s = old_feedrate;
#else #else
UNUSED(pos); UNUSED(pos);
UNUSED(z); UNUSED(z);

View File

@@ -119,7 +119,7 @@ void prepare_for_probe_offset_wizard() {
// Move Nozzle to Probing/Homing Position // Move Nozzle to Probing/Homing Position
ui.wait_for_move = true; ui.wait_for_move = true;
current_position += probe.offset_xy; current_position += probe.offset_xy;
line_to_current_position(MMM_TO_MMS(XY_PROBE_FEEDRATE)); line_to_current_position(XY_PROBE_FEEDRATE_MM_S);
ui.synchronize(GET_TEXT_F(MSG_PROBE_WIZARD_MOVING)); ui.synchronize(GET_TEXT_F(MSG_PROBE_WIZARD_MOVING));
ui.wait_for_move = false; ui.wait_for_move = false;

View File

@@ -141,7 +141,7 @@ void xatc_wizard_goto_next_point() {
xatc.set_enabled(true); xatc.set_enabled(true);
current_position += probe.offset_xy; current_position += probe.offset_xy;
current_position.z = (XATC_START_Z) - probe.offset.z + measured_z; current_position.z = (XATC_START_Z) - probe.offset.z + measured_z;
line_to_current_position(MMM_TO_MMS(XY_PROBE_FEEDRATE)); line_to_current_position(XY_PROBE_FEEDRATE_MM_S);
ui.wait_for_move = false; ui.wait_for_move = false;
} }
else else

View File

@@ -525,25 +525,15 @@ void line_to_current_position(const_feedRate_t fr_mm_s/*=feedrate_mm_s*/) {
void _internal_move_to_destination(const_feedRate_t fr_mm_s/*=0.0f*/ void _internal_move_to_destination(const_feedRate_t fr_mm_s/*=0.0f*/
OPTARG(IS_KINEMATIC, const bool is_fast/*=false*/) OPTARG(IS_KINEMATIC, const bool is_fast/*=false*/)
) { ) {
const feedRate_t old_feedrate = feedrate_mm_s; REMEMBER(fr, feedrate_mm_s);
REMEMBER(pct, feedrate_percentage, 100);
TERN_(HAS_EXTRUDERS, REMEMBER(fac, planner.e_factor[active_extruder], 1.0f));
if (fr_mm_s) feedrate_mm_s = fr_mm_s; if (fr_mm_s) feedrate_mm_s = fr_mm_s;
const uint16_t old_pct = feedrate_percentage;
feedrate_percentage = 100;
#if HAS_EXTRUDERS
const float old_fac = planner.e_factor[active_extruder];
planner.e_factor[active_extruder] = 1.0f;
#endif
if (TERN0(IS_KINEMATIC, is_fast)) if (TERN0(IS_KINEMATIC, is_fast))
TERN(IS_KINEMATIC, prepare_fast_move_to_destination(), NOOP); TERN(IS_KINEMATIC, prepare_fast_move_to_destination(), NOOP);
else else
prepare_line_to_destination(); prepare_line_to_destination();
feedrate_mm_s = old_feedrate;
feedrate_percentage = old_pct;
TERN_(HAS_EXTRUDERS, planner.e_factor[active_extruder] = old_fac);
} }
/** /**

View File

@@ -80,11 +80,12 @@
// Feedrate for manual moves // Feedrate for manual moves
#ifdef MANUAL_FEEDRATE #ifdef MANUAL_FEEDRATE
constexpr xyze_feedrate_t _mf = MANUAL_FEEDRATE, constexpr xyze_feedrate_t manual_feedrate_mm_m = MANUAL_FEEDRATE,
manual_feedrate_mm_s = LOGICAL_AXIS_ARRAY(_mf.e / 60.0f, manual_feedrate_mm_s = LOGICAL_AXIS_ARRAY(
_mf.x / 60.0f, _mf.y / 60.0f, _mf.z / 60.0f, MMM_TO_MMS(manual_feedrate_mm_m.e),
_mf.i / 60.0f, _mf.j / 60.0f, _mf.k / 60.0f, MMM_TO_MMS(manual_feedrate_mm_m.x), MMM_TO_MMS(manual_feedrate_mm_m.y), MMM_TO_MMS(manual_feedrate_mm_m.z),
_mf.u / 60.0f, _mf.v / 60.0f, _mf.w / 60.0f); MMM_TO_MMS(manual_feedrate_mm_m.i), MMM_TO_MMS(manual_feedrate_mm_m.j), MMM_TO_MMS(manual_feedrate_mm_m.k),
MMM_TO_MMS(manual_feedrate_mm_m.u), MMM_TO_MMS(manual_feedrate_mm_m.v), MMM_TO_MMS(manual_feedrate_mm_m.w));
#endif #endif
#if IS_KINEMATIC && HAS_JUNCTION_DEVIATION #if IS_KINEMATIC && HAS_JUNCTION_DEVIATION

View File

@@ -957,13 +957,12 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0.
* If cooling fan is enabled, calls filament_swap_cooling(); * If cooling fan is enabled, calls filament_swap_cooling();
*/ */
void extruder_prime() { void extruder_prime() {
if (too_cold(active_extruder)) { if (too_cold(active_extruder)) {
FS_DEBUG("Priming Aborted - Nozzle Too Cold!"); FS_DEBUG("Priming Aborted - Nozzle Too Cold!");
return; // Extruder too cold to prime return; // Extruder too cold to prime
} }
float fr = toolchange_settings.unretract_speed; // Set default speed for unretract feedRate_t fr_mm_s = MMM_TO_MMS(toolchange_settings.unretract_speed); // Set default speed for unretract
#if ENABLED(TOOLCHANGE_FS_SLOW_FIRST_PRIME) #if ENABLED(TOOLCHANGE_FS_SLOW_FIRST_PRIME)
/** /**
@@ -973,18 +972,19 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0.
if (!extruder_did_first_prime[active_extruder]) { if (!extruder_did_first_prime[active_extruder]) {
extruder_did_first_prime.set(active_extruder); // Log first prime complete extruder_did_first_prime.set(active_extruder); // Log first prime complete
// new nozzle - prime at user-specified speed. // new nozzle - prime at user-specified speed.
FS_DEBUG("First time priming T", active_extruder, ", reducing speed from ", MMM_TO_MMS(fr), " to ", MMM_TO_MMS(toolchange_settings.prime_speed), "mm/s"); const feedRate_t prime_mm_s = MMM_TO_MMS(toolchange_settings.prime_speed);
fr = toolchange_settings.prime_speed; FS_DEBUG("First time priming T", active_extruder, ", reducing speed from ", fr_mm_s, " to ", prime_mm_s, "mm/s");
unscaled_e_move(0, MMM_TO_MMS(fr)); // Init planner with 0 length move fr_mm_s = prime_mm_s;
unscaled_e_move(0, fr_mm_s); // Init planner with 0 length move
} }
#endif #endif
// Calculate and perform the priming distance // Calculate and perform the priming distance
if (toolchange_settings.extra_prime >= 0) { if (toolchange_settings.extra_prime >= 0) {
// Positive extra_prime value // Positive extra_prime value
// - Return filament at speed (fr) then extra_prime at prime speed // - Return filament at speed (fr_mm_s) then extra_prime at prime speed
FS_DEBUG("Loading Filament for T", active_extruder, " | Distance: ", toolchange_settings.swap_length, " | Speed: ", MMM_TO_MMS(fr), "mm/s"); FS_DEBUG("Loading Filament for T", active_extruder, " | Distance: ", toolchange_settings.swap_length, " | Speed: ", fr_mm_s, "mm/s");
unscaled_e_move(toolchange_settings.swap_length, MMM_TO_MMS(fr)); // Prime (Unretract) filament by extruding equal to Swap Length (Unretract) unscaled_e_move(toolchange_settings.swap_length, fr_mm_s); // Prime (Unretract) filament by extruding equal to Swap Length (Unretract)
if (toolchange_settings.extra_prime > 0) { if (toolchange_settings.extra_prime > 0) {
FS_DEBUG("Performing Extra Priming for T", active_extruder, " | Distance: ", toolchange_settings.extra_prime, " | Speed: ", MMM_TO_MMS(toolchange_settings.prime_speed), "mm/s"); FS_DEBUG("Performing Extra Priming for T", active_extruder, " | Distance: ", toolchange_settings.extra_prime, " | Speed: ", MMM_TO_MMS(toolchange_settings.prime_speed), "mm/s");
@@ -996,8 +996,8 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0.
// - Unretract distance (swap length) is reduced by the value of extra_prime // - Unretract distance (swap length) is reduced by the value of extra_prime
const float eswap = toolchange_settings.swap_length + toolchange_settings.extra_prime; const float eswap = toolchange_settings.swap_length + toolchange_settings.extra_prime;
FS_DEBUG("Negative ExtraPrime value - Swap Return Length has been reduced from ", toolchange_settings.swap_length, " to ", eswap); FS_DEBUG("Negative ExtraPrime value - Swap Return Length has been reduced from ", toolchange_settings.swap_length, " to ", eswap);
FS_DEBUG("Loading Filament for T", active_extruder, " | Distance: ", eswap, " | Speed: ", MMM_TO_MMS(fr), "mm/s"); FS_DEBUG("Loading Filament for T", active_extruder, " | Distance: ", eswap, " | Speed: ", fr_mm_s, "mm/s");
unscaled_e_move(eswap, MMM_TO_MMS(fr)); unscaled_e_move(eswap, fr_mm_s);
} }
extruder_was_primed.set(active_extruder); // Log that this extruder has been primed extruder_was_primed.set(active_extruder); // Log that this extruder has been primed
@@ -1010,7 +1010,6 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0.
// Cool down with fan // Cool down with fan
filament_swap_cooling(); filament_swap_cooling();
} }
/** /**

View File

@@ -34,8 +34,8 @@
float extra_resume; // M217 B float extra_resume; // M217 B
int16_t prime_speed; // M217 P int16_t prime_speed; // M217 P
int16_t wipe_retract; // M217 G int16_t wipe_retract; // M217 G
int16_t retract_speed; // M217 R int16_t retract_speed; // M217 R (mm/m)
int16_t unretract_speed; // M217 U int16_t unretract_speed; // M217 U (mm/m)
uint8_t fan_speed; // M217 F uint8_t fan_speed; // M217 F
uint8_t fan_time; // M217 D uint8_t fan_time; // M217 D
#endif #endif