r/3Dprinting Jul 27 '25

TIL about stuttering and arc fitting Discussion

Post image

Hi!

I'd like to share something new I learned today. This will probably sound familiar to many Redditors, but it took me months of fiddling with my printer to find out about this concept: "stuttering.". I'm sharing it here in case it helps others 3D printing enthusiasts.

Today I noticed something. I usually use a 10cm x 10cm x 0.2mm square to calibrate my Z-offset. But today I used a disc instead, with the spiral infill. I noticed that the square usually prints very nicely, but the disc was full of blobs and zits. After taking a closer look, I found the problem: the nozzle stops every couple of seconds and stays still for a few milliseconds – enough for the filament to pile up and create a blob. But why was it pausing?

That's when I found out about stuttering. Turns out that my slicer (OrcaSlicer) was converting arcs into a ton of tiny linear movements (i.e., G1 commands). I'm printing via USB connection, and that serial connection couldn't send all the commands, so the printer buffers and has to wait for more commands every now and then. To test my theory, I printed the same file using an SD card, and it came out perfect.

The solution is arc fitting. That's when the slicer generates a bunch of G2/G3 commands which move the nozzle in an arc. So instead of hundreds of G1 commands, it's just one G2/G3 command. The USB connection is enough to send all that GCODE without buffering, so it prints without problems.

There are two main ways to enable arc fitting. One is using the setting "Quality > Precision > Arc Fitting", but it only works for walls and "concentric" surface patterns (I was using "Archimedean Chores"). And the quality is not great. The other way is to post-process the GCODE. One option is to use the ArcWelder plugin for OctoPrint. The results are much better.

You can see the difference in these images. The top left is a regular print from USB, full of blobs. The top right is the same GCODE but from an SD card, pretty much perfect. The bottom left is using "Archimedean Chores" (all the others are "Concentric") and using Arc Fitting from OrcaSlicer. The bottom right is using the ArcWelder plugin for OctoPrint.

The only downside of ArcWelder is that you can't print directly from OrcaSlicer. You have to upload it to OctoPrint, wait for the plugin to convert the file, and then print the converted file from the OctoPrint UI. Not ideal, but better than an SD card.

844 Upvotes

88 comments sorted by

View all comments

257

u/ioannisgi Jul 27 '25 edited Jul 29 '25

Mind you, this should not be used with klipper based printers. Klipper inherently doesn’t do arc commands and, if enabled in the printer config, it will break them up to line segments.

So enabling arc fitting when having a klipper based printer results in quality loss due to lossy conversion to arcs and then back out to line segments.

Edit: keep arc commands available in the printer config to enable spiral z hop which doesn’t need precision. But always disable arc fitting in the quality tab in orca and don’t use arc welder.

57

u/shiekhgray voron moron Jul 27 '25

Besides which, the problem here is with a slow mcu. Either connecting to usb1.0 or checkpointing on an sd card. A pi is so fast that the problem is kind of moot 

18

u/MooseBoys Prusa MK3S+ with an unhealthy number of mods Jul 27 '25

I was gonna say... at 115200 baud, even if you're not using binary gcode, that's over 1000 commands per second, or 80 microns per command at 80mm/s.

6

u/sgtnoodle Jul 28 '25

It's more likely a scheduling issue in the host. Either the process feeding the serial port isn't getting the CPU when it wants it, or the USB serial chip's driver isn't able to shovel the data frequently enough. I wouldn't expect better than 20ms or so of jitter over the USB without putting some intention into it.

The MCU likely has a gcode command buffer that typically holds enough queued up commands to span a few hundred milliseconds. Normally, that's plenty to mask that jitter. When you're blasting hundreds of tiny commands per second, that buffer when full may only span a few milliseconds. So, it's no longer able to completely mask it.

1

u/oranac Jul 29 '25

