Compare commits
73 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
520569cb30 | ||
|
f73a7b46a2 | ||
|
fb9eca85c6 | ||
|
ce6aec428d | ||
|
4e9d169c31 | ||
|
1810160103 | ||
|
0c9ae8d60c | ||
|
9a0bad4e61 | ||
|
90047815b0 | ||
|
eac0086199 | ||
|
51c649cc53 | ||
|
5fa33d7c4d | ||
|
78ce51d045 | ||
|
23cbadf6df | ||
|
c9c2ffafba | ||
|
2e0e833d40 | ||
|
6c51f8726c | ||
|
0b035dbd15 | ||
|
34b58e3b64 | ||
|
df43fe7dc6 | ||
|
b5fe03fcb2 | ||
|
1658f6f0b4 | ||
|
7b126f9792 | ||
|
479207fd4f | ||
|
3ee55981f9 | ||
|
8c2b4a20fe | ||
|
1529759406 | ||
|
c4a986aa21 | ||
|
ebee729d08 | ||
|
90e7f1a315 | ||
|
e39af154bb | ||
|
933fea687c | ||
|
a7803b1efb | ||
|
1255e71271 | ||
|
b11c5914b3 | ||
|
ac60057801 | ||
|
332933a4fd | ||
|
6b0132c32e | ||
|
afac5f9737 | ||
|
8d8df3cb8a | ||
|
81eb183db9 | ||
|
c99ed98a64 | ||
|
7f65e5d539 | ||
|
ffb7f87cc5 | ||
|
d0513c7299 | ||
|
d1429a3b7d | ||
|
70513993bd | ||
|
9eb35accfd | ||
|
7276f18566 | ||
|
d944198dc4 | ||
|
04f2499a9e | ||
|
1eb8b378e9 | ||
|
362dbdb4fc | ||
|
57d223d84b | ||
|
699385342f | ||
|
547a418cea | ||
|
b6d25048bc | ||
|
4cdab218d9 | ||
|
b6147e5684 | ||
|
966ba536ed | ||
|
2419d50641 | ||
|
02211c2034 | ||
|
77d73b075d | ||
|
cb54a3131b | ||
|
3cf275579c | ||
|
fb41f218fe | ||
|
e6a26bc7b1 | ||
|
cb4fa40643 | ||
|
6a26903514 | ||
|
d08d949887 | ||
|
574a73e527 | ||
|
87a35126de | ||
|
1ca485b66b |
@@ -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>
|
||||
//
|
||||
|
@@ -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
|
||||
|
1
lib.scad
@@ -43,6 +43,7 @@ include <vitamins/ldrs.scad>
|
||||
include <vitamins/leadnuts.scad>
|
||||
include <vitamins/led_meter.scad>
|
||||
include <vitamins/light_strips.scad>
|
||||
include <vitamins/magnets.scad>
|
||||
include <vitamins/mains_sockets.scad>
|
||||
include <vitamins/modules.scad>
|
||||
include <vitamins/panel_meters.scad>
|
||||
|
BIN
libtest.png
Before Width: | Height: | Size: 813 KiB After Width: | Height: | Size: 819 KiB |
36
libtest.scad
@@ -17,6 +17,23 @@
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
//!# NopSCADlib
|
||||
//! An ever expanding library of parts modelled in OpenSCAD useful for 3D printers and enclosures for electronics, etc.
|
||||
//!
|
||||
//! It contains lots of vitamins (the RepRap term for non-printed parts), some general purpose printed parts and some utilities.
|
||||
//! There are also Python scripts to generate Bills of Materials (BOMs),
|
||||
//! STL files for all the printed parts, DXF files for CNC routed parts in a project and a manual containing assembly
|
||||
//! instructions and exploded views by scraping markdown embedded in OpenSCAD comments, [see scripts](scripts/readme.md).
|
||||
//!
|
||||
//! A simple example project can be found [here](examples/MainsBreakOutBox/readme.md).
|
||||
//!
|
||||
//! For more examples of what it can make see the [gallery](gallery/readme.md).
|
||||
//!
|
||||
//! The license is GNU General Public License v3.0, see [COPYING](COPYING).
|
||||
//!
|
||||
//! See [usage](docs/usage.md) for requirements, installation instructions and a usage guide.
|
||||
//!
|
||||
//! <img src="libtest.png" width="100%"/>
|
||||
//
|
||||
// This file shows all the parts in the library.
|
||||
//
|
||||
@@ -50,6 +67,7 @@ use <tests/LEDs.scad>
|
||||
use <tests/light_strips.scad>
|
||||
use <tests/linear_bearings.scad>
|
||||
use <tests/LED_meters.scad>
|
||||
use <tests/magnets.scad>
|
||||
use <tests/microswitches.scad>
|
||||
use <tests/modules.scad>
|
||||
use <tests/nuts.scad>
|
||||
@@ -116,17 +134,17 @@ cable_grommets_y = 0;
|
||||
translate([x5, cable_grommets_y])
|
||||
cable_grommets();
|
||||
|
||||
translate([x5, cable_grommets_y + 50])
|
||||
feet();
|
||||
translate([x5 + 80, cable_grommets_y])
|
||||
ribbon_clamps();
|
||||
|
||||
translate([x5, cable_grommets_y + 75])
|
||||
translate([x5, cable_grommets_y + 60])
|
||||
fixing_blocks();
|
||||
|
||||
translate([x5, cable_grommets_y + 100])
|
||||
translate([x5, cable_grommets_y + 90])
|
||||
corner_blocks();
|
||||
|
||||
translate([x5, cable_grommets_y + 150])
|
||||
ribbon_clamps();
|
||||
feet();
|
||||
|
||||
translate([x5 + 70, cable_grommets_y + 150])
|
||||
screw_knobs();
|
||||
@@ -271,8 +289,9 @@ translate([x1, leadnuts_y])
|
||||
|
||||
leds_y = 0;
|
||||
carriers_y = leds_y + 40;
|
||||
spades_y = carriers_y + 40;
|
||||
buttons_y = spades_y + 40;
|
||||
magnets_y = carriers_y + 40;
|
||||
spades_y = magnets_y + 20;
|
||||
buttons_y = spades_y + 20;
|
||||
jacks_y = buttons_y + 40;
|
||||
microswitches_y = jacks_y + 40;
|
||||
rockers_y = microswitches_y + 40;
|
||||
@@ -288,6 +307,9 @@ translate([x2 + 35, leds_y])
|
||||
translate([x2 + 8, carriers_y])
|
||||
carriers();
|
||||
|
||||
translate([x2, magnets_y])
|
||||
magnets();
|
||||
|
||||
translate([x2 + 20, carriers_y])
|
||||
led_meters();
|
||||
|
||||
|
@@ -74,7 +74,7 @@ module door_hinge(door_thickness) { //! Generates STL fo
|
||||
square([1, thickness + door_thickness]);
|
||||
}
|
||||
translate([dia / 2, thickness + door_thickness / 2])
|
||||
teardrop(r = screw_clearance_radius(pin_screw), h = 0);
|
||||
teardrop_plus(r = screw_clearance_radius(pin_screw), h = 0);
|
||||
}
|
||||
linear_extrude(thickness)
|
||||
difference() {
|
||||
@@ -127,7 +127,7 @@ module door_hinge_stat_stl() { //! Generates the STL for the stationary part
|
||||
square([dia, 1], center = true);
|
||||
}
|
||||
translate([0, dia / 2 + stat_clearance])
|
||||
teardrop(r = screw_clearance_radius(pin_screw), h = 0);
|
||||
teardrop_plus(r = screw_clearance_radius(pin_screw), h = 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -24,69 +24,72 @@ include <../core.scad>
|
||||
use <../vitamins/insert.scad>
|
||||
use <../vitamins/cable_strip.scad>
|
||||
|
||||
wall = 2;
|
||||
wall = 1.6;
|
||||
min_wall = 2 * extrusion_width;
|
||||
screw = M3_cap_screw;
|
||||
insert = screw_insert(screw);
|
||||
screw_depth = insert_length(insert) + 1;
|
||||
|
||||
function ribbon_clamp_hole_pitch(ways) = ribbon_clamp_slot(ways) + 2 * min_wall + 2 * corrected_radius(insert_hole_radius(insert)); //! Hole pitch
|
||||
function ribbon_clamp_width() = 2 * (insert_hole_radius(insert) + wall); //! Width
|
||||
function ribbon_clamp_length(ways) = ribbon_clamp_hole_pitch(ways) + ribbon_clamp_width(); //! Length given ways
|
||||
function ribbon_clamp_height() = screw_depth + 1; //! Height
|
||||
function ribbon_clamp_screw_depth(screw = screw) = insert_length(screw_insert(screw)) + 1;
|
||||
function ribbon_clamp_hole_pitch(ways, screw = screw) =
|
||||
ribbon_clamp_slot(ways) + 2 * min_wall + 2 * corrected_radius(insert_hole_radius(screw_insert(screw))); //! Hole pitch
|
||||
|
||||
module ribbon_clamp_hole_positions(ways, side = undef) //! Place children at hole positions
|
||||
function ribbon_clamp_width(screw = screw) = 2 * (insert_hole_radius(screw_insert(screw)) + wall); //! Width
|
||||
function ribbon_clamp_length(ways, screw = screw) = ribbon_clamp_hole_pitch(ways, screw) + ribbon_clamp_width(screw); //! Length given ways
|
||||
function ribbon_clamp_height(screw = screw) = ribbon_clamp_screw_depth(screw) + 1; //! Height
|
||||
|
||||
module ribbon_clamp_hole_positions(ways, screw = screw, side = undef) //! Place children at hole positions
|
||||
for(x = is_undef(side) ? [-1, 1] : side)
|
||||
translate([x * ribbon_clamp_hole_pitch(ways) / 2, 0])
|
||||
translate([x * ribbon_clamp_hole_pitch(ways, screw) / 2, 0])
|
||||
children();
|
||||
|
||||
module ribbon_clamp_holes(ways, h = 20) //! Drill screw holes
|
||||
ribbon_clamp_hole_positions(ways)
|
||||
module ribbon_clamp_holes(ways, h = 20, screw = screw) //! Drill screw holes
|
||||
ribbon_clamp_hole_positions(ways, screw)
|
||||
drill(screw_clearance_radius(screw), h);
|
||||
|
||||
module ribbon_clamp(ways) { //! Generate STL for given number of ways
|
||||
stl(str("ribbon_clamp_", ways));
|
||||
module ribbon_clamp(ways, screw = screw) { //! Generate STL for given number of ways
|
||||
screw_d = screw_radius(screw) * 2;
|
||||
stl(str("ribbon_clamp_", ways, screw_d != 3 ? str("_", screw_d) : ""));
|
||||
|
||||
pitch = ribbon_clamp_hole_pitch(ways);
|
||||
d = ribbon_clamp_width();
|
||||
h = ribbon_clamp_height();
|
||||
t = h - ribbon_clamp_slot_depth() - wall;
|
||||
pitch = ribbon_clamp_hole_pitch(ways, screw);
|
||||
d = ribbon_clamp_width(screw);
|
||||
h = ribbon_clamp_height(screw);
|
||||
t = round_to_layer(ribbon_clamp_slot_depth() + wall);
|
||||
insert = screw_insert(screw);
|
||||
|
||||
difference() {
|
||||
union() {
|
||||
hull() {
|
||||
translate_z(h - t / 2)
|
||||
cube([ribbon_clamp_hole_pitch(ways), d, t], center = true);
|
||||
cube([ribbon_clamp_hole_pitch(ways, screw), d, t], center = true);
|
||||
|
||||
translate_z(1)
|
||||
cube([pitch, max(wall, d - 2 * (h - t)), 2], center = true);
|
||||
}
|
||||
ribbon_clamp_hole_positions(ways, -1)
|
||||
ribbon_clamp_hole_positions(ways, screw, -1)
|
||||
cylinder(d = d, h = h);
|
||||
|
||||
ribbon_clamp_hole_positions(ways, 1)
|
||||
ribbon_clamp_hole_positions(ways, screw, 1)
|
||||
cylinder(d = d, h = h);
|
||||
|
||||
}
|
||||
|
||||
translate_z(h)
|
||||
cube([ribbon_clamp_slot(ways), d + 1, ribbon_clamp_slot_depth() * 2], center = true);
|
||||
|
||||
ribbon_clamp_hole_positions(ways)
|
||||
ribbon_clamp_hole_positions(ways, screw)
|
||||
translate_z(h)
|
||||
rotate(22.5)
|
||||
insert_hole(insert, screw_depth - insert_length(insert));
|
||||
insert_hole(insert, ribbon_clamp_screw_depth(screw) - insert_length(insert));
|
||||
}
|
||||
}
|
||||
|
||||
module ribbon_clamp_assembly(ways) pose([55, 180, 25]) //! Printed part with inserts in place
|
||||
assembly(str("ribbon_clamp_", ways)) {
|
||||
h = ribbon_clamp_height();
|
||||
module ribbon_clamp_assembly(ways, screw) pose([55, 180, 25]) //! Printed part with inserts in place
|
||||
assembly(let(screw_d = screw_radius(screw) * 2)str("ribbon_clamp_", ways, screw_d != 3 ? str("_", screw_d) : "")) {
|
||||
h = ribbon_clamp_height(screw);
|
||||
insert = screw_insert(screw);
|
||||
|
||||
stl_colour(pp1_colour) render()
|
||||
translate_z(h) vflip() ribbon_clamp(ways);
|
||||
translate_z(h) vflip() ribbon_clamp(ways, screw);
|
||||
|
||||
ribbon_clamp_hole_positions(ways)
|
||||
ribbon_clamp_hole_positions(ways, screw)
|
||||
vflip()
|
||||
insert(insert);
|
||||
}
|
||||
@@ -99,20 +102,24 @@ module ribbon_clamp_fastened_assembly(ways, thickness, screw = screw) { //! Clam
|
||||
vitamin(str(": Tape self amalgamating silicone ",tape_l," x 25mm"));
|
||||
|
||||
washer = screw_washer(screw);
|
||||
screw_length = screw_shorter_than(2 * washer_thickness(washer) + thickness + screw_depth);
|
||||
screw_length = screw_shorter_than(2 * washer_thickness(washer) + thickness + ribbon_clamp_screw_depth(screw));
|
||||
|
||||
ribbon_clamp_assembly(ways);
|
||||
ribbon_clamp_assembly(ways, screw);
|
||||
|
||||
color("red") translate_z(tape_thickness / 2)
|
||||
cube([tape_l, tape_width, tape_thickness], center = true);
|
||||
|
||||
ribbon_clamp_hole_positions(ways)
|
||||
ribbon_clamp_hole_positions(ways, screw)
|
||||
vflip()
|
||||
translate_z(thickness)
|
||||
screw_and_washer(screw, screw_length, true);
|
||||
}
|
||||
|
||||
module ribbon_clamp_20_stl() ribbon_clamp(20);
|
||||
module ribbon_clamp_8_2_stl() ribbon_clamp(8, M2_dome_screw);
|
||||
|
||||
//! * Place inserts into the holes and press home with a soldering iron with a conical bit heated to 200°C.
|
||||
module ribbon_clamp_20_assembly() ribbon_clamp_assembly(20);
|
||||
|
||||
//! * Place inserts into the holes and press home with a soldering iron with a conical bit heated to 200°C.
|
||||
module ribbon_clamp_8_2_assembly() ribbon_clamp_assembly(8, M2_dome_screw);
|
||||
|
311
readme.md
@@ -1,10 +1,12 @@
|
||||
# NopSCADlib
|
||||
An ever expanding library of parts modelled in OpenSCAD useful for 3D printers and enclosures for electronics, etc.
|
||||
|
||||
It contains lots of vitamins (the RepRap term for non-printed parts), some general purpose printed parts and
|
||||
some utilities. There are also Python scripts to generate Bills of Materials (BOMs),
|
||||
STL files for all the printed parts, DXF files for CNC routed parts in a project and a manual containing assembly
|
||||
instructions and exploded views by scraping markdown embedded in OpenSCAD comments, [see scripts](scripts/readme.md). A simple example project can be found [here](examples/MainsBreakOutBox/readme.md).
|
||||
It contains lots of vitamins (the RepRap term for non-printed parts), some general purpose printed parts and some utilities.
|
||||
There are also Python scripts to generate Bills of Materials (BOMs),
|
||||
STL files for all the printed parts, DXF files for CNC routed parts in a project and a manual containing assembly
|
||||
instructions and exploded views by scraping markdown embedded in OpenSCAD comments, [see scripts](scripts/readme.md).
|
||||
|
||||
A simple example project can be found [here](examples/MainsBreakOutBox/readme.md).
|
||||
|
||||
For more examples of what it can make see the [gallery](gallery/readme.md).
|
||||
|
||||
@@ -20,27 +22,27 @@ See [usage](docs/usage.md) for requirements, installation instructions and a usa
|
||||
<th align="left"> Vitamins A-I </th><th align="left"> Vitamins J-Q </th><th align="left"> Vitamins R-Z </th><th align="left"> Printed </th><th align="left"> Utilities </th><th align="left"> Core Utilities </th></tr>
|
||||
<tr><td> <a href = "#Axials">Axials</a> </td><td> <a href = "#Jack">Jack</a> </td><td> <a href = "#Rails">Rails</a> </td><td> <a href = "#Box">Box</a> </td><td> <a href = "#Annotation">Annotation</a> </td><td> <a href = "#BOM">BOM</a> </td></tr>
|
||||
<tr><td> <a href = "#Ball_bearings">Ball_bearings</a> </td><td> <a href = "#KP_pillow_blocks">KP_pillow_blocks</a> </td><td> <a href = "#Ring_terminals">Ring_terminals</a> </td><td> <a href = "#Butt_box">Butt_box</a> </td><td> <a href = "#Bezier">Bezier</a> </td><td> <a href = "#Clip">Clip</a> </td></tr>
|
||||
<tr><td> <a href = "#Batteries">Batteries</a> </td><td> <a href = "#LDRs">LDRs</a> </td><td> <a href = "#Rockers">Rockers</a> </td><td> <a href = "#Cable_grommets">Cable_grommets</a> </td><td> <a href = "#Dogbones">Dogbones</a> </td><td> <a href = "#Global">Global</a> </td></tr>
|
||||
<tr><td> <a href = "#Belts">Belts</a> </td><td> <a href = "#LED_meters">LED_meters</a> </td><td> <a href = "#Rod">Rod</a> </td><td> <a href = "#Carriers">Carriers</a> </td><td> <a href = "#Fillet">Fillet</a> </td><td> <a href = "#Polyholes">Polyholes</a> </td></tr>
|
||||
<tr><td> <a href = "#Blowers">Blowers</a> </td><td> <a href = "#LEDs">LEDs</a> </td><td> <a href = "#SCS_bearing_blocks">SCS_bearing_blocks</a> </td><td> <a href = "#Corner_block">Corner_block</a> </td><td> <a href = "#Gears">Gears</a> </td><td> <a href = "#Rounded_rectangle">Rounded_rectangle</a> </td></tr>
|
||||
<tr><td> <a href = "#Bulldogs">Bulldogs</a> </td><td> <a href = "#Leadnuts">Leadnuts</a> </td><td> <a href = "#SK_brackets">SK_brackets</a> </td><td> <a href = "#Door_hinge">Door_hinge</a> </td><td> <a href = "#Hanging_hole">Hanging_hole</a> </td><td> <a href = "#Sphere">Sphere</a> </td></tr>
|
||||
<tr><td> <a href = "#Buttons">Buttons</a> </td><td> <a href = "#Light_strips">Light_strips</a> </td><td> <a href = "#SMDs">SMDs</a> </td><td> <a href = "#Door_latch">Door_latch</a> </td><td> <a href = "#Layout">Layout</a> </td><td> <a href = "#Teardrops">Teardrops</a> </td></tr>
|
||||
<tr><td> <a href = "#Cable_strips">Cable_strips</a> </td><td> <a href = "#Linear_bearings">Linear_bearings</a> </td><td> <a href = "#SSRs">SSRs</a> </td><td> <a href = "#Fan_guard">Fan_guard</a> </td><td> <a href = "#Maths">Maths</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Cameras">Cameras</a> </td><td> <a href = "#Mains_sockets">Mains_sockets</a> </td><td> <a href = "#Screws">Screws</a> </td><td> <a href = "#Fixing_block">Fixing_block</a> </td><td> <a href = "#Offset">Offset</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Circlips">Circlips</a> </td><td> <a href = "#Microswitches">Microswitches</a> </td><td> <a href = "#Sealing_strip">Sealing_strip</a> </td><td> <a href = "#Flat_hinge">Flat_hinge</a> </td><td> <a href = "#Quadrant">Quadrant</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Components">Components</a> </td><td> <a href = "#Microview">Microview</a> </td><td> <a href = "#Sheets">Sheets</a> </td><td> <a href = "#Foot">Foot</a> </td><td> <a href = "#Round">Round</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#DIP">DIP</a> </td><td> <a href = "#Modules">Modules</a> </td><td> <a href = "#Spades">Spades</a> </td><td> <a href = "#Handle">Handle</a> </td><td> <a href = "#Rounded_cylinder">Rounded_cylinder</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#D_connectors">D_connectors</a> </td><td> <a href = "#Nuts">Nuts</a> </td><td> <a href = "#Spools">Spools</a> </td><td> <a href = "#PCB_mount">PCB_mount</a> </td><td> <a href = "#Rounded_polygon">Rounded_polygon</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Displays">Displays</a> </td><td> <a href = "#O_ring">O_ring</a> </td><td> <a href = "#Springs">Springs</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 = "#Opengrab">Opengrab</a> </td><td> <a href = "#Stepper_motors">Stepper_motors</a> </td><td> <a href = "#Printed_box">Printed_box</a> </td><td> <a href = "#Sweep">Sweep</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Extrusions">Extrusions</a> </td><td> <a href = "#PCB">PCB</a> </td><td> <a href = "#Swiss_clips">Swiss_clips</a> </td><td> <a href = "#Ribbon_clamp">Ribbon_clamp</a> </td><td> <a href = "#Thread">Thread</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Fans">Fans</a> </td><td> <a href = "#PCBs">PCBs</a> </td><td> <a href = "#Toggles">Toggles</a> </td><td> <a href = "#SSR_shroud">SSR_shroud</a> </td><td> <a href = "#Tube">Tube</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Fuseholder">Fuseholder</a> </td><td> <a href = "#PSUs">PSUs</a> </td><td> <a href = "#Transformers">Transformers</a> </td><td> <a href = "#Screw_knob">Screw_knob</a> </td><td></td><td></td></tr>
|
||||
<tr><td> <a href = "#Geared_steppers">Geared_steppers</a> </td><td> <a href = "#Panel_meters">Panel_meters</a> </td><td> <a href = "#Tubings">Tubings</a> </td><td> <a href = "#Socket_box">Socket_box</a> </td><td></td><td></td></tr>
|
||||
<tr><td> <a href = "#Green_terminals">Green_terminals</a> </td><td> <a href = "#Pillars">Pillars</a> </td><td> <a href = "#Variacs">Variacs</a> </td><td> <a href = "#Strap_handle">Strap_handle</a> </td><td></td><td></td></tr>
|
||||
<tr><td> <a href = "#Hot_ends">Hot_ends</a> </td><td> <a href = "#Pin_headers">Pin_headers</a> </td><td> <a href = "#Veroboard">Veroboard</a> </td><td></td><td></td><td></td></tr>
|
||||
<tr><td> <a href = "#Hygrometer">Hygrometer</a> </td><td> <a href = "#Pulleys">Pulleys</a> </td><td> <a href = "#Washers">Washers</a> </td><td></td><td></td><td></td></tr>
|
||||
<tr><td> <a href = "#IECs">IECs</a> </td><td></td><td> <a href = "#Wire">Wire</a> </td><td></td><td></td><td></td></tr>
|
||||
<tr><td> <a href = "#Batteries">Batteries</a> </td><td> <a href = "#LDRs">LDRs</a> </td><td> <a href = "#Rockers">Rockers</a> </td><td> <a href = "#Cable_grommets">Cable_grommets</a> </td><td> <a href = "#Catenary">Catenary</a> </td><td> <a href = "#Global">Global</a> </td></tr>
|
||||
<tr><td> <a href = "#Belts">Belts</a> </td><td> <a href = "#LED_meters">LED_meters</a> </td><td> <a href = "#Rod">Rod</a> </td><td> <a href = "#Carriers">Carriers</a> </td><td> <a href = "#Dogbones">Dogbones</a> </td><td> <a href = "#Polyholes">Polyholes</a> </td></tr>
|
||||
<tr><td> <a href = "#Blowers">Blowers</a> </td><td> <a href = "#LEDs">LEDs</a> </td><td> <a href = "#SCS_bearing_blocks">SCS_bearing_blocks</a> </td><td> <a href = "#Corner_block">Corner_block</a> </td><td> <a href = "#Fillet">Fillet</a> </td><td> <a href = "#Rounded_rectangle">Rounded_rectangle</a> </td></tr>
|
||||
<tr><td> <a href = "#Bulldogs">Bulldogs</a> </td><td> <a href = "#Leadnuts">Leadnuts</a> </td><td> <a href = "#SK_brackets">SK_brackets</a> </td><td> <a href = "#Door_hinge">Door_hinge</a> </td><td> <a href = "#Gears">Gears</a> </td><td> <a href = "#Sphere">Sphere</a> </td></tr>
|
||||
<tr><td> <a href = "#Buttons">Buttons</a> </td><td> <a href = "#Light_strips">Light_strips</a> </td><td> <a href = "#SMDs">SMDs</a> </td><td> <a href = "#Door_latch">Door_latch</a> </td><td> <a href = "#Hanging_hole">Hanging_hole</a> </td><td> <a href = "#Teardrops">Teardrops</a> </td></tr>
|
||||
<tr><td> <a href = "#Cable_strips">Cable_strips</a> </td><td> <a href = "#Linear_bearings">Linear_bearings</a> </td><td> <a href = "#SSRs">SSRs</a> </td><td> <a href = "#Fan_guard">Fan_guard</a> </td><td> <a href = "#Horiholes">Horiholes</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Cameras">Cameras</a> </td><td> <a href = "#Magnets">Magnets</a> </td><td> <a href = "#Screws">Screws</a> </td><td> <a href = "#Fixing_block">Fixing_block</a> </td><td> <a href = "#Layout">Layout</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Circlips">Circlips</a> </td><td> <a href = "#Mains_sockets">Mains_sockets</a> </td><td> <a href = "#Sealing_strip">Sealing_strip</a> </td><td> <a href = "#Flat_hinge">Flat_hinge</a> </td><td> <a href = "#Maths">Maths</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Components">Components</a> </td><td> <a href = "#Microswitches">Microswitches</a> </td><td> <a href = "#Sheets">Sheets</a> </td><td> <a href = "#Foot">Foot</a> </td><td> <a href = "#Offset">Offset</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#DIP">DIP</a> </td><td> <a href = "#Microview">Microview</a> </td><td> <a href = "#Spades">Spades</a> </td><td> <a href = "#Handle">Handle</a> </td><td> <a href = "#Quadrant">Quadrant</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#D_connectors">D_connectors</a> </td><td> <a href = "#Modules">Modules</a> </td><td> <a href = "#Spools">Spools</a> </td><td> <a href = "#PCB_mount">PCB_mount</a> </td><td> <a href = "#Round">Round</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Displays">Displays</a> </td><td> <a href = "#Nuts">Nuts</a> </td><td> <a href = "#Springs">Springs</a> </td><td> <a href = "#PSU_shroud">PSU_shroud</a> </td><td> <a href = "#Rounded_cylinder">Rounded_cylinder</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Extrusion_brackets">Extrusion_brackets</a> </td><td> <a href = "#O_ring">O_ring</a> </td><td> <a href = "#Stepper_motors">Stepper_motors</a> </td><td> <a href = "#Printed_box">Printed_box</a> </td><td> <a href = "#Rounded_polygon">Rounded_polygon</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Extrusions">Extrusions</a> </td><td> <a href = "#Opengrab">Opengrab</a> </td><td> <a href = "#Swiss_clips">Swiss_clips</a> </td><td> <a href = "#Ribbon_clamp">Ribbon_clamp</a> </td><td> <a href = "#Sector">Sector</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Fans">Fans</a> </td><td> <a href = "#PCB">PCB</a> </td><td> <a href = "#Toggles">Toggles</a> </td><td> <a href = "#SSR_shroud">SSR_shroud</a> </td><td> <a href = "#Sweep">Sweep</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Fuseholder">Fuseholder</a> </td><td> <a href = "#PCBs">PCBs</a> </td><td> <a href = "#Transformers">Transformers</a> </td><td> <a href = "#Screw_knob">Screw_knob</a> </td><td> <a href = "#Thread">Thread</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Geared_steppers">Geared_steppers</a> </td><td> <a href = "#PSUs">PSUs</a> </td><td> <a href = "#Tubings">Tubings</a> </td><td> <a href = "#Socket_box">Socket_box</a> </td><td> <a href = "#Tube">Tube</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Green_terminals">Green_terminals</a> </td><td> <a href = "#Panel_meters">Panel_meters</a> </td><td> <a href = "#Variacs">Variacs</a> </td><td> <a href = "#Strap_handle">Strap_handle</a> </td><td></td><td></td></tr>
|
||||
<tr><td> <a href = "#Hot_ends">Hot_ends</a> </td><td> <a href = "#Pillars">Pillars</a> </td><td> <a href = "#Veroboard">Veroboard</a> </td><td></td><td></td><td></td></tr>
|
||||
<tr><td> <a href = "#Hygrometer">Hygrometer</a> </td><td> <a href = "#Pin_headers">Pin_headers</a> </td><td> <a href = "#Washers">Washers</a> </td><td></td><td></td><td></td></tr>
|
||||
<tr><td> <a href = "#IECs">IECs</a> </td><td> <a href = "#Pulleys">Pulleys</a> </td><td> <a href = "#Wire">Wire</a> </td><td></td><td></td><td></td></tr>
|
||||
<tr><td> <a href = "#Inserts">Inserts</a> </td><td></td><td> <a href = "#Zipties">Zipties</a> </td><td></td><td></td><td></td></tr>
|
||||
</table>
|
||||
|
||||
@@ -85,6 +87,7 @@ Axial components for PCBs.
|
||||
| 1 | ```ax_res(res1_4, 47000)``` | Resistor 47000 Ohms 5% 0.25W |
|
||||
| 1 | ```ax_res(res1_2, 8200)``` | Resistor 8200 Ohms 5% 0.5W |
|
||||
| 1 | ```ax_res(res1_2, 8250, tol = 1)``` | Resistor 8250 Ohms 1% 0.5W |
|
||||
| 1 | ```wire_link(0.8, 10.16)``` | Wire link 0.8mm x 0.4" |
|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
@@ -209,6 +212,7 @@ Only models 2D paths, so not core XY!
|
||||
To make the back of the belt run against a smooth pulley on the outside of the loop specify a negative pitch radius.
|
||||
|
||||
By default the path is a closed loop but a gap length and position can be specified to make open loops.
|
||||
To draw the gap its XY position is specified by ```gap_pos```. ```gap_pos.z``` can be used to specify a rotation if the gap is not at the bottom of the loop.
|
||||
|
||||
Individual teeth are not drawn, instead they are represented by a lighter colour.
|
||||
|
||||
@@ -223,6 +227,7 @@ Individual teeth are not drawn, instead they are represented by a lighter colour
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| ```belt_pitch(type)``` | Pitch in mm |
|
||||
| ```belt_pitch_height(type)``` | Offset of the pitch radius from the tips of the teeth |
|
||||
| ```belt_thickness(type)``` | Total thickness including teeth |
|
||||
| ```belt_tooth_height(type)``` | Tooth height |
|
||||
| ```belt_width(type)``` | Width in mm |
|
||||
@@ -231,12 +236,12 @@ Individual teeth are not drawn, instead they are represented by a lighter colour
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| ```belt_length(points, gap = 0)``` | Compute belt length given path and optional gap |
|
||||
| ```belt_pitch_height(type)``` | Offset of the pitch radius from the tips of the teeth |
|
||||
| ```belt_pitch_to_back(type)``` | Offset of the back from the pitch radius |
|
||||
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| ```belt(type, points, gap = 0, gap_pt = undef, belt_colour = grey(20)``` | Draw a belt path given a set of points and pitch radii where the pulleys are. Closed loop unless a gap is specified |
|
||||
| ```belt(type, points, gap = 0, gap_pos = undef, belt_colour = grey(20)``` | Draw a belt path given a set of points and pitch radii where the pulleys are. Closed loop unless a gap is specified |
|
||||
|
||||

|
||||
|
||||
@@ -244,7 +249,7 @@ Individual teeth are not drawn, instead they are represented by a lighter colour
|
||||
| Qty | Module call | BOM entry |
|
||||
| ---:|:--- |:---|
|
||||
| 1 | ```belt(GT2x6, [ ... ])``` | Belt GT2 x 6mm x 128mm |
|
||||
| 1 | ```belt(GT2x6, [ ... ], 80, [0, 0.81])``` | Belt GT2 x 6mm x 694mm |
|
||||
| 1 | ```belt(GT2x6, [ ... ], 80, [0, 0])``` | Belt GT2 x 6mm x 696mm |
|
||||
| 1 | ```belt(T2p5x6, [ ... ])``` | Belt T2.5 x 6mm x 130mm |
|
||||
| 1 | ```belt(T5x10, [ ... ])``` | Belt T5 x 10mm x 130mm |
|
||||
| 1 | ```belt(T5x6, [ ... ])``` | Belt T5 x 6mm x 130mm |
|
||||
@@ -400,7 +405,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.
|
||||
@@ -900,7 +905,7 @@ Can draw three styles: solid, open frame and open frame with screw bosses.
|
||||
| ---:|:--- |:---|
|
||||
| 1 | ```fan(fan120x25)``` | Fan 120mm x 25mm |
|
||||
| 1 | ```fan(fan17x8)``` | Fan 17mm x 8mm |
|
||||
| 1 | ```fan(fan25x10)``` | Fan 25mm x 10mm |
|
||||
| 1 | ```fan(fan25.4x10)``` | Fan 25.4mm x 10mm |
|
||||
| 1 | ```fan(fan30x10)``` | Fan 30mm x 10mm |
|
||||
| 1 | ```fan(fan40x11)``` | Fan 40mm x 11mm |
|
||||
| 1 | ```fan(fan50x15)``` | Fan 50mm x 15mm |
|
||||
@@ -1250,6 +1255,7 @@ Heatfit threaded inserts. Can be pushed into thermoplastics using a soldering ir
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| ```insert_boss_radius(type, wall)``` | Compute the outer radius of an insert boss |
|
||||
| ```insert_nose_length(type, d)``` | The length before the second ring. |
|
||||
|
||||
### Modules
|
||||
| Module | Description |
|
||||
@@ -1264,7 +1270,7 @@ Heatfit threaded inserts. Can be pushed into thermoplastics using a soldering ir
|
||||
### Vitamins
|
||||
| Qty | Module call | BOM entry |
|
||||
| ---:|:--- |:---|
|
||||
| 1 | ```insert(F1BM)``` | Heatfit insert M2 |
|
||||
| 1 | ```insert(F1BM2)``` | Heatfit insert M2 |
|
||||
| 1 | ```insert(F1BM2p5)``` | Heatfit insert M2.5 |
|
||||
| 1 | ```insert(F1BM3)``` | Heatfit insert M3 |
|
||||
| 1 | ```insert(F1BM4)``` | Heatfit insert M4 |
|
||||
@@ -1673,6 +1679,36 @@ LMnUU linear bearings.
|
||||
| 1 | ```linear_bearing(LM8UU)``` | Linear bearing LM8UU |
|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
|
||||
---
|
||||
<a name="Magnets"></a>
|
||||
## Magnets
|
||||
Cylindrical and ring magnets.
|
||||
|
||||
|
||||
[vitamins/magnets.scad](vitamins/magnets.scad) Object definitions.
|
||||
|
||||
[vitamins/magnet.scad](vitamins/magnet.scad) Implementation.
|
||||
|
||||
[tests/magnets.scad](tests/magnets.scad) Code for this example.
|
||||
|
||||
### Properties
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| ```magnet_h(type)``` | Height |
|
||||
| ```magnet_id(type)``` | Inside diameter if a ring |
|
||||
| ```magnet_od(type)``` | Outer diameter |
|
||||
| ```magnet_r(type)``` | Corner radius |
|
||||
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| ```magnet(type)``` | Draw specified magnet |
|
||||
|
||||

|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
|
||||
---
|
||||
@@ -1976,6 +2012,8 @@ A permanent magnet that can be magnatized and de-magnatized electronically.
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| ```opengrab_depth()``` | Module height |
|
||||
| ```opengrab_pcb()``` | The PCB |
|
||||
| ```opengrab_pcb_z()``` | PCB offset from the front |
|
||||
| ```opengrab_target_thickness()``` | Target sheet thickness |
|
||||
| ```opengrab_width()``` | Module width |
|
||||
|
||||
@@ -1984,6 +2022,7 @@ A permanent magnet that can be magnatized and de-magnatized electronically.
|
||||
|:--- |:--- |
|
||||
| ```opengrab()``` | Draw OpenGrab module |
|
||||
| ```opengrab_hole_positions()``` | Position children at the screw positions |
|
||||
| ```opengrab_side_hole_positions()``` | Position children at the two 4mm hole |
|
||||
| ```opengrab_target()``` | Draw OpenGrab target |
|
||||
|
||||

|
||||
@@ -1991,8 +2030,8 @@ A permanent magnet that can be magnatized and de-magnatized electronically.
|
||||
### Vitamins
|
||||
| Qty | Module call | BOM entry |
|
||||
| ---:|:--- |:---|
|
||||
| 1 | ```opengrab_target()``` | OpenGrab silicon steel target plate |
|
||||
| 1 | ```opengrab()``` | OpenGrab V3 electro permanent magnet |
|
||||
| 1 | ```opengrab_target()``` | OpenGrab silicon steel target plate |
|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
@@ -2140,6 +2179,7 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
|
||||
| ```usb_Ax1(cutout = false)``` | Draw USB type A single socket |
|
||||
| ```usb_Ax2(cutout = false)``` | Draw USB type A dual socket |
|
||||
| ```usb_B(cutout = false)``` | Draw USB B connector |
|
||||
| ```usb_C(cutout = false)``` | Draw USB C connector |
|
||||
| ```usb_uA(cutout = false)``` | Draw USB micro A connector |
|
||||
|
||||

|
||||
@@ -2176,6 +2216,7 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
|
||||
| 1 | ```smd_resistor(RES0603, 1K)``` | SMD resistor 0603 1K 0.1W |
|
||||
| 1 | ```smd_resistor(RES0805, 1K)``` | SMD resistor 0805 1K 0.125W |
|
||||
| 1 | ```smd_resistor(RES1206, 1K)``` | SMD resistor 1206 1K 0.25W |
|
||||
| 1 | ```square_button(button_4p5mm)``` | Square button 4.5mm |
|
||||
| 1 | ```square_button(button_6mm)``` | Square button 6mm |
|
||||
| 1 | ```pcb(TMC2130)``` | TMC2130 |
|
||||
| 1 | ```green_terminal(gt_5p08, 2)``` | Terminal block 2 way 0.2" |
|
||||
@@ -2188,6 +2229,8 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
|
||||
| 2 | ```green_terminal(gt_3p5, 4)``` | Terminal block 4 way 3.5mm |
|
||||
| 1 | ```terminal_35(4)``` | Terminal block 4 way 3.5mm |
|
||||
| 1 | ```pcb(TestPCB)``` | Test PCB |
|
||||
| 1 | ```wire_link(0.8, 5.08, h = 10.16)``` | Wire link 0.8mm x 0.2" |
|
||||
| 1 | ```wire_link(0.8, 10.16)``` | Wire link 0.8mm x 0.4" |
|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
@@ -2273,6 +2316,7 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
|
||||
| ```usb_Ax1(cutout = false)``` | Draw USB type A single socket |
|
||||
| ```usb_Ax2(cutout = false)``` | Draw USB type A dual socket |
|
||||
| ```usb_B(cutout = false)``` | Draw USB B connector |
|
||||
| ```usb_C(cutout = false)``` | Draw USB C connector |
|
||||
| ```usb_uA(cutout = false)``` | Draw USB micro A connector |
|
||||
|
||||

|
||||
@@ -2290,14 +2334,14 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
|
||||
| 1 | ```pcb(EnviroPlus)``` | Enviro+ |
|
||||
| 1 | ```pcb(ExtruderPCB)``` | Extruder connection PCB |
|
||||
| 1 | ```pcb(Keyes5p1)``` | Keyes5.1 Arduino Uno expansion board |
|
||||
| 1 | ```pcb(MP1584EN)``` | MP1584EN 3A buck converter |
|
||||
| 1 | ```pcb(MT3608)``` | MT3608 boost converter module |
|
||||
| 1 | ```pcb(Melzi)``` | Melzi electronics |
|
||||
| 4 | | Micro SD card |
|
||||
| 1 | ```molex_254(2)``` | Molex KK header 2 way |
|
||||
| 1 | ```molex_254(3)``` | Molex KK header 3 way |
|
||||
| 16 | ```nut(M2_nut, nyloc = true)``` | Nut M2 x 1.6mm nyloc |
|
||||
| 30 | ```nut(M2p5_nut, nyloc = true)``` | Nut M2.5 x 2.2mm nyloc |
|
||||
| 16 | ```nut(M3_nut, nyloc = true)``` | Nut M3 x 2.4mm nyloc |
|
||||
| 34 | ```nut(M2p5_nut, nyloc = true)``` | Nut M2.5 x 2.2mm nyloc |
|
||||
| 12 | ```nut(M3_nut, nyloc = true)``` | Nut M3 x 2.4mm nyloc |
|
||||
| 12 | ```nut(M4_nut, nyloc = true)``` | Nut M4 x 3.2mm nyloc |
|
||||
| 1 | ```pcb(PI_IO)``` | PI_IO V2 |
|
||||
| 1 | ```pcb(PSU12V1A)``` | PSU 12V 1A |
|
||||
@@ -2309,28 +2353,25 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
|
||||
| 1 | ```pin_socket(2p54header, 13, 2, right_angle = true)``` | Pin socket 13 x 2 right_angle |
|
||||
| 1 | ```pcb(RAMPSEndstop)``` | RAMPS Endstop Switch |
|
||||
| 1 | ```pcb(RPI3)``` | Raspberry Pi 3 |
|
||||
| 1 | ```pcb(RPI4)``` | Raspberry Pi 4 |
|
||||
| 1 | ```pcb(RPI0)``` | Raspberry Pi Zero |
|
||||
| 12 | ```screw(M2_cap_screw, 16)``` | Screw M2 cap x 16mm |
|
||||
| 4 | ```screw(M2_cap_screw, 20)``` | Screw M2 cap x 20mm |
|
||||
| 2 | ```screw(M2p5_cap_screw, 16)``` | Screw M2.5 cap x 16mm |
|
||||
| 4 | ```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 |
|
||||
| 2 | ```screw(M2p5_cap_screw, 20)``` | Screw M2.5 cap x 20mm |
|
||||
| 8 | ```screw(M2p5_cap_screw, 25)``` | Screw M2.5 cap x 25mm |
|
||||
| 8 | ```screw(M2p5_cap_screw, 30)``` | Screw M2.5 cap x 30mm |
|
||||
| 4 | ```screw(M2p5_pan_screw, 20)``` | Screw M2.5 pan x 20mm |
|
||||
| 12 | ```screw(M2p5_pan_screw, 25)``` | Screw M2.5 pan x 25mm |
|
||||
| 4 | ```screw(M3_cap_screw, 16)``` | Screw M3 cap x 16mm |
|
||||
| 8 | ```screw(M3_cap_screw, 30)``` | Screw M3 cap x 30mm |
|
||||
| 4 | ```screw(M3_cap_screw, 35)``` | Screw M3 cap x 35mm |
|
||||
| 4 | ```screw(M4_cap_screw, 30)``` | Screw M4 cap x 30mm |
|
||||
| 8 | ```screw(M4_cap_screw, 35)``` | Screw M4 cap x 35mm |
|
||||
| 12 | ```screw(M4_cap_screw, 35)``` | Screw M4 cap x 35mm |
|
||||
| 1 | ```pcb(TP4056)``` | TP4056 Li-lon Battery charger module |
|
||||
| 3 | ```terminal_35(2)``` | Terminal block 2 way 3.5mm |
|
||||
| 2 | ```green_terminal(gt_2p54, 4)``` | Terminal block 4 way 0.1" |
|
||||
| 1 | | USB A to Mini B lead |
|
||||
| 1 | ```pcb(WD2002SJ)``` | WD2002SJ Buck Boost DC-DC converter |
|
||||
| 16 | ```washer(M2_washer)``` | Washer M2 x 5mm x 0.3mm |
|
||||
| 30 | ```washer(M2p5_washer)``` | Washer M2.5 x 5.9mm x 0.5mm |
|
||||
| 16 | ```washer(M3_washer)``` | Washer M3 x 7mm x 0.5mm |
|
||||
| 34 | ```washer(M2p5_washer)``` | Washer M2.5 x 5.9mm x 0.5mm |
|
||||
| 12 | ```washer(M3_washer)``` | Washer M3 x 7mm x 0.5mm |
|
||||
| 12 | ```washer(M4_washer)``` | Washer M4 x 9mm x 0.8mm |
|
||||
| 1 | ```pcb(ZC_A0591)``` | ZC-A0591 ULN2003 driver PCB |
|
||||
|
||||
@@ -2341,21 +2382,21 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
|
||||
| 4 | pcb_spacer2070.stl |
|
||||
| 4 | pcb_spacer2080.stl |
|
||||
| 4 | pcb_spacer2090.stl |
|
||||
| 4 | pcb_spacer25100.stl |
|
||||
| 4 | pcb_spacer25110.stl |
|
||||
| 4 | pcb_spacer25120.stl |
|
||||
| 4 | pcb_spacer25130_2.stl |
|
||||
| 4 | pcb_spacer25130.stl |
|
||||
| 4 | pcb_spacer25140_2.stl |
|
||||
| 4 | pcb_spacer25150_2.stl |
|
||||
| 4 | pcb_spacer25180.stl |
|
||||
| 2 | pcb_spacer2570.stl |
|
||||
| 4 | pcb_spacer30160.stl |
|
||||
| 4 | pcb_spacer25160_2.stl |
|
||||
| 4 | pcb_spacer25190.stl |
|
||||
| 4 | pcb_spacer25200.stl |
|
||||
| 2 | pcb_spacer2580.stl |
|
||||
| 4 | pcb_spacer30170.stl |
|
||||
| 4 | pcb_spacer30220.stl |
|
||||
| 4 | pcb_spacer30180.stl |
|
||||
| 4 | pcb_spacer3050.stl |
|
||||
| 4 | pcb_spacer40190.stl |
|
||||
| 4 | pcb_spacer40200.stl |
|
||||
| 4 | pcb_spacer40210.stl |
|
||||
| 4 | pcb_spacer40220.stl |
|
||||
| 4 | pcb_spacer40230.stl |
|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
@@ -2424,19 +2465,24 @@ Pin headers and sockets, etc.
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| ```hdr_base_colour(type)``` | Header insulator colour |
|
||||
| ```hdr_box_size(type)``` | Box header outside dimensions |
|
||||
| ```hdr_box_wall(type)``` | Box header wall thickness |
|
||||
| ```hdr_pin_below(type)``` | Header pin length underneath |
|
||||
| ```hdr_pin_colour(type)``` | Header pin colour |
|
||||
| ```hdr_pin_length(type)``` | Header pin length |
|
||||
| ```hdr_pin_width(type)``` | Header pin size |
|
||||
| ```hdr_pitch(type)``` | Header pitch |
|
||||
| ```hdr_ra_box_offset(type)``` | Offset between back of the box and the pins |
|
||||
| ```hdr_ra_height(type)``` | Height of right angle connector |
|
||||
| ```hdr_socket_depth(type)``` | Socket depth for female housing |
|
||||
| ```hdr_y_offset(type)``` | Y offset of pins from center of the box |
|
||||
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| ```box_header(type, cols = 1, rows = 1, smt = false, cutout = false)``` | Draw box header |
|
||||
| ```idc_transition(type, cols = 5, skip = [], cutout = false)``` | Draw IDC transition header |
|
||||
| ```jst_xh_header(type, pin_count, right_angle=false, colour, pin_colour)``` | Draw JST XH connector |
|
||||
| ```jst_xh_header(type, pin_count, right_angle = false, colour = false, pin_colour = false)``` | Draw JST XH connector |
|
||||
| ```pin(type, length = undef)``` | Draw a header pin |
|
||||
| ```pin_header(type, cols = 1, rows = 1, smt = false, right_angle = false, cutout = false, colour)``` | Draw pin header |
|
||||
| ```pin_socket(type, cols = 1, rows = 1, right_angle = false, height = 0, smt = false, cutout = false, colour)``` | Draw pin socket |
|
||||
@@ -2447,11 +2493,18 @@ Pin headers and sockets, etc.
|
||||
| Qty | Module call | BOM entry |
|
||||
| ---:|:--- |:---|
|
||||
| 1 | ```box_header(2p54header, 10, 2)``` | Box header 10 x 2 |
|
||||
| 1 | ```box_header(2p54header, 8, 1)``` | Box header 8 x 1 |
|
||||
| 1 | ```idc_transition(2p54header, 10)``` | IDC transition header 10 x 2 |
|
||||
| 1 | ```pin_header(2p54header, 10, 2)``` | Pin header 10 x 2 |
|
||||
| 1 | ```pin_header(2p54header, 10, 2, right_angle = true)``` | Pin header 10 x 2 right_angle |
|
||||
| 1 | ```pin_header(2p54header, 3, 1, right_angle = true)``` | Pin header 3 x 1 right_angle |
|
||||
| 1 | ```pin_header(2p54header, 3, 2, right_angle = true)``` | Pin header 3 x 2 right_angle |
|
||||
| 1 | ```pin_header(2p54header, 3, 3, right_angle = true)``` | Pin header 3 x 3 right_angle |
|
||||
| 1 | ```pin_header(2p54header, 8, 1)``` | Pin header 8 x 1 |
|
||||
| 1 | ```pin_socket(2p54header, 10, 2)``` | Pin socket 10 x 2 |
|
||||
| 1 | ```pin_socket(2p54header, 10, 2, right_angle = true)``` | Pin socket 10 x 2 right_angle |
|
||||
| 1 | ```pin_socket(2p54header, 3, 1, right_angle = true)``` | Pin socket 3 x 1 right_angle |
|
||||
| 1 | ```pin_socket(2p54header, 3, 2, right_angle = true)``` | Pin socket 3 x 2 right_angle |
|
||||
| 1 | ```pin_socket(2p54header, 3, 3, right_angle = true)``` | Pin socket 3 x 3 right_angle |
|
||||
| 1 | ```pin_socket(2p54header, 8, 1)``` | Pin socket 8 x 1 |
|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
@@ -2589,6 +2642,7 @@ Timing belt pulleys, both toothed and plain with internal bearings for idlers.
|
||||
| 1 | ```pulley(GT2x20_toothed_idler)``` | Pulley GT2 idler 20 teeth |
|
||||
| 1 | ```pulley(GT2x20_plain_idler)``` | Pulley GT2 idler smooth 12mm |
|
||||
| 1 | ```pulley(GT2x16_plain_idler)``` | Pulley GT2 idler smooth 9.63mm |
|
||||
| 1 | ```pulley(GT2x16x7_plain_idler)``` | Pulley GT2 idler smooth 9.63mm |
|
||||
| 1 | ```pulley(GT2x20ob_pulley)``` | Pulley GT2OB 20 teeth |
|
||||
| 1 | ```pulley(GT2x12_pulley)``` | Pulley GT2RD 12 teeth |
|
||||
| 1 | ```pulley(GT2x20um_pulley)``` | Pulley GT2UM 20 teeth |
|
||||
@@ -2882,6 +2936,7 @@ Machine screws and wood screws with various head styles.
|
||||
| 1 | ```screw(No632_pan_screw, 30)``` | Screw 6-32 pan x 30mm |
|
||||
| 1 | ```screw(M2_cap_screw, 10)``` | Screw M2 cap x 10mm |
|
||||
| 1 | ```screw(M2_cs_cap_screw, 10)``` | Screw M2 cs cap x 10mm |
|
||||
| 1 | ```screw(M2_dome_screw, 10)``` | Screw M2 dome x 10mm |
|
||||
| 1 | ```screw(M2p5_cap_screw, 10)``` | Screw M2.5 cap x 10mm |
|
||||
| 1 | ```screw(M2p5_pan_screw, 10)``` | Screw M2.5 pan x 10mm |
|
||||
| 1 | ```screw(M3_cap_screw, 10)``` | Screw M3 cap x 10mm |
|
||||
@@ -3359,6 +3414,7 @@ NEMA stepper motor model.
|
||||
| ```NEMA_body_radius(type)``` | Body radius |
|
||||
| ```NEMA_boss_height(type)``` | Boss height |
|
||||
| ```NEMA_boss_radius(type)``` | Boss around the spindle radius |
|
||||
| ```NEMA_cap_heights(type)``` | Height of the end cap at the corner and the side |
|
||||
| ```NEMA_hole_pitch(type)``` | Screw hole pitch |
|
||||
| ```NEMA_length(type)``` | Body length |
|
||||
| ```NEMA_radius(type)``` | End cap radius |
|
||||
@@ -3375,7 +3431,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 |
|
||||
@@ -3582,16 +3638,22 @@ Tubing and sleeving. The internal diameter can be forced to stretch it over some
|
||||
| ```tubing_material(type)``` | Material description |
|
||||
| ```tubing_od(type)``` | Outside diameter |
|
||||
|
||||
### Functions
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| ```tubing_or(type)``` | Outside radius |
|
||||
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| ```tubing(type, length = 15, forced_id = 0)``` | Draw specified tubing with optional forced internal diameter |
|
||||
| ```tubing(type, length = 15, forced_id = 0, center = true)``` | Draw specified tubing with optional forced internal diameter |
|
||||
|
||||

|
||||
|
||||
### Vitamins
|
||||
| Qty | Module call | BOM entry |
|
||||
| ---:|:--- |:---|
|
||||
| 1 | ```tubing(CBNFIB10)``` | Carbon fiber OD 10mm ID 8mm x 15mm |
|
||||
| 1 | ```tubing(HSHRNK16)``` | Heatshrink sleeving ID 1.6mm x 15mm |
|
||||
| 1 | ```tubing(HSHRNK100)``` | Heatshrink sleeving ID 10mm x 15mm |
|
||||
| 1 | ```tubing(HSHRNK24)``` | Heatshrink sleeving ID 2.4mm x 15mm |
|
||||
@@ -3599,7 +3661,10 @@ Tubing and sleeving. The internal diameter can be forced to stretch it over some
|
||||
| 1 | ```tubing(NEOP85)``` | Neoprene tubing OD 8mm ID 5mm x 15mm |
|
||||
| 1 | ```tubing(PTFE07)``` | PTFE sleeving OD 1.2mm ID 0.71mm x 15mm |
|
||||
| 1 | ```tubing(PTFE20)``` | PTFE sleeving OD 2.6mm ID 2mm x 15mm |
|
||||
| 1 | ```tubing(PTFE2_3)``` | PTFE tubing OD 3mm ID 2mm x 15mm |
|
||||
| 1 | ```tubing(PF7)``` | PTFE tubing OD 4.6mm ID 3.84mm x 15mm |
|
||||
| 1 | ```tubing(PTFE2_4)``` | PTFE tubing OD 4mm ID 2mm x 15mm |
|
||||
| 1 | ```tubing(PTFE4_6)``` | PTFE tubing OD 6mm ID 4mm x 15mm |
|
||||
| 1 | ```tubing(PVC64)``` | PVC aquarium tubing OD 6mm ID 4mm x 15mm |
|
||||
| 1 | ```tubing(PVC85)``` | PVC aquarium tubing OD 8mm ID 5mm x 15mm |
|
||||
|
||||
@@ -4241,7 +4306,7 @@ Star washers can be omitted by setting ```star_washers``` to false.
|
||||
### Vitamins
|
||||
| Qty | Module call | BOM entry |
|
||||
| ---:|:--- |:---|
|
||||
| 3 | ```insert(F1BM)``` | Heatfit insert M2 |
|
||||
| 3 | ```insert(F1BM2)``` | Heatfit insert M2 |
|
||||
| 3 | ```insert(F1BM2p5)``` | Heatfit insert M2.5 |
|
||||
| 3 | ```insert(F1BM3)``` | Heatfit insert M3 |
|
||||
| 3 | ```insert(F1BM4)``` | Heatfit insert M4 |
|
||||
@@ -4403,7 +4468,7 @@ The ring spacing as well as the number of spokes can be specified, if zero a gas
|
||||
| ---:|:--- |
|
||||
| 1 | fan_guard_120.stl |
|
||||
| 1 | fan_guard_17.stl |
|
||||
| 1 | fan_guard_25.stl |
|
||||
| 1 | fan_guard_25.4.stl |
|
||||
| 1 | fan_guard_30.stl |
|
||||
| 1 | fan_guard_40.stl |
|
||||
| 1 | fan_guard_50.stl |
|
||||
@@ -4461,7 +4526,7 @@ Star washers can be omitted by setting ```star_washers``` to false.
|
||||
### Vitamins
|
||||
| Qty | Module call | BOM entry |
|
||||
| ---:|:--- |:---|
|
||||
| 3 | ```insert(F1BM)``` | Heatfit insert M2 |
|
||||
| 3 | ```insert(F1BM2)``` | Heatfit insert M2 |
|
||||
| 3 | ```insert(F1BM2p5)``` | Heatfit insert M2.5 |
|
||||
| 3 | ```insert(F1BM3)``` | Heatfit insert M3 |
|
||||
| 3 | ```insert(F1BM4)``` | Heatfit insert M4 |
|
||||
@@ -4791,7 +4856,7 @@ It can also have printed feet on the base with the screws doubling up to hold th
|
||||
### Vitamins
|
||||
| Qty | Module call | BOM entry |
|
||||
| ---:|:--- |:---|
|
||||
| 4 | ```insert(F1BM)``` | Heatfit insert M2 |
|
||||
| 4 | ```insert(F1BM2)``` | Heatfit insert M2 |
|
||||
| 4 | ```insert(F1BM3)``` | Heatfit insert M3 |
|
||||
| 4 | ```screw(M2_cap_screw, 6)``` | Screw M2 cap x 6mm |
|
||||
| 3 | ```screw(M3_pan_screw, 6)``` | Screw M3 pan x 6mm |
|
||||
@@ -4890,41 +4955,48 @@ Clamp for ribbon cable and polypropylene strip.
|
||||
### Functions
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| ```ribbon_clamp_height()``` | Height |
|
||||
| ```ribbon_clamp_hole_pitch(ways)``` | Hole pitch |
|
||||
| ```ribbon_clamp_length(ways)``` | Length given ways |
|
||||
| ```ribbon_clamp_width()``` | Width |
|
||||
| ```ribbon_clamp_height(screw = screw)``` | Height |
|
||||
| ```ribbon_clamp_length(ways, screw = screw)``` | Length given ways |
|
||||
| ```ribbon_clamp_width(screw = screw)``` | Width |
|
||||
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| ```ribbon_clamp(ways)``` | Generate STL for given number of ways |
|
||||
| ```ribbon_clamp_assembly(ways)``` | Printed part with inserts in place |
|
||||
| ```ribbon_clamp(ways, screw = screw)``` | Generate STL for given number of ways |
|
||||
| ```ribbon_clamp_assembly(ways, screw)``` | Printed part with inserts in place |
|
||||
| ```ribbon_clamp_fastened_assembly(ways, thickness, screw = screw)``` | Clamp with fasteners in place |
|
||||
| ```ribbon_clamp_hole_positions(ways, side = undef)``` | Place children at hole positions |
|
||||
| ```ribbon_clamp_holes(ways, h = 20)``` | Drill screw holes |
|
||||
| ```ribbon_clamp_hole_positions(ways, screw = screw, side = undef)``` | Place children at hole positions |
|
||||
| ```ribbon_clamp_holes(ways, h = 20, screw = screw)``` | Drill screw holes |
|
||||
|
||||

|
||||
|
||||
### Vitamins
|
||||
| Qty | Module call | BOM entry |
|
||||
| ---:|:--- |:---|
|
||||
| 2 | ```insert(F1BM2)``` | Heatfit insert M2 |
|
||||
| 2 | ```insert(F1BM3)``` | Heatfit insert M3 |
|
||||
| 1 | | Ribbon cable 20 way 100mm |
|
||||
| 1 | | Ribbon cable 8 way 100mm |
|
||||
| 2 | ```screw(M2_dome_screw, 8)``` | Screw M2 dome x 8mm |
|
||||
| 2 | ```screw(M3_cap_screw, 10)``` | Screw M3 cap x 10mm |
|
||||
| 1 | | Tape self amalgamating silicone 11 x 25mm |
|
||||
| 1 | | Tape self amalgamating silicone 26 x 25mm |
|
||||
| 2 | ```washer(M2_washer)``` | Washer M2 x 5mm x 0.3mm |
|
||||
| 2 | ```washer(M3_washer)``` | Washer M3 x 7mm x 0.5mm |
|
||||
| 2 | ```star_washer(M2_washer)``` | Washer star M2 x 0.3mm |
|
||||
| 2 | ```star_washer(M3_washer)``` | Washer star M3 x 0.5mm |
|
||||
|
||||
### Printed
|
||||
| Qty | Filename |
|
||||
| ---:|:--- |
|
||||
| 1 | ribbon_clamp_20.stl |
|
||||
| 1 | ribbon_clamp_8_2.stl |
|
||||
|
||||
### Assemblies
|
||||
| Qty | Name |
|
||||
| ---:|:--- |
|
||||
| 1 | ribbon_clamp_20_assembly |
|
||||
| 1 | ribbon_clamp_8_2_assembly |
|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
@@ -5179,6 +5251,36 @@ Bezier curves and function to get and adjust the length or minimum z point.
|
||||

|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
|
||||
---
|
||||
<a name="Catenary"></a>
|
||||
## Catenary
|
||||
Catenary curve to model hanging wires, etc.
|
||||
|
||||
Although the equation of the curve is simply ```y = a cosh(x / a)``` there is no explicit formula to calculate the constant ```a``` or the range of ```x``` given the
|
||||
length of the cable and the end point coordinates. See <https://en.wikipedia.org/wiki/Catenary#Determining_parameters>. The Newton-Raphson method is used to find
|
||||
```a``` numerically, see <https://en.wikipedia.org/wiki/Newton%27s_method>.
|
||||
|
||||
The coordinates of the lowest point on the curve can be retrieved by calling ```catenary_points()``` with ```steps``` equal to zero.
|
||||
|
||||
|
||||
[utils/catenary.scad](utils/catenary.scad) Implementation.
|
||||
|
||||
[tests/catenary.scad](tests/catenary.scad) Code for this example.
|
||||
|
||||
### Functions
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| ```catenary(t, a)``` | Parametric catenary function linear along the length of the curve. |
|
||||
| ```catenary_ds_by_da(d, a)``` | First derivative of the length with respect to ```a```. |
|
||||
| ```catenary_find_a(d, l, a = 1, best_e = inf, best_a = 1)``` | Find the catenary constant ```a```, given half the horizontal span and the length. |
|
||||
| ```catenary_points(l, x, y, steps = 100)``` | Returns a list of 2D points on the curve that goes from the origin to ```(x,y)``` and has length ```l```. |
|
||||
| ```catenary_s(d, a)``` | Length of a symmetric catenary with width ```2d```. |
|
||||
|
||||

|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
|
||||
---
|
||||
@@ -5229,6 +5331,7 @@ Rounded fillet for adding to corners.
|
||||
Utilities for making involute gears.
|
||||
|
||||
Formulas from <https://khkgears.net/new/gear_knowledge/gear_technical_reference/involute_gear_profile.html>
|
||||
<https://khkgears.net/new/gear_knowledge/gear_technical_reference/calculation_gear_dimensions.html>
|
||||
and <https://www.tec-science.com/mechanical-power-transmission/involute-gear/calculation-of-involute-gears/>
|
||||
|
||||
```involute_gear_profile()``` returns a polygon that can have the bore and spokes, etc, subtracted from it before linear extruding it to 3D.
|
||||
@@ -5241,6 +5344,8 @@ The clearance between tip and root defaults to module / 6, but can be overridden
|
||||
|
||||
The origin of the rack is the left end of the pitch line and its width is below the pitch line. I.e. it does not include the addendum.
|
||||
|
||||
```involute_worm_profile()``` returns a tooth profile that can be passed to ```thread()``` to make worms.
|
||||
|
||||
|
||||
[utils/gears.scad](utils/gears.scad) Implementation.
|
||||
|
||||
@@ -5249,8 +5354,11 @@ The origin of the rack is the left end of the pitch line and its width is below
|
||||
### Functions
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| ```centre_distance(m, z1, z2, pa)``` | Calculate distance between centres taking profile shift into account |
|
||||
| ```centre_distance(m, z1, z2, pa = 20)``` | Calculate distance between centres taking profile shift into account |
|
||||
| ```involute(r, u)``` | Involute of circle radius r at angle u in radians |
|
||||
| ```involute_gear_od(m, z, pa = 20)``` | involute gear outside diameter given modulus, tooth count and pressure angle |
|
||||
| ```involute_rack_tooth_profile(m, pa = 20, clearance = undef)``` | Calculate rack tooth profile given module and pressure angle |
|
||||
| ```involute_worm_profile(m, pa = 20, clearance = undef)``` | Calculate worm profile suitable for passing to thread() |
|
||||
| ```profile_shift(z, pa)``` | Calculate profile shift for small gears |
|
||||
|
||||
### Modules
|
||||
@@ -5282,6 +5390,35 @@ Method to print holes in mid air. See <https://hydraraptor.blogspot.com/2014/03/
|
||||

|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
|
||||
---
|
||||
<a name="Horiholes"></a>
|
||||
## 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.
|
||||
|
||||
[tests/horiholes.scad](tests/horiholes.scad) Code for this example.
|
||||
|
||||
### 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 |
|
||||
|
||||

|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
|
||||
---
|
||||
@@ -5323,7 +5460,14 @@ Maths utilities for manipulating vectors and matrices.
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| ```angle_between(v1, v2)``` | Return the angle between two vectors |
|
||||
| ```argcosh(x)``` | inverse hyperbolic cosine |
|
||||
| ```argcoth(x)``` | inverse hyperbolic cotangent |
|
||||
| ```argsinh(x)``` | inverse hyperbolic sine |
|
||||
| ```argtanh(x)``` | inverse hyperbolic tangent |
|
||||
| ```augment(m)``` | Augment a matrix by adding an identity matrix to the right |
|
||||
| ```circle_intersect(c1, r1, c2, r2)``` | Calculate one point where two circles in the X-Z plane intersect, clockwise around c1 |
|
||||
| ```cosh(x)``` | hyperbolic cosine |
|
||||
| ```coth(x)``` | hyperbolic cotangent |
|
||||
| ```degrees(radians)``` | Convert degrees to radians |
|
||||
| ```euler(R)``` | Convert a rotation matrix to a Euler rotation vector. |
|
||||
| ```identity(n, x = 1)``` | Construct an arbitrary size identity matrix |
|
||||
@@ -5336,9 +5480,11 @@ Maths utilities for manipulating vectors and matrices.
|
||||
| ```rotate(a, v)``` | Generate a 4x4 rotation matrix, ```a``` can be a vector of three angles or a single angle around ```z```, or around axis ```v``` |
|
||||
| ```rowswap(m, i, j)``` | Swap two rows of a matrix |
|
||||
| ```scale(v)``` | Generate a 4x4 matrix that scales by ```v```, which can be a vector of xyz factors or a scalar to scale all axes equally |
|
||||
| ```sinh(x)``` | hyperbolic sine |
|
||||
| ```solve(m, i = 0, j = 0)``` | Solve each row ensuring diagonal is not zero |
|
||||
| ```solve_row(m, i)``` | Make diagonal one by dividing the row by it and subtract from other rows to make column zero |
|
||||
| ```sqr(x)``` | Square x |
|
||||
| ```tanh(x)``` | hyperbolic tangent |
|
||||
| ```transform(v, m)``` | Apply 4x4 transform to a 3 vector by extending it and cropping it again |
|
||||
| ```transform_points(path, m)``` | Apply transform to a path |
|
||||
| ```translate(v)``` | Generate a 4x4 translation matrix, ```v``` can be ```[x, y]```, ```[x, y, z]``` or ```z``` |
|
||||
@@ -5528,7 +5674,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 |
|
||||
|
||||

|
||||
|
||||
@@ -5574,7 +5720,7 @@ Threads obey the $fn, $fa, $fs variables.
|
||||
|:--- |:--- |
|
||||
| ```female_metric_thread(d, pitch, length, center = true, top = -1, bot = -1, colour = undef)``` | Create female thread with metric profile |
|
||||
| ```male_metric_thread(d, pitch, length, center = true, top = -1, bot = -1, solid = true, colour = undef)``` | Create male thread with metric profile |
|
||||
| ```thread(dia, pitch, length, profile, center = true, top = -1, bot = -1, starts = 1, solid = true, female = false, colour = undef)``` | Create male or femail thread, ends can be tapered, chamfered or square |
|
||||
| ```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 |
|
||||
|
||||

|
||||
|
||||
@@ -5596,6 +5742,7 @@ Simple tube or ring
|
||||
|:--- |:--- |
|
||||
| ```ring(or, ir)``` | Create a ring with specified external and internal radii |
|
||||
| ```tube(or, ir, h, center = true)``` | Create a tube with specified external and internal radii and height ```h``` |
|
||||
| ```woven_tube(or, ir, h, center= true, colour = grey(30)``` | Create a woven tube with specified external and internal radii, height ```h```, colours, warp and weft |
|
||||
|
||||

|
||||
|
||||
@@ -5720,10 +5867,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 |
|
||||
|
||||
@@ -5769,7 +5919,7 @@ The module provides `poly_circle()`, `poly_cylinder()` and `poly_ring()` that is
|
||||
|:--- |:--- |
|
||||
| ```drill(r, h = 100, center = true)``` | Make a cylinder for drilling holes suitable for CNC routing, set h = 0 for circle |
|
||||
| ```poly_circle(r, sides = 0)``` | Make a circle adjusted to print the correct size |
|
||||
| ```poly_cylinder(r, h, center = false, sides = 0)``` | Make a cylinder adjusted to print the correct size |
|
||||
| ```poly_cylinder(r, h, center = false, sides = 0, chamfer = false)``` | Make a cylinder adjusted to print the correct size |
|
||||
| ```poly_drill(r, h = 100, center = true)``` | Make a cylinder for drilling holes suitable for CNC routing if cnc_bit_r is non zero, otherwise a poly_cylinder. |
|
||||
| ```poly_ring(or, ir, sides = 0)``` | Make a 2D ring adjusted to have the correct internal radius |
|
||||
| ```poly_tube(or, ir, h, center = false)``` | Make a tube adjusted to have the correct internal radius |
|
||||
@@ -5854,6 +6004,9 @@ This ensures `hull` and `minkowski` results have the correct dimensions when sph
|
||||
For making horizontal holes that don't need support material.
|
||||
Small holes can get away without it, but they print better with truncated teardrops.
|
||||
|
||||
Using teardrop_plus() or setting the plus option on other modules will elongate the teardrop vertically by the layer height, so when sliced the staircase tips
|
||||
do not intrude into the circle. See <https://hydraraptor.blogspot.com/2020/07/horiholes-2.html>
|
||||
|
||||
|
||||
[utils/core/teardrops.scad](utils/core/teardrops.scad) Implementation.
|
||||
|
||||
@@ -5862,12 +6015,12 @@ Small holes can get away without it, but they print better with truncated teardr
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| ```semi_teardrop(h, r, d = undef, center = true, chamfer = 0)``` | A semi teardrop in the positive Y domain |
|
||||
| ```teardrop(h, r, center = true, truncate = true, chamfer = 0)``` | For making horizontal holes that don't need support material, set ```truncate = false``` to make traditional RepRap teardrops that don't even need bridging |
|
||||
| ```semi_teardrop(h, r, d = undef, center = true, chamfer = 0, plus = false)``` | A semi teardrop in the positive Y domain |
|
||||
| ```teardrop(h, r, center = true, truncate = true, chamfer = 0, plus = false)``` | For making horizontal holes that don't need support material, set ```truncate = false``` to make traditional RepRap teardrops that don't even need bridging |
|
||||
| ```teardrop_chamfer(h, center, chamfer)``` | Helper module for adding chamfer to a teardrop |
|
||||
| ```teardrop_plus(h, r, center = true, truncate = true, chamfer = 0)``` | Slightly bigger teardrop to allow for the 3D printing staircase effect |
|
||||
| ```tearslot(h, r, w, center = true, chamfer = 0)``` | A horizontal slot that doesn't need support material |
|
||||
| ```vertical_tearslot(h, r, l, center = true, chamfer = 0)``` | A vertical slot that doesn't need support material |
|
||||
| ```teardrop_plus(h, r, center = true, truncate = true, chamfer = 0)``` | Slightly elongated teardrop to allow for the 3D printing staircase effect |
|
||||
| ```tearslot(h, r, w, center = true, chamfer = 0, plus = false)``` | A horizontal slot that doesn't need support material |
|
||||
| ```vertical_tearslot(h, r, l, center = true, chamfer = 0, plus = false)``` | A vertical slot that doesn't need support material |
|
||||
|
||||

|
||||
|
||||
|
@@ -97,7 +97,6 @@ def tests(tests):
|
||||
for dir in [deps_dir, png_dir, bom_dir]:
|
||||
if not os.path.isdir(dir):
|
||||
os.makedirs(dir)
|
||||
doc_name = "readme.md"
|
||||
index = {}
|
||||
bodies = {}
|
||||
done = []
|
||||
@@ -108,19 +107,33 @@ def tests(tests):
|
||||
#
|
||||
png_name = "libtest.png"
|
||||
scad_name = "libtest.scad"
|
||||
if not os.path.isfile(png_name):
|
||||
openscad.run(colour_scheme, "--projection=p", "--imgsize=%d,%d" % (w, h), "--camera=0,0,0,50,0,340,500", "--autocenter", "--viewall", "-o", png_name, scad_name);
|
||||
do_cmd(["magick", png_name, "-trim", "-resize", "1280", "-bordercolor", background, "-border", "10", png_name])
|
||||
if os.path.isfile(scad_name):
|
||||
libtest = True
|
||||
lib_blurb = scrape_blurb(scad_name)
|
||||
if not os.path.isfile(png_name):
|
||||
openscad.run(colour_scheme, "--projection=p", "--imgsize=%d,%d" % (w, h), "--camera=0,0,0,50,0,340,500", "--autocenter", "--viewall", "-o", png_name, scad_name);
|
||||
do_cmd(["magick", png_name, "-trim", "-resize", "1280", "-bordercolor", background, "-border", "10", png_name])
|
||||
else:
|
||||
#
|
||||
# Project tests so just a title
|
||||
#
|
||||
libtest = False
|
||||
project = ' '.join(word[0].upper() + word[1:] for word in os.path.basename(os.getcwd()).split('_'))
|
||||
lib_blurb = '#' + project + ' Tests\n'
|
||||
|
||||
doc_base_name = "readme" if libtest else "tests"
|
||||
doc_name = doc_base_name + ".md"
|
||||
#
|
||||
# List of individual part files
|
||||
#
|
||||
scads = [i for i in sorted(os.listdir(scad_dir), key = lambda s: s.lower()) if i[-5:] == ".scad"]
|
||||
|
||||
scads = [i for i in sorted(os.listdir(scad_dir), key = lambda s: s.lower()) if i[-5:] == ".scad"]
|
||||
types = []
|
||||
for scad in scads:
|
||||
base_name = scad[:-5]
|
||||
if not tests or base_name in tests:
|
||||
done.append(base_name)
|
||||
print(base_name)
|
||||
print('\n'+base_name)
|
||||
cap_name = base_name[0].capitalize() + base_name[1:]
|
||||
base_name = base_name.lower()
|
||||
scad_name = scad_dir + '/' + scad
|
||||
@@ -132,29 +145,42 @@ def tests(tests):
|
||||
if is_plural(base_name) and os.path.isfile(vits_name):
|
||||
objects_name = vits_name
|
||||
|
||||
locations = [
|
||||
('vitamins/' + depluralise(base_name) + '.scad', 'Vitamins'),
|
||||
('printed/' + base_name + '.scad', 'Printed'),
|
||||
('utils/' + base_name + '.scad', 'Utilities'),
|
||||
('utils/core/' + base_name + '.scad', 'Core Utilities'),
|
||||
]
|
||||
locations = []
|
||||
if os.path.isdir('vitamins'):
|
||||
locations.append(('vitamins/' + depluralise(base_name) + '.scad', 'Vitamins'))
|
||||
if os.path.isdir('printed'):
|
||||
locations.append(('printed/' + base_name + '.scad', 'Printed'))
|
||||
if os.path.isdir('utils'):
|
||||
locations.append(('utils/' + base_name + '.scad', 'Utilities'))
|
||||
if libtest and os.path.isdir('utils/core'):
|
||||
locations.append(('utils/core/' + base_name + '.scad', 'Core Utilities'))
|
||||
|
||||
for name, type in locations:
|
||||
if os.path.isfile(name):
|
||||
impl_name = name
|
||||
break
|
||||
else:
|
||||
print("Can't find implementation!")
|
||||
continue
|
||||
if libtest:
|
||||
print("Can't find implementation!")
|
||||
continue
|
||||
else:
|
||||
type = 'Tests' # OK when testing part of a project
|
||||
impl_name = None
|
||||
|
||||
vsplit = "AJR" + chr(ord('Z') + 1)
|
||||
vtype = locations[0][1]
|
||||
types = [vtype + ' ' + vsplit[i] + '-' + chr(ord(vsplit[i + 1]) - 1) for i in range(len(vsplit) - 1)] + [loc[1] for loc in locations[1 :]]
|
||||
if type == vtype:
|
||||
for i in range(1, len(vsplit)):
|
||||
if cap_name[0] < vsplit[i]:
|
||||
type = types[i - 1]
|
||||
break
|
||||
if libtest:
|
||||
vsplit = "AJR" + chr(ord('Z') + 1)
|
||||
vtype = locations[0][1]
|
||||
types = [vtype + ' ' + vsplit[i] + '-' + chr(ord(vsplit[i + 1]) - 1) for i in range(len(vsplit) - 1)] + [loc[1] for loc in locations[1 :]]
|
||||
if type == vtype:
|
||||
for i in range(1, len(vsplit)):
|
||||
if cap_name[0] < vsplit[i]:
|
||||
type = types[i - 1]
|
||||
break
|
||||
else:
|
||||
if not types:
|
||||
types = [loc[1] for loc in locations] # No need to split up the vitamin list
|
||||
if not type in types: # Will happen when implementation is not found and type is set to Tests
|
||||
types.append(type)
|
||||
|
||||
for t in types:
|
||||
if not t in bodies:
|
||||
@@ -250,24 +276,7 @@ def tests(tests):
|
||||
usage()
|
||||
|
||||
with open(doc_name, "wt") as doc_file:
|
||||
print('# NopSCADlib', file = doc_file)
|
||||
print('''\
|
||||
An ever expanding library of parts modelled in OpenSCAD useful for 3D printers and enclosures for electronics, etc.
|
||||
|
||||
It contains lots of vitamins (the RepRap term for non-printed parts), some general purpose printed parts and
|
||||
some utilities. There are also Python scripts to generate Bills of Materials (BOMs),
|
||||
STL files for all the printed parts, DXF files for CNC routed parts in a project and a manual containing assembly
|
||||
instructions and exploded views by scraping markdown embedded in OpenSCAD comments, [see scripts](scripts/readme.md). A simple example project can be found [here](examples/MainsBreakOutBox/readme.md).
|
||||
|
||||
For more examples of what it can make see the [gallery](gallery/readme.md).
|
||||
|
||||
The license is GNU General Public License v3.0, see [COPYING](COPYING).
|
||||
|
||||
See [usage](docs/usage.md) for requirements, installation instructions and a usage guide.
|
||||
|
||||
<img src="libtest.png" width="100%"/>\n
|
||||
''', file = doc_file)
|
||||
|
||||
print(lib_blurb, file = doc_file)
|
||||
print('## Table of Contents<a name="top"/>', file = doc_file)
|
||||
print('<table><tr>', file = doc_file)
|
||||
n = 0
|
||||
@@ -288,10 +297,10 @@ See [usage](docs/usage.md) for requirements, installation instructions and a usa
|
||||
for type in types:
|
||||
for line in bodies[type]:
|
||||
print(line, file = doc_file)
|
||||
with open("readme.html", "wt") as html_file:
|
||||
do_cmd("python -m markdown -x tables readme.md".split(), html_file)
|
||||
with open(doc_base_name + ".html", "wt") as html_file:
|
||||
do_cmd(("python -m markdown -x tables " + doc_name).split(), html_file)
|
||||
times.print_times()
|
||||
do_cmd('codespell -L od readme.md'.split())
|
||||
do_cmd(('codespell -L od ' + doc_name).split())
|
||||
|
||||
if __name__ == '__main__':
|
||||
for arg in sys.argv[1:]:
|
||||
|
@@ -86,10 +86,13 @@ test_pcb = ["TestPCB", "Test PCB",
|
||||
[ 5, 218, 180, "hdmi"],
|
||||
[ 3, 235, 180, "mini_hdmi"],
|
||||
[ 6, 175, 180, "uSD", [12, 11.5, 1.4]],
|
||||
|
||||
[ 65, 9, 0, "link", inch(0.4)],
|
||||
[ 65, 12, 0, "ax_res", res1_8, 1000],
|
||||
[ 65, 17, 0, "ax_res", res1_4, 10000],
|
||||
[ 65, 22, 0, "ax_res", res1_2, 100000],
|
||||
|
||||
[ 80, 9, 0, "link", inch(0.2), inch(0.4)],
|
||||
[ 80, 12, 0, "ax_res", res1_8, 1000000, 1, inch(0.1)],
|
||||
[ 80, 17, 0, "ax_res", res1_4, 100, 2, inch(0.1)],
|
||||
[ 80, 22, 0, "ax_res", res1_2, 10, 10, inch(0.2)],
|
||||
@@ -118,7 +121,8 @@ test_pcb = ["TestPCB", "Test PCB",
|
||||
[ 70, 130, 180, "term35", 3, "lime"],
|
||||
[ 50, 150, 0, "transition", 5],
|
||||
[ 50, 160, 0, "block", 10, 5, 8, "orange"],
|
||||
[ 50, 170, 0, "button_6mm"],
|
||||
[ 45, 170, 0, "button_6mm"],
|
||||
[ 55, 170, 0, "button_4p5mm"],
|
||||
[ 50, 185, 0, "microswitch", small_microswitch],
|
||||
[ 52, 200, 0, "pcb", 11, TMC2130 ],
|
||||
[ 80, 200, 0, "pdip", 24, "27C32", true, inch(0.6) ],
|
||||
|
@@ -60,7 +60,7 @@ module belt_test() {
|
||||
[p4.x, p4.y, pulley_pr(GT2x20ob_pulley)]
|
||||
];
|
||||
belt = GT2x6;
|
||||
belt(belt, path, 80, [0, belt_pitch_height(belt) - belt_thickness(belt) / 2]);
|
||||
belt(belt, path, 80, [0, 0]);
|
||||
|
||||
translate([-25, 0])
|
||||
layout([for(b = belts) belt_width(b)], 10)
|
||||
|
56
tests/catenary.scad
Normal file
@@ -0,0 +1,56 @@
|
||||
//
|
||||
// NopSCADlib Copyright Chris Palmer 2020
|
||||
// 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/>.
|
||||
//
|
||||
l = 250; // [1: 1000]
|
||||
x = 200; // [1: 1000]
|
||||
y = 50; //[-500 : 500]
|
||||
|
||||
include <../utils/core/core.scad>
|
||||
use <../utils/catenary.scad>
|
||||
use <../utils/sweep.scad>
|
||||
use <../utils/annotation.scad>
|
||||
|
||||
module catenaries() {
|
||||
//
|
||||
// catenary curve path from control points
|
||||
//
|
||||
curve = [for(p = catenary_points(l, x, y)) [p.x, p.y, 0]];
|
||||
//
|
||||
// Draw the curve
|
||||
//
|
||||
r = 0.5;
|
||||
sweep(curve, circle_points(r, $fn = 64));
|
||||
//
|
||||
// Minimum Z
|
||||
//
|
||||
min_z = catenary_points(l, x, y, 0);
|
||||
|
||||
color("blue") {
|
||||
translate([min_z.x, min_z.y + r])
|
||||
rotate([-90, 0, 0])
|
||||
arrow();
|
||||
|
||||
translate([min_z.x, min_z.y - r])
|
||||
rotate([90, 0, 0])
|
||||
arrow();
|
||||
}
|
||||
}
|
||||
|
||||
if($preview)
|
||||
rotate(is_undef($bom) ? 0 : [70, 0, 315])
|
||||
catenaries();
|
@@ -21,14 +21,14 @@ use <../printed/foot.scad>
|
||||
|
||||
module feet()
|
||||
if($preview) {
|
||||
translate([50, 0])
|
||||
translate([40, 0])
|
||||
foot_assembly(3);
|
||||
|
||||
translate([foot_diameter(insert_foot()) / 2, 0])
|
||||
fastened_insert_foot_assembly(3);
|
||||
}
|
||||
else {
|
||||
translate([50, 0])
|
||||
translate([40, 0])
|
||||
foot();
|
||||
|
||||
insert_foot();
|
||||
|
@@ -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();
|
||||
|
94
tests/horiholes.scad
Normal file
@@ -0,0 +1,94 @@
|
||||
//
|
||||
// NopSCADlib Copyright Chris Palmer 2020
|
||||
// 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/>.
|
||||
//
|
||||
$layer_height = 0.25;
|
||||
include <../utils/core/core.scad>
|
||||
use <../utils/horiholes.scad>
|
||||
|
||||
show_disc = true;
|
||||
use_horihole = true;
|
||||
thickness = 6;
|
||||
length = 60;
|
||||
height = 20;
|
||||
overlap_x = 15;
|
||||
overlap_y = 10;
|
||||
|
||||
module hole_positions() {
|
||||
x0 = (length - 40) / 2;
|
||||
for($i = [0 : 4], $z = 5 + $i * layer_height / 5, $r = 3)
|
||||
translate([x0 + $i * 10, $z])
|
||||
children();
|
||||
|
||||
for($i = [0 : 4], $z = 15 + $i * layer_height / 5, $r = 0.5 + $i / 2)
|
||||
translate([x0 + $i * 10, $z])
|
||||
children();
|
||||
}
|
||||
|
||||
module horiholes_stl(t = thickness) {
|
||||
rotate([90, 0, 0])
|
||||
difference() {
|
||||
linear_extrude(t, center = true) {
|
||||
difference() {
|
||||
square([length, height]);
|
||||
|
||||
hole_positions()
|
||||
if(use_horihole)
|
||||
horihole($r, $z);
|
||||
else
|
||||
teardrop_plus(h = 0, r = $r);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(t == thickness)
|
||||
translate([length / 2, 0])
|
||||
rounded_rectangle([length + 2 * overlap_x, thickness + 2 * overlap_y, 2], 5);
|
||||
}
|
||||
|
||||
module horiholes() {
|
||||
stl_colour(pp1_colour)
|
||||
rotate([-90, 0, 0])
|
||||
horiholes_stl(eps);
|
||||
|
||||
if(show_disc)
|
||||
hole_positions()
|
||||
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(3 * eps, center = true)
|
||||
intersection() {
|
||||
difference() {
|
||||
square(8, center = true);
|
||||
|
||||
horihole($r, $z);
|
||||
}
|
||||
|
||||
circle($r, $fn = 360);
|
||||
}
|
||||
}
|
||||
|
||||
if($preview)
|
||||
rotate(is_undef($bom) ? 0 : [70, 0, 315])
|
||||
horiholes();
|
||||
else
|
||||
horiholes_stl();
|
29
tests/magnets.scad
Normal file
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// NopSCADlib Copyright Chris Palmer 2020
|
||||
// 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 <../core.scad>
|
||||
use <../utils/layout.scad>
|
||||
|
||||
include <../vitamins/magnets.scad>
|
||||
|
||||
module magnets()
|
||||
layout([for(m = magnets) magnet_od(m)], 5)
|
||||
magnet(magnets[$i]);
|
||||
|
||||
if($preview)
|
||||
magnets();
|
@@ -69,6 +69,33 @@ module maths() {
|
||||
// Test Euler
|
||||
//
|
||||
assert(euler(rotate(r)) == r, "euler() failed");
|
||||
//
|
||||
// Circle intersect
|
||||
//
|
||||
r1 = 10;
|
||||
c1 = [50, 0, 10];
|
||||
r2 = 20;
|
||||
c2 = [67, 0, 0];
|
||||
p1 = circle_intersect(c1, r1, c2, r2);
|
||||
p2 = circle_intersect(c2, r2, c1, r1);
|
||||
|
||||
rotate(90) {
|
||||
color(grey(90))
|
||||
translate(c1) rotate([90, 0, 0]) cylinder(r = r1, h = 4 * eps, center = true);
|
||||
|
||||
color(grey(80))
|
||||
translate(c2) rotate([90, 0, 0]) cylinder(r = r2, h = eps, center = true);
|
||||
|
||||
color("red")
|
||||
translate(p1) rotate([90, 0, 0]) cylinder(r = 0.1, h = 6 * eps, center = true);
|
||||
|
||||
color("blue")
|
||||
translate(p2) rotate([90, 0, 0]) cylinder(r = 0.1, h = 6 * eps, center = true);
|
||||
|
||||
translate(p1) arrow();
|
||||
|
||||
translate(p2) vflip() arrow();
|
||||
}
|
||||
}
|
||||
|
||||
rotate(45)
|
||||
|
@@ -21,11 +21,11 @@ include <../utils/core/core.scad>
|
||||
use <../vitamins/opengrab.scad>
|
||||
|
||||
module opengrab_test() {
|
||||
opengrab_target();
|
||||
|
||||
rotate(45)
|
||||
translate_z(opengrab_target_thickness())
|
||||
opengrab();
|
||||
opengrab_target();
|
||||
|
||||
translate_z(opengrab_target_thickness())
|
||||
opengrab();
|
||||
}
|
||||
|
||||
if($preview)
|
||||
|
@@ -23,26 +23,56 @@ include <../vitamins/pin_headers.scad>
|
||||
|
||||
pins = 10;
|
||||
|
||||
module pin_headers()
|
||||
module pin_headers() {
|
||||
layout([for(p = pin_headers) hdr_pitch(p) * pins], 15) {
|
||||
idc_transition(pin_headers[$i], 10);
|
||||
|
||||
translate([0, 20])
|
||||
pin_header(pin_headers[$i], 10, 2, right_angle = true);
|
||||
pin_header(pin_headers[$i], 3, 2, right_angle = true);
|
||||
|
||||
translate([-10, 20])
|
||||
pin_header(pin_headers[$i], 3, 1, right_angle = true);
|
||||
|
||||
translate([10, 20])
|
||||
pin_header(pin_headers[$i], 3, 3, right_angle = true);
|
||||
|
||||
translate([0, 30])
|
||||
pin_header(pin_headers[$i], 8, 1);
|
||||
|
||||
translate([0, 40])
|
||||
pin_header(pin_headers[$i], 10, 2);
|
||||
|
||||
translate([0, 50])
|
||||
box_header(pin_headers[$i], 8, 1);
|
||||
|
||||
translate([0, 60])
|
||||
box_header(pin_headers[$i], 10, 2);
|
||||
|
||||
translate([0, 70])
|
||||
pin_socket(pin_headers[$i], 8, 1);
|
||||
|
||||
translate([0, 80])
|
||||
pin_socket(pin_headers[$i], 10, 2);
|
||||
|
||||
translate([0, 110])
|
||||
pin_socket(pin_headers[$i], 10, 2, right_angle = true);
|
||||
translate([-10, 105])
|
||||
pin_socket(pin_headers[$i], 3, 1, right_angle = true);
|
||||
|
||||
translate([0, 105])
|
||||
pin_socket(pin_headers[$i], 3, 2, right_angle = true);
|
||||
|
||||
translate([10, 105])
|
||||
pin_socket(pin_headers[$i], 3, 3, right_angle = true);
|
||||
}
|
||||
|
||||
for(i = [0, 1], p = [5, 2][i], j = [0 , 1]) {
|
||||
h = [jst_ph_header, jst_xh_header][j];
|
||||
translate([-20 * (i + 1), 0 + j * 40])
|
||||
jst_xh_header(h, p);
|
||||
|
||||
translate([-20 * (i + 1), 20 + j * 40])
|
||||
jst_xh_header(h, p, true);
|
||||
}
|
||||
}
|
||||
|
||||
if($preview)
|
||||
pin_headers();
|
||||
|
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 95 KiB |
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 103 KiB |
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 112 KiB |
BIN
tests/png/catenary.png
Normal file
After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 118 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 119 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 117 KiB |
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 148 KiB |
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 102 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
BIN
tests/png/horiholes.png
Normal file
After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 125 KiB |
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 85 KiB |
BIN
tests/png/magnets.png
Normal file
After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 97 KiB |
Before Width: | Height: | Size: 172 KiB After Width: | Height: | Size: 174 KiB |
Before Width: | Height: | Size: 161 KiB After Width: | Height: | Size: 152 KiB |
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 166 KiB |
Before Width: | Height: | Size: 137 KiB After Width: | Height: | Size: 137 KiB |
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 90 KiB |
Before Width: | Height: | Size: 188 KiB After Width: | Height: | Size: 188 KiB |
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 160 KiB |
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 104 KiB |
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 150 KiB |
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 72 KiB |
@@ -67,7 +67,7 @@ module box1_external_additions() {
|
||||
|
||||
module box1_holes() {
|
||||
box1_feet_positions()
|
||||
teardrop(r = screw_pilot_hole(foot_screw(foot)), h = 10, center = true);
|
||||
teardrop_plus(r = screw_pilot_hole(foot_screw(foot)), h = 10, center = true);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -16,20 +16,22 @@
|
||||
// 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>
|
||||
include <../core.scad>
|
||||
use <../printed/ribbon_clamp.scad>
|
||||
use <../vitamins/wire.scad>
|
||||
|
||||
ways = 20;
|
||||
ways = [8, 20];
|
||||
screws = [M2_dome_screw, M3_cap_screw];
|
||||
|
||||
module ribbon_clamps()
|
||||
translate([ribbon_clamp_length(ways) / 2, 0])
|
||||
if($preview) {
|
||||
ribbon_clamp_fastened_assembly(ways, 3);
|
||||
for(i = [0 : len(screws) - 1])
|
||||
translate([ribbon_clamp_length(ways[i]) / 2, i * 30])
|
||||
if($preview) {
|
||||
ribbon_clamp_fastened_assembly(ways[i], 3, screws[i]);
|
||||
|
||||
ribbon_cable(ways, 100);
|
||||
}
|
||||
else
|
||||
ribbon_clamp(ways);
|
||||
ribbon_cable(ways[i], 100);
|
||||
}
|
||||
else
|
||||
ribbon_clamp(ways[i], screws[i]);
|
||||
|
||||
ribbon_clamps();
|
||||
|
@@ -22,12 +22,12 @@ include <../vitamins/stepper_motors.scad>
|
||||
use <../utils/layout.scad>
|
||||
|
||||
module stepper_motors()
|
||||
layout([for(s = stepper_motors) NEMA_width(s)], 5) {
|
||||
layout([for(s = stepper_motors) NEMA_width(s)], 5) let(m = stepper_motors[$i]) {
|
||||
rotate(180)
|
||||
NEMA(stepper_motors[$i]);
|
||||
NEMA(m, 0, m == NEMA17M || m == NEMA17M8);
|
||||
|
||||
translate_z(4)
|
||||
NEMA_screws(stepper_motors[$i], M3_pan_screw, n = $i, earth = $i > 4 ? undef : $i - 1);
|
||||
NEMA_screws(m, M3_pan_screw, n = $i, earth = $i > 4 ? undef : $i - 1);
|
||||
}
|
||||
|
||||
if($preview)
|
||||
|
@@ -41,7 +41,10 @@ module teardrops() {
|
||||
|
||||
translate([20, 10])
|
||||
semi_teardrop(h = 0, r = 3);
|
||||
}
|
||||
|
||||
translate([20, 20])
|
||||
teardrop(h = 0, r = 3, truncate = false, plus = true);
|
||||
}
|
||||
}
|
||||
translate([40, 0, 1.5]) {
|
||||
h = 3 + eps;
|
||||
@@ -61,6 +64,9 @@ module teardrops() {
|
||||
|
||||
translate([20, 10])
|
||||
semi_teardrop(h = h, r = 3, chamfer = chamfer);
|
||||
|
||||
translate([20, 20])
|
||||
teardrop(h = h, r = 3, truncate = false, plus = false, chamfer = chamfer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -22,7 +22,7 @@ use <../utils/layout.scad>
|
||||
include <../vitamins/tubings.scad>
|
||||
|
||||
module tubings()
|
||||
layout([for(t = tubings) tubing_od(t)], 10)
|
||||
layout([for(t = tubings) tubing_od(t)], 8)
|
||||
tubing(tubings[$i]);
|
||||
|
||||
if($preview)
|
||||
|
52
utils/catenary.scad
Normal file
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// NopSCADlib Copyright Chris Palmer 2020
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
//
|
||||
//! Catenary curve to model hanging wires, etc.
|
||||
//!
|
||||
//! Although the equation of the curve is simply ```y = a cosh(x / a)``` there is no explicit formula to calculate the constant ```a``` or the range of ```x``` given the
|
||||
//! length of the cable and the end point coordinates. See <https://en.wikipedia.org/wiki/Catenary#Determining_parameters>. The Newton-Raphson method is used to find
|
||||
//! ```a``` numerically, see <https://en.wikipedia.org/wiki/Newton%27s_method>.
|
||||
//!
|
||||
//! The coordinates of the lowest point on the curve can be retrieved by calling ```catenary_points()``` with ```steps``` equal to zero.
|
||||
//
|
||||
include <core/core.scad>
|
||||
use <maths.scad>
|
||||
|
||||
function catenary(t, a) = let(u = argsinh(t)) a * [u, cosh(u)]; //! Parametric catenary function linear along the length of the curve.
|
||||
function catenary_s(d, a) = 2 * a * sinh(d / a); //! Length of a symmetric catenary with width ```2d```.
|
||||
function catenary_ds_by_da(d, a) = 2 * sinh(d / a) - 2 * d / a * cosh(d / a); //! First derivative of the length with respect to ```a```.
|
||||
|
||||
function catenary_find_a(d, l, a = 1, best_e = inf, best_a = 1) = //! Find the catenary constant ```a```, given half the horizontal span and the length.
|
||||
assert(l > 2 * d, "Not long enough to span the gap") assert(d) let(error = abs(catenary_s(d, a) - l))
|
||||
error >= best_e && error < 0.0001 ? best_a
|
||||
: catenary_find_a(d, l, max(a - (catenary_s(d, a) - l) / catenary_ds_by_da(d, a), d / argsinh(1e99)), error, a);
|
||||
|
||||
function catenary_points(l, x, y, steps = 100) = //! Returns a list of 2D points on the curve that goes from the origin to ```(x,y)``` and has length ```l```.
|
||||
let(
|
||||
d = x / 2,
|
||||
a = catenary_find_a(d, sqrt(sqr(l) - sqr(y))), // Find a to get the correct length
|
||||
offset = argsinh(y / catenary_s(d, a)),
|
||||
t0 = sinh(-d / a + offset),
|
||||
t1 = sinh( d / a + offset),
|
||||
h = a * cosh(-d / a + offset) - a,
|
||||
lowest = offset > d / a ? [0, 0] : offset < -d / a ? [x, y] : [d - offset * a, -h],
|
||||
p0 = catenary(t0, a)
|
||||
)
|
||||
steps ? [for(t = [t0 : (t1 - t0) / steps : t1]) catenary(t, a) - p0] : lowest;
|
@@ -18,7 +18,7 @@
|
||||
//
|
||||
|
||||
//
|
||||
// Include this file to use the miniumum library
|
||||
// Include this file to use the minimum library
|
||||
//
|
||||
include <../../global_defs.scad>
|
||||
//
|
||||
|
@@ -31,16 +31,27 @@ function m(x) = x * 1000.0;
|
||||
|
||||
function sqr(x) = x * x; //! Returns the square of ```x```
|
||||
function echoit(x) = echo(x) x; //! Echo expression and return it, useful for debugging
|
||||
function no_point(str) = chr([for(c = str(str)) if(c == ".") ord("p") else ord(c)]);//! Replace decimal point in string with 'p'
|
||||
function in(list, x) = !!len([for(v = list) if(v == x) true]); //! Returns true if ```x``` is an element in the ```list```
|
||||
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° flip around the X axis
|
||||
module hflip() rotate([0, 180, 0]) children(); //! Invert children by doing a 180° 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
|
||||
|
@@ -32,10 +32,14 @@ module poly_circle(r, sides = 0) { //! Make a circle adjusted to print the corre
|
||||
circle(r = corrected_radius(r,n), $fn = n);
|
||||
}
|
||||
|
||||
module poly_cylinder(r, h, center = false, sides = 0) //! Make a cylinder adjusted to print the correct size
|
||||
module poly_cylinder(r, h, center = false, sides = 0, chamfer = false) {//! Make a cylinder adjusted to print the correct size
|
||||
extrude_if(h, center)
|
||||
poly_circle(r, sides);
|
||||
|
||||
if(h && chamfer)
|
||||
poly_cylinder(r + layer_height, center ? layer_height * 2 : layer_height, center, sides = sides ? sides : sides(r));
|
||||
}
|
||||
|
||||
module poly_ring(or, ir, sides = 0) { //! Make a 2D ring adjusted to have the correct internal radius
|
||||
cir = corrected_radius(ir, sides);
|
||||
filaments = (or - cir) / extrusion_width;
|
||||
|
@@ -20,17 +20,32 @@
|
||||
//
|
||||
//! For making horizontal holes that don't need support material.
|
||||
//! Small holes can get away without it, but they print better with truncated teardrops.
|
||||
//!
|
||||
//! Using teardrop_plus() or setting the plus option on other modules will elongate the teardrop vertically by the layer height, so when sliced the staircase tips
|
||||
//! do not intrude into the circle. See <https://hydraraptor.blogspot.com/2020/07/horiholes-2.html>
|
||||
//
|
||||
module teardrop(h, r, center = true, truncate = true, chamfer = 0) { //! For making horizontal holes that don't need support material, set ```truncate = false``` to make traditional RepRap teardrops that don't even need bridging
|
||||
module teardrop(h, r, center = true, truncate = true, chamfer = 0, plus = false) { //! For making horizontal holes that don't need support material, set ```truncate = false``` to make traditional RepRap teardrops that don't even need bridging
|
||||
module teardrop_2d(r, truncate) {
|
||||
hull() {
|
||||
circle4n(r);
|
||||
if(truncate)
|
||||
translate([0, r / 2])
|
||||
square([2 * r * (sqrt(2) - 1), r], center = true);
|
||||
else
|
||||
polygon([[0, 0], [eps, 0], [0, r * sqrt(2)]]);
|
||||
}
|
||||
er = layer_height / 2 - eps; // Extrustion edge radius
|
||||
R = plus ? r + er : r; // Corrected radius
|
||||
offset = plus ? -er : 0; // Offset inwards
|
||||
hull()
|
||||
for(side = [0 : 1])
|
||||
mirror([side, 0, 0])
|
||||
intersection() {
|
||||
hull()
|
||||
translate([offset, 0]) {
|
||||
circle4n(R);
|
||||
|
||||
if(truncate)
|
||||
translate([0, R / 2])
|
||||
square([2 * R * (sqrt(2) - 1), R], center = true);
|
||||
else
|
||||
polygon([[0, 0], [eps, 0], [0, R * sqrt(2)]]);
|
||||
}
|
||||
translate([0, -2 * R])
|
||||
square([R, 4 * R]);
|
||||
}
|
||||
}
|
||||
|
||||
render(convexity = 5)
|
||||
@@ -40,23 +55,23 @@ module teardrop(h, r, center = true, truncate = true, chamfer = 0) { //! For mak
|
||||
teardrop_chamfer(h, center, chamfer) {
|
||||
linear_extrude(eps, center = true)
|
||||
teardrop_2d(r + chamfer / 2, truncate);
|
||||
|
||||
translate_z(-chamfer / 2)
|
||||
linear_extrude(eps, center = true)
|
||||
teardrop_2d(r, truncate);
|
||||
}
|
||||
}
|
||||
|
||||
module semi_teardrop(h, r, d = undef, center = true, chamfer = 0) { //! A semi teardrop in the positive Y domain
|
||||
module semi_teardrop_2d(r, d) {
|
||||
module semi_teardrop(h, r, d = undef, center = true, chamfer = 0, plus = false) { //! A semi teardrop in the positive Y domain
|
||||
module semi_teardrop_2d(r, d)
|
||||
intersection() {
|
||||
R = is_undef(d) ? r : d / 2;
|
||||
teardrop(r = R, h = 0);
|
||||
teardrop(r = R, h = 0, plus = plus);
|
||||
|
||||
sq = R + 1;
|
||||
translate([-sq, 0])
|
||||
square([2 * sq, sq]);
|
||||
}
|
||||
}
|
||||
|
||||
render(convexity = 5)
|
||||
extrude_if(h, center)
|
||||
@@ -65,22 +80,21 @@ module semi_teardrop(h, r, d = undef, center = true, chamfer = 0) { //! A semi t
|
||||
teardrop_chamfer(h, center, chamfer) {
|
||||
linear_extrude(eps, center = true)
|
||||
semi_teardrop_2d(r + chamfer / 2, d);
|
||||
|
||||
translate_z(-chamfer / 2)
|
||||
linear_extrude(eps, center = true)
|
||||
semi_teardrop_2d(r, d);
|
||||
}
|
||||
}
|
||||
|
||||
module teardrop_plus(h, r, center = true, truncate = true, chamfer = 0) //! Slightly bigger teardrop to allow for the 3D printing staircase effect
|
||||
teardrop(h, r + layer_height / 4, center, truncate, chamfer);
|
||||
module teardrop_plus(h, r, center = true, truncate = true, chamfer = 0) //! Slightly elongated teardrop to allow for the 3D printing staircase effect
|
||||
teardrop(h, r, center, truncate, chamfer, plus = true);
|
||||
|
||||
module tearslot(h, r, w, center = true, chamfer = 0) { //! A horizontal slot that doesn't need support material
|
||||
module tearslot_2d(r, w) {
|
||||
hull() {
|
||||
translate([-w / 2, 0]) teardrop(r = r, h = 0);
|
||||
translate([w / 2, 0]) teardrop(r = r, h = 0);
|
||||
}
|
||||
}
|
||||
module tearslot(h, r, w, center = true, chamfer = 0, plus = false) { //! A horizontal slot that doesn't need support material
|
||||
module tearslot_2d(r, w)
|
||||
hull()
|
||||
for(x = [-1, 1])
|
||||
translate([x * w / 2, 0]) teardrop(r = r, h = 0, plus = plus);
|
||||
|
||||
extrude_if(h, center)
|
||||
tearslot_2d(r, w);
|
||||
@@ -88,19 +102,19 @@ module tearslot(h, r, w, center = true, chamfer = 0) { //! A horizontal slot tha
|
||||
teardrop_chamfer(h, center, chamfer) {
|
||||
linear_extrude(eps, center = true)
|
||||
tearslot_2d(r + chamfer / 2, w);
|
||||
|
||||
translate_z(-chamfer / 2)
|
||||
linear_extrude(eps, center = true)
|
||||
tearslot_2d(r, w);
|
||||
}
|
||||
}
|
||||
|
||||
module vertical_tearslot(h, r, l, center = true, chamfer = 0) { //! A vertical slot that doesn't need support material
|
||||
module vertical_tearslot_2d(r, l) {
|
||||
hull() {
|
||||
translate([0, l / 2]) teardrop(0, r, true);
|
||||
translate([0, -l / 2]) circle4n(r);
|
||||
}
|
||||
}
|
||||
module vertical_tearslot(h, r, l, center = true, chamfer = 0, plus = false) { //! A vertical slot that doesn't need support material
|
||||
module vertical_tearslot_2d(r, l)
|
||||
hull()
|
||||
for(y = [-1, 1])
|
||||
translate([0, y * l / 2])
|
||||
teardrop(0, r, true, plus = plus);
|
||||
|
||||
extrude_if(h, center)
|
||||
vertical_tearslot_2d(r, l);
|
||||
@@ -108,6 +122,7 @@ module vertical_tearslot(h, r, l, center = true, chamfer = 0) { //! A vertical s
|
||||
teardrop_chamfer(h, center, chamfer) {
|
||||
linear_extrude(eps, center = true)
|
||||
vertical_tearslot_2d(r + chamfer / 2, l);
|
||||
|
||||
translate_z(-chamfer / 2)
|
||||
linear_extrude(eps, center = true)
|
||||
vertical_tearslot_2d(r, l);
|
||||
@@ -123,4 +138,3 @@ module teardrop_chamfer(h, center, chamfer) { //! Helper module for adding chamf
|
||||
hull()
|
||||
children();
|
||||
}
|
||||
|
||||
|
@@ -21,6 +21,7 @@
|
||||
//! Utilities for making involute gears.
|
||||
//!
|
||||
//! Formulas from <https://khkgears.net/new/gear_knowledge/gear_technical_reference/involute_gear_profile.html>
|
||||
//! <https://khkgears.net/new/gear_knowledge/gear_technical_reference/calculation_gear_dimensions.html>
|
||||
//! and <https://www.tec-science.com/mechanical-power-transmission/involute-gear/calculation-of-involute-gears/>
|
||||
//!
|
||||
//! ```involute_gear_profile()``` returns a polygon that can have the bore and spokes, etc, subtracted from it before linear extruding it to 3D.
|
||||
@@ -32,6 +33,8 @@
|
||||
//! The clearance between tip and root defaults to module / 6, but can be overridden by setting the ```clearance``` parameter.
|
||||
//!
|
||||
//! The origin of the rack is the left end of the pitch line and its width is below the pitch line. I.e. it does not include the addendum.
|
||||
//!
|
||||
//! ```involute_worm_profile()``` returns a tooth profile that can be passed to ```thread()``` to make worms.
|
||||
//
|
||||
include <core/core.scad>
|
||||
use <maths.scad>
|
||||
@@ -40,9 +43,12 @@ function involute(r, u) = let(a = degrees(u), c = cos(a), s = sin(a)) r * [c + u
|
||||
|
||||
function profile_shift(z, pa) = z ? max(1 - z * sqr(sin(pa)) / 2, 0) : 0; //! Calculate profile shift for small gears
|
||||
|
||||
function centre_distance(m, z1, z2, pa) = //! Calculate distance between centres taking profile shift into account
|
||||
function centre_distance(m, z1, z2, pa = 20) = //! Calculate distance between centres taking profile shift into account
|
||||
let(x1 = profile_shift(z1, pa), x2 = profile_shift(z2, pa)) m * (z1/2 + z2/2 + x1 + x2);
|
||||
|
||||
function involute_gear_od(m, z, pa = 20) = //! involute gear outside diameter given modulus, tooth count and pressure angle
|
||||
m * (z + 2 * profile_shift(z, pa) + 2);
|
||||
|
||||
module involute_gear_profile(m, z, pa = 20, clearance = undef, steps = 20) { //! Calculate gear profile given module, number of teeth and pressure angle
|
||||
assert(z >= 7, "Gears must have at least 7 teeth.");
|
||||
d = m * z; // Reference pitch circle diameter
|
||||
@@ -62,7 +68,7 @@ module involute_gear_profile(m, z, pa = 20, clearance = undef, steps = 20) { //!
|
||||
base_r = base_d / 2;
|
||||
p1 = involute(base_r, 0);
|
||||
p2 = involute(base_r, umax);
|
||||
dist = norm(p2 - p1); // distance between beginning and end of the involute curve
|
||||
dist = norm(p2 - p1); // distance between beginning and end of the involute curve
|
||||
|
||||
base_angle = 2 * acos((sqr(base_r) + sqr(tip_d / 2) - sqr(dist)) / base_r / tip_d) + degrees(2 * ta);
|
||||
root_angle = 360 / z - base_angle;
|
||||
@@ -97,35 +103,36 @@ module involute_gear_profile(m, z, pa = 20, clearance = undef, steps = 20) { //!
|
||||
}
|
||||
}
|
||||
|
||||
function involute_rack_tooth_profile(m, pa = 20, clearance = undef) = //! Calculate rack tooth profile given module and pressure angle
|
||||
let(p = PI * m, // Pitch
|
||||
ha = m, // Addendum
|
||||
c = is_undef(clearance) ? m / 4 : clearance, // Tip root clearance
|
||||
hf = m + c, // Dedendum
|
||||
hw = 2 * m, // Working depth
|
||||
h = ha + hf, // Tooth depth
|
||||
crest_w = p / 2 - 2 * ha * tan(pa), // Crest width
|
||||
base_w = crest_w + 2 * hw * tan(pa), // Base width
|
||||
root_w = p - base_w, // Root width
|
||||
clearance_w = root_w - 2 * c * tan(pa), // Width of clearance without fillet
|
||||
kx = tan(pa / 2 + 45), // Fillet ratio of radius and xoffset
|
||||
pf = min(0.38 * m, kx * clearance_w / 2), // Dedendum fillet radius
|
||||
x = pf / kx, // Fillet centre x offset from corner
|
||||
sides = ceil(r2sides(pf) * (90 - pa) / 360), // Fillet facets taking $fa, $fs and $fn into account
|
||||
fillet = [ for(i = [0 : sides - 1], a = i * (90 - pa) / sides + 270) [clearance_w / 2 - x, -hf + pf] + pf * [cos(a), sin(a)] ],
|
||||
reflection = reverse([for(pt = fillet) [p - pt.x, pt.y] ]) // reflect for trailing edge
|
||||
) concat(fillet, [ [root_w / 2, -hw / 2], [p / 2 - crest_w / 2, ha], [p / 2 + crest_w / 2, ha], [p - root_w / 2, -hw / 2] ], reflection);
|
||||
|
||||
module involute_rack_profile(m, z, w, pa = 20, clearance = undef) { //! Calculate rack profile given module, number of teeth and pressure angle
|
||||
p = PI * m; // Pitch
|
||||
ha = m; // Addendum
|
||||
hf = 1.25 * m; // Dedendum
|
||||
hw = 2 * m; // Working depth
|
||||
h = ha + hf; // Tooth depth
|
||||
c = is_undef(clearance) ? m / 4 : clearance; // Tip root clearance
|
||||
crest_w = p / 2 - 2 * ha * tan(pa); // Crest width
|
||||
base_w = crest_w + 2 * hw * tan(pa); // Base width
|
||||
root_w = p - base_w; // Root width
|
||||
clearance_w = root_w - 2 * c * tan(pa); // Width of clearance without fillet
|
||||
kx = tan(pa / 2 + 45); // Fillet ratio of radius and xoffset
|
||||
pf = min(0.38 * m, kx * clearance_w / 2); // Dedendum fillet radius
|
||||
x = pf / kx; // Fillet centre x offset from corner
|
||||
|
||||
tooth = [ [root_w / 2, -hw / 2], [p / 2 - crest_w / 2, ha], [p / 2 + crest_w / 2, ha], [p - root_w / 2, -hw / 2] ];
|
||||
tooth = involute_rack_tooth_profile(m, pa, clearance);
|
||||
teeth = [for(i = [0 : z - 1], pt = tooth) [pt.x + i * p, pt.y] ];
|
||||
|
||||
difference() {
|
||||
polygon(concat([[0, -w], [0, -hf]], teeth, [[z * p, -hf ], [z * p, -w]])); // Add the corners
|
||||
|
||||
for(i = [0 : z]) // Add fillets
|
||||
hull() {
|
||||
for(side = [-1, 1])
|
||||
translate([i * p + side * (clearance_w / 2 - x), -hf + pf])
|
||||
circle(pf);
|
||||
|
||||
translate([i * p, -hw /2 + eps / 2]) // Need to extend to fillet up to meet the root at high pressure angles
|
||||
square([root_w, eps], center = true);
|
||||
}
|
||||
}
|
||||
polygon(concat([[0, -w], [0, -hf]], teeth, [[z * p, -hf ], [z * p, -w]])); // Add the corners
|
||||
}
|
||||
|
||||
function involute_worm_profile(m, pa = 20, clearance = undef) = //! Calculate worm profile suitable for passing to thread()
|
||||
let(tooth = involute_rack_tooth_profile(m),
|
||||
pitch = PI * m,
|
||||
y_min = min([for(p = tooth) p.y])
|
||||
) [for(p = tooth) [p.x - pitch / 2, p.y - y_min, 0]]; // Offset to be positive in y, centred in x and add 0 z ordintate
|
||||
|
@@ -39,11 +39,13 @@ module hanging_hole(z, ir, h = 100, h2 = 100) { //! Hole radius ```ir``` hanging
|
||||
infill_angle = z % (2 * layer_height) ? -45 : 45;
|
||||
below = min(z + eps, h2);
|
||||
big = 1000;
|
||||
|
||||
render(convexity = 3) translate_z(z)
|
||||
union() {
|
||||
translate_z(2 * layer_height)
|
||||
polyhole(ir - eps, h - 2 * layer_height);
|
||||
if(sides(ir) > 4)
|
||||
polyhole(ir - eps, h - 2 * layer_height);
|
||||
else
|
||||
poly_cylinder(ir, h - 2 * layer_height);
|
||||
|
||||
difference() {
|
||||
translate_z(-below)
|
||||
|
83
utils/horiholes.scad
Normal file
@@ -0,0 +1,83 @@
|
||||
//
|
||||
// NopSCADlib Copyright Chris Palmer 2020
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
//
|
||||
//! 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>
|
||||
|
||||
function teardrop_plus_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
|
||||
)
|
||||
max(0,
|
||||
y < hpot / sqrt(2) ? x - fr :
|
||||
y < hpot ? hpot * sqrt(2) - y - fr :
|
||||
0);
|
||||
|
||||
module horihole(r, z, h = 0, center = true) { //! For making horizontal holes 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_plus_x(r, y, layer_height);
|
||||
if(x > 0)
|
||||
translate([0, y])
|
||||
difference() {
|
||||
square([2 * x + layer_height, layer_height], center = true);
|
||||
|
||||
for(end = [-1, 1])
|
||||
translate([end * (x + layer_height / 2), 0])
|
||||
circle(d = layer_height, $fn = 32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
@@ -24,6 +24,14 @@ function sqr(x) = x * x; //! Square x
|
||||
function radians(degrees) = degrees * PI / 180; //! Convert radians to degrees
|
||||
function degrees(radians) = radians * 180 / PI; //! Convert degrees to radians
|
||||
|
||||
function sinh(x) = (exp(x) - exp(-x)) / 2; //! hyperbolic sine
|
||||
function cosh(x) = (exp(x) + exp(-x)) / 2; //! hyperbolic cosine
|
||||
function tanh(x) = sinh(x) / cosh(x); //! hyperbolic tangent
|
||||
function coth(x) = cosh(x) / sinh(x); //! hyperbolic cotangent
|
||||
function argsinh(x) = ln(x + sqrt(sqr(x) + 1)); //! inverse hyperbolic sine
|
||||
function argcosh(x) = ln(x + sqrt(sqr(x) - 1)); //! inverse hyperbolic cosine
|
||||
function argtanh(x) = ln((1 + x) / (1 - x)) / 2;//! inverse hyperbolic tangent
|
||||
function argcoth(x) = ln((x + 1) / (x - 1)) / 2;//! inverse hyperbolic cotangent
|
||||
|
||||
function translate(v) = let(u = is_list(v) ? len(v) == 2 ? [v.x, v.y, 0] //! Generate a 4x4 translation matrix, ```v``` can be ```[x, y]```, ```[x, y, z]``` or ```z```
|
||||
: v
|
||||
@@ -138,3 +146,10 @@ function invert(m) = let(n =len(m), m = solve(augment(m))) [ //! Invert a matrix
|
||||
each m[i][j]
|
||||
]
|
||||
];
|
||||
|
||||
function circle_intersect(c1, r1, c2, r2) = //! Calculate one point where two circles in the X-Z plane intersect, clockwise around c1
|
||||
let(
|
||||
v = c1 - c2, // Line between centres
|
||||
d = norm(v), // Distance between centres
|
||||
a = atan2(v.z, v.x) - acos((sqr(d) + sqr(r2) - sqr(r1)) / (2 * d * r2)) // Cosine rule to find angle from c2
|
||||
) c2 + r2 * [cos(a), 0, sin(a)]; // Point on second circle
|
||||
|
@@ -23,18 +23,21 @@
|
||||
include <../utils/core/core.scad>
|
||||
|
||||
module quadrant(w, r, center = false) { //! Draw a square with one rounded corner, can be centered on the arc centre, when ```center``` is ```true```.
|
||||
offset = center ? r - w : 0;
|
||||
translate([offset, offset])
|
||||
h = is_list(w) ? w.y : w;
|
||||
w = is_list(w) ? w.x : w;
|
||||
offset_w = center ? r - w : 0;
|
||||
offset_h = center ? r - h : 0;
|
||||
translate([offset_w, offset_h])
|
||||
hull() {
|
||||
intersection() {
|
||||
translate([w - r, w - r])
|
||||
translate([w - r, h - r])
|
||||
circle4n(r);
|
||||
|
||||
square(w);
|
||||
square([w, h]);
|
||||
}
|
||||
|
||||
square([w, eps]);
|
||||
|
||||
square([eps, w]);
|
||||
square([eps, h]);
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -49,7 +49,7 @@ function thread_profile(h, crest, angle, overlap = 0.1) = //! Create thread prof
|
||||
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]];
|
||||
|
||||
module thread(dia, pitch, length, profile, center = true, top = -1, bot = -1, starts = 1, solid = true, female = false, colour = undef) { //! Create male or femail thread, ends can be tapered, chamfered or square
|
||||
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
|
||||
//
|
||||
// Apply colour if defined
|
||||
//
|
||||
|
@@ -31,3 +31,41 @@ module ring(or, ir) //! Create a ring with specified external and internal radii
|
||||
module tube(or, ir, h, center = true) //! Create a tube with specified external and internal radii and height ```h```
|
||||
linear_extrude(h, center = center, convexity = 5)
|
||||
ring(or, ir);
|
||||
|
||||
module woven_tube(or, ir, h, center= true, colour = grey(30), colour2, warp = 2, weft) {//! Create a woven tube with specified external and internal radii, height ```h```, colours, warp and weft
|
||||
colour2 = colour2 ? colour2 : colour * 0.8;
|
||||
weft = weft ? weft : warp;
|
||||
warp_count = max(floor(PI * or / warp), 0.5);
|
||||
angle = 360 / (2 * warp_count);
|
||||
|
||||
module layer(weft) {
|
||||
points = [[ir, weft / 2], [or, weft / 2], [or, -weft / 2], [ir, -weft / 2]];
|
||||
color(colour)
|
||||
for (i = [0 : warp_count])
|
||||
rotate(2 * i * angle)
|
||||
rotate_extrude(angle = angle)
|
||||
polygon(points);
|
||||
color(colour2)
|
||||
for (i = [0 : warp_count])
|
||||
rotate((2 * i + 1) * angle)
|
||||
rotate_extrude(angle = angle)
|
||||
polygon(points);
|
||||
}
|
||||
|
||||
translate_z(center ? -h / 2 : 0) {
|
||||
weft_count = floor(h / weft);
|
||||
if (weft_count > 0)
|
||||
for (i = [0 : weft_count - 1]) {
|
||||
translate_z(i * weft + weft / 2)
|
||||
rotate(i * angle)
|
||||
layer(weft);
|
||||
}
|
||||
remainder = h - weft * weft_count;
|
||||
if (remainder) {
|
||||
translate_z(weft_count * weft + remainder / 2)
|
||||
rotate(weft_count * angle)
|
||||
layer(remainder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -24,6 +24,7 @@ include <../utils/core/core.scad>
|
||||
include <../utils/round.scad>
|
||||
|
||||
module wire_link(d, l, h = 1, tail = 3) { //! Draw a wire jumper link.
|
||||
vitamin(str("wire_link(", d, ", ", l, arg(h, 1, "h"), arg(tail, 3, "tail"), "): Wire link ", d, "mm x ", l / inch(1), "\""));
|
||||
r = d;
|
||||
$fn = 32;
|
||||
|
||||
@@ -57,13 +58,16 @@ module orientate_axial(length, height, pitch, wire_d) { // Orient horizontal or
|
||||
min_pitch = ceil((length + 1) / inch(0.1)) * inch(0.1);
|
||||
lead_pitch = pitch ? pitch : min_pitch;
|
||||
if(lead_pitch >= min_pitch) {
|
||||
wire_link(wire_d, lead_pitch, height);
|
||||
not_on_bom()
|
||||
wire_link(wire_d, lead_pitch, height);
|
||||
|
||||
translate_z(height)
|
||||
rotate([0, 90, 0])
|
||||
children();
|
||||
}
|
||||
else {
|
||||
wire_link(wire_d, lead_pitch, length + 0.7 + wire_d);
|
||||
not_on_bom()
|
||||
wire_link(wire_d, lead_pitch, length + 0.7 + wire_d);
|
||||
|
||||
translate([-pitch / 2, 0, length / 2 + 0.2])
|
||||
children();
|
||||
|
@@ -52,21 +52,21 @@ module ball_bearing(type) { //! Draw a ball bearing
|
||||
rim_chamfer = rim / 6;
|
||||
rotate_extrude()
|
||||
hull() {
|
||||
translate([or - rim / 2, 0])
|
||||
square([rim, h - 2 * rim_chamfer], center = true);
|
||||
translate([or - rim, -h / 2 + rim_chamfer])
|
||||
square([rim, h - 2 * rim_chamfer]);
|
||||
|
||||
translate([or - rim / 2 - rim_chamfer, 0])
|
||||
square([rim - rim_chamfer, h], center = true);
|
||||
translate([or - rim, -h / 2])
|
||||
square([rim - rim_chamfer, h]);
|
||||
}
|
||||
|
||||
hub_chamfer = hub / 6;
|
||||
rotate_extrude()
|
||||
hull() {
|
||||
translate([ir + hub / 2, 0])
|
||||
square([hub, h - 2 * hub_chamfer], center = true);
|
||||
translate([ir, -h / 2 + hub_chamfer])
|
||||
square([hub, h - 2 * hub_chamfer]);
|
||||
|
||||
translate([ir + hub / 2 + hub_chamfer, 0])
|
||||
square([hub - hub_chamfer, h], center = true);
|
||||
translate([ir + hub_chamfer, -h / 2])
|
||||
square([hub - hub_chamfer, h]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -24,29 +24,31 @@
|
||||
//! To make the back of the belt run against a smooth pulley on the outside of the loop specify a negative pitch radius.
|
||||
//!
|
||||
//! By default the path is a closed loop but a gap length and position can be specified to make open loops.
|
||||
//! To draw the gap its XY position is specified by ```gap_pos```. ```gap_pos.z``` can be used to specify a rotation if the gap is not at the bottom of the loop.
|
||||
//!
|
||||
//! Individual teeth are not drawn, instead they are represented by a lighter colour.
|
||||
//
|
||||
include <../utils/core/core.scad>
|
||||
use <../utils/rounded_polygon.scad>
|
||||
use <../utils/maths.scad>
|
||||
|
||||
function belt_pitch(type) = type[1]; //! Pitch in mm
|
||||
function belt_width(type) = type[2]; //! Width in mm
|
||||
function belt_thickness(type) = type[3]; //! Total thickness including teeth
|
||||
function belt_tooth_height(type) = type[4]; //! Tooth height
|
||||
function belt_pitch_height(type) = belt_tooth_height(type) + type[4]; //! Offset of the pitch radius from the tips of the teeth
|
||||
function belt_pitch_height(type) = type[5] + belt_tooth_height(type); //! Offset of the pitch radius from the tips of the teeth
|
||||
|
||||
function no_point(str) = chr([for(c = str) if(c == ".") ord("p") else ord(c)]);
|
||||
function belt_pitch_to_back(type) = belt_thickness(type) - belt_pitch_height(type); //! Offset of the back from the pitch radius
|
||||
//
|
||||
// We model the belt path at the pitch radius of the pulleys and the pitch line of the belt to get an accurate length.
|
||||
// The belt is then drawn by offseting each side from the pitch line.
|
||||
//
|
||||
module belt(type, points, gap = 0, gap_pt = undef, belt_colour = grey(20), tooth_colour = grey(50)) { //! Draw a belt path given a set of points and pitch radii where the pulleys are. Closed loop unless a gap is specified
|
||||
module belt(type, points, gap = 0, gap_pos = undef, belt_colour = grey(20), tooth_colour = grey(50)) { //! Draw a belt path given a set of points and pitch radii where the pulleys are. Closed loop unless a gap is specified
|
||||
width = belt_width(type);
|
||||
pitch = belt_pitch(type);
|
||||
thickness = belt_thickness(type);
|
||||
part = str(type[0],pitch);
|
||||
vitamin(str("belt(", no_point(part), "x", width, ", ", points, arg(gap, 0), arg(gap_pt, undef), "): Belt ", part," x ", width, "mm x ", length, "mm"));
|
||||
vitamin(str("belt(", no_point(part), "x", width, ", ", points, arg(gap, 0), arg(gap_pos, undef), "): Belt ", part," x ", width, "mm x ", length, "mm"));
|
||||
|
||||
len = len(points);
|
||||
|
||||
@@ -56,24 +58,28 @@ module belt(type, points, gap = 0, gap_pt = undef, belt_colour = grey(20), tooth
|
||||
|
||||
module shape() rounded_polygon(points, tangents);
|
||||
|
||||
ph = belt_pitch_height(type);
|
||||
th = belt_tooth_height(type);
|
||||
module gap()
|
||||
if(gap)
|
||||
translate(gap_pt)
|
||||
square([gap, thickness + eps], center = true);
|
||||
translate([gap_pos.x, gap_pos.y])
|
||||
rotate(is_undef(gap_pos.z) ? 0 : gap_pos.z)
|
||||
translate([0, ph - thickness / 2])
|
||||
square([gap, thickness + eps], center = true);
|
||||
|
||||
color(belt_colour)
|
||||
linear_extrude(width, center = true)
|
||||
difference() {
|
||||
offset(thickness - belt_pitch_height(type)) shape();
|
||||
offset(-belt_pitch_height(type) + belt_tooth_height(type)) shape();
|
||||
offset(-ph + thickness ) shape();
|
||||
offset(-ph + th) shape();
|
||||
gap();
|
||||
|
||||
}
|
||||
|
||||
color(tooth_colour)
|
||||
linear_extrude(width, center = true)
|
||||
difference() {
|
||||
offset(-belt_pitch_height(type) + belt_tooth_height(type)) shape();
|
||||
offset(-belt_pitch_height(type)) shape();
|
||||
offset(-ph + th) shape();
|
||||
offset(-ph) shape();
|
||||
gap();
|
||||
}
|
||||
}
|
||||
|
@@ -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.
|
||||
|
@@ -161,13 +161,13 @@ module al_clad_resistor(type, value, leads = true) { //! Draw an aluminium clad
|
||||
}
|
||||
linear_extrude(thickness)
|
||||
difference() {
|
||||
for(end = [-1, 1])
|
||||
translate([end * (length - tab) / 2, end * (width - width / 2) / 2])
|
||||
square([tab, width / 2], center = true);
|
||||
union()
|
||||
for(end = [-1, 1])
|
||||
translate([end * (length - tab) / 2, end * (width - width / 2) / 2])
|
||||
square([tab, width / 2], center = true);
|
||||
|
||||
al_clad_resistor_hole_positions(type)
|
||||
circle(d = al_clad_hole(type));
|
||||
|
||||
}
|
||||
if(leads) {
|
||||
translate_z(height / 2)
|
||||
|
@@ -17,28 +17,28 @@
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
// w d b h s h t o b b a
|
||||
// i e o o c u h u l o p
|
||||
// d p r l r b i t a s p
|
||||
// t t e e e c e d s e
|
||||
// h h w d k r e r
|
||||
// p i n s d t
|
||||
// i a e d u
|
||||
// t s i r
|
||||
// c s a e
|
||||
// h
|
||||
// w d b h s h t o b b a
|
||||
// i e o o c u h u l o p
|
||||
// d p r l r b i t a s p
|
||||
// t t e e e c e d s e
|
||||
// h h w d k r e r
|
||||
// p i n s d t
|
||||
// i a e d u
|
||||
// t s i r
|
||||
// c s a e
|
||||
// h
|
||||
//
|
||||
fan120x25= [120,25, 116,52.5, M4_dome_screw, 41, 4, 140, 9, 0, 137];
|
||||
fan80x38 = [80, 38, 75, 35.75, M4_dome_screw, 40, 4.3, 84, 7, 0, 85];
|
||||
fan80x25 = [80, 25, 75, 35.75, M4_dome_screw, 40, 4.3, 84, 7, 0, 85];
|
||||
fan70x15 = [70, 15, 66, 30.75, M4_dome_screw, 29, 3.8, 70 ,7, 0, undef];
|
||||
fan60x25 = [60, 25, 57, 25, M4_dome_screw, 31.5, 3.6, 64, 7, 0, 63];
|
||||
fan60x15 = [60, 15, 57, 25, M4_dome_screw, 29, 2.4, 60, 7, 7.7, 63];
|
||||
fan50x15 = [50, 15, 48, 20, M4_dome_screw, 25, 12.5,100,7, 0, undef];
|
||||
fan40x11 = [40, 11, 37, 16, M3_dome_screw, 25, 7.5,100, 9, 0, undef];
|
||||
fan30x10 = [30, 10, 27, 12, M3_dome_screw, 17, 10, 100, 5, 0, undef];
|
||||
fan25x10 = [25, 10, 24, 10, M2p5_pan_screw, 16, 10, 100, 5, 0, undef];
|
||||
fan17x8 = [17, 8, 16, 6.75, M2_cap_screw, 12.6, 8, 100, 7, 0, undef];
|
||||
fan120x25= [120, 25, 116,52.5, M4_dome_screw, 41, 4, 140, 9, 0, 137];
|
||||
fan80x38 = [80, 38, 75, 35.75, M4_dome_screw, 40, 4.3, 84, 7, 0, 85];
|
||||
fan80x25 = [80, 25, 75, 35.75, M4_dome_screw, 40, 4.3, 84, 7, 0, 85];
|
||||
fan70x15 = [70, 15, 66, 30.75, M4_dome_screw, 29, 3.8, 70 ,7, 0, undef];
|
||||
fan60x25 = [60, 25, 57, 25, M4_dome_screw, 31.5, 3.6, 64, 7, 0, 63];
|
||||
fan60x15 = [60, 15, 57, 25, M4_dome_screw, 29, 2.4, 60, 7, 7.7, 63];
|
||||
fan50x15 = [50, 15, 48, 20, M4_dome_screw, 25, 12.5,100, 7, 0, undef];
|
||||
fan40x11 = [40, 11, 37, 16, M3_dome_screw, 25, 7.5,100, 9, 0, undef];
|
||||
fan30x10 = [30, 10, 27, 12, M3_dome_screw, 17, 10, 100, 5, 0, undef];
|
||||
fan25x10 = [25.4,10, 24, 10, M2p5_pan_screw, 16, 10, 100, 5, 0, undef];
|
||||
fan17x8 = [17, 8, 16, 6.75, M2_cap_screw, 12.6, 8, 100, 7, 0, undef];
|
||||
|
||||
fans = [fan17x8, fan25x10, fan30x10, fan40x11, fan50x15, fan60x15, fan60x25, fan70x15, fan80x25, fan80x38, fan120x25];
|
||||
|
||||
|
@@ -33,8 +33,7 @@
|
||||
// h t s t t t
|
||||
// h
|
||||
//
|
||||
JHeadMk4 = ["JHeadMk4", jhead, "JHead MK4", 64, 5.1, 16, 50, grey(20), 12, 4.64, 14, [0, 2.94, -5], 20, 20];
|
||||
JHeadMk5 = ["JHeadMk5", jhead, "JHead MK5", 51.2, 5.1, 16, 40, grey(20), 12, 4.64, 13, [0, 2.38, -5], 20, 20];
|
||||
JHeadMk5 = ["JHeadMk5", jhead, "JHead MK5", 51.2, 4.75,16, 40, grey(20), 12, 4.64, 13, [0, 2.38, -5], 20, 20];
|
||||
E3Dv5 = ["E3Dv5", e3d, "E3D V5 direct", 70, 3.7, 16, 50.1, "silver", 12, 6, 15, [1, 5, -4.5], 14.5, 28];
|
||||
E3Dv6 = ["E3Dv6", e3d, "E3D V6 direct", 62, 3.7, 16, 42.7, "silver", 12, 6, 15, [1, 5, -4.5], 14, 21];
|
||||
E3D_clone = ["E3D_clone", e3d, "E3D clone aliexpress",66, 6.8, 16, 46, "silver", 12, 5.6, 15, [1, 5, -4.5], 14.5, 21];
|
||||
|
@@ -24,17 +24,26 @@ include <../utils/core/core.scad>
|
||||
use <../utils/quadrant.scad>
|
||||
use <../utils/thread.scad>
|
||||
|
||||
function insert_length(type) = type[1]; //! Length
|
||||
function insert_outer_d(type) = type[2]; //! Outer diameter at the top
|
||||
function insert_length(type) = type[1]; //! Length
|
||||
function insert_outer_d(type) = type[2]; //! Outer diameter at the top
|
||||
function insert_hole_radius(type) = type[3] / 2; //! Radius of the required hole in the plastic
|
||||
function insert_screw_diameter(type) = type[4]; //! Screw size
|
||||
function insert_barrel_d(type) = type[5]; //! Diameter of the main barrel
|
||||
function insert_ring1_h(type) = type[6]; //! Height of the top and middle rings
|
||||
function insert_ring2_d(type) = type[7]; //! Diameter of the middle ring
|
||||
function insert_ring3_d(type) = type[8]; //! Diameter of the bottom ring
|
||||
function insert_screw_diameter(type) = type[4]; //! Screw size
|
||||
function insert_barrel_d(type) = type[5]; //! Diameter of the main barrel
|
||||
function insert_ring1_h(type) = type[6]; //! Height of the top and middle rings
|
||||
function insert_ring2_d(type) = type[7]; //! Diameter of the middle ring
|
||||
function insert_ring3_d(type) = type[8]; //! Diameter of the bottom ring
|
||||
|
||||
function insert_hole_length(type) = round_to_layer(insert_length(type));
|
||||
|
||||
function insert_nose_length(type, d) = let( //! The length before the second ring.
|
||||
length = insert_length(type),
|
||||
ring1_h = insert_ring1_h(type),
|
||||
chamfer1 = (insert_ring2_d(type) - insert_barrel_d(type)) / 2,
|
||||
chamfer2 = (insert_ring3_d(type) - insert_barrel_d(type)) / 2,
|
||||
ring2_h = ring1_h + chamfer1,
|
||||
gap = (length - ring1_h - ring2_h - chamfer2) / 3
|
||||
) ring1_h + gap + ring2_h - d + insert_barrel_d(type);
|
||||
|
||||
module insert(type) { //! Draw specified insert
|
||||
length = insert_length(type);
|
||||
ring1_h = insert_ring1_h(type);
|
||||
@@ -42,12 +51,12 @@ module insert(type) { //! Draw specified insert
|
||||
chamfer1 = (insert_ring2_d(type) - insert_barrel_d(type)) / 2;
|
||||
chamfer2 = (insert_ring3_d(type) - insert_barrel_d(type)) / 2;
|
||||
ring2_h = ring1_h + chamfer1;
|
||||
gap = (length - ring1_h - ring2_h- chamfer2) / 3;
|
||||
gap = (length - ring1_h - ring2_h - chamfer2) / 3;
|
||||
|
||||
vitamin(str("insert(", type[0], "): Heatfit insert M", insert_screw_diameter(type)));
|
||||
$fn = 64;
|
||||
thread_d = insert_screw_diameter(type);
|
||||
explode(20, offset =[0, 0, -5]) translate_z(eps) vflip() {
|
||||
explode(20, offset = [0, 0, -5]) translate_z(eps) vflip() {
|
||||
r1 = thread_d / 2;
|
||||
r2 = insert_barrel_d(type) / 2;
|
||||
r3 = insert_ring3_d(type) / 2;
|
||||
@@ -58,7 +67,7 @@ module insert(type) { //! Draw specified insert
|
||||
h3 = ring1_h + gap + ring2_h;
|
||||
h4 = ring1_h + gap + ring2_h + gap;
|
||||
color(brass)
|
||||
rotate_extrude()
|
||||
rotate_extrude(convexity = 3)
|
||||
polygon([
|
||||
[r1, 0],
|
||||
[r1, length],
|
||||
@@ -128,19 +137,26 @@ module insert_lug(insert, wall, counter_bore = 0, extension = 0, corner_r = 0, f
|
||||
boss_h = insert_hole_length(insert);
|
||||
boss_h2 = boss_h + counter_bore;
|
||||
|
||||
module shape()
|
||||
intersection() {
|
||||
module shape() {
|
||||
module _shape()
|
||||
hull() {
|
||||
circle(boss_r);
|
||||
|
||||
translate([boss_r + extension - eps, 0])
|
||||
square([eps, 2 * boss_r], center = true);
|
||||
}
|
||||
if(corner_r)
|
||||
|
||||
if(corner_r)
|
||||
intersection() {
|
||||
_shape();
|
||||
|
||||
translate([boss_r + extension - corner_r, 0])
|
||||
rotate(-45)
|
||||
quadrant(w = 100, r = corner_r - eps, center = true);
|
||||
}
|
||||
}
|
||||
else
|
||||
_shape();
|
||||
}
|
||||
|
||||
translate_z(-boss_h)
|
||||
linear_extrude(boss_h)
|
||||
|
@@ -29,7 +29,7 @@
|
||||
// d d h d d
|
||||
// d
|
||||
//
|
||||
F1BM2 = [ "F1BM", 4.0, 3.6, 3.2, 2, 3.0, 1.0, 3.4, 3.1 ];
|
||||
F1BM2 = [ "F1BM2", 4.0, 3.6, 3.2, 2, 3.0, 1.0, 3.4, 3.1 ];
|
||||
F1BM2p5 = [ "F1BM2p5", 5.8, 4.6, 4.0, 2.5, 3.65, 1.6, 4.4, 3.9 ];
|
||||
F1BM3 = [ "F1BM3", 5.8, 4.6, 4.0, 3, 3.65, 1.6, 4.4, 3.9 ];
|
||||
F1BM4 = [ "F1BM4", 8.2, 6.3, 5.6, 4, 5.15, 2.3, 6.0, 5.55 ];
|
||||
|
@@ -29,7 +29,6 @@ include <zipties.scad>
|
||||
use <wire.scad>
|
||||
use <../utils/tube.scad>
|
||||
|
||||
MK4_heater = [ 12.76, 15.88, 8.22, (15.88 / 2 - 4.5), (12.76 / 2 - 0.5 - 2.5 / 2), (-15.88 / 2 + 5), 9.5, 3];
|
||||
MK5_heater = [ 12.76, 12.76, 8.22, (12.76 / 2 - 3.75), (12.76 / 2 - 0.5 - 2.5 / 2), (-12.76 / 2 + 4), 8, 2];
|
||||
|
||||
function heater_width(type) = type[0];
|
||||
@@ -71,7 +70,7 @@ module heater_block(type, resistor, thermistor) {
|
||||
cone_start_r = nozzle_cone(type) / 2;
|
||||
straight = 1;
|
||||
nozzle_r = 0.4 / 2;
|
||||
translate_z(-h / 2) vflip()
|
||||
translate([nozzle_x(type), 0, -h / 2]) vflip()
|
||||
rotate_extrude()
|
||||
polygon([
|
||||
[nozzle_r, 0],
|
||||
@@ -86,7 +85,7 @@ module heater_block(type, resistor, thermistor) {
|
||||
module jhead_hot_end(type, filament) {
|
||||
resistor = RIE1212UB5C5R6;
|
||||
thermistor = Epcos;
|
||||
heater = type == JHeadMk4 ? MK4_heater : MK5_heater;
|
||||
heater = MK5_heater;
|
||||
|
||||
insulator_length = hot_end_insulator_length(type);
|
||||
inset = hot_end_inset(type);
|
||||
@@ -106,7 +105,7 @@ module jhead_hot_end(type, filament) {
|
||||
|
||||
square([hot_end_insulator_diameter(type) / 2 - chamfer, insulator_length]);
|
||||
}
|
||||
square([3.2 / 2, insulator_length]);
|
||||
square([(filament + 0.2) / 2, insulator_length]);
|
||||
|
||||
translate([hot_end_groove_dia(type) / 2, insulator_length - hot_end_inset(type) - hot_end_groove(type)])
|
||||
square([100, hot_end_groove(type)]);
|
||||
@@ -122,7 +121,7 @@ module jhead_hot_end(type, filament) {
|
||||
module jhead_hot_end_assembly(type, filament, naked = false) { //! Assembly with resistor, thermistor, tape, sleaving and ziptie
|
||||
resistor = RIE1212UB5C5R6;
|
||||
thermistor = Epcos;
|
||||
heater = type == JHeadMk4 ? MK4_heater : MK5_heater;
|
||||
heater = MK5_heater;
|
||||
|
||||
insulator_length = hot_end_insulator_length(type);
|
||||
inset = hot_end_inset(type);
|
||||
@@ -139,7 +138,7 @@ module jhead_hot_end_assembly(type, filament, naked = false) { //! Assembly with
|
||||
//
|
||||
// silcone tape
|
||||
//
|
||||
if(!naked)
|
||||
if(is_undef(naked) || !naked)
|
||||
color("red")
|
||||
if(exploded())
|
||||
translate([0, max(hot_end_insulator_diameter(type) / 2, heater_length(heater) / 2 - nozzle_x(heater)),
|
||||
@@ -157,7 +156,7 @@ module jhead_hot_end_assembly(type, filament, naked = false) { //! Assembly with
|
||||
//
|
||||
// Zip tie and heatshrink
|
||||
//
|
||||
if(!naked)
|
||||
if(!naked && !is_undef(naked))
|
||||
rotate(10) {
|
||||
dia = hot_end_insulator_diameter(type);
|
||||
scale([1, (bundle + dia) / dia])
|
||||
@@ -180,23 +179,27 @@ module jhead_hot_end_assembly(type, filament, naked = false) { //! Assembly with
|
||||
//
|
||||
// heater block
|
||||
//
|
||||
rotate(90)
|
||||
translate([-nozzle_x(heater), 0, inset - insulator_length - heater_height(heater) / 2]) {
|
||||
intersection() {
|
||||
group() {
|
||||
translate([resistor_x(heater), -exploded() * 15, 0])
|
||||
rotate([90, 0, 0])
|
||||
sleeved_resistor(resistor, PTFE20, bare = -10);
|
||||
module heater_components() {
|
||||
translate([resistor_x(heater), -exploded() * 15, 0])
|
||||
rotate([90, 0, 0])
|
||||
sleeved_resistor(resistor, PTFE20, bare = -10);
|
||||
|
||||
translate([-heater_length(heater) / 2 + resistor_length(thermistor) / 2 - exploded() * 10, thermistor_y(heater), 0])
|
||||
rotate([90, 0, -90])
|
||||
sleeved_resistor(thermistor, PTFE07, heatshrink = HSHRNK16);
|
||||
}
|
||||
|
||||
rotate(90)
|
||||
translate([-nozzle_x(heater), 0, inset - insulator_length - heater_height(heater) / 2])
|
||||
if(exploded())
|
||||
heater_components();
|
||||
else
|
||||
intersection() {
|
||||
heater_components();
|
||||
|
||||
translate([-heater_length(heater) / 2 + resistor_length(thermistor) / 2 - exploded() * 10, thermistor_y(heater), 0])
|
||||
rotate([90, 0, -90])
|
||||
sleeved_resistor(thermistor, PTFE07, heatshrink = HSHRNK16);
|
||||
}
|
||||
if(!exploded())
|
||||
if(naked)
|
||||
color("grey") cylinder(r = 12, h = 100, center = true);
|
||||
else
|
||||
cube(1, true); // hide the wires when not exploded
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -85,7 +85,8 @@ module meter(type, colour = "red", value = "888", display_colour = false) //! Dr
|
||||
translate([0, meter_shunt_y(type), size.z])
|
||||
vflip()
|
||||
color("#b87333")
|
||||
wire_link(shunt.y, shunt.x, shunt.z, tail = 2);
|
||||
not_on_bom()
|
||||
wire_link(shunt.y, shunt.x, shunt.z, tail = 2);
|
||||
}
|
||||
|
||||
clearance = 0.1;
|
||||
|
49
vitamins/magnet.scad
Normal file
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// NopSCADlib Copyright Chris Palmer 2020
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
//
|
||||
//! Cylindrical and ring magnets.
|
||||
//
|
||||
include <../utils/core/core.scad>
|
||||
|
||||
function magnet_od(type) = type[1]; //! Outer diameter
|
||||
function magnet_id(type) = type[2]; //! Inside diameter if a ring
|
||||
function magnet_h(type) = type[3]; //! Height
|
||||
function magnet_r(type) = type[4]; //! Corner radius
|
||||
|
||||
module magnet(type) { //! Draw specified magnet
|
||||
od = magnet_od(type);
|
||||
id = magnet_id(type);
|
||||
h = magnet_h(type);
|
||||
r = magnet_r(type);
|
||||
|
||||
//vitamin(str("magnet(", type[0], "): Magnet ", od, "mm diameter, ", h, "mm high", id ? str(", ", id, "mm bore") : "" ));
|
||||
|
||||
or = od / 2;
|
||||
ir = id / 2;
|
||||
color(silver)
|
||||
rotate_extrude()
|
||||
union() {
|
||||
translate([ir, 0])
|
||||
rounded_square([or - ir, h], r, center = false);
|
||||
if(!ir)
|
||||
square([r, h]);
|
||||
}
|
||||
|
||||
}
|
30
vitamins/magnets.scad
Normal file
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// NopSCADlib Copyright Chris Palmer 2020
|
||||
// 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/>.
|
||||
//
|
||||
//
|
||||
//! Cylindrical and ring magnets.
|
||||
//
|
||||
|
||||
// od, id, h, r
|
||||
MAG8x4x4p2 = ["MAG8x4x4p2", 8, 4.2, 4, 0.5];
|
||||
MAG484 = ["MAG484", inch(1/4), inch(1/8), inch(1/4), 0.5];
|
||||
MAG5x8 = ["MAG484", 8, 0, 5, 0.5];
|
||||
|
||||
magnets = [MAG8x4x4p2, MAG484, MAG5x8];
|
||||
|
||||
use <magnet.scad>
|
@@ -24,27 +24,44 @@
|
||||
//
|
||||
include <../utils/core/core.scad>
|
||||
use <../utils/thread.scad>
|
||||
use <pcb.scad>
|
||||
include <smds.scad>
|
||||
|
||||
pitch = 33.8;
|
||||
pitch = 33.8 / 2;
|
||||
width = 40;
|
||||
depth = 18;
|
||||
magnet = 4.3;
|
||||
pcb = 0.8;
|
||||
pillar = 6;
|
||||
target = 1;
|
||||
pole_w = 2;
|
||||
pole_l = 36;
|
||||
poles = 15;
|
||||
|
||||
pcb = ["", "", width, width, 0.8, 0, 3.5, 0, "darkgreen", false, [],
|
||||
[ [ 3.45, 19, 0, "button_4p5mm"],
|
||||
[ 2.75, 24.5, 0, "smd_led", LED0805, "green"],
|
||||
[ 2.75, 28.0, 0, "smd_led", LED0805, "red"],
|
||||
[ 28.5, 13, 0, "2p54header", 3, 1, false, undef, true],
|
||||
]];
|
||||
|
||||
|
||||
module opengrab_hole_positions() //! Position children at the screw positions
|
||||
for(x = [-1, 1], y = [-1, 1])
|
||||
translate([x * pitch / 2, y * pitch / 2, 0])
|
||||
children();
|
||||
let($d = 3.2)
|
||||
for($x = [-pitch, pitch], $y = [-pitch, pitch])
|
||||
translate([$x, $y])
|
||||
children();
|
||||
|
||||
module opengrab_side_hole_positions() //! Position children at the two 4mm hole
|
||||
let($d = 4, pitch = width / 2 - 3.5)
|
||||
for($x = [-pitch, pitch])
|
||||
translate([$x, 0])
|
||||
children();
|
||||
|
||||
function opengrab_width() = width; //! Module width
|
||||
function opengrab_depth() = depth; //! Module height
|
||||
function opengrab_target_thickness() = target; //! Target sheet thickness
|
||||
function opengrab_width() = width; //! Module width
|
||||
function opengrab_depth() = depth; //! Module height
|
||||
function opengrab_target_thickness() = target; //! Target sheet thickness
|
||||
function opengrab_pcb() = pcb; //! The PCB
|
||||
function opengrab_pcb_z() = depth - pillar - pcb_thickness(pcb); //! PCB offset from the front
|
||||
|
||||
module opengrab() { //! Draw OpenGrab module
|
||||
vitamin("opengrab(): OpenGrab V3 electro permanent magnet");
|
||||
@@ -61,10 +78,9 @@ module opengrab() { //! Draw OpenGrab module
|
||||
cube([pole_w, pole_l, 1], center = true);
|
||||
}
|
||||
|
||||
color("darkgreen")
|
||||
translate_z(depth - pillar - pcb / 2)
|
||||
cube([width, width, pcb], center = true);
|
||||
|
||||
not_on_bom()
|
||||
translate_z(opengrab_pcb_z())
|
||||
pcb(pcb);
|
||||
|
||||
translate_z(1)
|
||||
opengrab_hole_positions() {
|
||||
@@ -82,7 +98,7 @@ module opengrab() { //! Draw OpenGrab module
|
||||
}
|
||||
|
||||
module opengrab_target() { //! Draw OpenGrab target
|
||||
vitamin("opengrab_target(): OpenGrab silicon steel target plate");
|
||||
vitamin("opengrab_target(): OpenGrab silicon steel target plate");
|
||||
|
||||
color(grey(80))
|
||||
linear_extrude(target)
|
||||
@@ -90,10 +106,9 @@ module opengrab_target() { //! Draw OpenGrab target
|
||||
square([width, width], center = true);
|
||||
|
||||
opengrab_hole_positions()
|
||||
circle(d = 3.2);
|
||||
circle(d = $d);
|
||||
|
||||
for(side = [-1, 1])
|
||||
translate([side * (width / 2 - 3.5), 0])
|
||||
circle(d = 4);
|
||||
opengrab_side_hole_positions()
|
||||
circle(d = $d);
|
||||
}
|
||||
}
|
||||
|
@@ -77,7 +77,6 @@ module panel_meter(type) { //! Draw panel mounted LCD meter module
|
||||
tab_z = pmeter_tab_z(type);
|
||||
pcb = pmeter_pcb(type);
|
||||
ap2 = pmeter_inner_ap(type);
|
||||
pcb_h = pmeter_pcb_h(type) - bezel.z;
|
||||
buttons = pmeter_buttons(type);
|
||||
|
||||
color("#94A7AB")
|
||||
@@ -146,15 +145,16 @@ module panel_meter(type) { //! Draw panel mounted LCD meter module
|
||||
translate(pmeter_inner_ap_o(type))
|
||||
square([ap2.x, ap2.y], center = true);
|
||||
}
|
||||
if(pcb)
|
||||
if(pcb) {
|
||||
vflip()
|
||||
translate_z(h - pcb_thickness(pcb) - pmeter_pcb_z(type))
|
||||
pcb(pcb);
|
||||
|
||||
if(pcb_h > 0)
|
||||
%translate_z(-pcb_h / 2 - eps)
|
||||
cube([size.x - 2 * t - eps, size.y - 2 * t - eps, pcb_h], center = true);
|
||||
|
||||
pcb_h = pmeter_pcb_h(type) - bezel.z;
|
||||
if(pcb_h > 0)
|
||||
%translate_z(-pcb_h / 2 - eps)
|
||||
cube([size.x - 2 * t - eps, size.y - 2 * t - eps, pcb_h], center = true);
|
||||
}
|
||||
if(buttons)
|
||||
for(b = buttons)
|
||||
panel_meter_button(b);
|
||||
|
@@ -41,10 +41,10 @@ DSP5005 = ["DSP5005", "Ruideng DSP5005 Power supply module", [7
|
||||
[[-25, 9, 0], [ 6.5, 4.5, 1], 0.5, "yellow"],
|
||||
]];
|
||||
|
||||
DSN_VC288PCB = ["", "", 41, 21, 1, 0, 0, 0, "green", false, [], [[ 5, -3, 0, "jst_xh", 3], ], []];
|
||||
DSN_VC288PCB = ["", "", 41, 21, 1, 0, 0, 0, "green", false, [], [[ 5, -3.525, 0, "jst_xh", 3], ], []];
|
||||
|
||||
DSN_VC288 = ["DSN_VC288","DSN-VC288 DC 100V 10A Voltmeter ammeter", [45.3, 26, 17.4], [47.8, 28.8, 2.5], 0, [1, 1.8], [36, 18, 2.5], [], 0, 2,
|
||||
[], 0, DSN_VC288PCB, 5];
|
||||
[], 0, DSN_VC288PCB, 5, 0];
|
||||
|
||||
panel_meters = [DSN_VC288, PZEM021, PZEM001, DSP5005];
|
||||
|
||||
|
@@ -333,8 +333,9 @@ function hdmi_height2(type) = type[6]; //! Inside height in the middle
|
||||
function hdmi_height(type) = type[7]; //! Outside height above the PCB
|
||||
function hdmi_thickness(type) = type[8]; //! Wall thickness of the metal
|
||||
|
||||
hdmi_full = [ "hdmi_full", "HDMI socket", 12, 14, 10, 3, 4.5, 6.5, 0.5 ];
|
||||
hdmi_mini = [ "hdmi_mini", "Mini HDMI socket", 7.5, 10.5, 8.3, 1.28, 2.5, 3.2, 0.35 ];
|
||||
hdmi_full = [ "hdmi_full", "HDMI socket", 12, 14, 10, 3, 4.5, 6.5, 0.5 ];
|
||||
hdmi_mini = [ "hdmi_mini", "Mini HDMI socket", 7.5, 10.5, 8.3, 1.28, 2.5, 3.2, 0.35 ];
|
||||
hdmi_micro = [ "hdmi_micro", "Micro HDMI socket", 8.5, 5.9, 4.43, 1.4, 2.3, 3, 0.3 ];
|
||||
|
||||
module hdmi(type, cutout = false) { //! Draw HDMI socket
|
||||
vitamin(str("hdmi(", type[0], "): ", type[1]));
|
||||
@@ -437,6 +438,39 @@ module usb_uA(cutout = false) { //! Draw USB micro A connector
|
||||
}
|
||||
}
|
||||
|
||||
module usb_C(cutout = false) { //! Draw USB C connector
|
||||
l = 7.35;
|
||||
w = 8.94;
|
||||
h = 3.26;
|
||||
t = 0.4;
|
||||
flange_h = 3;
|
||||
flange_w = 8;
|
||||
|
||||
module O()
|
||||
translate([0, h / 2])
|
||||
rounded_square([w, h], h / 2 - 0.5, center = true);
|
||||
|
||||
if(cutout)
|
||||
rotate([90, 0, 90])
|
||||
linear_extrude(100)
|
||||
offset(2 * panel_clearance)
|
||||
O();
|
||||
else
|
||||
color("silver") rotate([90, 0, 90]) {
|
||||
linear_extrude(l, center = true)
|
||||
difference() {
|
||||
O();
|
||||
|
||||
offset(-t)
|
||||
O();
|
||||
}
|
||||
|
||||
translate_z(-l / 2)
|
||||
linear_extrude(2.51)
|
||||
O();
|
||||
|
||||
}
|
||||
}
|
||||
module usb_B(cutout = false) { //! Draw USB B connector
|
||||
l = 16.4;
|
||||
w = 12.2;
|
||||
@@ -881,7 +915,7 @@ module pcb_component(comp, cutouts = false, angle = undef) { //! Draw pcb compon
|
||||
function param(n, default = 0) = len(comp) > n ? comp[n] : default;
|
||||
rotate(comp.z) {
|
||||
// Components that have a cutout parameter go in this section
|
||||
if(show(comp, "2p54header")) pin_header(2p54header, comp[4], comp[5], param(6, false), false, cutouts, colour = param(7, undef));
|
||||
if(show(comp, "2p54header")) pin_header(2p54header, comp[4], comp[5], param(6, false), param(8, false), cutouts, colour = param(7, undef));
|
||||
if(show(comp, "2p54boxhdr")) box_header(2p54header, comp[4], comp[5], param(6, false), cutouts);
|
||||
if(show(comp, "2p54socket")) pin_socket(2p54header, comp[4], comp[5], param(6, false), param(7, 0), param(8, false), cutouts, param(9, undef));
|
||||
if(show(comp, "chip")) chip(comp[4], comp[5], comp[6], param(7, grey(30)), cutouts);
|
||||
@@ -890,10 +924,12 @@ module pcb_component(comp, cutouts = false, angle = undef) { //! Draw pcb compon
|
||||
if(show(comp, "usb_Ax2")) usb_Ax2(cutouts);
|
||||
if(show(comp, "usb_uA")) usb_uA(cutouts);
|
||||
if(show(comp, "usb_B")) usb_B(cutouts);
|
||||
if(show(comp, "usb_C")) usb_C(cutouts);
|
||||
if(show(comp, "jack")) jack(cutouts);
|
||||
if(show(comp, "barrel_jack")) barrel_jack(cutouts);
|
||||
if(show(comp, "hdmi")) hdmi(hdmi_full, cutouts);
|
||||
if(show(comp, "mini_hdmi")) hdmi(hdmi_mini, cutouts);
|
||||
if(show(comp, "micro_hdmi")) hdmi(hdmi_micro, cutouts);
|
||||
if(show(comp, "flex")) flex(cutouts);
|
||||
if(show(comp, "flat_flex")) flat_flex(param(4, false) ? large_ff : small_ff, cutouts);
|
||||
if(show(comp, "uSD")) uSD(comp[4], cutouts);
|
||||
@@ -904,6 +940,7 @@ module pcb_component(comp, cutouts = false, angle = undef) { //! Draw pcb compon
|
||||
if(!cutouts) {
|
||||
// Components that don't have a cutout parameter go in this section
|
||||
if(show(comp, "button_6mm")) square_button(button_6mm);
|
||||
if(show(comp, "button_4p5mm")) square_button(button_4p5mm);
|
||||
if(show(comp, "microswitch")) translate_z(microswitch_thickness(comp[4])/2) microswitch(comp[4]);
|
||||
if(show(comp, "pcb")) translate_z(comp[4]) pcb(comp[5]);
|
||||
if(show(comp, "standoff")) standoff(comp[4], comp[5], comp[6], comp[7]);
|
||||
@@ -917,6 +954,7 @@ module pcb_component(comp, cutouts = false, angle = undef) { //! Draw pcb compon
|
||||
if(show(comp, "led")) led(comp[4], comp[5], 2.6);
|
||||
if(show(comp, "pdip")) pdip(comp[4], comp[5], param(6, false), param(7, inch(0.3)));
|
||||
if(show(comp, "ax_res")) ax_res(comp[4], comp[5], param(6, 5), param(7, 0));
|
||||
if(show(comp, "link")) wire_link(l = comp[4], h = param(5, 1), d = param(6, 0.8), tail = param(7, 3));
|
||||
if(show(comp, "D_plug")) translate_z(d_pcb_offset(comp[4])) d_plug(comp[4], pcb = true);
|
||||
if(show(comp, "molex_hdr")) molex_254(comp[4]);
|
||||
if(show(comp, "jst_xh")) jst_xh_header(jst_xh_header, comp[4], param(5, false), param(6, "white"), param(7, undef));
|
||||
@@ -983,8 +1021,6 @@ module pcb(type) { //! Draw specified PCB
|
||||
for(part = pcb_accessories(type))
|
||||
vitamin(part);
|
||||
|
||||
pcb_components(type);
|
||||
|
||||
color(pcb_colour(type)) linear_extrude(t) difference() {
|
||||
if(Len(pcb_polygon(type)))
|
||||
polygon(pcb_polygon(type));
|
||||
@@ -1038,6 +1074,8 @@ module pcb(type) { //! Draw specified PCB
|
||||
circle(d = 2);
|
||||
}
|
||||
}
|
||||
|
||||
pcb_components(type);
|
||||
}
|
||||
|
||||
module pcb_spacer(screw, height, wall = 1.8, taper = 0) { //! Generate STL for PCB spacer
|
||||
|
@@ -217,6 +217,25 @@ RPI3 = ["RPI3", "Raspberry Pi 3", 85, 56, 1.4, 3, 2.75, 6, "green"
|
||||
[": Micro SD card"],
|
||||
[32.5 - 9.5 * 2.54, 52.5 - 1.27, 20, 2]];
|
||||
|
||||
RPI4 = ["RPI4", "Raspberry Pi 4", 85, 56, 1.4, 3, 2.75, 6, "green", false, [[3.5, 3.5], [61.5, 3.5], [61.5, -3.5], [3.5, -3.5]], [
|
||||
[32.5, -3.5, 0, "2p54header", 20, 2],
|
||||
[-6.5, 9, 0, "usb_Ax2"],
|
||||
[-6.5, 27, 0, "usb_Ax2"],
|
||||
[-8.5, 45.75, 0, "rj45"],
|
||||
|
||||
[ 4, 28, 90, "flex"],
|
||||
[11.2, 3.675 - 1.6, -90, "usb_C"],
|
||||
[ 26, 2.5, -90, "micro_hdmi"],
|
||||
[39.5, 2.5, -90, "micro_hdmi"],
|
||||
[46.5, 11.5, -90, "flex"],
|
||||
[ 54, 6, -90, "jack"],
|
||||
|
||||
[ 29.25, 32.5, 0, "chip", 14, 14, 2.4],
|
||||
[ 60, -22.3, 0, "chip", 9, 9, 0.6],
|
||||
[7.75, 28, 180, "-uSD", [12, 11.5, 1.28]]
|
||||
], [": Micro SD card"], [32.5 - 9.5 * 2.54, 52.5 - 1.27, 20, 2]
|
||||
];
|
||||
|
||||
RPI0 = ["RPI0", "Raspberry Pi Zero", 65, 30, 1.4, 3, 2.75, 6, "green", false, [[3.5, 3.5], [-3.5, 3.5], [-3.5, -3.5], [3.5, -3.5]],
|
||||
[//[32.5, -3.5, 0, "2p54header", 20, 2],
|
||||
[25.5, 13, 0, "chip", 12, 12, 1.2],
|
||||
@@ -329,7 +348,7 @@ PI_IO = ["PI_IO", "PI_IO V2", 35.56, 25.4, 1.6, 0, 0, 0, "green", tru
|
||||
], []];
|
||||
|
||||
ZC_A0591 = ["ZC_A0591", "ZC-A0591 ULN2003 driver PCB", 35, 32, 1.6, 0, 2.5, 0, "green", false, [[2.25, 3.25], [-2.25, 3.25], [2.25, -3.25], [-2.25, -3.25] ],
|
||||
[ [ 12.25, 8.3, -90, "jst_xh", 5],
|
||||
[ [ 11.725, 8.3, -90, "jst_xh", 5],
|
||||
[ -6.5, 10, 0, "2p54header", 1, 4],
|
||||
[ 20.4, -4.5, 0, "2p54header", 4, 1],
|
||||
[ 20.4, 11, 180, "pdip", 16, "ULN2803AN", true],
|
||||
@@ -366,6 +385,11 @@ WD2002SJ = ["WD2002SJ", "WD2002SJ Buck Boost DC-DC converter", 78, 47, 1.6, 0, 3
|
||||
],
|
||||
[]];
|
||||
|
||||
MP1584EN = ["MP1584EN", "MP1584EN 3A buck converter", 22, 17, 1.2, 0, 1, [2, 2], "green", false,
|
||||
[[1.75, 1.75], [1.75, -1.75], [-1.75, 1.75], [-1.75, -1.75], [-1.75, -4.4], [-1.75, 4.48], [1.75, -4.4], [1.75, 4.4]],
|
||||
[]
|
||||
];
|
||||
|
||||
PERF80x20 = ["PERF80x20", "Perfboard 80 x 20mm", 80, 20, 1.6, 0, 2.3, 0, "green", true, [[2,2],[-2,2],[2,-2],[-2,-2]], [], [], [5.87, 3.49]];
|
||||
|
||||
PERF70x50 = ["PERF70x50", "Perfboard 70 x 50mm", 70, 50, 1.6, 0, 2.3, 0, "green", true, [[2,2],[-2,2],[2,-2],[-2,-2]], [], [], [5.87, 3.49]];
|
||||
@@ -384,14 +408,14 @@ RAMPSEndstop = ["RAMPSEndstop", "RAMPS Endstop Switch",
|
||||
[2, 2, false], [2, 13.5, false], [17, 13.5], [36, 13.5]
|
||||
],
|
||||
[
|
||||
[ 12, 8, -90, "jst_xh", 3, true, "white", "silver"],
|
||||
[ 11.6, 8, -90, "jst_xh", 3, true, "white", "silver"],
|
||||
[ 26.5, 12.75, 0, "microswitch", small_microswitch],
|
||||
[ 27.5, 17.5, 15, "chip", 15, 0.5, 4.5, "silver"],
|
||||
],
|
||||
[]];
|
||||
|
||||
|
||||
pcbs = [TP4056, MT3608, RAMPSEndstop, ExtruderPCB, PI_IO, ZC_A0591, RPI0, EnviroPlus, ArduinoUno3, ArduinoLeonardo, Keyes5p1, PSU12V1A, WD2002SJ, RPI3, DuetE, Duex2, Duex5, Melzi];
|
||||
pcbs = [MP1584EN, TP4056, MT3608, RAMPSEndstop, ExtruderPCB, PI_IO, ZC_A0591, RPI0, EnviroPlus, ArduinoUno3, ArduinoLeonardo, Keyes5p1, PSU12V1A, WD2002SJ, RPI3, RPI4, DuetE, Duex2, Duex5];
|
||||
|
||||
perfboards = [PERF74x51, PERF70x50, PERF60x40, PERF70x30, PERF80x20];
|
||||
|
||||
|
@@ -29,13 +29,18 @@ function hdr_pin_width(type) = type[4]; //! Header pin size
|
||||
function hdr_pin_colour(type) = type[5]; //! Header pin colour
|
||||
function hdr_base_colour(type) = type[6]; //! Header insulator colour
|
||||
function hdr_socket_depth(type) = type[7]; //! Socket depth for female housing
|
||||
function hdr_box_size(type) = type[8]; //! Box header outside dimensions
|
||||
function hdr_box_wall(type) = type[9]; //! Box header wall thickness
|
||||
function hdr_y_offset(type) = type[10]; //! Y offset of pins from center of the box
|
||||
function hdr_ra_box_offset(type)= type[11]; //! Offset between back of the box and the pins
|
||||
function hdr_ra_height(type) = type[12]; //! Height of right angle connector
|
||||
|
||||
module pin(type, length = undef) { //! Draw a header pin
|
||||
w = hdr_pin_width(type);
|
||||
l = length == undef ? hdr_pin_length(type) : length;
|
||||
chamfer = w / 2;
|
||||
color(hdr_pin_colour(type))
|
||||
translate_z(l / 2 -hdr_pin_below(type))
|
||||
translate_z(l / 2 - hdr_pin_below(type))
|
||||
hull() {
|
||||
cube([w, w, l - 2 * chamfer], center = true);
|
||||
|
||||
@@ -50,26 +55,37 @@ module pin_header(type, cols = 1, rows = 1, smt = false, right_angle = false, cu
|
||||
ra_offset = 2.4;
|
||||
width = pitch * rows;
|
||||
|
||||
if(cutout)
|
||||
module cutout()
|
||||
dogbone_rectangle([cols * pitch + 2 * panel_clearance, rows * pitch + 2 * panel_clearance, 100], center = false);
|
||||
|
||||
if(cutout) {
|
||||
if(right_angle)
|
||||
translate_z(width / 2)
|
||||
rotate([-90, 0, 180])
|
||||
cutout();
|
||||
else
|
||||
cutout();
|
||||
}
|
||||
else {
|
||||
vitamin(str("pin_header(", type[0], ", ", cols, ", ", rows,
|
||||
arg(smt, false, "smt"), arg(right_angle, false, "right_angle"), "): Pin header ", cols, " x ", rows, right_angle ? " right_angle" : ""));
|
||||
|
||||
translate_z(smt ? 3.5 - h : 0) {
|
||||
for(x = [0 : cols - 1], y = [0 : rows - 1]) {
|
||||
translate([pitch * (x - (cols - 1) / 2), pitch * (y - (rows - 1) / 2), 0])
|
||||
// Vertical part of the pin
|
||||
translate([pitch * (x - (cols - 1) / 2), pitch * (y - (rows - 1) / 2)])
|
||||
if(right_angle)
|
||||
pin(type, hdr_pin_below(type) + width / 2 + (y - 0.5) * pitch);
|
||||
pin(type, hdr_pin_below(type) + (y + 0.5) * pitch);
|
||||
else
|
||||
pin(type);
|
||||
|
||||
if(right_angle) {
|
||||
w = hdr_pin_width(type);
|
||||
// Horizontal part of the pin
|
||||
rotate([-90, 0, 180])
|
||||
translate([pitch * (x - (cols - 1) / 2), -pitch * (y - (rows - 1) / 2) -width / 2, hdr_pin_below(type) - (y - 0.5) * pitch])
|
||||
translate([pitch * (x - (cols - 1) / 2), -pitch * (y - (rows - 1) / 2) - width / 2, hdr_pin_below(type) - (y - (rows - 1) / 2) * pitch])
|
||||
pin(type, hdr_pin_length(type) - hdr_pin_below(type) + ra_offset + pitch / 2 + (y - 0.5) * pitch);
|
||||
|
||||
// corner
|
||||
translate([pitch * (x - (cols - 1) / 2), pitch * (y - (rows - 1) / 2) - w / 2, pitch * (y - (rows - 1) / 2) + width / 2 - w / 2])
|
||||
rotate([0, -90, 0])
|
||||
color(hdr_pin_colour(type))
|
||||
@@ -78,7 +94,8 @@ module pin_header(type, cols = 1, rows = 1, smt = false, right_angle = false, cu
|
||||
square(w);
|
||||
}
|
||||
}
|
||||
translate([0, right_angle ? -ra_offset - pitch / 2 : 0, right_angle ? width / 2 : 0])
|
||||
// Insulator
|
||||
translate([0, right_angle ? -ra_offset - (rows - 1) * pitch / 2 : 0, right_angle ? width / 2 : 0])
|
||||
rotate([right_angle ? 90 : 0, 0, 0])
|
||||
color(base_colour)
|
||||
linear_extrude(h)
|
||||
@@ -96,9 +113,11 @@ module pin_header(type, cols = 1, rows = 1, smt = false, right_angle = false, cu
|
||||
|
||||
module box_header(type, cols = 1, rows = 1, smt = false, cutout = false) { //! Draw box header
|
||||
pitch = hdr_pitch(type);
|
||||
size = hdr_box_size(type);
|
||||
w = cols * pitch + 7.62;
|
||||
l = rows * pitch + 3.52;
|
||||
h = 8.7;
|
||||
h = size.z;
|
||||
t = hdr_box_wall(type);
|
||||
base = h - 6.4;
|
||||
|
||||
if(cutout)
|
||||
@@ -119,7 +138,7 @@ module box_header(type, cols = 1, rows = 1, smt = false, cutout = false) { //! D
|
||||
difference() {
|
||||
square([w, l], center = true);
|
||||
|
||||
square([w - 2.4, l - 2.4], center = true);
|
||||
square([w - t, l - t], center = true);
|
||||
|
||||
translate([0, -l / 2])
|
||||
square([4.5, 4.5], center = true);
|
||||
@@ -176,7 +195,7 @@ module pin_socket(type, cols = 1, rows = 1, right_angle = false, height = 0, smt
|
||||
vitamin(str("pin_socket(", type[0], ", ", cols, ", ", rows, arg(right_angle, false, "right_angle"), arg(height, 0, "height"), arg(smt, false, "smt"),
|
||||
"): Pin socket ", cols, " x ", rows, right_angle ? " right_angle" : ""));
|
||||
color(base_colour)
|
||||
translate([0, right_angle ? -ra_offset - pitch / 2 : 0, right_angle ? width / 2 : 0])
|
||||
translate([0, right_angle ? -ra_offset - (rows - 1) * pitch / 2 : 0, right_angle ? width / 2 : 0])
|
||||
rotate([right_angle ? 90 : 0, 0, 0])
|
||||
translate_z(depth / 2)
|
||||
linear_extrude(depth, center = true)
|
||||
@@ -192,11 +211,11 @@ module pin_socket(type, cols = 1, rows = 1, right_angle = false, height = 0, smt
|
||||
for(x = [0 : cols - 1], y = [0 : rows -1]) {
|
||||
if(!smt)
|
||||
translate([pitch * (x - (cols - 1) / 2), pitch * (y - (rows - 1) / 2), 0])
|
||||
pin(type, hdr_pin_below(type) + width / 2 + (y - 0.5) * pitch);
|
||||
pin(type, hdr_pin_below(type) + (y + 0.5) * pitch);
|
||||
|
||||
if(right_angle) {
|
||||
rotate([-90, 0, 0])
|
||||
translate([pitch * (x - (cols - 1) / 2), -pitch * (y - (rows - 1) / 2) -width / 2, 0])
|
||||
rotate([-90, 0, 180])
|
||||
translate([pitch * (x - (cols - 1) / 2), -pitch * (y - (rows - 1) / 2) - width / 2, hdr_pin_below(type) - (y - (rows - 1) / 2) * pitch])
|
||||
pin(type, hdr_pin_below(type) + (y - 0.5) * pitch);
|
||||
|
||||
w = hdr_pin_width(type);
|
||||
@@ -210,68 +229,98 @@ module pin_socket(type, cols = 1, rows = 1, right_angle = false, height = 0, smt
|
||||
}
|
||||
}
|
||||
|
||||
module jst_xh_header(type, pin_count, right_angle=false, colour, pin_colour) { //! Draw JST XH connector
|
||||
module jst_xh_header(type, pin_count, right_angle = false, colour = false, pin_colour = false) { //! Draw JST XH connector
|
||||
colour = colour ? colour : hdr_base_colour(type);
|
||||
pin_colour = pin_colour ? pin_colour : hdr_pin_colour(type);
|
||||
sizeY = 5.75;
|
||||
pitch = hdr_pitch(type);
|
||||
size = hdr_box_size(type) + [(pin_count - 1) * pitch, 0, 0];
|
||||
pinOffsetX = hdr_box_size(type).x / 2; // Offset from last pin to box edge
|
||||
wallThickness = hdr_box_wall(type);
|
||||
y_offset = hdr_y_offset(type);
|
||||
ra_box_offset = hdr_ra_box_offset(type);
|
||||
ra_h = hdr_ra_height(type);
|
||||
ra_z = ra_h - size.y / 2;
|
||||
ra_extra = ra_h - size.y; // thicker base for right angle version
|
||||
pinWidth = hdr_pin_width(type);
|
||||
|
||||
module jst_xh_socket(type, pin_count) {
|
||||
socketSizeZ = hdr_socket_depth(type);
|
||||
pinOffsetX = 2.45;
|
||||
sizeY = 5.75;
|
||||
wallThickness = 0.8;
|
||||
size = [pinOffsetX * 2 + (pin_count - 1) * pitch, sizeY, socketSizeZ];
|
||||
translate([-size[0] / 2, -size[1] / 2, 0]) {
|
||||
// the base
|
||||
cube([size[0], size[1], wallThickness]);
|
||||
// the three full sides
|
||||
translate([0, size[1] - wallThickness, 0])
|
||||
cube([size[0], wallThickness, size[2]]);
|
||||
cube([wallThickness, size[1], size[2]]);
|
||||
translate([size[0] - wallThickness, 0, 0])
|
||||
cube([wallThickness, size[1], size[2]]);
|
||||
// the sides with cutouts
|
||||
cube([size[0], wallThickness, 2]);
|
||||
cutoutWidth = 1;
|
||||
cutoutOffset = pinOffsetX - cutoutWidth / 2;
|
||||
cube([cutoutOffset, wallThickness, size[2]]);
|
||||
translate([size[0] - cutoutOffset, 0, 0])
|
||||
cube([cutoutOffset, wallThickness, size[2]]);
|
||||
cube([cutoutOffset, wallThickness, size[2]]);
|
||||
translate([size[0]-cutoutOffset, 0, 0])
|
||||
cube([cutoutOffset, wallThickness, size[2]]);
|
||||
translate([cutoutOffset + cutoutWidth, 0, 0])
|
||||
cube([size[0] - 2 * (cutoutWidth + cutoutOffset), wallThickness, size[2]]);
|
||||
module jst_xh_socket(type, pin_count, ra = false) {
|
||||
module wall() {
|
||||
difference() {
|
||||
square([size.x, size.y], center = true);
|
||||
|
||||
offset(-wallThickness)
|
||||
square([size.x, size.y], center = true);
|
||||
}
|
||||
if(right_angle)
|
||||
translate([0, size.y / 2 + ra_extra / 2])
|
||||
square([size.x, ra_extra], center = true);
|
||||
}
|
||||
} // end module
|
||||
|
||||
module slots() {
|
||||
cutoutWidth = 1.3;
|
||||
cutoutOffset = pinOffsetX + cutoutWidth / 2 - hdr_pin_width(type) / 2;
|
||||
for(side = [-1, 1])
|
||||
translate([side * (size.x / 2 - cutoutOffset), -size.y / 2 + wallThickness / 2])
|
||||
square([cutoutWidth, 2 * wallThickness], center = true);
|
||||
}
|
||||
|
||||
linear_extrude(wallThickness)
|
||||
square([size.x, size.y], center = true); // the base
|
||||
|
||||
linear_extrude(size.z / 2) // full walls up to the slots
|
||||
wall();
|
||||
|
||||
linear_extrude(size.z) // slotted walls to the top
|
||||
difference() {
|
||||
wall();
|
||||
|
||||
if(type[0] == "jst_xh_header") {
|
||||
if(pin_count > 2)
|
||||
slots();
|
||||
else
|
||||
hull()
|
||||
slots();
|
||||
|
||||
translate([0, -size.y / 2 + 3 * wallThickness / 2])
|
||||
square([size.x + 1, wallThickness], center = true);
|
||||
}
|
||||
|
||||
if(type[0] == "jst_ph_header") {
|
||||
translate([0, -size.y / 2 + wallThickness / 2])
|
||||
square([max((pin_count - 2) * pitch, 1), 2 * wallThickness], center = true);
|
||||
|
||||
translate([0, -y_offset / 2 - pinWidth / 4])
|
||||
square([size.x + 1, y_offset + pinWidth / 2], center = true);
|
||||
}
|
||||
}
|
||||
} // end module
|
||||
|
||||
color(colour)
|
||||
if(right_angle)
|
||||
translate([0, -1, sizeY / 2])
|
||||
translate([0, -ra_box_offset, ra_z])
|
||||
rotate([-90, 0, 180])
|
||||
jst_xh_socket(type, pin_count);
|
||||
jst_xh_socket(type, pin_count, true);
|
||||
else
|
||||
jst_xh_socket(type, pin_count);
|
||||
translate([0, y_offset])
|
||||
jst_xh_socket(type, pin_count);
|
||||
|
||||
color(pin_colour)
|
||||
for(x = [0 : pin_count - 1]) {
|
||||
pinWidth = hdr_pin_width(type);
|
||||
verticalPinLength = right_angle ? hdr_pin_below(type) + sizeY / 2 : hdr_pin_length(type);
|
||||
translate([pitch * (x - (pin_count - 1) / 2), 0, 0]) {
|
||||
verticalPinLength = right_angle ? hdr_pin_below(type) + ra_z + y_offset : hdr_pin_length(type);
|
||||
horizontalPinLength = hdr_pin_length(type) - hdr_pin_below(type) + ra_box_offset;
|
||||
translate([pitch * (x - (pin_count - 1) / 2), 0]) {
|
||||
pin(type, verticalPinLength);
|
||||
|
||||
if(right_angle) {
|
||||
translate([0, -pinWidth / 2, sizeY / 2 - pinWidth / 2])
|
||||
translate([0, -pinWidth / 2, ra_z - pinWidth / 2 + y_offset])
|
||||
rotate([0, -90, 0])
|
||||
rotate_extrude(angle = 90, $fn = 32)
|
||||
translate([0, -pinWidth / 2])
|
||||
square(pinWidth);
|
||||
|
||||
translate([0, -sizeY / 2 - 3 * pinWidth / 4, sizeY / 2])
|
||||
rotate([90,0,0])
|
||||
pin(type, hdr_pin_length(type) - hdr_pin_below(type));
|
||||
translate([0, -hdr_pin_below(type), ra_z + y_offset])
|
||||
rotate([90, 0, 0])
|
||||
pin(type, horizontalPinLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -17,15 +17,16 @@
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
// p p b p p b Socket depth
|
||||
// i i e i i a
|
||||
// t n l n n s
|
||||
// c o e
|
||||
// h l w w c
|
||||
// c
|
||||
//
|
||||
2p54header = ["2p54header", 2.54, 11.6, 3.2, 0.66, "gold", grey(20), 8.5];
|
||||
jst_xh_header = ["JST XH header",2.5,10,3.4, 0.64, "gold", grey(90), 7];
|
||||
// p p b p p b s b b p r r
|
||||
// i i e i i a o o o i a a
|
||||
// t n l n n s c x x n
|
||||
// c o e k b h
|
||||
// h l w w c s t y
|
||||
// c h z o
|
||||
// f
|
||||
2p54header = ["2p54header", 2.54, 11.6, 3.2, 0.66, "gold", grey(20), 8.5, [0, 0, 8.7], 2.4, 0, 0, 0 ];
|
||||
jst_xh_header = ["jst_xh_header",2.5, 10, 3.4, 0.64, "gold", grey(90), 0, [4.9, 5.75, 7], 0.8, 0.525, 0.6, 6.1];
|
||||
jst_ph_header = ["jst_ph_header",2.0, 9, 3.4, 0.64, silver, grey(90), 0, [3.9, 4.5, 6], 0.6, 0.55, 0.25, 4.8];
|
||||
|
||||
pin_headers = [ 2p54header ];
|
||||
|
||||
|
@@ -35,7 +35,8 @@ GT2x12_pulley = ["GT2x12_pulley", "GT2RD", 12, 7.15, GT2x6, 6.5,
|
||||
GT2x20_toothed_idler = ["GT2x20_toothed_idler", "GT2", 20, 12.22, GT2x6, 6.5, 18, 0, 4, 18.0, 1.0, 0, 0, false, 0];
|
||||
GT2x20_plain_idler = ["GT2x20_plain_idler", "GT2", 0, 12.0, GT2x6, 6.5, 18, 0, 4, 18.0, 1.0, 0, 0, false, 0];
|
||||
GT2x16_toothed_idler = ["GT2x16_toothed_idler", "GT2", 16, 9.75, GT2x6, 6.5, 14, 0, 3, 14.0, 1.0, 0, 0, false, 0];
|
||||
GT2x16_plain_idler = ["GT2x16_plain_idler", "GT2", 0, 9.63, GT2x6, 7.0, 13, 0, 3, 13.0, 1.0, 0, 0, false, 0];
|
||||
GT2x16_plain_idler = ["GT2x16_plain_idler", "GT2", 0, 9.63, GT2x6, 6.5, 13, 0, 3, 13.0, 1.0, 0, 0, false, 0];
|
||||
GT2x16x7_plain_idler = ["GT2x16x7_plain_idler", "GT2", 0, 9.63, GT2x6, 7.0, 13, 0, 3, 13.0, 1.0, 0, 0, false, 0];
|
||||
|
||||
pulleys = [T5x10_pulley,
|
||||
T2p5x16_pulley,
|
||||
@@ -45,6 +46,7 @@ pulleys = [T5x10_pulley,
|
||||
GT2x20_toothed_idler,
|
||||
GT2x20_plain_idler,
|
||||
GT2x16_toothed_idler,
|
||||
GT2x16_plain_idler];
|
||||
GT2x16_plain_idler,
|
||||
GT2x16x7_plain_idler];
|
||||
|
||||
use <pulley.scad>
|
||||
|
@@ -175,12 +175,15 @@ module screw(type, length, hob_point = 0, nylon = false) { //! Draw specified sc
|
||||
|
||||
if(head_type == hs_dome) {
|
||||
lift = 0.38;
|
||||
h = head_height - lift;
|
||||
r = min(2 * head_height, (sqr(head_rad) + sqr(h)) / 2 * h); // Special case for M2
|
||||
y = sqrt(sqr(r) - sqr(head_rad));
|
||||
color(colour) {
|
||||
rotate_extrude() {
|
||||
difference() {
|
||||
intersection() {
|
||||
translate([0, -head_height + lift])
|
||||
circle(2 * head_height);
|
||||
translate([0, -y + lift])
|
||||
circle(r);
|
||||
|
||||
square([head_rad, head_height]);
|
||||
}
|
||||
|
@@ -75,10 +75,11 @@ M5_cap_screw = ["M5_cap", "M5 cap", hs_cap, 5, 8.5, 5, 2.5, 4.0
|
||||
M6_cap_screw = ["M6_cap", "M6 cap", hs_cap, 6, 10, 6, 3.3, 5.0, 24, M6_washer, M6_nut, M6_tap_radius, M6_clearance_radius];
|
||||
M8_cap_screw = ["M8_cap", "M8 cap", hs_cap, 8, 13, 8, 4.3, 6.0, 28, M8_washer, M8_nut, M8_tap_radius, M8_clearance_radius];
|
||||
|
||||
M2_cs_cap_screw = ["M2_cs_cap","M2 cs cap", hs_cs_cap,2, 3.8, 0, 0.65,1.27,16, M2_washer, M2_nut, M2_tap_radius, M2_clearance_radius];
|
||||
M2_cs_cap_screw = ["M2_cs_cap","M2 cs cap", hs_cs_cap,2, 3.8, 0, 0.65,1.3, 16, M2_washer, M2_nut, M2_tap_radius, M2_clearance_radius];
|
||||
M3_cs_cap_screw = ["M3_cs_cap","M3 cs cap", hs_cs_cap,3, 6.0, 0, 1.05,2.0, 18, M3_washer, M3_nut, M3_tap_radius, M3_clearance_radius];
|
||||
M4_cs_cap_screw = ["M4_cs_cap","M4 cs cap", hs_cs_cap,4, 8.0, 0, 1.49,2.5, 20, M4_washer, M4_nut, M4_tap_radius, M4_clearance_radius];
|
||||
|
||||
M2_dome_screw = ["M2_dome", "M2 dome", hs_dome, 2, 3.5, 1.3, 0.6, 1.3, 16, M2_washer, M2_nut, M2_tap_radius, M2_clearance_radius];
|
||||
M3_dome_screw = ["M3_dome", "M3 dome", hs_dome, 3, 5.7, 1.65, 1.04,2.0, 18, M3_washer, M3_nut, M3_tap_radius, M3_clearance_radius];
|
||||
M4_dome_screw = ["M4_dome", "M4 dome", hs_dome, 4, 7.6, 2.2, 1.3, 2.5, 20, M4_washer, M4_nut, M4_tap_radius, M4_clearance_radius];
|
||||
|
||||
@@ -106,14 +107,14 @@ No6_screw = ["No6", "No6 pan wood", hs_pan, 3.5, 6.7, 2.2, 0, 0
|
||||
No6_cs_screw = ["No6_cs", "No6 cs wood", hs_cs, 3.5, 7.0, 0, 0, 0, 0, M4_washer, false, No6_pilot_radius, No6_clearance_radius];
|
||||
|
||||
screw_lists = [
|
||||
[ M2_cap_screw, M2p5_cap_screw, M3_cap_screw, M4_cap_screw, M5_cap_screw, M6_cap_screw, M8_cap_screw],
|
||||
[ M2_cap_screw, M2p5_cap_screw, M3_cap_screw, M4_cap_screw, M5_cap_screw, M6_cap_screw, M8_cap_screw],
|
||||
[ 0, 0, M3_low_cap_screw],
|
||||
[ 0, 0, M3_hex_screw, M4_hex_screw, M5_hex_screw, M6_hex_screw, M8_hex_screw],
|
||||
[ 0, M2p5_pan_screw, M3_pan_screw, M4_pan_screw, M5_pan_screw, M6_pan_screw, No632_pan_screw],
|
||||
[ 0, No2_screw, No4_screw, No6_screw, No6_cs_screw],
|
||||
[ 0, 0, M3_hex_screw, M4_hex_screw, M5_hex_screw, M6_hex_screw, M8_hex_screw],
|
||||
[ 0, M2p5_pan_screw, M3_pan_screw, M4_pan_screw, M5_pan_screw, M6_pan_screw, No632_pan_screw],
|
||||
[ 0, No2_screw, No4_screw, No6_screw, No6_cs_screw],
|
||||
[ 0, M2_cs_cap_screw,M3_cs_cap_screw, M4_cs_cap_screw],
|
||||
[ 0, 0, M3_dome_screw, M4_dome_screw],
|
||||
[ 0, 0, M3_grub_screw, M4_grub_screw]
|
||||
[ 0, M2_dome_screw, M3_dome_screw, M4_dome_screw],
|
||||
[ 0, 0, M3_grub_screw, M4_grub_screw]
|
||||
];
|
||||
|
||||
use <screw.scad>
|
||||
|
@@ -62,9 +62,10 @@ module smd_led(type, colour, cutout) { //! Draw an SMD LED with specified ```col
|
||||
intersection() {
|
||||
square([size.x, size.y], center = true);
|
||||
|
||||
for(end = [-1, 1])
|
||||
translate([end * size.x / 2, 0])
|
||||
ring(or = r, ir = r / 2);
|
||||
union()
|
||||
for(end = [-1, 1])
|
||||
translate([end * size.x / 2, 0])
|
||||
ring(or = r, ir = r / 2);
|
||||
}
|
||||
|
||||
color(colour, 0.9)
|
||||
|
@@ -23,8 +23,10 @@
|
||||
include <../core.scad>
|
||||
include <ring_terminals.scad>
|
||||
|
||||
include <../vitamins/pin_headers.scad>
|
||||
use <../utils/tube.scad>
|
||||
use <../utils/thread.scad>
|
||||
use <../utils/round.scad>
|
||||
use <washer.scad>
|
||||
use <rod.scad>
|
||||
|
||||
@@ -37,9 +39,10 @@ function NEMA_boss_height(type) = type[6]; //! Boss height
|
||||
function NEMA_shaft_dia(type) = type[7]; //! Shaft diameter
|
||||
function NEMA_shaft_length(type)= type[8]; //! Shaft length above the face, if a list then a leadscrew: length, lead, starts
|
||||
function NEMA_hole_pitch(type) = type[9]; //! Screw hole pitch
|
||||
function NEMA_cap_heights(type) = type[10]; //! Height of the end cap at the corner and the side
|
||||
|
||||
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,19 +55,20 @@ 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);
|
||||
boss_rad = NEMA_boss_radius(type);
|
||||
boss_height =NEMA_boss_height(type);
|
||||
shaft_rad = NEMA_shaft_dia(type) / 2;
|
||||
cap = 8;
|
||||
cap = NEMA_cap_heights(type)[1];
|
||||
cap2 = NEMA_cap_heights(type)[0];
|
||||
vitamin(str("NEMA(", type[0], "): Stepper motor NEMA", round(NEMA_width(type) / 2.54), " x ", length, "mm"));
|
||||
thread_d = 3; // Is this always the case?
|
||||
thread_d = 3; // Is this always the case?
|
||||
|
||||
module cap_shape(end)
|
||||
difference() {
|
||||
round(0.5, $fn = 32) difference() {
|
||||
intersection() {
|
||||
square([side, side], center = true);
|
||||
|
||||
@@ -89,15 +93,44 @@ module NEMA(type, shaft_angle = 0) { //! Draw specified NEMA stepper motor
|
||||
tube(or = boss_rad, ir = shaft_rad + 2, h = boss_height * 2); // raised boss
|
||||
|
||||
linear_extrude(eps)
|
||||
cap_shape(true);
|
||||
cap_shape(1);
|
||||
}
|
||||
|
||||
color(stepper_cap_colour) // aluminium end caps
|
||||
for(end = [-1, 1])
|
||||
pcb_thickness = 1.6;
|
||||
header = jst_ph_header;
|
||||
socket_size = hdr_box_size(header);
|
||||
tabSize = [16, 4, cap - hdr_ra_height(header) - pcb_thickness];
|
||||
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);
|
||||
|
||||
translate_z(-length / 2 + end * (length - cap2) / 2)
|
||||
linear_extrude(cap2, center = true)
|
||||
difference() {
|
||||
cap_shape(end);
|
||||
|
||||
circle(body_rad);
|
||||
}
|
||||
}
|
||||
|
||||
if(jst_connector)
|
||||
translate([-tabSize.x / 2, side / 2, -length])
|
||||
cube(tabSize);
|
||||
}
|
||||
|
||||
if(jst_connector)
|
||||
translate([0, side / 2, -length + cap - hdr_ra_height(header)]) {
|
||||
rotate(180)
|
||||
not_on_bom()
|
||||
jst_xh_header(header, 6, true);
|
||||
|
||||
translate_z(-pcb_thickness / 2)
|
||||
color("green")
|
||||
cube([socket_size.x + 5 * 2, tabSize.y * 2, pcb_thickness], true);
|
||||
}
|
||||
|
||||
if(show_threads)
|
||||
for(x = NEMA_holes(type), y = NEMA_holes(type))
|
||||
translate([x, y, -cap / 2])
|
||||
@@ -111,15 +144,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
|
||||
|
@@ -22,14 +22,14 @@
|
||||
//
|
||||
|
||||
// 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 ];
|
||||
// side, length, radius, radius, radius, depth, shaft, length, holes, cap heights
|
||||
NEMA17 = ["NEMA17", 42.3, 47, 53.6/2, 25, 11, 2, 5, 24, 31, [11.5, 9]];
|
||||
NEMA17M = ["NEMA17M", 42.3, 40, 53.6/2, 25, 11, 2, 5, 20, 31, [12.5, 11]];
|
||||
NEMA17M8= ["NEMA17M8", 42.3, 40, 53.6/2, 25, 11, 2, 8, [280, 8, 4], 31, [12.5, 11]];
|
||||
NEMA17S = ["NEMA17S", 42.3, 34, 53.6/2, 25, 11, 2, 5, 24, 31, [8, 8]];
|
||||
NEMA16 = ["NEMA16", 39.5, 19.2, 50.6/2, 50.6/2, 11, 2, 5, 12, 31, [8, 8]];
|
||||
NEMA14 = ["NEMA14", 35.2, 36, 46.4/2, 21, 11, 2, 5, 21, 26, [8, 8]];
|
||||
NEMA23 = ["NEMA23", 56.4, 51.2, 75.7/2, 35, 38.1/2, 1.6, 6.35, 24, 47.1, [8, 8]];
|
||||
|
||||
stepper_motors = [NEMA14, NEMA16, NEMA17S, NEMA17M, NEMA17, NEMA23];
|
||||
|
||||
|
@@ -21,13 +21,16 @@
|
||||
//! Tubing and sleeving. The internal diameter can be forced to stretch it over something.
|
||||
//
|
||||
include <../utils/core/core.scad>
|
||||
include <../utils/tube.scad>
|
||||
|
||||
function tubing_material(type) = type[1]; //! Material description
|
||||
function tubing_od(type) = type[2]; //! Outside diameter
|
||||
function tubing_id(type) = type[3]; //! Inside diameter
|
||||
function tubing_colour(type) = type[4]; //! Colour
|
||||
|
||||
module tubing(type, length = 15, forced_id = 0) { //! Draw specified tubing with optional forced internal diameter
|
||||
function tubing_or(type) = tubing_od(type) / 2; //! Outside radius
|
||||
|
||||
module tubing(type, length = 15, forced_id = 0, center = true) { //! Draw specified tubing with optional forced internal diameter
|
||||
original_od = tubing_od(type);
|
||||
original_id = tubing_id(type);
|
||||
id = forced_id ? forced_id : original_id;
|
||||
@@ -36,10 +39,15 @@ module tubing(type, length = 15, forced_id = 0) { //! Draw specified tubing with
|
||||
vitamin(str("tubing(", type[0], arg(length, 15), "): ", tubing_material(type), " ID ", original_id, "mm x ",length, "mm"));
|
||||
else
|
||||
vitamin(str("tubing(", type[0], arg(length, 15), "): ", tubing_material(type), " OD ", original_od, "mm ID ", original_id,"mm x ",length, "mm"));
|
||||
color(tubing_colour(type))
|
||||
linear_extrude(length, center = true, convexity = 4)
|
||||
difference() {
|
||||
circle(d = od);
|
||||
circle(d = id);
|
||||
}
|
||||
|
||||
if(tubing_material(type) == "Carbon fiber")
|
||||
woven_tube(od / 2, id /2, length, colour = tubing_colour(type));
|
||||
else
|
||||
color(tubing_colour(type))
|
||||
linear_extrude(length, center = center, convexity = 4)
|
||||
difference() {
|
||||
circle(d = od);
|
||||
circle(d = id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -19,21 +19,23 @@
|
||||
|
||||
//
|
||||
// Tubing and sleeving
|
||||
//
|
||||
tubing_colour = [0.8, 0.8, 0.8, 0.75 ];
|
||||
// Description OD ID Colour
|
||||
PVC64 = ["PVC64", "PVC aquarium tubing", 6, 4, [0.8, 0.8, 0.8, 0.75 ]];
|
||||
PVC85 = ["PVC85", "PVC aquarium tubing", 8, 5, [0.8, 0.8, 0.8, 0.75 ]];
|
||||
NEOP85 = ["NEOP85", "Neoprene tubing", 8, 5, [0.2,0.2,0.2]];
|
||||
PTFE07 = ["PTFE07", "PTFE sleeving", 1.2, 0.71, [0.95, 0.95, 0.95, 0.9]];
|
||||
PTFE20 = ["PTFE20", "PTFE sleeving", 2.6, 2, [0.95, 0.95, 0.95, 0.9]];
|
||||
PTFE2_4 = ["PTFE2_4", "PTFE tubing", 4, 2, [0.95, 0.95, 0.95, 0.9]];
|
||||
PTFE2_3 = ["PTFE2_3", "PTFE tubing", 3, 2, [0.95, 0.95, 0.95, 0.9]];
|
||||
PTFE4_6 = ["PTFE4_6", "PTFE tubing", 6, 4, [0.95, 0.95, 0.95, 0.9]];
|
||||
PF7 = ["PF7", "PTFE tubing", 46/10, 3.84, [0.95, 0.95, 0.95, 0.9]];
|
||||
HSHRNK16 = ["HSHRNK16", "Heatshrink sleeving", 2.0, 1.6, "grey"];
|
||||
HSHRNK24 = ["HSHRNK24", "Heatshrink sleeving", 2.8, 2.4, "grey"];
|
||||
HSHRNK32 = ["HSHRNK32", "Heatshrink sleeving", 3.6, 3.2, "grey"];
|
||||
HSHRNK64 = ["HSHRNK64", "Heatshrink sleeving", 6.8, 6.4, "grey"];
|
||||
HSHRNK100 = ["HSHRNK100", "Heatshrink sleeving",10.4, 10.0, [0.2,0.2,0.2]];
|
||||
CARBONFIBER10 = ["CBNFIB10", "Carbon fiber", 10.0, 8.0, [0.3,0.3,0.3]];
|
||||
|
||||
PVC64 = ["PVC64", "PVC aquarium tubing", 6, 4, tubing_colour];
|
||||
PVC85 = ["PVC85", "PVC aquarium tubing", 8, 5, tubing_colour];
|
||||
NEOP85 = ["NEOP85", "Neoprene tubing", 8, 5, [0.2,0.2,0.2]];
|
||||
PTFE07 = ["PTFE07", "PTFE sleeving", 1.2, 0.71, tubing_colour];
|
||||
PTFE20 = ["PTFE20", "PTFE sleeving", 2.6, 2, tubing_colour];
|
||||
PF7 = ["PF7", "PTFE tubing", 46/10, 3.84, tubing_colour];
|
||||
HSHRNK16 = ["HSHRNK16", "Heatshrink sleeving", 2.0, 1.6, "grey"];
|
||||
HSHRNK24 = ["HSHRNK24", "Heatshrink sleeving", 2.8, 2.4, "grey"];
|
||||
HSHRNK32 = ["HSHRNK32", "Heatshrink sleeving", 3.6, 3.2, "grey"];
|
||||
HSHRNK64 = ["HSHRNK64", "Heatshrink sleeving", 6.8, 6.4, "grey"];
|
||||
HSHRNK100 = ["HSHRNK100", "Heatshrink sleeving",10.4, 10.0, [0.2,0.2,0.2]];
|
||||
|
||||
tubings = [PVC64, PVC85, NEOP85, PTFE07, PTFE20, PF7, HSHRNK16, HSHRNK24, HSHRNK64, HSHRNK100];
|
||||
tubings = [PVC64, PVC85, NEOP85, PTFE07, PTFE20, PF7, PTFE2_3, PTFE2_4, PTFE4_6, HSHRNK16, HSHRNK24, HSHRNK64, HSHRNK100, CARBONFIBER10];
|
||||
|
||||
use <tubing.scad>
|
||||
|
@@ -132,8 +132,12 @@ module veroboard(type) { //! Draw specified veroboard with missing tracks and tr
|
||||
module vero_components(type, cutouts = false, angle = undef)
|
||||
for(comp = vero_components(type))
|
||||
vero_grid_pos(type, comp.x, comp.y)
|
||||
translate_z(vero_thickness(type))
|
||||
pcb_component(comp, cutouts, angle);
|
||||
if(comp[3][0] == "-")
|
||||
vflip()
|
||||
pcb_component(comp, cutouts, angle);
|
||||
else
|
||||
translate_z(vero_thickness(type))
|
||||
pcb_component(comp, cutouts, angle);
|
||||
|
||||
module vero_cutouts(type, angle = undef) vero_components(type, true, angle); //! Make cutouts to clear components
|
||||
|
||||
|