Skip to content

$slop used incorrectly for threading and screws, or $slop doesn't work at small scales #1679

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
coryrc opened this issue May 11, 2025 · 36 comments
Assignees

Comments

@coryrc
Copy link
Contributor

coryrc commented May 11, 2025

Describe the bug

Following the $slop calibration does not result in properly-sized holes for #6-32 holes or M7 nuts.

I have a Bambu A1 Mini, using PETG, and am printing some self-tap and clearance holes for #6-32 screws. I have the following diameters:

$slop self-tap dia self-tap measured clearance dia clearance measured
0.00 2.94 unk 3.91 unk
0.04 3.1 ~3.0 unk unk
0.08 unk unk 4.23 3.9
0.22 3.81 3.67 4.79 4.45

In both cases, the calibrated $slop value resulted in holes far too big.

Yesterday I printed the slop tester and calculated 0.22 for slop. Using the raw threading.scad and with a printed M7 buttress thread and $slop = 0.22, I created working nut and screws printed vertically. Some numbers from that print:

$slop nut innermost diameter nut innermost measured
0.00 5.53 unk
0.22 6.38 6.22

However this just happened to work, because the tol_gap for a normal M7 in the screws.scad library would be about 0.8, which is passed to screw() as shaft_undersize=-0.8 so a normal fit would be 6.33mm innermost diameter and setting $slop = 0.22 coincidentally got a working value. (The threading.scad library does not have any tolerance adjustment besides $slop). Had I correctly compensated diameter for fit, then the nut would have been far too large.

This also resulted in holes too big having followed the calibration procedure and applying it.

Code To Reproduce Bug

module clamp_block() {
    diff() cube([1.9,6.5,12],anchor=BOT+RIGHT) {
        position(TOP+RIGHT) cube([2,6.3,1.9], anchor=TOP+LEFT);
        tag("remove") up(tapping_hole_z) position(BOTTOM) screw_hole(screw_info("#6-32"), tolerance="tight", l=10, orient=LEFT, $slop=0.22);
    }
}
module tapping_hole() {
    screw_hole(screw_info("#6-32"), tolerance="self tap", l=10, orient=LEFT, $slop=get_slop()/2);
}

// Has #6-32 Clearance hole
translate([-8.8,1.3,0]) recolor("blue") clamp_block();
// Has #6-32 tapping hole
difference() {
    translate([-5.7,1.3,0]) flatten_block();
    translate([-7,1.3,4]) tapping_hole();
}
// M7x1.0 Buttress-threaded nut
fwd(18.6)
buttress_threaded_nut(nutwidth=10,id=7,h=6,pitch=1,shape="square",orient=DOWN,anchor=BOT, $slop=0.22);

Printed in PETG, 0.2mm layer, 0.4mm nozzle.

Expected behavior

Following the documentation at https://github.com/BelfrySCAD/BOSL2/wiki/screws.scad and https://github.com/BelfrySCAD/BOSL2/wiki/threading.scad should yield holes with the intended diameter, or at least warn when the instructions are incorrect for certain edge cases.

Additional context
Add any other context about the problem here.

  • OpenSCAD Version: 2025.02.19 (git 91070a09f)
  • Other libraries used: BOSL2 master downloaded 2025-2-23 I believe
@adrianVmariano
Copy link
Collaborator

That $slop value of 0.22 is huge. I have used 0.05 on my Prusa mk3s. And with the screws in screws.scad, they already have clearance created by the screw tolerances. Whether the slop tester correctly predicts the slop, well, that I don't know. It could be that at different sized holes, and especially for small circles, the printer's over-extrusion is not the consistent. However, when I printed the slop tester, it clearly indicates that 0.05 is where I get a slip fit. At 0.2 it's a very sloppy, loose, fit.

It does appear that the slop tester isn't consistent with how screw sizing is done, because if I'm reading the code right, it creates a 2*slop adjustment to the hole width where as the screws code does it to the radius.

@coryrc
Copy link
Contributor Author

coryrc commented May 11, 2025

It could be that at different sized holes, and especially for small circles, the printer's over-extrusion is not the consistent.

I think so. I'm going to make something to measure this on my printer and share it soon.

It does appear that the slop tester isn't consistent with how screw sizing is done, because if I'm reading the code right, it creates a 2*slop adjustment to the hole width where as the screws code does it to the radius.

