1
0
mirror of https://github.com/nophead/NopSCADlib.git synced 2025-09-03 20:32:35 +02:00

Compare commits

...

30 Commits

Author SHA1 Message Date
Chris Palmer
53d1ea93cd Can now specify a rotation angle for a geared_stepper's shaft. 2024-06-30 12:30:29 +01:00
Chris Palmer
7eaca85e96 Updated changelog. 2024-06-12 21:25:13 +01:00
Chris Palmer
b00709da82 Image edge pixel changes due to new PC. 2024-06-12 21:23:32 +01:00
Chris Palmer
c76be23867 Fixed thread bug on threaded inserts revealed by latest OpenSCAD snapshot. 2024-06-12 21:18:11 +01:00
Chris Palmer
f6f348b76e Fixed rocker slot height. 2024-06-12 21:15:44 +01:00
Chris
11a1f65158 Updated changelog. 2024-05-08 00:29:33 +01:00
Chris
870b396574 Revoved strailing comma in let() in splines.scad. 2024-05-08 00:22:19 +01:00
Chris Palmer
00c19b08f1 Updated changelog. 2024-04-21 15:45:15 +01:00
Chris Palmer
22bbb85899 Merge branch 'vshcryabets-pcb/rcwl0516' 2024-04-21 15:41:13 +01:00
Chris Palmer
c1fdb2e701 Dpdated images and readme. 2024-04-21 15:40:51 +01:00
Chris Palmer
728d5d32a9 Merge branch 'pcb/rcwl0516' of https://github.com/vshcryabets/NopSCADlib into vshcryabets-pcb/rcwl0516 2024-04-21 15:20:59 +01:00
Chris Palmer
771ba04e18 Updated changelog. 2024-04-21 15:19:33 +01:00
Chris Palmer
dbf930fd36 Added cubic splines and Catmull Rom splines. 2024-04-21 12:13:31 +01:00
Chris Palmer
97cea65f41 Cable clips can now use inserts or nut traps. 2024-04-21 12:08:40 +01:00
Chris Palmer
c7e912cd77 A optional path can now be specified for tubing. 2024-04-21 10:26:28 +01:00
Chris Palmer
f563645e45 Corrected M2 nut_trap_depth, was too big. 2024-04-21 10:20:36 +01:00
Chris Palmer
2840cc2390 Washer now uses sweep.scad instead of including it, leaking its interface. 2024-04-21 10:18:34 +01:00
Chris Palmer
a5b2018008 Added offset_paths() to sweep.scad.
show_path() now takes an optional radius.
2024-04-21 08:47:44 +01:00
V.Shcriabets
cbe2c085b7 Add RCWL-0516 PCB 2024-04-20 12:59:16 +03:00
Chris Palmer
7a395e475e Updated changelog. 2024-03-14 23:56:12 +00:00
Chris Palmer
7b7348d98f Merge branch 'vshcryabets-update/mt3608-pcb' 2024-03-14 23:54:17 +00:00
Chris Palmer
19dadcb58d Updated images and readme. 2024-03-14 23:53:44 +00:00
Chris Palmer
60a2ef8976 Merge branch 'update/mt3608-pcb' of https://github.com/vshcryabets/NopSCADlib into vshcryabets-update/mt3608-pcb 2024-03-14 23:22:14 +00:00
Chris Palmer
188b3f706d Updated changelog. 2024-03-14 21:41:08 +00:00
Chris Palmer
5579c0d988 Fixed box_shelf_bracket() horizontal holes.
Added a third child to box_shelf_bracket() to allow custom additions.
2024-03-14 21:36:04 +00:00
Chris Palmer
67408f8422 Added d_hole() module. 2024-03-14 21:02:20 +00:00
Chris Palmer
929abbefda Updated front page image. 2024-03-14 21:01:37 +00:00
Chris Palmer
c7727e7106 Added Sellotape to sheets. 2024-03-14 20:58:54 +00:00
Chris Palmer
1dbba5a650 Added camera_lens_height() function. 2024-03-14 20:58:02 +00:00
V.Shkriabets
c565f2912e Update MT3608 pcb module 2024-03-14 19:21:52 +02:00
34 changed files with 449 additions and 140 deletions

View File

