AM
Adrian Mariano
Sun, Nov 3, 2024 2:28 PM
Here's a bit on the subtlety of the Hirth joint. I thought (like many
others, I suspect) that you could just create a triangle, stand it up
vertically, center it and scale it in the direction of the origin to create
the joint. But if you do this, you run into issues with mating between the
two halves of the joint that are quite obvious if the tooth count is low.
In order for the joints to mate, they have to touch at their half-way
points (which are on the XY plane in this construction). That constrains
the size of the triangle based on the other joint parameters. But if you
form the simple construction I described, you get these triangles, where
red is the bottom part and green is the top part. They are touching at the
triangle midles, but nowhere else. And furthermore, the triangles for one
joint don't meet at their corners!
[image: image.png]
To solve this problem, you need to rotate the triangle bottoms inward until
their vertices meet. That produces this set of triangles:
[image: image.png]
From here you can sweep the triangles toward the origin to make the joint.
But it's not in the direction of the normal to the triangle, since the
triangle bottoms were shifted inward by the rotation. The more teeth
you add, the smaller this effect becomes. It depends on how close to 2 you
get with the ratio of tan(180/n) to tan(90/n). So for large numbers of
teeth it doesn't make much difference.
Note also that Sanjeev posted a case with an asymmetric tooth shape. I
don't know how to do the general case, but if you have a right triangle
like he showed, then it appears that everything will work with
appropriately scaled vertically positioned triangles---no funny tilt
required.
On Sat, Nov 2, 2024 at 9:38 AM Adrian Mariano avm4@cornell.edu wrote:
Ray, I tried out your code and ran into numerous problems. It is super
slow to preview. You don't give a convexity argument so stuff is missing
in preview. Render fails with a bunch of errors, perhaps due to the
reversed faces. So I can't really look at the shape very well. I tried
setting the tooth count to 5 and it gets really weird. My suspicion is
that you fell into the same trap that I did in not recognizing the subtlety
of the face spline design, but I can't be certain.... Or maybe you don't
care if it fits accurately--could be that the modeling errors in question
aren't a major source of error at high tooth count. Note that EVEN the
case of two symmetric parts is rather tricky to get right. I didn't
realize this at first. A fully correct implementation will let someone
make a 5 tooth design that could be used to set a mechanism at fifth of a
circle angles, for example.
With regards to terminology, my main reason for asking the question about
other face splines is that I'd call this module in BOSL2 face_spline(),
except that if there are 4 other kinds of face spline then that could be
confusing, in which case perhaps it should be hirth() which is more
obscure.
On Thu, Oct 31, 2024 at 8:01 PM Raymond West via Discuss <
discuss@lists.openscad.org> wrote:
Hi Bob,
Here's the basic code for a parametric Hirth Joint. Spring loaded often
use as a slip clutch in torque sensitive situations, e.g screw drivers,
tapping heads, etc. Larger scale high speed turbines for shaft
connections, since easy to balance, no windage, etc. I've tested as
saving as stl, and re-importing, gives no errors. Easy enough to cut out
the centre teeth if you don't want them.
// clutch.scad
ind= 50; // overall diameter
num= 20; // number of teeth
back = 6; //thickness of back
////////////////////////////////////////////
diam= ind/cos (180/num); // bigger to allow for chords
chord = diam*sin(180/num);
ridge= chord *sqrt(3)/3; // or set to whatever (denominator = 2 for 60
degrees.)
points=[
[0,0,ridge/2],
[diam/2,-chord/2,0],
[diam/2,+chord/2,0],
[diam/2,0,ridge]
];
faces=[
[0,1,2],
[0,1,3],
[0,2,3],
[1,2,3]
];
module wedge(){
polyhedron(points,faces,convexity=10);
}
//rotate wedge
intersection(){
translate([0,0,-back])
cylinder(d=ind,h=200,$fn=100);
union(){
for (j=[0:1:+1+360/num])
rotate([0,0,j360/num+0.5360/num]) wedge();
cylinder(d1=diam,d2=0,h=ridge/2,$fn=num);
translate([0,0,-back])
cylinder(d=diam,h=back,$fn=num);
}
}
//save as stl, then import to check for valid stl. (remove comments
below and run again)
/*
translate([0,0,6])
rotate([0,180,360/(num*2)])
import("P:/Docs/openscad/clutch.stl");
*/
On 26/10/2024 00:44, Bob Carlson via Discuss wrote:
I got really intrigued by the Hirth joint and have been working a
library entry that would generate them. I have it fully working,
apparently, because it renders perfectly as far as I can see. However when
I load one of the parts (a concave part) into PrusaSlicer, it reports
thousands of errors that it supposedly fixed. The visual rendering is fine,
but when you look at the slice it is completely screwed up.
First some explanation. When I looked up hirth joints I only saw flat
ones mentioned. The one I have actually encountered though is a conical
one. There is a concave part and a convex part. They fit together
perfectly. I had to invent some terminology since I did not find terms for
some things I found to be important. The outer center line is the plane
that passes through the midpoint of the teeth at the outer radius. In a
flat hirth joint all the teeth radiate from the center of this circle, call
it the origin. If the origin of the teeth is above the outer center line,
then joint has a conical shape and the two parts are concave and convex.
Each tooth at every point has the same profile, the top of the tooth
profile is either 60 or 90 degrees. The groove angle is the angle that the
groove forms from the origin to the outer radius. It will pass below (for a
convex part) the outer radius. It’s critical for making hirth joints
because it forms the tool path. The ridge angle is the angle formed by the
corresponding ridge.
If the joint is conical, then there is an inner center line that passes
through the center of the teeth at the inner radius. The tooth height is
the critical number to calculate. It is dependent on the number of teeth,
the profile angle and the inner and out radii. Something that really
complicates the mental gymnastics is that the tooth height is smaller at
the inner radius. My code adds a “base” of extra material at the bottom of
the convex part and the top of the concave part. What’s tricky is
positioning the base of the concave part relative to the inner center line.
The concave parts base is relatively easy to place because it depends on
the outer radius and center line.
I generate the raw teeth using the groove and ridge angles and
spherical coordinates to make two 2d tooth profiles. Then I complete a
tooth using skin(). A for loop generates the full set of N teeth. Then
intersection or difference is used the trim the teeth at the inner and
outer radii. I discovered something at that point, but solved it pretty
simply. When diffing a cylinder from the N teeth, each tooth took up a
small portion of the cylinder being diffed out. I had to raise the $fn on
the cylinder or tube being used so that I got enough points in each tooth
that diff or intersection was accurate. I kept raising it until the results
stopped improving. I ended up with the 16*360 you see in the code.
After I have the raw teeth, I generate a cone that is diffed away to
produce the chamfer at the top of the teeth. Then I add in the base. The
base also adds the “chamfer” at the bottom of the groove. It’s half the
size of the top chamfer to leave a little gap when the parts are joined.
When I comment out the everything but the raw teeth and import the STL
into PrusaSlicer, it reports errors fixed, but appears to slice correctly
when supports are added.
When I add the intersection to trim the raw teeth, the number of
reported errors goes way up.
When I add the diff to remove the chamfer, the number goes way up again.
When I add in the base, the number goes up again and it starts
reporting many open edges.
Throughout, OpenSCAD reports no errors. Using $fn at 16*360, manifold
renders in 4+ seconds. At 32*360, it’s 53+ seconds. I did check CSG and it
did not help.
Maybe the biggest hint is that the convex part uses almost identical
code, but produces no errors. Very weird.
So, is this an OpenSCAD problem? Or something in my code?
It’s also possible that my math is off somewhere. My formal trig
training was 60 years ago. However I doubt a math error is responsible for
the slicing problem and STL errors.
-Bob
include <BOSL2/std.scad>
include <BOSL2/structs.scad>
// Number of Teeth
_n = 36; // Number Of Teeth
// Inner Radius
_ir = 30;
// Outer Radius
_or = 50;
// Is the coupling conical?
_conic = 10;
// Tooth Profile Angle
_profile = 60; // [60, 90]
// Percentage of tooth height
_chamfer = 5; // Default 5%
_base = 1;
$fn = 180;
tiny = 1 / 1024;
hirth_concave();
_irRatio = _ir / _or;
_toothAngle = 360/_n;
_toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2);
_chamferHeight = _chamfer * _toothHeight / 100;
_grooveAngle = atan(((_toothHeight/2) + _conic) / _or);
_ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or);
_innerCenterLine = (1 - _irRatio) * _conic;
_stackHeight = _innerCenterLine + _toothHeight + 2*_base;
_tubeHeight = 2*_conic + 2*_base + 2*_toothHeight;
module hirth_concave() {
zrot(_toothAngle/2)
union() {
difference() {
intersection() {
union() {
for (i = [0 : 360/_n : 359])
zrot(i)
_profileF();
}
tube(ir = _ir, or = _or, anchor = CENTER, l =
_tubeHeight, orient = UP, $fn = 16*360);
}
_chamferF();
zcyl(r = _ir, h = _tubeHeight, $fn = 16*360, anchor =
}
_baseF();
}
} // hirth_concave
module _profileF() {
IR = _ir * .5;
OR = _or * 1.5;
tI = [spherical_to_xyz(IR, 0, _grooveAngle + 90),
spherical_to_xyz(IR, _toothAngle/2, _ridgeAngle + 90),
spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)];
tO = [spherical_to_xyz(OR, 0, _grooveAngle + 90),
spherical_to_xyz(OR, _toothAngle/2, _ridgeAngle + 90),
spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)];
up(_conic)
skin([tI, tO], slices = 0);
}
module _chamferF() {
A = -_toothHeight/2 - .1;
B = -_toothHeight/2 + _chamferHeight;
pts = [[0, _conic],
[_or+tiny, A],
[_or+tiny, B]];
rotate_extrude(angle = 360, $fn = 16*360)
polygon(pts);
}
module _baseF() {
A = _base + _irRatio*_toothHeight/2 + _innerCenterLine;
B = _irRatio * (_toothHeight/2 - _chamferHeight/2) +
C = _toothHeight/2 - _chamferHeight/2;
pts = [
[_ir, A],
[_ir, B],
[_or, C],
[_or, A]
];
rotate_extrude(angle = 360, $fn = 360*16)
polygon(pts);
}
OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org
Here's a bit on the subtlety of the Hirth joint. I thought (like many
others, I suspect) that you could just create a triangle, stand it up
vertically, center it and scale it in the direction of the origin to create
the joint. But if you do this, you run into issues with mating between the
two halves of the joint that are quite obvious if the tooth count is low.
In order for the joints to mate, they have to touch at their half-way
points (which are on the XY plane in this construction). That constrains
the size of the triangle based on the other joint parameters. But if you
form the simple construction I described, you get these triangles, where
red is the bottom part and green is the top part. They are touching at the
triangle midles, but nowhere else. And furthermore, the triangles for one
joint don't meet at their corners!
[image: image.png]
To solve this problem, you need to rotate the triangle bottoms inward until
their vertices meet. That produces this set of triangles:
[image: image.png]
From here you can sweep the triangles toward the origin to make the joint.
But it's not in the direction of the normal to the triangle, since the
triangle bottoms were shifted inward by the rotation. The more teeth
you add, the smaller this effect becomes. It depends on how close to 2 you
get with the ratio of tan(180/n) to tan(90/n). So for large numbers of
teeth it doesn't make much difference.
Note also that Sanjeev posted a case with an asymmetric tooth shape. I
don't know how to do the general case, but if you have a right triangle
like he showed, then it appears that everything will work with
appropriately scaled vertically positioned triangles---no funny tilt
required.
On Sat, Nov 2, 2024 at 9:38 AM Adrian Mariano <avm4@cornell.edu> wrote:
> Ray, I tried out your code and ran into numerous problems. It is super
> slow to preview. You don't give a convexity argument so stuff is missing
> in preview. Render fails with a bunch of errors, perhaps due to the
> reversed faces. So I can't really look at the shape very well. I tried
> setting the tooth count to 5 and it gets really weird. My suspicion is
> that you fell into the same trap that I did in not recognizing the subtlety
> of the face spline design, but I can't be certain.... Or maybe you don't
> care if it fits accurately--could be that the modeling errors in question
> aren't a major source of error at high tooth count. Note that EVEN the
> case of two symmetric parts is rather tricky to get right. I didn't
> realize this at first. A fully correct implementation will let someone
> make a 5 tooth design that could be used to set a mechanism at fifth of a
> circle angles, for example.
>
> With regards to terminology, my main reason for asking the question about
> other face splines is that I'd call this module in BOSL2 face_spline(),
> except that if there are 4 other kinds of face spline then that could be
> confusing, in which case perhaps it should be hirth() which is more
> obscure.
>
> On Thu, Oct 31, 2024 at 8:01 PM Raymond West via Discuss <
> discuss@lists.openscad.org> wrote:
>
>> Hi Bob,
>>
>> Here's the basic code for a parametric Hirth Joint. Spring loaded often
>> use as a slip clutch in torque sensitive situations, e.g screw drivers,
>> tapping heads, etc. Larger scale high speed turbines for shaft
>> connections, since easy to balance, no windage, etc. I've tested as
>> saving as stl, and re-importing, gives no errors. Easy enough to cut out
>> the centre teeth if you don't want them.
>>
>> // clutch.scad
>>
>> ind= 50; // overall diameter
>> num= 20; // number of teeth
>> back = 6; //thickness of back
>> ////////////////////////////////////////////
>>
>>
>> diam= ind/cos (180/num); // bigger to allow for chords
>> chord = diam*sin(180/num);
>>
>> ridge= chord *sqrt(3)/3; // or set to whatever (denominator = 2 for 60
>> degrees.)
>>
>> points=[
>> [0,0,ridge/2],
>> [diam/2,-chord/2,0],
>> [diam/2,+chord/2,0],
>> [diam/2,0,ridge]
>> ];
>> faces=[
>> [0,1,2],
>> [0,1,3],
>> [0,2,3],
>> [1,2,3]
>> ];
>>
>> module wedge(){
>> polyhedron(points,faces,convexity=10);
>> }
>>
>> //rotate wedge
>>
>> intersection(){
>> translate([0,0,-back])
>> cylinder(d=ind,h=200,$fn=100);
>> union(){
>> for (j=[0:1:+1+360/num])
>> rotate([0,0,j*360/num+0.5*360/num]) wedge();
>> cylinder(d1=diam,d2=0,h=ridge/2,$fn=num);
>> translate([0,0,-back])
>> cylinder(d=diam,h=back,$fn=num);
>> }
>> }
>>
>> //save as stl, then import to check for valid stl. (remove comments
>> below and run again)
>>
>> /*
>> translate([0,0,6])
>> rotate([0,180,360/(num*2)])
>> import("P:/Docs/openscad/clutch.stl");
>> */
>>
>>
>> On 26/10/2024 00:44, Bob Carlson via Discuss wrote:
>> > I got really intrigued by the Hirth joint and have been working a
>> library entry that would generate them. I have it fully working,
>> apparently, because it renders perfectly as far as I can see. However when
>> I load one of the parts (a concave part) into PrusaSlicer, it reports
>> thousands of errors that it supposedly fixed. The visual rendering is fine,
>> but when you look at the slice it is completely screwed up.
>> >
>> > First some explanation. When I looked up hirth joints I only saw flat
>> ones mentioned. The one I have actually encountered though is a conical
>> one. There is a concave part and a convex part. They fit together
>> perfectly. I had to invent some terminology since I did not find terms for
>> some things I found to be important. The outer center line is the plane
>> that passes through the midpoint of the teeth at the outer radius. In a
>> flat hirth joint all the teeth radiate from the center of this circle, call
>> it the origin. If the origin of the teeth is above the outer center line,
>> then joint has a conical shape and the two parts are concave and convex.
>> >
>> > Each tooth at every point has the same profile, the top of the tooth
>> profile is either 60 or 90 degrees. The groove angle is the angle that the
>> groove forms from the origin to the outer radius. It will pass below (for a
>> convex part) the outer radius. It’s critical for making hirth joints
>> because it forms the tool path. The ridge angle is the angle formed by the
>> corresponding ridge.
>> >
>> > If the joint is conical, then there is an inner center line that passes
>> through the center of the teeth at the inner radius. The tooth height is
>> the critical number to calculate. It is dependent on the number of teeth,
>> the profile angle and the inner and out radii. Something that really
>> complicates the mental gymnastics is that the tooth height is smaller at
>> the inner radius. My code adds a “base” of extra material at the bottom of
>> the convex part and the top of the concave part. What’s tricky is
>> positioning the base of the concave part relative to the inner center line.
>> The concave parts base is relatively easy to place because it depends on
>> the outer radius and center line.
>> >
>> > I generate the raw teeth using the groove and ridge angles and
>> spherical coordinates to make two 2d tooth profiles. Then I complete a
>> tooth using skin(). A for loop generates the full set of N teeth. Then
>> intersection or difference is used the trim the teeth at the inner and
>> outer radii. I discovered something at that point, but solved it pretty
>> simply. When diffing a cylinder from the N teeth, each tooth took up a
>> small portion of the cylinder being diffed out. I had to raise the $fn on
>> the cylinder or tube being used so that I got enough points in each tooth
>> that diff or intersection was accurate. I kept raising it until the results
>> stopped improving. I ended up with the 16*360 you see in the code.
>> >
>> > After I have the raw teeth, I generate a cone that is diffed away to
>> produce the chamfer at the top of the teeth. Then I add in the base. The
>> base also adds the “chamfer” at the bottom of the groove. It’s half the
>> size of the top chamfer to leave a little gap when the parts are joined.
>> >
>> > When I comment out the everything but the raw teeth and import the STL
>> into PrusaSlicer, it reports errors fixed, but appears to slice correctly
>> when supports are added.
>> >
>> > When I add the intersection to trim the raw teeth, the number of
>> reported errors goes way up.
>> >
>> > When I add the diff to remove the chamfer, the number goes way up again.
>> >
>> > When I add in the base, the number goes up again and it starts
>> reporting many open edges.
>> >
>> > Throughout, OpenSCAD reports no errors. Using $fn at 16*360, manifold
>> renders in 4+ seconds. At 32*360, it’s 53+ seconds. I did check CSG and it
>> did not help.
>> >
>> > Maybe the biggest hint is that the convex part uses almost identical
>> code, but produces no errors. Very weird.
>> >
>> > So, is this an OpenSCAD problem? Or something in my code?
>> >
>> > It’s also possible that my math is off somewhere. My formal trig
>> training was 60 years ago. However I doubt a math error is responsible for
>> the slicing problem and STL errors.
>> >
>> > -Bob
>> >
>> >
>> > include <BOSL2/std.scad>
>> > include <BOSL2/structs.scad>
>> >
>> > // Number of Teeth
>> > _n = 36; // Number Of Teeth
>> >
>> > // Inner Radius
>> > _ir = 30;
>> > // Outer Radius
>> > _or = 50;
>> > // Is the coupling conical?
>> > _conic = 10;
>> > // Tooth Profile Angle
>> > _profile = 60; // [60, 90]
>> > // Percentage of tooth height
>> > _chamfer = 5; // Default 5%
>> > _base = 1;
>> >
>> > $fn = 180;
>> > tiny = 1 / 1024;
>> >
>> > hirth_concave();
>> >
>> > _irRatio = _ir / _or;
>> > _toothAngle = 360/_n;
>> > _toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2);
>> > _chamferHeight = _chamfer * _toothHeight / 100;
>> > _grooveAngle = atan(((_toothHeight/2) + _conic) / _or);
>> > _ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or);
>> > _innerCenterLine = (1 - _irRatio) * _conic;
>> > _stackHeight = _innerCenterLine + _toothHeight + 2*_base;
>> > _tubeHeight = 2*_conic + 2*_base + 2*_toothHeight;
>> >
>> > module hirth_concave() {
>> > zrot(_toothAngle/2)
>> > union() {
>> > difference() {
>> > intersection() {
>> > union() {
>> > for (i = [0 : 360/_n : 359])
>> > zrot(i)
>> > _profileF();
>> > }
>> > tube(ir = _ir, or = _or, anchor = CENTER, l =
>> _tubeHeight, orient = UP, $fn = 16*360);
>> > }
>> > _chamferF();
>> > zcyl(r = _ir, h = _tubeHeight, $fn = 16*360, anchor =
>> CENTER);
>> > }
>> > _baseF();
>> > }
>> > } // hirth_concave
>> >
>> > module _profileF() {
>> > IR = _ir * .5;
>> > OR = _or * 1.5;
>> > tI = [spherical_to_xyz(IR, 0, _grooveAngle + 90),
>> > spherical_to_xyz(IR, _toothAngle/2, _ridgeAngle + 90),
>> > spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)];
>> >
>> > tO = [spherical_to_xyz(OR, 0, _grooveAngle + 90),
>> > spherical_to_xyz(OR, _toothAngle/2, _ridgeAngle + 90),
>> > spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)];
>> > up(_conic)
>> > skin([tI, tO], slices = 0);
>> > }
>> >
>> >
>> > module _chamferF() {
>> > A = -_toothHeight/2 - .1;
>> > B = -_toothHeight/2 + _chamferHeight;
>> >
>> > pts = [[0, _conic],
>> > [_or+tiny, A],
>> > [_or+tiny, B]];
>> >
>> > rotate_extrude(angle = 360, $fn = 16*360)
>> > polygon(pts);
>> > }
>> >
>> > module _baseF() {
>> > A = _base + _irRatio*_toothHeight/2 + _innerCenterLine;
>> > B = _irRatio * (_toothHeight/2 - _chamferHeight/2) +
>> _innerCenterLine;
>> > C = _toothHeight/2 - _chamferHeight/2;
>> > pts = [
>> > [_ir, A],
>> > [_ir, B],
>> > [_or, C],
>> > [_or, A]
>> > ];
>> >
>> > rotate_extrude(angle = 360, $fn = 360*16)
>> > polygon(pts);
>> > }
>> > _______________________________________________
>> > OpenSCAD mailing list
>> > To unsubscribe send an email to discuss-leave@lists.openscad.org
>> _______________________________________________
>> OpenSCAD mailing list
>> To unsubscribe send an email to discuss-leave@lists.openscad.org
>>
>
SP
Sanjeev Prabhakar
Sun, Nov 3, 2024 3:25 PM
I am not sure what is the method used to model the coupling.
The method I used did not have any such issues at teeth up to 3 (a video of
the same was also posted here), below that I think it is not relevant.
attached here is the wire model for 3 , 4 and 5 teeth with just 1 mm gap
and it can be seen that the gap is consistent. Also I am not sure if these
low teeth models are of any use in real life.
The method I used needs functions to project a surface onto another, which
might be more clear from the posted video.
[image: Screenshot 2024-11-03 at 8.53.56 PM.png]
[image: Screenshot 2024-11-03 at 8.41.08 PM.png]
On Sun, 3 Nov 2024 at 19:59, Adrian Mariano via Discuss <
discuss@lists.openscad.org> wrote:
Here's a bit on the subtlety of the Hirth joint. I thought (like many
others, I suspect) that you could just create a triangle, stand it up
vertically, center it and scale it in the direction of the origin to create
the joint. But if you do this, you run into issues with mating between the
two halves of the joint that are quite obvious if the tooth count is low.
In order for the joints to mate, they have to touch at their half-way
points (which are on the XY plane in this construction). That constrains
the size of the triangle based on the other joint parameters. But if you
form the simple construction I described, you get these triangles, where
red is the bottom part and green is the top part. They are touching at the
triangle midles, but nowhere else. And furthermore, the triangles for one
joint don't meet at their corners!
[image: image.png]
To solve this problem, you need to rotate the triangle bottoms inward
until their vertices meet. That produces this set of triangles:
[image: image.png]
From here you can sweep the triangles toward the origin to make the
joint. But it's not in the direction of the normal to the triangle, since
the triangle bottoms were shifted inward by the rotation. The more
teeth you add, the smaller this effect becomes. It depends on how close to
2 you get with the ratio of tan(180/n) to tan(90/n). So for large numbers
of teeth it doesn't make much difference.
Note also that Sanjeev posted a case with an asymmetric tooth shape. I
don't know how to do the general case, but if you have a right triangle
like he showed, then it appears that everything will work with
appropriately scaled vertically positioned triangles---no funny tilt
required.
On Sat, Nov 2, 2024 at 9:38 AM Adrian Mariano avm4@cornell.edu wrote:
Ray, I tried out your code and ran into numerous problems. It is super
slow to preview. You don't give a convexity argument so stuff is missing
in preview. Render fails with a bunch of errors, perhaps due to the
reversed faces. So I can't really look at the shape very well. I tried
setting the tooth count to 5 and it gets really weird. My suspicion is
that you fell into the same trap that I did in not recognizing the subtlety
of the face spline design, but I can't be certain.... Or maybe you don't
care if it fits accurately--could be that the modeling errors in question
aren't a major source of error at high tooth count. Note that EVEN the
case of two symmetric parts is rather tricky to get right. I didn't
realize this at first. A fully correct implementation will let someone
make a 5 tooth design that could be used to set a mechanism at fifth of a
circle angles, for example.
With regards to terminology, my main reason for asking the question about
other face splines is that I'd call this module in BOSL2 face_spline(),
except that if there are 4 other kinds of face spline then that could be
confusing, in which case perhaps it should be hirth() which is more
obscure.
On Thu, Oct 31, 2024 at 8:01 PM Raymond West via Discuss <
discuss@lists.openscad.org> wrote:
Hi Bob,
Here's the basic code for a parametric Hirth Joint. Spring loaded often
use as a slip clutch in torque sensitive situations, e.g screw drivers,
tapping heads, etc. Larger scale high speed turbines for shaft
connections, since easy to balance, no windage, etc. I've tested as
saving as stl, and re-importing, gives no errors. Easy enough to cut out
the centre teeth if you don't want them.
// clutch.scad
ind= 50; // overall diameter
num= 20; // number of teeth
back = 6; //thickness of back
////////////////////////////////////////////
diam= ind/cos (180/num); // bigger to allow for chords
chord = diam*sin(180/num);
ridge= chord *sqrt(3)/3; // or set to whatever (denominator = 2 for 60
degrees.)
points=[
[0,0,ridge/2],
[diam/2,-chord/2,0],
[diam/2,+chord/2,0],
[diam/2,0,ridge]
];
faces=[
[0,1,2],
[0,1,3],
[0,2,3],
[1,2,3]
];
module wedge(){
polyhedron(points,faces,convexity=10);
}
//rotate wedge
intersection(){
translate([0,0,-back])
cylinder(d=ind,h=200,$fn=100);
union(){
for (j=[0:1:+1+360/num])
rotate([0,0,j360/num+0.5360/num]) wedge();
cylinder(d1=diam,d2=0,h=ridge/2,$fn=num);
translate([0,0,-back])
cylinder(d=diam,h=back,$fn=num);
}
}
//save as stl, then import to check for valid stl. (remove comments
below and run again)
/*
translate([0,0,6])
rotate([0,180,360/(num*2)])
import("P:/Docs/openscad/clutch.stl");
*/
On 26/10/2024 00:44, Bob Carlson via Discuss wrote:
I got really intrigued by the Hirth joint and have been working a
library entry that would generate them. I have it fully working,
apparently, because it renders perfectly as far as I can see. However when
I load one of the parts (a concave part) into PrusaSlicer, it reports
thousands of errors that it supposedly fixed. The visual rendering is fine,
but when you look at the slice it is completely screwed up.
First some explanation. When I looked up hirth joints I only saw flat
ones mentioned. The one I have actually encountered though is a conical
one. There is a concave part and a convex part. They fit together
perfectly. I had to invent some terminology since I did not find terms for
some things I found to be important. The outer center line is the plane
that passes through the midpoint of the teeth at the outer radius. In a
flat hirth joint all the teeth radiate from the center of this circle, call
it the origin. If the origin of the teeth is above the outer center line,
then joint has a conical shape and the two parts are concave and convex.
Each tooth at every point has the same profile, the top of the tooth
profile is either 60 or 90 degrees. The groove angle is the angle that the
groove forms from the origin to the outer radius. It will pass below (for a
convex part) the outer radius. It’s critical for making hirth joints
because it forms the tool path. The ridge angle is the angle formed by the
corresponding ridge.
If the joint is conical, then there is an inner center line that
passes through the center of the teeth at the inner radius. The tooth
height is the critical number to calculate. It is dependent on the number
of teeth, the profile angle and the inner and out radii. Something that
really complicates the mental gymnastics is that the tooth height is
smaller at the inner radius. My code adds a “base” of extra material at the
bottom of the convex part and the top of the concave part. What’s tricky is
positioning the base of the concave part relative to the inner center line.
The concave parts base is relatively easy to place because it depends on
the outer radius and center line.
I generate the raw teeth using the groove and ridge angles and
spherical coordinates to make two 2d tooth profiles. Then I complete a
tooth using skin(). A for loop generates the full set of N teeth. Then
intersection or difference is used the trim the teeth at the inner and
outer radii. I discovered something at that point, but solved it pretty
simply. When diffing a cylinder from the N teeth, each tooth took up a
small portion of the cylinder being diffed out. I had to raise the $fn on
the cylinder or tube being used so that I got enough points in each tooth
that diff or intersection was accurate. I kept raising it until the results
stopped improving. I ended up with the 16*360 you see in the code.
After I have the raw teeth, I generate a cone that is diffed away to
produce the chamfer at the top of the teeth. Then I add in the base. The
base also adds the “chamfer” at the bottom of the groove. It’s half the
size of the top chamfer to leave a little gap when the parts are joined.
When I comment out the everything but the raw teeth and import the STL
into PrusaSlicer, it reports errors fixed, but appears to slice correctly
when supports are added.
When I add the intersection to trim the raw teeth, the number of
reported errors goes way up.
When I add the diff to remove the chamfer, the number goes way up
When I add in the base, the number goes up again and it starts
reporting many open edges.
Throughout, OpenSCAD reports no errors. Using $fn at 16*360, manifold
renders in 4+ seconds. At 32*360, it’s 53+ seconds. I did check CSG and it
did not help.
Maybe the biggest hint is that the convex part uses almost identical
code, but produces no errors. Very weird.
So, is this an OpenSCAD problem? Or something in my code?
It’s also possible that my math is off somewhere. My formal trig
training was 60 years ago. However I doubt a math error is responsible for
the slicing problem and STL errors.
-Bob
include <BOSL2/std.scad>
include <BOSL2/structs.scad>
// Number of Teeth
_n = 36; // Number Of Teeth
// Inner Radius
_ir = 30;
// Outer Radius
_or = 50;
// Is the coupling conical?
_conic = 10;
// Tooth Profile Angle
_profile = 60; // [60, 90]
// Percentage of tooth height
_chamfer = 5; // Default 5%
_base = 1;
$fn = 180;
tiny = 1 / 1024;
hirth_concave();
_irRatio = _ir / _or;
_toothAngle = 360/_n;
_toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2);
_chamferHeight = _chamfer * _toothHeight / 100;
_grooveAngle = atan(((_toothHeight/2) + _conic) / _or);
_ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or);
_innerCenterLine = (1 - _irRatio) * _conic;
_stackHeight = _innerCenterLine + _toothHeight + 2*_base;
_tubeHeight = 2*_conic + 2*_base + 2*_toothHeight;
module hirth_concave() {
zrot(_toothAngle/2)
union() {
difference() {
intersection() {
union() {
for (i = [0 : 360/_n : 359])
zrot(i)
_profileF();
}
tube(ir = _ir, or = _or, anchor = CENTER, l =
_tubeHeight, orient = UP, $fn = 16*360);
}
_chamferF();
zcyl(r = _ir, h = _tubeHeight, $fn = 16*360, anchor =
}
_baseF();
}
} // hirth_concave
module _profileF() {
IR = _ir * .5;
OR = _or * 1.5;
tI = [spherical_to_xyz(IR, 0, _grooveAngle + 90),
spherical_to_xyz(IR, _toothAngle/2, _ridgeAngle + 90),
spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)];
tO = [spherical_to_xyz(OR, 0, _grooveAngle + 90),
spherical_to_xyz(OR, _toothAngle/2, _ridgeAngle + 90),
spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)];
up(_conic)
skin([tI, tO], slices = 0);
}
module _chamferF() {
A = -_toothHeight/2 - .1;
B = -_toothHeight/2 + _chamferHeight;
pts = [[0, _conic],
[_or+tiny, A],
[_or+tiny, B]];
rotate_extrude(angle = 360, $fn = 16*360)
polygon(pts);
}
module _baseF() {
A = _base + _irRatio*_toothHeight/2 + _innerCenterLine;
B = _irRatio * (_toothHeight/2 - _chamferHeight/2) +
C = _toothHeight/2 - _chamferHeight/2;
pts = [
[_ir, A],
[_ir, B],
[_or, C],
[_or, A]
];
rotate_extrude(angle = 360, $fn = 360*16)
polygon(pts);
}
OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org
I am not sure what is the method used to model the coupling.
The method I used did not have any such issues at teeth up to 3 (a video of
the same was also posted here), below that I think it is not relevant.
attached here is the wire model for 3 , 4 and 5 teeth with just 1 mm gap
and it can be seen that the gap is consistent. Also I am not sure if these
low teeth models are of any use in real life.
The method I used needs functions to project a surface onto another, which
might be more clear from the posted video.
[image: Screenshot 2024-11-03 at 8.53.56 PM.png]
[image: Screenshot 2024-11-03 at 8.41.08 PM.png]
On Sun, 3 Nov 2024 at 19:59, Adrian Mariano via Discuss <
discuss@lists.openscad.org> wrote:
> Here's a bit on the subtlety of the Hirth joint. I thought (like many
> others, I suspect) that you could just create a triangle, stand it up
> vertically, center it and scale it in the direction of the origin to create
> the joint. But if you do this, you run into issues with mating between the
> two halves of the joint that are quite obvious if the tooth count is low.
> In order for the joints to mate, they have to touch at their half-way
> points (which are on the XY plane in this construction). That constrains
> the size of the triangle based on the other joint parameters. But if you
> form the simple construction I described, you get these triangles, where
> red is the bottom part and green is the top part. They are touching at the
> triangle midles, but nowhere else. And furthermore, the triangles for one
> joint don't meet at their corners!
>
> [image: image.png]
>
> To solve this problem, you need to rotate the triangle bottoms inward
> until their vertices meet. That produces this set of triangles:
>
> [image: image.png]
> From here you can sweep the triangles toward the origin to make the
> joint. But it's not in the direction of the normal to the triangle, since
> the triangle bottoms were shifted inward by the rotation. The more
> teeth you add, the smaller this effect becomes. It depends on how close to
> 2 you get with the ratio of tan(180/n) to tan(90/n). So for large numbers
> of teeth it doesn't make much difference.
>
> Note also that Sanjeev posted a case with an asymmetric tooth shape. I
> don't know how to do the general case, but if you have a right triangle
> like he showed, then it appears that everything will work with
> appropriately scaled vertically positioned triangles---no funny tilt
> required.
>
> On Sat, Nov 2, 2024 at 9:38 AM Adrian Mariano <avm4@cornell.edu> wrote:
>
>> Ray, I tried out your code and ran into numerous problems. It is super
>> slow to preview. You don't give a convexity argument so stuff is missing
>> in preview. Render fails with a bunch of errors, perhaps due to the
>> reversed faces. So I can't really look at the shape very well. I tried
>> setting the tooth count to 5 and it gets really weird. My suspicion is
>> that you fell into the same trap that I did in not recognizing the subtlety
>> of the face spline design, but I can't be certain.... Or maybe you don't
>> care if it fits accurately--could be that the modeling errors in question
>> aren't a major source of error at high tooth count. Note that EVEN the
>> case of two symmetric parts is rather tricky to get right. I didn't
>> realize this at first. A fully correct implementation will let someone
>> make a 5 tooth design that could be used to set a mechanism at fifth of a
>> circle angles, for example.
>>
>> With regards to terminology, my main reason for asking the question about
>> other face splines is that I'd call this module in BOSL2 face_spline(),
>> except that if there are 4 other kinds of face spline then that could be
>> confusing, in which case perhaps it should be hirth() which is more
>> obscure.
>>
>> On Thu, Oct 31, 2024 at 8:01 PM Raymond West via Discuss <
>> discuss@lists.openscad.org> wrote:
>>
>>> Hi Bob,
>>>
>>> Here's the basic code for a parametric Hirth Joint. Spring loaded often
>>> use as a slip clutch in torque sensitive situations, e.g screw drivers,
>>> tapping heads, etc. Larger scale high speed turbines for shaft
>>> connections, since easy to balance, no windage, etc. I've tested as
>>> saving as stl, and re-importing, gives no errors. Easy enough to cut out
>>> the centre teeth if you don't want them.
>>>
>>> // clutch.scad
>>>
>>> ind= 50; // overall diameter
>>> num= 20; // number of teeth
>>> back = 6; //thickness of back
>>> ////////////////////////////////////////////
>>>
>>>
>>> diam= ind/cos (180/num); // bigger to allow for chords
>>> chord = diam*sin(180/num);
>>>
>>> ridge= chord *sqrt(3)/3; // or set to whatever (denominator = 2 for 60
>>> degrees.)
>>>
>>> points=[
>>> [0,0,ridge/2],
>>> [diam/2,-chord/2,0],
>>> [diam/2,+chord/2,0],
>>> [diam/2,0,ridge]
>>> ];
>>> faces=[
>>> [0,1,2],
>>> [0,1,3],
>>> [0,2,3],
>>> [1,2,3]
>>> ];
>>>
>>> module wedge(){
>>> polyhedron(points,faces,convexity=10);
>>> }
>>>
>>> //rotate wedge
>>>
>>> intersection(){
>>> translate([0,0,-back])
>>> cylinder(d=ind,h=200,$fn=100);
>>> union(){
>>> for (j=[0:1:+1+360/num])
>>> rotate([0,0,j*360/num+0.5*360/num]) wedge();
>>> cylinder(d1=diam,d2=0,h=ridge/2,$fn=num);
>>> translate([0,0,-back])
>>> cylinder(d=diam,h=back,$fn=num);
>>> }
>>> }
>>>
>>> //save as stl, then import to check for valid stl. (remove comments
>>> below and run again)
>>>
>>> /*
>>> translate([0,0,6])
>>> rotate([0,180,360/(num*2)])
>>> import("P:/Docs/openscad/clutch.stl");
>>> */
>>>
>>>
>>> On 26/10/2024 00:44, Bob Carlson via Discuss wrote:
>>> > I got really intrigued by the Hirth joint and have been working a
>>> library entry that would generate them. I have it fully working,
>>> apparently, because it renders perfectly as far as I can see. However when
>>> I load one of the parts (a concave part) into PrusaSlicer, it reports
>>> thousands of errors that it supposedly fixed. The visual rendering is fine,
>>> but when you look at the slice it is completely screwed up.
>>> >
>>> > First some explanation. When I looked up hirth joints I only saw flat
>>> ones mentioned. The one I have actually encountered though is a conical
>>> one. There is a concave part and a convex part. They fit together
>>> perfectly. I had to invent some terminology since I did not find terms for
>>> some things I found to be important. The outer center line is the plane
>>> that passes through the midpoint of the teeth at the outer radius. In a
>>> flat hirth joint all the teeth radiate from the center of this circle, call
>>> it the origin. If the origin of the teeth is above the outer center line,
>>> then joint has a conical shape and the two parts are concave and convex.
>>> >
>>> > Each tooth at every point has the same profile, the top of the tooth
>>> profile is either 60 or 90 degrees. The groove angle is the angle that the
>>> groove forms from the origin to the outer radius. It will pass below (for a
>>> convex part) the outer radius. It’s critical for making hirth joints
>>> because it forms the tool path. The ridge angle is the angle formed by the
>>> corresponding ridge.
>>> >
>>> > If the joint is conical, then there is an inner center line that
>>> passes through the center of the teeth at the inner radius. The tooth
>>> height is the critical number to calculate. It is dependent on the number
>>> of teeth, the profile angle and the inner and out radii. Something that
>>> really complicates the mental gymnastics is that the tooth height is
>>> smaller at the inner radius. My code adds a “base” of extra material at the
>>> bottom of the convex part and the top of the concave part. What’s tricky is
>>> positioning the base of the concave part relative to the inner center line.
>>> The concave parts base is relatively easy to place because it depends on
>>> the outer radius and center line.
>>> >
>>> > I generate the raw teeth using the groove and ridge angles and
>>> spherical coordinates to make two 2d tooth profiles. Then I complete a
>>> tooth using skin(). A for loop generates the full set of N teeth. Then
>>> intersection or difference is used the trim the teeth at the inner and
>>> outer radii. I discovered something at that point, but solved it pretty
>>> simply. When diffing a cylinder from the N teeth, each tooth took up a
>>> small portion of the cylinder being diffed out. I had to raise the $fn on
>>> the cylinder or tube being used so that I got enough points in each tooth
>>> that diff or intersection was accurate. I kept raising it until the results
>>> stopped improving. I ended up with the 16*360 you see in the code.
>>> >
>>> > After I have the raw teeth, I generate a cone that is diffed away to
>>> produce the chamfer at the top of the teeth. Then I add in the base. The
>>> base also adds the “chamfer” at the bottom of the groove. It’s half the
>>> size of the top chamfer to leave a little gap when the parts are joined.
>>> >
>>> > When I comment out the everything but the raw teeth and import the STL
>>> into PrusaSlicer, it reports errors fixed, but appears to slice correctly
>>> when supports are added.
>>> >
>>> > When I add the intersection to trim the raw teeth, the number of
>>> reported errors goes way up.
>>> >
>>> > When I add the diff to remove the chamfer, the number goes way up
>>> again.
>>> >
>>> > When I add in the base, the number goes up again and it starts
>>> reporting many open edges.
>>> >
>>> > Throughout, OpenSCAD reports no errors. Using $fn at 16*360, manifold
>>> renders in 4+ seconds. At 32*360, it’s 53+ seconds. I did check CSG and it
>>> did not help.
>>> >
>>> > Maybe the biggest hint is that the convex part uses almost identical
>>> code, but produces no errors. Very weird.
>>> >
>>> > So, is this an OpenSCAD problem? Or something in my code?
>>> >
>>> > It’s also possible that my math is off somewhere. My formal trig
>>> training was 60 years ago. However I doubt a math error is responsible for
>>> the slicing problem and STL errors.
>>> >
>>> > -Bob
>>> >
>>> >
>>> > include <BOSL2/std.scad>
>>> > include <BOSL2/structs.scad>
>>> >
>>> > // Number of Teeth
>>> > _n = 36; // Number Of Teeth
>>> >
>>> > // Inner Radius
>>> > _ir = 30;
>>> > // Outer Radius
>>> > _or = 50;
>>> > // Is the coupling conical?
>>> > _conic = 10;
>>> > // Tooth Profile Angle
>>> > _profile = 60; // [60, 90]
>>> > // Percentage of tooth height
>>> > _chamfer = 5; // Default 5%
>>> > _base = 1;
>>> >
>>> > $fn = 180;
>>> > tiny = 1 / 1024;
>>> >
>>> > hirth_concave();
>>> >
>>> > _irRatio = _ir / _or;
>>> > _toothAngle = 360/_n;
>>> > _toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2);
>>> > _chamferHeight = _chamfer * _toothHeight / 100;
>>> > _grooveAngle = atan(((_toothHeight/2) + _conic) / _or);
>>> > _ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or);
>>> > _innerCenterLine = (1 - _irRatio) * _conic;
>>> > _stackHeight = _innerCenterLine + _toothHeight + 2*_base;
>>> > _tubeHeight = 2*_conic + 2*_base + 2*_toothHeight;
>>> >
>>> > module hirth_concave() {
>>> > zrot(_toothAngle/2)
>>> > union() {
>>> > difference() {
>>> > intersection() {
>>> > union() {
>>> > for (i = [0 : 360/_n : 359])
>>> > zrot(i)
>>> > _profileF();
>>> > }
>>> > tube(ir = _ir, or = _or, anchor = CENTER, l =
>>> _tubeHeight, orient = UP, $fn = 16*360);
>>> > }
>>> > _chamferF();
>>> > zcyl(r = _ir, h = _tubeHeight, $fn = 16*360, anchor =
>>> CENTER);
>>> > }
>>> > _baseF();
>>> > }
>>> > } // hirth_concave
>>> >
>>> > module _profileF() {
>>> > IR = _ir * .5;
>>> > OR = _or * 1.5;
>>> > tI = [spherical_to_xyz(IR, 0, _grooveAngle + 90),
>>> > spherical_to_xyz(IR, _toothAngle/2, _ridgeAngle + 90),
>>> > spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)];
>>> >
>>> > tO = [spherical_to_xyz(OR, 0, _grooveAngle + 90),
>>> > spherical_to_xyz(OR, _toothAngle/2, _ridgeAngle + 90),
>>> > spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)];
>>> > up(_conic)
>>> > skin([tI, tO], slices = 0);
>>> > }
>>> >
>>> >
>>> > module _chamferF() {
>>> > A = -_toothHeight/2 - .1;
>>> > B = -_toothHeight/2 + _chamferHeight;
>>> >
>>> > pts = [[0, _conic],
>>> > [_or+tiny, A],
>>> > [_or+tiny, B]];
>>> >
>>> > rotate_extrude(angle = 360, $fn = 16*360)
>>> > polygon(pts);
>>> > }
>>> >
>>> > module _baseF() {
>>> > A = _base + _irRatio*_toothHeight/2 + _innerCenterLine;
>>> > B = _irRatio * (_toothHeight/2 - _chamferHeight/2) +
>>> _innerCenterLine;
>>> > C = _toothHeight/2 - _chamferHeight/2;
>>> > pts = [
>>> > [_ir, A],
>>> > [_ir, B],
>>> > [_or, C],
>>> > [_or, A]
>>> > ];
>>> >
>>> > rotate_extrude(angle = 360, $fn = 360*16)
>>> > polygon(pts);
>>> > }
>>> > _______________________________________________
>>> > OpenSCAD mailing list
>>> > To unsubscribe send an email to discuss-leave@lists.openscad.org
>>> _______________________________________________
>>> OpenSCAD mailing list
>>> To unsubscribe send an email to discuss-leave@lists.openscad.org
>>>
>> _______________________________________________
> OpenSCAD mailing list
> To unsubscribe send an email to discuss-leave@lists.openscad.org
>
SP
Sanjeev Prabhakar
Sun, Nov 3, 2024 3:27 PM
oh you would need dependencies2.scad file to view the models in scad.
attached below:
On Sun, 3 Nov 2024 at 20:55, Sanjeev Prabhakar sprabhakar2006@gmail.com
wrote:
I am not sure what is the method used to model the coupling.
The method I used did not have any such issues at teeth up to 3 (a video
of the same was also posted here), below that I think it is not relevant.
attached here is the wire model for 3 , 4 and 5 teeth with just 1 mm gap
and it can be seen that the gap is consistent. Also I am not sure if these
low teeth models are of any use in real life.
The method I used needs functions to project a surface onto another, which
might be more clear from the posted video.
[image: Screenshot 2024-11-03 at 8.53.56 PM.png]
[image: Screenshot 2024-11-03 at 8.41.08 PM.png]
On Sun, 3 Nov 2024 at 19:59, Adrian Mariano via Discuss <
discuss@lists.openscad.org> wrote:
Here's a bit on the subtlety of the Hirth joint. I thought (like many
others, I suspect) that you could just create a triangle, stand it up
vertically, center it and scale it in the direction of the origin to create
the joint. But if you do this, you run into issues with mating between the
two halves of the joint that are quite obvious if the tooth count is low.
In order for the joints to mate, they have to touch at their half-way
points (which are on the XY plane in this construction). That constrains
the size of the triangle based on the other joint parameters. But if you
form the simple construction I described, you get these triangles, where
red is the bottom part and green is the top part. They are touching at the
triangle midles, but nowhere else. And furthermore, the triangles for one
joint don't meet at their corners!
[image: image.png]
To solve this problem, you need to rotate the triangle bottoms inward
until their vertices meet. That produces this set of triangles:
[image: image.png]
From here you can sweep the triangles toward the origin to make the
joint. But it's not in the direction of the normal to the triangle, since
the triangle bottoms were shifted inward by the rotation. The more
teeth you add, the smaller this effect becomes. It depends on how close to
2 you get with the ratio of tan(180/n) to tan(90/n). So for large numbers
of teeth it doesn't make much difference.
Note also that Sanjeev posted a case with an asymmetric tooth shape. I
don't know how to do the general case, but if you have a right triangle
like he showed, then it appears that everything will work with
appropriately scaled vertically positioned triangles---no funny tilt
required.
On Sat, Nov 2, 2024 at 9:38 AM Adrian Mariano avm4@cornell.edu wrote:
Ray, I tried out your code and ran into numerous problems. It is super
slow to preview. You don't give a convexity argument so stuff is missing
in preview. Render fails with a bunch of errors, perhaps due to the
reversed faces. So I can't really look at the shape very well. I tried
setting the tooth count to 5 and it gets really weird. My suspicion is
that you fell into the same trap that I did in not recognizing the subtlety
of the face spline design, but I can't be certain.... Or maybe you don't
care if it fits accurately--could be that the modeling errors in question
aren't a major source of error at high tooth count. Note that EVEN the
case of two symmetric parts is rather tricky to get right. I didn't
realize this at first. A fully correct implementation will let someone
make a 5 tooth design that could be used to set a mechanism at fifth of a
circle angles, for example.
With regards to terminology, my main reason for asking the question
about other face splines is that I'd call this module in BOSL2
face_spline(), except that if there are 4 other kinds of face spline then
that could be confusing, in which case perhaps it should be hirth() which
is more obscure.
On Thu, Oct 31, 2024 at 8:01 PM Raymond West via Discuss <
discuss@lists.openscad.org> wrote:
Hi Bob,
Here's the basic code for a parametric Hirth Joint. Spring loaded often
use as a slip clutch in torque sensitive situations, e.g screw drivers,
tapping heads, etc. Larger scale high speed turbines for shaft
connections, since easy to balance, no windage, etc. I've tested as
saving as stl, and re-importing, gives no errors. Easy enough to cut
out
the centre teeth if you don't want them.
// clutch.scad
ind= 50; // overall diameter
num= 20; // number of teeth
back = 6; //thickness of back
////////////////////////////////////////////
diam= ind/cos (180/num); // bigger to allow for chords
chord = diam*sin(180/num);
ridge= chord *sqrt(3)/3; // or set to whatever (denominator = 2 for 60
degrees.)
points=[
[0,0,ridge/2],
[diam/2,-chord/2,0],
[diam/2,+chord/2,0],
[diam/2,0,ridge]
];
faces=[
[0,1,2],
[0,1,3],
[0,2,3],
[1,2,3]
];
module wedge(){
polyhedron(points,faces,convexity=10);
}
//rotate wedge
intersection(){
translate([0,0,-back])
cylinder(d=ind,h=200,$fn=100);
union(){
for (j=[0:1:+1+360/num])
rotate([0,0,j360/num+0.5360/num]) wedge();
cylinder(d1=diam,d2=0,h=ridge/2,$fn=num);
translate([0,0,-back])
cylinder(d=diam,h=back,$fn=num);
}
}
//save as stl, then import to check for valid stl. (remove comments
below and run again)
/*
translate([0,0,6])
rotate([0,180,360/(num*2)])
import("P:/Docs/openscad/clutch.stl");
*/
On 26/10/2024 00:44, Bob Carlson via Discuss wrote:
I got really intrigued by the Hirth joint and have been working a
library entry that would generate them. I have it fully working,
apparently, because it renders perfectly as far as I can see. However when
I load one of the parts (a concave part) into PrusaSlicer, it reports
thousands of errors that it supposedly fixed. The visual rendering is fine,
but when you look at the slice it is completely screwed up.
First some explanation. When I looked up hirth joints I only saw flat
ones mentioned. The one I have actually encountered though is a conical
one. There is a concave part and a convex part. They fit together
perfectly. I had to invent some terminology since I did not find terms for
some things I found to be important. The outer center line is the plane
that passes through the midpoint of the teeth at the outer radius. In a
flat hirth joint all the teeth radiate from the center of this circle, call
it the origin. If the origin of the teeth is above the outer center line,
then joint has a conical shape and the two parts are concave and convex.
Each tooth at every point has the same profile, the top of the tooth
profile is either 60 or 90 degrees. The groove angle is the angle that the
groove forms from the origin to the outer radius. It will pass below (for a
convex part) the outer radius. It’s critical for making hirth joints
because it forms the tool path. The ridge angle is the angle formed by the
corresponding ridge.
If the joint is conical, then there is an inner center line that
passes through the center of the teeth at the inner radius. The tooth
height is the critical number to calculate. It is dependent on the number
of teeth, the profile angle and the inner and out radii. Something that
really complicates the mental gymnastics is that the tooth height is
smaller at the inner radius. My code adds a “base” of extra material at the
bottom of the convex part and the top of the concave part. What’s tricky is
positioning the base of the concave part relative to the inner center line.
The concave parts base is relatively easy to place because it depends on
the outer radius and center line.
I generate the raw teeth using the groove and ridge angles and
spherical coordinates to make two 2d tooth profiles. Then I complete a
tooth using skin(). A for loop generates the full set of N teeth. Then
intersection or difference is used the trim the teeth at the inner and
outer radii. I discovered something at that point, but solved it pretty
simply. When diffing a cylinder from the N teeth, each tooth took up a
small portion of the cylinder being diffed out. I had to raise the $fn on
the cylinder or tube being used so that I got enough points in each tooth
that diff or intersection was accurate. I kept raising it until the results
stopped improving. I ended up with the 16*360 you see in the code.
After I have the raw teeth, I generate a cone that is diffed away to
produce the chamfer at the top of the teeth. Then I add in the base. The
base also adds the “chamfer” at the bottom of the groove. It’s half the
size of the top chamfer to leave a little gap when the parts are joined.
When I comment out the everything but the raw teeth and import the
STL into PrusaSlicer, it reports errors fixed, but appears to slice
correctly when supports are added.
When I add the intersection to trim the raw teeth, the number of
reported errors goes way up.
When I add the diff to remove the chamfer, the number goes way up
When I add in the base, the number goes up again and it starts
reporting many open edges.
Throughout, OpenSCAD reports no errors. Using $fn at 16*360, manifold
renders in 4+ seconds. At 32*360, it’s 53+ seconds. I did check CSG and it
did not help.
Maybe the biggest hint is that the convex part uses almost identical
code, but produces no errors. Very weird.
So, is this an OpenSCAD problem? Or something in my code?
It’s also possible that my math is off somewhere. My formal trig
training was 60 years ago. However I doubt a math error is responsible for
the slicing problem and STL errors.
-Bob
include <BOSL2/std.scad>
include <BOSL2/structs.scad>
// Number of Teeth
_n = 36; // Number Of Teeth
// Inner Radius
_ir = 30;
// Outer Radius
_or = 50;
// Is the coupling conical?
_conic = 10;
// Tooth Profile Angle
_profile = 60; // [60, 90]
// Percentage of tooth height
_chamfer = 5; // Default 5%
_base = 1;
$fn = 180;
tiny = 1 / 1024;
hirth_concave();
_irRatio = _ir / _or;
_toothAngle = 360/_n;
_toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2);
_chamferHeight = _chamfer * _toothHeight / 100;
_grooveAngle = atan(((_toothHeight/2) + _conic) / _or);
_ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or);
_innerCenterLine = (1 - _irRatio) * _conic;
_stackHeight = _innerCenterLine + _toothHeight + 2*_base;
_tubeHeight = 2*_conic + 2*_base + 2*_toothHeight;
module hirth_concave() {
zrot(_toothAngle/2)
union() {
difference() {
intersection() {
union() {
for (i = [0 : 360/_n : 359])
zrot(i)
_profileF();
}
tube(ir = _ir, or = _or, anchor = CENTER, l =
_tubeHeight, orient = UP, $fn = 16*360);
}
_chamferF();
zcyl(r = _ir, h = _tubeHeight, $fn = 16*360, anchor =
}
_baseF();
}
} // hirth_concave
module _profileF() {
IR = _ir * .5;
OR = _or * 1.5;
tI = [spherical_to_xyz(IR, 0, _grooveAngle + 90),
spherical_to_xyz(IR, _toothAngle/2, _ridgeAngle + 90),
spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)];
tO = [spherical_to_xyz(OR, 0, _grooveAngle + 90),
spherical_to_xyz(OR, _toothAngle/2, _ridgeAngle + 90),
spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)];
up(_conic)
skin([tI, tO], slices = 0);
}
module _chamferF() {
A = -_toothHeight/2 - .1;
B = -_toothHeight/2 + _chamferHeight;
pts = [[0, _conic],
[_or+tiny, A],
[_or+tiny, B]];
rotate_extrude(angle = 360, $fn = 16*360)
polygon(pts);
}
module _baseF() {
A = _base + _irRatio*_toothHeight/2 + _innerCenterLine;
B = _irRatio * (_toothHeight/2 - _chamferHeight/2) +
C = _toothHeight/2 - _chamferHeight/2;
pts = [
[_ir, A],
[_ir, B],
[_or, C],
[_or, A]
];
rotate_extrude(angle = 360, $fn = 360*16)
polygon(pts);
}
OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org
oh you would need dependencies2.scad file to view the models in scad.
attached below:
On Sun, 3 Nov 2024 at 20:55, Sanjeev Prabhakar <sprabhakar2006@gmail.com>
wrote:
> I am not sure what is the method used to model the coupling.
> The method I used did not have any such issues at teeth up to 3 (a video
> of the same was also posted here), below that I think it is not relevant.
>
> attached here is the wire model for 3 , 4 and 5 teeth with just 1 mm gap
> and it can be seen that the gap is consistent. Also I am not sure if these
> low teeth models are of any use in real life.
>
> The method I used needs functions to project a surface onto another, which
> might be more clear from the posted video.
> [image: Screenshot 2024-11-03 at 8.53.56 PM.png]
> [image: Screenshot 2024-11-03 at 8.41.08 PM.png]
>
> On Sun, 3 Nov 2024 at 19:59, Adrian Mariano via Discuss <
> discuss@lists.openscad.org> wrote:
>
>> Here's a bit on the subtlety of the Hirth joint. I thought (like many
>> others, I suspect) that you could just create a triangle, stand it up
>> vertically, center it and scale it in the direction of the origin to create
>> the joint. But if you do this, you run into issues with mating between the
>> two halves of the joint that are quite obvious if the tooth count is low.
>> In order for the joints to mate, they have to touch at their half-way
>> points (which are on the XY plane in this construction). That constrains
>> the size of the triangle based on the other joint parameters. But if you
>> form the simple construction I described, you get these triangles, where
>> red is the bottom part and green is the top part. They are touching at the
>> triangle midles, but nowhere else. And furthermore, the triangles for one
>> joint don't meet at their corners!
>>
>> [image: image.png]
>>
>> To solve this problem, you need to rotate the triangle bottoms inward
>> until their vertices meet. That produces this set of triangles:
>>
>> [image: image.png]
>> From here you can sweep the triangles toward the origin to make the
>> joint. But it's not in the direction of the normal to the triangle, since
>> the triangle bottoms were shifted inward by the rotation. The more
>> teeth you add, the smaller this effect becomes. It depends on how close to
>> 2 you get with the ratio of tan(180/n) to tan(90/n). So for large numbers
>> of teeth it doesn't make much difference.
>>
>> Note also that Sanjeev posted a case with an asymmetric tooth shape. I
>> don't know how to do the general case, but if you have a right triangle
>> like he showed, then it appears that everything will work with
>> appropriately scaled vertically positioned triangles---no funny tilt
>> required.
>>
>> On Sat, Nov 2, 2024 at 9:38 AM Adrian Mariano <avm4@cornell.edu> wrote:
>>
>>> Ray, I tried out your code and ran into numerous problems. It is super
>>> slow to preview. You don't give a convexity argument so stuff is missing
>>> in preview. Render fails with a bunch of errors, perhaps due to the
>>> reversed faces. So I can't really look at the shape very well. I tried
>>> setting the tooth count to 5 and it gets really weird. My suspicion is
>>> that you fell into the same trap that I did in not recognizing the subtlety
>>> of the face spline design, but I can't be certain.... Or maybe you don't
>>> care if it fits accurately--could be that the modeling errors in question
>>> aren't a major source of error at high tooth count. Note that EVEN the
>>> case of two symmetric parts is rather tricky to get right. I didn't
>>> realize this at first. A fully correct implementation will let someone
>>> make a 5 tooth design that could be used to set a mechanism at fifth of a
>>> circle angles, for example.
>>>
>>> With regards to terminology, my main reason for asking the question
>>> about other face splines is that I'd call this module in BOSL2
>>> face_spline(), except that if there are 4 other kinds of face spline then
>>> that could be confusing, in which case perhaps it should be hirth() which
>>> is more obscure.
>>>
>>> On Thu, Oct 31, 2024 at 8:01 PM Raymond West via Discuss <
>>> discuss@lists.openscad.org> wrote:
>>>
>>>> Hi Bob,
>>>>
>>>> Here's the basic code for a parametric Hirth Joint. Spring loaded often
>>>> use as a slip clutch in torque sensitive situations, e.g screw drivers,
>>>> tapping heads, etc. Larger scale high speed turbines for shaft
>>>> connections, since easy to balance, no windage, etc. I've tested as
>>>> saving as stl, and re-importing, gives no errors. Easy enough to cut
>>>> out
>>>> the centre teeth if you don't want them.
>>>>
>>>> // clutch.scad
>>>>
>>>> ind= 50; // overall diameter
>>>> num= 20; // number of teeth
>>>> back = 6; //thickness of back
>>>> ////////////////////////////////////////////
>>>>
>>>>
>>>> diam= ind/cos (180/num); // bigger to allow for chords
>>>> chord = diam*sin(180/num);
>>>>
>>>> ridge= chord *sqrt(3)/3; // or set to whatever (denominator = 2 for 60
>>>> degrees.)
>>>>
>>>> points=[
>>>> [0,0,ridge/2],
>>>> [diam/2,-chord/2,0],
>>>> [diam/2,+chord/2,0],
>>>> [diam/2,0,ridge]
>>>> ];
>>>> faces=[
>>>> [0,1,2],
>>>> [0,1,3],
>>>> [0,2,3],
>>>> [1,2,3]
>>>> ];
>>>>
>>>> module wedge(){
>>>> polyhedron(points,faces,convexity=10);
>>>> }
>>>>
>>>> //rotate wedge
>>>>
>>>> intersection(){
>>>> translate([0,0,-back])
>>>> cylinder(d=ind,h=200,$fn=100);
>>>> union(){
>>>> for (j=[0:1:+1+360/num])
>>>> rotate([0,0,j*360/num+0.5*360/num]) wedge();
>>>> cylinder(d1=diam,d2=0,h=ridge/2,$fn=num);
>>>> translate([0,0,-back])
>>>> cylinder(d=diam,h=back,$fn=num);
>>>> }
>>>> }
>>>>
>>>> //save as stl, then import to check for valid stl. (remove comments
>>>> below and run again)
>>>>
>>>> /*
>>>> translate([0,0,6])
>>>> rotate([0,180,360/(num*2)])
>>>> import("P:/Docs/openscad/clutch.stl");
>>>> */
>>>>
>>>>
>>>> On 26/10/2024 00:44, Bob Carlson via Discuss wrote:
>>>> > I got really intrigued by the Hirth joint and have been working a
>>>> library entry that would generate them. I have it fully working,
>>>> apparently, because it renders perfectly as far as I can see. However when
>>>> I load one of the parts (a concave part) into PrusaSlicer, it reports
>>>> thousands of errors that it supposedly fixed. The visual rendering is fine,
>>>> but when you look at the slice it is completely screwed up.
>>>> >
>>>> > First some explanation. When I looked up hirth joints I only saw flat
>>>> ones mentioned. The one I have actually encountered though is a conical
>>>> one. There is a concave part and a convex part. They fit together
>>>> perfectly. I had to invent some terminology since I did not find terms for
>>>> some things I found to be important. The outer center line is the plane
>>>> that passes through the midpoint of the teeth at the outer radius. In a
>>>> flat hirth joint all the teeth radiate from the center of this circle, call
>>>> it the origin. If the origin of the teeth is above the outer center line,
>>>> then joint has a conical shape and the two parts are concave and convex.
>>>> >
>>>> > Each tooth at every point has the same profile, the top of the tooth
>>>> profile is either 60 or 90 degrees. The groove angle is the angle that the
>>>> groove forms from the origin to the outer radius. It will pass below (for a
>>>> convex part) the outer radius. It’s critical for making hirth joints
>>>> because it forms the tool path. The ridge angle is the angle formed by the
>>>> corresponding ridge.
>>>> >
>>>> > If the joint is conical, then there is an inner center line that
>>>> passes through the center of the teeth at the inner radius. The tooth
>>>> height is the critical number to calculate. It is dependent on the number
>>>> of teeth, the profile angle and the inner and out radii. Something that
>>>> really complicates the mental gymnastics is that the tooth height is
>>>> smaller at the inner radius. My code adds a “base” of extra material at the
>>>> bottom of the convex part and the top of the concave part. What’s tricky is
>>>> positioning the base of the concave part relative to the inner center line.
>>>> The concave parts base is relatively easy to place because it depends on
>>>> the outer radius and center line.
>>>> >
>>>> > I generate the raw teeth using the groove and ridge angles and
>>>> spherical coordinates to make two 2d tooth profiles. Then I complete a
>>>> tooth using skin(). A for loop generates the full set of N teeth. Then
>>>> intersection or difference is used the trim the teeth at the inner and
>>>> outer radii. I discovered something at that point, but solved it pretty
>>>> simply. When diffing a cylinder from the N teeth, each tooth took up a
>>>> small portion of the cylinder being diffed out. I had to raise the $fn on
>>>> the cylinder or tube being used so that I got enough points in each tooth
>>>> that diff or intersection was accurate. I kept raising it until the results
>>>> stopped improving. I ended up with the 16*360 you see in the code.
>>>> >
>>>> > After I have the raw teeth, I generate a cone that is diffed away to
>>>> produce the chamfer at the top of the teeth. Then I add in the base. The
>>>> base also adds the “chamfer” at the bottom of the groove. It’s half the
>>>> size of the top chamfer to leave a little gap when the parts are joined.
>>>> >
>>>> > When I comment out the everything but the raw teeth and import the
>>>> STL into PrusaSlicer, it reports errors fixed, but appears to slice
>>>> correctly when supports are added.
>>>> >
>>>> > When I add the intersection to trim the raw teeth, the number of
>>>> reported errors goes way up.
>>>> >
>>>> > When I add the diff to remove the chamfer, the number goes way up
>>>> again.
>>>> >
>>>> > When I add in the base, the number goes up again and it starts
>>>> reporting many open edges.
>>>> >
>>>> > Throughout, OpenSCAD reports no errors. Using $fn at 16*360, manifold
>>>> renders in 4+ seconds. At 32*360, it’s 53+ seconds. I did check CSG and it
>>>> did not help.
>>>> >
>>>> > Maybe the biggest hint is that the convex part uses almost identical
>>>> code, but produces no errors. Very weird.
>>>> >
>>>> > So, is this an OpenSCAD problem? Or something in my code?
>>>> >
>>>> > It’s also possible that my math is off somewhere. My formal trig
>>>> training was 60 years ago. However I doubt a math error is responsible for
>>>> the slicing problem and STL errors.
>>>> >
>>>> > -Bob
>>>> >
>>>> >
>>>> > include <BOSL2/std.scad>
>>>> > include <BOSL2/structs.scad>
>>>> >
>>>> > // Number of Teeth
>>>> > _n = 36; // Number Of Teeth
>>>> >
>>>> > // Inner Radius
>>>> > _ir = 30;
>>>> > // Outer Radius
>>>> > _or = 50;
>>>> > // Is the coupling conical?
>>>> > _conic = 10;
>>>> > // Tooth Profile Angle
>>>> > _profile = 60; // [60, 90]
>>>> > // Percentage of tooth height
>>>> > _chamfer = 5; // Default 5%
>>>> > _base = 1;
>>>> >
>>>> > $fn = 180;
>>>> > tiny = 1 / 1024;
>>>> >
>>>> > hirth_concave();
>>>> >
>>>> > _irRatio = _ir / _or;
>>>> > _toothAngle = 360/_n;
>>>> > _toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2);
>>>> > _chamferHeight = _chamfer * _toothHeight / 100;
>>>> > _grooveAngle = atan(((_toothHeight/2) + _conic) / _or);
>>>> > _ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or);
>>>> > _innerCenterLine = (1 - _irRatio) * _conic;
>>>> > _stackHeight = _innerCenterLine + _toothHeight + 2*_base;
>>>> > _tubeHeight = 2*_conic + 2*_base + 2*_toothHeight;
>>>> >
>>>> > module hirth_concave() {
>>>> > zrot(_toothAngle/2)
>>>> > union() {
>>>> > difference() {
>>>> > intersection() {
>>>> > union() {
>>>> > for (i = [0 : 360/_n : 359])
>>>> > zrot(i)
>>>> > _profileF();
>>>> > }
>>>> > tube(ir = _ir, or = _or, anchor = CENTER, l =
>>>> _tubeHeight, orient = UP, $fn = 16*360);
>>>> > }
>>>> > _chamferF();
>>>> > zcyl(r = _ir, h = _tubeHeight, $fn = 16*360, anchor =
>>>> CENTER);
>>>> > }
>>>> > _baseF();
>>>> > }
>>>> > } // hirth_concave
>>>> >
>>>> > module _profileF() {
>>>> > IR = _ir * .5;
>>>> > OR = _or * 1.5;
>>>> > tI = [spherical_to_xyz(IR, 0, _grooveAngle + 90),
>>>> > spherical_to_xyz(IR, _toothAngle/2, _ridgeAngle + 90),
>>>> > spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)];
>>>> >
>>>> > tO = [spherical_to_xyz(OR, 0, _grooveAngle + 90),
>>>> > spherical_to_xyz(OR, _toothAngle/2, _ridgeAngle + 90),
>>>> > spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)];
>>>> > up(_conic)
>>>> > skin([tI, tO], slices = 0);
>>>> > }
>>>> >
>>>> >
>>>> > module _chamferF() {
>>>> > A = -_toothHeight/2 - .1;
>>>> > B = -_toothHeight/2 + _chamferHeight;
>>>> >
>>>> > pts = [[0, _conic],
>>>> > [_or+tiny, A],
>>>> > [_or+tiny, B]];
>>>> >
>>>> > rotate_extrude(angle = 360, $fn = 16*360)
>>>> > polygon(pts);
>>>> > }
>>>> >
>>>> > module _baseF() {
>>>> > A = _base + _irRatio*_toothHeight/2 + _innerCenterLine;
>>>> > B = _irRatio * (_toothHeight/2 - _chamferHeight/2) +
>>>> _innerCenterLine;
>>>> > C = _toothHeight/2 - _chamferHeight/2;
>>>> > pts = [
>>>> > [_ir, A],
>>>> > [_ir, B],
>>>> > [_or, C],
>>>> > [_or, A]
>>>> > ];
>>>> >
>>>> > rotate_extrude(angle = 360, $fn = 360*16)
>>>> > polygon(pts);
>>>> > }
>>>> > _______________________________________________
>>>> > OpenSCAD mailing list
>>>> > To unsubscribe send an email to discuss-leave@lists.openscad.org
>>>> _______________________________________________
>>>> OpenSCAD mailing list
>>>> To unsubscribe send an email to discuss-leave@lists.openscad.org
>>>>
>>> _______________________________________________
>> OpenSCAD mailing list
>> To unsubscribe send an email to discuss-leave@lists.openscad.org
>>
>
AM
Adrian Mariano
Sun, Nov 3, 2024 4:33 PM
It appears that you found a construction method that works, but your vague
description isn't enough for me to understand what it is. Do you have a
method that can construct a part that mates with itself? Or is it that you
can construct one part and then through a projection scheme, build a mate
for it?
I think that low tooth count splines are useful for controlling alignment
of parts, like if you want something that turns in 45 degree increments and
locks into position you can do this with 8 teeth.
On Sun, Nov 3, 2024 at 10:25 AM Sanjeev Prabhakar sprabhakar2006@gmail.com
wrote:
I am not sure what is the method used to model the coupling.
The method I used did not have any such issues at teeth up to 3 (a video
of the same was also posted here), below that I think it is not relevant.
attached here is the wire model for 3 , 4 and 5 teeth with just 1 mm gap
and it can be seen that the gap is consistent. Also I am not sure if these
low teeth models are of any use in real life.
The method I used needs functions to project a surface onto another, which
might be more clear from the posted video.
[image: Screenshot 2024-11-03 at 8.53.56 PM.png]
[image: Screenshot 2024-11-03 at 8.41.08 PM.png]
On Sun, 3 Nov 2024 at 19:59, Adrian Mariano via Discuss <
discuss@lists.openscad.org> wrote:
Here's a bit on the subtlety of the Hirth joint. I thought (like many
others, I suspect) that you could just create a triangle, stand it up
vertically, center it and scale it in the direction of the origin to create
the joint. But if you do this, you run into issues with mating between the
two halves of the joint that are quite obvious if the tooth count is low.
In order for the joints to mate, they have to touch at their half-way
points (which are on the XY plane in this construction). That constrains
the size of the triangle based on the other joint parameters. But if you
form the simple construction I described, you get these triangles, where
red is the bottom part and green is the top part. They are touching at the
triangle midles, but nowhere else. And furthermore, the triangles for one
joint don't meet at their corners!
[image: image.png]
To solve this problem, you need to rotate the triangle bottoms inward
until their vertices meet. That produces this set of triangles:
[image: image.png]
From here you can sweep the triangles toward the origin to make the
joint. But it's not in the direction of the normal to the triangle, since
the triangle bottoms were shifted inward by the rotation. The more
teeth you add, the smaller this effect becomes. It depends on how close to
2 you get with the ratio of tan(180/n) to tan(90/n). So for large numbers
of teeth it doesn't make much difference.
Note also that Sanjeev posted a case with an asymmetric tooth shape. I
don't know how to do the general case, but if you have a right triangle
like he showed, then it appears that everything will work with
appropriately scaled vertically positioned triangles---no funny tilt
required.
On Sat, Nov 2, 2024 at 9:38 AM Adrian Mariano avm4@cornell.edu wrote:
Ray, I tried out your code and ran into numerous problems. It is super
slow to preview. You don't give a convexity argument so stuff is missing
in preview. Render fails with a bunch of errors, perhaps due to the
reversed faces. So I can't really look at the shape very well. I tried
setting the tooth count to 5 and it gets really weird. My suspicion is
that you fell into the same trap that I did in not recognizing the subtlety
of the face spline design, but I can't be certain.... Or maybe you don't
care if it fits accurately--could be that the modeling errors in question
aren't a major source of error at high tooth count. Note that EVEN the
case of two symmetric parts is rather tricky to get right. I didn't
realize this at first. A fully correct implementation will let someone
make a 5 tooth design that could be used to set a mechanism at fifth of a
circle angles, for example.
With regards to terminology, my main reason for asking the question
about other face splines is that I'd call this module in BOSL2
face_spline(), except that if there are 4 other kinds of face spline then
that could be confusing, in which case perhaps it should be hirth() which
is more obscure.
On Thu, Oct 31, 2024 at 8:01 PM Raymond West via Discuss <
discuss@lists.openscad.org> wrote:
Hi Bob,
Here's the basic code for a parametric Hirth Joint. Spring loaded often
use as a slip clutch in torque sensitive situations, e.g screw drivers,
tapping heads, etc. Larger scale high speed turbines for shaft
connections, since easy to balance, no windage, etc. I've tested as
saving as stl, and re-importing, gives no errors. Easy enough to cut
out
the centre teeth if you don't want them.
// clutch.scad
ind= 50; // overall diameter
num= 20; // number of teeth
back = 6; //thickness of back
////////////////////////////////////////////
diam= ind/cos (180/num); // bigger to allow for chords
chord = diam*sin(180/num);
ridge= chord *sqrt(3)/3; // or set to whatever (denominator = 2 for 60
degrees.)
points=[
[0,0,ridge/2],
[diam/2,-chord/2,0],
[diam/2,+chord/2,0],
[diam/2,0,ridge]
];
faces=[
[0,1,2],
[0,1,3],
[0,2,3],
[1,2,3]
];
module wedge(){
polyhedron(points,faces,convexity=10);
}
//rotate wedge
intersection(){
translate([0,0,-back])
cylinder(d=ind,h=200,$fn=100);
union(){
for (j=[0:1:+1+360/num])
rotate([0,0,j360/num+0.5360/num]) wedge();
cylinder(d1=diam,d2=0,h=ridge/2,$fn=num);
translate([0,0,-back])
cylinder(d=diam,h=back,$fn=num);
}
}
//save as stl, then import to check for valid stl. (remove comments
below and run again)
/*
translate([0,0,6])
rotate([0,180,360/(num*2)])
import("P:/Docs/openscad/clutch.stl");
*/
On 26/10/2024 00:44, Bob Carlson via Discuss wrote:
I got really intrigued by the Hirth joint and have been working a
library entry that would generate them. I have it fully working,
apparently, because it renders perfectly as far as I can see. However when
I load one of the parts (a concave part) into PrusaSlicer, it reports
thousands of errors that it supposedly fixed. The visual rendering is fine,
but when you look at the slice it is completely screwed up.
First some explanation. When I looked up hirth joints I only saw flat
ones mentioned. The one I have actually encountered though is a conical
one. There is a concave part and a convex part. They fit together
perfectly. I had to invent some terminology since I did not find terms for
some things I found to be important. The outer center line is the plane
that passes through the midpoint of the teeth at the outer radius. In a
flat hirth joint all the teeth radiate from the center of this circle, call
it the origin. If the origin of the teeth is above the outer center line,
then joint has a conical shape and the two parts are concave and convex.
Each tooth at every point has the same profile, the top of the tooth
profile is either 60 or 90 degrees. The groove angle is the angle that the
groove forms from the origin to the outer radius. It will pass below (for a
convex part) the outer radius. It’s critical for making hirth joints
because it forms the tool path. The ridge angle is the angle formed by the
corresponding ridge.
If the joint is conical, then there is an inner center line that
passes through the center of the teeth at the inner radius. The tooth
height is the critical number to calculate. It is dependent on the number
of teeth, the profile angle and the inner and out radii. Something that
really complicates the mental gymnastics is that the tooth height is
smaller at the inner radius. My code adds a “base” of extra material at the
bottom of the convex part and the top of the concave part. What’s tricky is
positioning the base of the concave part relative to the inner center line.
The concave parts base is relatively easy to place because it depends on
the outer radius and center line.
I generate the raw teeth using the groove and ridge angles and
spherical coordinates to make two 2d tooth profiles. Then I complete a
tooth using skin(). A for loop generates the full set of N teeth. Then
intersection or difference is used the trim the teeth at the inner and
outer radii. I discovered something at that point, but solved it pretty
simply. When diffing a cylinder from the N teeth, each tooth took up a
small portion of the cylinder being diffed out. I had to raise the $fn on
the cylinder or tube being used so that I got enough points in each tooth
that diff or intersection was accurate. I kept raising it until the results
stopped improving. I ended up with the 16*360 you see in the code.
After I have the raw teeth, I generate a cone that is diffed away to
produce the chamfer at the top of the teeth. Then I add in the base. The
base also adds the “chamfer” at the bottom of the groove. It’s half the
size of the top chamfer to leave a little gap when the parts are joined.
When I comment out the everything but the raw teeth and import the
STL into PrusaSlicer, it reports errors fixed, but appears to slice
correctly when supports are added.
When I add the intersection to trim the raw teeth, the number of
reported errors goes way up.
When I add the diff to remove the chamfer, the number goes way up
When I add in the base, the number goes up again and it starts
reporting many open edges.
Throughout, OpenSCAD reports no errors. Using $fn at 16*360, manifold
renders in 4+ seconds. At 32*360, it’s 53+ seconds. I did check CSG and it
did not help.
Maybe the biggest hint is that the convex part uses almost identical
code, but produces no errors. Very weird.
So, is this an OpenSCAD problem? Or something in my code?
It’s also possible that my math is off somewhere. My formal trig
training was 60 years ago. However I doubt a math error is responsible for
the slicing problem and STL errors.
-Bob
include <BOSL2/std.scad>
include <BOSL2/structs.scad>
// Number of Teeth
_n = 36; // Number Of Teeth
// Inner Radius
_ir = 30;
// Outer Radius
_or = 50;
// Is the coupling conical?
_conic = 10;
// Tooth Profile Angle
_profile = 60; // [60, 90]
// Percentage of tooth height
_chamfer = 5; // Default 5%
_base = 1;
$fn = 180;
tiny = 1 / 1024;
hirth_concave();
_irRatio = _ir / _or;
_toothAngle = 360/_n;
_toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2);
_chamferHeight = _chamfer * _toothHeight / 100;
_grooveAngle = atan(((_toothHeight/2) + _conic) / _or);
_ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or);
_innerCenterLine = (1 - _irRatio) * _conic;
_stackHeight = _innerCenterLine + _toothHeight + 2*_base;
_tubeHeight = 2*_conic + 2*_base + 2*_toothHeight;
module hirth_concave() {
zrot(_toothAngle/2)
union() {
difference() {
intersection() {
union() {
for (i = [0 : 360/_n : 359])
zrot(i)
_profileF();
}
tube(ir = _ir, or = _or, anchor = CENTER, l =
_tubeHeight, orient = UP, $fn = 16*360);
}
_chamferF();
zcyl(r = _ir, h = _tubeHeight, $fn = 16*360, anchor =
}
_baseF();
}
} // hirth_concave
module _profileF() {
IR = _ir * .5;
OR = _or * 1.5;
tI = [spherical_to_xyz(IR, 0, _grooveAngle + 90),
spherical_to_xyz(IR, _toothAngle/2, _ridgeAngle + 90),
spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)];
tO = [spherical_to_xyz(OR, 0, _grooveAngle + 90),
spherical_to_xyz(OR, _toothAngle/2, _ridgeAngle + 90),
spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)];
up(_conic)
skin([tI, tO], slices = 0);
}
module _chamferF() {
A = -_toothHeight/2 - .1;
B = -_toothHeight/2 + _chamferHeight;
pts = [[0, _conic],
[_or+tiny, A],
[_or+tiny, B]];
rotate_extrude(angle = 360, $fn = 16*360)
polygon(pts);
}
module _baseF() {
A = _base + _irRatio*_toothHeight/2 + _innerCenterLine;
B = _irRatio * (_toothHeight/2 - _chamferHeight/2) +
C = _toothHeight/2 - _chamferHeight/2;
pts = [
[_ir, A],
[_ir, B],
[_or, C],
[_or, A]
];
rotate_extrude(angle = 360, $fn = 360*16)
polygon(pts);
}
OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org
It appears that you found a construction method that works, but your vague
description isn't enough for me to understand what it is. Do you have a
method that can construct a part that mates with itself? Or is it that you
can construct one part and then through a projection scheme, build a mate
for it?
I think that low tooth count splines are useful for controlling alignment
of parts, like if you want something that turns in 45 degree increments and
locks into position you can do this with 8 teeth.
On Sun, Nov 3, 2024 at 10:25 AM Sanjeev Prabhakar <sprabhakar2006@gmail.com>
wrote:
> I am not sure what is the method used to model the coupling.
> The method I used did not have any such issues at teeth up to 3 (a video
> of the same was also posted here), below that I think it is not relevant.
>
> attached here is the wire model for 3 , 4 and 5 teeth with just 1 mm gap
> and it can be seen that the gap is consistent. Also I am not sure if these
> low teeth models are of any use in real life.
>
> The method I used needs functions to project a surface onto another, which
> might be more clear from the posted video.
> [image: Screenshot 2024-11-03 at 8.53.56 PM.png]
> [image: Screenshot 2024-11-03 at 8.41.08 PM.png]
>
> On Sun, 3 Nov 2024 at 19:59, Adrian Mariano via Discuss <
> discuss@lists.openscad.org> wrote:
>
>> Here's a bit on the subtlety of the Hirth joint. I thought (like many
>> others, I suspect) that you could just create a triangle, stand it up
>> vertically, center it and scale it in the direction of the origin to create
>> the joint. But if you do this, you run into issues with mating between the
>> two halves of the joint that are quite obvious if the tooth count is low.
>> In order for the joints to mate, they have to touch at their half-way
>> points (which are on the XY plane in this construction). That constrains
>> the size of the triangle based on the other joint parameters. But if you
>> form the simple construction I described, you get these triangles, where
>> red is the bottom part and green is the top part. They are touching at the
>> triangle midles, but nowhere else. And furthermore, the triangles for one
>> joint don't meet at their corners!
>>
>> [image: image.png]
>>
>> To solve this problem, you need to rotate the triangle bottoms inward
>> until their vertices meet. That produces this set of triangles:
>>
>> [image: image.png]
>> From here you can sweep the triangles toward the origin to make the
>> joint. But it's not in the direction of the normal to the triangle, since
>> the triangle bottoms were shifted inward by the rotation. The more
>> teeth you add, the smaller this effect becomes. It depends on how close to
>> 2 you get with the ratio of tan(180/n) to tan(90/n). So for large numbers
>> of teeth it doesn't make much difference.
>>
>> Note also that Sanjeev posted a case with an asymmetric tooth shape. I
>> don't know how to do the general case, but if you have a right triangle
>> like he showed, then it appears that everything will work with
>> appropriately scaled vertically positioned triangles---no funny tilt
>> required.
>>
>> On Sat, Nov 2, 2024 at 9:38 AM Adrian Mariano <avm4@cornell.edu> wrote:
>>
>>> Ray, I tried out your code and ran into numerous problems. It is super
>>> slow to preview. You don't give a convexity argument so stuff is missing
>>> in preview. Render fails with a bunch of errors, perhaps due to the
>>> reversed faces. So I can't really look at the shape very well. I tried
>>> setting the tooth count to 5 and it gets really weird. My suspicion is
>>> that you fell into the same trap that I did in not recognizing the subtlety
>>> of the face spline design, but I can't be certain.... Or maybe you don't
>>> care if it fits accurately--could be that the modeling errors in question
>>> aren't a major source of error at high tooth count. Note that EVEN the
>>> case of two symmetric parts is rather tricky to get right. I didn't
>>> realize this at first. A fully correct implementation will let someone
>>> make a 5 tooth design that could be used to set a mechanism at fifth of a
>>> circle angles, for example.
>>>
>>> With regards to terminology, my main reason for asking the question
>>> about other face splines is that I'd call this module in BOSL2
>>> face_spline(), except that if there are 4 other kinds of face spline then
>>> that could be confusing, in which case perhaps it should be hirth() which
>>> is more obscure.
>>>
>>> On Thu, Oct 31, 2024 at 8:01 PM Raymond West via Discuss <
>>> discuss@lists.openscad.org> wrote:
>>>
>>>> Hi Bob,
>>>>
>>>> Here's the basic code for a parametric Hirth Joint. Spring loaded often
>>>> use as a slip clutch in torque sensitive situations, e.g screw drivers,
>>>> tapping heads, etc. Larger scale high speed turbines for shaft
>>>> connections, since easy to balance, no windage, etc. I've tested as
>>>> saving as stl, and re-importing, gives no errors. Easy enough to cut
>>>> out
>>>> the centre teeth if you don't want them.
>>>>
>>>> // clutch.scad
>>>>
>>>> ind= 50; // overall diameter
>>>> num= 20; // number of teeth
>>>> back = 6; //thickness of back
>>>> ////////////////////////////////////////////
>>>>
>>>>
>>>> diam= ind/cos (180/num); // bigger to allow for chords
>>>> chord = diam*sin(180/num);
>>>>
>>>> ridge= chord *sqrt(3)/3; // or set to whatever (denominator = 2 for 60
>>>> degrees.)
>>>>
>>>> points=[
>>>> [0,0,ridge/2],
>>>> [diam/2,-chord/2,0],
>>>> [diam/2,+chord/2,0],
>>>> [diam/2,0,ridge]
>>>> ];
>>>> faces=[
>>>> [0,1,2],
>>>> [0,1,3],
>>>> [0,2,3],
>>>> [1,2,3]
>>>> ];
>>>>
>>>> module wedge(){
>>>> polyhedron(points,faces,convexity=10);
>>>> }
>>>>
>>>> //rotate wedge
>>>>
>>>> intersection(){
>>>> translate([0,0,-back])
>>>> cylinder(d=ind,h=200,$fn=100);
>>>> union(){
>>>> for (j=[0:1:+1+360/num])
>>>> rotate([0,0,j*360/num+0.5*360/num]) wedge();
>>>> cylinder(d1=diam,d2=0,h=ridge/2,$fn=num);
>>>> translate([0,0,-back])
>>>> cylinder(d=diam,h=back,$fn=num);
>>>> }
>>>> }
>>>>
>>>> //save as stl, then import to check for valid stl. (remove comments
>>>> below and run again)
>>>>
>>>> /*
>>>> translate([0,0,6])
>>>> rotate([0,180,360/(num*2)])
>>>> import("P:/Docs/openscad/clutch.stl");
>>>> */
>>>>
>>>>
>>>> On 26/10/2024 00:44, Bob Carlson via Discuss wrote:
>>>> > I got really intrigued by the Hirth joint and have been working a
>>>> library entry that would generate them. I have it fully working,
>>>> apparently, because it renders perfectly as far as I can see. However when
>>>> I load one of the parts (a concave part) into PrusaSlicer, it reports
>>>> thousands of errors that it supposedly fixed. The visual rendering is fine,
>>>> but when you look at the slice it is completely screwed up.
>>>> >
>>>> > First some explanation. When I looked up hirth joints I only saw flat
>>>> ones mentioned. The one I have actually encountered though is a conical
>>>> one. There is a concave part and a convex part. They fit together
>>>> perfectly. I had to invent some terminology since I did not find terms for
>>>> some things I found to be important. The outer center line is the plane
>>>> that passes through the midpoint of the teeth at the outer radius. In a
>>>> flat hirth joint all the teeth radiate from the center of this circle, call
>>>> it the origin. If the origin of the teeth is above the outer center line,
>>>> then joint has a conical shape and the two parts are concave and convex.
>>>> >
>>>> > Each tooth at every point has the same profile, the top of the tooth
>>>> profile is either 60 or 90 degrees. The groove angle is the angle that the
>>>> groove forms from the origin to the outer radius. It will pass below (for a
>>>> convex part) the outer radius. It’s critical for making hirth joints
>>>> because it forms the tool path. The ridge angle is the angle formed by the
>>>> corresponding ridge.
>>>> >
>>>> > If the joint is conical, then there is an inner center line that
>>>> passes through the center of the teeth at the inner radius. The tooth
>>>> height is the critical number to calculate. It is dependent on the number
>>>> of teeth, the profile angle and the inner and out radii. Something that
>>>> really complicates the mental gymnastics is that the tooth height is
>>>> smaller at the inner radius. My code adds a “base” of extra material at the
>>>> bottom of the convex part and the top of the concave part. What’s tricky is
>>>> positioning the base of the concave part relative to the inner center line.
>>>> The concave parts base is relatively easy to place because it depends on
>>>> the outer radius and center line.
>>>> >
>>>> > I generate the raw teeth using the groove and ridge angles and
>>>> spherical coordinates to make two 2d tooth profiles. Then I complete a
>>>> tooth using skin(). A for loop generates the full set of N teeth. Then
>>>> intersection or difference is used the trim the teeth at the inner and
>>>> outer radii. I discovered something at that point, but solved it pretty
>>>> simply. When diffing a cylinder from the N teeth, each tooth took up a
>>>> small portion of the cylinder being diffed out. I had to raise the $fn on
>>>> the cylinder or tube being used so that I got enough points in each tooth
>>>> that diff or intersection was accurate. I kept raising it until the results
>>>> stopped improving. I ended up with the 16*360 you see in the code.
>>>> >
>>>> > After I have the raw teeth, I generate a cone that is diffed away to
>>>> produce the chamfer at the top of the teeth. Then I add in the base. The
>>>> base also adds the “chamfer” at the bottom of the groove. It’s half the
>>>> size of the top chamfer to leave a little gap when the parts are joined.
>>>> >
>>>> > When I comment out the everything but the raw teeth and import the
>>>> STL into PrusaSlicer, it reports errors fixed, but appears to slice
>>>> correctly when supports are added.
>>>> >
>>>> > When I add the intersection to trim the raw teeth, the number of
>>>> reported errors goes way up.
>>>> >
>>>> > When I add the diff to remove the chamfer, the number goes way up
>>>> again.
>>>> >
>>>> > When I add in the base, the number goes up again and it starts
>>>> reporting many open edges.
>>>> >
>>>> > Throughout, OpenSCAD reports no errors. Using $fn at 16*360, manifold
>>>> renders in 4+ seconds. At 32*360, it’s 53+ seconds. I did check CSG and it
>>>> did not help.
>>>> >
>>>> > Maybe the biggest hint is that the convex part uses almost identical
>>>> code, but produces no errors. Very weird.
>>>> >
>>>> > So, is this an OpenSCAD problem? Or something in my code?
>>>> >
>>>> > It’s also possible that my math is off somewhere. My formal trig
>>>> training was 60 years ago. However I doubt a math error is responsible for
>>>> the slicing problem and STL errors.
>>>> >
>>>> > -Bob
>>>> >
>>>> >
>>>> > include <BOSL2/std.scad>
>>>> > include <BOSL2/structs.scad>
>>>> >
>>>> > // Number of Teeth
>>>> > _n = 36; // Number Of Teeth
>>>> >
>>>> > // Inner Radius
>>>> > _ir = 30;
>>>> > // Outer Radius
>>>> > _or = 50;
>>>> > // Is the coupling conical?
>>>> > _conic = 10;
>>>> > // Tooth Profile Angle
>>>> > _profile = 60; // [60, 90]
>>>> > // Percentage of tooth height
>>>> > _chamfer = 5; // Default 5%
>>>> > _base = 1;
>>>> >
>>>> > $fn = 180;
>>>> > tiny = 1 / 1024;
>>>> >
>>>> > hirth_concave();
>>>> >
>>>> > _irRatio = _ir / _or;
>>>> > _toothAngle = 360/_n;
>>>> > _toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2);
>>>> > _chamferHeight = _chamfer * _toothHeight / 100;
>>>> > _grooveAngle = atan(((_toothHeight/2) + _conic) / _or);
>>>> > _ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or);
>>>> > _innerCenterLine = (1 - _irRatio) * _conic;
>>>> > _stackHeight = _innerCenterLine + _toothHeight + 2*_base;
>>>> > _tubeHeight = 2*_conic + 2*_base + 2*_toothHeight;
>>>> >
>>>> > module hirth_concave() {
>>>> > zrot(_toothAngle/2)
>>>> > union() {
>>>> > difference() {
>>>> > intersection() {
>>>> > union() {
>>>> > for (i = [0 : 360/_n : 359])
>>>> > zrot(i)
>>>> > _profileF();
>>>> > }
>>>> > tube(ir = _ir, or = _or, anchor = CENTER, l =
>>>> _tubeHeight, orient = UP, $fn = 16*360);
>>>> > }
>>>> > _chamferF();
>>>> > zcyl(r = _ir, h = _tubeHeight, $fn = 16*360, anchor =
>>>> CENTER);
>>>> > }
>>>> > _baseF();
>>>> > }
>>>> > } // hirth_concave
>>>> >
>>>> > module _profileF() {
>>>> > IR = _ir * .5;
>>>> > OR = _or * 1.5;
>>>> > tI = [spherical_to_xyz(IR, 0, _grooveAngle + 90),
>>>> > spherical_to_xyz(IR, _toothAngle/2, _ridgeAngle + 90),
>>>> > spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)];
>>>> >
>>>> > tO = [spherical_to_xyz(OR, 0, _grooveAngle + 90),
>>>> > spherical_to_xyz(OR, _toothAngle/2, _ridgeAngle + 90),
>>>> > spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)];
>>>> > up(_conic)
>>>> > skin([tI, tO], slices = 0);
>>>> > }
>>>> >
>>>> >
>>>> > module _chamferF() {
>>>> > A = -_toothHeight/2 - .1;
>>>> > B = -_toothHeight/2 + _chamferHeight;
>>>> >
>>>> > pts = [[0, _conic],
>>>> > [_or+tiny, A],
>>>> > [_or+tiny, B]];
>>>> >
>>>> > rotate_extrude(angle = 360, $fn = 16*360)
>>>> > polygon(pts);
>>>> > }
>>>> >
>>>> > module _baseF() {
>>>> > A = _base + _irRatio*_toothHeight/2 + _innerCenterLine;
>>>> > B = _irRatio * (_toothHeight/2 - _chamferHeight/2) +
>>>> _innerCenterLine;
>>>> > C = _toothHeight/2 - _chamferHeight/2;
>>>> > pts = [
>>>> > [_ir, A],
>>>> > [_ir, B],
>>>> > [_or, C],
>>>> > [_or, A]
>>>> > ];
>>>> >
>>>> > rotate_extrude(angle = 360, $fn = 360*16)
>>>> > polygon(pts);
>>>> > }
>>>> > _______________________________________________
>>>> > OpenSCAD mailing list
>>>> > To unsubscribe send an email to discuss-leave@lists.openscad.org
>>>> _______________________________________________
>>>> OpenSCAD mailing list
>>>> To unsubscribe send an email to discuss-leave@lists.openscad.org
>>>>
>>> _______________________________________________
>> OpenSCAD mailing list
>> To unsubscribe send an email to discuss-leave@lists.openscad.org
>>
>
SP
Sanjeev Prabhakar
Sun, Nov 3, 2024 4:50 PM
Description of the method would need some time and it is a little late in
India.
Will write tomorrow morning. I thought my youtube video explained the
process well (not the functions obviously).
On Sun, 3 Nov 2024 at 22:04, Adrian Mariano avm4@cornell.edu wrote:
It appears that you found a construction method that works, but your vague
description isn't enough for me to understand what it is. Do you have a
method that can construct a part that mates with itself? Or is it that you
can construct one part and then through a projection scheme, build a mate
for it?
I think that low tooth count splines are useful for controlling alignment
of parts, like if you want something that turns in 45 degree increments and
locks into position you can do this with 8 teeth.
On Sun, Nov 3, 2024 at 10:25 AM Sanjeev Prabhakar <
sprabhakar2006@gmail.com> wrote:
I am not sure what is the method used to model the coupling.
The method I used did not have any such issues at teeth up to 3 (a video
of the same was also posted here), below that I think it is not relevant.
attached here is the wire model for 3 , 4 and 5 teeth with just 1 mm gap
and it can be seen that the gap is consistent. Also I am not sure if these
low teeth models are of any use in real life.
The method I used needs functions to project a surface onto another,
which might be more clear from the posted video.
[image: Screenshot 2024-11-03 at 8.53.56 PM.png]
[image: Screenshot 2024-11-03 at 8.41.08 PM.png]
On Sun, 3 Nov 2024 at 19:59, Adrian Mariano via Discuss <
discuss@lists.openscad.org> wrote:
Here's a bit on the subtlety of the Hirth joint. I thought (like many
others, I suspect) that you could just create a triangle, stand it up
vertically, center it and scale it in the direction of the origin to create
the joint. But if you do this, you run into issues with mating between the
two halves of the joint that are quite obvious if the tooth count is low.
In order for the joints to mate, they have to touch at their half-way
points (which are on the XY plane in this construction). That constrains
the size of the triangle based on the other joint parameters. But if you
form the simple construction I described, you get these triangles, where
red is the bottom part and green is the top part. They are touching at the
triangle midles, but nowhere else. And furthermore, the triangles for one
joint don't meet at their corners!
[image: image.png]
To solve this problem, you need to rotate the triangle bottoms inward
until their vertices meet. That produces this set of triangles:
[image: image.png]
From here you can sweep the triangles toward the origin to make the
joint. But it's not in the direction of the normal to the triangle, since
the triangle bottoms were shifted inward by the rotation. The more
teeth you add, the smaller this effect becomes. It depends on how close to
2 you get with the ratio of tan(180/n) to tan(90/n). So for large numbers
of teeth it doesn't make much difference.
Note also that Sanjeev posted a case with an asymmetric tooth shape. I
don't know how to do the general case, but if you have a right triangle
like he showed, then it appears that everything will work with
appropriately scaled vertically positioned triangles---no funny tilt
required.
On Sat, Nov 2, 2024 at 9:38 AM Adrian Mariano avm4@cornell.edu wrote:
Ray, I tried out your code and ran into numerous problems. It is super
slow to preview. You don't give a convexity argument so stuff is missing
in preview. Render fails with a bunch of errors, perhaps due to the
reversed faces. So I can't really look at the shape very well. I tried
setting the tooth count to 5 and it gets really weird. My suspicion is
that you fell into the same trap that I did in not recognizing the subtlety
of the face spline design, but I can't be certain.... Or maybe you don't
care if it fits accurately--could be that the modeling errors in question
aren't a major source of error at high tooth count. Note that EVEN the
case of two symmetric parts is rather tricky to get right. I didn't
realize this at first. A fully correct implementation will let someone
make a 5 tooth design that could be used to set a mechanism at fifth of a
circle angles, for example.
With regards to terminology, my main reason for asking the question
about other face splines is that I'd call this module in BOSL2
face_spline(), except that if there are 4 other kinds of face spline then
that could be confusing, in which case perhaps it should be hirth() which
is more obscure.
On Thu, Oct 31, 2024 at 8:01 PM Raymond West via Discuss <
discuss@lists.openscad.org> wrote:
Hi Bob,
Here's the basic code for a parametric Hirth Joint. Spring loaded
often
use as a slip clutch in torque sensitive situations, e.g screw
drivers,
tapping heads, etc. Larger scale high speed turbines for shaft
connections, since easy to balance, no windage, etc. I've tested as
saving as stl, and re-importing, gives no errors. Easy enough to cut
out
the centre teeth if you don't want them.
// clutch.scad
ind= 50; // overall diameter
num= 20; // number of teeth
back = 6; //thickness of back
////////////////////////////////////////////
diam= ind/cos (180/num); // bigger to allow for chords
chord = diam*sin(180/num);
ridge= chord *sqrt(3)/3; // or set to whatever (denominator = 2 for
60
degrees.)
points=[
[0,0,ridge/2],
[diam/2,-chord/2,0],
[diam/2,+chord/2,0],
[diam/2,0,ridge]
];
faces=[
[0,1,2],
[0,1,3],
[0,2,3],
[1,2,3]
];
module wedge(){
polyhedron(points,faces,convexity=10);
}
//rotate wedge
intersection(){
translate([0,0,-back])
cylinder(d=ind,h=200,$fn=100);
union(){
for (j=[0:1:+1+360/num])
rotate([0,0,j360/num+0.5360/num]) wedge();
cylinder(d1=diam,d2=0,h=ridge/2,$fn=num);
translate([0,0,-back])
cylinder(d=diam,h=back,$fn=num);
}
}
//save as stl, then import to check for valid stl. (remove comments
below and run again)
/*
translate([0,0,6])
rotate([0,180,360/(num*2)])
import("P:/Docs/openscad/clutch.stl");
*/
On 26/10/2024 00:44, Bob Carlson via Discuss wrote:
I got really intrigued by the Hirth joint and have been working a
library entry that would generate them. I have it fully working,
apparently, because it renders perfectly as far as I can see. However when
I load one of the parts (a concave part) into PrusaSlicer, it reports
thousands of errors that it supposedly fixed. The visual rendering is fine,
but when you look at the slice it is completely screwed up.
First some explanation. When I looked up hirth joints I only saw
flat ones mentioned. The one I have actually encountered though is a
conical one. There is a concave part and a convex part. They fit together
perfectly. I had to invent some terminology since I did not find terms for
some things I found to be important. The outer center line is the plane
that passes through the midpoint of the teeth at the outer radius. In a
flat hirth joint all the teeth radiate from the center of this circle, call
it the origin. If the origin of the teeth is above the outer center line,
then joint has a conical shape and the two parts are concave and convex.
Each tooth at every point has the same profile, the top of the tooth
profile is either 60 or 90 degrees. The groove angle is the angle that the
groove forms from the origin to the outer radius. It will pass below (for a
convex part) the outer radius. It’s critical for making hirth joints
because it forms the tool path. The ridge angle is the angle formed by the
corresponding ridge.
If the joint is conical, then there is an inner center line that
passes through the center of the teeth at the inner radius. The tooth
height is the critical number to calculate. It is dependent on the number
of teeth, the profile angle and the inner and out radii. Something that
really complicates the mental gymnastics is that the tooth height is
smaller at the inner radius. My code adds a “base” of extra material at the
bottom of the convex part and the top of the concave part. What’s tricky is
positioning the base of the concave part relative to the inner center line.
The concave parts base is relatively easy to place because it depends on
the outer radius and center line.
I generate the raw teeth using the groove and ridge angles and
spherical coordinates to make two 2d tooth profiles. Then I complete a
tooth using skin(). A for loop generates the full set of N teeth. Then
intersection or difference is used the trim the teeth at the inner and
outer radii. I discovered something at that point, but solved it pretty
simply. When diffing a cylinder from the N teeth, each tooth took up a
small portion of the cylinder being diffed out. I had to raise the $fn on
the cylinder or tube being used so that I got enough points in each tooth
that diff or intersection was accurate. I kept raising it until the results
stopped improving. I ended up with the 16*360 you see in the code.
After I have the raw teeth, I generate a cone that is diffed away to
produce the chamfer at the top of the teeth. Then I add in the base. The
base also adds the “chamfer” at the bottom of the groove. It’s half the
size of the top chamfer to leave a little gap when the parts are joined.
When I comment out the everything but the raw teeth and import the
STL into PrusaSlicer, it reports errors fixed, but appears to slice
correctly when supports are added.
When I add the intersection to trim the raw teeth, the number of
reported errors goes way up.
When I add the diff to remove the chamfer, the number goes way up
When I add in the base, the number goes up again and it starts
reporting many open edges.
Throughout, OpenSCAD reports no errors. Using $fn at 16*360,
manifold renders in 4+ seconds. At 32*360, it’s 53+ seconds. I did check
CSG and it did not help.
Maybe the biggest hint is that the convex part uses almost identical
code, but produces no errors. Very weird.
So, is this an OpenSCAD problem? Or something in my code?
It’s also possible that my math is off somewhere. My formal trig
training was 60 years ago. However I doubt a math error is responsible for
the slicing problem and STL errors.
-Bob
include <BOSL2/std.scad>
include <BOSL2/structs.scad>
// Number of Teeth
_n = 36; // Number Of Teeth
// Inner Radius
_ir = 30;
// Outer Radius
_or = 50;
// Is the coupling conical?
_conic = 10;
// Tooth Profile Angle
_profile = 60; // [60, 90]
// Percentage of tooth height
_chamfer = 5; // Default 5%
_base = 1;
$fn = 180;
tiny = 1 / 1024;
hirth_concave();
_irRatio = _ir / _or;
_toothAngle = 360/_n;
_toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2);
_chamferHeight = _chamfer * _toothHeight / 100;
_grooveAngle = atan(((_toothHeight/2) + _conic) / _or);
_ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or);
_innerCenterLine = (1 - _irRatio) * _conic;
_stackHeight = _innerCenterLine + _toothHeight + 2*_base;
_tubeHeight = 2*_conic + 2*_base + 2*_toothHeight;
module hirth_concave() {
zrot(_toothAngle/2)
union() {
difference() {
intersection() {
union() {
for (i = [0 : 360/_n : 359])
zrot(i)
_profileF();
}
tube(ir = _ir, or = _or, anchor = CENTER, l =
_tubeHeight, orient = UP, $fn = 16*360);
}
_chamferF();
zcyl(r = _ir, h = _tubeHeight, $fn = 16*360, anchor =
}
_baseF();
}
} // hirth_concave
module _profileF() {
IR = _ir * .5;
OR = _or * 1.5;
tI = [spherical_to_xyz(IR, 0, _grooveAngle + 90),
spherical_to_xyz(IR, _toothAngle/2, _ridgeAngle + 90),
spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)];
tO = [spherical_to_xyz(OR, 0, _grooveAngle + 90),
spherical_to_xyz(OR, _toothAngle/2, _ridgeAngle + 90),
spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)];
up(_conic)
skin([tI, tO], slices = 0);
}
module _chamferF() {
A = -_toothHeight/2 - .1;
B = -_toothHeight/2 + _chamferHeight;
pts = [[0, _conic],
[_or+tiny, A],
[_or+tiny, B]];
rotate_extrude(angle = 360, $fn = 16*360)
polygon(pts);
}
module _baseF() {
A = _base + _irRatio*_toothHeight/2 + _innerCenterLine;
B = _irRatio * (_toothHeight/2 - _chamferHeight/2) +
C = _toothHeight/2 - _chamferHeight/2;
pts = [
[_ir, A],
[_ir, B],
[_or, C],
[_or, A]
];
rotate_extrude(angle = 360, $fn = 360*16)
polygon(pts);
}
OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org
Description of the method would need some time and it is a little late in
India.
Will write tomorrow morning. I thought my youtube video explained the
process well (not the functions obviously).
On Sun, 3 Nov 2024 at 22:04, Adrian Mariano <avm4@cornell.edu> wrote:
> It appears that you found a construction method that works, but your vague
> description isn't enough for me to understand what it is. Do you have a
> method that can construct a part that mates with itself? Or is it that you
> can construct one part and then through a projection scheme, build a mate
> for it?
>
> I think that low tooth count splines are useful for controlling alignment
> of parts, like if you want something that turns in 45 degree increments and
> locks into position you can do this with 8 teeth.
>
> On Sun, Nov 3, 2024 at 10:25 AM Sanjeev Prabhakar <
> sprabhakar2006@gmail.com> wrote:
>
>> I am not sure what is the method used to model the coupling.
>> The method I used did not have any such issues at teeth up to 3 (a video
>> of the same was also posted here), below that I think it is not relevant.
>>
>> attached here is the wire model for 3 , 4 and 5 teeth with just 1 mm gap
>> and it can be seen that the gap is consistent. Also I am not sure if these
>> low teeth models are of any use in real life.
>>
>> The method I used needs functions to project a surface onto another,
>> which might be more clear from the posted video.
>> [image: Screenshot 2024-11-03 at 8.53.56 PM.png]
>> [image: Screenshot 2024-11-03 at 8.41.08 PM.png]
>>
>> On Sun, 3 Nov 2024 at 19:59, Adrian Mariano via Discuss <
>> discuss@lists.openscad.org> wrote:
>>
>>> Here's a bit on the subtlety of the Hirth joint. I thought (like many
>>> others, I suspect) that you could just create a triangle, stand it up
>>> vertically, center it and scale it in the direction of the origin to create
>>> the joint. But if you do this, you run into issues with mating between the
>>> two halves of the joint that are quite obvious if the tooth count is low.
>>> In order for the joints to mate, they have to touch at their half-way
>>> points (which are on the XY plane in this construction). That constrains
>>> the size of the triangle based on the other joint parameters. But if you
>>> form the simple construction I described, you get these triangles, where
>>> red is the bottom part and green is the top part. They are touching at the
>>> triangle midles, but nowhere else. And furthermore, the triangles for one
>>> joint don't meet at their corners!
>>>
>>> [image: image.png]
>>>
>>> To solve this problem, you need to rotate the triangle bottoms inward
>>> until their vertices meet. That produces this set of triangles:
>>>
>>> [image: image.png]
>>> From here you can sweep the triangles toward the origin to make the
>>> joint. But it's not in the direction of the normal to the triangle, since
>>> the triangle bottoms were shifted inward by the rotation. The more
>>> teeth you add, the smaller this effect becomes. It depends on how close to
>>> 2 you get with the ratio of tan(180/n) to tan(90/n). So for large numbers
>>> of teeth it doesn't make much difference.
>>>
>>> Note also that Sanjeev posted a case with an asymmetric tooth shape. I
>>> don't know how to do the general case, but if you have a right triangle
>>> like he showed, then it appears that everything will work with
>>> appropriately scaled vertically positioned triangles---no funny tilt
>>> required.
>>>
>>> On Sat, Nov 2, 2024 at 9:38 AM Adrian Mariano <avm4@cornell.edu> wrote:
>>>
>>>> Ray, I tried out your code and ran into numerous problems. It is super
>>>> slow to preview. You don't give a convexity argument so stuff is missing
>>>> in preview. Render fails with a bunch of errors, perhaps due to the
>>>> reversed faces. So I can't really look at the shape very well. I tried
>>>> setting the tooth count to 5 and it gets really weird. My suspicion is
>>>> that you fell into the same trap that I did in not recognizing the subtlety
>>>> of the face spline design, but I can't be certain.... Or maybe you don't
>>>> care if it fits accurately--could be that the modeling errors in question
>>>> aren't a major source of error at high tooth count. Note that EVEN the
>>>> case of two symmetric parts is rather tricky to get right. I didn't
>>>> realize this at first. A fully correct implementation will let someone
>>>> make a 5 tooth design that could be used to set a mechanism at fifth of a
>>>> circle angles, for example.
>>>>
>>>> With regards to terminology, my main reason for asking the question
>>>> about other face splines is that I'd call this module in BOSL2
>>>> face_spline(), except that if there are 4 other kinds of face spline then
>>>> that could be confusing, in which case perhaps it should be hirth() which
>>>> is more obscure.
>>>>
>>>> On Thu, Oct 31, 2024 at 8:01 PM Raymond West via Discuss <
>>>> discuss@lists.openscad.org> wrote:
>>>>
>>>>> Hi Bob,
>>>>>
>>>>> Here's the basic code for a parametric Hirth Joint. Spring loaded
>>>>> often
>>>>> use as a slip clutch in torque sensitive situations, e.g screw
>>>>> drivers,
>>>>> tapping heads, etc. Larger scale high speed turbines for shaft
>>>>> connections, since easy to balance, no windage, etc. I've tested as
>>>>> saving as stl, and re-importing, gives no errors. Easy enough to cut
>>>>> out
>>>>> the centre teeth if you don't want them.
>>>>>
>>>>> // clutch.scad
>>>>>
>>>>> ind= 50; // overall diameter
>>>>> num= 20; // number of teeth
>>>>> back = 6; //thickness of back
>>>>> ////////////////////////////////////////////
>>>>>
>>>>>
>>>>> diam= ind/cos (180/num); // bigger to allow for chords
>>>>> chord = diam*sin(180/num);
>>>>>
>>>>> ridge= chord *sqrt(3)/3; // or set to whatever (denominator = 2 for
>>>>> 60
>>>>> degrees.)
>>>>>
>>>>> points=[
>>>>> [0,0,ridge/2],
>>>>> [diam/2,-chord/2,0],
>>>>> [diam/2,+chord/2,0],
>>>>> [diam/2,0,ridge]
>>>>> ];
>>>>> faces=[
>>>>> [0,1,2],
>>>>> [0,1,3],
>>>>> [0,2,3],
>>>>> [1,2,3]
>>>>> ];
>>>>>
>>>>> module wedge(){
>>>>> polyhedron(points,faces,convexity=10);
>>>>> }
>>>>>
>>>>> //rotate wedge
>>>>>
>>>>> intersection(){
>>>>> translate([0,0,-back])
>>>>> cylinder(d=ind,h=200,$fn=100);
>>>>> union(){
>>>>> for (j=[0:1:+1+360/num])
>>>>> rotate([0,0,j*360/num+0.5*360/num]) wedge();
>>>>> cylinder(d1=diam,d2=0,h=ridge/2,$fn=num);
>>>>> translate([0,0,-back])
>>>>> cylinder(d=diam,h=back,$fn=num);
>>>>> }
>>>>> }
>>>>>
>>>>> //save as stl, then import to check for valid stl. (remove comments
>>>>> below and run again)
>>>>>
>>>>> /*
>>>>> translate([0,0,6])
>>>>> rotate([0,180,360/(num*2)])
>>>>> import("P:/Docs/openscad/clutch.stl");
>>>>> */
>>>>>
>>>>>
>>>>> On 26/10/2024 00:44, Bob Carlson via Discuss wrote:
>>>>> > I got really intrigued by the Hirth joint and have been working a
>>>>> library entry that would generate them. I have it fully working,
>>>>> apparently, because it renders perfectly as far as I can see. However when
>>>>> I load one of the parts (a concave part) into PrusaSlicer, it reports
>>>>> thousands of errors that it supposedly fixed. The visual rendering is fine,
>>>>> but when you look at the slice it is completely screwed up.
>>>>> >
>>>>> > First some explanation. When I looked up hirth joints I only saw
>>>>> flat ones mentioned. The one I have actually encountered though is a
>>>>> conical one. There is a concave part and a convex part. They fit together
>>>>> perfectly. I had to invent some terminology since I did not find terms for
>>>>> some things I found to be important. The outer center line is the plane
>>>>> that passes through the midpoint of the teeth at the outer radius. In a
>>>>> flat hirth joint all the teeth radiate from the center of this circle, call
>>>>> it the origin. If the origin of the teeth is above the outer center line,
>>>>> then joint has a conical shape and the two parts are concave and convex.
>>>>> >
>>>>> > Each tooth at every point has the same profile, the top of the tooth
>>>>> profile is either 60 or 90 degrees. The groove angle is the angle that the
>>>>> groove forms from the origin to the outer radius. It will pass below (for a
>>>>> convex part) the outer radius. It’s critical for making hirth joints
>>>>> because it forms the tool path. The ridge angle is the angle formed by the
>>>>> corresponding ridge.
>>>>> >
>>>>> > If the joint is conical, then there is an inner center line that
>>>>> passes through the center of the teeth at the inner radius. The tooth
>>>>> height is the critical number to calculate. It is dependent on the number
>>>>> of teeth, the profile angle and the inner and out radii. Something that
>>>>> really complicates the mental gymnastics is that the tooth height is
>>>>> smaller at the inner radius. My code adds a “base” of extra material at the
>>>>> bottom of the convex part and the top of the concave part. What’s tricky is
>>>>> positioning the base of the concave part relative to the inner center line.
>>>>> The concave parts base is relatively easy to place because it depends on
>>>>> the outer radius and center line.
>>>>> >
>>>>> > I generate the raw teeth using the groove and ridge angles and
>>>>> spherical coordinates to make two 2d tooth profiles. Then I complete a
>>>>> tooth using skin(). A for loop generates the full set of N teeth. Then
>>>>> intersection or difference is used the trim the teeth at the inner and
>>>>> outer radii. I discovered something at that point, but solved it pretty
>>>>> simply. When diffing a cylinder from the N teeth, each tooth took up a
>>>>> small portion of the cylinder being diffed out. I had to raise the $fn on
>>>>> the cylinder or tube being used so that I got enough points in each tooth
>>>>> that diff or intersection was accurate. I kept raising it until the results
>>>>> stopped improving. I ended up with the 16*360 you see in the code.
>>>>> >
>>>>> > After I have the raw teeth, I generate a cone that is diffed away to
>>>>> produce the chamfer at the top of the teeth. Then I add in the base. The
>>>>> base also adds the “chamfer” at the bottom of the groove. It’s half the
>>>>> size of the top chamfer to leave a little gap when the parts are joined.
>>>>> >
>>>>> > When I comment out the everything but the raw teeth and import the
>>>>> STL into PrusaSlicer, it reports errors fixed, but appears to slice
>>>>> correctly when supports are added.
>>>>> >
>>>>> > When I add the intersection to trim the raw teeth, the number of
>>>>> reported errors goes way up.
>>>>> >
>>>>> > When I add the diff to remove the chamfer, the number goes way up
>>>>> again.
>>>>> >
>>>>> > When I add in the base, the number goes up again and it starts
>>>>> reporting many open edges.
>>>>> >
>>>>> > Throughout, OpenSCAD reports no errors. Using $fn at 16*360,
>>>>> manifold renders in 4+ seconds. At 32*360, it’s 53+ seconds. I did check
>>>>> CSG and it did not help.
>>>>> >
>>>>> > Maybe the biggest hint is that the convex part uses almost identical
>>>>> code, but produces no errors. Very weird.
>>>>> >
>>>>> > So, is this an OpenSCAD problem? Or something in my code?
>>>>> >
>>>>> > It’s also possible that my math is off somewhere. My formal trig
>>>>> training was 60 years ago. However I doubt a math error is responsible for
>>>>> the slicing problem and STL errors.
>>>>> >
>>>>> > -Bob
>>>>> >
>>>>> >
>>>>> > include <BOSL2/std.scad>
>>>>> > include <BOSL2/structs.scad>
>>>>> >
>>>>> > // Number of Teeth
>>>>> > _n = 36; // Number Of Teeth
>>>>> >
>>>>> > // Inner Radius
>>>>> > _ir = 30;
>>>>> > // Outer Radius
>>>>> > _or = 50;
>>>>> > // Is the coupling conical?
>>>>> > _conic = 10;
>>>>> > // Tooth Profile Angle
>>>>> > _profile = 60; // [60, 90]
>>>>> > // Percentage of tooth height
>>>>> > _chamfer = 5; // Default 5%
>>>>> > _base = 1;
>>>>> >
>>>>> > $fn = 180;
>>>>> > tiny = 1 / 1024;
>>>>> >
>>>>> > hirth_concave();
>>>>> >
>>>>> > _irRatio = _ir / _or;
>>>>> > _toothAngle = 360/_n;
>>>>> > _toothHeight = (sin(_toothAngle/2) * _or) / tan(_profile/2);
>>>>> > _chamferHeight = _chamfer * _toothHeight / 100;
>>>>> > _grooveAngle = atan(((_toothHeight/2) + _conic) / _or);
>>>>> > _ridgeAngle = -atan(((_toothHeight/2) - _conic) / _or);
>>>>> > _innerCenterLine = (1 - _irRatio) * _conic;
>>>>> > _stackHeight = _innerCenterLine + _toothHeight + 2*_base;
>>>>> > _tubeHeight = 2*_conic + 2*_base + 2*_toothHeight;
>>>>> >
>>>>> > module hirth_concave() {
>>>>> > zrot(_toothAngle/2)
>>>>> > union() {
>>>>> > difference() {
>>>>> > intersection() {
>>>>> > union() {
>>>>> > for (i = [0 : 360/_n : 359])
>>>>> > zrot(i)
>>>>> > _profileF();
>>>>> > }
>>>>> > tube(ir = _ir, or = _or, anchor = CENTER, l =
>>>>> _tubeHeight, orient = UP, $fn = 16*360);
>>>>> > }
>>>>> > _chamferF();
>>>>> > zcyl(r = _ir, h = _tubeHeight, $fn = 16*360, anchor =
>>>>> CENTER);
>>>>> > }
>>>>> > _baseF();
>>>>> > }
>>>>> > } // hirth_concave
>>>>> >
>>>>> > module _profileF() {
>>>>> > IR = _ir * .5;
>>>>> > OR = _or * 1.5;
>>>>> > tI = [spherical_to_xyz(IR, 0, _grooveAngle + 90),
>>>>> > spherical_to_xyz(IR, _toothAngle/2, _ridgeAngle + 90),
>>>>> > spherical_to_xyz(IR, -_toothAngle/2, _ridgeAngle + 90)];
>>>>> >
>>>>> > tO = [spherical_to_xyz(OR, 0, _grooveAngle + 90),
>>>>> > spherical_to_xyz(OR, _toothAngle/2, _ridgeAngle + 90),
>>>>> > spherical_to_xyz(OR, -_toothAngle/2, _ridgeAngle + 90)];
>>>>> > up(_conic)
>>>>> > skin([tI, tO], slices = 0);
>>>>> > }
>>>>> >
>>>>> >
>>>>> > module _chamferF() {
>>>>> > A = -_toothHeight/2 - .1;
>>>>> > B = -_toothHeight/2 + _chamferHeight;
>>>>> >
>>>>> > pts = [[0, _conic],
>>>>> > [_or+tiny, A],
>>>>> > [_or+tiny, B]];
>>>>> >
>>>>> > rotate_extrude(angle = 360, $fn = 16*360)
>>>>> > polygon(pts);
>>>>> > }
>>>>> >
>>>>> > module _baseF() {
>>>>> > A = _base + _irRatio*_toothHeight/2 + _innerCenterLine;
>>>>> > B = _irRatio * (_toothHeight/2 - _chamferHeight/2) +
>>>>> _innerCenterLine;
>>>>> > C = _toothHeight/2 - _chamferHeight/2;
>>>>> > pts = [
>>>>> > [_ir, A],
>>>>> > [_ir, B],
>>>>> > [_or, C],
>>>>> > [_or, A]
>>>>> > ];
>>>>> >
>>>>> > rotate_extrude(angle = 360, $fn = 360*16)
>>>>> > polygon(pts);
>>>>> > }
>>>>> > _______________________________________________
>>>>> > OpenSCAD mailing list
>>>>> > To unsubscribe send an email to discuss-leave@lists.openscad.org
>>>>> _______________________________________________
>>>>> OpenSCAD mailing list
>>>>> To unsubscribe send an email to discuss-leave@lists.openscad.org
>>>>>
>>>> _______________________________________________
>>> OpenSCAD mailing list
>>> To unsubscribe send an email to discuss-leave@lists.openscad.org
>>>
>>
M
mikeonenine@web.de
Sun, Nov 3, 2024 7:25 PM
The quest for the holy grail has hit the magic ton, 103 in fact, if you include the thread I started on the same subject just over 5 weeks ago. Must be a record.
That’s nice, but it is becoming increasingly tedious always having to scroll down to the end.
At what point would it be worth starting a new thread?
The quest for the holy grail has hit the magic ton, 103 in fact, if you include the thread I started on the same subject just over 5 weeks ago. Must be a record.
That’s nice, but it is becoming increasingly tedious always having to scroll down to the end.
At what point would it be worth starting a new thread?