Preload: A Modest Proposal

Beefeater
Posts: 34
Joined: 17 Jul 2017, 22:54

Preload: A Modest Proposal

Post by Beefeater »

After investigating Preload over the last few weeks, I believe performance could be improved quite dramatically by changing the way extrusion ramps and feed ramps are constructed. This will be a really REALLY long post, so I’ll begin with TL;DR:

* The Wizard will give a better measurement if it measures ooze over the first few seconds instead of 2 minutes.

* The main idea of Prelaod is to gradually slow down extrusion and simultaneously slow down head travel, a.k.a. feed. If the extrusion ramp and the feed ramp are synchronized, one can achieve, at least in principle, correct extrusion width all the way to the end of the path and no ooze. But in Kisslicer, the ramps are not synchronized. I do not know why. See Fig. 2 attached.

* Even with synchronization corrected, the (parabolic?) ramp functions implemented in Kisslicer are not the best ones to use because they are sensitive to mis-estimation of viscoelasticity. I found other ramp functions that are less sensitive. The best performer, believe it or not, is a simple constant.

* Probably no Preload strategy will work well on all printers. It may be a good idea to put a checkbox in Printer profile, “Use Preload For This Printer”. Same idea as setting DRVLEN=0, but stronger emotional punch.

Now on to the details.


PART 1: WIZARD

It has been a long-standing theory of mine that ooze consists of two components: Elastic ooze from compression of filament in the Bowden tube, and thermal ooze due to more filament heating up and expanding after extrusion stops. The elastic ooze decays exponentially with time constant tau=32*(D^2)*L*l/(d^4)*VE, where D is filament diameter, L is Bowden tube length, d is nozzle diameter, l is nozzle length, and VE is viscoelasticity. The thermal ooze is (I expect) also exponential, but with a longer time constant determined by relevant thermal conductivities and heat capacities.

To test this theory, I made a test pattern where I stop extrusion mid-path and then slow down the feed according to how I expect the ooze to behave. If this guess about ooze behavior is correct, the bead width should remain constant after extrusion stop. I tried this with ABS on a 0.4mm and 0.25mm nozzles and results are consistent with the exponential law is in both cases. See Fig. 1. I can even estimate viscoelasticity in this way, with about +/-30% confidence, and it comes out to be between 0.5us and 0.8us; the datasheet value for ABS is 0.65us. (This is a way better agreement than I deserve, given the uncertainty in D and l.) There is also a trace of thermal ooze, which starts out some 10-30 times smaller than elastic ooze but continues for tens of seconds. I did not try to match head travel to thermal ooze, so I can’t be more quantitative than that.

Now, the parameters of my rig are D=2.85mm, L=150mm, d=0.4mm, l=0.6mm. This gives tau~0.6s for ABS. Many printers have longer drives, but also use 1.75mm filament, so will end up with a similar tau. I do not know what thermal ooze is like on other printers, or even if there is any. But as a general matter, a measurement of an exponential process with time constant tau is most accurate when made over a time on the order of a few tau. A longer measurement may be contaminated by a concurrent slower process. So the Wizard should measure just the first few seconds of ooze, if possible. In practice, stop extrusion, and at the same time drive the printhead past a wiper; wait 3 seconds, retract, and measure ooze. If there is no wiper, you can improvise one by holding up a business card and driving the printhead past that. If your machine has lots of thermal ooze, you’ll get a better VE measurement this way. If the machine has no thermal ooze, it may not be worth the bother.

There is good news here also. Jumps in actual prints take a fraction of a second. Thermal ooze is insignificant over this short time. We thus have experimental evidence, for my hardware at least, that elastic ooze dominates and is exponential as anticipated. So Preload is a worthwhile endeavor.


PART II: RAMPS