@@ -3,6 +3,67 @@
This changelog is generated by `changelog.py` using manually added semantic version tags to classify commits as breaking changes, additions or fixes.
#### [v21.23.2](https://github.com/nophead/NopSCADlib/releases/tag/v21.23.2 "show release") Fixes [...](https://github.com/nophead/NopSCADlib/compare/v21.23.1...v21.23.2 "diff with v21.23.1")
* 2024-06-12 [`b00709d`](https://github.com/nophead/NopSCADlib/commit/b00709da820e1241422b6e156b0c61157c18d63d "show commit") [C.P.](# "Chris Palmer") Image edge pixel changes due to new PC.
* 2024-06-12 [`c76be23`](https://github.com/nophead/NopSCADlib/commit/c76be2386715b80bbbc9a71c99214df7f3c71bc7 "show commit") [C.P.](# "Chris Palmer") Fixed thread bug on threaded inserts revealed by latest OpenSCAD snapshot.
* 2024-06-12 [`f6f348b`](https://github.com/nophead/NopSCADlib/commit/f6f348b76e7986927a571e1c07c3f866bcbeeafe "show commit") [C.P.](# "Chris Palmer") Fixed rocker slot height.
#### [v21.23.1](https://github.com/nophead/NopSCADlib/releases/tag/v21.23.1 "show release") Fixes [...](https://github.com/nophead/NopSCADlib/compare/v21.23.0...v21.23.1 "diff with v21.23.0")
* 2024-05-08 [`870b396`](https://github.com/nophead/NopSCADlib/commit/870b396574935603305462f1fea88564c909aad8 "show commit") [C.](# "Chris") Revoved strailing comma in `let()` in `splines.scad`.
### [v21.23.0](https://github.com/nophead/NopSCADlib/releases/tag/v21.23.0 "show release") Additions [...](https://github.com/nophead/NopSCADlib/compare/v21.22.0...v21.23.0 "diff with v21.22.0")
* 2024-04-21 [`c1fdb2e`](https://github.com/nophead/NopSCADlib/commit/c1fdb2e701672b2404e34f224e77f21fb2ff34da "show commit") [C.P.](# "Chris Palmer") Dpdated images and readme.
* 2024-04-20 [`cbe2c08`](https://github.com/nophead/NopSCADlib/commit/cbe2c085b72d0e5d9f0c6485d5fa7df0e172a4cc "show commit") [V.](# "V.Shcriabets") Add RCWL-0516 PCB
### [v21.22.0](https://github.com/nophead/NopSCADlib/releases/tag/v21.22.0 "show release") Additions [...](https://github.com/nophead/NopSCADlib/compare/v21.21.0...v21.22.0 "diff with v21.21.0")
* 2024-04-21 [`dbf930f`](https://github.com/nophead/NopSCADlib/commit/dbf930fd366c28aa9e581d9fe01e3654b882923a "show commit") [C.P.](# "Chris Palmer") Added cubic splines and Catmull Rom splines.
### [v21.21.0](https://github.com/nophead/NopSCADlib/releases/tag/v21.21.0 "show release") Additions [...](https://github.com/nophead/NopSCADlib/compare/v21.20.0...v21.21.0 "diff with v21.20.0")
* 2024-04-21 [`97cea65`](https://github.com/nophead/NopSCADlib/commit/97cea65f41714acd31a3a3b968d8c133ce1a91d2 "show commit") [C.P.](# "Chris Palmer") Cable clips can now use inserts or nut traps.
### [v21.20.0](https://github.com/nophead/NopSCADlib/releases/tag/v21.20.0 "show release") Additions [...](https://github.com/nophead/NopSCADlib/compare/v21.19.2...v21.20.0 "diff with v21.19.2")
* 2024-04-21 [`c7e912c`](https://github.com/nophead/NopSCADlib/commit/c7e912cd77e189ef729f94956245f1c6a9f72012 "show commit") [C.P.](# "Chris Palmer") A optional path can now be specified for tubing.
#### [v21.19.2](https://github.com/nophead/NopSCADlib/releases/tag/v21.19.2 "show release") Fixes [...](https://github.com/nophead/NopSCADlib/compare/v21.19.1...v21.19.2 "diff with v21.19.1")
* 2024-04-21 [`f563645`](https://github.com/nophead/NopSCADlib/commit/f563645e45817a4f89ef3cb1be9d932310c485c6 "show commit") [C.P.](# "Chris Palmer") Corrected M2 `nut_trap_depth,` was too big.
#### [v21.19.1](https://github.com/nophead/NopSCADlib/releases/tag/v21.19.1 "show release") Fixes [...](https://github.com/nophead/NopSCADlib/compare/v21.19.0...v21.19.1 "diff with v21.19.0")
* 2024-04-21 [`2840cc2`](https://github.com/nophead/NopSCADlib/commit/2840cc2390a8e776add8ca3ef715abfc8d15dadc "show commit") [C.P.](# "Chris Palmer") Washer now uses `sweep.scad` instead of including it, leaking its interface.
### [v21.19.0](https://github.com/nophead/NopSCADlib/releases/tag/v21.19.0 "show release") Additions [...](https://github.com/nophead/NopSCADlib/compare/v21.18.0...v21.19.0 "diff with v21.18.0")
* 2024-04-21 [`a5b2018`](https://github.com/nophead/NopSCADlib/commit/a5b20180083ba8d3014bc298cf0e28c20e6be437 "show commit") [C.P.](# "Chris Palmer") Added `offset_paths()` to `sweep.scad`.
`show_path()` now takes an optional radius.
### [v21.18.0](https://github.com/nophead/NopSCADlib/releases/tag/v21.18.0 "show release") Additions [...](https://github.com/nophead/NopSCADlib/compare/v21.17.0...v21.18.0 "diff with v21.17.0")
* 2024-03-14 [`19dadcb`](https://github.com/nophead/NopSCADlib/commit/19dadcb58db0dd7408726c69d46cf2b7b26c764b "show commit") [C.P.](# "Chris Palmer") Updated images and readme.
* 2024-03-14 [`c565f29`](https://github.com/nophead/NopSCADlib/commit/c565f2912e7319575fc6ec3262699b73305c46b4 "show commit") [V.](# "V.Shkriabets") Update MT3608 pcb module
### [v21.17.0](https://github.com/nophead/NopSCADlib/releases/tag/v21.17.0 "show release") Additions [...](https://github.com/nophead/NopSCADlib/compare/v21.16.1...v21.17.0 "diff with v21.16.1")
* 2024-03-14 [`5579c0d`](https://github.com/nophead/NopSCADlib/commit/5579c0d988c6d7983d3884afa7e42fdb283109a8 "show commit") [C.P.](# "Chris Palmer") Fixed `box_shelf_bracket()` horizontal holes.
Added a third child to `box_shelf_bracket()` to allow custom additions.
* 2024-03-14 [`67408f8`](https://github.com/nophead/NopSCADlib/commit/67408f8422918416c617ec7389dbc09b2c62a2ae "show commit") [C.P.](# "Chris Palmer") Added `d_hole()` module.
* 2024-03-14 [`929abbe`](https://github.com/nophead/NopSCADlib/commit/929abbefda2c380b121c775371f197860c6c3aff "show commit") [C.P.](# "Chris Palmer") Updated front page image.
* 2024-03-14 [`c7727e7`](https://github.com/nophead/NopSCADlib/commit/c7727e7106e3829a6b5f6c501b1a082d540a4a68 "show commit") [C.P.](# "Chris Palmer") Added Sellotape to sheets.
* 2024-03-14 [`1dbba5a`](https://github.com/nophead/NopSCADlib/commit/1dbba5a650f8dac2d05a5668008e61a5ec22ea4f "show commit") [C.P.](# "Chris Palmer") Added `camera_lens_height()` function.
#### [v21.16.1](https://github.com/nophead/NopSCADlib/releases/tag/v21.16.1 "show release") Fixes [...](https://github.com/nophead/NopSCADlib/compare/v21.16.0...v21.16.1 "diff with v21.16.0")
* 2024-03-14 [`db2a9a8`](https://github.com/nophead/NopSCADlib/commit/db2a9a8a24966f098d4c0c8157de98a885b79a85 "show commit") [C.P.](# "Chris Palmer") Ziptie test can now show wires with t `=` 0.
* 2024-03-14 [`6ced9c8`](https://github.com/nophead/NopSCADlib/commit/6ced9c871c5a637dbe8494836a4233e1f6cd4971 "show commit") [C.P.](# "Chris Palmer") Fixed FOV for ESP32 camera being rotated.
Shortened the ESP32 camera header pins.
* 2024-03-14 [`d6b00fb`](https://github.com/nophead/NopSCADlib/commit/d6b00fbf5719239adc5e8b66f863c003a50806d3 "show commit") [C.P.](# "Chris Palmer") Removed unused test code.
* 2024-03-14 [`2c996bb`](https://github.com/nophead/NopSCADlib/commit/2c996bb7a143a85c21833a69f56f2f47afabe072 "show commit") [C.P.](# "Chris Palmer") Fixed random error caused by not running bom first.
### [v21.16.0](https://github.com/nophead/NopSCADlib/releases/tag/v21.16.0 "show release") Additions [...](https://github.com/nophead/NopSCADlib/compare/v21.15.0...v21.16.0 "diff with v21.15.0")
* 2024-02-19 [`fdb92ec`](https://github.com/nophead/NopSCADlib/commit/fdb92ec263d60a42e04f06abfeec5e1648a12b6b "show commit") [C.P.](# "Chris Palmer") Improved layout to fit into front page view.

View File

@@ -97,6 +97,7 @@ use <utils/hanging_hole.scad>
use <utils/fillet.scad>
use <utils/rounded_polygon.scad>
use <utils/rounded_triangle.scad>
use <utils/splines.scad>
use <utils/layout.scad>
use <utils/round.scad>
use <utils/offset.scad>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1000 KiB

After

Width:  |  Height:  |  Size: 1002 KiB

View File

@@ -494,7 +494,8 @@ module box_shelf_screw_positions(type, screw_positions, thickness = 0, wall = un
for(p = screw_positions)
multmatrix(p)
translate_z(thickness)
children();
let($horizontal = true)
children();
r = box_boss_r(type);
inset = box_intrusion(type) - r + (r + insert_boss_radius(insert, w) + bezel_clearance / 2) / sqrt(2);
@@ -503,10 +504,11 @@ module box_shelf_screw_positions(type, screw_positions, thickness = 0, wall = un
for(x = [-1, 1], y = [-1, 1])
translate([x * (box_width(type) / 2 - inset), y * (box_depth(type) / 2 - inset)])
rotate(45 * x * (2 + y))
children();
let($horizontal = false)
children();
}
module box_shelf_bracket(type, screw_positions, wall = undef) { //! Generates a shelf bracket, the first optional child is a 2D cutout and the second 3D cutouts
module box_shelf_bracket(type, screw_positions, wall = undef) { //! Generates a shelf bracket, the first optional child is a 2D cutout and the second 3D cutouts, third child is 3D additions.
w = is_undef(wall) ? box_wall(type) : wall;
insert = box_shelf_insert(type);
lip = 2 * insert_boss_radius(insert, w);
@@ -561,9 +563,13 @@ module box_shelf_bracket(type, screw_positions, wall = undef) { //! Generates a
children(0);
}
hflip()
hflip() {
box_shelf_screw_positions(type, screw_positions, 0, w)
boss();
if($children > 2)
children(2);
}
}
if($children > 1)
hflip()
@@ -571,7 +577,7 @@ module box_shelf_bracket(type, screw_positions, wall = undef) { //! Generates a
hflip()
box_shelf_screw_positions(type, screw_positions, 0, w)
insert_hole(insert, counterbore = 1, horizontal = true);
insert_hole(insert, counterbore = 1, horizontal = $horizontal);
}
}

View File

@@ -18,7 +18,7 @@
//
//
//! Cable clips to order. Can be for one or two cables of different sizes. Can use an insert and a screw from below or a screw and nut either way up.
//! Cable clips to order. Can be for one or two cables of different sizes. Can use an insert and a screw from below or a screw and nut, nyloc or plain, either way up.
//
include <../core.scad>
use <../vitamins/wire.scad>
@@ -30,27 +30,29 @@ wall = 2;
function cable_clip_insert(screw, insert = true) = //! Insert type for clip, given screw.
is_list(insert) ? insert : insert ? screw_insert(screw, true) : false;
function cable_clip_width(screw, insert = false) = //! Width given the `screw` and possibly insert.
function cable_clip_width(screw, insert = false, nut = false) = //! Width given the `screw` and possibly insert or nut.
let(insert = cable_clip_insert(screw, insert))
insert ? 2 * (insert_hole_radius(insert) + wall) :
max(wall + 2 * screw_clearance_radius(screw) + wall, washer_diameter(screw_washer(screw)));
nut ? 2 * (nut_radius(screw_nut(screw)) + wall) :
max(wall + 2 * screw_clearance_radius(screw) + wall, washer_diameter(screw_washer(screw)));
function cable_clip_height(cable, screw = false, insert = false) = //! Height given the `cable`.
function cable_clip_height(cable, screw = false, insert = false, nut = false) = //! Height given the `cable`.
let(insert = cable_clip_insert(screw, insert))
max(cable_height(cable) + wall, insert ? insert_hole_length(insert) + 1 : 0);
max(cable_height(cable) + wall, insert ? insert_hole_length(insert) + 1 : 0, nut ? nut_trap_depth(screw_nut(screw)) + wall : 0);
function cable_clip_extent(screw, cable, insert = false) = cable_clip_width(screw, insert) / 2 + cable_width(cable) + wall; //! How far it extends from the screw.
function cable_clip_offset(screw, cable, insert = false) = cable_clip_width(screw, insert) / 2 + cable_width(cable) / 2; //! The offset of the cable from the screw.
function cable_clip_extent(screw, cable, insert = false, nut = false) = cable_clip_width(screw, insert, nut) / 2 + cable_width(cable) + wall; //! How far it extends from the screw.
function cable_clip_offset(screw, cable, insert = false, nut = false) = cable_clip_width(screw, insert, nut) / 2 + cable_width(cable) / 2; //! The offset of the cable from the screw.
module single_cable_clip(screw, cable, h = 0, insert = false) {
module single_cable_clip(screw, cable, h = 0, insert = false, nut = false) {
insert = cable_clip_insert(screw, insert);
height = cable_clip_width(screw, insert);
depth = h ? h : cable_clip_height(cable, screw, insert);
height = cable_clip_width(screw, insert, nut);
depth = h ? h : cable_clip_height(cable, screw, insert, nut);
w = cable_width(cable);
width = wall + w + height;
hole_x = wall + w + height / 2;
rad = min(wall + cable_wire_size(cable) / 2, depth / 2);
r = extrusion_width - eps;
the_nut = screw_nut(screw);
translate([-hole_x, 0])
difference() {
linear_extrude(height)
@@ -85,62 +87,68 @@ module single_cable_clip(screw, cable, h = 0, insert = false) {
if(insert)
insert_hole(insert, 10, horizontal = true);
else
teardrop_plus(h = 2 * depth + 1, r = screw_clearance_radius(screw), center = true);
if(nut) {
translate_z(depth - wall - nut_trap_depth(the_nut))
nut_trap(screw, the_nut, horizontal = true);
nut_trap(screw, the_nut, horizontal = true);
}
else
teardrop_plus(h = 2 * depth + 1, r = screw_clearance_radius(screw), center = true);
}
}
module double_cable_clip(screw, cable1, cable2, insert = false) {
h = max(cable_clip_height(cable1, screw, insert), cable_clip_height(cable2, screw, insert));
module double_cable_clip(screw, cable1, cable2, insert = false, nut = false) {
h = max(cable_clip_height(cable1, screw, insert, nut), cable_clip_height(cable2, screw, insert, nut));
union() {
single_cable_clip(screw, cable1, h, insert);
single_cable_clip(screw, cable1, h, insert, nut);
mirror([1,0,0]) single_cable_clip(screw, cable2, h, insert);
mirror([1,0,0]) single_cable_clip(screw, cable2, h, insert, nut);
}
}
module cable_clip(screw, cable1, cable2 = 0, insert = false) { //! Create the STL for a single cable or two cable clip
function clip_str(screw) = str("cable_clip_", screw_radius(screw) * 20, insert ? "I" : "");
module cable_clip(screw, cable1, cable2 = 0, insert = false, nut = false) { //! Create the STL for a single cable or two cable clip
function clip_str(screw) = str("cable_clip_", screw_radius(screw) * 20, insert ? "I" : nut ? "N" : "");
function cable_str(cable) = str("_", cable_wires(cable), "_", round(cable_wire_size(cable) * 10));
if(cable2) {
stl(str(clip_str(screw), cable_str(cable1), cable_str(cable2)));
double_cable_clip(screw, cable1, cable2, insert);
}
else {
stl(str(clip_str(screw), cable_str(cable1)));
single_cable_clip(screw, cable1, h = 0, insert = insert);
}
assert(!(insert && nut), "insert and nut mutually exclusive");
if(cable2)
stl(str(clip_str(screw), cable_str(cable1), cable_str(cable2)))
double_cable_clip(screw, cable1, cable2, insert, nut);
else
stl(str(clip_str(screw), cable_str(cable1)))
single_cable_clip(screw, cable1, h = 0, insert = insert, nut = nut);
}
module cable_clip_assembly(screw, thickness, cable1, cable2 = 0, flip = false, insert = false) { //! Cable clip with the fasteners
flip = flip || insert; // Screw must be below if using an insert
module cable_clip_assembly(screw, thickness, cable1, cable2 = 0, flip = false, insert = false, nut = false, nyloc = true) { //! Cable clip with the fasteners
flip = flip || insert || nut; // Screw must be below if using an insert or nut
insert = cable_clip_insert(screw, insert);
height = max(cable_clip_height(cable1, screw, insert), cable2 ? cable_clip_height(cable2, screw, insert) : 0);
height = max(cable_clip_height(cable1, screw, insert, nut), cable2 ? cable_clip_height(cable2, screw, insert, nut) : 0);
stl_colour(pp1_colour) render()
translate([0, cable_clip_width(screw, insert) / 2])
translate([0, cable_clip_width(screw, insert, nut) / 2])
rotate([90, 0, 0])
cable_clip(screw, cable1, cable2, insert);
cable_clip(screw, cable1, cable2, insert, nut);
nut = screw_nut(screw);
screw_len = screw_length(screw, height + thickness, 2, nyloc = !insert, insert = insert);
the_nut = screw_nut(screw);
screw_len = nut ? screw_length(screw, thickness + wall, nyloc ? 1 : 2, nyloc = nyloc, nut = !nyloc)
: screw_length(screw, thickness + height, 2, nut = !nyloc && !insert, nyloc = !insert && nyloc, insert = insert);
translate_z(height)
if(flip)
if(insert)
insert(insert);
else
nut_and_washer(nut, true);
if(nut)
translate_z(-height + wall)
nut(the_nut, nyloc);
else
nut_and_washer(the_nut, nyloc);
else
screw_and_washer(screw, screw_len);
translate_z(-thickness)
vflip()
if(flip)
screw_and_washer(screw, screw_len, insert);
screw_and_washer(screw, screw_len, insert || !nyloc);
else
nut_and_washer(nut, true);
nut_and_washer(the_nut, nyloc);
}

103
readme.md
View File

@@ -40,10 +40,10 @@ A list of changes classified as breaking, additions or fixes is maintained in [C
<tr><td> <a href = "#dip">DIP</a> </td><td> <a href = "#opengrab">Opengrab</a> </td><td> <a href = "#springs">Springs</a> </td><td> <a href = "#led_bezel">LED_bezel</a> </td><td> <a href = "#rounded_polygon">Rounded_polygon</a> </td><td></td></tr>
<tr><td> <a href = "#d_connectors">D_connectors</a> </td><td> <a href = "#pcb">PCB</a> </td><td> <a href = "#stepper_motors">Stepper_motors</a> </td><td> <a href = "#pcb_mount">PCB_mount</a> </td><td> <a href = "#rounded_triangle">Rounded_triangle</a> </td><td></td></tr>
<tr><td> <a href = "#displays">Displays</a> </td><td> <a href = "#pcbs">PCBs</a> </td><td> <a href = "#swiss_clips">Swiss_clips</a> </td><td> <a href = "#psu_shroud">PSU_shroud</a> </td><td> <a href = "#sector">Sector</a> </td><td></td></tr>
<tr><td> <a href = "#extrusion_brackets">Extrusion_brackets</a> </td><td> <a href = "#psus">PSUs</a> </td><td> <a href = "#terminals">Terminals</a> </td><td> <a href = "#pocket_handle">Pocket_handle</a> </td><td> <a href = "#sweep">Sweep</a> </td><td></td></tr>
<tr><td> <a href = "#extrusions">Extrusions</a> </td><td> <a href = "#panel_meters">Panel_meters</a> </td><td> <a href = "#toggles">Toggles</a> </td><td> <a href = "#press_fit">Press_fit</a> </td><td> <a href = "#thread">Thread</a> </td><td></td></tr>
<tr><td> <a href = "#fans">Fans</a> </td><td> <a href = "#photo_interrupters">Photo_interrupters</a> </td><td> <a href = "#transformers">Transformers</a> </td><td> <a href = "#printed_box">Printed_box</a> </td><td> <a href = "#tube">Tube</a> </td><td></td></tr>
<tr><td> <a href = "#fastons">Fastons</a> </td><td> <a href = "#pillars">Pillars</a> </td><td> <a href = "#ttracks">Ttracks</a> </td><td> <a href = "#printed_pulleys">Printed_pulleys</a> </td><td></td><td></td></tr>
<tr><td> <a href = "#extrusion_brackets">Extrusion_brackets</a> </td><td> <a href = "#psus">PSUs</a> </td><td> <a href = "#terminals">Terminals</a> </td><td> <a href = "#pocket_handle">Pocket_handle</a> </td><td> <a href = "#splines">Splines</a> </td><td></td></tr>
<tr><td> <a href = "#extrusions">Extrusions</a> </td><td> <a href = "#panel_meters">Panel_meters</a> </td><td> <a href = "#toggles">Toggles</a> </td><td> <a href = "#press_fit">Press_fit</a> </td><td> <a href = "#sweep">Sweep</a> </td><td></td></tr>
<tr><td> <a href = "#fans">Fans</a> </td><td> <a href = "#photo_interrupters">Photo_interrupters</a> </td><td> <a href = "#transformers">Transformers</a> </td><td> <a href = "#printed_box">Printed_box</a> </td><td> <a href = "#thread">Thread</a> </td><td></td></tr>
<tr><td> <a href = "#fastons">Fastons</a> </td><td> <a href = "#pillars">Pillars</a> </td><td> <a href = "#ttracks">Ttracks</a> </td><td> <a href = "#printed_pulleys">Printed_pulleys</a> </td><td> <a href = "#tube">Tube</a> </td><td></td></tr>
<tr><td> <a href = "#fuseholder">Fuseholder</a> </td><td> <a href = "#pillow_blocks">Pillow_blocks</a> </td><td> <a href = "#tubings">Tubings</a> </td><td> <a href = "#ribbon_clamp">Ribbon_clamp</a> </td><td></td><td></td></tr>
<tr><td> <a href = "#gear_motors">Gear_motors</a> </td><td> <a href = "#pin_headers">Pin_headers</a> </td><td> <a href = "#variacs">Variacs</a> </td><td> <a href = "#ssr_shroud">SSR_shroud</a> </td><td></td><td></td></tr>
<tr><td> <a href = "#geared_steppers">Geared_steppers</a> </td><td> <a href = "#potentiometers">Potentiometers</a> </td><td> <a href = "#veroboard">Veroboard</a> </td><td> <a href = "#screw_knob">Screw_knob</a> </td><td></td><td></td></tr>
@@ -779,6 +779,11 @@ PCB cameras.
| `camera_lens_offset(type)` | Offset of the lens center from the PCB centre |
| `camera_pcb(type)` | The PCB part of the camera |
### Functions
| Function | Description |
|:--- |:--- |
| `camera_lens_height(type)` | The height of the lens stack |
### Modules
| Module | Description |
|:--- |:--- |
@@ -982,6 +987,7 @@ D-connectors. Can be any number of ways, male or female, solder buckets, PCB mou
| Module | Description |
|:--- |:--- |
| `d_connector_holes(type)` | Place children at the screw hole positions |
| `d_hole(type, h = 0, center = true, clearance = 0.2)` | Make a hole to clear the back of d-connector |
| `d_pillar()` | Draw a pillar for a D-connector |
| `d_plug(type, socket = false, pcb = false, idc = false)` | Draw specified D plug, which can be IDC, PCB or plain solder bucket |
| `d_plug_D(length, width, rad)` | D plug D shape |
@@ -1453,7 +1459,7 @@ Geared tin can steppers
### Modules
| Module | Description |
|:--- |:--- |
| `geared_stepper(type)` | Draw the specified geared stepper |
| `geared_stepper(type, angle = 0)` | Draw the specified geared stepper with optional shaft angle. |
| `geared_stepper_screw_positions(type)` | Place children at the screw positions |
![geared_steppers](tests/png/geared_steppers.png)
@@ -2878,6 +2884,7 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
| 1 | `pcb(Melzi)` | Melzi electronics - not shown |
| 6 | | Micro SD card |
| 1 | | Micro SD card - not shown |
| 1 | `pcb(RCWL-0516)` | Microwave Radar Sensor |
| 1 | `molex_254(2)` | Molex KK header 2 way - not shown |
| 1 | `molex_254(3)` | Molex KK header 3 way - not shown |
| 20 | `nut(M2_nut, nyloc = true)` | Nut M2 x 1.6mm nyloc |
@@ -2905,8 +2912,7 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
| 8 | `screw(M2_cap_screw, 20)` | Screw M2 cap x 20mm |
| 4 | `screw(M2_cap_screw, 25)` | Screw M2 cap x 25mm |
| 2 | `screw(M2p5_cap_screw, 20)` | Screw M2.5 cap x 20mm |
| 4 | `screw(M2p5_cap_screw, 25)` | Screw M2.5 cap x 25mm |
| 4 | `screw(M2p5_cap_screw, 30)` | Screw M2.5 cap x 30mm |
| 8 | `screw(M2p5_cap_screw, 30)` | Screw M2.5 cap x 30mm |
| 12 | `screw(M2p5_cap_screw, 35)` | Screw M2.5 cap x 35mm |
| 4 | `screw(M2p5_dome_screw, 25)` | Screw M2.5 dome x 25mm |
| 4 | `screw(M2p5_pan_screw, 20)` | Screw M2.5 pan x 20mm |
@@ -2914,8 +2920,7 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
| 19 | `screw(M3_cap_screw, 16)` | Screw M3 cap x 16mm |
| 13 | `screw(M3_cap_screw, 20)` | Screw M3 cap x 20mm |
| 4 | `screw(M3_cap_screw, 25)` | Screw M3 cap x 25mm |
| 8 | `screw(M3_cap_screw, 30)` | Screw M3 cap x 30mm |
| 3 | `screw(M3_cap_screw, 35)` | Screw M3 cap x 35mm |
| 11 | `screw(M3_cap_screw, 35)` | Screw M3 cap x 35mm |
| 4 | `screw(M4_cap_screw, 20)` | Screw M4 cap x 20mm |
| 4 | `screw(M4_cap_screw, 25)` | Screw M4 cap x 25mm |
| 1 | `pcb(XIAO)` | Seeeduino XIAO |
@@ -2935,24 +2940,24 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
| Qty | Filename |
| ---:|:--- |
| 4 | pcb_spacer20100.stl |
| 4 | pcb_spacer20140.stl |
| 4 | pcb_spacer20150.stl |
| 4 | pcb_spacer2070.stl |
| 4 | pcb_spacer2080.stl |
| 4 | pcb_spacer2090.stl |
| 2 | pcb_spacer25100.stl |
| 4 | pcb_spacer25130.stl |
| 4 | pcb_spacer25160.stl |
| 2 | pcb_spacer25110.stl |
| 4 | pcb_spacer25140.stl |
| 4 | pcb_spacer25170.stl |
| 4 | pcb_spacer25180_2.stl |
| 4 | pcb_spacer25180.stl |
| 4 | pcb_spacer25190_2.stl |
| 4 | pcb_spacer25230.stl |
| 4 | pcb_spacer25200_2.stl |
| 4 | pcb_spacer25240.stl |
| 4 | pcb_spacer25250.stl |
| 4 | pcb_spacer25260.stl |
| 4 | pcb_spacer2580.stl |
| 4 | pcb_spacer30120.stl |
| 4 | pcb_spacer30200.stl |
| 4 | pcb_spacer30130.stl |
| 4 | pcb_spacer30210.stl |
| 3 | pcb_spacer30220.stl |
| 4 | pcb_spacer30220.stl |
| 3 | pcb_spacer30230.stl |
| 10 | pcb_spacer3050.stl |
| 9 | pcb_spacer3060.stl |
| 9 | pcb_spacer3070.stl |
@@ -4033,6 +4038,7 @@ When woven sheets (e.g. carbon fibre) are rendered it is necessary to specify th
| 1 | `sheet(Spring08, 30, 30, 2)` | Bi-metal saw blade 30mm x 30mm x 0.8mm |
| 1 | `sheet(Cardboard, 30, 30, 2)` | Corrugated cardboard 30mm x 30mm x 5mm |
| 1 | `sheet(Foam20, 30, 30, 2)` | Foam sponge 30mm x 30mm x 20mm |
| 1 | `sheet(Sellotape, 30, 30, 2)` | Sellotape tape 30mm x 30mm x 0.05mm |
| 1 | `sheet(DiBond, 30, 30, 2)` | Sheet DiBond 30mm x 30mm x 3mm |
| 1 | `sheet(DiBond6, 30, 30, 2)` | Sheet DiBond 30mm x 30mm x 6mm |
| 1 | `sheet(MDF10, 30, 30, 2)` | Sheet MDF 30mm x 30mm x 10mm |
@@ -4222,6 +4228,7 @@ E.g. 475A is 4.7uF 10V on the parts list.
### Vitamins
| Qty | Module call | BOM entry |
| ---:|:--- |:---|
| 1 | `smd_inductor(CDRH104)` | CDRH104 package 10R |
| 1 | `smd_diode(DO214AC)` | DO214AC package SS34 |
| 1 | `smd_inductor(IND2525)` | IND2525 package 4R7 |
| 1 | `smd_led(LED0603, green)` | SMD LED 0603 green |
@@ -4763,7 +4770,7 @@ T-Tracks used in woodworking jigs
---
<a name="tubings"></a>
## Tubings
Tubing and sleeving. The internal diameter can be forced to stretch it over something.
Tubing and sleeving. The internal diameter can be forced to stretch it over something. A path can be specified, otherwise it is just straight with the specified length.
[vitamins/tubings.scad](vitamins/tubings.scad) Object definitions.
@@ -4788,7 +4795,7 @@ Tubing and sleeving. The internal diameter can be forced to stretch it over some
### Modules
| Module | Description |
|:--- |:--- |
| `tubing(type, length = 15, forced_id = 0, center = true)` | Draw specified tubing with optional forced internal diameter |
| `tubing(type, length = 15, forced_id = 0, center = true, path = [])` | Draw specified tubing with optional forced internal diameter and optional path. |
![tubings](tests/png/tubings.png)
@@ -5199,7 +5206,7 @@ The top bezel can have an optional child, which is subtracted to allow modificat
| `box_right(type)` | Default right side, can be overridden to customise |
| `box_right_blank(type, sheet = false)` | Generates a 2D template for the right sheet, `sheet` can be set to override the type |
| `box_shelf_blank(type, sheet = false, wall = undef)` | Generates a 2D template for a shelf sheet |
| `box_shelf_bracket(type, screw_positions, wall = undef)` | Generates a shelf bracket, the first optional child is a 2D cutout and the second 3D cutouts |
| `box_shelf_bracket(type, screw_positions, wall = undef)` | Generates a shelf bracket, the first optional child is a 2D cutout and the second 3D cutouts, third child is 3D additions. |
| `box_shelf_bracket_section(type, rows, cols, x, y)` | Generates sections of the shelf bracket to allow it to be bigger than the printer |
| `box_shelf_screw_positions(type, screw_positions, thickness = 0, wall = undef, top_screws = true)` | Place children at the shelf screw positions |
| `box_top(type)` | Default top, can be overridden to customise |
@@ -5357,7 +5364,7 @@ fixing_blocks along the sides.
---
<a name="cable_clip"></a>
## Cable_clip
Cable clips to order. Can be for one or two cables of different sizes. Can use an insert and a screw from below or a screw and nut either way up.
Cable clips to order. Can be for one or two cables of different sizes. Can use an insert and a screw from below or a screw and nut, nyloc or plain, either way up.
[printed/cable_clip.scad](printed/cable_clip.scad) Implementation.
@@ -5366,17 +5373,17 @@ Cable clips to order. Can be for one or two cables of different sizes. Can use a
### Functions
| Function | Description |
|:--- |:--- |
| `cable_clip_extent(screw, cable, insert = false)` | How far it extends from the screw. |
| `cable_clip_height(cable, screw = false, insert = false)` | Height given the `cable`. |
| `cable_clip_extent(screw, cable, insert = false, nut = false)` | How far it extends from the screw. |
| `cable_clip_height(cable, screw = false, insert = false, nut = false)` | Height given the `cable`. |
| `cable_clip_insert(screw, insert = true)` | Insert type for clip, given screw. |
| `cable_clip_offset(screw, cable, insert = false)` | The offset of the cable from the screw. |
| `cable_clip_width(screw, insert = false)` | Width given the `screw` and possibly insert. |
| `cable_clip_offset(screw, cable, insert = false, nut = false)` | The offset of the cable from the screw. |
| `cable_clip_width(screw, insert = false, nut = false)` | Width given the `screw` and possibly insert or nut. |
### Modules
| Module | Description |
|:--- |:--- |
| `cable_clip(screw, cable1, cable2 = 0, insert = false)` | Create the STL for a single cable or two cable clip |
| `cable_clip_assembly(screw, thickness, cable1, cable2 = 0, flip = false, insert = false)` | Cable clip with the fasteners |
| `cable_clip(screw, cable1, cable2 = 0, insert = false, nut = false)` | Create the STL for a single cable or two cable clip |
| `cable_clip_assembly(screw, thickness, cable1, cable2 = 0, flip = false, insert = false, nut = false, nyloc = true)` | Cable clip with the fasteners |
![cable_clip](tests/png/cable_clip.png)
@@ -5385,10 +5392,10 @@ Cable clips to order. Can be for one or two cables of different sizes. Can use a
| ---:|:--- |:---|
| 2 | `insert(CNCKM3)` | Heatfit insert M3 x 3mm |
| 5 | `nut(M3_nut, nyloc = true)` | Nut M3 x 2.4mm nyloc |
| 2 | `screw(M3_dome_screw, 10)` | Screw M3 dome x 10mm |
| 3 | `screw(M3_dome_screw, 10)` | Screw M3 dome x 10mm |
| 1 | `screw(M3_dome_screw, 12)` | Screw M3 dome x 12mm |
| 4 | `screw(M3_dome_screw, 16)` | Screw M3 dome x 16mm |
| 12 | `washer(M3_washer)` | Washer M3 x 7mm x 0.5mm |
| 3 | `screw(M3_dome_screw, 16)` | Screw M3 dome x 16mm |
| 11 | `washer(M3_washer)` | Washer M3 x 7mm x 0.5mm |
| 2 | `star_washer(M3_washer)` | Washer star M3 x 0.5mm |
### Printed
@@ -5396,10 +5403,10 @@ Cable clips to order. Can be for one or two cables of different sizes. Can use a
| ---:|:--- |
| 1 | cable_clip_30I_10_13.stl |
| 1 | cable_clip_30I_5_14_6_14.stl |
| 1 | cable_clip_30N_7_14_8_14.stl |
| 1 | cable_clip_30_1_14_2_14.stl |
| 1 | cable_clip_30_1_60.stl |
| 1 | cable_clip_30_3_14_4_14.stl |
| 1 | cable_clip_30_7_14_8_14.stl |
| 1 | cable_clip_30_9_14.stl |
@@ -5480,7 +5487,8 @@ Housings for PCB cameras.
| 1 | `camera(rpi_camera_v1)` | Raspberry Pi camera V1 |
| 1 | `camera(rpi_camera_v2)` | Raspberry Pi camera V2 |
| 1 | `camera(rpi_camera)` | Raspberry Pi focusable camera |
| 7 | `screw(M2_cap_screw, 10)` | Screw M2 cap x 10mm |
| 3 | `screw(M2_cap_screw, 8)` | Screw M2 cap x 8mm |
| 4 | `screw(M2_cap_screw, 10)` | Screw M2 cap x 10mm |
| 4 | `screw(M3_cap_screw, 16)` | Screw M3 cap x 16mm |
| 4 | `screw(M3_dome_screw, 10)` | Screw M3 dome x 10mm |
| 2 | `screw(M3_dome_screw, 12)` | Screw M3 dome x 12mm |
@@ -7411,6 +7419,32 @@ A sector of a circle between two angles.
![sector](tests/png/sector.png)
<a href="#top">Top</a>
---
<a name="splines"></a>
## Splines
Cubic splines that interpolate between a list of 2D points passing through all of them.
Translated from the Python version at <https://community.alteryx.com/t5/Engine-Works/Creating-a-Cubic-Spline-in-Python-and-Alteryx/ba-p/581173>.
Note the x values of the points must be strictly increasing.
Catmull-Rom splines are well behaved but the ends points are control points and the curve only goes from the second point to the penultimate point.
Coded from <https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline#Code_example_in_Python>.
No restrictions on points and they can be 3D.
[utils/splines.scad](utils/splines.scad) Implementation.
[tests/splines.scad](tests/splines.scad) Code for this example.
### Functions
| Function | Description |
|:--- |:--- |
| `catmull_rom_spline(points, n, alpha = 0.5)` | Interpolate n new points between the specified points with a Catmull-Rom spline, alpha = 0.5 for centripetal, 0 for uniform and 1 for chordal. |
| `cubic_spline(points, N = 100)` | Interpolate the list of points given to produce N points on a cubic spline that passes through points given. |
![splines](tests/png/splines.png)
<a href="#top">Top</a>
---
@@ -7443,6 +7477,7 @@ Each vertex, apart from the first and the last, has an associated radius and the
| `cap(facets, segment = 0, end)` | Create the mesh for an end cap |
| `circle_points(r = 1, z = 0, dir = -1)` | Generate the points of a circle, setting z makes a single turn spiral |
| `helical_twist_per_segment(r, pitch, sides)` | Calculate the twist around Z that rotate_from_to() introduces |
| `offset_paths(path, offsets, twists = 0)` | Create new paths offset from the original, optionally spiralling around it |
| `rectangle_points(w, h)` | Generate the points of a rectangle |
| `rounded_path(path)` | Convert a rounded_path, consisting of a start coordinate, vertex / radius pairs and then an end coordinate, to a path of points for sweep. |
| `rounded_path_vertices(path)` | Show the unrounded version of a rounded_path for debug |
@@ -7454,7 +7489,7 @@ Each vertex, apart from the first and the last, has an associated radius and the
### Modules
| Module | Description |
|:--- |:--- |
| `show_path(path)` | Show a path using a chain of hulls for debugging, duplicate points are highlighted. |
| `show_path(path, r = 0.1)` | Show a path using a chain of hulls for debugging, duplicate points are highlighted. |
| `sweep(path, profile, loop = false, twist = 0, convexity = 1)` | Draw a polyhedron that is the swept volume |
![sweep](tests/png/sweep.png)

View File

@@ -67,7 +67,7 @@ module smds() {
translate([0, 39])
layout([for(i = smd_inductors) smd_inductor_leads(i).x], 1)
let(i = smd_inductors[$i])
smd_inductor(i, "4R7");
smd_inductor(i, ["4R7", "10R"][$i % 2]);
translate([20, 6])
layout([for(q = smd_qfps) smd_qfp_body_size(q).x], 3)

View File

@@ -20,33 +20,39 @@
include <../core.scad>
use <../printed/cable_clip.scad>
use <../vitamins/wire.scad>
use <../utils/layout.scad>
screw = M3_dome_screw;
sheet_thickness = 3;
cables = [
[10, inch(0.05), true], 0, for(i = [1 : 9]) [i, 1.4], 0, [1, 6], 0,
];
screw = M3_dome_screw;
clips = [for(i = [0 : ceil(len(cables) / 2) - 1]) let(c1= cables[2 * i], c2 = cables[2 * i + 1]) [c1, c2]];
function use_insert(i) = in([0, 3], i);
function use_nut(i) = in([4], i);
clip_lengths = [for(i = [0 : len(clips) - 1])
let(c = clips[i], c1 = c.x, c2 = c.y, ins = use_insert(i), nut = use_nut(i))
cable_clip_extent(screw, c1, insert = ins, nut = nut) + (c2 ? cable_clip_extent(screw, c2, insert = ins, nut = nut) : cable_clip_width(screw, insert = ins, nut = nut) / 2)];
module cable_clips() {
for(i = [0 : ceil(len(cables) / 2) - 1]) {
cable1 = cables[2 * i];
cable2 = cables[2 * i + 1];
translate([i * 21 + (!cable2 ? cable_clip_offset(screw, cable1) / 2 : 0), 0]) {
insert = in([0, 3], i);
layout(clip_lengths, 3, true) let(cable1 = clips[$i].x, cable2 = clips[$i].y) {
insert = use_insert($i);
nut = use_nut($i);
translate([cable_clip_extent(screw, cable1, insert = insert, nut = nut) - clip_lengths[$i] / 2, 0]) {
if($preview) {
cable_clip_assembly(screw, sheet_thickness, cable1, cable2, insert = insert, flip = i == 1);
cable_clip_assembly(screw, sheet_thickness, cable1, cable2, insert = insert, nut = nut, flip = $i == 1);
for(j = [0 : 1])
let(cable = cables[2 * i + j])
let(cable = clips[$i][j])
if(cable)
let(positions = cable_bundle_positions(cable))
for(i = [0 : len(positions) - 1])
let(p = positions[i])
translate([p.x + [-1, 1][j] * cable_clip_offset(screw, cable, insert = insert), 0, p.y])
translate([p.x + [-1, 1][j] * cable_clip_offset(screw, cable, insert = insert, nut = nut), 0, p.y])
rotate([90, 0, 0])
color([grey(20), "blue", "red", "orange", "yellow", "green", "brown", "purple", "grey", "white"][i])
cylinder(d = cable_wire_size(cable), h = 30, center = true);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 KiB

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

After

Width:  |  Height:  |  Size: 122 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: 151 KiB

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 244 KiB

After

Width:  |  Height:  |  Size: 241 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 179 KiB

After

Width:  |  Height:  |  Size: 190 KiB

BIN
tests/png/splines.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 222 KiB

After

Width:  |  Height:  |  Size: 222 KiB

38
tests/splines.scad Normal file
View File

@@ -0,0 +1,38 @@
//
// NopSCADlib Copyright Chris Palmer 2024
// nop.head@gmail.com
// hydraraptor.blogspot.com
//
// This file is part of NopSCADlib.
//
// NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
// GNU General Public License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with NopSCADlib.
// If not, see <https://www.gnu.org/licenses/>.
//
include <../utils/core/core.scad>
use <../utils/splines.scad>
use <../utils/sweep.scad>
points = [[0, 1.5], [2, 2], [3, 1], [4, -2], [5, 1], [6, 2], [7, 3]];
module splines() {
cm_spline = catmull_rom_spline(points, 100 / len(points), 0.5);
color("green") show_path(cm_spline, 0.01);
cu_spline = cubic_spline(points, 100);
color("blue") show_path(cu_spline, 0.01);
for(p = points)
translate(p) color("red")
cylinder($fn = 64, r = 0.03, h = 0.02, center = true);
}
rotate([70, 0, 315]) splines();

101
utils/splines.scad Normal file
View File

@@ -0,0 +1,101 @@
//
// NopSCADlib Copyright Chris Palmer 2024
// nop.head@gmail.com
// hydraraptor.blogspot.com
//
// This file is part of NopSCADlib.
//
// NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
// GNU General Public License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with NopSCADlib.
// If not, see <https://www.gnu.org/licenses/>.
//
//
//! Cubic splines that interpolate between a list of 2D points passing through all of them.
//! Translated from the Python version at <https://community.alteryx.com/t5/Engine-Works/Creating-a-Cubic-Spline-in-Python-and-Alteryx/ba-p/581173>.
//! Note the x values of the points must be strictly increasing.
//!
//! Catmull-Rom splines are well behaved but the ends points are control points and the curve only goes from the second point to the penultimate point.
//! Coded from <https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline#Code_example_in_Python>.
//! No restrictions on points and they can be 3D.
//
include <../utils/core/core.scad>
use <maths.scad>
use <sweep.scad>
function cubic_spline(points, N = 100) = let( //! Interpolate the list of points given to produce N points on a cubic spline that passes through points given.
N = N - 1,
n = len(points),
ass1 = assert(n >= 3, "must be at least 3 points")0,
dx = [for(i = [0 : n - 2]) points[i + 1].x - points[i].x], // x deltas
ass2 = assert(min(dx) > 0, "X must strictly increase")0,
//
// A and C are diagonals above and below the main diagonal B, which is all 2's
//
A = [for(i = [0 : n - 3]) dx[i] / (dx[i] + dx[i + 1]), 0],
C = [0, for(i = [0 : n - 3]) dx[i + 1] / (dx[i] + dx[i + 1]), 0],
//
// D are the target values on the right hand side of the equation
//
D = [0, for(i = [1 : n - 2]) 6 * ((points[i + 1].y - points[i].y) / dx[i] - (points[i].y - points[i - 1].y) / dx[i - 1]) / (dx[i] + dx[i - 1]), 0],
//
// Solve the tridiagonal equation using the Thomas algorithm
//
c = [for(i = 1, c = 0; i < n; c = C[i] / (2 - c * A[i - 1]), i = i + 1) c, 0],
d = [for(i = 1, d = 0; i < n; d = (D[i] - d * A[i - 1]) / (2 - c[i - 1] * A[i - 1]), i = i + 1) d, 0],
M = [for(i = n - 2, x = 0; i >= 0; x = d[i] - c[i] * x, i = i - 1) x, 0],
//
// Calculate the coefficients of each cubic curve
//
coefficients = [for(i = [0 : n - 2], dx2 = sqr(dx[i]), j = n - 1 - i)
[(M[j - 1] - M[j]) * dx2 / 6,
M[j] * dx2 / 2,
points[i + 1].y - points[i].y - (M[j - 1] + 2 * M[j]) * dx2 / 6,
points[i].y]
],
//
// Use the coefficients to interpolate between the points
//
x0 = points[0].x,
x1 = points[n - 1].x,
spline = [for(i = 0, j = 0, z = 0, x = x0; i <= N + 1;
x = x0 + (x1 - x0) * i / N,
j = i < N - 1 && x > points[j + 1].x ? j + 1 : j,
z = (x - points[j].x) / dx[j],
i = i + 1,
C = coefficients[j]
) if(i) [x, (((C[0] * z) + C[1]) * z + C[2]) * z + C[3]]
]
) spline;
function tj(ti, pi, pj, alpha = 0.5) = ti + pow(norm(pi - pj), alpha);
function catmull_rom_segment(P0, P1, P2, P3, n, alpha = 0.5, last = false) = let(
t0 = 0,
t1 = tj(t0, P0, P1, alpha),
t2 = tj(t1, P1, P2, alpha),
t3 = tj(t2, P2, P3, alpha),
end = last ? n : n - 1,
points = [for(i = [0 : end], t = t1 + (t2 - t1) * i / n) let(
A1 = (t1 - t) / (t1 - t0) * P0 + (t - t0) / (t1 - t0) * P1,
A2 = (t2 - t) / (t2 - t1) * P1 + (t - t1) / (t2 - t1) * P2,
A3 = (t3 - t) / (t3 - t2) * P2 + (t - t2) / (t3 - t2) * P3,
B1 = (t2 - t) / (t2 - t0) * A1 + (t - t0) / (t2 - t0) * A2,
B2 = (t3 - t) / (t3 - t1) * A2 + (t - t1) / (t3 - t1) * A3
) (t2 - t) / (t2 - t1) * B1 + (t - t1) / (t2 - t1) * B2]
) points;
function catmull_rom_spline(points, n, alpha = 0.5) = let( //! Interpolate n new points between the specified points with a Catmull-Rom spline, alpha = 0.5 for centripetal, 0 for uniform and 1 for chordal.
segs = len(points) - 3
) [for(i = [0 : segs - 1]) each catmull_rom_segment(points[i], points[i + 1], points[i + 2], points[i + 3], n, alpha, last = i == segs - 1)];

View File

@@ -111,7 +111,7 @@ function helical_twist_per_segment(r, pitch, sides) = //! Calculate the twist ar
//
// Generate all the transforms for the profile of the swept volume.
//
function sweep_transforms(path, loop = false, twist = 0) =
function sweep_transforms(path, loop = false, twist = 0, initial_rotation = undef) =
let(len = len(path),
last = len - 1,
@@ -122,7 +122,7 @@ function sweep_transforms(path, loop = false, twist = 0) =
lengths = [for(i = 0, t = 0; i < len; t = t + norm(path[min(i + 1, last)] - path[i]), i = i + 1) t],
length = lengths[last],
rotations = [for(i = 0, rot = fs_frame(tangents);
rotations = [for(i = 0, rot = is_undef(initial_rotation) ? fs_frame(tangents) : rot3_z(initial_rotation);
i < len;
i = i + 1,
rot = i < len ? rotate_from_to(tangents[i - 1], tangents[i]) * rot : undef) rot],
@@ -169,7 +169,7 @@ function sweep(path, profile, loop = false, twist = 0) = //! Generate the point
points = skin_points(profile, path, loop, twist),
skin_faces = skin_faces(points, npoints, facets, loop),
faces = loop ? skin_faces : concat([cap(facets)], skin_faces, [cap(facets, npoints - 1)])
) [points, faces];
) [points, faces];
module sweep(path, profile, loop = false, twist = 0, convexity = 1) { //! Draw a polyhedron that is the swept volume
mesh = sweep(path, profile, loop, twist);
@@ -229,16 +229,20 @@ function rounded_path(path) = //! Convert a rounded_path, consisting of a start
function segmented_path(path, min_segment) = [ //! Add points to a path to enforce a minimum segment length
for(i = [0 : len(path) - 2])
let(delta =
assert(path[i] != path[i + 1], str("Coincident points at path[", i, "] = ", path[i]))
path[i+1] - path[i],
segs = ceil(norm(delta) / min_segment)
)
for(j = [0 : segs - 1])
path[i] + delta * j / segs, // Linear interpolation
path[len(path) - 1]
let(delta =
assert(path[i] != path[i + 1], str("Coincident points at path[", i, "] = ", path[i]))
path[i+1] - path[i],
segs = ceil(norm(delta) / min_segment)
)
for(j = [0 : segs - 1])
path[i] + delta * j / segs, // Linear interpolation
path[len(path) - 1]
];
function offset_paths(path, offsets, twists = 0) = let( //! Create new paths offset from the original, optionally spiralling around it
transforms = sweep_transforms(path, twist = 360 * twists, initial_rotation = 0)
) [for(o = offsets) let(initial = [o.x, o.y, o.z, 1]) [for(t = transforms) initial * t]];
function spiral_paths(path, n, r, twists, start_angle) = let( //! Create a new paths which spiral around the given path. Use for making twisted cables
segment = twists ? path_length(path) / twists / r2sides(2 * r) : inf,
transforms = sweep_transforms(segmented_path(path, segment), twist = 360 * twists)
@@ -246,16 +250,16 @@ function spiral_paths(path, n, r, twists, start_angle) = let( //! Create a new p
function rounded_path_vertices(path) = [path[0], for(i = [1 : 2 : len(path) - 1]) path[i]]; //! Show the unrounded version of a rounded_path for debug
module show_path(path) //! Show a path using a chain of hulls for debugging, duplicate points are highlighted.
module show_path(path, r = 0.1) //! Show a path using a chain of hulls for debugging, duplicate points are highlighted.
for(i = [0 : len(path) - 2]) {
hull($fn = 16) {
translate(path[i])
sphere(0.1);
sphere(r);
translate(path[i + 1])
sphere(0.1);
sphere(r);
}
if(path[i] == path[i + 1])
translate(path[i])
color("red") sphere(1);
color("red") sphere($fn = 16, r * 4);
}

View File

@@ -47,7 +47,7 @@ thread_colour_factor = 0.8; // 60 degree threads appear too bright due to the an
function thread_profile(h, crest, angle, overlap = 0.1) = //! Create thread profile path
let(base = crest + 2 * (h + overlap) * tan(angle / 2))
[[-base / 2, -overlap, 0], [-crest / 2, h, 0], [crest / 2, h, 0], [base / 2, -overlap, 0]];
[[-base / 2, -overlap, 0], [-crest / 2, h, 0], if(crest) [crest / 2, h, 0], [base / 2, -overlap, 0]];
module thread(dia, pitch, length, profile, center = true, top = -1, bot = -1, starts = 1, solid = true, female = false, colour = undef) { //! Create male or female thread, ends can be tapered, chamfered or square
assert(is_undef(colour) || is_list(colour), "Thread colour must be in [r, g, b] form");

View File

@@ -30,6 +30,9 @@ function camera_connector_pos(type) = type[5]; //! The flex connector block for
function camera_connector_size(type)= type[6]; //! The flex connector block for the camera itself's size
function camera_fov(type) = type[7]; //! The field of view of the camera lens
function camera_lens_height(type) = //! The height of the lens stack
let(lenses = camera_lens(type), lens = lenses[len(lenses) - 1][0]) lens.y + lens.z;
module camera_lens(type, offset = 0, show_lens = true) //! Draw the lens stack, with optional offset for making a clearance hole
color(grey(20))
translate(camera_lens_offset(type))

View File

@@ -80,6 +80,13 @@ module d_plug_D(length, width, rad) { //! D plug D shape
circle(rad);
}
module d_hole(type, h = 0, center = true, clearance = 0.2) { //! Make a hole to clear the back of d-connector
dwall = 0.5 + clearance;
extrude_if(h, center)
d_plug_D(d_lengths(type)[0] + 2 * dwall, d_widths(type)[0] + 2 * dwall, 2.5 + dwall);
}
module d_plug(type, socket = false, pcb = false, idc = false) { //! Draw specified D plug, which can be IDC, PCB or plain solder bucket
hole_r = 3.05 / 2;
dwall = 0.5;
@@ -106,7 +113,7 @@ module d_plug(type, socket = false, pcb = false, idc = false) { //! Draw specifi
// Shell
//
color(d_plug_shell_colour) {
linear_extrude( d_flange_thickness(type))
linear_extrude(d_flange_thickness(type))
difference() {
rounded_square([flange_length, flange_width], 2);

View File

@@ -52,7 +52,7 @@ module geared_stepper_screw_positions(type) //! Place children at the screw posi
motor_colour = "#9BA2AC";
gearbox_colour = "#FFF7EE";
module geared_stepper(type) { //! Draw the specified geared stepper
module geared_stepper(type, angle = 0) { //! Draw the specified geared stepper with optional shaft angle.
vitamin(str("geared_stepper(", type[0], "): Geared stepper - ", type[1]));
radius = gs_diameter(type) / 2;
@@ -125,19 +125,20 @@ module geared_stepper(type) { //! Draw the specified geared stepper
f = gs_shaft_flat(type);
two_flats = f < 0;
vflip()
color(two_flats ? brass : gearbox_colour) {
d = gs_shaft_d(type);
h = gs_shaft_length(type);
linear_extrude(h)
intersection() {
circle(d = d);
rotate(angle)
color(two_flats ? brass : gearbox_colour) {
d = gs_shaft_d(type);
h = gs_shaft_length(type);
linear_extrude(h)
intersection() {
circle(d = d);
translate([0, two_flats ? 0 : (f - d) / 2])
square([d + 1, abs(f)], center = true);
}
translate([0, two_flats ? 0 : (f - d) / 2])
square([d + 1, abs(f)], center = true);
}
cylinder(d = d, h = h - gs_flat_length(type));
}
cylinder(d = d, h = h - gs_flat_length(type));
}
// Wire block
color(bulge_z ? "white" : "skyblue") {

View File

@@ -212,13 +212,10 @@ module threaded_insert(type) { //! Draw specified threaded insert, for use in wo
thread_l = insert_length(type) - z; // - insert_ring1_h(type);
vitamin(str("threaded_insert(", type[0], "): Threaded insert M", insert_screw_diameter(type), " x ", length, "mm"));
union() {
color(silver)
difference() {
render() difference() {
base_insert(type);
translate_z(-socket/2 + 0.01)
cylinder(r=socket, $fn = 6, h=socket/2);
@@ -245,5 +242,4 @@ module threaded_insert(type) { //! Draw specified threaded insert, for use in wo
female = false,
colour = silver);
}
}

View File

@@ -20,7 +20,7 @@ include <washers.scad>
//
// Nuts
//
M2_nut_trap_depth = 2.5;
M2_nut_trap_depth = 1.75;
M2p5_nut_trap_depth = 2.5;
M3_nut_trap_depth = 3;
M4_nut_trap_depth = 4;

View File

@@ -760,9 +760,15 @@ ZC_A0591 = ["ZC_A0591", "ZC-A0591 ULN2003 driver PCB", 35, 32, 1.6, 0, 2.5, 0, "
], [], [], [], M2p5_pan_screw];
MT3608 = ["MT3608", "MT3608 boost converter module", 37, 17, 1.2, 2, 1.5, [5, 3], "#2140BE", false, [[3.0725, 5.095], [3.0725, -5.095], [-3.0725, 5.095], [-3.0725, -5.095]],
[ [-12.05 , -6.8, 180, "trimpot10"]
]];
MT3608 = ["MT3608", "MT3608 boost converter module", 37, 17, 1.2, 2, 1.5, [5, 3], "#2140BE", false,
[[3.0725, 5.095], [3.0725, -5.095], [-3.0725, 5.095], [-3.0725, -5.095]],
[[-12.05 , -6.8, 180, "trimpot10"],
[-24.05 , 13.8, 90, "smd_soic", SOT23_6, "B628"],
[-12.3, -14.4, 0, "smd_diode",DO214AC, "SS34"],
[-28.5, 13.2, 90,"smd_cap", CAP1206, 0.5],
[-20, 13.2, 90,"smd_cap", CAP1206, 0.5],
[-24.05 , -11.8, 180, "smd_inductor", CDRH104, "220"]]
];
HW803_1WAY_RELAY = [
"HW803_1WAY_RELAY", "HW-803 5V 1 way relay module",
@@ -1196,6 +1202,28 @@ ESP_12F = pcb("ESP_12F", "ESP-12F ESP8266 WiFi module", [24, 16, 0.8],
]
);
RCWL0516 = pcb(
"RCWL-0516", "Microwave Radar Sensor",
size = [36, 17.3, 1.2],
colour = "#17682d",
hole_d = 1.7,
holes = [
[ inch(0.05), inch(0.05) ],
[ -inch(0.05), inch(0.05) ],
[ -inch(0.05), -inch(0.05) ],
[ inch(0.05), -inch(0.05) ],
[ -inch(0.65), -inch(0.05) ],
[ -inch(0.65), inch(0.05) ],
],
grid = [inch(0.05), inch(0.13), 1, 5, silver, inch(0.1), inch(0.1)],
components = [
[inch(0.18), inch(0.13), 90,"smd_cap", CAP1206, 0.5],
[inch(0.18), inch(0.32), 90,"smd_cap", CAP1206, 0.5],
[inch(0.18), inch(0.54), 90,"smd_cap", CAP1206, 0.5],
[inch(0.45), inch(0.34), 0,"smd_soic", SOIC16, "RCWL9196"],
]
);
tiny_buck = pcb("tiny_buck", "Ultra Small 3A buck regulator", [20, 11, 1.6],
hole_d = 1.2,
land_d = [2, 2],
@@ -1220,7 +1248,7 @@ tiny_pcbs = [ESP_201, ESP_01M, XIAO, ESP_12F, MP1584EN, ESP_01,tiny_buck, LIPO_f
big_pcbs = [BTT_RELAY_V1_2, BTT_SKR_MINI_E3_V2_0, BTT_SKR_E3_TURBO, BTT_SKR_V1_4_TURBO, DuetE, Duex5];
pcbs = [KY_040, TP4056, L9110S, ZC_A0591, MT3608, RAMPSEndstop, ArduinoNano, HW803_1WAY_RELAY, Feather405, RPI_Pico, ESP32_DOIT_V1, RPI0, EnviroPlus, ArduinoUno3, ArduinoLeonardo, WD2002SJ, OPZ2, PanelDue_v3, RPI3A, RPI3, RPI4];
pcbs = [KY_040, TP4056, L9110S, ZC_A0591, RCWL0516, MT3608,RAMPSEndstop, ArduinoNano, HW803_1WAY_RELAY, Feather405, RPI_Pico, ESP32_DOIT_V1, RPI0, EnviroPlus, ArduinoUno3, ArduinoLeonardo, WD2002SJ, OPZ2, PanelDue_v3, RPI3A, RPI3, RPI4];
pcbs_not_shown = [Melzi, Duex2, PSU12V1A, Keyes5p1, PI_IO, ExtruderPCB];

View File

@@ -35,8 +35,8 @@ neon_spades = [[spade4p8, 7.3, 0, -7, 0],
//
// w h t
//
small_rocker = ["small_rocker", "Rocker Switch PRASA1-16F-BB0BW", 13, 19.8, 15, 21, 2, 12.8, 18.5, 11.8, 2.5, -1, 3.8, small_spades];
neon_indicator = ["neon_indicator", "Neon Indicator H8630FBNAL", 13, 19.8, 15, 21, 2, 12.8, 18.5, 12.5, 2.5, 0, 0.3, neon_spades];
small_rocker = ["small_rocker", "Rocker Switch PRASA1-16F-BB0BW", 13, 19.25, 15, 21, 2, 12.8, 18.5, 11.8, 2.5, -1, 3.8, small_spades];
neon_indicator = ["neon_indicator", "Neon Indicator H8630FBNAL", 13, 19.25, 15, 21, 2, 12.8, 18.5, 12.5, 2.5, 0, 0.3, neon_spades];
rockers = [small_rocker, neon_indicator];

View File

@@ -44,6 +44,7 @@ DiBond = [ "DiBond", "Sheet DiBond", 3, [0.2, 0.2, 0.2, 1 ],
DiBond6 = [ "DiBond6", "Sheet DiBond", 6, [0.2, 0.2, 0.2, 1 ], false];
Cardboard = [ "Cardboard", "Corrugated cardboard", 5, [0.8, 0.6, 0.3, 1 ], false];
FoilTape = [ "FoilTape", "Aluminium foil tape", 0.05,[0.9, 0.9, 0.9, 1 ], false];
Sellotape = [ "Sellotape", "Sellotape tape", 0.05,[1, 1, 0.9, 0.5 ], false];
Foam20 = [ "Foam20", "Foam sponge", 20,[0.3, 0.3, 0.3, 1 ], true];
AL1_6 = [ "AL1_6", "Aluminium tooling plate", 1.6, [0.5, 0.5, 0.5, 0.5], false];
AL2 = [ "AL2", "Aluminium tooling plate", 2, [0.9, 0.9, 0.9, 1 ], false];
@@ -59,6 +60,6 @@ CF3 = [ "CF3", "Sheet carbon fiber", 3, grey(35),
sheets = [CF1, CF2, CF3, MDF3, MDF6, MDF10, MDF12, MDF19, MDF22, PMMA1p25, PMMA2, PMMA3, PMMA6, PMMA8, PMMA10,
glass2, DiBond, DiBond6, Cardboard, FoilTape, AL1_6, AL2, AL3, AL6, AL8, Steel06, Spring08, Silicone3, Foam20];
glass2, DiBond, DiBond6, Cardboard, FoilTape, Sellotape, AL1_6, AL2, AL3, AL6, AL8, Steel06, Spring08, Silicone3, Foam20];
use <sheet.scad>

View File

@@ -70,8 +70,9 @@ TANT_C = ["TANT_C", [5.8, 3.2, 2.6], 0.1, 1.3, [6.0, 2.2, 0.08, 2.9], ["#E9D769
smd_tants = [TANT_A, TANT_B, TANT_C];
IND2525 = ["IND2525", [6.75, 6.75, 2], 0.1, 1.75, [7.24, 3.2, 0.15, 4.4], grey(50)];
CDRH104 = ["CDRH104", [10.3, 10.3, 4.0], 0.1, 3.85, [10.5, 3.2, 0.15, 4.4], grey(50)];
smd_inductors = [IND2525];
smd_inductors = [IND2525, CDRH104];
TC33X1 = ["TC33X1", [3.0, 3.8, 0.5], [0.95, 0.9, 0.88, 1.5, 0.2, 0.75],[3.0, 0.1, 0.2, 1.2, 1.7, 1.2, 1, 0.5], [2.1, 0.5], 1.5];

View File

@@ -18,10 +18,11 @@
//
//
//! Tubing and sleeving. The internal diameter can be forced to stretch it over something.
//! Tubing and sleeving. The internal diameter can be forced to stretch it over something. A path can be specified, otherwise it is just straight with the specified length.
//
include <../utils/core/core.scad>
include <../utils/tube.scad>
include <../utils/sweep.scad>
function tubing_material(type) = type[1]; //! Material description
function tubing_od(type) = type[2]; //! Outside diameter
@@ -31,11 +32,12 @@ function tubing_colour(type) = type[4]; //! Colour
function tubing_or(type) = tubing_od(type) / 2; //! Outside radius
function tubing_ir(type) = tubing_id(type) / 2; //! Inside radius
module tubing(type, length = 15, forced_id = 0, center = true) { //! Draw specified tubing with optional forced internal diameter
module tubing(type, length = 15, forced_id = 0, center = true, path = []) { //! Draw specified tubing with optional forced internal diameter and optional path.
original_od = tubing_od(type);
original_id = tubing_id(type);
id = forced_id ? forced_id : original_id;
od = original_od + id - original_id;
length = path ? round(path_length(path)) : length;
if(tubing_material(type) == "Heatshrink sleeving")
vitamin(str("tubing(", type[0], arg(length, 15), "): ", tubing_material(type), " ID ", original_id, "mm x ",length, "mm"));
else
@@ -45,9 +47,19 @@ module tubing(type, length = 15, forced_id = 0, center = true) { //! Draw specif
woven_tube(od / 2, id /2, center = center, length, colour = tubing_colour(type));
else
color(tubing_colour(type))
linear_extrude(length, center = center, convexity = 4)
difference() {
circle(d = od);
circle(d = id);
}
if(path)
render_if(manifold)
difference() {
sweep(path, circle_points(od / 2));
start = path[0] - eps * unit(path[1] - path[0]);
n = len(path) - 1;
end = path[n] + eps * unit(path[n] - path[n - 1]);
sweep(concat([start], path, [end]), circle_points(id / 2));
}
else
linear_extrude(length, center = center, convexity = 4)
difference() {
circle(d = od);
circle(d = id);
}
}

View File

@@ -23,7 +23,7 @@
//! If a washer is given a child, usually a screw or a nut, then it is placed on its top surface.
//
include <../utils/core/core.scad>
include <../utils/sweep.scad>
use <../utils/sweep.scad>
soft_washer_colour = grey(20);
hard_washer_colour = grey(85);