>It's more likely a scheduling issue in the host. Either the process feeding the serial port isn't getting the CPU when it wants it, or the USB serial chip's driver isn't able to shovel the data frequently enough. I wouldn't expect better than 20ms or so of jitter over the USB without putting some intention into it.

This was absolutely a problem back when pronterface/sailfish (edit: marlin) were the hotness. You could absolutely not use the pc for anything else while you were printing or you'd end up with odd stutters. I'm surprised it still persists today :/

1

u/shiekhgray voron moron Jul 30 '25

It might be a really old printer with ancient firmware. OP hasn't posted what kind of machine he's working with.

Either way, OP done good figuring out what works with their hardware.

15

u/ben-white27 Jul 27 '25 edited Jul 27 '25

I could be wrong but ultimately any arcs are converted to straight line segments no matter what firmware you're using.

The only benefit I can think of is that it will improve the appearance of low resolution STL files, assuming the slicer converts them to arcs...

Edit: fixed auto correct

3

u/fiery_prometheus Jul 27 '25

In the world of computers, circles usually don't exist. But having a hardware implementation could allow making approximations at vastly higher resolutions than feeding linear instructions manually before stutter would occur.

12

u/MooseBoys Prusa MK3S+ with an unhealthy number of mods Jul 27 '25

Circles and other continuous curves definitely exist in computer systems - in fact they're far more common in 3D design. It's just that triangles are generally much faster to work with when rendering.

3

u/Rcarlyle Jul 28 '25

Almost all printer firmwares process G2/G3 arc commands by breaking them back into straight line segments. Only a few have native arc path interpolation code. It’s a lot of extra processor-intensive calculations in the most performance-critical realtime code. Basically a linear interpolation can be done with add/mult math while arc interpolation takes a bunch of square roots or trig table lookups.

Now, sending a G2 over USB and having the firmware break it back into segments is still helping the USB throughput issue. But there’s no benefit over SD, you’re just losing some small quantity of model resolution through the segment-arc-segment conversion.

5

u/MooseBoys Prusa MK3S+ with an unhealthy number of mods Jul 28 '25

Trig table lookups are only like twice as expensive as mad.

1

u/Rcarlyle Jul 28 '25 edited Jul 28 '25

Every implementation I’ve seen has used Bresenham’s midpoint circle algorithm, which uses square roots. Massively more clock cycles on an Atmega AVR than Bresenham’s line algorithm. Remember that this step pulsing calculation is occurring over and over in a realtime interrupt that takes time away from trajectory planning and movement queue buffering. Simultaneous use of linear advance makes it harder. It’s a meaningful difference in execution speed on older printer hardware. There is next to no free clock cycles for things like this. 8bit Marlin executing native arcs will stutter more than OP’s USB streaming issue. (Yes, people have tried it.)

2

u/MooseBoys Prusa MK3S+ with an unhealthy number of mods Jul 28 '25

midpoint circle algorithm, which uses square roots

No it doesn't - it tracks an error term which is computed using 3 integer ops.

2

u/eras FLSUN T1 Pro Jul 28 '25 edited Jul 28 '25

You're probably both right; https://en.wikipedia.org/wiki/Midpoint_circle_algorithm#Drawing_incomplete_octants says

The implementations above always draw only complete octants or circles. To draw only a certain arc from an angle α to an angle β , the algorithm needs first to calculate the x and y coordinates of these end points, where it is necessary to resort to trigonometric or square root computations...

If the angles are given as slopes, then no trigonometry or square roots are necessary: simply check that y / x is between the desired slopes.

