diff --git a/Marlin/src/gcode/config/M200-M205.cpp b/Marlin/src/gcode/config/M200-M205.cpp index 1537710d4e..bb55d0c44f 100644 --- a/Marlin/src/gcode/config/M200-M205.cpp +++ b/Marlin/src/gcode/config/M200-M205.cpp @@ -118,26 +118,33 @@ void GcodeSuite::M204() { /** * M205: Set Advanced Settings * + * B = Min Segment Time (µs) * S = Min Feed Rate (units/s) * T = Min Travel Feed Rate (units/s) - * B = Min Segment Time (µs) * X = Max X Jerk (units/sec^2) * Y = Max Y Jerk (units/sec^2) * Z = Max Z Jerk (units/sec^2) * E = Max E Jerk (units/sec^2) + * J = Junction Deviation (mm) (Requires JUNCTION_DEVIATION) */ void GcodeSuite::M205() { + if (parser.seen('B')) planner.min_segment_time_us = parser.value_ulong(); if (parser.seen('S')) planner.min_feedrate_mm_s = parser.value_linear_units(); if (parser.seen('T')) planner.min_travel_feedrate_mm_s = parser.value_linear_units(); - if (parser.seen('B')) planner.min_segment_time_us = parser.value_ulong(); - if (parser.seen('X')) planner.max_jerk[X_AXIS] = parser.value_linear_units(); - if (parser.seen('Y')) planner.max_jerk[Y_AXIS] = parser.value_linear_units(); - if (parser.seen('Z')) { - planner.max_jerk[Z_AXIS] = parser.value_linear_units(); - #if HAS_MESH - if (planner.max_jerk[Z_AXIS] <= 0.1) - SERIAL_ECHOLNPGM("WARNING! Low Z Jerk may lead to unwanted pauses."); - #endif - } - if (parser.seen('E')) planner.max_jerk[E_AXIS] = parser.value_linear_units(); + #if ENABLED(JUNCTION_DEVIATION) + if (parser.seen('J')) planner.junction_deviation_mm = parser.value_linear_units(); + #else + if (parser.seen('X')) planner.max_jerk[X_AXIS] = parser.value_linear_units(); + if (parser.seen('Y')) planner.max_jerk[Y_AXIS] = parser.value_linear_units(); + if (parser.seen('Z')) { + planner.max_jerk[Z_AXIS] = parser.value_linear_units(); + #if HAS_MESH + if (planner.max_jerk[Z_AXIS] <= 0.1) + SERIAL_ECHOLNPGM("WARNING! Low Z Jerk may lead to unwanted pauses."); + #endif + } + #endif + #if DISABLED(JUNCTION_DEVIATION) || ENABLED(LIN_ADVANCE) + if (parser.seen('E')) planner.max_jerk[E_AXIS] = parser.value_linear_units(); + #endif } diff --git a/Marlin/src/lcd/language/language_en.h b/Marlin/src/lcd/language/language_en.h index 92bb6f0fb9..1cf3567662 100644 --- a/Marlin/src/lcd/language/language_en.h +++ b/Marlin/src/lcd/language/language_en.h @@ -371,7 +371,7 @@ #ifndef MSG_LED_CONTROL #define MSG_LED_CONTROL _UxGT("LED Control") #endif -#ifndef MSG_LEDS +#ifndef MSG_LEDS #define MSG_LEDS _UxGT("Lights") #endif #ifndef MSG_LED_PRESETS @@ -537,6 +537,9 @@ #ifndef MSG_VE_JERK #define MSG_VE_JERK _UxGT("Ve-jerk") #endif +#ifndef MSG_JUNCTION_DEVIATION + #define MSG_JUNCTION_DEVIATION _UxGT("Junction Dev") +#endif #ifndef MSG_VELOCITY #define MSG_VELOCITY _UxGT("Velocity") #endif @@ -739,7 +742,7 @@ #define MSG_CNG_SDCARD _UxGT("Change SD card") #endif #ifndef MSG_ZPROBE_OUT - #define MSG_ZPROBE_OUT _UxGT("Z probe out. bed") + #define MSG_ZPROBE_OUT _UxGT("Z Probe past bed") #endif #ifndef MSG_SKEW_FACTOR #define MSG_SKEW_FACTOR _UxGT("Skew Factor") diff --git a/Marlin/src/lcd/ultralcd.cpp b/Marlin/src/lcd/ultralcd.cpp index 4b3f39c536..69920a9943 100644 --- a/Marlin/src/lcd/ultralcd.cpp +++ b/Marlin/src/lcd/ultralcd.cpp @@ -3753,12 +3753,16 @@ void lcd_quick_feedback(const bool clear_buttons) { START_MENU(); MENU_BACK(MSG_MOTION); - MENU_ITEM_EDIT(float3, MSG_VA_JERK, &planner.max_jerk[A_AXIS], 1, 990); - MENU_ITEM_EDIT(float3, MSG_VB_JERK, &planner.max_jerk[B_AXIS], 1, 990); - #if ENABLED(DELTA) - MENU_ITEM_EDIT(float3, MSG_VC_JERK, &planner.max_jerk[C_AXIS], 1, 990); + #if ENABLED(JUNCTION_DEVIATION) + MENU_ITEM_EDIT(float3, MSG_JUNCTION_DEVIATION, &planner.junction_deviation_mm, 0, 5); #else - MENU_ITEM_EDIT(float52sign, MSG_VC_JERK, &planner.max_jerk[C_AXIS], 0.1, 990); + MENU_ITEM_EDIT(float3, MSG_VA_JERK, &planner.max_jerk[A_AXIS], 1, 990); + MENU_ITEM_EDIT(float3, MSG_VB_JERK, &planner.max_jerk[B_AXIS], 1, 990); + #if ENABLED(DELTA) + MENU_ITEM_EDIT(float3, MSG_VC_JERK, &planner.max_jerk[C_AXIS], 1, 990); + #else + MENU_ITEM_EDIT(float52sign, MSG_VC_JERK, &planner.max_jerk[C_AXIS], 0.1, 990); + #endif #endif MENU_ITEM_EDIT(float3, MSG_VE_JERK, &planner.max_jerk[E_AXIS], 1, 990); diff --git a/Marlin/src/module/configuration_store.cpp b/Marlin/src/module/configuration_store.cpp index 8b06f76acb..3dbf3fa757 100644 --- a/Marlin/src/module/configuration_store.cpp +++ b/Marlin/src/module/configuration_store.cpp @@ -37,7 +37,7 @@ */ // Change EEPROM version if the structure changes -#define EEPROM_VERSION "V54" +#define EEPROM_VERSION "V55" #define EEPROM_OFFSET 100 // Check the integrity of data offsets. @@ -112,16 +112,17 @@ typedef struct SettingsDataStruct { // uint8_t esteppers; // XYZE_N - XYZ + uint32_t planner_max_acceleration_mm_per_s2[XYZE_N], // M201 XYZE planner.max_acceleration_mm_per_s2[XYZE_N] + planner_min_segment_time_us; // M205 B planner.min_segment_time_us float planner_axis_steps_per_mm[XYZE_N], // M92 XYZE planner.axis_steps_per_mm[XYZE_N] - planner_max_feedrate_mm_s[XYZE_N]; // M203 XYZE planner.max_feedrate_mm_s[XYZE_N] - uint32_t planner_max_acceleration_mm_per_s2[XYZE_N]; // M201 XYZE planner.max_acceleration_mm_per_s2[XYZE_N] - float planner_acceleration, // M204 P planner.acceleration + planner_max_feedrate_mm_s[XYZE_N], // M203 XYZE planner.max_feedrate_mm_s[XYZE_N] + planner_acceleration, // M204 P planner.acceleration planner_retract_acceleration, // M204 R planner.retract_acceleration planner_travel_acceleration, // M204 T planner.travel_acceleration planner_min_feedrate_mm_s, // M205 S planner.min_feedrate_mm_s - planner_min_travel_feedrate_mm_s; // M205 T planner.min_travel_feedrate_mm_s - uint32_t planner_min_segment_time_us; // M205 B planner.min_segment_time_us - float planner_max_jerk[XYZE]; // M205 XYZE planner.max_jerk[XYZE] + planner_min_travel_feedrate_mm_s, // M205 T planner.min_travel_feedrate_mm_s + planner_max_jerk[XYZE], // M205 XYZE planner.max_jerk[XYZE] + planner_junction_deviation_mm; // M205 J planner.junction_deviation_mm float home_offset[XYZ]; // M206 XYZ @@ -401,18 +402,24 @@ void MarlinSettings::postprocess() { const uint8_t esteppers = COUNT(planner.axis_steps_per_mm) - XYZ; EEPROM_WRITE(esteppers); + EEPROM_WRITE(planner.max_acceleration_mm_per_s2); + EEPROM_WRITE(planner.min_segment_time_us); EEPROM_WRITE(planner.axis_steps_per_mm); EEPROM_WRITE(planner.max_feedrate_mm_s); - EEPROM_WRITE(planner.max_acceleration_mm_per_s2); - EEPROM_WRITE(planner.acceleration); EEPROM_WRITE(planner.retract_acceleration); EEPROM_WRITE(planner.travel_acceleration); EEPROM_WRITE(planner.min_feedrate_mm_s); EEPROM_WRITE(planner.min_travel_feedrate_mm_s); - EEPROM_WRITE(planner.min_segment_time_us); EEPROM_WRITE(planner.max_jerk); + #if ENABLED(JUNCTION_DEVIATION) + EEPROM_WRITE(planner.junction_deviation_mm); + #else + dummy = 0.02; + EEPROM_WRITE(dummy); + #endif + _FIELD_TEST(home_offset); #if !HAS_HOME_OFFSET @@ -980,17 +987,20 @@ void MarlinSettings::postprocess() { // Get only the number of E stepper parameters previously stored // Any steppers added later are set to their defaults - const float def1[] = DEFAULT_AXIS_STEPS_PER_UNIT, def2[] = DEFAULT_MAX_FEEDRATE; - const uint32_t def3[] = DEFAULT_MAX_ACCELERATION; - float tmp1[XYZ + esteppers], tmp2[XYZ + esteppers]; - uint32_t tmp3[XYZ + esteppers]; - EEPROM_READ(tmp1); - EEPROM_READ(tmp2); - EEPROM_READ(tmp3); + const uint32_t def1[] = DEFAULT_MAX_ACCELERATION; + const float def2[] = DEFAULT_AXIS_STEPS_PER_UNIT, def3[] = DEFAULT_MAX_FEEDRATE; + + uint32_t tmp1[XYZ + esteppers]; + EEPROM_READ(tmp1); // max_acceleration_mm_per_s2 + EEPROM_READ(planner.min_segment_time_us); + + float tmp2[XYZ + esteppers], tmp3[XYZ + esteppers]; + EEPROM_READ(tmp2); // axis_steps_per_mm + EEPROM_READ(tmp3); // max_feedrate_mm_s if (!validating) LOOP_XYZE_N(i) { - planner.axis_steps_per_mm[i] = i < XYZ + esteppers ? tmp1[i] : def1[i < COUNT(def1) ? i : COUNT(def1) - 1]; - planner.max_feedrate_mm_s[i] = i < XYZ + esteppers ? tmp2[i] : def2[i < COUNT(def2) ? i : COUNT(def2) - 1]; - planner.max_acceleration_mm_per_s2[i] = i < XYZ + esteppers ? tmp3[i] : def3[i < COUNT(def3) ? i : COUNT(def3) - 1]; + planner.max_acceleration_mm_per_s2[i] = i < XYZ + esteppers ? tmp1[i] : def1[i < COUNT(def1) ? i : COUNT(def1) - 1]; + planner.axis_steps_per_mm[i] = i < XYZ + esteppers ? tmp2[i] : def2[i < COUNT(def2) ? i : COUNT(def2) - 1]; + planner.max_feedrate_mm_s[i] = i < XYZ + esteppers ? tmp3[i] : def3[i < COUNT(def3) ? i : COUNT(def3) - 1]; } EEPROM_READ(planner.acceleration); @@ -998,9 +1008,14 @@ void MarlinSettings::postprocess() { EEPROM_READ(planner.travel_acceleration); EEPROM_READ(planner.min_feedrate_mm_s); EEPROM_READ(planner.min_travel_feedrate_mm_s); - EEPROM_READ(planner.min_segment_time_us); EEPROM_READ(planner.max_jerk); + #if ENABLED(JUNCTION_DEVIATION) + EEPROM_READ(planner.junction_deviation_mm); + #else + EEPROM_READ(dummy); + #endif + // // Home Offset (M206) // @@ -1518,9 +1533,9 @@ void MarlinSettings::postprocess() { #if ENABLED(AUTO_BED_LEVELING_UBL) if (!validating) { - ubl.report_state(); + ubl.report_state(); - if (!ubl.sanity_check()) { + if (!ubl.sanity_check()) { SERIAL_EOL_P(port); #if ENABLED(EEPROM_CHITCHAT) ubl.echo_name(); @@ -1703,17 +1718,21 @@ void MarlinSettings::reset(PORTARG_SOLO) { planner.max_acceleration_mm_per_s2[i] = pgm_read_dword_near(&tmp3[i < COUNT(tmp3) ? i : COUNT(tmp3) - 1]); } + planner.min_segment_time_us = DEFAULT_MINSEGMENTTIME; planner.acceleration = DEFAULT_ACCELERATION; planner.retract_acceleration = DEFAULT_RETRACT_ACCELERATION; planner.travel_acceleration = DEFAULT_TRAVEL_ACCELERATION; planner.min_feedrate_mm_s = DEFAULT_MINIMUMFEEDRATE; planner.min_travel_feedrate_mm_s = DEFAULT_MINTRAVELFEEDRATE; - planner.min_segment_time_us = DEFAULT_MINSEGMENTTIME; planner.max_jerk[X_AXIS] = DEFAULT_XJERK; planner.max_jerk[Y_AXIS] = DEFAULT_YJERK; planner.max_jerk[Z_AXIS] = DEFAULT_ZJERK; planner.max_jerk[E_AXIS] = DEFAULT_EJERK; + #if ENABLED(JUNCTION_DEVIATION) + planner.junction_deviation_mm = JUNCTION_DEVIATION_MM; + #endif + #if HAS_HOME_OFFSET ZERO(home_offset); #endif @@ -2094,16 +2113,34 @@ void MarlinSettings::reset(PORTARG_SOLO) { if (!forReplay) { CONFIG_ECHO_START; - SERIAL_ECHOLNPGM_P(port, "Advanced: S T B X Z E"); + SERIAL_ECHOPGM_P(port, "Advanced: B S T"); + #if ENABLED(JUNCTION_DEVIATION) + SERIAL_ECHOPGM_P(port, " J"); + #else + SERIAL_ECHOPGM_P(port, " X Y Z"); + #endif + #if DISABLED(JUNCTION_DEVIATION) || ENABLED(LIN_ADVANCE) + SERIAL_ECHOPGM_P(port, " E"); + #endif + SERIAL_EOL_P(port); } CONFIG_ECHO_START; - SERIAL_ECHOPAIR_P(port, " M205 S", LINEAR_UNIT(planner.min_feedrate_mm_s)); + SERIAL_ECHOPAIR_P(port, " M205 B", LINEAR_UNIT(planner.min_segment_time_us)); + SERIAL_ECHOPAIR_P(port, " S", LINEAR_UNIT(planner.min_feedrate_mm_s)); SERIAL_ECHOPAIR_P(port, " T", LINEAR_UNIT(planner.min_travel_feedrate_mm_s)); - SERIAL_ECHOPAIR_P(port, " B", planner.min_segment_time_us); - SERIAL_ECHOPAIR_P(port, " X", LINEAR_UNIT(planner.max_jerk[X_AXIS])); - SERIAL_ECHOPAIR_P(port, " Y", LINEAR_UNIT(planner.max_jerk[Y_AXIS])); - SERIAL_ECHOPAIR_P(port, " Z", LINEAR_UNIT(planner.max_jerk[Z_AXIS])); - SERIAL_ECHOLNPAIR_P(port, " E", LINEAR_UNIT(planner.max_jerk[E_AXIS])); + + #if ENABLED(JUNCTION_DEVIATION) + SERIAL_ECHOPAIR_P(port, " J", LINEAR_UNIT(planner.junction_deviation_mm)); + #else + SERIAL_ECHOPAIR_P(port, " X", LINEAR_UNIT(planner.max_jerk[X_AXIS])); + SERIAL_ECHOPAIR_P(port, " Y", LINEAR_UNIT(planner.max_jerk[Y_AXIS])); + SERIAL_ECHOPAIR_P(port, " Z", LINEAR_UNIT(planner.max_jerk[Z_AXIS])); + #endif + #if DISABLED(JUNCTION_DEVIATION) || ENABLED(LIN_ADVANCE) + SERIAL_ECHOPAIR_P(port, " E", LINEAR_UNIT(planner.max_jerk[E_AXIS])); + #endif + + SERIAL_EOL_P(port); #if HAS_M206_COMMAND if (!forReplay) { diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp index d1e423c3d0..87a3d1a2ae 100644 --- a/Marlin/src/module/planner.cpp +++ b/Marlin/src/module/planner.cpp @@ -110,9 +110,23 @@ uint16_t Planner::cleaning_buffer_counter; // A counter to disable queuing of uint8_t Planner::delay_before_delivering, // This counter delays delivery of blocks when queue becomes empty to allow the opportunity of merging blocks Planner::block_buffer_planned; // Index of the optimally planned block -float Planner::max_feedrate_mm_s[XYZE_N], // Max speeds in mm per second - Planner::axis_steps_per_mm[XYZE_N], - Planner::steps_to_mm[XYZE_N]; +uint32_t Planner::max_acceleration_mm_per_s2[XYZE_N], // (mm/s^2) M201 XYZE + Planner::max_acceleration_steps_per_s2[XYZE_N], // (steps/s^2) Derived from mm_per_s2 + Planner::min_segment_time_us; // (µs) M205 B + +float Planner::max_feedrate_mm_s[XYZE_N], // (mm/s) M203 XYZE - Max speeds + Planner::axis_steps_per_mm[XYZE_N], // (steps) M92 XYZE - Steps per millimeter + Planner::steps_to_mm[XYZE_N], // (mm) Millimeters per step + Planner::min_feedrate_mm_s, // (mm/s) M205 S - Minimum linear feedrate + Planner::acceleration, // (mm/s^2) M204 S - Normal acceleration. DEFAULT ACCELERATION for all printing moves. + Planner::retract_acceleration, // (mm/s^2) M204 R - Retract acceleration. Filament pull-back and push-forward while standing still in the other axes + Planner::travel_acceleration, // (mm/s^2) M204 T - Travel acceleration. DEFAULT ACCELERATION for all NON printing moves. + Planner::max_jerk[XYZE], // (mm/s^2) M205 XYZE - The largest speed change requiring no acceleration. + Planner::min_travel_feedrate_mm_s; // (mm/s) M205 T - Minimum travel feedrate + +#if ENABLED(JUNCTION_DEVIATION) + float Planner::junction_deviation_mm; // (mm) M205 J +#endif #if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED) bool Planner::abort_on_endstop_hit = false; @@ -132,19 +146,6 @@ float Planner::e_factor[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(1.0); // The flow perce Planner::volumetric_multiplier[EXTRUDERS]; // Reciprocal of cross-sectional area of filament (in mm^2). Pre-calculated to reduce computation in the planner #endif -uint32_t Planner::max_acceleration_steps_per_s2[XYZE_N], - Planner::max_acceleration_mm_per_s2[XYZE_N]; // Use M201 to override by software - -uint32_t Planner::min_segment_time_us; - -// Initialized by settings.load() -float Planner::min_feedrate_mm_s, - Planner::acceleration, // Normal acceleration mm/s^2 DEFAULT ACCELERATION for all printing moves. M204 SXXXX - Planner::retract_acceleration, // Retract acceleration mm/s^2 filament pull-back and push-forward while standing still in the other axes M204 TXXXX - Planner::travel_acceleration, // Travel acceleration mm/s^2 DEFAULT ACCELERATION for all NON printing moves. M204 MXXXX - Planner::max_jerk[XYZE], // The largest speed change requiring no acceleration - Planner::min_travel_feedrate_mm_s; - #if HAS_LEVELING bool Planner::leveling_active = false; // Flag that auto bed leveling is enabled #if ABL_PLANAR @@ -2187,7 +2188,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move, const float junction_acceleration = limit_value_by_axis_maximum(block->acceleration, junction_unit_vec), sin_theta_d2 = SQRT(0.5 * (1.0 - junction_cos_theta)); // Trig half angle identity. Always positive. - vmax_junction_sqr = (junction_acceleration * JUNCTION_DEVIATION_MM * sin_theta_d2) / (1.0 - sin_theta_d2); + vmax_junction_sqr = (junction_acceleration * junction_deviation_mm * sin_theta_d2) / (1.0 - sin_theta_d2); if (block->millimeters < 1.0) { // Fast acos approximation, minus the error bar to be safe diff --git a/Marlin/src/module/planner.h b/Marlin/src/module/planner.h index 94dda12ff9..2d880c8bd9 100644 --- a/Marlin/src/module/planner.h +++ b/Marlin/src/module/planner.h @@ -116,10 +116,10 @@ typedef struct { decelerate_after; // The index of the step event on which to start decelerating #if ENABLED(S_CURVE_ACCELERATION) - uint32_t cruise_rate; // The actual cruise rate to use, between end of the acceleration phase and start of deceleration phase - uint32_t acceleration_time, // Acceleration time and deceleration time in STEP timer counts - deceleration_time; - uint32_t acceleration_time_inverse, // Inverse of acceleration and deceleration periods, expressed as integer. Scale depends on CPU being used + uint32_t cruise_rate, // The actual cruise rate to use, between end of the acceleration phase and start of deceleration phase + acceleration_time, // Acceleration time and deceleration time in STEP timer counts + deceleration_time, + acceleration_time_inverse, // Inverse of acceleration and deceleration periods, expressed as integer. Scale depends on CPU being used deceleration_time_inverse; #else uint32_t acceleration_rate; // The acceleration rate used for acceleration calculation @@ -195,20 +195,23 @@ class Planner { // May be auto-adjusted by a filament width sensor #endif + static uint32_t max_acceleration_steps_per_s2[XYZE_N], + max_acceleration_mm_per_s2[XYZE_N], // Use M201 to override + min_segment_time_us; // Use 'M205 B<µs>' to override 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 uint32_t max_acceleration_steps_per_s2[XYZE_N], - max_acceleration_mm_per_s2[XYZE_N]; // Use M201 to override - - static uint32_t min_segment_time_us; // Use 'M205 B<µs>' to override - static float min_feedrate_mm_s, + steps_to_mm[XYZE_N], + 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 ENABLED(JUNCTION_DEVIATION) + static float junction_deviation_mm; // Initialized by EEPROM + #endif + #if HAS_LEVELING static bool leveling_active; // Flag that bed leveling is enabled #if ABL_PLANAR