-
-
Notifications
You must be signed in to change notification settings - Fork 19.6k
FT_MOTION nonlinear extrusion support #28250
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: bugfix-2.1.x
Are you sure you want to change the base?
Conversation
|
@dbuezas hi, I tried your suggestion if (use_advance_lead) {
// Don't apply LA or NLE to retract/unretract blocks
const float e_rate = (traj_e - prev_traj_e) * (FTM_FS);
#if ENABLED(NONLINEAR_EXTRUSION)
const float v = abs(e_rate); // extruder velocity in mm/s
const float multiplier = max(C, stepper.ne.settings.coeff.A * sq(v) + stepper.ne.settings.coeff.B * v + stepper.ne.settings.coeff.C);
traj_coords.e += e_rate * advK * multiplier;
#else
traj_coords.e += e_rate * advK;
#endif
}but without effect. So I simplified code until const float traj_e = traj_coords.e;
const float e_rate = (traj_e - prev_traj_e) * (FTM_FS);
traj_coords.e += e_rate * 1.5;
prev_traj_e = traj_e;and printed this code: G92 X0
G1 X100 E100 F600Extrusion was 100mm, as if |
|
Oh, I see the issue, we need it to accumulate. My original suggestion adds a constant term to position, but it doesn't accumulate, so it behaves like some weird non linear advance. You could calculate the NLE term separately accumulate it in both startPos.E and endPos_prevBlock.E |
|
Here? const float totalLength = current_block->millimeters;
startPos = endPos_prevBlock;
const xyze_pos_t& moveDist = current_block->dist_mm;
ratio = moveDist / totalLength;
// Plan the trajectory using the trajectory generator
currentGenerator->plan(current_block->entry_speed, current_block->exit_speed, current_block->acceleration, current_block->nominal_speed, totalLength);
endPos_prevBlock += moveDist;
Multiply |
|
I mean to basically put nle_term = ....
traj_coord.e += nle_term
startPos.e += nle_term
endPos_prevBlock.e += nle_termIn the original place i suggested (there with linear advance) Just make sure to calculate the nle term as a term, not a factor |
As far as I understand current algorithm factor we apply to the E speed, while term to the distance, right? If speed is |
|
Yes, but not dist, it is speed. So use the original equation with the multiplier, and the term would be: You can optimize the arithmetic but that would be the idea, yes. |
Should |
|
What i mean is not to change the formula, but just to "extract" how much it offsets position so it can be accumulated. The point of accumulating it is so that the extra extrusion is not undone down the line. I'm wondering now that the non linearity of extrusion is afaik because the "back pressure" makes the filament compress while the teeth push it (the teeth dents get closer). |
You may be right, I'd need to sit with a piece of paper (tomorrow) |
Not really. It's caused by teeth slippage, and depends on speed, but not speed change. It could be 5-10% or more at the high end. So if planned speed is 10mm/sec, we should command, for instance, 11 mm/sec. |
|
I remember someone measuring the teeth mark distances and them being closer when extruding strongly. |
I'm not saying it depends on speed change, back pressure doesn't either. In fact if you look at how I implemented LA in ftmotion, it multiplies k by rate, not acceleration. The standard motion implementation does rate += accel*k. But that's not pressure, that's it's derivative. Both implementations are mathematically equivalent, but ftmotion's doesn't lose track of the integration constant during discontinuities at the beginning of blocks (jerk) |
Even for long constant speed movements? Actually that's exactly what NLE is supposed to do, not LA. Or do I miss something? |
|
It's just the derivative: If you integrate both sides you get My point is that pressure is If the non linearity comes from pressure (teeth grabbing closer or slippage, or whatever), then we could use that known pressure to compute it: Anyway it would be a different model than normal nle |
You mean planned_extruder_vel(t)? |
|
Corrected |
|
Ok, took a look, you were right, NLE should be calculated from the rate, but applied to the extruder delta. And applied independently of LA. I think this should work: if (use_advance_lead) {
// Don't apply LA or NLE to retract/unretract blocks
const float e_rate = (traj_e - prev_traj_e) * (FTM_FS);
traj_coords.e += e_rate * advK;
#if ENABLED(NONLINEAR_EXTRUSION)
const float v = abs(e_rate); // extruder velocity in mm/s
const float multiplier = max(C, stepper.ne.settings.coeff.A * sq(v) + stepper.ne.settings.coeff.B * v + stepper.ne.settings.coeff.C);
const float nle_term = (traj_e - prev_traj_e) * (multiplier - 1);
traj_coord.e += nle_term;
startPos.e += nle_term;
endPos_prevBlock.e += nle_term;
#endif
} |
The different instantaneous pressure based model would be like this:if (use_advance_lead) {
// Don't apply LA or NLE to retract/unretract blocks
const float e_rate = (traj_e - prev_traj_e) * (FTM_FS);
const float pressure = e_rate * advK;
traj_coords.e += pressure;
#if ENABLED(PRESSURE_DEPENDENT_EXTRUSION)
const float multiplier = pressure * stepper.pressure_dependent_extrussion.settings.constant;
const float nle_term = (traj_e - prev_traj_e) * (multiplier - 1);
traj_coord.e += nle_term;
startPos.e += nle_term;
endPos_prevBlock.e += nle_term;
#endif
} |
|
I've tested (with extra ABS and hardcoded multiplier to be on the safe side) #if ENABLED(NONLINEAR_EXTRUSION)
const float v = abs(e_rate); // extruder velocity in mm/s
const float multiplier = 1.5;
const float nle_term = abs(traj_e - prev_traj_e) * (multiplier - 1);
traj_coord.e += nle_term;
startPos.e += nle_term;
endPos_prevBlock.e += nle_term;
#endifand this G92 X0
G1 X100 E100 F600coded resulted in 200mm extrusion instead of 150. For whatever reason |
|
The abs in the delta shouldn't be necessary (arguably wrong if nle were to ever see retractions) |
|
Still 200mm. const float v = abs(e_rate); // extruder velocity in mm/s
const float multiplier = 1.5;//max(stepper.ne.settings.coeff.C, stepper.ne.settings.coeff.A * sq(v) + stepper.ne.settings.coeff.B * v + stepper.ne.settings.coeff.C);
const float nle_term = abs(traj_e - prev_traj_e) * (multiplier - 1);
traj_coords.e += nle_term;
prev_traj_e = traj_e + nle_term;
startPos.e += nle_term;
endPos_prevBlock.e += nle_term;
Well, I'm not familiar with FTM algorithm and code. |
|
I've put multiplier = 1.25, and got 135mm extrusion. Does it point to something? By a way, this code is not ISR, isn't it? So can we use DEBUG? |
|
The code doesn't work in the isr, but it runs at 1khz (on average) so if you put a serial print, make sure to not call it on every iteration. |
|
I added but got only one output: Does printing block SERIAL_ECHOLNPGM? Anyway, could we learn something? Is it correct that startPos.e is 0, while endPos_prevBlock.e is 100? |
|
i can take a look at the code if you commit it |
5492e27 to
f0f3004
Compare
f0f3004 to
dc59a81
Compare
|
Committed with your remarks.
could it explain extrusion of 200 instead of 150? K is 0.02, assume it's 0.04. Still it has very little effect on 100mm constant speed extrusion. |
dc59a81 to
c6494e9
Compare
|
It seems to work now, thanks for help @dbuezas! I combined checks for Advance K and NLE to remove duplicates. If it looks good for you I'll mark PR as ready for review. |
|
By a way, abs(...) not needed, extruder always advance. I've got logs issuing command from terminal instead of printing. |
|
Also currently |
Non-linear extrusion adds a call to |
Ok, but could we use it on 8bit for FTM? |
Worth a code comment there, something like "use_advance_lead guarantees delta is positive" should suffice |
Following to #27935 (comment)
FT_MOTIONNONLINEAR_EXTRUSIONimplementation.