screws.scad explicitly mentions thread diameter is affected by 4*$slop and clearance/self-tap holes are driven off that measurement. The code takes 4*$slop and applies it to internal holes, though I can't see how it affects the call to threaded_rod() that follows. You added the 4*$slop in this PR, but I can't find the motivation or why 4* was chosen.

The slop tester is a square and not a circle, which might also make it worse.

@adrianVmariano
Copy link
Collaborator

Maybe @revarbat can comment on this, since he's the one who designed the $slop system. I'm pretty sure that I followed his guidance in how $slop behaved for screws.

What do you mean about "how it affects the call to threaded_rod"? All the threaded_rod calls apply $slop if internal=true.

There's the other question which is: is your printer really so bad that you get a snug fit on the tester with $slop=0.22? Why would overextrusion be different for circles than squares? Unless the tight fit you get is entirely a result of extra overextrusion in the corners?

@coryrc
Copy link
Contributor Author

coryrc commented May 12, 2025

What do you mean about "how it affects the call to threaded_rod"? All the threaded_rod calls apply $slop if internal=true.

Uh, right, I forgot. So non-threaded measurements -- clearance/tap holes and shanks, shoulders, and heads -- use 4*$slop because they all use islop which is set as 4*get_slop(), but the threads use 2*get_slop() because threading.scad calculates it itself.

I would think they should be the same if you were, as in my case, intending to use a metal machined screw with fairly tight tolerances; but with your low slop value it may not have been noticeable.

There's the other question which is: is your printer really so bad that you get a snug fit on the tester with $slop=0.22?

My flow rate is a bit higher than normal (1.045), but it's what was best using the top surface calibration with Orca Slicer. I also inadvertently printed the slop test with random seams which may have added excessive slop; I'm going to reprint and will update and document.

Even so, I updated my chart in the first post. With $slop=0.08 I get exactly the intended clearance hole size. If the clearance hole was using 2*get_slop() instead of 4*get_slop(), then the appropriate slop would be 0.16 which is getting pretty close to my "measured" value.

I'm also going to print the following to try to fit a curve to model hole size => actual hole size and whether it is dependent on hole diameter and/or orientation.

include <BOSL2/std.scad>

// Inputs
holes = 8;
start_dia = 0.5;
exponent = 1.75;
$fn=48;

module params() {
    lines = [str("holes = ", holes),
             str("start_dia = ", start_dia),
             str("exponent = ", exponent),
             str("$fn = ", $fn),
             ];
    size = 3;
    union(){ for (i = [0 : len(lines)-1])
      translate([0 , 0, -i * (size + 2) - size ]) text3d(lines[i], 1, size, orient=RIGHT,spin=90, anchor=TOP+LEFT);
    }
}

//params();

// Computations
function hole_dia(index) = start_dia*exponent^index;
function sum(v) = [for(p=v) 1]*v;
function hole_dia_through(index) = sum([for (i=[0:index]) hole_dia(i)]);
// 4mm between hole edges + 4mm on each end
width = hole_dia_through(holes-1) + 4*(holes+1);
// 4mm above and below biggest hole
height = hole_dia(holes-1) + 8;
depth = hole_dia(holes-1)+8;

module test_vertical_cylinders(index, _height=height, on_ground=false) {
    hole = hole_dia(index);
    right(hole/2) fwd(hole/2) cylinder(h=_height,d=hole,anchor=TOP)
        if(hole < (depth-8)/2) position(on_ground? BOT : TOP) fwd(hole+4) cube([hole,hole,2],anchor=on_ground? BOT : TOP);
    if (index>0) right(hole+4) test_vertical_cylinders(index-1, _height, on_ground);
}

fwd(10) up(3) test_vertical_cylinders(holes-1, _height=3, on_ground=true);

module test_horizontal_cylinders(index, _height=height) {
    hole = hole_dia(index);
    echo(hole);
    left(hole/2) up(hole/2) cylinder(h=_height,d=hole,anchor=TOP, orient=FWD);
    if(hole < (height-8)/2) left(hole/2) up(hole*1.5+4) yrot(45) cube([hole,min(_height,3),hole],anchor=FRONT);
    if (index>0) left(hole+4) test_horizontal_cylinders(index-1, _height);
}

//test_horizontal_cylinders(holes-1);

module test_block() {
    diff() cube([width, depth, height]) {
        tag("remove") fwd(4) right(4) position(TOP+LEFT+BACK) test_vertical_cylinders(holes-1);
        tag("remove") up(4) left(4) position(RIGHT+FRONT+BOT) test_horizontal_cylinders(holes-1, _height=depth/exponent);
        tag("remove") down(1) back(1) position(RIGHT+FRONT+TOP) params();
    }
}

