Saturday, 5 February 2011


When Reprap machines print holes they tend to come out undersized, even if the linear dimensions of an object are spot on. There are several effects that all make holes smaller than they should be: -

Faceting error
When CAD systems convert cylinders to triangles they produce a polygonal prism, so holes represented in an STL file are polygons with their vertices on the circumference of the original circle. That means the sides of the polygon are inside the circle, shrinking it by cos(π / n).
You need 10 vertices to reduce the error to 5% and 22 for 1%. So this error quickly becomes small as n increases but that creates another error:-

Segment pausing
When a circle is broken into a lot of little segments the start up time for a segment becomes significant. Reprap in the past has suffered from this really badly and I am unsure what the current status is. Slow serial comms and complex floating point firmware add pauses where extra filament can ooze from the nozzle.

I have never suffered from pausing because I use a 100Mbit Ethernet connection, which has a very low latency, and the data is transmitted in binary and in the units my firmware works in. This means that no further processing is required other than calculating which of the three axes has to go the furthest. However, I use trapezoidal acceleration on each segment, so for very short segments the average speed will be a little lower.

Arc shrinkage
When a flat strip of filament is bent into an arc there is too much plastic on the inside of the curve and too little on the outside. That makes both the inside and outside edges a smaller diameter than they should be. Adrian calculated a formula for it here: The formula comes out with a figure that is too small though. I think there is a secondary effect:

Corner cutting
When filament is dragged round a corner it likes to take a short-cut. This depends on how elastic the filament is and how much it is being stretched. I think when the nozzle moves in a circle the filament is continually trying to cut the corner and ends up forming a smaller diameter circle. I think this is the dominant effect on my machines.

Obviously, if you lie to Skeinforge about how wide your filament is that will make holes even smaller, but that is just a calibration problem.

Ideally all these effects should be compensated for in the slicing software but what has happened instead recently is that people are using parametric values in OpenScad to tweak the holes to come out right on their machines. That is the wrong approach because when the holes comes out smaller than they should be, without the slicing software compensating for it, then the infill doesn't meet it as tightly as it should do.

When I started printing Prusa Mendel parts I found the values in the configuration file far too big. I have also noticed this when downloading some designs from Thingiverse. That implies that my holes shrink less than a lot of other peoples, which is odd because all the effects above don't depend on the machine, apart from segment  pausing.

Some of the holes in Josef's parts are octagonal. That made me realise that polygons with low vertex counts don't shrink. The inside of the hole is defined by straight lines and they get extruded in the correct place. What does happen though is that the corners of the polygon are rounded. As long as the polygon has a small number of vertices, the corners are far enough from the circle that they can be rounded without impinging on it. The ideal number of vertices is when the corner cutting just meets the circle.

I decided to investigate this using OpenScad. I made a script that generates holes from 1 to 10mm with vertex counts from 3 to 8, 10, 16 and 32. The diameter of the holes is increased to make the polygon edges tangential to the circular hole. I.e. removing the faceting error by dividing by cos(π / n).

difference() {
    cube(size = [95,125,3]);
    for(i = [1:9]) {
        assign(v=[3,4,5,6,7,8,10,16,32][i - 1]) {
     assign(shrink =  cos (180 / v)) {
                for(d = [1:9]) {
                    translate([d * d + 5 - ((v == 3) ? 3 : 0), 13 * i, 0]) 
                         cylinder(h= 20, r = (d/2)/shrink, $fn= v);

I printed the resulting shape on HydraRaptor and used drill shanks to gauge the hole sizes. Not terribly accurate as the shanks tend to be a little smaller than the tip. I inserted the drills in the highest vertex count hole that it would fit in.

A pattern emerged that the seemed to indicate the maximum number of vertices you can have before the hole shrinks is twice the hole size in mm. The only drill I couldn't fit was the 1mm drill because you can't have a polygon with only two sides. The "1mm" triangular hole did at least leave a hole though, whereas higher polygon counts fill in completely.

To test this simple rule I made a new shape with holes from 1mm to 10.5mm in 0.5mm steps with the number of vertices set to twice the diameter and the diameter increased by cos(π / n).

module polyhole(h, d) {
    n = max(round(2 * d),3);
        cylinder(h = h, r = (d / 2) / cos (180 / n), $fn = n);

difference() {
 cube(size = [100,27,3]);
    union() {
     for(i = [1:10]) {
            translate([(i * i + i)/2 + 3 * i , 8,-1])
                polyhole(h = 5, d = i);
            assign(d = i + 0.5)
                translate([(d * d + d)/2 + 3 * d, 19,-1])
                    polyhole(h = 5, d = d);

I found that all my drills bigger than 1mm fit. The large ones are a snug fit and the smaller ones a little loose, probably because with only a few tangential points touching there is little friction.

These two tests where done on HydraRaptor extruding 0.375mm filament from a 0.4mm nozzle. I printed this the test again on my Mendel with 0.6mm filament through a 0.5mm nozzle and the drills still fit, so it seems universal, at least amongst my machines. It would be interesting to see if others get the same result, so I have put the files on Thingiverse.

My goal is to work out how to print circular holes the correct size, but this seems like a good hack for OpenScad designs to allow holes to come out the right size, regardless of the printer or whether it compensates hole diameters. For example, one would expect circular holes to come out right on a professional printer, so if you have oversized circular holes in your model they will come out too big. However, if you use these low vertex count polygonal holes they should still come out the right size as one would also expect a professional printer to print polygons at least as accurately.