Kisslicer Preload algorithm is configured with two parameters: Viscoelasticity VE, which yields the drivetrain time constant tau = 32*(D^2)*L*l/(d^4)*VE, and an extrusion speed VP. In the following, I use “extrusion speed” and “extrusion flow” interchangeably: The speed is converted to the flow by multiplying by filament cross-section pi*(D^2)/4. I denote by G(t) the “command flow”, which is the speed on the E axis in G-code; by F(t) the actual flow; by V(t) the head travel velocity (feed); and by F1, V1 the “design flow” and “design velocity”, which are the steady-state parameters along the path far away from its endpoints. Actual flow F(t) depends on G(t) and tau (as a solution of a first-order differential equation). The controller uses tau to estimate F(t) for a given G(t). Extrusion width is proportional to F(t)/V(t). The objective is to construct an extrusion ramp G(t) and a velocity ramp V(t) such that F(t)/V(t) = const = F1/V1 all the way to the end of the path, then drops sharply to zero (no ooze).

As best I can tell, at path ends Kisslicer uses a parabolic ramp G(t)=F1*(1-a*(t^2)), calculated in such a way that the estimated F(t) reaches zero at the same moment as G(t) reaches or comes very close to (F1-VP). At path starts, G(t) begins close to +VP and is calculated so that the estimated F(t) reaches the design flow F1 of the new path at the same moment as G(t) also reaches F1. The feed V(t) is in each case synchronized with F(t), so F(t)/V(t) = const. And this works, at least as long as Kisslicer is given the correct tau.

However, Kisslicer only uses this algorithm when F1<<VP. With greater F1 (Fig. 2 shows an example where F1=0.5VP on the infill), G(t) does not go as high at path start, does not go as far negative at path end, and V(t) is not synchronized with F(t). I do not know whether this is intentional or in error. But Fig. 2 displays the consequences: Under-extrusion at path start, over-extrusion at path end, and plenty of ooze. (I should probably note that filament diameter in the model is 3mm. In a printer using 1.75mm filament, VP=10mm/s corresponds to 24mm^3/s. So F1=0.5VP is not an unreasonable condition for fast infills.)

Now, faced with this situation, and since VP is usually the maximum retract rate practically possible in hardware, the user would of course try to tune VE (that is, tau) to eliminate the ooze. And if he enters a VE 4 times greater than the true value, he will succeed. Which is why the Wizard recommends a VE value 4 times greater than what it measures. Fig. 3 shows the result. Ooze at the end of the infill path is almost gone, but over-retract causes severe problems elsewhere: A short loop path under-extrudes even when it follows another loop path; at infill start, extrusion does not even begin until 6mm into the path; the perimeter following the infill over-extrudes 3.6x initially and still over-extrudes 2x 5mm into the path; and so on. What would the user do next? He’ll reduce VE and try to compensate with traditional fixed destring. This will achieve some improvement over Fig. 3. But clearly something is not right.


PART III: RAMPS, CONT.

Let us go back to the drawing board. We need to choose an extruder ramp function G(t), estimate actual flow F(t), and match the feed V(t) to F(t) such that F(t)/V(t)=const. In principle, any G(t) will do, as long as F(t) is correctly calculated and V(t) is correctly matched. However, we also want, if possible, robustness to mis-estimation of tau. That is to say, suppose we use tau to estimate F(t) and match V(t) to F(t), but the real time constant is tau’ and the real flow is F’(t). There is then a relative error in extrusion width equal to (F’-F)/F. We would like that to be small.

Now, if G(t) is very slow (relative to tau timescale), F(t) would stay very close to G(t) regardless of tau and therefore would be predictable, which achieves the robustness goal. But the ramp would take forever to come to a stop. So there is a trade-off here. We don’t need the shortest possible stopping distance, but it must remain reasonable.

