1
0
mirror of https://github.com/nophead/NopSCADlib.git synced 2025-09-03 12:22:46 +02:00

Compare commits

...

12 Commits

Author SHA1 Message Date
Chris Palmer
23cbadf6df Merge branch 'martinbudden-stepper_motor_jst_connector' 2020-11-08 21:29:03 +00:00
Chris Palmer
c9c2ffafba Fixed connector position, fixed missing wires, updated images.
Reverted the jst header pin position change.
2020-11-08 21:28:08 +00:00
Martin Budden
2e0e833d40 Made jst_connector a parameter to NEMA. 2020-11-08 15:14:19 +00:00
Martin Budden
0b035dbd15 Added optional jst connector to stepper motors. 2020-11-08 12:20:15 +00:00
Chris Palmer
34b58e3b64 Added convexity parameter to sweep. 2020-11-04 22:27:31 +00:00
Chris Palmer
df43fe7dc6 Added list and string slicing. 2020-11-04 21:44:07 +00:00
Chris Palmer
b5fe03fcb2 Test image pixel differences due to switch to winter computer 2020-11-04 20:48:22 +00:00
Chris Palmer
1658f6f0b4 Sweep can now cope with the start having colinear points. 2020-11-04 19:56:51 +00:00
Chris Palmer
7b126f9792 More spelling 2020-11-04 19:50:35 +00:00
Chris Palmer
479207fd4f Spelling 2020-11-04 10:52:57 +00:00
Chris Palmer
3ee55981f9 Comment spelling. 2020-10-05 12:02:54 +01:00
Chris Palmer
8c2b4a20fe Added tesrdrop_minus() and horicylinder(). 2020-10-05 10:59:50 +01:00
23 changed files with 116 additions and 32 deletions

View File

@@ -18,7 +18,7 @@
//
//
// Include this file to use the miniumum library plus screws, nuts and washers
// Include this file to use the minimum library plus screws, nuts and washers
//
include <utils/core/core.scad>
//

View File

@@ -33,7 +33,7 @@ $exploded = is_undef($explode) ? 0 : $explode; // 1 f
layer_height = is_undef($layer_height) ? 0.25 : $layer_height; // layer heigth when printing
extrusion_width = is_undef($extrusion_width) ? 0.5 : $extrusion_width; // filament width when printing
nozzle = is_undef($nozzle) ? 0.45 : $nozzle; // 3D printer nozzle
cnc_bit_r = is_undef($cnc_bit_r) ? 1.2 : $cnc_bit_r; // miniumum tool radius when milling 2D objects
cnc_bit_r = is_undef($cnc_bit_r) ? 1.2 : $cnc_bit_r; // minimum tool radius when milling 2D objects
pp1_colour = is_undef($pp1_colour) ? [0, 146/255, 0] : $pp1_colour; // printed part colour 1, RepRap logo colour
pp2_colour = is_undef($pp2_colour) ? "red" : $pp2_colour; // printed part colour 2
pp3_colour = is_undef($pp3_colour) ? "blue" : $pp3_colour; // printed part colour 3

Binary file not shown.

Before

Width:  |  Height:  |  Size: 818 KiB

After

Width:  |  Height:  |  Size: 819 KiB

View File