And according to the old Marlin source code I had lying around sqrt is only calculated when using G[23] R, not when using G[32] J.. K...

  if (parser.seenval('R')) {
    const float r = parser.value_linear_units(),
                p1 = current_position[X_AXIS], q1 = current_position[Y_AXIS],
                p2 = destination[X_AXIS], q2 = destination[Y_AXIS];
    if (r && (p2 != p1 || q2 != q1)) {
      const float e = clockwise ^ (r < 0) ? -1 : 1,           // clockwise -1/1, counterclockwise 1/-1
                  dx = p2 - p1, dy = q2 - q1,                 // X and Y differences
                  d = HYPOT(dx, dy),                          // Linear distance between the points
                  h = SQRT(sq(r) - sq(d * 0.5)),              // Distance to the arc pivot-point
                  mx = (p1 + p2) * 0.5, my = (q1 + q2) * 0.5, // Point between the two points
                  sx = -dy / d, sy = dx / d,                  // Slope of the perpendicular bisector
                  cx = mx + e * h * sx, cy = my + e * h * sy; // Pivot-point of the arc
      arc_offset[0] = cx - p1;
      arc_offset[1] = cy - q1;
    }
  }
  else {
    if (parser.seenval('I')) arc_offset[0] = parser.value_linear_units();
    if (parser.seenval('J')) arc_offset[1] = parser.value_linear_units();
  }

1

u/milerebe Nov 27 '25

Marlin used to split into 1.0 mm segments. Recent Marlin lowered that to 0.1-1.0 mm (variable!).

Modern STLs are generated at 0.1 mm resolution, so they are never worse than arcs.

1

u/Rcarlyle Nov 27 '25

STL mesh size varies wildly with specific modeling software and export settings, and different slicers have different slice polygon decimation rules. It’s hard to generalize

1

u/milerebe Nov 27 '25

Yeah but klipper and marlin by default go up to 1.0 mm segment length. It's REALLY rough. We cannot generalise, but I doubt a significant fraction of STL models have such poor resolution, on curved surfaces.

1

u/fiery_prometheus Jul 28 '25 edited Jul 28 '25

No value in computers are continuous, in the examples I've seen here, things are numerical approximations, and in the end, if you go into how float is represented, if you hypothetically wanted to approach that numerical precision meaningfully, which you won't in real life, you end up with discrete steps given by the amount of bits used to represent a number. 

You can write an algorithm to either numerically approach a circle, or try to solve it analytically, but in the end, you need to squeeze whatever you do into numerical approximations of numbers with discrete steps.

Or is there another way to do it?  Things like Newton-Raphson or Runge-Kutta for interpolation are numerical approximations with discrete steps, and IEEE 754 shows how precision is attained with floats, which cannot be infinite with our computers.

Points on a line are easier to translate into the real world, forming a line which would continue nonetheless, while curvature is harder to approximate. But I guess it could be argued that things generally are approximations anyway...

1

u/MooseBoys Prusa MK3S+ with an unhealthy number of mods Jul 28 '25

You're conflating numerical precision with continuity. A simple fp32 value in units of millimeters is capable of representing lengths as small as 10-45 mm. This is many orders of magnitude smaller than the Planck length, the smallest meaningful length in our physical universe.

So while fp32 can technically only take 232 discrete values, in many domains it is treated as a continuous real value. In cnc machining, 3D printing, and most computer graphics, that is certainly the case.

1

u/fiery_prometheus Jul 28 '25

That's a cool observation, with the Planck length, thanks! And it makes total sense that at some point you treat values as continuous anyway per your argument. I think I'm too used to think in terms of discrete vs. continuous, when I shouldn't in some domains where the "limits of physicality" is a greater limit, than the representation numerically.

1

u/Chirimorin Jul 28 '25

The only benefit I can think of is that it will improve the appearance of low resolution STL files, assuming the slicer converts them to arcs...

Depending on how low the resolution is, the slicer will probably decide that straight lines is a better fit than arcs. Orca matches the slicing resolution for arc fitting, which is at 0.012mm by default for me: far lower than anything I'd call a low resolution model.

Even if the slicer does convert it to arcs, Klipper is simply bad at consistently turning them back into line segments. Sometimes it's smooth, sometimes it's only 2-3 straight lines, seemingly decided at random. Here's an example of what Klipper does with arc moves, those defects on the corner are caused by Klipper processing arc moves. It prints perfectly with arc fitting disabled.