Here’s a little intuition. I would not have found this intuition persuasive before spending time with the equations, so you might not either, but I’ll give it anyway. The F(t) rate of change equals (G(t)-F(t))/tau. When G(t)-F(t) is large, rate of change is large and if tau is incorrect, error F’-F accumulates quickly. But because what matters is the ratio (F’-F)/F, this can be tolerated while F itself is large. Then later when F(t) is small, G(t) must be close to F(t). If F(t) changed faster than expected early in the ramp, it will change slower toward the end. So we want to start with a large difference G(t)-F(t) and end with a small difference – the exact opposite of the parabolic form Kisslicer implements now. I tried several other forms for G(t) in the computer. The best turned out to be the one that does not reverse the extruder at all, but continues forward at low speed. I define it formally later in this post.

There’s another problem: At path end, we need F(t)=0. How can the ratio (F’-F)/F remain reasonable when F=0? Here’s how: Just before F(t) reaches zero, we abandon the matching strategy and switch to regular destring. We all know that destring works well at low flows F<<VELDSTR, and it can be shown mathematically also. Problem is, the fastest destring most hardware can do is not much faster (on my rig, only ~2.5x faster) than the flow with which we want to print our infills.

To formalize the preceding discussion: Get rid of VP. Instead, let the user choose a flow H at which standard destring is acceptable. I propose (after experimenting with a few others) the following strategy when finishing a path with design flow F1 and jumping to a path with flow F2 (see Fig. 4 for an illustration):

1. If F1>H, set G(t)=aH, a=0.5. The flow F(t) will exponentially approach aH and reach H at time tz = -tau* log(1-a)/(F1/H-a). Slow down V(t) in the same exponential manner to match F(t). Sensitivity of extrusion error to mis-estimation of tau during this step is given in Fig. 5, with h = H/F1. Plan the ramp so that the printhead reaches path endpoint at time tz. If F1 < H, skip Step 1 and proceed to Step 2.

2. Denote by Fs the flow at the end of step 1, Fs = min{F1, H}. Apply fast retract (destring) with retract speed R=VELDSTR, concurrently (if possible) with the jump to the starting point of the next path. Retract duration TR is the ratio of DESTRING_LENGTH to VELDSTR, and we let the user choose DESTRING_LENGTH. (The model recommends TR = tau* log(1+Fs/R), plus the amount necessary to suppress thermal ooze, plus a safety margin if needed. In practice, increase DESTRING_LENGTH until ooze stops improving. Excess retract only chews up filament.)

3. At the start of the next path, apply fast prime with speed R. The amount of prime _must_ equal the amount of preceding retract. Expect a blob of roughly the same volume as the ooze. The prime will bring the flow to F(0) = FsR / (Fs + R) (usually close enough to Fs to ignore the difference).

4. (a) If F(0) > F2, drive the flow down with the same technique as in step 1. Viz., set G(t) = aF2. The flow F(t) will exponentially approach aF2 and reach F2 at time tz = tau*log(1-a)/(F(0)/F2-a). Slow down V(t) to match the flow. Sensitivity of extrusion error to mis-estimation of tau during this step is given in Fig. 5, with h = F1 /F2. At time t = tz, revert to design flow G(t) = F2.
(b) If F(0) < F2 (a more common situation, since H is small), set G(t) = F2. The flow will exponentially approach F2. Accelerate V(t) to match the flow. When the flow is within, e.g., 10% of F2, revert to design feed. Relative extrusion errors should be small because the flow is increasing.

The plot in Fig.5 shows how the algorithm (theoretically, of course) would perform. On my rig, I expect to set H~0.8mm^3/s, and the fastest flow I dare to print with is ~8mm^3/s, so I’ll have h~0.1 and the error number ~2. This means for every 10% of mis-estimation of tau I’ll get a maximum of 20% over-or under-extrusion somewhere along the path (usually at the endpoints). (Whereas in Figs. 2,3 errors reach 100% even with the best possible tau). The stopping distance is ~V1*tau, e.g. 32mm on paths printed at 53mm/s. This is ~2.5x longer than the stopping distance in Fig. 2. But the comparison is not fair, since the ramps in Fig. 2 don’t really do the job.

