Skip to content

Commit 3029a6b

Browse files
mh-dmthinkyhead
andauthored
🩹 Jerk correction for LIN_ADVANCE + CLASSIC_JERK (MarlinFirmware#26551)
Co-authored-by: Scott Lahteine <[email protected]>
1 parent 342048b commit 3029a6b

File tree

1 file changed

+49
-32
lines changed

1 file changed

+49
-32
lines changed

Marlin/src/module/planner.cpp

Lines changed: 49 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2490,9 +2490,9 @@ bool Planner::_populate_block(
24902490
*
24912491
* extruder_advance_K[extruder] : There is an advance factor set for this extruder.
24922492
*
2493-
* dist.e > 0 : Extruder is running forward (e.g., for "Wipe while retracting" (Slic3r) or "Combing" (Cura) moves)
2493+
* dm.e : Extruder is running forward (e.g., for "Wipe while retracting" (Slic3r) or "Combing" (Cura) moves)
24942494
*/
2495-
use_advance_lead = esteps && extruder_advance_K[E_INDEX_N(extruder)] && dist.e > 0;
2495+
use_advance_lead = esteps && extruder_advance_K[E_INDEX_N(extruder)] && dm.e;
24962496

24972497
if (use_advance_lead) {
24982498
float e_D_ratio = (target_float.e - position_float.e) /
@@ -2770,53 +2770,70 @@ bool Planner::_populate_block(
27702770
* Heavily modified. Originally adapted from Průša firmware.
27712771
* https://github.com/prusa3d/Prusa-Firmware
27722772
*/
2773-
#ifndef TRAVEL_EXTRA_XYJERK
2774-
#define TRAVEL_EXTRA_XYJERK 0.0f
2773+
#if defined(TRAVEL_EXTRA_XYJERK) || ENABLED(LIN_ADVANCE)
2774+
xyze_float_t max_j = max_jerk;
2775+
#else
2776+
const xyze_float_t &max_j = max_jerk;
27752777
#endif
2776-
const float extra_xyjerk = TERN0(HAS_EXTRUDERS, dist.e <= 0) ? TRAVEL_EXTRA_XYJERK : 0.0f;
27772778

2778-
if (!moves_queued || UNEAR_ZERO(previous_nominal_speed)) {
2779-
// Compute "safe" speed, limited by a jerk to/from full halt.
2779+
#ifdef TRAVEL_EXTRA_XYJERK
2780+
if (dist.e <= 0) {
2781+
max_j.x += TRAVEL_EXTRA_XYJERK;
2782+
max_j.y += TRAVEL_EXTRA_XYJERK;
2783+
}
2784+
#endif
27802785

2781-
float v_factor = 1.0f;
2782-
LOOP_LOGICAL_AXES(i) {
2783-
const float jerk = ABS(current_speed[i]), // Starting from zero, change in speed for this axis
2784-
maxj = max_jerk[i] + (i == X_AXIS || i == Y_AXIS ? extra_xyjerk : 0.0f); // The max jerk setting for this axis
2785-
if (jerk * v_factor > maxj) v_factor = maxj / jerk;
2786+
#if ENABLED(LIN_ADVANCE)
2787+
// Advance affects E_AXIS speed and therefore jerk. Add a speed correction whenever
2788+
// LA is turned OFF. No correction is applied when LA is turned ON (because it didn't
2789+
// perform well; it takes more time/effort to push/melt filament than the reverse).
2790+
static uint32_t previous_advance_rate;
2791+
static float previous_e_mm_per_step;
2792+
if (dist.e < 0 && previous_advance_rate) {
2793+
// Retract move after a segment with LA that ended with an E speed decrease.
2794+
// Correct for this to allow a faster junction speed. Since the decrease always helps to
2795+
// get E to nominal retract speed, the equation simplifies to an increase in max jerk.
2796+
max_j.e += previous_advance_rate * previous_e_mm_per_step;
27862797
}
2787-
vmax_junction_sqr = sq(block->nominal_speed * v_factor);
2788-
NOLESS(minimum_planner_speed_sqr, vmax_junction_sqr);
2798+
// Prepare for next segment.
2799+
previous_advance_rate = block->la_advance_rate;
2800+
previous_e_mm_per_step = mm_per_step[E_AXIS_N(extruder)];
2801+
#endif
2802+
2803+
xyze_float_t speed_diff = current_speed;
2804+
float vmax_junction;
2805+
const bool start_from_zero = !moves_queued || UNEAR_ZERO(previous_nominal_speed);
2806+
if (start_from_zero) {
2807+
// Limited by a jerk to/from full halt.
2808+
vmax_junction = block->nominal_speed;
27892809
}
27902810
else {
27912811
// Compute the maximum velocity allowed at a joint of two successive segments.
27922812

27932813
// The junction velocity will be shared between successive segments. Limit the junction velocity to their minimum.
2794-
float vmax_junction, previous_speed_factor, current_speed_factor;
2814+
// Scale per-axis velocities for the same vmax_junction.
27952815
if (block->nominal_speed < previous_nominal_speed) {
27962816
vmax_junction = block->nominal_speed;
2797-
previous_speed_factor = vmax_junction / previous_nominal_speed;
2798-
current_speed_factor = 1.0f;
2817+
const float previous_scale = vmax_junction / previous_nominal_speed;
2818+
LOOP_LOGICAL_AXES(i) speed_diff[i] -= previous_speed[i] * previous_scale;
27992819
}
28002820
else {
28012821
vmax_junction = previous_nominal_speed;
2802-
previous_speed_factor = 1.0f;
2803-
current_speed_factor = vmax_junction / block->nominal_speed;
2822+
const float current_scale = vmax_junction / block->nominal_speed;
2823+
LOOP_LOGICAL_AXES(i) speed_diff[i] = speed_diff[i] * current_scale - previous_speed[i];
28042824
}
2825+
}
28052826

2806-
// Now limit the jerk in all axes.
2807-
float v_factor = 1.0f;
2808-
LOOP_LOGICAL_AXES(i) {
2809-
// Scale per-axis velocities for the same vmax_junction.
2810-
const float v_exit = previous_speed[i] * previous_speed_factor,
2811-
v_entry = current_speed[i] * current_speed_factor;
2812-
2813-
// Jerk is the per-axis velocity difference.
2814-
const float jerk = ABS(v_exit - v_entry),
2815-
maxj = max_jerk[i] + (i == X_AXIS || i == Y_AXIS ? extra_xyjerk : 0.0f);
2816-
if (jerk * v_factor > maxj) v_factor = maxj / jerk;
2817-
}
2818-
vmax_junction_sqr = sq(vmax_junction * v_factor);
2827+
// Now limit the jerk in all axes.
2828+
float v_factor = 1.0f;
2829+
LOOP_LOGICAL_AXES(i) {
2830+
// Jerk is the per-axis velocity difference.
2831+
const float jerk = ABS(speed_diff[i]), maxj = max_j[i];
2832+
if (jerk * v_factor > maxj) v_factor = maxj / jerk;
28192833
}
2834+
vmax_junction_sqr = sq(vmax_junction * v_factor);
2835+
2836+
if (start_from_zero) minimum_planner_speed_sqr = vmax_junction_sqr;
28202837

28212838
#endif // CLASSIC_JERK
28222839

0 commit comments

Comments
 (0)