diff --git a/Marlin/Conditionals_LCD.h b/Marlin/Conditionals_LCD.h index 13dbf8a006..8418385026 100644 --- a/Marlin/Conditionals_LCD.h +++ b/Marlin/Conditionals_LCD.h @@ -286,7 +286,7 @@ * HOTENDS - Number of hotends, whether connected or separate * E_STEPPERS - Number of actual E stepper motors * TOOL_E_INDEX - Index to use when getting/setting the tool state - * + * */ #if ENABLED(SINGLENOZZLE) // One hotend, multi-extruder #define HOTENDS 1 @@ -316,6 +316,18 @@ #define TOOL_E_INDEX current_block->active_extruder #endif + /** + * Distinct E Factors – Disable by commenting out DISTINCT_E_FACTORS + */ + #if ENABLED(DISTINCT_E_FACTORS) && E_STEPPERS > 1 + #define XYZE_N (XYZ + E_STEPPERS) + #define E_AXIS_N (E_AXIS + extruder) + #else + #undef DISTINCT_E_FACTORS + #define XYZE_N XYZE + #define E_AXIS_N E_AXIS + #endif + /** * The BLTouch Probe emulates a servo probe * and uses "special" angles for its state. diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index e616fa3fd8..5565afb3b1 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -145,6 +145,9 @@ // :[1, 2, 3, 4] #define EXTRUDERS 1 +// Enable if your E steppers or extruder gear ratios are not identical +//#define DISTINCT_E_FACTORS + // For Cyclops or any "multi-extruder" that shares a single nozzle. //#define SINGLENOZZLE @@ -472,26 +475,31 @@ * * These settings can be reset by M502 * + * You can set distinct factors for each E stepper, if needed. + * If fewer factors are given, the last will apply to the rest. + * * Note that if EEPROM is enabled, saved values will override these. */ /** * Default Axis Steps Per Unit (steps/mm) * Override with M92 + * X, Y, Z, E0 [, E1[, E2[, E3]]] */ #define DEFAULT_AXIS_STEPS_PER_UNIT { 80, 80, 4000, 500 } /** * Default Max Feed Rate (mm/s) * Override with M203 + * X, Y, Z, E0 [, E1[, E2[, E3]]] */ #define DEFAULT_MAX_FEEDRATE { 300, 300, 5, 25 } /** * Default Max Acceleration (change/s) change = mm/s + * (Maximum start speed for accelerated moves) * Override with M201 - * - * Maximum start speed for accelerated moves: { X, Y, Z, E } + * X, Y, Z, E0 [, E1[, E2[, E3]]] */ #define DEFAULT_MAX_ACCELERATION { 3000, 3000, 100, 10000 } diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index 4e7a1b8f31..6c60fabdaa 100755 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -1227,7 +1227,7 @@ inline bool code_value_bool() { return !code_has_value() || code_value_byte() > } inline float axis_unit_factor(int axis) { - return (axis == E_AXIS && volumetric_enabled ? volumetric_unit_factor : linear_unit_factor); + return (axis >= E_AXIS && volumetric_enabled ? volumetric_unit_factor : linear_unit_factor); } inline float code_value_linear_units() { return code_value_float() * linear_unit_factor; } @@ -5794,22 +5794,38 @@ inline void gcode_M85() { if (code_seen('S')) max_inactive_time = code_value_millis_from_seconds(); } +/** + * Multi-stepper support for M92, M201, M203 + */ +#if ENABLED(DISTINCT_E_FACTORS) + #define GET_TARGET_EXTRUDER(CMD) if (get_target_extruder_from_command(CMD)) return + #define TARGET_EXTRUDER target_extruder +#else + #define GET_TARGET_EXTRUDER(CMD) NOOP + #define TARGET_EXTRUDER 0 +#endif + /** * M92: Set axis steps-per-unit for one or more axes, X, Y, Z, and E. * (Follows the same syntax as G92) + * + * With multiple extruders use T to specify which one. */ inline void gcode_M92() { + + GET_TARGET_EXTRUDER(92); + LOOP_XYZE(i) { if (code_seen(axis_codes[i])) { if (i == E_AXIS) { - float value = code_value_per_axis_unit(i); + float value = code_value_per_axis_unit(E_AXIS + TARGET_EXTRUDER); if (value < 20.0) { - float factor = planner.axis_steps_per_mm[i] / value; // increase e constants if M92 E14 is given for netfab. + float factor = planner.axis_steps_per_mm[E_AXIS + TARGET_EXTRUDER] / value; // increase e constants if M92 E14 is given for netfab. planner.max_jerk[E_AXIS] *= factor; - planner.max_feedrate_mm_s[E_AXIS] *= factor; - planner.max_acceleration_steps_per_s2[E_AXIS] *= factor; + planner.max_feedrate_mm_s[E_AXIS + TARGET_EXTRUDER] *= factor; + planner.max_acceleration_steps_per_s2[E_AXIS + TARGET_EXTRUDER] *= factor; } - planner.axis_steps_per_mm[E_AXIS] = value; + planner.axis_steps_per_mm[E_AXIS + TARGET_EXTRUDER] = value; } else { planner.axis_steps_per_mm[i] = code_value_per_axis_unit(i); @@ -6060,11 +6076,17 @@ inline void gcode_M200() { /** * M201: Set max acceleration in units/s^2 for print moves (M201 X1000 Y1000) + * + * With multiple extruders use T to specify which one. */ inline void gcode_M201() { + + GET_TARGET_EXTRUDER(201); + LOOP_XYZE(i) { if (code_seen(axis_codes[i])) { - planner.max_acceleration_mm_per_s2[i] = code_value_axis_units(i); + const uint8_t a = i + (i == E_AXIS ? TARGET_EXTRUDER : 0); + planner.max_acceleration_mm_per_s2[a] = code_value_axis_units(a); } } // steps per sq second need to be updated to agree with the units per sq second (as they are what is used in the planner) @@ -6082,11 +6104,18 @@ inline void gcode_M201() { /** * M203: Set maximum feedrate that your machine can sustain (M203 X200 Y200 Z300 E10000) in units/sec + * + * With multiple extruders use T to specify which one. */ inline void gcode_M203() { + + GET_TARGET_EXTRUDER(203); + LOOP_XYZE(i) - if (code_seen(axis_codes[i])) - planner.max_feedrate_mm_s[i] = code_value_axis_units(i); + if (code_seen(axis_codes[i])) { + const uint8_t a = i + (i == E_AXIS ? TARGET_EXTRUDER : 0); + planner.max_feedrate_mm_s[a] = code_value_axis_units(a); + } } /** diff --git a/Marlin/configuration_store.cpp b/Marlin/configuration_store.cpp index f1f898c4a3..a3ae225b22 100644 --- a/Marlin/configuration_store.cpp +++ b/Marlin/configuration_store.cpp @@ -47,9 +47,9 @@ * 100 Version (char x4) * 104 EEPROM Checksum (uint16_t) * - * 106 M92 XYZE planner.axis_steps_per_mm (float x4) - * 122 M203 XYZE planner.max_feedrate_mm_s (float x4) - * 138 M201 XYZE planner.max_acceleration_mm_per_s2 (uint32_t x4) + * 106 M92 XYZE planner.axis_steps_per_mm (float x4 ... x7) + * 122 M203 XYZE planner.max_feedrate_mm_s (float x4 ... x7) + * 138 M201 XYZE planner.max_acceleration_mm_per_s2 (uint32_t x4 ... x7) * 154 M204 P planner.acceleration (float) * 158 M204 R planner.retract_acceleration (float) * 162 M204 T planner.travel_acceleration (float) @@ -571,10 +571,10 @@ void Config_Postprocess() { void Config_ResetDefault() { const float tmp1[] = DEFAULT_AXIS_STEPS_PER_UNIT, tmp2[] = DEFAULT_MAX_FEEDRATE; const long tmp3[] = DEFAULT_MAX_ACCELERATION; - LOOP_XYZE(i) { - planner.axis_steps_per_mm[i] = tmp1[i]; - planner.max_feedrate_mm_s[i] = tmp2[i]; - planner.max_acceleration_mm_per_s2[i] = tmp3[i]; + LOOP_XYZE_N(i) { + planner.axis_steps_per_mm[i] = tmp1[i < COUNT(tmp1) ? i : COUNT(tmp1) - 1]; + planner.max_feedrate_mm_s[i] = tmp2[i < COUNT(tmp2) ? i : COUNT(tmp2) - 1]; + planner.max_acceleration_mm_per_s2[i] = tmp3[i < COUNT(tmp3) ? i : COUNT(tmp3) - 1]; } planner.acceleration = DEFAULT_ACCELERATION; @@ -719,8 +719,16 @@ void Config_ResetDefault() { SERIAL_ECHOPAIR(" M92 X", planner.axis_steps_per_mm[X_AXIS]); SERIAL_ECHOPAIR(" Y", planner.axis_steps_per_mm[Y_AXIS]); SERIAL_ECHOPAIR(" Z", planner.axis_steps_per_mm[Z_AXIS]); - SERIAL_ECHOPAIR(" E", planner.axis_steps_per_mm[E_AXIS]); + #if E_STEPPERS == 1 + SERIAL_ECHOPAIR(" E", planner.axis_steps_per_mm[E_AXIS]); + #endif SERIAL_EOL; + #if ENABLED(DISTINCT_E_FACTORS) + for (uint8_t i = 0; i < E_STEPPERS; i++) { + SERIAL_ECHOPAIR(" M92 T", (int)i); + SERIAL_ECHOLNPAIR(" E", planner.axis_steps_per_mm[E_AXIS + i]); + } + #endif CONFIG_ECHO_START; @@ -731,8 +739,16 @@ void Config_ResetDefault() { SERIAL_ECHOPAIR(" M203 X", planner.max_feedrate_mm_s[X_AXIS]); SERIAL_ECHOPAIR(" Y", planner.max_feedrate_mm_s[Y_AXIS]); SERIAL_ECHOPAIR(" Z", planner.max_feedrate_mm_s[Z_AXIS]); - SERIAL_ECHOPAIR(" E", planner.max_feedrate_mm_s[E_AXIS]); + #if E_STEPPERS == 1 + SERIAL_ECHOPAIR(" E", planner.max_feedrate_mm_s[E_AXIS]); + #endif SERIAL_EOL; + #if ENABLED(DISTINCT_E_FACTORS) + for (uint8_t i = 0; i < E_STEPPERS; i++) { + SERIAL_ECHOPAIR(" M203 T", (int)i); + SERIAL_ECHOLNPAIR(" E", planner.max_feedrate_mm_s[E_AXIS + i]); + } + #endif CONFIG_ECHO_START; if (!forReplay) { @@ -742,8 +758,17 @@ void Config_ResetDefault() { SERIAL_ECHOPAIR(" M201 X", planner.max_acceleration_mm_per_s2[X_AXIS]); SERIAL_ECHOPAIR(" Y", planner.max_acceleration_mm_per_s2[Y_AXIS]); SERIAL_ECHOPAIR(" Z", planner.max_acceleration_mm_per_s2[Z_AXIS]); - SERIAL_ECHOPAIR(" E", planner.max_acceleration_mm_per_s2[E_AXIS]); + #if E_STEPPERS == 1 + SERIAL_ECHOPAIR(" E", planner.max_acceleration_mm_per_s2[E_AXIS]); + #endif SERIAL_EOL; + #if ENABLED(DISTINCT_E_FACTORS) + for (uint8_t i = 0; i < E_STEPPERS; i++) { + SERIAL_ECHOPAIR(" M201 T", (int)i); + SERIAL_ECHOLNPAIR(" E", planner.max_acceleration_mm_per_s2[E_AXIS + i]); + } + #endif + CONFIG_ECHO_START; if (!forReplay) { SERIAL_ECHOLNPGM("Accelerations: P=printing, R=retract and T=travel"); diff --git a/Marlin/enum.h b/Marlin/enum.h index d7042e2a86..23b1fd0339 100644 --- a/Marlin/enum.h +++ b/Marlin/enum.h @@ -50,6 +50,7 @@ enum AxisEnum { #define LOOP_XYZ(VAR) for (uint8_t VAR=X_AXIS; VAR<=Z_AXIS; VAR++) #define LOOP_XYZE(VAR) for (uint8_t VAR=X_AXIS; VAR<=E_AXIS; VAR++) +#define LOOP_XYZE_N(VAR) for (uint8_t VAR=X_AXIS; VAR (int32_t)axis_steps_per_mm[E_AXIS] * (EXTRUDE_MAXLENGTH)) { // It's not important to get max. extrusion length in a precision < 1mm, so save some cycles and cast to int + if (labs(de) > (int32_t)axis_steps_per_mm[E_AXIS_N] * (EXTRUDE_MAXLENGTH)) { // It's not important to get max. extrusion length in a precision < 1mm, so save some cycles and cast to int position[E_AXIS] = target[E_AXIS]; // Behave as if the move really took place, but ignore E part de = 0; // no difference SERIAL_ECHO_START; @@ -941,7 +953,7 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const delta_mm[Y_AXIS] = db * steps_to_mm[Y_AXIS]; delta_mm[Z_AXIS] = dc * steps_to_mm[Z_AXIS]; #endif - delta_mm[E_AXIS] = esteps_float * steps_to_mm[E_AXIS]; + delta_mm[E_AXIS] = esteps_float * steps_to_mm[E_AXIS_N]; if (block->steps[X_AXIS] < MIN_STEPS_PER_SEGMENT && block->steps[Y_AXIS] < MIN_STEPS_PER_SEGMENT && block->steps[Z_AXIS] < MIN_STEPS_PER_SEGMENT) { block->millimeters = fabs(delta_mm[E_AXIS]); @@ -1091,16 +1103,16 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const accel = ceil(retract_acceleration * steps_per_mm); } else { - #define LIMIT_ACCEL_LONG(AXIS) do{ \ - if (block->steps[AXIS] && max_acceleration_steps_per_s2[AXIS] < accel) { \ - const uint32_t comp = max_acceleration_steps_per_s2[AXIS] * block->step_event_count; \ + #define LIMIT_ACCEL_LONG(AXIS,INDX) do{ \ + if (block->steps[AXIS] && max_acceleration_steps_per_s2[AXIS+INDX] < accel) { \ + const uint32_t comp = max_acceleration_steps_per_s2[AXIS+INDX] * block->step_event_count; \ if (accel * block->steps[AXIS] > comp) accel = comp / block->steps[AXIS]; \ } \ }while(0) - #define LIMIT_ACCEL_FLOAT(AXIS) do{ \ - if (block->steps[AXIS] && max_acceleration_steps_per_s2[AXIS] < accel) { \ - const float comp = (float)max_acceleration_steps_per_s2[AXIS] * (float)block->step_event_count; \ + #define LIMIT_ACCEL_FLOAT(AXIS,INDX) do{ \ + if (block->steps[AXIS] && max_acceleration_steps_per_s2[AXIS+INDX] < accel) { \ + const float comp = (float)max_acceleration_steps_per_s2[AXIS+INDX] * (float)block->step_event_count; \ if ((float)accel * (float)block->steps[AXIS] > comp) accel = comp / (float)block->steps[AXIS]; \ } \ }while(0) @@ -1109,16 +1121,17 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const accel = ceil((esteps ? acceleration : travel_acceleration) * steps_per_mm); // Limit acceleration per axis - if (block->step_event_count <= cutoff_long){ - LIMIT_ACCEL_LONG(X_AXIS); - LIMIT_ACCEL_LONG(Y_AXIS); - LIMIT_ACCEL_LONG(Z_AXIS); - LIMIT_ACCEL_LONG(E_AXIS); - } else { - LIMIT_ACCEL_FLOAT(X_AXIS); - LIMIT_ACCEL_FLOAT(Y_AXIS); - LIMIT_ACCEL_FLOAT(Z_AXIS); - LIMIT_ACCEL_FLOAT(E_AXIS); + if (block->step_event_count <= cutoff_long) { + LIMIT_ACCEL_LONG(X_AXIS,0); + LIMIT_ACCEL_LONG(Y_AXIS,0); + LIMIT_ACCEL_LONG(Z_AXIS,0); + LIMIT_ACCEL_LONG(E_AXIS,extruder); + } + else { + LIMIT_ACCEL_FLOAT(X_AXIS,0); + LIMIT_ACCEL_FLOAT(Y_AXIS,0); + LIMIT_ACCEL_FLOAT(Z_AXIS,0); + LIMIT_ACCEL_FLOAT(E_AXIS,extruder); } } block->acceleration_steps_per_s2 = accel; @@ -1302,7 +1315,7 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const } else { block->use_advance_lead = true; - block->abs_adv_steps_multiplier8 = lround(extruder_advance_k * (de_float / mm_D_float) * block->nominal_speed / (float)block->nominal_rate * axis_steps_per_mm[E_AXIS] * 256.0); + block->abs_adv_steps_multiplier8 = lround(extruder_advance_k * (de_float / mm_D_float) * block->nominal_speed / (float)block->nominal_rate * axis_steps_per_mm[E_AXIS_N] * 256.0); } #elif ENABLED(ADVANCE) @@ -1350,13 +1363,18 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const */ void Planner::_set_position_mm(const float &a, const float &b, const float &c, const float &e) { + #if ENABLED(DISTINCT_E_FACTORS) + #define _EINDEX (E_AXIS + active_extruder) + last_extruder = active_extruder; + #else + #define _EINDEX E_AXIS + #endif long na = position[X_AXIS] = lround(a * axis_steps_per_mm[X_AXIS]), nb = position[Y_AXIS] = lround(b * axis_steps_per_mm[Y_AXIS]), nc = position[Z_AXIS] = lround(c * axis_steps_per_mm[Z_AXIS]), - ne = position[E_AXIS] = lround(e * axis_steps_per_mm[E_AXIS]); + ne = position[E_AXIS] = lround(e * axis_steps_per_mm[_EINDEX]); stepper.set_position(na, nb, nc, ne); previous_nominal_speed = 0.0; // Resets planner junction speeds. Assumes start from rest. - ZERO(previous_speed); } @@ -1375,7 +1393,6 @@ void Planner::set_position_mm_kinematic(const float position[NUM_AXIS]) { #endif } - /** * Sync from the stepper positions. (e.g., after an interrupted move) */ @@ -1387,24 +1404,35 @@ void Planner::sync_from_steppers() { * Setters for planner position (also setting stepper position). */ void Planner::set_position_mm(const AxisEnum axis, const float& v) { - position[axis] = lround(v * axis_steps_per_mm[axis]); + #if ENABLED(DISTINCT_E_FACTORS) + const uint8_t axis_index = axis + (axis == E_AXIS ? active_extruder : 0); + last_extruder = active_extruder; + #else + const uint8_t axis_index = axis; + #endif + position[axis] = lround(v * axis_steps_per_mm[axis_index]); stepper.set_position(axis, v); previous_speed[axis] = 0.0; } // Recalculate the steps/s^2 acceleration rates, based on the mm/s^2 void Planner::reset_acceleration_rates() { + #if ENABLED(DISTINCT_E_FACTORS) + #define HIGHEST_CONDITION (i < E_AXIS || i == E_AXIS + active_extruder) + #else + #define HIGHEST_CONDITION true + #endif uint32_t highest_rate = 1; - LOOP_XYZE(i) { + LOOP_XYZE_N(i) { max_acceleration_steps_per_s2[i] = max_acceleration_mm_per_s2[i] * axis_steps_per_mm[i]; - NOLESS(highest_rate, max_acceleration_steps_per_s2[i]); + if (HIGHEST_CONDITION) NOLESS(highest_rate, max_acceleration_steps_per_s2[i]); } cutoff_long = 4294967295UL / highest_rate; } // Recalculate position, steps_to_mm if axis_steps_per_mm changes! void Planner::refresh_positioning() { - LOOP_XYZE(i) steps_to_mm[i] = 1.0 / axis_steps_per_mm[i]; + LOOP_XYZE_N(i) steps_to_mm[i] = 1.0 / axis_steps_per_mm[i]; set_position_mm_kinematic(current_position); reset_acceleration_rates(); } diff --git a/Marlin/planner.h b/Marlin/planner.h index 7be65297f0..9ba2e69f3a 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -140,22 +140,26 @@ class Planner { * A ring buffer of moves described in steps */ static block_t block_buffer[BLOCK_BUFFER_SIZE]; - static volatile uint8_t block_buffer_head; // Index of the next block to be pushed - static volatile uint8_t block_buffer_tail; + static volatile uint8_t block_buffer_head, // Index of the next block to be pushed + block_buffer_tail; - static float max_feedrate_mm_s[NUM_AXIS]; // Max speeds in mm per second - static float axis_steps_per_mm[NUM_AXIS]; - static float steps_to_mm[NUM_AXIS]; - static unsigned long max_acceleration_steps_per_s2[NUM_AXIS]; - static unsigned long max_acceleration_mm_per_s2[NUM_AXIS]; // Use M201 to override by software + #if ENABLED(DISTINCT_E_FACTORS) + static uint8_t last_extruder; // Respond to extruder change + #endif + + static float max_feedrate_mm_s[XYZE_N], // Max speeds in mm per second + axis_steps_per_mm[XYZE_N], + steps_to_mm[XYZE_N]; + static unsigned long max_acceleration_steps_per_s2[XYZE_N], + max_acceleration_mm_per_s2[XYZE_N]; // Use M201 to override by software static millis_t min_segment_time; - static float min_feedrate_mm_s; - static float acceleration; // Normal acceleration mm/s^2 DEFAULT ACCELERATION for all printing moves. M204 SXXXX - static float retract_acceleration; // Retract acceleration mm/s^2 filament pull-back and push-forward while standing still in the other axes M204 TXXXX - static float travel_acceleration; // Travel acceleration mm/s^2 DEFAULT ACCELERATION for all NON printing moves. M204 MXXXX - static float max_jerk[XYZE]; // The largest speed change requiring no acceleration - static float min_travel_feedrate_mm_s; + static float min_feedrate_mm_s, + acceleration, // Normal acceleration mm/s^2 DEFAULT ACCELERATION for all printing moves. M204 SXXXX + retract_acceleration, // Retract acceleration mm/s^2 filament pull-back and push-forward while standing still in the other axes M204 TXXXX + travel_acceleration, // Travel acceleration mm/s^2 DEFAULT ACCELERATION for all NON printing moves. M204 MXXXX + max_jerk[XYZE], // The largest speed change requiring no acceleration + min_travel_feedrate_mm_s; #if HAS_ABL static bool abl_enabled; // Flag that bed leveling is enabled @@ -343,7 +347,13 @@ class Planner { static void set_position_mm_kinematic(const float position[NUM_AXIS]); static void set_position_mm(const AxisEnum axis, const float &v); static FORCE_INLINE void set_z_position_mm(const float &z) { set_position_mm(Z_AXIS, z); } - static FORCE_INLINE void set_e_position_mm(const float &e) { set_position_mm(E_AXIS, e); } + static FORCE_INLINE void set_e_position_mm(const float &e) { + set_position_mm(E_AXIS + #if ENABLED(DISTINCT_E_FACTORS) + + active_extruder + #endif + , e); + } /** * Sync from the stepper positions. (e.g., after an interrupted move) diff --git a/Marlin/ultralcd.cpp b/Marlin/ultralcd.cpp index 73f78324e9..2aa5055b66 100755 --- a/Marlin/ultralcd.cpp +++ b/Marlin/ultralcd.cpp @@ -1850,7 +1850,35 @@ void kill_screen(const char* lcd_msg) { void lcd_control_temperature_preheat_material2_settings_menu() { _lcd_control_temperature_preheat_settings_menu(1); } void _reset_acceleration_rates() { planner.reset_acceleration_rates(); } + #if ENABLED(DISTINCT_E_FACTORS) + void _reset_e_acceleration_rate(const uint8_t e) { if (e == active_extruder) _reset_acceleration_rates(); } + void _reset_e0_acceleration_rate() { _reset_e_acceleration_rate(0); } + void _reset_e1_acceleration_rate() { _reset_e_acceleration_rate(1); } + #if E_STEPPERS > 2 + void _reset_e2_acceleration_rate() { _reset_e_acceleration_rate(2); } + #if E_STEPPERS > 3 + void _reset_e3_acceleration_rate() { _reset_e_acceleration_rate(3); } + #endif + #endif + #endif + void _planner_refresh_positioning() { planner.refresh_positioning(); } + #if ENABLED(DISTINCT_E_FACTORS) + void _planner_refresh_e_positioning(const uint8_t e) { + if (e == active_extruder) + _planner_refresh_positioning(); + else + planner.steps_to_mm[i] = 1.0 / planner.axis_steps_per_mm[i]; + } + void _planner_refresh_e0_positioning() { _reset_e_acceleration_rate(0); } + void _planner_refresh_e1_positioning() { _reset_e_acceleration_rate(1); } + #if E_STEPPERS > 2 + void _planner_refresh_e2_positioning() { _reset_e_acceleration_rate(2); } + #if E_STEPPERS > 3 + void _planner_refresh_e3_positioning() { _reset_e_acceleration_rate(3); } + #endif + #endif + #endif /** * @@ -1876,22 +1904,76 @@ void kill_screen(const char* lcd_msg) { MENU_ITEM_EDIT(float52, MSG_VZ_JERK, &planner.max_jerk[Z_AXIS], 0.1, 990); #endif MENU_ITEM_EDIT(float3, MSG_VE_JERK, &planner.max_jerk[E_AXIS], 1, 990); + + // + // M203 Settings + // MENU_ITEM_EDIT(float3, MSG_VMAX MSG_X, &planner.max_feedrate_mm_s[X_AXIS], 1, 999); MENU_ITEM_EDIT(float3, MSG_VMAX MSG_Y, &planner.max_feedrate_mm_s[Y_AXIS], 1, 999); MENU_ITEM_EDIT(float3, MSG_VMAX MSG_Z, &planner.max_feedrate_mm_s[Z_AXIS], 1, 999); - MENU_ITEM_EDIT(float3, MSG_VMAX MSG_E, &planner.max_feedrate_mm_s[E_AXIS], 1, 999); + + #if ENABLED(DISTINCT_E_FACTORS) + MENU_ITEM_EDIT(float3, MSG_VMAX MSG_E, &planner.max_feedrate_mm_s[E_AXIS + active_extruder], 1, 999); + MENU_ITEM_EDIT(float3, MSG_VMAX MSG_E1, &planner.max_feedrate_mm_s[E_AXIS], 1, 999); + MENU_ITEM_EDIT(float3, MSG_VMAX MSG_E2, &planner.max_feedrate_mm_s[E_AXIS + 1], 1, 999); + #if E_STEPPERS > 2 + MENU_ITEM_EDIT(float3, MSG_VMAX MSG_E3, &planner.max_feedrate_mm_s[E_AXIS + 2], 1, 999); + #if E_STEPPERS > 3 + MENU_ITEM_EDIT(float3, MSG_VMAX MSG_E3, &planner.max_feedrate_mm_s[E_AXIS + 3], 1, 999); + #endif + #endif + #else + MENU_ITEM_EDIT(float3, MSG_VMAX MSG_E, &planner.max_feedrate_mm_s[E_AXIS], 1, 999); + #endif + MENU_ITEM_EDIT(float3, MSG_VMIN, &planner.min_feedrate_mm_s, 0, 999); MENU_ITEM_EDIT(float3, MSG_VTRAV_MIN, &planner.min_travel_feedrate_mm_s, 0, 999); + + // + // M201 Settings + // MENU_ITEM_EDIT_CALLBACK(long5, MSG_AMAX MSG_X, &planner.max_acceleration_mm_per_s2[X_AXIS], 100, 99000, _reset_acceleration_rates); MENU_ITEM_EDIT_CALLBACK(long5, MSG_AMAX MSG_Y, &planner.max_acceleration_mm_per_s2[Y_AXIS], 100, 99000, _reset_acceleration_rates); MENU_ITEM_EDIT_CALLBACK(long5, MSG_AMAX MSG_Z, &planner.max_acceleration_mm_per_s2[Z_AXIS], 10, 99000, _reset_acceleration_rates); - MENU_ITEM_EDIT_CALLBACK(long5, MSG_AMAX MSG_E, &planner.max_acceleration_mm_per_s2[E_AXIS], 100, 99000, _reset_acceleration_rates); + + #if ENABLED(DISTINCT_E_FACTORS) + MENU_ITEM_EDIT_CALLBACK(long5, MSG_AMAX MSG_E, &planner.max_acceleration_mm_per_s2[E_AXIS + active_extruder], 100, 99000, _reset_acceleration_rates); + MENU_ITEM_EDIT_CALLBACK(long5, MSG_AMAX MSG_E1, &planner.max_acceleration_mm_per_s2[E_AXIS], 100, 99000, _reset_e0_acceleration_rate); + MENU_ITEM_EDIT_CALLBACK(long5, MSG_AMAX MSG_E2, &planner.max_acceleration_mm_per_s2[E_AXIS + 1], 100, 99000, _reset_e1_acceleration_rate); + #if E_STEPPERS > 2 + MENU_ITEM_EDIT_CALLBACK(long5, MSG_AMAX MSG_E3, &planner.max_acceleration_mm_per_s2[E_AXIS + 2], 100, 99000, _reset_e2_acceleration_rate); + #if E_STEPPERS > 3 + MENU_ITEM_EDIT_CALLBACK(long5, MSG_AMAX MSG_E4, &planner.max_acceleration_mm_per_s2[E_AXIS + 3], 100, 99000, _reset_e3_acceleration_rate); + #endif + #endif + #else + MENU_ITEM_EDIT_CALLBACK(long5, MSG_AMAX MSG_E, &planner.max_acceleration_mm_per_s2[E_AXIS], 100, 99000, _reset_acceleration_rates); + #endif + MENU_ITEM_EDIT(float5, MSG_A_RETRACT, &planner.retract_acceleration, 100, 99000); MENU_ITEM_EDIT(float5, MSG_A_TRAVEL, &planner.travel_acceleration, 100, 99000); + + // + // M92 Settings + // MENU_ITEM_EDIT_CALLBACK(float62, MSG_XSTEPS, &planner.axis_steps_per_mm[X_AXIS], 5, 9999, _planner_refresh_positioning); MENU_ITEM_EDIT_CALLBACK(float62, MSG_YSTEPS, &planner.axis_steps_per_mm[Y_AXIS], 5, 9999, _planner_refresh_positioning); MENU_ITEM_EDIT_CALLBACK(float62, MSG_ZSTEPS, &planner.axis_steps_per_mm[Z_AXIS], 5, 9999, _planner_refresh_positioning); - MENU_ITEM_EDIT_CALLBACK(float62, MSG_ESTEPS, &planner.axis_steps_per_mm[E_AXIS], 5, 9999, _planner_refresh_positioning); + + #if ENABLED(DISTINCT_E_FACTORS) + MENU_ITEM_EDIT_CALLBACK(float62, MSG_ESTEPS, &planner.axis_steps_per_mm[E_AXIS + active_extruder], 5, 9999, _planner_refresh_positioning); + MENU_ITEM_EDIT_CALLBACK(float62, MSG_ESTEPS MSG_E1, &planner.axis_steps_per_mm[E_AXIS], 5, 9999, _planner_refresh_e0_positioning); + MENU_ITEM_EDIT_CALLBACK(float62, MSG_ESTEPS MSG_E2, &planner.axis_steps_per_mm[E_AXIS + 1], 5, 9999, _planner_refresh_e1_positioning); + #if E_STEPPERS > 2 + MENU_ITEM_EDIT_CALLBACK(float62, MSG_ESTEPS MSG_E3, &planner.axis_steps_per_mm[E_AXIS + 2], 5, 9999, _planner_refresh_e2_positioning); + #if E_STEPPERS > 3 + MENU_ITEM_EDIT_CALLBACK(float62, MSG_ESTEPS MSG_E4, &planner.axis_steps_per_mm[E_AXIS + 3], 5, 9999, _planner_refresh_e3_positioning); + #endif + #endif + #else + MENU_ITEM_EDIT_CALLBACK(float62, MSG_ESTEPS, &planner.axis_steps_per_mm[E_AXIS], 5, 9999, _planner_refresh_positioning); + #endif + #if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED) MENU_ITEM_EDIT(bool, MSG_ENDSTOP_ABORT, &stepper.abort_on_endstop_hit); #endif