* 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