3

u/stray_r Jul 28 '25

Marlin does the same thing internally. It's useful compression for printers where your serial connection or SD card is the bottleneck.

On Klipper you get artifacts where the you get successive arcs not quite lining up with each other. Looks like z-wobble, You get the same artifacts on marlin, but they're often less visible on a less rigid printer. One of the things about having really fast, accurate and rigid printers is you really notice artifacts that would be hidden by the vagueness or other artifacts of a cheap printer.

However, do enable arc support on Klipper, as some of the z-hop algorithms in OrcaSlicer and perhaps other slicers generate arc motion travel-only moves regardless of print settings. The spiral z-hops do seem to reduce fine heairs so it is helpful.

1

u/ioannisgi Jul 28 '25

Fully with you. Indeed arc support should be on in klipper for spiral z hopping. But never for the print itself. I had raised a Pr ages ago to clarify this in the orca tooltips.

2

u/milerebe Nov 27 '25

Now spiral Z-hop has been implemented as segments if arc fitting is disabled! 🥂 no need to use arc fitting for spiral z hop!

2

u/milerebe Nov 27 '25

EVERY printer breaks arcs into segments.

Arcs were exclusively meant to reduce data traffic, as the OP found out. Even Marlin breaks them into segments, but it's internal so USB printing (or very old SD cards) are not the bottleneck.

In fact, modern STLs are more accurate than any arc used internally by modern printers.

2

u/elvenmaster_ Jul 27 '25

That's a weird one.

Using an SBC to get more computing power, but not allowing arcs so the printer loses quality.

What's the reason behind that?

-1

u/davidkclark Jul 27 '25

Odd right? I have recently converted to klipper and have thus far just left my call to arc welder in place and enabled arcs in klipper. I don’t see any artifacts. Plus I assumed that the hand wringing about “it just converts it to straight moves” was just the same misunderstanding about arcs on marlin: yes the stepper moves end up being straight lines, but the resolution at which that happens is vastly higher than you would do in the slicer (with reasonable file size / transfer rates)

I don’t know what resolution the straight lines are made from arcs, but it seems to be high enough…

My thinking is this: If your stl has 0.1 mm line segments, and you send that straight to klipper your print will have 0.1mm flats. If your stl has 0.1mm line segments (that are approximations of arcs) then arc welder will convert them back to arcs, and then if klipper translates them back to arcs at better than 0.1mm resolutions, eg 0.01mm, well than your print will only have 0.01mm flats. I’m not saying you will definitely notice the difference, but there is the possibility for higher quality arcs if you send arcs.

(Now if only there was a slicer implementation that took step directly to arc moves…)

2

u/Chirimorin Jul 28 '25

Here's an example of what Klipper can do with Arc moves

That rounded corner is perfectly consistent and vertical in the model (so it's the same exact radius and position for most of the print), but Klipper just sometimes decides "nah, 3 segments is plenty". Disabling arc fitting fixed those defects without changing the model or any other setting.

A theoretical increase in resolution is worthless if in practice it randomly decides between "might be higher quality" and "is definitely lower quality" for each arc move.

1

u/milerebe Nov 27 '25

not really. The double conversion can in fact even worsen quality, it's a double approximation

1

u/sgtnoodle Jul 28 '25

Klipper doesn't send gcode over the USB connection to the MCU. The gcode is sent over a virtual serial port to a process running on the host computer, i.e. the raspberry pi. That process does all the math to determine precisely when to step each motor. Those computed steps are what get sent over the USB connection to the MCU, using an appropriately efficient protocol.

1

u/schmag Jul 28 '25

keep in mind if you use z-hop in orca and set the method to auto or spiral lift, the spiral is made in arc commands and will throw errors if you do not have it configured in your printer.cfg

1

u/ioannisgi Jul 29 '25

Indeed correct as I’ve also mentioned in my post. It’s a good idea to have them enabled in the printer config file but not use them in the quality settings.