This is somewhat related to: Error in syncemitter 'extruder' step generation - #11 by igiannakas
And: Happy-Hare/extras/mmu/unit/mmu_calibrator.py at v4-IG-Dev · moggieuk/Happy-Hare · GitHub
Generally, it seems that there is a tendency to synchronize 2 motors by adjustment of the RD at either side. For example, with a filament buffer, by adjusting either the extruder or the secondary synchronized motor.
Or with some “mixing” extruders: Stepcompress check fails if rotation distance is changed at runtime
It doesn’t seem that there is a need to actually queue the adjustment, but to just apply it.
And for an unknown reason, it is cumbersome to flush the queue every time it happens.
So, my general idea was to adjust the step size live with some smoothing function within itersolve_gen_steps_range().
But it seems to be fairly complicated for what it should do.
Per step update
There should be a target print time to do so reliably, and I don’t like any additional code within or near the “hot” path.
Also, probably there are other places where it can be updated safely (if there are no movements, and the motor is stationary?).
diff --git a/klippy/chelper/itersolve.c b/klippy/chelper/itersolve.c
index 444d4e4c8..6daf48006 100644
--- a/klippy/chelper/itersolve.c
+++ b/klippy/chelper/itersolve.c
@@ -87,6 +87,8 @@ itersolve_gen_steps_range(struct stepper_kinematics *sk, struct stepcompress *sc
} else if (rel_dist < -(half_step + half_step + .000000010)) {
// Found direction change
sdir = !sdir;
+ sk->step_dist = sk->next_step_dist;
+ half_step = .5 * sk->step_dist;
target = (sdir ? target + half_step + half_step
: target - half_step - half_step);
low_time = last_time;
@@ -108,6 +110,15 @@ itersolve_gen_steps_range(struct stepper_kinematics *sk, struct stepcompress *sc
int ret = stepcompress_append(sc, sdir, m->print_time, guess.time);
if (ret)
return ret;
+ if (sk->step_dist != sk->next_step_dist) {
+ double tdiff = guess.time - last_time;
+ // Smooth over one second
+ double coef = tdiff / 1.0;
+ double diff = sk->next_step_dist - sk->step_dist;
+ sk->step_dist += diff * coef;
+ sk->step_dist = nexttoward(sk->step_dist,sk->next_step_dist);
+ half_step = .5 * sk->step_dist;
+ }
target = sdir ? target+half_step+half_step : target-half_step-half_step;
// Reset bounds checking
double seek_time_delta = 1.5 * (guess.time - last_time);
The next/current idea is to basically smoothly transition the value within the itersolve_generate_steps() for each itersolve_gen_steps_range() until it reaches the target: GitHub - nefelim4ag/klipper at flushless-step-distance · GitHub
It is possible to do so with some time smoothing, for example, smooth over 1s, for every flush, it would be about 5% diff adjustment.
But, in such a case, it seems that it should be enough to get a similar behaviour:
diff --git a/klippy/chelper/itersolve.c b/klippy/chelper/itersolve.c
index 5b1683606..b1743372f 100644
--- a/klippy/chelper/itersolve.c
+++ b/klippy/chelper/itersolve.c
@@ -182,6 +182,16 @@ itersolve_generate_steps(struct stepper_kinematics *sk, struct stepcompress *sc
, flush_time);
if (ret)
return ret;
+ // Smoothly transition step size
+ if (sk->next_step_dist > sk->step_dist) {
+ sk->step_dist += sk->step_dist * 0.05;
+ if (sk->step_dist > sk->next_step_dist)
+ sk->step_dist = sk->next_step_dist;
+ } else if (sk->next_step_dist < sk->step_dist) {
+ sk->step_dist -= sk->step_dist * 0.05;
+ if (sk->step_dist < sk->next_step_dist)
+ sk->step_dist = sk->next_step_dist;
+ }
if (move_end >= flush_time) {
sk->last_move_time = flush_time;
return 0;
@@ -245,6 +255,13 @@ itersolve_set_trapq(struct stepper_kinematics *sk, struct trapq *tq
{
sk->tq = tq;
sk->step_dist = step_dist;
+ sk->next_step_dist = step_dist;
+}
+
+void __visible
+itersolve_update_step_dist(struct stepper_kinematics *sk, double step_dist)
+{
+ sk->next_step_dist = step_dist;
}
struct trapq * __visible
Not sure how sane/useful it is practically to do this that way.
It seems to work okayish in my small local tests.
G0 E=-1 F=300
SET_EXTRUDER_ROTATION_DISTANCE EXTRUDER=extruder DISTANCE=33
G0 E=-1 F=300
SET_EXTRUDER_ROTATION_DISTANCE EXTRUDER=extruder DISTANCE=35
G0 E=-1 F=300
SET_EXTRUDER_ROTATION_DISTANCE EXTRUDER=extruder DISTANCE=37
G0 E=-1 F=300
SET_EXTRUDER_ROTATION_DISTANCE EXTRUDER=extruder DISTANCE=5
G0 E=-1 F=300
SET_EXTRUDER_ROTATION_DISTANCE EXTRUDER=extruder DISTANCE=33
G0 E=-1 F=300
SET_EXTRUDER_ROTATION_DISTANCE EXTRUDER=extruder DISTANCE=35
G0 E=-1 F=300
SET_EXTRUDER_ROTATION_DISTANCE EXTRUDER=extruder DISTANCE=37
G0 E=-1 F=300
SET_EXTRUDER_ROTATION_DISTANCE EXTRUDER=extruder DISTANCE=5
G0 E=-1 F=300
So, it is here.
Thanks,
-Timofey