OK, that’s my pitch. Sorry so long. I wonder how many people even read this far :)
Attachments
Fig5_ProposedRampPerformance.jpg
Fig5_ProposedRampPerformance.jpg (12.11 KiB) Viewed 4588 times
Fig4_ProposedRamps.jpg
Fig4_ProposedRamps.jpg (15.87 KiB) Viewed 4588 times
Fig3_StdPreload4xtau.jpg
Fig3_StdPreload4xtau.jpg (34.98 KiB) Viewed 4588 times
Fig2_StdPreload.jpg
Fig2_StdPreload.jpg (33.01 KiB) Viewed 4588 times
Fig1_OozeTest.jpg
Fig1_OozeTest.jpg (41.64 KiB) Viewed 4588 times
hacker
Posts: 149
Joined: 20 Aug 2016, 18:25

Re: Preload: A Modest Proposal

Post by hacker »

I've read this far ;-) No idea what effect it will have on kisslicer, I hope Jonathan will not dismiss it, but at any rate it was great read, thanks!
User avatar
lonesock
Posts: 258
Joined: 09 Nov 2014, 18:41
Contact:

Re: Preload: A Modest Proposal

Post by lonesock »

Nice! I'll have to digest this more fully later. Quick question: I assume you were evaluating KISSlicer's preload functionality with non-BfB firmware (as I couldn't get the extruder to run backward at the end of the path to reduce the preload under BfB firmware)? Btw, some of the shape of the extruder ramp profile came from trying to let KISSlicer handle speed ramps for the supported and unsupported segments of a single path independently, then use a simple superposition to stitch them together. The good news is that all the code for the Preload function is written knowing it's probably not optimal and I might have to update it someday. [8^)

Improvements to Preload is definitely on the list for v2, thanks!

EDIT: I wanted to point out that the extruder values in the G-code at given "nodes" along the path are correct at that point, that is, the printer will drive the extruder to that E value as it drives the X and Y axes to the matching XY values. However the head speed specified by F does not behave the same way, the printer accel/decelerates to the desired F speed according to an unknown acceleration, then (mostly) keeps it constant over the length of that segment of the path. For this reason, the F value requested by KISSlicer is actually the average computed F for the whole segment, and if you plot the F and E values requested by KISSlicer there will be a slight offset.

Jonathan
Beefeater
Posts: 34
Joined: 17 Jul 2017, 22:54

Re: Preload: A Modest Proposal

Post by Beefeater »

Except for Fig. 1, everything is entirely inside the Windows PC. I run Kisslicer to generate "5D-Absolute E", then use a script to analyze the .gcode file.

I know I b... I mean complained a lot about in-firmware acceleration, but I did not include it in my model here. If the G-code reads

G1 X100 Y100 Z10 E10 F600
G1 X101 Y101 E10.1

then I assume the printhead travels 1.41421mm in 0.141421 seconds at a uniform speed and the extruder stepper runs at a uniform 0.707107mm/s during that entire time. As you point out, not all printers behave this way, which is one reason Preload may fail on some printers. But I am not dealing with that here.
User avatar
pjr
Posts: 692
Joined: 05 May 2015, 10:27
Location: Kamnik, Slovenia

Re: Preload: A Modest Proposal

Post by pjr »

OK, this is a quite brilliant post, most of which was way above my level of comprehension.

There are a couple of other things I will add.

1. I have found that ooze depends on what the extruder is doing; wipes induce oozing, as would a travel move without sufficient Z-lift. During testing, I was able to print a line almost 400mm in length following an extrusion and with the nozzle just 0.2mm above the bed. The ooze is very much reduced then extruding in air, down to as little as 15mm of ooze over 2 minutes.

2. Prusa Research has just released firmware which includes "Linear Advance" which I have been testing (with inconsistent results), but I believe that is based on the existing Marlin feature reworked to an extent. It does require a reduction of acceleration and jerk values and seems to require relatively high-speed printing (100mm/s) - both of which I have tried using PLA (I print mainly with PLA). I used the KISS <TUNINGVAL> wizard to determine a "K" value of 480 (with MMU setup), then printed the same cube with "seam hiding" and there was significant under-extrusion at the start of paths, so more work required.

Peter
User avatar
Olivier13
Posts: 45
Joined: 29 Jun 2015, 10:46
Contact:

Re: Preload: A Modest Proposal

Post by Olivier13 »

Hi
Very interesting...nice approach!
IMHO, "mechanical purpose" should be take in account...i will try to explain :

With bowden, forces applied on filament depend of
  1. the X/Y head position relative to the feeder (fixed position)...if the head is far of the feeder : less forces...if near : more forces
  2. the curve adopted by the bowden while the head is movingg...always a -Z force with moments around X or (including) Y
Next "level" : add forces created by electric' wires/duct and/or watercooling flexible pipes

Preload could be a good tool to determine the best destring valueS...if we have control on prime and suck speed/lengh
Preload should stay as experimental (regarding to my remarks)
Printer : A4v3 From 3ntr - 2 Extruders.
http://www.additec.fr
Beefeater
Posts: 34
Joined: 17 Jul 2017, 22:54

Re: Preload: A Modest Proposal

Post by Beefeater »

pjr wrote:1. I have found that ooze depends on what the extruder is doing; wipes induce oozing, as would a travel move without sufficient Z-lift. During testing, I was able to print a line almost 400mm in length following an extrusion and with the nozzle just 0.2mm above the bed. The ooze is very much reduced then extruding in air, down to as little as 15mm of ooze over 2 minutes.
That's true. I hadn't thought about this. If a nozzle is, say, 0.4mm diameter and 0.2mm above the bed, there's viscous resistance not only as the melt passes through the nozzle, but also as it spreads on the bed under the nozzle. It's like having a slightly longer nozzle. So tau measured in free air may be different from tau while extruding. Now, I am guessing that the 400mm printed line becomes very narrow toward the end, whereas the 15mm bead oozed in free air does not, so the difference in total ooze _volume_ is much less than 25-fold. But there could be some difference. As far as wipe inducing ooze, though, I can't visualize why that would be. Any ideas?
User avatar
pjr
Posts: 692
Joined: 05 May 2015, 10:27
Location: Kamnik, Slovenia

Re: Preload: A Modest Proposal

Post by pjr »

Beefeater wrote:the 400mm printed line becomes very narrow toward the end, whereas the 15mm bead oozed in free air does not, so the difference in total ooze _volume_ is much less than 25-fold.
True, but the total ooze volume was significantly larger than in air.
Beefeater wrote:As far as wipe inducing ooze, though, I can't visualize why that would be. Any ideas?
For exactly the same reason; the wipe is (say) 0.2mm above a solid object and the act of moving the nozzle will pull the molten filament out of the nozzle. Yes, preload retract should effectively remove the pressure from the nozzle, but surface tension (and please bare in mind I have no idea what I am talking about...) will drag more filament out.

Also Join-loop has gone a long way to improve seams, but there is still the issue that the nozzle has to stop at the perimeter (acceleration/jerk) before moving inwards to the loop and this still causes the end of the perimeter to be raised slightly.

Peter
Beefeater
Posts: 34
Joined: 17 Jul 2017, 22:54

Re: Preload: A Modest Proposal

Post by Beefeater »

pjr wrote:Beefeater wrote:
the 400mm printed line becomes very narrow toward the end, whereas the 15mm bead oozed in free air does not, so the difference in total ooze _volume_ is much less than 25-fold.


True, but the total ooze volume was significantly larger than in air.
It's hard for me to believe that the melt can be pulled through the nozzle by surface tension. Just think how much force is needed to push it. Also, I think surface tension will not even pull on the melt, but rather on the nozzle itself, if the nozzle is wetted. (I may be wrong on this though.) If much more ooze flows when printing than in free air, maybe there's some other explanation. Was the nozzle kept at the same temperature in both cases? How did you measure ooze volume? What happens if you move the nozzle along the same path as in the print experiment, but far above the bed?
Beefeater
Posts: 34
Joined: 17 Jul 2017, 22:54

Re: Preload: A Modest Proposal

Post by Beefeater »

Beefeater wrote:Also Join-loop has gone a long way to improve seams, but there is still the issue that the nozzle has to stop at the perimeter (acceleration/jerk) before moving inwards to the loop and this still causes the end of the perimeter to be raised slightly.
Acceleration is a whole other can of worms. Right now, I think the seam is raised because Preload does not work correctly. The join-loop widget is only ~2mm long, and over-extrusion can continue much longer, cf. Fig. 3 in my earlier post. But even when Preload is properly constructed, in-firmware acceleration can interfere with it on some printers.

Consider a perimeter path sketched below, starting with join-loop at point A. How will the firmware handle it? Each in its own peculiar way, I am afraid. I can think of at least 4 possibilities (and these are just the sensible ones :)):

