adrianschlatter / threadlib

thread library for OpenSCAD
BSD 3-Clause "New" or "Revised" License
351 stars 34 forks source link

specifying bolt by length #39

Closed nohkumado closed 1 year ago

nohkumado commented 4 years ago

hello, modified a bit the bolt module to be able to specify the bolt by length: module bolt(designator, turns = 5, higbee_arc=20, fn=120, table=THREAD_TABLE, h = -1) { name = str(sanitize(designator), "-ext"); union() { specs = thread_specs(name, table=table); P = specs[0]; Dsupport = specs[2]; H = (h >0)? h: (turns + 1) * P; thread(name, turns=(h >0)?H/P-1:turns, higbee_arc=higbee_arc, fn=fn, table=table); translate([0, 0, -P / 2]) cylinder(h=H, d=Dsupport, $fn=fn); }; };

its in my tree... don't know if its any use to make pull requests?

nohkumado commented 4 years ago

made the same modification to nut in the meantime...

adrianschlatter commented 4 years ago

Please do not add new features / issues to an existing pull request. This is more confusing than helpful.

I understand that specifying length instead of turns is a desired feature. So far, I didn't see an elegant solution: Defining bolt2(designator, length, ...) has maintenance issues (see #32). Your approach does not have that problem but it's also not very elegant. Writing bolt("M8", turns=5, length=0.3) is perfectly correct syntax but will not work correctly.

I'm considering a solution like this:

bolt("M4", turns=0.3, unit="length")

Another (code-incompatible) solution would be:

bolt("M4", length=5, unit="turns") bolt("M4", length=0.3, unit="length")

nohkumado commented 4 years ago

well the last one would be my preferred one :D even indeed i breaks existing code....

adrianschlatter commented 4 years ago

I've been thinking a little more about that feature. I still believe that specifying bolt and nut lengths would make sense. The question remains: What about the thread() module?

The Length Problem

A logical approach would be to calculate turns = length / P. That would not be useful, however. Usually, a thread will be attached to some support. Usually, the length of that support is known and the length of the thread is derived from it (not the other way around). A thread using the length of the support would not fit onto a support of the same length. The length of the thread should be a little less than the length of the support. "A little less" means approximately one pitch. And looking up the pitch is exactly what we want to avoid. User code would not get simpler or shorter.

A more useful but a little counterintuitive approach is to calculate turns = length / P - 1. That way, the thread will fit onto the support. It could happen that the thread just touches (on one side or both sides) the end of the support. But usually - for thread-types with crest centered in pitch-length - one "valley" remains free on both sides. The user that wants to add a little more space either adds it as a length (mm, inches, whatever) or as a number of turns. In the latter case, she will again have to look up the pitch. But I guess the former will be good enough in many cases and will avoid this lookup => simpler and shorter user code.

What makes this approach a little more counterintuitive is the name of the argument (which I can't change without breaking backwards compatibility): thread("M4", turns=3.2, units="length").

User code would then look like this:

// make my own bolt:
L = 0.3;

specs = thread_specs("M4-ext");
P = specs[0];
Dsupport = specs[2];
translate([0, 0, +P / 2])
    thread("M4-ext"), turns=L, units="length");
cylinder(h=L, d=Dsupport);

Whoops: We still have to look up thread specs! We need to know the diameter of the support and we still need to know the pitch so that we can translate by half a pitch (otherwise, it would overlap the end).

The Half-Pitch Problem

The solution is ugly: thread("M4-ext"), turns=L, units="length", shiftByHalfPitch=true)

Alternative: break backwards compatibility and shift by P/2 by default.

The Support-Diameter Problem

A thread needs a support. To get the proper diameter, I need to look it up ...

An elegant solution could be something like this (would solve the P/2 problem as well):

P, Rrot, Dsupport, profile = thread("M4-ext"), turns=L, units="length");
translate([0, 0, -P / 2])
    cylinder(h=L, d=Dsupport);

This would require a new language feature in OpenSCAD that allows modules to not only create an object but to return values as well.

Conclusions

Providing length support for thread() module is utterly useless.

If we go for a length feature, it will be used in bolt() and nut() exclusively, or it will be added to thread() as well but then simply to remain consistent, not because it is useful.

adrianschlatter commented 4 years ago

I just realized that I have never used bolt() or nut() in my own parts. They were always special enough to warrant the use of thread(). To make sure we do not miss something: Can someone provide real examples where bolt() or nut() was used to build a part?

nohkumado commented 4 years ago

Hello Well since i was dabbling with your lib anyway, i implemented your (legacy breaking) version and used it here:

https://github.com/nohkumado/spulenhalter/blob/master/files/Spulenhalterschraube.scad

I also use it in my garden stuff (that's why i needed the british imperial thread, still uurrrggghh....) should be alsi somewhere on git.....

And i am migrating my other stuff to it ..... Will have to look into the tapering stuff though prior to that...

ciao

Bruno Böttcher

35 rue de la république, FR-6720 Schwindratzheim email: bboett@adlp.org, mobile:bboett@gmail.com Fon:+33 3 88 89 91, Mob:+33 6 76 55 82 68

Dev: Java/Perl/PHP OS:GNU/LINUX, Android

Adrian Schlatter notifications@github.com schrieb am Fr., 12. Juni 2020, 12:27:

I just realized that I have never used bolt() or nut() in my own parts. They were always special enough to warrant the use of thread(). To make sure we do not miss something: Can someone provide real examples where bolt() or nut() was used to build a part?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/adrianschlatter/threadlib/issues/39#issuecomment-643198937, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADR5CZ5LS5VN2T2RF6ISV7LRWH7HRANCNFSM4NZK6YWA .

adrianschlatter commented 4 years ago

Thanks for your example code. As far as I can see, you would really get rid of the call to thread_specs() if nut() is extended to support a length argument.

However, you have hard-coded the "aussenradius" which is actually pretty much what thread_specs() returns as Dsupport. In that sense, you did indirectly need that call to thread_specs(). You would have the choice of removing the argument "aussenradius" of module "mutter" (and look it up via thread_specs() instead) or removing the call to thread_specs() (keeping the argument that has to be looked up manually to match the thread).

I have the impression that efficient use of a length argument is significantly hampered by limitations of OpenSCAD (see Support Diameter Problem in my previous post).

bvarner commented 4 years ago

Since you asked for examples of using bolt() to produce parts....

When converting from the 'threads.scad' that Prusa used in their printer designs (and I subsequently used...) all of my parts assume 'bolt' type interactions. Also, I've used that module extensively for literally printing bolts. I think the recommendation to place length-based code into the bolt() functions is exactly what needs to happen, and should be doable in a backwards compatible manner, without making the user code of the bolt() module yicky.

adrianschlatter commented 4 years ago

Can you provide these examples? Can you comment on my summary of the situation I have provided above?

Since you asked for examples of using bolt() to produce parts....

When converting from the 'threads.scad' that Prusa used in their printer designs (and I subsequently used...) all of my parts assume 'bolt' type interactions. Also, I've used that module extensively for literally printing bolts. I think the recommendation to place length-based code into the bolt() functions is exactly what needs to happen, and should be doable in a backwards compatible manner, without making the user code of the bolt() module yicky.

bvarner commented 4 years ago

I just realized today they're using openscad-threads! (which is at least twice as slow at creating comparable high-res thread profiles)

I have many parts that render 'taps' -- or a positive representing the internal threads, then removing the material with difference. I commonly do this if I don't have an actual tap for that thread type or size.

Here's a few (horrible) examples: https://github.com/bvarner/bricabrac/blob/master/plumbing/Threaded_Barbed_Tee.scad https://github.com/bvarner/bricabrac/blob/master/plumbing/latex_hose_connector.scad

A few better ones: https://github.com/bvarner/bricabrac/blob/master/hydroponic_rig/PVC_Inlet_Cleanout.stl https://github.com/bvarner/bricabrac/blob/master/hydroponic_rig/PVC_Drain_Cleanout.scad