test_block();

Image

@adrianVmariano
Copy link
Collaborator

Look more carefully: threading.scad sets the RADIUS to use 2*get_slop() which means the diameter is 4*$slop. There is a guy who posted a thing about "polyholes" where he allegedly worked out a formula for how to produce properly sized holes at different scales, but when I tested it on my printer, it didn't seem to work. A problem with making the slop model more complicated here is that (1) we break existing code in a subtle way and (2) the complicated model may only work for your printer. At least with a simple linear model it's easy to understand and adjust as needed. We need to hear from @revarbat about why the 4 multiplier.

@revarbat
Copy link
Collaborator

In general, you look at the cross section of the object you want to insert into another, and use one $slop for each place they would touch along a given axis. That should give a snug fitting. If you need a loose fitting, you add 2*$slop instead. Since screws need to rotate within their threaded hole counterpart, the diameter of said threaded hole gets adjusted by 4*$slop.

That's the theory, at least. This seemed to work for the large parts of my printable printer (30mm 8pitch), but I never tried to make small (3mm) threaded holes. I always assumed that was beyond the resolution of my printer.

@adrianVmariano
Copy link
Collaborator

What does "snug" mean? I could probably force the test piece together with $slop=0, but I wouldn't be able to get it apart again without a hammer. At 0.05 it slides together easily with no play.

A clearance hole for a screw, if it is to receive a metal screw, would presumably need only two $slop factors, because the metal screws is presumably not oversized. You'd only need the full four factors if you wanted to mate a printed screw with a printed hole. But also, in the case of screws, the objects themselves have built-in clearance. It's not like trying to fit a 5mm object in a 5mm hole.

@coryrc
Copy link
Contributor Author

coryrc commented May 12, 2025

Data

Here are my modeled and measured dimensions with $fn=48:

Modeled Horizontal Hole ID Vertical Hole ID Vertical Cyl OD Horizontal Diamond Side Vertical Square Inside Vertical Square Outside (flats)
0.500 0.5? 0 0.86 unk 0 0.8?
0.875 0.87? 0 1.1 0.73? 0 1.2?
1.53 1.42 0.8? 1.46 1.5 1.3 1.7
2.68 2.5 2.2 2.6 2.5 2.6 2.7
4.69 4.4 4.5 4.7 4.7 4.7 4.7
8.21 8.0 8.0 8.1 8.1 8.2 8.1
14.4 14.2 14.2 14.2 unk unk unk
25.1 24.9 24.9 24.9 unk unk unk
33.1 unk unk unk unk unk 33.1 (Y)
94.0 unk unk unk unk unk 93.8 (X)

Interpretations

Above a certain diameter (~8mm), ID and OD of cylinders/holes shrink a fixed amount (0.2mm). A fixed $slop value would work for all holes and orientations; but we should be adding something to the OD of bolts in screws.scad so the bolts actually match the intended size.

As diameter shrinks, the ID continues to be a fixed amount smaller, but the OD becomes accurate.

As diameter shrinks further, vertical holes go non-linear and collapse (polyholes documents why; I could retry the print after enabling polyholes). Horizontal holes eventually stabilize at an accurate ID (~2mm) down as small as I could see.

Conclusions

It seems $slop as currently implement (a fixed value) is accurate above a certain hole size. I'd like to update the documentation to note that below some hole size it's likely to need tweaking on a hole-by-hole basis, if you all are alright with that.

@coryrc
Copy link
Contributor Author

coryrc commented May 12, 2025

is your printer really so bad that you get a snug fit on the tester with $slop=0.22? Why would overextrusion be different for circles than squares? Unless the tight fit you get is entirely a result of extra overextrusion in the corners?

Your last guess was correct, my corners have significant overshoot like this person. Looking at my collected data, for a 14.4mm round hole my $slop would be about 0.05 just like yours (I can just barely jam my test cylinder into the matching hole with $slop=0).

Look more carefully: threading.scad sets the RADIUS to use 2*get_slop() which means the diameter is 4*$slop.

D'oh. I get it now.

here is a guy who posted a thing about "polyholes" where he allegedly worked out a formula for how to produce properly sized holes at different scales

I see, polyholes and horiholes. So the size and shape of every hole is dependent on diameter, orientation, nozzle width, and layer height. Whew!