1. The firmware may program velocity ramps at start and end of each G1 segment, to avoid jerks and perhaps slippage at the stepper motors (any slippage would of course instantly ruin the entire print). This would cause over-extrusion not just at the seam, but at every node D, E, F, G, effectively everywhere along any curve because a slicer breaks up the curve into short segments, and even in some straight paths because Kisslicer often breaks up straight paths into shorter segments for various reasons.

2. The firmware may program velocity ramps only at sharp corners such as point G, and not at D, E, F, where they are not needed because the segments are nearly collinear and there would be no jerk. But to do this the firmware must, while executing a G1 command, look ahead to the next G1 command. I don’t know how many firmwares are that smart. The next G1 may not even be the next line in the G-code file, since the file also has fan commands, comments, etc.

3. The firmware may never program velocity ramps. In some cases, the printhead is light enough and the drivetrain is strong enough to tolerate jerks at fairly high speeds. Otherwise, the slicer must implement velocity ramps in G-code. And some slicers do, e.g. CraftWare. But they can’t do it well because that would involve a large number of very short, progressively faster or slower G1 steps. Some firmware may not even be able to consume G-code fast enough. And of course if the slicer tries this against a firmware that builds its own ramps as per item 1 above, it makes matters worse.

4. The firmware may program a velocity ramp at the start of each G1 segment to accelerate/decelerate from the previous speed to the new speed, but no ramp at the end of the segment. This works perfectly everywhere except at corners: E.g., at point G, motion in Y must stop immediately and a jerk would occur if there had been no deceleration between F and G. Ahead of such sharp corners, the slicer must break up the segment FG into two segments FQ and QG, FQ covering most of the path at high speed V1 and QG assigned a low speed V2 and just long enough for the firmware to decelerate from V1 to V2. I like this strategy best because optimal performance can be achieved. But to write the QG segment correctly, the slicer must know exactly how the firmware constructs its ramps. And again, if the slicer tries this against a different firmware, it could make matters worse.

An important circumstance to bear in mind is that printhead travel responds much faster to commands than filament flow. So when Preload is matching the travel speed to filament flow, the acceleration/deceleration is much softer than what the printhead driver is capable of. Therefore, Preload will work smoothly with firmwares if types 2-4 above, but not with firmwares of type 1. For the same reason, it is impossible to avoid over-extrusion at corners such as point G: The printhead _must_ slow down at the corner, and filament flow _cannot_ slow down and speed up as quickly. (Decelerating so gradually at each corner that the extruder can keep up would slow the print down to a crawl.) As far as the rest – well, you’re stuck with the firmware you’ve got. Unless you can patch it.
Attachments
Accel.jpg
Accel.jpg (10.95 KiB) Viewed 4439 times
Post Reply