OpenSCAD

I just wish that the FreeCAD devs would make OpenSCAD a full-fledged scripting option — seems a natural fit, and would be a great way to get better exports out of it.

1 Like

This is the result of too much time spent with OpenSCAD. But it was a good exercise.

I was not able to create the hole for the nut and the threaded rod in OpenSCAD. I had to load the .stl in Sketchup and draw it myself.
For some reason OpenSCAD will not cut any sections after the rounding has finished.

I did have to learn a few things, but after 30+ years of programming professionally I feel more comfortable in a programming environment than a program that is the opposite of intuitive.

I will have a look at the steps Michael showed above, and try to repeat these, and maybe I get used to it…
sometime.

1 Like

My take on OpenSCAD has always been:

The great thing about OpenSCAD is that it makes it easy to model things which may may be represented by cubes, spheres, and cylinders, mathematically positioned and scaled.

The awful thing about OpenSCAD is that one’s ability to use it is determined by one’s facility with mathematics and using programming to position and scale cubes, spheres, and cylinders.

1 Like

and if you are comfortable typing in data, 10 finger typing helps, then it’s easy.
You wouldn’t believe the number of people who don’t like typing because they are 2 finger peckers and have to look at the keyboard, the screen, keyboard, screen, repeat.

I too have a coding background, learned to 10 finger type in 10th grade and I’ve been tortured helping or working with other coders who can’t 10 finger type.

OpenSCAD felt really intuitive. But all the added capabilities in FreeCAD are my favorite now.

1 Like

With OpenSCAD The big issue here is that the minkowski() operation only uses a single CPU core, and forms a bottleneck. Memory helps but the number of cores in the machine is irrelevant; it is single-thread speed that matters.

My general rule of thumb is that Intersecting, differencing and extruding operations are cheap, but minkowski is expensive; don’t use more than is necessary. Outlining (hull) falls somewhere in between and is very dependent on the number of points in the hull.

So; working on that principle; here is what I came up with: First I broke the handle into the smallest repeatable unit:

then minkowski just that:

Finally; mirror it and repeat to make a full circle; and add the central shaft + holes to the finished object.

Rendered at fn = 90 it takes 3 min 36 sec to preview and is very smooth (the manifold render only takes 2 seconds, the hard work was done in the preview).

I think there is a way to do this much faster using some functional programming to create the body 3d mesh directly. I also wonder if it could be done in PythonSCAD using the ability to extrude with a function on the z-axis.

Code:

/* Handle; Segmented version.
- timings taken for each resolution using a fresh instance (no cache)
fn = 18; // Preview time: 0:00:01.287 : manifold render: 0:00:00.298
fn = 36; // Preview time: 0:00:09.918 : manifold render: 0:00:00.516
fn = 54; // Preview time: 0:00:35.324 : manifold render: 0:00:00.839
fn = 72; // Preview time: 0:01:41.459 : manifold render: 0:00:01.280
fn = 90; // Preview time: 0:03:36.698 : manifold render: 0:00:01.610
*/

fn = 90;

outer_diameter = 70;
inner_diameter = 30;
lob_diameter = 44;
protrusion = 10; // from top
lob_count = 5;
round_radius = 4;
hex_diameter = 13; // in mm between flat sides
nut_depth = 5; // in mm
hole_radius = 4.25; // mm

torus_diameter = (outer_diameter - inner_diameter - round_radius) / 2;
hex_correction = hex_diameter / cos(30) + 0.2; // 0.2 mm tolerance

module segment() {  // hard-edged
    R = (outer_diameter - torus_diameter) / 2;
    difference() {
        rotate_extrude(angle = 180 / lob_count, $fn=fn) {
                translate([R, 0])
                circle(r = torus_diameter / 2, $fn=fn);
                translate([hole_radius + round_radius, -torus_diameter / 2])
                square([R - hole_radius - round_radius,torus_diameter]);
        }
        translate([R + lob_diameter/2, 0, -torus_diameter])
        cylinder(h = torus_diameter*2  + round_radius, r = lob_diameter / 2, $fn = fn);
    }
}

module rounded_segment() {  // round off
    minkowski() {
        segment();
        sphere( r = round_radius, $fn = fn / 2 );
    }
}

module slice() {
    rounded_segment();
    mirror([0,1,0])
    rounded_segment();
}

module stub() {
    minkowski() {
        cylinder(h = (torus_diameter ) / 2 + protrusion , r = inner_diameter / 2 - round_radius, $fn = fn );
        sphere( r = round_radius, $fn = fn / 2 );
    }
}

module nutcase() {
    translate([0, 0, -round_radius - 0.1]) // M8 hole
    cylinder(h = torus_diameter + protrusion + 0.2, d = 2 * hole_radius, $fn = fn);
    translate([0, 0, torus_diameter/2 + round_radius + protrusion - nut_depth]) // M8 nut
    cylinder(h = nut_depth + 0.2 , d = hex_correction, $fn = 6);
}

module handle() {  
    for (x=[1:lob_count])
        rotate(x*(360/lob_count))
        slice();
    difference() {
        stub();
        nutcase();
    }
}

handle();
3 Likes

We’re nearly there Owen. Reducing the minkowski calculations to half a lob was an excellent idea.
Different parameters however do not always work:
With these parameters the hole for the threaded rod is missing. I haven’t analysed the problem yet, bedtime now :slight_smile:

outer_diameter = 25;
inner_diameter = 15;
lob_diameter = 40;
protrusion = 10; // from top
lob_count = 3;
round_radius = 4;
hex_diameter = 5.5; // in mm between flat sides
nut_depth = 4; // in mm
hole_radius = 1.7; // mm

Humm, the ‘stub’ module was a bit of a hack.

Try replacing stub() and nutcase() with these:

module stub() {
    rotate_extrude($fn = fn) intersection () {
        hull() {
            translate([inner_diameter / 2 - round_radius, torus_diameter / 2 + protrusion - round_radius])
            circle(r=round_radius, $fn=fn/2);
            square([inner_diameter / 2, 0.1]);
            square([0.1, torus_diameter / 2 + protrusion]);
        }
        translate([hole_radius,0])
        square([inner_diameter / 2, torus_diameter / 2 + protrusion + round_radius]);
    }
}

module nutcase() {
    translate([0, 0, torus_diameter/2 + protrusion - nut_depth])
    cylinder(h = nut_depth + 0.2 , d = hex_correction, $fn = 6);
}

This should scale properly as the main parameters change. But note that there are plenty of values you can pick that will (essentially) blow the model up.
(also; note the intersection() on the rotate_extrude(); not only does it create the hole for the screwthread, it also stops the extrude from blowing up due to a negative offset if the circle(r=round radius) is bigger than the X offset it is extruded around (inner_diameter / 2 - round_radius))


It’s worth noting that reducing the lobe count from 5 to 3 with your new values fairly dramatically increases the preview render time; this is because each segment now contains more points for the minkowski.

Did you really copy all my parameters? Mine looks different:


I think I’m running in the same problem that in some cases minkowsky rounded parts do not accept intersections.

I understand that with only three lobes the calculation of minkowsky takes more time but try to fit your fingers between the lobes when the diameter is only 25mm with 5 lobes.

Heh. Here’s a picture that includes the 3d-printed knob I use the most. 12mm OD. My fingers definitely do not fit between the lobes! :grinning_face:

2 Likes

yep, copy-n-paste..

I wonder if our code has diverged somewhere; I took the calculations for the lobe cutouts directly from your code posted above:

R = (outer_diameter - torus_diameter) / 2;
... torus extrude here ...
for (i = [0 : lob_count-1]) {
    rotate([0, 0, i * 360 / lob_count])
    translate([R + lob_diameter/2, 0, -torus_diameter])
    cylinder(h = torus_diameter*2, r = lob_diameter / 2, $fn = fn);

Since this is done before the minkowski() in both cases the ‘real’ radius being cut out is reduced by the rounding_radius.
Try replacing the translate() with:
translate([R + lob_diameter/2 - round_radius, 0, -torus_diameter])

Which gives something that looks like what you posted: (you could add it to the circle() radius instead, but doing it on the translate() makes the indents slightly ‘sharper’.

I know what you mean :wink:,
Incedentally; if you turn lob_count up to 12 or 15 you get quite a nice looking knurled nut. Not so great for grip but nice for some applications. And it renders fast even with fn turned up to 90+

@easytarget,

Sorry for the late reply. Today, I had to do some preparations for our “sinterklaasviering”. I’ve just returned from Belgium where our family gathered last night.

I changed more than I mentioned. I also changed this line:

torus_diameter = 10; //(outer_diameter - inner_diameter - round_radius) / 2;

It makes the indents a bit deeper but it messes up the hole for the threaded rod.

@mcdanlj,

Is that a potentiometer, or something that needs a bit more force like a threaded rod to squeeze something? Makes a difference, don’t you think.

That’s a terminal knob. It has a threaded insert melted into it, and is used to attach a wire using a “spade terminal” where the spade terminal is held between the threaded insert and a nut that is partially embedded in the purple box in the picture.

It’s part of a ham radio antenna system.

I have a wire of a particular length with a spade connector on it to use as an antenna. I put the other end of the wire at the end of a fishing pole or up in a tree, and connect it to that post. I connect a shorter wire to another similar terminal and try to hang it over a bush or twig, or possibly just set it on the ground if I can’t put it in the air. Then I connect the box to my radio with a piece of coax cable. It basically hangs from the elevated wire, so it has to be tight enough to hold the box in place when hanging from the wire, and it’s important that it not slip out while I’m operating.

It’s the BindingKnob in QRPUnun.FCStd here:

That was basically why I posted the picture — knurling is another effective approach to leverage. However, for it to be effective, you probably want a smaller minkowski object, because part of what makes knurling effective is how the edge grips your skin. The size of the grooves in the minuscule knobs, combined with a sufficiently but not painfully sharp edge, has been effective for me in practice as gross knurling.

I was inspired by your post: https://knobgenerator.com/ I have another link but after purchase I realized its NSFW. Anyways.. try it out I’m sure your modeling will be better but it’s a fun way to play with different designs quickly.

1 Like

The reason I started with this script is the knob on the right in the picture below.
My son bought a herb grinder like this one and asked me to print a new knob.

The edges of this knob are sharp and when you curl your fingers around it, it does not feel comfortable. I see the same design in your webpage. Maybe an extra choice in the left panel to choose between half round or full, or a “Bottom Edge Rounding” feature, would be an improvement.

1 Like