That should give a snug fitting. If you need a loose fitting, you add 2*$slop instead. Since screws need to rotate within their threaded hole counterpart, the diameter of said threaded hole gets adjusted by 4*$slop.

I'm sorry, I don't follow why rotating implies an additional doubling.

This seemed to work for the large parts of my printable printer (30mm 8pitch), but I never tried to make small (3mm) threaded holes.

I think this makes sense with the data I collected.

@adrianVmariano
Copy link
Collaborator

I wonder if the slop tester should be modified to have rounded corners on the plug portion.

Yeah, polyholes and horiholes are complicated, and don't seem to be generally accepted practice. It seems like some of what horiholes is supposed to accomplish is done by creating a small corner on the bottom of your horizontal hole. (The hole needs to be teardrop shaped to be printable.) And I also found polyholes uncompelling because for all of the fancy theory behind them, it didn't actually work on my printer.

Also you are getting undersized cylinders. My slop tester is measuring about 10.03mm x 10.00mm, so I'm not seeing that undersizing that you are. For larger objects you are getting the same size for both holes and cylinders. Is this due to PET shrinkage? My print is in PLA. I have no clue how different materials may vary with respect to printing accuracy.

We haven't yet heard from @revarbat about what a "snug" fit is. If a snug fit means that you can insert the part while encountering a small but nonzero resistance then that would be too tight for screws. Rotating means loose enough to move freely. But the whole screw business is complicated by the existence of a separate tolerance system for screws. You only need screw related parts to print at their exact modeled size, not to print with extra clearance, because clearance is built in already. There's also the issue of mixed materials that I previously noted, where a clearance hole gets 4*$slop but doesn't need it because it's mating to a metal screw that is correctly sized.

Another point: if you get a snug fit at $slop=0.2 you presumably don't need a 0.4 clearance for a freely turning fit. Probably 0.25 would suffice. The use of doubling to capture that seems questionable.

If you would like the either submit updates to the documentation, or perhaps an updated slop test fixture, I would welcome either one. But it does seem important to clearly identify the story here, as it's not clear that your printing experience matches mine. Perhaps you avoid absolute statements about the behavior of holes---maybe other printers are different than yours---but draw attention to the possibility that things could get messy when the holes are small. Does material make a significant difference? Might be interesting to include a test fixture for vertical and horizontal holes that people could test with drill bits---probably would need a metric and USA version. Also holes should use circum=true which doesn't matter at high $fn but would for smaller $fn, which will probably be used in practice.

@revarbat
Copy link
Collaborator

The term "snug" is for this purpose defined as "As snug as the fit of the plug in your $slop test print when you have it inserted into the hole corresponding to your chosen $slop value." ie: it should be insertable without applying high pressure, and it should be removable without breaking.

@adrianVmariano
Copy link
Collaborator

But "snug" is tighter than desired for screws?

@revarbat
Copy link
Collaborator

revarbat commented May 13, 2025

The theory is that the screw hole should be increased by 2*$slop for BOTH sides, as that will make it loose enough that you can screw in your screw without breaking your screw head off along a layer.

(Assuming both a printed screw and screwhole.)

@revarbat
Copy link
Collaborator

The concept of making a hole with plastic that can be screwed into with a metal bolt, having its threads biting into the plastic, is not (AFAIK) addressed by $slop, or by tolerances in the threading library at all.

@revarbat
Copy link
Collaborator

if you get a snug fit at $slop=0.2 you presumably don't need a 0.4 clearance for a freely turning fit. Probably 0.25 would suffice. The use of doubling to capture that seems questionable.

I have no idea about smaller parts, but the 4x was what worked for making my 30mm diameter 8mm pitch lifter rods in my printable printer.

@adrianVmariano
Copy link
Collaborator

What was your $slop value? Was it as large as 0.2?

@revarbat
Copy link
Collaborator

My $slop value for the printer I had at the time, was exactly 0.2.

@adrianVmariano
Copy link
Collaborator

The concept of making a hole with plastic that can be screwed into with a metal bolt, having its threads biting into the plastic, is not (AFAIK) addressed by $slop, or by tolerances in the threading library at all.

I thought he was mostly interested in clearance holes. But yes, this issue is addressed by an ad-hoc adjustment to the hole size. so the one exception to the case of exact sizing with tolerances.

@adrianVmariano
Copy link
Collaborator

adrianVmariano commented May 13, 2025

