diff --git a/printed/cable_clip.scad b/printed/cable_clip.scad index cdadf47..0fbadf2 100644 --- a/printed/cable_clip.scad +++ b/printed/cable_clip.scad @@ -18,100 +18,129 @@ // // -//! Cable clips to order. Can be for one or two cables of different sizes. +//! 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. // include <../core.scad> use <../vitamins/wire.scad> use <../utils/fillet.scad> +use <../vitamins/insert.scad> wall = 2; -function cable_clip_width(screw) = max(wall + 2 * screw_clearance_radius(screw) + wall, washer_diameter(screw_washer(screw))); //! Width given the `screw`. -function cable_clip_height(cable) = cable_height(cable) + wall; //! Height given the `cable`. -function cable_clip_extent(screw, cable) = screw_clearance_radius(screw) + wall + cable_width(cable) + wall; //! How far it extends from the screw. -function cable_clip_offset(screw, cable) = screw_clearance_radius(screw) + wall + cable_width(cable) / 2; //! The offset of the cable from the screw +function cable_clip_insert(screw, insert = true) = //! Insert type for clip, given screw. + is_list(insert) ? insert : insert ? screw_insert(screw, true) : false; -module single_cable_clip(screw, cable, h = 0) { - screw_dia = 2 * screw_clearance_radius(screw); - height = cable_clip_width(screw); - depth = h ? h : cable_height(cable) + wall; +function cable_clip_width(screw, insert = false) = //! Width given the `screw` and possibly insert. + 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))); + +function cable_clip_height(cable, screw = false, insert = false) = //! Height given the `cable`. + let(insert = cable_clip_insert(screw, insert)) + max(cable_height(cable) + wall, insert ? insert_hole_length(insert) + 1 : 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. + +module single_cable_clip(screw, cable, h = 0, insert = false) { + insert = cable_clip_insert(screw, insert); + height = cable_clip_width(screw, insert); + depth = h ? h : cable_clip_height(cable, screw, insert); w = cable_width(cable); - width = wall + w + wall + screw_dia + wall; - hole_x = wall + w + wall + screw_dia / 2; + width = wall + w + height; + hole_x = wall + w + height / 2; rad = min(wall + cable_wire_size(cable) / 2, depth / 2); r = extrusion_width - eps; - translate([-hole_x, 0]) difference() { - linear_extrude(height) - difference() { - hull() { - rounded_square([width, 1], r, center = false); - - translate([width - 1, 0]) - rounded_square([1, depth], r, center = false); - - translate([rad, depth - rad]) - circle(r = rad); - } - - translate([wall + cable_width(cable) / 2, 0]) { + translate([-hole_x, 0]) + difference() { + linear_extrude(height) + difference() { hull() { - for(p = cable_bundle_positions(cable)) - translate(p) - circle(d = cable_wire_size(cable)); + rounded_square([width, 1], r, center = false); - square([w, eps], center = true); + translate([width - 1, 0]) + rounded_square([1, depth], r, center = false); + + translate([rad, depth - rad]) + circle(r = rad); + } + + translate([wall + cable_width(cable) / 2, 0]) { + hull() { + for(p = cable_bundle_positions(cable)) + translate(p) + circle(d = cable_wire_size(cable)); + + square([w, eps], center = true); + } + for(side = [-1, 1]) + translate([side * w / 2, 0]) + hflip(side < 0) + fillet(r = r, h = 0); } - for(side = [-1, 1]) - translate([side * w / 2, 0]) - hflip(side < 0) - fillet(r = r, h = 0); } - } - translate([hole_x, depth / 2, height / 2]) - rotate([90,0,0]) - teardrop_plus(h = depth + 1, r = screw_dia / 2, center = true); - } + translate([hole_x, depth, height / 2]) + rotate([90, 0, 0]) + if(insert) + insert_hole(insert, 10, horizontal = true); + else + teardrop_plus(h = 2 * depth + 1, r = screw_clearance_radius(screw), center = true); + } } -module double_cable_clip(screw, cable1, cable2) { - h = max(cable_clip_height(cable1), cable_clip_height(cable2)); +module double_cable_clip(screw, cable1, cable2, insert = false) { + h = max(cable_clip_height(cable1, screw, insert), cable_clip_height(cable2, screw, insert)); union() { - single_cable_clip(screw, cable1, h); + single_cable_clip(screw, cable1, h, insert); - mirror([1,0,0]) single_cable_clip(screw, cable2, h); + mirror([1,0,0]) single_cable_clip(screw, cable2, h, insert); } } -module cable_clip(screw, cable1, cable2 = 0) { //! Create the STL for a single cable or two cable clip - function clip_str(screw) = str("cable_clip_", screw_radius(screw) * 20); +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" : ""); 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); + double_cable_clip(screw, cable1, cable2, insert); } else { stl(str(clip_str(screw), cable_str(cable1))); - single_cable_clip(screw, cable1); + single_cable_clip(screw, cable1, h = 0, insert = insert); } } -module cable_clip_assembly(screw, thickness, cable1, cable2 = 0) { //! Cable clip with the fasteners - height = max(cable_clip_height(cable1), cable2 ? cable_clip_height(cable2) : 0); +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 + insert = cable_clip_insert(screw, insert); + height = max(cable_clip_height(cable1, screw, insert), cable2 ? cable_clip_height(cable2, screw, insert) : 0); stl_colour(pp1_colour) render() - translate([0, cable_clip_width(screw) / 2]) rotate([90, 0, 0]) - cable_clip(screw, cable1, cable2); + translate([0, cable_clip_width(screw, insert) / 2]) + rotate([90, 0, 0]) + cable_clip(screw, cable1, cable2, insert); + nut = screw_nut(screw); + screw_len = screw_length(screw, height + thickness, 2, nyloc = !insert, insert = insert); translate_z(height) - screw_and_washer(screw, screw_length(screw, height + thickness, 2, nyloc = true)); + if(flip) + if(insert) + insert(insert); + else + nut_and_washer(nut, true); + else + screw_and_washer(screw, screw_len); translate_z(-thickness) vflip() - nut_and_washer(screw_nut(screw), true); + if(flip) + screw_and_washer(screw, screw_len, insert); + else + nut_and_washer(nut, true); } diff --git a/readme.md b/readme.md index 9888c3c..4a454b2 100644 --- a/readme.md +++ b/readme.md @@ -4968,6 +4968,7 @@ Utilities for adding wires to the BOM and optionally drawing them and cable bund | `cable_bundle_positions(cable)` | Positions of wires in a bundle to go through a cable strip | | `cable_height(cable)` | Height in flat clip | | `cable_is_ribbon(cable)` | Is a ribbon cable? | +| `cable_merge(cable1, cable2)` | Combine the wires of two cables | | `cable_radius(cable)` | Radius of a bundle of wires, see . | | `cable_tlen(cable)` | Twisted cable twist length | | `cable_twisted_radius(cable)` | Approximate radius of a cable when twisted | @@ -5271,7 +5272,7 @@ fixing_blocks along the sides. --- ## Cable_clip -Cable clips to order. Can be for one or two cables of different sizes. +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. [printed/cable_clip.scad](printed/cable_clip.scad) Implementation. @@ -5280,35 +5281,41 @@ Cable clips to order. Can be for one or two cables of different sizes. ### Functions | Function | Description | |:--- |:--- | -| `cable_clip_extent(screw, cable)` | How far it extends from the screw. | -| `cable_clip_height(cable)` | Height given the `cable`. | -| `cable_clip_offset(screw, cable)` | The offset of the cable from the screw | -| `cable_clip_width(screw)` | Width given the `screw`. | +| `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_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. | ### Modules | Module | Description | |:--- |:--- | -| `cable_clip(screw, cable1, cable2 = 0)` | Create the STL for a single cable or two cable clip | -| `cable_clip_assembly(screw, thickness, cable1, cable2 = 0)` | Cable clip with the fasteners | +| `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](tests/png/cable_clip.png) ### Vitamins | Qty | Module call | BOM entry | | ---:|:--- |:---| +| 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, 12)` | Screw M3 dome x 12mm | -| 3 | `screw(M3_dome_screw, 16)` | Screw M3 dome x 16mm | -| 10 | `washer(M3_washer)` | Washer M3 x 7mm x 0.5mm | +| 2 | `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 | +| 2 | `star_washer(M3_washer)` | Washer star M3 x 0.5mm | ### Printed | Qty | Filename | | ---:|:--- | -| 1 | cable_clip_30_10_13.stl | +| 1 | cable_clip_30I_10_13.stl | +| 1 | cable_clip_30I_5_14_6_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_5_14_6_14.stl | +| 1 | cable_clip_30_7_14_8_14.stl | +| 1 | cable_clip_30_9_14.stl | Top diff --git a/tests/cable_clip.scad b/tests/cable_clip.scad index 6b62bb4..3a403d6 100644 --- a/tests/cable_clip.scad +++ b/tests/cable_clip.scad @@ -25,20 +25,20 @@ use <../vitamins/wire.scad> sheet_thickness = 3; cables = [ - for(i = [1 : 6]) [i, 1.4], [1, 6], 0, [10, inch(0.05), true], 0 + [10, inch(0.05), true], 0, for(i = [1 : 9]) [i, 1.4], 0, [1, 6], 0, ]; screw = M3_dome_screw; module cable_clips() { - for(i = [0 : ceil(len(cables) / 2) - 1]) - translate([i * 25, 0]) { - cable1 = cables[2 * i]; - cable2 = cables[2 * i + 1]; - + 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); if($preview) { - cable_clip_assembly(screw, sheet_thickness, cable1, cable2); + cable_clip_assembly(screw, sheet_thickness, cable1, cable2, insert = insert, flip = i == 1); for(j = [0 : 1]) let(cable = cables[2 * i + j]) @@ -46,14 +46,15 @@ module cable_clips() { 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), 0, p.y]) + translate([p.x + [-1, 1][j] * cable_clip_offset(screw, cable, insert = insert), 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); } else - cable_clip(screw, cable1, cable2); + cable_clip(screw, cable1, cable2, insert = insert); } + } } cable_clips(); diff --git a/tests/png/cable_clip.png b/tests/png/cable_clip.png index 559cd3d..3484a0e 100644 Binary files a/tests/png/cable_clip.png and b/tests/png/cable_clip.png differ diff --git a/vitamins/wire.scad b/vitamins/wire.scad index ae1e000..a73f01d 100644 --- a/vitamins/wire.scad +++ b/vitamins/wire.scad @@ -44,23 +44,62 @@ function cable_is_ribbon(cable) = len(cable) > 2 && cable[2]; //! Is a ribbon ca function cable_wire_colours(cable) = assert(len(cable[3]) >= cable_wires(cable)) cable[3]; //! Individual wire colours function cable_tlen(cable) = cable[4]; //! Twisted cable twist length function cable(wires, size, colours, ribbon = false, tlen = 25) = [wires, size, ribbon, colours, tlen]; //! Cable constructor +function cable_merge(cable1, cable2) = //! Combine the wires of two cables + assert(cable_wire_size(cable1) == cable_wire_size(cable2)) + assert(cable_is_ribbon(cable1) == cable_is_ribbon(cable2)) + cable(cable_wires(cable1) + cable_wires(cable2), + cable_wire_size(cable1), + concat(cable_wire_colours(cable1), cable_wire_colours(cable1)), + cable_is_ribbon(cable1)); -// numbers from http://mathworld.wolfram.com/CirclePacking.html -function cable_radius(cable) = [0, 1, 2, 2.15, 2.41, 2.7, 3, 3, 3.3][cable_wires(cable)] * cable_wire_size(cable) / 2; //! Radius of a bundle of wires, see . +// numbers from https://en.wikipedia.org/wiki/Circle_packing_in_a_circle +function cable_radius(cable) = [ //! Radius of a bundle of wires, see . + 0, 1, 2, + 2.154, // 3 + 2.414, // 4 + 2.701, // 5 + 3, // 6 + 3, // 7 + 3.304, // 8 + 3.613, // 9 + 3.813, // 10 + 3.923, // 11 + 4.029, // 12 + 4.236, // 13 + 4.328, // 14 + 4.521, // 15 + 4.615, // 16 + 4.792, // 17 + 4.863, // 18 + 4.863, // 19 + 5.122, // 20 + ][cable_wires(cable)] * cable_wire_size(cable) / 2; function wire_hole_radius(cable) = ceil(4 * cable_radius(cable) + 1) / 4; //! Radius of a hole to accept a bundle of wires, rounded up to standard metric drill size function cable_bundle(cable) = //! Dimensions of the bounding rectangle of a bundle of wires in a flat cable clip (cable_is_ribbon(cable) ? [cable_wires(cable), 1] : - [[0,0], [1,1], [2,1], [2, 1 + sin(60)], [2,2], [3, 1 + sin(60)], [3,2]][cable_wires(cable)]) * cable_wire_size(cable); + [[0, 0], // 0 + [1, 1], // 1 + [2, 1], // 2 + [2, 1 + sin(60)], // 3 + [2, 2], // 4 + [3, 1 + sin(60)], // 5 + [3, 2], // 6 + [4, 1 + sin(60)], // 7 + [3, 2 + sin(60)], // 8 + [3, 3] + ][cable_wires(cable)]) * cable_wire_size(cable); function cable_bundle_positions(cable) = let( //! Positions of wires in a bundle to go through a cable strip wires = cable_wires(cable), - bottom = cable_is_ribbon(cable) ? wires : wires < 3 ? wires : ceil(wires / 2), - top = wires - bottom + bottom = cable_is_ribbon(cable) ? wires : wires < 3 ? wires : wires <= 7 ? ceil(wires / 2) : min(wires, 3), + middle = min(wires - bottom, 3), + top = wires - bottom - middle ) - [for(i = [0 : 1 : bottom - 1]) [i - (bottom - 1) / 2, 0.5], - for(i = [top - 1 : -1 : 0]) [i - (top - 1) / 2, top == bottom ? 1.5 : 0.5 + sin(60)] + [for(i = [0 : 1 : bottom - 1]) [i - (bottom - 1) / 2, 0.5], + for(i = [middle - 1 : -1 : 0]) [i - (middle - 1) / 2, middle == bottom ? 1.5 : 0.5 + sin(60)], + for(i = [0 : 1 : top - 1]) [i - [0.5, 0.5, 1][top - 1], top == middle ? 2.5 : 1.5 + sin(60)] ] * cable_wire_size(cable); function cable_width(cable) = cable_bundle(cable).x; //! Width in flat clip