@@ -403,7 +403,7 @@ PCB mounted buttons. Can optionally have a coloured cap
## Cable_strips
A strip of polypropylene used with ribbon cable to make a cable flexible in one direction only.
Modelled with a Bezier spline, which is not quite the same as a miniumum energy curve but very close, epecially
Modelled with a Bezier spline, which is not quite the same as a minimum energy curve but very close, epecially
near the extreme positions, where the model needs to be accurate.
When the sides are constrained then a circular model is more accurate.
@@ -3422,7 +3422,7 @@ NEMA stepper motor model.
### Modules
| Module | Description |
|:--- |:--- |
| ```NEMA(type, shaft_angle = 0)``` | Draw specified NEMA stepper motor |
| ```NEMA(type, shaft_angle = 0, jst_connector = false)``` | Draw specified NEMA stepper motor |
| ```NEMA_outline(type)``` | 2D outline |
| ```NEMA_screw_positions(type, n = 4)``` | Positions children at the screw holes |
| ```NEMA_screws(type, screw, n = 4, screw_length = 8, earth = undef)``` | Place screws and optional earth tag |
@@ -5387,6 +5387,8 @@ Method to print holes in mid air. See <https://hydraraptor.blogspot.com/2014/03/
## Horiholes
Utilities for depicting the staircase slicing of horizontal holes made with [`teardrop_plus()`](#teardrops), see <https://hydraraptor.blogspot.com/2020/07/horiholes-2.html>
```horicylinder()``` makes cylinders that fit inside a round hole. Layers that are less than 2 filaments wide and layers that need more than a 45 degree overhang are omitted.
[utils/horiholes.scad](utils/horiholes.scad) Implementation.
@@ -5395,11 +5397,13 @@ Utilities for depicting the staircase slicing of horizontal holes made with [`te
### Functions
| Function | Description |
|:--- |:--- |
| ```teardrop_minus_x(r, y, h)``` | Calculate the ordinate of a compensated teardrop given y and layer height. |
| ```teardrop_plus_x(r, y, h)``` | Calculate the ordinate of a compensated teardrop given y and layer height. |
### Modules
| Module | Description |
|:--- |:--- |
| ```horicylinder(r, z, h = 0, center = true)``` | For making horizontal cylinders that don't need support material and are correct dimensions |
| ```horihole(r, z, h = 0, center = true)``` | For making horizontal holes that don't need support material and are correct dimensions |
![horiholes](tests/png/horiholes.png)
@@ -5660,7 +5664,7 @@ An additional twist around the path can be specified. If the path is closed this
### Modules
| Module | Description |
|:--- |:--- |
| ```sweep(path, profile, loop = false, twist = 0)``` | Draw a polyhedron that is the swept volume |
| ```sweep(path, profile, loop = false, twist = 0, convexity = 1)``` | Draw a polyhedron that is the swept volume |
![sweep](tests/png/sweep.png)
@@ -5852,11 +5856,13 @@ Global constants, functions and modules. This file is used directly or indirectl
| ```foot(x)``` | Foot to mm conversion |
| ```in(list, x)``` | Returns true if ```x``` is an element in the ```list``` |
| ```inch(x)``` | Inch to mm conversion (For fractional inches, 'inch(1 + 7/8)' will work as expected.) |
| ```limit(x, min, max)``` | Force x in range min <= x <= max |
| ```m(x)``` | m to mm conversion |
| ```mm(x)``` | Explicit mm specified |
| ```no_point(str)``` | Replace decimal point in string with 'p' |
| ```r2sides(r)``` | Replicates the OpenSCAD logic to calculate the number of sides from the radius |
| ```r2sides4n(r)``` | Round up the number of sides to a multiple of 4 to ensure points land on all axes |
| ```slice(list, start = 0, end = undef)``` | Slice a list or string with Python type semantics |
| ```sqr(x)``` | Returns the square of ```x``` |
| ```yard(x)``` | Yard to mm conversion |

View File

@@ -29,6 +29,23 @@ module globals() {
translate([50, 0])
right_triangle(10, 20, 0);
}
assert(slice("ABCD") == "ABCD");
assert(slice("ABCD", 1) == "BCD");
assert(slice("ABCD", 2) == "CD");
assert(slice("ABCD", 3) == "D");
assert(slice("ABCD", 4) == "");
assert(slice("ABCD", 1, -1) == "BC");
assert(slice("ABCD", 2, -1) == "C");
assert(slice("ABCD", 3, -1) == "");
assert(slice("ABCD", 4, -1) == "");
assert(slice("ABCD", 0, -1) == "ABC");
assert(slice("ABCD", 0, -2) == "AB");
assert(slice("ABCD", 0, -3) == "A");
assert(slice("ABCD", 0, -4) == "");
assert(slice("ABCD", 0, 0) == "");
assert(slice("ABCD", 0, 1) == "A");
assert(slice("ABCD", 0, 2) == "AB");
assert(slice("ABCD", 0, 3) == "ABC");
}
rotate([70, 0, 315]) globals();

View File

@@ -69,9 +69,13 @@ module horiholes() {
color(silver)
cylinder(r = $r, h = eps, center = true, $fn = 360);
hole_positions()
color("blue")
horicylinder(r = $r, z = $z, h = 2 * eps, center = true, $fn = 360);
hole_positions()
color("red")
linear_extrude(2 * eps, center = true)
linear_extrude(3 * eps, center = true)
intersection() {
difference() {
square(8, center = true);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 108 KiB

View File

@@ -24,7 +24,7 @@ use <../utils/layout.scad>
module stepper_motors()
layout([for(s = stepper_motors) NEMA_width(s)], 5) {
rotate(180)
NEMA(stepper_motors[$i]);
NEMA(stepper_motors[$i], 0, $i > 1 && $i < 5);
translate_z(4)
NEMA_screws(stepper_motors[$i], M3_pan_screw, n = $i, earth = $i > 4 ? undef : $i - 1);

View File

@@ -18,7 +18,7 @@
//
//
// Include this file to use the miniumum library
// Include this file to use the minimum library
//
include <../../global_defs.scad>
//

View File

@@ -36,12 +36,22 @@ function in(list, x) = !!len([for(v = list) if(v == x) true]);
function Len(x) = is_list(x) ? len(x) : 0; //! Returns the length of a list or 0 if ```x``` is not a list
function r2sides(r) = $fn ? $fn : ceil(max(min(360/ $fa, r * 2 * PI / $fs), 5)); //! Replicates the OpenSCAD logic to calculate the number of sides from the radius
function r2sides4n(r) = floor((r2sides(r) + 3) / 4) * 4; //! Round up the number of sides to a multiple of 4 to ensure points land on all axes
function limit(x, min, max) = max(min(x, max), min); //! Force x in range min <= x <= max
module translate_z(z) translate([0, 0, z]) children(); //! Shortcut for Z only translations
module vflip() rotate([180, 0, 0]) children(); //! Invert children by doing a 180&deg; flip around the X axis
module hflip() rotate([0, 180, 0]) children(); //! Invert children by doing a 180&deg; flip around the Y axis
module ellipse(xr, yr) scale([1, yr / xr]) circle4n(xr); //! Draw an ellipse
function slice_str(str, start, end, s ="") = start >= end ? s : slice_str(str, start + 1, end, str(s, str[start])); // Helper for slice()
function slice(list, start = 0, end = undef) = let( //! Slice a list or string with Python type semantics
len = len(list),
start = limit(start < 0 ? len + start : start, 0, len),
end = is_undef(end) ? len : limit(end < 0 ? len + end : end, 0, len)
) is_string(list) ? slice_str(list, start, end) : [for(i = [start : 1 : end - 1]) list[i]];
module extrude_if(h, center = true) //! Extrudes 2D object to 3D when ```h``` is nonzero, otherwise leaves it 2D
if(h)
linear_extrude(h, center = center, convexity = 2) // 3D

View File

@@ -19,6 +19,8 @@
//
//! Utilities for depicting the staircase slicing of horizontal holes made with [`teardrop_plus()`](#teardrops), see <https://hydraraptor.blogspot.com/2020/07/horiholes-2.html>
//!
//! ```horicylinder()``` makes cylinders that fit inside a round hole. Layers that are less than 2 filaments wide and layers that need more than a 45 degree overhang are omitted.
//
include <../utils/core/core.scad>
@@ -53,3 +55,29 @@ module horihole(r, z, h = 0, center = true) { //! For making horizontal holes th
}
}
}
function teardrop_minus_x(r, y, h) = //! Calculate the ordinate of a compensated teardrop given y and layer height.
let(fr = h / 2,
hpot = r - fr,
x2 = sqr(hpot) - sqr(y),
x = x2 > 0 ? sqrt(x2) : 0,
X = y >= -hpot / sqrt(2) ? x + fr : 0
)
X >= extrusion_width ? X : 0;
module horicylinder(r, z, h = 0, center = true) { //! For making horizontal cylinders that don't need support material and are correct dimensions
bot_layer = floor((z - r) / layer_height);
top_layer = ceil((z + r) / layer_height);
render(convexity = 5)
extrude_if(h, center)
for(i = [bot_layer : top_layer]) {
Z = i * layer_height;
y = Z - z + layer_height / 2;
x = teardrop_minus_x(r, y, layer_height);
if(x >= extrusion_width)
hull()
for(end = [-1, 1])
translate([end * (x - layer_height / 2), y])
circle(d = layer_height, $fn = 32);
}
}

View File

@@ -34,14 +34,22 @@ function transpose3(m) = [ [m[0].x, m[1].x, m[2].x],
[m[0].y, m[1].y, m[2].y],
[m[0].z, m[1].z, m[2].z] ];
//
// Find the first non-colinear point
//
tiny = 0.00001;
function find_curve(tangents, i = 1) =
i >= len(tangents) - 1 || norm(cross(tangents[0], tangents[i] - tangents[0])) > tiny ? i
: find_curve(tangents, i + 1);
//
// Frenet-Serret frame
//
function fs_frame(tangents) =
let(tangent = tangents[0],
normal = tangents[1] - tangents[0],
i = find_curve(tangents),
normal = tangents[i] - tangents[0],
binormal = cross(tangent, normal),
z = unit(tangent),
x = assert(norm(binormal) > 0.00001, "first three points are colinear") unit(binormal),
x = assert(norm(binormal) > tiny, "all points are colinear") unit(binormal),
y = unit(cross(z, x))
) [[x.x, y.x, z.x],
[x.y, y.y, z.y],
@@ -70,7 +78,6 @@ function orientate(p, r) =
[x.y, y.y, z.y],
[x.z, y.z, z.z],
[p.x, p.y, p.z]];
//
// Rotate around z
//
@@ -145,10 +152,10 @@ function sweep(path, profile, loop = false, twist = 0) = //! Generate the point
faces = loop ? skin_faces : concat([cap(facets)], skin_faces, [cap(facets, npoints - 1)])
) [points, faces];
module sweep(path, profile, loop = false, twist = 0) { //! Draw a polyhedron that is the swept volume
module sweep(path, profile, loop = false, twist = 0, convexity = 1) { //! Draw a polyhedron that is the swept volume
mesh = sweep(path, profile, loop, twist);
polyhedron(points = mesh[0], faces = mesh[1]);
polyhedron(points = mesh[0], faces = mesh[1], convexity = convexity);
}
function path_length(path, i = 0, length = 0) = //! Calculated the length along a path

View File

@@ -20,7 +20,7 @@
//
//! A strip of polypropylene used with ribbon cable to make a cable flexible in one direction only.
//!
//! Modelled with a Bezier spline, which is not quite the same as a miniumum energy curve but very close, epecially
//! Modelled with a Bezier spline, which is not quite the same as a minimum energy curve but very close, epecially
//! near the extreme positions, where the model needs to be accurate.
//!
//! When the sides are constrained then a circular model is more accurate.

View File

@@ -23,6 +23,7 @@
include <../core.scad>
include <ring_terminals.scad>
include <../vitamins/pin_headers.scad>
use <../utils/tube.scad>
use <../utils/thread.scad>
use <washer.scad>
@@ -39,7 +40,6 @@ function NEMA_shaft_length(type)= type[8]; //! Shaft length above the face, if a
function NEMA_hole_pitch(type) = type[9]; //! Screw hole pitch
function NEMA_holes(type) = [-NEMA_hole_pitch(type) / 2, NEMA_hole_pitch(type) / 2]; //! Screw positions for for loop
function NEMA_big_hole(type) = NEMA_boss_radius(type) + 0.2; //! Clearance hole for the big boss
stepper_body_colour = "black";
stepper_cap_colour = grey(50);
stepper_machined_colour = grey(90);
@@ -52,7 +52,7 @@ module NEMA_outline(type) //! 2D outline
circle(NEMA_radius(type));
}
module NEMA(type, shaft_angle = 0) { //! Draw specified NEMA stepper motor
module NEMA(type, shaft_angle = 0, jst_connector = false) { //! Draw specified NEMA stepper motor
side = NEMA_width(type);
length = NEMA_length(type);
body_rad = NEMA_body_radius(type);
@@ -92,12 +92,23 @@ module NEMA(type, shaft_angle = 0) { //! Draw specified NEMA stepper motor
cap_shape(1);
}
color(stepper_cap_colour) // aluminium end caps
tabSize = [16, 4, 2.5];
color(stepper_cap_colour) { // aluminium end caps
for(end = [-1, 1])
translate_z(-length / 2 + end * (length - cap) / 2)
linear_extrude(cap, center = true)
cap_shape(end);
if(jst_connector)
translate([-tabSize.x / 2, side / 2, -length])
cube(tabSize);
}
if(jst_connector)
translate([0, side / 2 - 2, -length + tabSize.z + 5.75 / 2])
rotate([-90, 0, 0])
jst_xh_header(jst_xh_header, 6);
if(show_threads)
for(x = NEMA_holes(type), y = NEMA_holes(type))
translate([x, y, -cap / 2])
@@ -111,15 +122,16 @@ module NEMA(type, shaft_angle = 0) { //! Draw specified NEMA stepper motor
cylinder(r = shaft_rad, h = shaft + 5); // shaft
else
not_on_bom()
leadscrew(shaft_rad * 2, shaft.x + 5, shaft.y, shaft.z, center = false)
leadscrew(shaft_rad * 2, shaft.x + 5, shaft.y, shaft.z, center = false);
translate([0, side / 2, -length + cap / 2])
rotate([90, 0, 0])
for(i = [0 : 3])
rotate(225 + i * 90)
color(["red", "blue","green","black"][i])
translate([1, 0, 0])
cylinder(r = 1.5 / 2, h = 12, center = true);
if(!jst_connector)
translate([0, side / 2, -length + cap / 2])
rotate([90, 0, 0])
for(i = [0 : 3])
rotate(225 + i * 90)
color(["red", "blue","green","black"][i])
translate([1, 0, 0])
cylinder(r = 1.5 / 2, h = 12, center = true);
}
module NEMA_screw_positions(type, n = 4) { //! Positions children at the screw holes

View File

@@ -23,13 +23,13 @@
// corner body boss boss shaft
// side, length, radius, radius, radius, depth, shaft, length, holes
NEMA17 = ["NEMA17", 42.3, 47, 53.6/2, 25, 11, 2, 5, 24, 31 ];
NEMA17M = ["NEMA17M", 42.3, 40, 53.6/2, 25, 11, 2, 5, 20, 31 ];
NEMA17M8= ["NEMA17M8", 42.3, 40, 53.6/2, 25, 11, 2, 8, [280, 8, 4], 31 ];
NEMA17S = ["NEMA17S", 42.3, 34, 53.6/2, 25, 11, 2, 5, 24, 31 ];
NEMA16 = ["NEMA16", 39.5, 19.2, 50.6/2, 50.6/2, 11, 2, 5, 12, 31 ];
NEMA14 = ["NEMA14", 35.2, 36, 46.4/2, 21, 11, 2, 5, 21, 26 ];
NEMA23 = ["NEMA23", 56.4, 51.2, 75.7/2, 35, 38.1/2, 1.6, 6.35, 24, 47.1 ];
NEMA17 = ["NEMA17", 42.3, 47, 53.6/2, 25, 11, 2, 5, 24, 31];
NEMA17M = ["NEMA17M", 42.3, 40, 53.6/2, 25, 11, 2, 5, 20, 31];
NEMA17M8= ["NEMA17M8", 42.3, 40, 53.6/2, 25, 11, 2, 8, [280, 8, 4], 31];
NEMA17S = ["NEMA17S", 42.3, 34, 53.6/2, 25, 11, 2, 5, 24, 31];
NEMA16 = ["NEMA16", 39.5, 19.2, 50.6/2, 50.6/2, 11, 2, 5, 12, 31];
NEMA14 = ["NEMA14", 35.2, 36, 46.4/2, 21, 11, 2, 5, 21, 26];
NEMA23 = ["NEMA23", 56.4, 51.2, 75.7/2, 35, 38.1/2, 1.6, 6.35, 24, 47.1];
stepper_motors = [NEMA14, NEMA16, NEMA17S, NEMA17M, NEMA17, NEMA23];