Suppose you had a printer that had horrible but very accurate over-extrusion so every hole was 1mm undersized. The slop tester would tell you you needed 0.5mm of adjustment for a snug fit where it applies double the slop. But four times that slop value---2mm---for a sliding fit is going to be ridiculous. For a sliding fit you need something like .6mm of adjustment. The extra amount needed is not proportional to the error due to overextrusion. It's additive.

@revarbat
Copy link
Collaborator

I was considering whether we could calculate a slop based on hole size, but I believe over-extrusion on small holes will be a combination of hole vertex count, extrusion rate, print controller speed, and GCode queue saturation / print stutter. Basically, I think it's too complex to make a simple correction for this.

@coryrc
Copy link
Contributor Author

coryrc commented May 13, 2025

Perhaps you avoid absolute statements about the behavior of holes---maybe other printers are different than yours---but draw attention to the possibility that things could get messy when the holes are small.

That's exactly what I'll make a PR for.

Also you are getting undersized cylinders. My slop tester is measuring about 10.03mm x 10.00mm, so I'm not seeing that undersizing that you are

I think vertical cylinders are expected to be undersized unless using slicer compensation (I'm not). The cubic slop tester plug I printed measures 14.94 x 14.94mm on the flats using my cheap digital calipers. I haven't calibrated for shrinkage, but I read PETG is about the lowest.

The concept of making a hole with plastic that can be screwed into with a metal bolt, having its threads biting into the plastic, is not (AFAIK) addressed by $slop, or by tolerances in the threading library at all.

I thought he was mostly interested in clearance holes. But yes, this issue is addressed by an ad-hoc adjustment to the hole size. so the one exception to the case of exact sizing with tolerances.

I have both clearance and "self tap" holes for my #6-32 machine screw (about 3mm). It so happens that with this filament and printer settings, $slop=0.04 causes the intended-sized hole to be printed for screw_hole()'s tolerance="self tap" (I worked backward from the measured error) I could have also edited the spec returned by screw_info("#6-32") instead, but the end result is the same. It works great! It's a bit tough getting the screw in there straight the first time, unsurprisingly, but the threads are good enough. The clearance hole required $slop=0.08 to print the intended hole size (which, like the self tap, already includes the intended fit adjustments to diameter).

I was considering whether we could calculate a slop based on hole size, but I believe over-extrusion on small holes will be a combination of hole vertex count, extrusion rate, print controller speed, and GCode queue saturation / print stutter. Basically, I think it's too complex to make a simple correction for this.

Agreed. There's no simple adjustment or single additional parameter that can make small holes usefully more accurate. The print-then-adjust loop is much better than complicating the code, I'll just document this.

@adrianVmariano
Copy link
Collaborator

Why are vertical cylinders expected to be undersized? And why wouldn't I expect the slicer to do what's needed to produce the most accurate possible result? My tests was with the out-of-the-box slicer settings, and the error is <0.03mm.

@adrianVmariano
Copy link
Collaborator

@coryrc Do we need to keep this issue open?

@coryrc
Copy link
Contributor Author

coryrc commented May 29, 2025

Up to you, I still plan to make the changes. Here's my updates so far:

  1. I made a different slop tester to avoid bulging corners and scaled it down to 10mm wide to save filament. Turns out, my printer doesn't have bulging corners for walls 10mm long but does for 15mm long, so I didn't prove it was correct. Ugh. Need to print another.
  2. I was wondering if you and @revarbat were going to follow up on

The extra amount needed is not proportional to the error due to overextrusion. It's additive.

Because I planned to incorporate any decision into my PR.

  1. You asked me:

Why are vertical cylinders expected to be undersized?

Without working arc compensation you would expect them to be slightly undersized and I haven't done anything to ensure they are correct -- there's also Arachne and inner/outer order and more that can affect final dimensions. But we're also talking about 0.2mm when line width is over 0.4mm. Are your cylinders exactly as correct as the cube you mentioned?

  1. I think the slop tester is clever and I have been trying to think if there was something clever which could make adjusting the holes work. All I can think up is updating the slop tester to be able to produce round and cubic bits; and both vertically and horizontally, for someone to use if they don't have calipers; but this requires a print for every diameter of hole. Besides offering up the block I used in this earlier comment I don't have a better idea.

@coryrc
Copy link
Contributor Author

coryrc commented May 29, 2025

The concept of making a hole with plastic that can be screwed into with a metal bolt, having its threads biting into the plastic, is not (AFAIK) addressed by $slop, or by tolerances in the threading library at all.

I didn't directly address this before. The purpose of tolerance="self tap" is for metal screws and, on my printer, matched the $slop value (from the corrected slop tester) to get the correct OD. So, at least for me, it is addressed by $slop and the screws library (but not the threading library in this case).

@coryrc
Copy link
Contributor Author

coryrc commented May 30, 2025

I printed an M7 buttress screw and nut to meet actual standards diameter for "standard" tolerance as if 2*$slop was being used (instead of 4*$slop). [0]

The screw works; being buttress thread and riding on flat surface, the layer line transitions can be felt, but it does work just fine as a bolt and nut. I think 4*$slop is too much and is causing unnecessarily-weak components to be produced. I think it should be changed to 2*$slop and if people want loose fit, they should be using either screws.scad for tolerance or manually adjust ID to add tolerance. Additionally, 2*$slop follows the guidance from the documentation on $slop that says each mating surface should have a gap of one single $slop width.

[0] I printed by my M7 buttress screw and nut with $slop=0.05 and increasing the ID of the nut by 0.68mm. If threading.scad was using 2*$slop, that would be equivalent to increasing nut ID by 0.78mm. In my first post, I referenced that "normal" tolerance for M7 nuts, as referenced by screws.scad and actually in the standards docs, would add 0.8mm to nut ID. I also compensated for my undersized cylinder size by increasing the screw OD by 0.2mm and verified with calipers.

coryrc added a commit to coryrc/BOSL2 that referenced this issue May 30, 2025
Incorporating findings from Issue BelfrySCAD#1679

Describing why based on the diff on my screen, starting top to bottom:

Removing XY vs Z axis, because the printing direction isn't known for the parts. Even precise CNC machining still has tolerances and I tried to write a simple way of passing that along.

Adding the limitations we talked about in issue BelfrySCAD#1679.

Added some more written examples of where slop should be added. Now that I'm writing this, these would be better as an example.

I can't add a new line to the first "Calibration" line because that'll make a new number. I thought this was good info to add though.

Moved caveat to Limitations section.
Added line about filleting/chamfers now that I made the tester cut off corners, so you can test both ways.

Also fix a typo later in doc
coryrc added a commit to coryrc/BOSL2 that referenced this issue May 30, 2025
Per [my argument](BelfrySCAD#1679 (comment)), I believe this is the proper method. There is only one mating surface for each radius, so by following the documentation for `$slop`, we should only be adding one `$slop` for radius and not two.
coryrc added a commit to coryrc/BOSL2 that referenced this issue May 30, 2025
Incorporating findings from Issue BelfrySCAD#1679

Describing why based on the diff on my screen, starting top to bottom:

Removing XY vs Z axis, because the printing direction isn't known for the parts. Even precise CNC machining still has tolerances and I tried to write a simple way of passing that along.

Adding the limitations we talked about in issue BelfrySCAD#1679.

Added some more written examples of where slop should be added. Now that I'm writing this, these would be better as an example.

I can't add a new line to the first "Calibration" line because that'll make a new number. I thought this was good info to add though.

Moved caveat to Limitations section.
Added line about filleting/chamfers now that I made the tester cut off corners, so you can test both ways.

Also fix a typo later in doc
coryrc added a commit to coryrc/BOSL2 that referenced this issue May 30, 2025
Per [my argument](BelfrySCAD#1679 (comment)), I believe this is the proper method. There is only one mating surface for each radius, so by following the documentation for `$slop`, we should only be adding one `$slop` for radius and not two.
coryrc added a commit to coryrc/BOSL2 that referenced this issue May 30, 2025
Per [my argument](BelfrySCAD#1679 (comment)), I believe this is the proper method. There is only one mating surface for each radius, so by following the documentation for `$slop`, we should only be adding one `$slop` for radius and not two.
@adrianVmariano
Copy link
Collaborator

No, 2*$slop does not follow the guidance. Or rather, it follows the guidance assuming you want a "snug" fit, which would mean that the parts don't turn easily. There are two mating surfaces for each radius, one on each side.

"When making your own parts, you should add $slop to both sides of a hole that another part is to fit snugly into. For a loose fit, add 2*$slop to each side."

If I had to guess I'd say lots of people probably fiddle with $slop until the model fit is good. And changing it now from 4 slops to 2 slops is going to break everybody's code, so that's a concern.

@coryrc
Copy link
Contributor Author

coryrc commented May 30, 2025

No, 2*$slop does not follow the guidance. Or rather, it follows the guidance assuming you want a "snug" fit, which would mean that the parts don't turn easily.

As I noted above, I printed my M7 nut with normal tolerance (0.8mm increased ID) and it worked fine with 2*$slop. You can always increase the diameter and make it easier to turn, but that reduces strength, which is harder to detect and measure.

There are two mating surfaces for each radius, one on each side.

I don't understand -- if you took a bolt in a nut and sliced it through top and bottom, you could draw a single path up each side, so there's only one mating surface per radius and two mating surfaces per diameter.

"When making your own parts, you should add $slop to both sides of a hole that another part is to fit snugly into. For a loose fit, add 2*$slop to each side."

I thought you were making the argument that is the wrong thing to do? I was persuaded.

And changing it now from 4 slops to 2 slops is going to break everybody's code, so that's a concern.

That's true, but as the main page says it's still beta code, I think it would be worth it to fix now if it's decided it's wrong.

@adrianVmariano
Copy link
Collaborator

It seems easy to get confused here about the nomenclature. It doesn't really make sense to talk about surfaces "per radius" or "per diameter". If you look at a cross section of a cylinder fit into a hole there are four surfaces that mate, two on the inner cylinder and two on the hole.

Yes, I did make an argument that Revar's strategy is wrong, because it should be 2*$slop for a snug fit and 2*$slop+$extra for a loose fit. This is a more complex formulation. It's not clear that $extra is scale independent. (Well, or $slop either when you get down to it.) But it's a second parameter. You took my statement and threw out the $extra parameter. So you aren't dong what I said.

We are trying not to break things too much if we can avoid it right now, and since the screws stuff is about 3 years old and a lot of people use BOSL2 just for the screws, I think it's a significant concern to break all outstanding code.

@coryrc
Copy link
Contributor Author

coryrc commented May 31, 2025

In almost all cases 4*$slop "works", in that using the matching nut and screw from screws.scad will mate, but will get proportionally tighter as diameter increases (hence why 4*$slop worked for Revar for a 30mm thread with a larger slop value of 0.20) and will be proportionally looser than intended at small hole sizes. And that means weaker than intended, which is a lot harder to detect than tighter to turn.

@adrianVmariano
Copy link
Collaborator

I would argue that a too-loose result doesn't really count as "working". I'm not sure what your point is, though---that it's OK to break all existing code because overly tight threads are easy to detect? Are you imagining that all the extant code features threads that are too loose and this will be improved by reducing the 4 to 2? When I printed threads I selected $slop by testing MY THREADS not using the slop tester, and I would imagine that others have done that as well.

@coryrc
Copy link
Contributor Author

coryrc commented May 31, 2025

I'm not sure what your point is, though

Ideally I should be able to calibrate a $slop value for my material and print settings, then use an Openscad model using BOSL2 and expect it to print the same, even if the creator's $slop value was much higher or lower than mine.

For the following model and all the threaded rods and nuts should mate with each other with the same overlap and the cubes should fit snugly in each other's sockets, even for widely-varying slop values. For example, issue #1485 shows 0.0, 0.10, and 0.15 for slop values for 3 filaments on the same printer; the bolts are all going to be looser in the third nut than the first nut, but with 2*$slop we would expect the same fit in all three. With the cubes, we should expect all to fit into each other the same way, because each mating surface has only one slop adjustment.

buttress_threaded_nut(nutwidth=10,id=7.8,h=6,pitch=1,shape="square",orient=DOWN, anchor=TOP);
right(20) buttress_threaded_rod(d=7,l=17,pitch=1,anchor=BOT);
left(20) cube(10, anchor=BOT);
left(40) diff() cube(15, anchor=BOT) tag("remove") position(TOP) cube(10+2*get_slop(), anchor=TOP);

This doesn't work if the reason for slop is due to oversized plug parts or if the holes are too small (as documented in this issue and in #1699 ).

When I printed threads I selected $slop by testing MY THREADS not using the slop tester

You shouldn't have to do that, and I think you wouldn't, except for the documented caveats, if we fixed this now.

@coryrc
Copy link
Contributor Author

coryrc commented May 31, 2025

Are you imagining that all the extant code features threads that are too loose and this will be improved by reducing the 4 to 2?

For anybody who blindly followed the $slop instructions (like I tried to originally) and used modules from screws.scad, then the answer is yes.

When I printed threads I selected $slop by testing MY THREADS not using the slop tester, and I would imagine that others have done that as well.

It's possible for you and me and others to be broken -- this is a breaking change. At the very least screws will be tighter than before, some to the point they may not work.

But if we don't expect a global $slop value to work well and you're required to tweak it for every usage, then why have it as a special variable and have a slop calibration tool?

@adrianVmariano
Copy link
Collaborator

This is Revar's infrastructure, not mine. As I've noted, the notion that you get a snug fit at 2*$slop and a loose fit at 4*$slop seems wrong. Handling both cases properly seems to require two parameters. But maybe the clearance to go from snug to loose doesn't belong in this infrastructure at all. It seems like two different issues are conflated here. The way it's described, the purpose of $slop is to manage printer overextrusion, but also, clearance is required in any situation where parts need to fit together. And it seems like Revar is trying to do both with one parameter.

It seems to me that the real way to handle printer overextrusion is in the slicer, not in the CAD model. And if the goal is to just manage overextrusion, then the correct setting would be when the hole is exactly 1 cm wide. That seems to happen for me with $slop=0 in the Y direction, but my hole is slightly undersized by 0.04 in the X direction, at least on my old slop tester print.

A reason to have $slop as a global $variable independent of universality is that you can adjust screws (or other things) that are 12 levels deep in your model. Otherwise you have to explicitly propagate that information all the way down through the hierarchy. In fact, I've been pondering the user of teardrop for screw holes and how I need to introduce $ variables to give more control over them.

The old slop tester gives me a slip fit at 0.05 with very little play. It took me a while of fiddling to realize that the play was not zero. I do usually start with $slop set around 0.05. My expectation is that if I cut the slop values in half for screws like you are effectively suggesting, none of my test cases are going to go together at all. I took my diamond threading example from the docs, which has a slop value of 0.075 and divided it in half and printed it. The resulting model is totally unusable---too tight for the nuts to engage at all. The jammed and immediately and I can't get them to advance or come off (without tools). This is the likely result of the change you are proposing: a bunch of working models are going to be rendered unusable.

Since I had 0.05 from the old one it seemed like I didn't really know the right slop value, so I printed it in 0.01 increments. Note that to include a cylinder version you should have a global variable that controls it, not tell the user to comment and uncomment code. With the new rectangular tester I found a $slop value from that test of 0.01. However...the male end of the slop tester is undersized, being 9.92 mm x 9.97 mm. My old one is 9.98 mm x 10.03 mm. If I insert my old one it fits snugly but without a struggle into the 0.03 hole on the new tester.

@revarbat
Copy link
Collaborator

revarbat commented Jun 2, 2025

It's not just over-extrusion that slop was for. Some printers are inexact at layer-to-layer alignment, too.

The way slop was derived goes something like this:

  • I designed my idea of a "printable" 3D printer, that would have to be printed in parts that would be assembled together.
  • I noticed that mating parts I designed would not fit together when printed, even though they theoretically should have.
  • I made a part with holes in it with slightly different sizes, and a plug to fit into the holes. That became the slop calibrator.
  • I found the hole that the plug fit into, given my specific printer, was enlarged by 0.4mm in the X and Y dimensions.
  • I redesigned my parts to have a $slop factor added for each wall interface, for a "snug" fit. I set $slop = 0.2;
  • I printed new parts using the slop factor, and they fit together snugly.
  • I designed lifter screw rods for my Z axis, and found that the snug fit added way too much friction for use.
  • I experimented with the lifter screw rods a bit to find that I needed to use twice the slop value for a loose rotating screw.

At no point did I ever really analyze why slop was needed, or if the size of the hole affected the slop needed. I just experimentally found that for what I was doing, I had to add slop to make parts fit.

@coryrc
Copy link
Contributor Author

coryrc commented Jun 2, 2025

I took my diamond threading example from the docs, which has a slop value of 0.075 and divided it in half and printed it. The resulting model is totally unusable

It should be. If I made it out of metal, it probably would not work either. The design is bad because threading.scad does not include any tolerances related to allowing threads and nuts to work together.

Another problem is threading.scad uses 4*$slop because sometimes you can print workable threads and mating parts from it, but screws.scad has its own, industrially-proven, standard system for making workable threads and then 4*$slop is added on top.

So is threading.scad supposed to create threads accurate to what you are asking for or is threading.scad supposed to create threads which travel freely with a mating nut with the exact same pitch diameter and only on the same printer? If it's the former, it's not doing that.

If it's the latter, the former still seems like something you would want to have, for reasons including making parts which mate with precision metal parts and work with parts printed across printers. And for the purposes of the latter, is 4*$slop better than 2*$slop + using the a tolerance table?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants