supermerill / SuperSlicer

G-code generator for 3D printers (Prusa, Voron, Creality, etc.)
4.1k stars 517 forks source link

Minimum filament volume after unretract #3956

Open VanessaE opened 10 months ago

VanessaE commented 10 months ago

Is your feature request related to a problem? Please describe.

Sort-of -- it's related to a quirk present in most extruders, particularly those which employ a spring, idler arm, and bearing to apply pressure to hold the filament against the drive gear. This kind of design is extremely common, but because they usually don't limit how far the filament can be pushed relative to the gear, they can outright crush the filament if it's run back and forth over the gear too many times without enough net forward movement, especially if the spring tension is set too high.

Suppose you have a print with a whole bunch of very short print moves in a row, each of which begins with an unretract after a travel, and ends with a retract and another travel. For example, below is a gear where SuperSlicer is laying gap fill into the tips of its teeth, one tooth after another, the spacing between them being big enough to trigger retractions:

image

If you have enough of these kinds of moves in a row, you end up with the filament basically just going back and forth over the extruder gear, without it actually advancing all that much. The patch of filament being run back and forth through the extruder is gradually compressed, and new teeth marks get applied over previous teeth marks, over and over, destroying the precision to which the filament was manufactured. This will almost certainly lead to one of three failures:

  1. as the filament is compressed, plastic must by definition be pushed away perpendicular to that force, like squeezing a balloon - as you compress the middle, air is forced to the ends and/or sides. Similarly, some of the displaced material is pushed perpendicular to the filament's length, thus making it wider in that area. Get it wide enough, and it'll exceed the diameter of the extruder's filament path, or that of the hotend, resulting in a jam.

  2. if the filament gets crushed flat enough, regardless of how much lengthwise or sideways expansion it causes, it can eventually get so flat that the extruder gear simply loses grip altogether and just starts slipping, grinding/chewing the filament, and preventing any further forward movement, like a car that's stuck in mud or sand. I believe this is what the author of [#400] was trying to convey. Indeed, the biggest cause of these excessive retractions is having lots and lots of tiny gap fills all over the place.

  3. as a patch of filament compresses and lengthens, each successive set of unretract-print-retract moves will push progressively less volume than expected. Sideways displacement doesn't really affect the volume pushed per millimeter of extruder movement, but the lengthwise displacement does. Since the extruder's movements can't be auto-adjusted to compensate for that effect, the end result is that the hotend gradually loses pressure, eventually starving future print moves. In a big print, this is probably okay since the starved lines will probably be safely hidden inside the part, and buried under other, full-volume lines. On the other hand, this starvation will end up affecting exterior perimeters or thin walls if the print is small enough, resulting in poor surface quality, or even making the part too weak to be useful. Either way, the print is ruined.

Describe the solution you'd like

The user should be allowed to set a minimum amount of plastic volume that must be printed before a retract can be triggered on a following travel move, thus limiting how much retract/unretract activity gets thrown at any one bit of filament, and in turn limiting the crush-and-expand effect to the point where it won't ruin the print.

Describe how it would work

If the set of print moves between one unretract and the next retract would not use up enough filament volume, then that next retract would simply not be triggered -- the travel move would be a simple no-retract travel instead.

If that no-retract travel would cross a perimeter, it should instead be re-routed according to the "avoid crossing perimeters" algorithm -- even if that setting is turned off -- otherwise you risk leaving ooze on the exterior of the part.

Travels would continue without retractions until the extruder has pushed the configured amount of plastic via normal print moves, even if that means going for several print-travel-print-travel-[...] moves before the next retract can finally be allowed.

The threshold to trigger a retract should be measured in cubic millimeters of extruded volume. That of course directly translates to net forward filament movement through the extruder, but cubic millimeters seems a bit more user friendly to me (those numbers are an order of magnitude larger and need not be as "precise").

Assuming I've done the maths right[], I would suggest a default of 0.2 mm³ for this feature. A nice round number :smile: . Assuming 1.75 mm filament, that's about 0.083 mm of net forward movement through the extruder. With a typical 0.2 mm layer height and 0.4 mm line width, that's about 2.8 mm worth of print moves before triggering the next retract. In my screenshot above, this threshold would result in those gap fills getting retractions roughly every *other\ tooth, or maybe even every third tooth (hard to be sure, gap fills being as variable as they are).

[*]

w=0.4; h=0.2
0.2/((w-h)*h + pi*(h/2)^2)
2.8004957689
0.2/(pi*(1.75/2)^2)
.0831503377

Describe alternatives you've considered

There is no real alternative except to play with various print settings to try to minimize retractions.

Do note that this is not related in any way to the existing setting that limits retractions according to travel length. This is strictly about limiting how much the extruder can wail on a patch of filament before it moves on.

supermerill commented 10 months ago

also, in the exemple picture, it should be possible to merge the gapfill in the perimeter loop. But more difficult to implement.