Compare commits
92 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
b67cf4ce97 | ||
|
5bac2bf46d | ||
|
079168142b | ||
|
cb30f0c63d | ||
|
4cb324ed37 | ||
|
eb997aa18c | ||
|
f09343a285 | ||
|
54aab027bd | ||
|
cc61a11602 | ||
|
9cf2e9d7c3 | ||
|
9da8a3cb26 | ||
|
36521cf0b9 | ||
|
f760aaa20a | ||
|
1c445385b4 | ||
|
45f3fc275f | ||
|
f7fbbd5fe4 | ||
|
a769a38dff | ||
|
0485eeeb34 | ||
|
0a7208ff5a | ||
|
f32182d6df | ||
|
84fbd05f9b | ||
|
2a1fa3fe6b | ||
|
176dc3231c | ||
|
e7ac18e3c0 | ||
|
74b8dcb6d8 | ||
|
6269575fd4 | ||
|
2923e35725 | ||
|
5a1b06fbb9 | ||
|
fd174bbfb4 | ||
|
186f31bb09 | ||
|
80f0490d58 | ||
|
c9e9942070 | ||
|
e41366e20c | ||
|
0595fb5a92 | ||
|
abb676b75c | ||
|
19bae20e24 | ||
|
a7d181ffc4 | ||
|
6b2f8d282b | ||
|
5bb95b2406 | ||
|
dc3905b284 | ||
|
bd2ea3f284 | ||
|
62183bcadc | ||
|
7f9122ae66 | ||
|
93b260b7b9 | ||
|
c33876530e | ||
|
8fea8f437b | ||
|
bc3ef607af | ||
|
6bcdc24cd3 | ||
|
b8b4232882 | ||
|
0394d9981f | ||
|
e4e7096e3c | ||
|
d71bb4bdfa | ||
|
89c3767f21 | ||
|
c837de721d | ||
|
f8c87bd8e3 | ||
|
ef58fe5818 | ||
|
9c0c0c0acf | ||
|
ac6e8e040a | ||
|
accf4f7bc1 | ||
|
6bd4638e7d | ||
|
4cca9d5285 | ||
|
c3fc352288 | ||
|
a8b634de39 | ||
|
1a55a08c59 | ||
|
8ca4bb5adc | ||
|
53e3378efe | ||
|
888199f698 | ||
|
f51e93969d | ||
|
757b808f07 | ||
|
eca8f2eccc | ||
|
450224ec39 | ||
|
dcd2624a12 | ||
|
83e8502ecb | ||
|
a722df0b2b | ||
|
6d223c8d1f | ||
|
6d59ea2bc8 | ||
|
b74cbee151 | ||
|
9f7efd50fb | ||
|
0b14d3fbc4 | ||
|
8243b244af | ||
|
1a2e04367d | ||
|
abc38f2744 | ||
|
f97070099e | ||
|
729891b675 | ||
|
4b533cffd2 | ||
|
a40a2190dc | ||
|
6556d14a11 | ||
|
c7d12b20c9 | ||
|
545329b875 | ||
|
760e3a890d | ||
|
bd4f7b155b | ||
|
16c1eeef27 |
@@ -172,7 +172,7 @@ This is achieved by having a pair of modules: -
|
||||
//! Place inserts in the bottom of the posts and push them home with a soldering iron with a conical bit heated to 200°C.
|
||||
//
|
||||
module handle_assembly() pose([225, 0, 150], [0, 0, 14]) //! Printed part with inserts in place
|
||||
assembly("handle") {
|
||||
assembly("handle", ngb = true) {
|
||||
translate_z(handle_height())
|
||||
stl_colour(pp1_colour) vflip() handle_stl();
|
||||
|
||||
@@ -182,7 +182,7 @@ This is achieved by having a pair of modules: -
|
||||
}
|
||||
|
||||
module handle_fastened_assembly(thickness) { //! Assembly with fasteners in place
|
||||
screw_length = screw_longer_than(thickness + insert_length(insert) + 2 * washer_thickness(screw_washer(screw)));
|
||||
screw_length = screw_length(screw, thickness, 2, true, longer = true);
|
||||
|
||||
handle_assembly();
|
||||
|
||||
@@ -201,6 +201,9 @@ When the parent assembly is shown exploded the handle's screws will be exploded
|
||||
Note also the `pose([225, 0, 150], [0, 0, 14])` call before the `assembly()` call. This allows the sub-assembly to be posed differently in its build step but doesn't
|
||||
affect its orientation in the parent assembly. The pose parameters are the rotation and the translation taken from the GUI.
|
||||
|
||||
Setting `ngb = true` in the `assembly()` prevents the handle assembly appearing as a columun in the top level BOM in the build instructions.
|
||||
Instead its parts are merged into the parent BOM so the correct quantites are listed.
|
||||
|
||||
### Exploded diagrams
|
||||
|
||||
A lot of vitamins explode themselves when `$explode=1`. This is done with module `explode()` that can be passed a Z offset, or a 3D vector that gives the displacement
|
||||
|
@@ -2,6 +2,7 @@
|
||||
{
|
||||
"name": "base_assembly",
|
||||
"big": null,
|
||||
"ngb": false,
|
||||
"count": 1,
|
||||
"assemblies": {},
|
||||
"vitamins": {
|
||||
@@ -20,6 +21,7 @@
|
||||
{
|
||||
"name": "feet_assembly",
|
||||
"big": null,
|
||||
"ngb": false,
|
||||
"count": 1,
|
||||
"assemblies": {
|
||||
"base_assembly": 1
|
||||
@@ -46,6 +48,7 @@
|
||||
{
|
||||
"name": "mains_in_assembly",
|
||||
"big": null,
|
||||
"ngb": false,
|
||||
"count": 1,
|
||||
"assemblies": {
|
||||
"feet_assembly": 1
|
||||
@@ -82,6 +85,7 @@
|
||||
{
|
||||
"name": "main_assembly",
|
||||
"big": null,
|
||||
"ngb": false,
|
||||
"count": 1,
|
||||
"assemblies": {
|
||||
"mains_in_assembly": 1
|
||||
|
@@ -15,6 +15,7 @@ Earth leakage can be measured Canadian CSA style by disconnected the neutral lin
|
||||
|
||||

|
||||
|
||||
<span></span>
|
||||
|
||||
---
|
||||
## Table of Contents
|
||||
@@ -24,6 +25,7 @@ Earth leakage can be measured Canadian CSA style by disconnected the neutral lin
|
||||
1. [Mains In Assembly](#mains_in_assembly)
|
||||
1. [Main Assembly](#main_assembly)
|
||||
|
||||
<span></span>
|
||||
[Top](#TOP)
|
||||
|
||||
---
|
||||
@@ -54,6 +56,7 @@ Earth leakage can be measured Canadian CSA style by disconnected the neutral lin
|
||||
| 1 | . | . | . | 1 | socket_box.stl |
|
||||
| 1 | 4 | . | . | 5 | Total 3D printed parts count |
|
||||
|
||||
<span></span>
|
||||
[Top](#TOP)
|
||||
|
||||
---
|
||||
@@ -81,6 +84,7 @@ Earth leakage can be measured Canadian CSA style by disconnected the neutral lin
|
||||
|
||||

|
||||
|
||||
<span></span>
|
||||
[Top](#TOP)
|
||||
|
||||
---
|
||||
@@ -117,6 +121,7 @@ Earth leakage can be measured Canadian CSA style by disconnected the neutral lin
|
||||
|
||||

|
||||
|
||||
<span></span>
|
||||
[Top](#TOP)
|
||||
|
||||
---
|
||||
@@ -156,6 +161,7 @@ Earth leakage can be measured Canadian CSA style by disconnected the neutral lin
|
||||
|
||||

|
||||
|
||||
<span></span>
|
||||
[Top](#TOP)
|
||||
|
||||
---
|
||||
@@ -199,4 +205,5 @@ Earth leakage can be measured Canadian CSA style by disconnected the neutral lin
|
||||
|
||||

|
||||
|
||||
<span></span>
|
||||
[Top](#TOP)
|
||||
|
1
lib.scad
@@ -35,7 +35,6 @@ include <vitamins/displays.scad>
|
||||
include <vitamins/extrusions.scad>
|
||||
include <vitamins/extrusion_brackets.scad>
|
||||
include <vitamins/geared_steppers.scad>
|
||||
include <vitamins/green_terminals.scad>
|
||||
include <vitamins/hot_ends.scad>
|
||||
include <vitamins/inserts.scad>
|
||||
include <vitamins/kp_pillow_blocks.scad>
|
||||
|
BIN
libtest.png
Before Width: | Height: | Size: 862 KiB After Width: | Height: | Size: 875 KiB |
@@ -118,6 +118,7 @@ use <tests/foot.scad>
|
||||
use <tests/handle.scad>
|
||||
use <tests/PCB_mount.scad>
|
||||
use <tests/printed_box.scad>
|
||||
use <tests/printed_pulleys.scad>
|
||||
use <tests/ribbon_clamp.scad>
|
||||
use <tests/screw_knob.scad>
|
||||
use <tests/socket_box.scad>
|
||||
@@ -170,6 +171,9 @@ translate([x5, cable_grommets_y + 370])
|
||||
translate([x5 + 60, cable_grommets_y + 200])
|
||||
strap_handles();
|
||||
|
||||
translate([640, cable_grommets_y + 200])
|
||||
printed_pulley_test();
|
||||
|
||||
translate([x5, cable_grommets_y + 250])
|
||||
handle();
|
||||
|
||||
|
196
printed/box.scad
@@ -75,9 +75,9 @@ function box_corner_overlap(type) = box_wall(type);
|
||||
function box_corner_rad(type) = box_sheet_slot(type) - sheet_slot_clearance / 2 + box_corner_gap(type) + box_corner_overlap(type);
|
||||
function box_sheet_r(type) = box_corner_rad(type) - box_sheet_slot(type) - box_corner_overlap(type);
|
||||
|
||||
function box_screw_length(type, top) = screw_longer_than(2 * washer_thickness(box_washer(type))
|
||||
+ sheet_thickness(top ? box_top_sheet(type) : box_base_sheet(type))
|
||||
+ box_corner_gap(type) + box_profile_overlap(type) + box_insert_l(type) - 1);
|
||||
function box_screw_length(type, top) =
|
||||
let(s = top ? box_top_sheet(type) : box_base_sheet(type))
|
||||
screw_length(box_screw(type), sheet_thickness(s) + box_corner_gap(type) + box_profile_overlap(type) - 1, washers = 2, insert = true, longer = true);
|
||||
|
||||
function box_wall_clearance(type) = box_sheet_slot(type) / 2 - sheet_thickness(box_sheets(type)) / 2;
|
||||
function box_margin(type) = box_profile_overlap(type) + box_corner_gap(type); //! How much the bezel intrudes on the specified height
|
||||
@@ -139,17 +139,17 @@ module box_corner_profile_2D(type) { //! The 2D shape of the corner profile.
|
||||
}
|
||||
|
||||
module box_corner_profile(type) { //! Generates the corner profile STL for 3D printing.
|
||||
stl("box_corner_profile");
|
||||
|
||||
length = box_height(type) - 2 * box_margin(type);
|
||||
difference() {
|
||||
linear_extrude(length, center = true, convexity = 5)
|
||||
box_corner_profile_2D(type);
|
||||
|
||||
for(z = [-1, 1])
|
||||
translate([box_hole_inset(type), box_hole_inset(type), z * length / 2])
|
||||
insert_hole(box_insert(type), 5);
|
||||
}
|
||||
stl("box_corner_profile")
|
||||
difference() {
|
||||
linear_extrude(length, center = true, convexity = 5)
|
||||
box_corner_profile_2D(type);
|
||||
|
||||
for(z = [-1, 1])
|
||||
translate([box_hole_inset(type), box_hole_inset(type), z * length / 2])
|
||||
insert_hole(box_insert(type), 5);
|
||||
}
|
||||
}
|
||||
|
||||
module box_corner_profile_section(type, section, sections) { //! Generates interlocking sections of the corner profile to allow it to be taller than the printer
|
||||
@@ -209,7 +209,6 @@ module box_corner_quadrants(type, width, depth)
|
||||
}
|
||||
|
||||
module box_bezel(type, bottom) { //! Generates top and bottom bezel STLs
|
||||
stl(bottom ? "bottom_bezel" : "top_bezel");
|
||||
feet = bottom && box_feet(type);
|
||||
t = box_sheet_slot(type);
|
||||
outset = box_outset(type);
|
||||
@@ -221,66 +220,67 @@ module box_bezel(type, bottom) { //! Generates top and bottom bezel STLs
|
||||
height = box_bezel_height(type, bottom);
|
||||
foot_extension = foot_height - height;
|
||||
|
||||
difference() {
|
||||
w = box_width(type);
|
||||
d = box_depth(type);
|
||||
translate_z(-box_profile_overlap(type)) difference() {
|
||||
tw = w + 2 * outset;
|
||||
td = d + 2 * outset;
|
||||
rounded_rectangle([tw, td, feet ? foot_height : height], box_corner_rad(type), false);
|
||||
//
|
||||
// Remove edges between the feet
|
||||
//
|
||||
if(feet)
|
||||
hull() {
|
||||
translate_z(height + 0.5)
|
||||
cube([w - 2 * foot_length, td + 1, 1], center = true);
|
||||
stl(bottom ? "bottom_bezel" : "top_bezel")
|
||||
difference() {
|
||||
w = box_width(type);
|
||||
d = box_depth(type);
|
||||
translate_z(-box_profile_overlap(type)) difference() {
|
||||
tw = w + 2 * outset;
|
||||
td = d + 2 * outset;
|
||||
rounded_rectangle([tw, td, feet ? foot_height : height], box_corner_rad(type), false);
|
||||
//
|
||||
// Remove edges between the feet
|
||||
//
|
||||
if(feet)
|
||||
hull() {
|
||||
translate_z(height + 0.5)
|
||||
cube([w - 2 * foot_length, td + 1, 1], center = true);
|
||||
|
||||
translate_z(foot_height + 1)
|
||||
cube([w - 2 * (foot_length - foot_extension), td + 1, 1], center = true);
|
||||
}
|
||||
if(feet)
|
||||
hull() {
|
||||
translate_z(height + 0.5)
|
||||
cube([tw + 1, d - 2 * foot_length, 1], center = true);
|
||||
|
||||
translate_z(foot_height + 1)
|
||||
cube([tw + 1, d - 2 * (foot_length - foot_extension), 1], center = true);
|
||||
}
|
||||
}
|
||||
//
|
||||
// slots for side panels
|
||||
//
|
||||
translate_z(-box_profile_overlap(type))
|
||||
linear_extrude(2 * box_profile_overlap(type), center = true)
|
||||
for(i = [-1, 1]) {
|
||||
translate([i * (w + t - sheet_slot_clearance) / 2, 0])
|
||||
square([t, d - 2 * cgap], center = true);
|
||||
|
||||
translate([0, i * (d + t - sheet_slot_clearance) / 2])
|
||||
square([w - 2 * cgap, t], center = true);
|
||||
}
|
||||
//
|
||||
// recess for top / bottom panel
|
||||
//
|
||||
translate_z(cgap)
|
||||
rounded_rectangle([w + bezel_clearance, d + bezel_clearance, height], inner_r + bezel_clearance / 2, false);
|
||||
//
|
||||
// leave plastic over the corner profiles
|
||||
//
|
||||
translate_z(-box_profile_overlap(type) - 1)
|
||||
linear_extrude(box_profile_overlap(type) + cgap + 2)
|
||||
union() {
|
||||
difference() {
|
||||
square([w - 2 * inset,
|
||||
d - 2 * inset], center = true);
|
||||
|
||||
box_corner_quadrants(type, w, d);
|
||||
translate_z(foot_height + 1)
|
||||
cube([w - 2 * (foot_length - foot_extension), td + 1, 1], center = true);
|
||||
}
|
||||
box_screw_hole_positions(type)
|
||||
poly_circle(screw_clearance_radius(box_screw(type)));
|
||||
}
|
||||
}
|
||||
if(feet)
|
||||
hull() {
|
||||
translate_z(height + 0.5)
|
||||
cube([tw + 1, d - 2 * foot_length, 1], center = true);
|
||||
|
||||
translate_z(foot_height + 1)
|
||||
cube([tw + 1, d - 2 * (foot_length - foot_extension), 1], center = true);
|
||||
}
|
||||
}
|
||||
//
|
||||
// slots for side panels
|
||||
//
|
||||
translate_z(-box_profile_overlap(type))
|
||||
linear_extrude(2 * box_profile_overlap(type), center = true)
|
||||
for(i = [-1, 1]) {
|
||||
translate([i * (w + t - sheet_slot_clearance) / 2, 0])
|
||||
square([t, d - 2 * cgap], center = true);
|
||||
|
||||
translate([0, i * (d + t - sheet_slot_clearance) / 2])
|
||||
square([w - 2 * cgap, t], center = true);
|
||||
}
|
||||
//
|
||||
// recess for top / bottom panel
|
||||
//
|
||||
translate_z(cgap)
|
||||
rounded_rectangle([w + bezel_clearance, d + bezel_clearance, height], inner_r + bezel_clearance / 2, false);
|
||||
//
|
||||
// leave plastic over the corner profiles
|
||||
//
|
||||
translate_z(-box_profile_overlap(type) - 1)
|
||||
linear_extrude(box_profile_overlap(type) + cgap + 2)
|
||||
union() {
|
||||
difference() {
|
||||
square([w - 2 * inset,
|
||||
d - 2 * inset], center = true);
|
||||
|
||||
box_corner_quadrants(type, w, d);
|
||||
}
|
||||
box_screw_hole_positions(type)
|
||||
poly_circle(screw_clearance_radius(box_screw(type)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dowel_length = 20;
|
||||
@@ -485,7 +485,6 @@ module box_shelf_screw_positions(type, screw_positions, thickness = 0, wall = un
|
||||
}
|
||||
|
||||
module box_shelf_bracket(type, screw_positions, wall = undef) { //! Generates a shelf bracket, the first optional child is a 2D cutout and the second 3D cutouts
|
||||
stl("shelf_bracket");
|
||||
w = is_undef(wall) ? box_wall(type) : wall;
|
||||
insert = box_shelf_insert(type);
|
||||
lip = 2 * insert_boss_radius(insert, w);
|
||||
@@ -513,44 +512,45 @@ module box_shelf_bracket(type, screw_positions, wall = undef) { //! Generates a
|
||||
square([lip, eps]);
|
||||
}
|
||||
|
||||
difference() {
|
||||
union() {
|
||||
linear_extrude(w)
|
||||
difference() {
|
||||
shape()
|
||||
if($children)
|
||||
children(0);
|
||||
|
||||
round(2) offset(-width)
|
||||
stl("shelf_bracket")
|
||||
difference() {
|
||||
union() {
|
||||
linear_extrude(w)
|
||||
difference() {
|
||||
shape()
|
||||
if($children)
|
||||
children(0);
|
||||
}
|
||||
|
||||
linear_extrude(lip)
|
||||
difference() {
|
||||
shape()
|
||||
if($children)
|
||||
children(0);
|
||||
round(2) offset(-width)
|
||||
shape()
|
||||
if($children)
|
||||
children(0);
|
||||
}
|
||||
|
||||
offset(-w)
|
||||
linear_extrude(lip)
|
||||
difference() {
|
||||
shape()
|
||||
if($children)
|
||||
children(0);
|
||||
}
|
||||
|
||||
offset(-w)
|
||||
shape()
|
||||
if($children)
|
||||
children(0);
|
||||
}
|
||||
|
||||
hflip()
|
||||
box_shelf_screw_positions(type, screw_positions, 0, w)
|
||||
boss();
|
||||
}
|
||||
if($children > 1)
|
||||
hflip()
|
||||
children(1);
|
||||
|
||||
hflip()
|
||||
box_shelf_screw_positions(type, screw_positions, 0, w)
|
||||
boss();
|
||||
insert_hole(insert, counterbore = 1, horizontal = true);
|
||||
}
|
||||
if($children > 1)
|
||||
hflip()
|
||||
children(1);
|
||||
|
||||
hflip()
|
||||
box_shelf_screw_positions(type, screw_positions, 0, w)
|
||||
insert_hole(insert, counterbore = 1, horizontal = true);
|
||||
}
|
||||
}
|
||||
|
||||
module box_shelf_bracket_section(type, rows, cols, x, y) { //! Generates sections of the shelf bracket to allow it to be bigger than the printer
|
||||
|
@@ -49,84 +49,84 @@ module ribbon_grommet_hole(ways, h = 50, expand = true) { //! Generate a hole fo
|
||||
}
|
||||
|
||||
module ribbon_grommet(ways, thickness) { //! Generate the STL for a printed ribbon grommet
|
||||
stl(str("ribbon_grommet_", ways, "_", thickness));
|
||||
|
||||
width = 2 * (wall + clearance) + thickness;
|
||||
slot_length = ribbon_clamp_slot(ways);
|
||||
length = slot_length + 2 * wall + 2 * overlap;
|
||||
|
||||
rotate([90, 0, 0])
|
||||
union() {
|
||||
for(side = [-1, 1])
|
||||
translate_z(side * (width - wall) / 2)
|
||||
linear_extrude(wall, center = true, convexity = 5)
|
||||
difference() {
|
||||
hull() {
|
||||
translate([-length / 2, 0])
|
||||
square([length, base]);
|
||||
stl(str("ribbon_grommet_", ways, "_", thickness))
|
||||
rotate([90, 0, 0])
|
||||
union() {
|
||||
for(side = [-1, 1])
|
||||
translate_z(side * (width - wall) / 2)
|
||||
linear_extrude(wall, center = true, convexity = 5)
|
||||
difference() {
|
||||
hull() {
|
||||
translate([-length / 2, 0])
|
||||
square([length, base]);
|
||||
|
||||
for(end = [-1, 1])
|
||||
translate([end * (length / 2 - rad), height - rad])
|
||||
semi_circle(rad);
|
||||
for(end = [-1, 1])
|
||||
translate([end * (length / 2 - rad), height - rad])
|
||||
semi_circle(rad);
|
||||
}
|
||||
translate([-slot_length / 2, base])
|
||||
square([slot_length, slot_height]);
|
||||
}
|
||||
translate([-slot_length / 2, base])
|
||||
square([slot_length, slot_height]);
|
||||
}
|
||||
|
||||
linear_extrude(width -1, center = true)
|
||||
difference() {
|
||||
ribbon_grommet_hole(ways, expand = false, h = 0);
|
||||
linear_extrude(width -1, center = true)
|
||||
difference() {
|
||||
ribbon_grommet_hole(ways, expand = false, h = 0);
|
||||
|
||||
translate([-slot_length / 2, base])
|
||||
square([slot_length, slot_height]);
|
||||
}
|
||||
}
|
||||
translate([-slot_length / 2, base])
|
||||
square([slot_length, slot_height]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module round_grommet_top(diameter, thickness, od = undef) { //! Generate the STL for a round grommet top half
|
||||
stl(str("round_grommet_top_", round(diameter * 10), "_", thickness));
|
||||
chamfer = layer_height;
|
||||
h = wall + thickness + wall;
|
||||
r1 = diameter / 2;
|
||||
r2 = od == undef ? corrected_radius(r1) + wall : od / 2;
|
||||
r3 = r2 + overlap;
|
||||
r0 = r1 + 1;
|
||||
union() {
|
||||
rotate_extrude()
|
||||
polygon([
|
||||
[r0, 0],
|
||||
[r3 - chamfer, 0],
|
||||
[r3, chamfer],
|
||||
[r3, wall],
|
||||
[r2, wall],
|
||||
[r2, h - chamfer],
|
||||
[r2 - chamfer, h],
|
||||
[r0, h],
|
||||
]);
|
||||
stl(str("round_grommet_top_", round(diameter * 10), "_", thickness))
|
||||
union() {
|
||||
rotate_extrude()
|
||||
polygon([
|
||||
[r0, 0],
|
||||
[r3 - chamfer, 0],
|
||||
[r3, chamfer],
|
||||
[r3, wall],
|
||||
[r2, wall],
|
||||
[r2, h - chamfer],
|
||||
[r2 - chamfer, h],
|
||||
[r0, h],
|
||||
]);
|
||||
|
||||
render() difference() {
|
||||
cylinder(r = r0 + eps, h = h);
|
||||
render() difference() {
|
||||
cylinder(r = r0 + eps, h = h);
|
||||
|
||||
poly_cylinder(r = r1, h = 100, center = true);
|
||||
poly_cylinder(r = r1, h = 100, center = true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module round_grommet_bottom(diameter, od = undef) { //! Generate the STL for a round grommet bottom half
|
||||
stl(str("round_grommet_bottom_", round(diameter * 10)));
|
||||
chamfer = layer_height;
|
||||
r1 = diameter / 2;
|
||||
r2 = od == undef ? corrected_radius(r1) + wall : od / 2;
|
||||
r3 = r2 + max(overlap, wall + chamfer);
|
||||
rotate_extrude()
|
||||
polygon([
|
||||
[r2, chamfer],
|
||||
[r2 + chamfer, 0],
|
||||
[r3, 0],
|
||||
[r3, wall - chamfer],
|
||||
[r3 - chamfer, wall],
|
||||
[r2, wall],
|
||||
]);
|
||||
stl(str("round_grommet_bottom_", round(diameter * 10)))
|
||||
rotate_extrude()
|
||||
polygon([
|
||||
[r2, chamfer],
|
||||
[r2 + chamfer, 0],
|
||||
[r3, 0],
|
||||
[r3, wall - chamfer],
|
||||
[r3 - chamfer, wall],
|
||||
[r2, wall],
|
||||
]);
|
||||
}
|
||||
|
||||
module round_grommet_hole(diameter, h = 100) //! Make a hole for a round grommet
|
||||
@@ -161,30 +161,30 @@ module mouse_grommet_hole(r, h = 50, z = undef, expand = wall + clearance) //! M
|
||||
function mouse_grommet_offset(r) = r + wall;
|
||||
|
||||
module mouse_grommet(r, thickness) { //! Make the STL for a mouse grommet
|
||||
stl(str("mouse_grommet_", r * 10, "_", thickness));
|
||||
|
||||
width = 2 * (wall + clearance) + thickness;
|
||||
length = 2 * r + 2 * wall + 2 * overlap;
|
||||
|
||||
rotate([90, 0, 0])
|
||||
union() {
|
||||
for(side = [-1, 1])
|
||||
translate_z(side * (width - wall) / 2)
|
||||
linear_extrude(wall, center = true)
|
||||
difference() {
|
||||
mouse_grommet_hole(r, z = r + wall, h = 0, expand = wall + overlap);
|
||||
stl(str("mouse_grommet_", r * 10, "_", thickness))
|
||||
rotate([90, 0, 0])
|
||||
union() {
|
||||
for(side = [-1, 1])
|
||||
translate_z(side * (width - wall) / 2)
|
||||
linear_extrude(wall, center = true)
|
||||
difference() {
|
||||
mouse_grommet_hole(r, z = r + wall, h = 0, expand = wall + overlap);
|
||||
|
||||
translate([0, wall])
|
||||
mouse_grommet_hole(r, h = 0, expand = 0);
|
||||
}
|
||||
linear_extrude(width - 1, center = true)
|
||||
difference() {
|
||||
mouse_grommet_hole(r, h = 0, z = r + wall, expand = wall);
|
||||
|
||||
translate([0, wall])
|
||||
mouse_grommet_hole(r, h = 0, expand = 0);
|
||||
}
|
||||
linear_extrude(width - 1, center = true)
|
||||
difference() {
|
||||
mouse_grommet_hole(r, h = 0, z = r + wall, expand = wall);
|
||||
|
||||
translate([0, wall])
|
||||
mouse_grommet_hole(r, h = 0, expand = 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module mouse_grommet_assembly(r, thickness)
|
||||
|
@@ -68,7 +68,7 @@ function cam_screw_length(cam) = let(
|
||||
front = cam_front_size(cam),
|
||||
screw = pcb_screw(camera_pcb(cam)),
|
||||
nut = screw_nut(screw)
|
||||
) screw_longer_than(front.z + washer_thickness(screw_washer(screw)) - nut_trap_depth(nut) + nut_thickness(nut, true));
|
||||
) screw_length(screw, front.z - nut_trap_depth(nut), 1, nyloc = true);
|
||||
|
||||
function hinge_z(cam) = cam_screw_length(cam) - hinge_r;
|
||||
|
||||
@@ -82,7 +82,6 @@ module cam_holes(cam) {
|
||||
}
|
||||
|
||||
module rpi_camera_focus_ring_stl() { //! Focus ring the glue onto RPI lens
|
||||
stl("rpi_camera_focus_ring");
|
||||
|
||||
rad = 15 / 2;
|
||||
hole_r1 = 2.5 / 2;
|
||||
@@ -93,58 +92,58 @@ module rpi_camera_focus_ring_stl() { //! Focus ring the glue onto RPI lens
|
||||
x = rad / (sin(angle / 2) + cos(angle / 2));
|
||||
r = x * sin(angle / 2);
|
||||
|
||||
difference() {
|
||||
linear_extrude(height = thickness, convexity = 5)
|
||||
difference() {
|
||||
union() {
|
||||
circle(x);
|
||||
stl("rpi_camera_focus_ring")
|
||||
difference() {
|
||||
linear_extrude(height = thickness, convexity = 5)
|
||||
difference() {
|
||||
union() {
|
||||
circle(x);
|
||||
for(i = [0 : flutes - 1])
|
||||
rotate([0, 0, 2 * angle * i])
|
||||
translate([x, 0])
|
||||
circle(r);
|
||||
}
|
||||
for(i = [0 : flutes - 1])
|
||||
rotate([0, 0, 2 * angle * i])
|
||||
rotate([0, 0, 2 * angle * i + angle])
|
||||
translate([x, 0])
|
||||
circle(r);
|
||||
}
|
||||
for(i = [0 : flutes - 1])
|
||||
rotate([0, 0, 2 * angle * i + angle])
|
||||
translate([x, 0])
|
||||
circle(r);
|
||||
}
|
||||
hull() {
|
||||
poly_cylinder(r = hole_r1, h = 0.1, center = true);
|
||||
hull() {
|
||||
poly_cylinder(r = hole_r1, h = 0.1, center = true);
|
||||
|
||||
translate([0, 0, thickness])
|
||||
poly_cylinder(r = hole_r2, h = 0.1, center = true);
|
||||
translate([0, 0, thickness])
|
||||
poly_cylinder(r = hole_r2, h = 0.1, center = true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module camera_back(cam) { //! Make the STL for a camera case back
|
||||
stl(str("camera_back_", cam[0]));
|
||||
pcb = camera_pcb(cam);
|
||||
back = cam_back_size(cam);
|
||||
screw = pcb_screw(pcb);
|
||||
nut = screw_nut(screw);
|
||||
|
||||
translate_z(back.z)
|
||||
hflip()
|
||||
difference() {
|
||||
translate_z(back.z / 2)
|
||||
cube(back, center = true);
|
||||
stl(str("camera_back_", cam[0]))
|
||||
translate_z(back.z)
|
||||
hflip()
|
||||
difference() {
|
||||
translate_z(back.z / 2)
|
||||
cube(back, center = true);
|
||||
|
||||
translate([0, -cam_back_overlap])
|
||||
cube([pcb_length(pcb) - 2 * cam_back_overlap, pcb_width(pcb), 2 * cam_back_clearance], center = true);
|
||||
translate([0, -cam_back_overlap])
|
||||
cube([pcb_length(pcb) - 2 * cam_back_overlap, pcb_width(pcb), 2 * cam_back_clearance], center = true);
|
||||
|
||||
translate([0, -pcb_width(pcb) / 2])
|
||||
cube([connector_size.x + 2 * clearance, 2 * connector_size.y + 1, 2 * round_to_layer(connector_size.z + clearance)], center = true);
|
||||
translate([0, -pcb_width(pcb) / 2])
|
||||
cube([connector_size.x + 2 * clearance, 2 * connector_size.y + 1, 2 * round_to_layer(connector_size.z + clearance)], center = true);
|
||||
|
||||
translate_z(back.z)
|
||||
cam_holes(cam)
|
||||
hflip()
|
||||
nut_trap(screw, nut, supported = true);
|
||||
}
|
||||
translate_z(back.z)
|
||||
cam_holes(cam)
|
||||
hflip()
|
||||
nut_trap(screw, nut, supported = true);
|
||||
}
|
||||
}
|
||||
|
||||
module camera_front(cam, hinge = 0) { //! Make the STL for a camera case front
|
||||
stl(str("camera_front_", cam[0]));
|
||||
front = cam_front_size(cam);
|
||||
back = cam_back_size(cam);
|
||||
pcb = camera_pcb(cam);
|
||||
@@ -170,70 +169,71 @@ module camera_front(cam, hinge = 0) { //! Make the STL for a camera case front
|
||||
translate([0, (hinge ? front.x * hinge : front.y) / 2 + hinge_offset, hinge_r])
|
||||
children();
|
||||
|
||||
difference() {
|
||||
union() {
|
||||
hull()
|
||||
for(x = [-1, 1], y = [-1, 1])
|
||||
translate([x * (front.x / 2 - rad), y * (front.y / 2 - rad)])
|
||||
hull() { // 3D truncated teardrop gives radiused edges without exceeding 45 degree overhang
|
||||
translate_z(front.z - 1)
|
||||
cylinder(r = rad, h = 1);
|
||||
stl(str("camera_front_", cam[0]))
|
||||
difference() {
|
||||
union() {
|
||||
hull()
|
||||
for(x = [-1, 1], y = [-1, 1])
|
||||
translate([x * (front.x / 2 - rad), y * (front.y / 2 - rad)])
|
||||
hull() { // 3D truncated teardrop gives radiused edges without exceeding 45 degree overhang
|
||||
translate_z(front.z - 1)
|
||||
cylinder(r = rad, h = 1);
|
||||
|
||||
translate_z(rad)
|
||||
sphere(rad);
|
||||
translate_z(rad)
|
||||
sphere(rad);
|
||||
|
||||
cylinder(r = rad * (sqrt(2) - 1), h = eps);
|
||||
}
|
||||
cylinder(r = rad * (sqrt(2) - 1), h = eps);
|
||||
}
|
||||
|
||||
hinge_pos()
|
||||
hull() {
|
||||
rotate([-90, 0, -90])
|
||||
teardrop(r = hinge_r, h = hinge_h, center = false);
|
||||
hinge_pos()
|
||||
hull() {
|
||||
rotate([-90, 0, -90])
|
||||
teardrop(r = hinge_r, h = hinge_h, center = false);
|
||||
|
||||
translate([0, -10, -hinge_r])
|
||||
cube([hinge_h, eps, 2 * hinge_r]);
|
||||
}
|
||||
}
|
||||
|
||||
hinge_pos()
|
||||
rotate([90, 0, 90])
|
||||
teardrop_plus(r = screw_clearance_radius(hinge_screw), h = 100, center = true);
|
||||
|
||||
translate_z(front.z / 2 + shelf - layer_height) // recess for the back
|
||||
cube([back.x + 2 * clearance, back.y + 2 * clearance, front.z], center = true);
|
||||
|
||||
translate_z(front.z / 2 + shelf - pcb_size.z) // recess for PCB
|
||||
cube([pcb_size.x + 2 * clearance, pcb_size.y + 2 * clearance, front.z], center = true);
|
||||
|
||||
translate_z(shelf)
|
||||
hflip() {
|
||||
pcb_component_position(pcb, "smd_led") // clearance for LED
|
||||
cube(led_clearance, center = true);
|
||||
|
||||
pcb_component_position(pcb, "smd_res") // clearance for resistor
|
||||
cube(res_clearance, center = true);
|
||||
translate([0, -10, -hinge_r])
|
||||
cube([hinge_h, eps, 2 * hinge_r]);
|
||||
}
|
||||
}
|
||||
|
||||
translate([conn_pos.x, lens_offset.y + sensor_length / 2, shelf - pcb_size.z]) // clearance for sensor connector
|
||||
cube([conn.x + 2 * clearance, sensor_length, 2 * cam_front_clearance(cam)], center = true);
|
||||
hinge_pos()
|
||||
rotate([90, 0, 90])
|
||||
teardrop_plus(r = screw_clearance_radius(hinge_screw), h = 100, center = true);
|
||||
|
||||
translate([0, -front.y / 2, shelf + front.z / 2]) // slot for connector
|
||||
cube([connector_slot.x, connector_slot.y, front.z], center = true);
|
||||
translate_z(front.z / 2 + shelf - layer_height) // recess for the back
|
||||
cube([back.x + 2 * clearance, back.y + 2 * clearance, front.z], center = true);
|
||||
|
||||
translate_z(cam_back_clearance + layer_height)
|
||||
cam_holes(cam)
|
||||
rotate(90)
|
||||
poly_cylinder(r = screw_clearance_radius(screw), h = 100, center = true);
|
||||
translate_z(front.z / 2 + shelf - pcb_size.z) // recess for PCB
|
||||
cube([pcb_size.x + 2 * clearance, pcb_size.y + 2 * clearance, front.z], center = true);
|
||||
|
||||
translate_z(shelf)
|
||||
hflip() {
|
||||
pcb_component_position(pcb, "smd_led") // clearance for LED
|
||||
cube(led_clearance, center = true);
|
||||
|
||||
pcb_component_position(pcb, "smd_res") // clearance for resistor
|
||||
cube(res_clearance, center = true);
|
||||
}
|
||||
|
||||
translate([conn_pos.x, lens_offset.y + sensor_length / 2, shelf - pcb_size.z]) // clearance for sensor connector
|
||||
cube([conn.x + 2 * clearance, sensor_length, 2 * cam_front_clearance(cam)], center = true);
|
||||
|
||||
translate([0, -front.y / 2, shelf + front.z / 2]) // slot for connector
|
||||
cube([connector_slot.x, connector_slot.y, front.z], center = true);
|
||||
|
||||
translate_z(cam_back_clearance + layer_height)
|
||||
cam_holes(cam)
|
||||
rotate(90)
|
||||
poly_cylinder(r = screw_clearance_radius(screw), h = 100, center = true);
|
||||
|
||||
translate_z(shelf - pcb_size.z)
|
||||
hflip()
|
||||
camera_lens(cam, clearance);
|
||||
|
||||
translate_z(shelf - pcb_size.z)
|
||||
hflip()
|
||||
camera_lens(cam, clearance);
|
||||
|
||||
hflip()
|
||||
pcb_component_position(pcb, "smd_led")
|
||||
rotate(45)
|
||||
poly_cylinder(r = led_hole_r, h = 100, center = true); // hole for led
|
||||
}
|
||||
pcb_component_position(pcb, "smd_led")
|
||||
rotate(45)
|
||||
poly_cylinder(r = led_hole_r, h = 100, center = true); // hole for led
|
||||
}
|
||||
}
|
||||
|
||||
function bracket_thickness(cam) = max(wall, min(3.5, hinge_z(cam) - hinge_r - 1));
|
||||
@@ -253,38 +253,39 @@ module camera_bracket_position(cam) //! Position children at the bracket positio
|
||||
children();
|
||||
|
||||
module camera_bracket(cam) { //! Make the STL for the camera bracket
|
||||
stl(str("camera_bracket_", cam[0]));
|
||||
|
||||
t = bracket_thickness(cam);
|
||||
z = hinge_z(cam);
|
||||
translate([hinge_h / 2, 0])
|
||||
difference() {
|
||||
hull() {
|
||||
translate_z(eps / 2)
|
||||
cube([hinge_h, 2 * hinge_r, eps], center = true);
|
||||
|
||||
translate_z(z)
|
||||
rotate([0, 90, 0])
|
||||
cylinder(r = hinge_r, h = hinge_h, center = true);
|
||||
stl(str("camera_bracket_", cam[0])) union() {
|
||||
translate([hinge_h / 2, 0])
|
||||
difference() {
|
||||
hull() {
|
||||
translate_z(eps / 2)
|
||||
cube([hinge_h, 2 * hinge_r, eps], center = true);
|
||||
|
||||
translate_z(z)
|
||||
rotate([0, 90, 0])
|
||||
cylinder(r = hinge_r, h = hinge_h, center = true);
|
||||
}
|
||||
translate([hinge_h / 2, 0, z])
|
||||
rotate([90, 0, 90])
|
||||
nut_trap(hinge_screw, screw_nut(hinge_screw), horizontal = true);
|
||||
}
|
||||
translate([hinge_h / 2, 0, z])
|
||||
rotate([90, 0, 90])
|
||||
nut_trap(hinge_screw, screw_nut(hinge_screw), horizontal = true);
|
||||
}
|
||||
|
||||
linear_extrude(t)
|
||||
difference() {
|
||||
hull()
|
||||
linear_extrude(t)
|
||||
difference() {
|
||||
hull()
|
||||
camera_bracket_screw_positions(cam)
|
||||
circle(washer_radius(screw_washer(bracket_screw)) + 0.5);
|
||||
|
||||
camera_bracket_screw_positions(cam)
|
||||
circle(washer_radius(screw_washer(bracket_screw)) + 0.5);
|
||||
|
||||
camera_bracket_screw_positions(cam)
|
||||
poly_circle(screw_clearance_radius(bracket_screw));
|
||||
}
|
||||
poly_circle(screw_clearance_radius(bracket_screw));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module camera_assembly(cam, angle = 0) //! Camera case assembly
|
||||
assembly(str("camera_", cam[0])) {
|
||||
assembly(str("camera_", cam[0]), ngb = true) {
|
||||
front = cam_front_size(cam);
|
||||
screw = pcb_screw(camera_pcb(cam));
|
||||
nut = screw_nut(screw);
|
||||
@@ -344,9 +345,8 @@ module camera_fastened_assembly(cam, thickness, angle = 0) {
|
||||
camera_bracket_position(cam)
|
||||
camera_bracket_screw_positions(cam) {
|
||||
nut = screw_nut(bracket_screw);
|
||||
washer = screw_washer(bracket_screw);
|
||||
t = bracket_thickness(cam);
|
||||
screw_length = screw_longer_than(thickness + t + nut_thickness(nut, true) + 2 * washer_thickness(washer));
|
||||
screw_length = screw_length(bracket_screw, thickness + t, 2, nyloc = true);
|
||||
vflip()
|
||||
translate_z(thickness)
|
||||
screw_and_washer(bracket_screw, screw_length);
|
||||
|
@@ -27,7 +27,6 @@ include <../utils/core/core.scad>
|
||||
function carrier_height() = 3; //! Height of PCB carrier
|
||||
|
||||
module ESP12F_carrier_stl() { //! Generate the STL for an ESP12 carrier
|
||||
stl("ESP12F_carrier");
|
||||
pins = 8;
|
||||
pitch1 = 2;
|
||||
pitch2 = 2.54;
|
||||
@@ -43,29 +42,29 @@ module ESP12F_carrier_stl() { //! Generate the STL for an ESP12 carrier
|
||||
width1 = wpitch1 + hole + squeezed_wall * 2;
|
||||
width2 = wpitch2 + hole2 + squeezed_wall * 2;
|
||||
|
||||
difference() {
|
||||
hull() {
|
||||
translate_z(height - eps / 2)
|
||||
cube([width1, length1, eps], center = true);
|
||||
stl("ESP12F_carrier")
|
||||
difference() {
|
||||
hull() {
|
||||
translate_z(height - eps / 2)
|
||||
cube([width1, length1, eps], center = true);
|
||||
|
||||
translate_z(eps / 2)
|
||||
cube([width2, length2, eps], center = true);
|
||||
translate_z(eps / 2)
|
||||
cube([width2, length2, eps], center = true);
|
||||
}
|
||||
|
||||
for(side = [-1, 1])
|
||||
for(i = [0 : pins - 1])
|
||||
hull() {
|
||||
translate([side * wpitch1 / 2, i * pitch1 - (pins - 1) * pitch1 / 2, height])
|
||||
cube([hole, hole, eps], center = true);
|
||||
|
||||
translate([side * wpitch2 / 2, i * pitch2 - (pins - 1) * pitch2 / 2])
|
||||
cube([hole2, hole2, eps], center = true);
|
||||
}
|
||||
}
|
||||
|
||||
for(side = [-1, 1])
|
||||
for(i = [0 : pins - 1])
|
||||
hull() {
|
||||
translate([side * wpitch1 / 2, i * pitch1 - (pins - 1) * pitch1 / 2, height])
|
||||
cube([hole, hole, eps], center = true);
|
||||
|
||||
translate([side * wpitch2 / 2, i * pitch2 - (pins - 1) * pitch2 / 2])
|
||||
cube([hole2, hole2, eps], center = true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module TP4056_carrier_stl() { //! Generate the STL for an TP4056 carrier, two required
|
||||
stl("TP4056_carrier");
|
||||
pitch = 2.54;
|
||||
outer_pitch = 13.9;
|
||||
inner_pitch = 7.54;
|
||||
@@ -78,30 +77,30 @@ module TP4056_carrier_stl() { //! Generate the STL for an TP4056 carrier, two re
|
||||
width = hole + squeezed_wall * 2;
|
||||
spacing = inch(0.9);
|
||||
|
||||
difference() {
|
||||
hull() {
|
||||
translate_z(height - eps / 2)
|
||||
cube([width, length1, eps], center = true);
|
||||
stl("TP4056_carrier")
|
||||
difference() {
|
||||
hull() {
|
||||
translate_z(height - eps / 2)
|
||||
cube([width, length1, eps], center = true);
|
||||
|
||||
translate_z(eps / 2)
|
||||
cube([width, length2, eps], center = true);
|
||||
translate_z(eps / 2)
|
||||
cube([width, length2, eps], center = true);
|
||||
}
|
||||
|
||||
for(i = [0 : pins - 1])
|
||||
let(x = [-outer_pitch / 2, - inner_pitch / 2, 0, 0, inner_pitch / 2, outer_pitch / 2][i])
|
||||
if(x)
|
||||
hull() {
|
||||
translate([0, x, height])
|
||||
cube([hole, hole, eps], center = true);
|
||||
|
||||
translate([0, i * pitch - (pins - 1) * pitch / 2])
|
||||
cube([hole, hole, eps], center = true);
|
||||
}
|
||||
}
|
||||
|
||||
for(i = [0 : pins - 1])
|
||||
let(x = [-outer_pitch / 2, - inner_pitch / 2, 0, 0, inner_pitch / 2, outer_pitch / 2][i])
|
||||
if(x)
|
||||
hull() {
|
||||
translate([0, x, height])
|
||||
cube([hole, hole, eps], center = true);
|
||||
|
||||
translate([0, i * pitch - (pins - 1) * pitch / 2])
|
||||
cube([hole, hole, eps], center = true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module MT3608_carrier_stl() { //! Generate the STL for an MT3608 carrier, two required
|
||||
stl("MT3608_carrier");
|
||||
pcb_width = 17;
|
||||
w_pitch_top = 6.81;
|
||||
w_pitch_bot = inch(0.3);
|
||||
@@ -113,21 +112,22 @@ module MT3608_carrier_stl() { //! Generate the STL for an MT3608 carrier, two re
|
||||
width = hole + 2 * wall;
|
||||
offset = (l_pitch_top - l_pitch_bot) / 2;
|
||||
|
||||
difference() {
|
||||
hull() {
|
||||
translate([offset, 0, height - eps / 2])
|
||||
rounded_rectangle([width, pcb_width - 2, eps], 1);
|
||||
|
||||
translate_z(eps / 2)
|
||||
rounded_rectangle([width, pcb_width - 2, eps], 1);
|
||||
}
|
||||
for(side = [-1, 1])
|
||||
stl("MT3608_carrier")
|
||||
difference() {
|
||||
hull() {
|
||||
translate([offset, side * w_pitch_top / 2, height])
|
||||
cube([hole, hole, eps], center = true);
|
||||
translate([offset, 0, height - eps / 2])
|
||||
rounded_rectangle([width, pcb_width - 2, eps], 1);
|
||||
|
||||
translate([0, side * w_pitch_bot / 2])
|
||||
cube([hole, hole, eps], center = true);
|
||||
translate_z(eps / 2)
|
||||
rounded_rectangle([width, pcb_width - 2, eps], 1);
|
||||
}
|
||||
}
|
||||
for(side = [-1, 1])
|
||||
hull() {
|
||||
translate([offset, side * w_pitch_top / 2, height])
|
||||
cube([hole, hole, eps], center = true);
|
||||
|
||||
translate([0, side * w_pitch_bot / 2])
|
||||
cube([hole, hole, eps], center = true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -72,8 +72,6 @@ module corner_block_holes(screw = def_screw) //! Place children at all the holes
|
||||
children();
|
||||
|
||||
module corner_block(screw = def_screw, name = false) { //! Generate the STL for a printed corner block
|
||||
stl(name ? name : str("corner_block", "_M", screw_radius(screw) * 20));
|
||||
|
||||
r = 1;
|
||||
cb_width = corner_block_width(screw);
|
||||
cb_height = cb_width;
|
||||
@@ -81,43 +79,45 @@ module corner_block(screw = def_screw, name = false) { //! Generate the STL for
|
||||
insert = screw_insert(screw);
|
||||
corner_rad = insert_outer_d(insert) / 2 + wall;
|
||||
offset = corner_block_hole_offset(screw);
|
||||
difference() {
|
||||
hull() {
|
||||
translate([r, r])
|
||||
rounded_cylinder(r = r, h = cb_height, r2 = r);
|
||||
|
||||
translate([r, cb_depth - r])
|
||||
cylinder(r = r, h = cb_height - corner_rad);
|
||||
stl(name ? name : str("corner_block", "_M", screw_radius(screw) * 20))
|
||||
difference() {
|
||||
hull() {
|
||||
translate([r, r])
|
||||
rounded_cylinder(r = r, h = cb_height, r2 = r);
|
||||
|
||||
translate([cb_width - r, r])
|
||||
cylinder(r = r, h = cb_height - corner_rad);
|
||||
translate([r, cb_depth - r])
|
||||
cylinder(r = r, h = cb_height - corner_rad);
|
||||
|
||||
translate([offset, offset, offset])
|
||||
sphere(corner_rad);
|
||||
translate([cb_width - r, r])
|
||||
cylinder(r = r, h = cb_height - corner_rad);
|
||||
|
||||
translate([offset, offset])
|
||||
cylinder(r = corner_rad, h = offset);
|
||||
translate([offset, offset, offset])
|
||||
sphere(corner_rad);
|
||||
|
||||
translate([offset, r, offset])
|
||||
rotate([-90, 0, 180])
|
||||
rounded_cylinder(r = corner_rad, h = r, r2 = r);
|
||||
translate([offset, offset])
|
||||
cylinder(r = corner_rad, h = offset);
|
||||
|
||||
translate([r, offset, offset])
|
||||
rotate([0, 90, 180])
|
||||
rounded_cylinder(r = corner_rad, h = r, r2 = r);
|
||||
translate([offset, r, offset])
|
||||
rotate([-90, 0, 180])
|
||||
rounded_cylinder(r = corner_rad, h = r, r2 = r);
|
||||
|
||||
translate([r, offset, offset])
|
||||
rotate([0, 90, 180])
|
||||
rounded_cylinder(r = corner_rad, h = r, r2 = r);
|
||||
}
|
||||
corner_block_v_hole(screw)
|
||||
insert_hole(insert, overshoot);
|
||||
|
||||
corner_block_h_holes(screw)
|
||||
insert_hole(insert, overshoot, true);
|
||||
|
||||
children();
|
||||
}
|
||||
corner_block_v_hole(screw)
|
||||
insert_hole(insert, overshoot);
|
||||
|
||||
corner_block_h_holes(screw)
|
||||
insert_hole(insert, overshoot, true);
|
||||
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
module corner_block_assembly(screw = def_screw, name = false) //! The printed block with inserts
|
||||
assembly(str("corner_block_M", 20 * screw_radius(screw))) {
|
||||
assembly(str("corner_block_M", 20 * screw_radius(screw)), ngb = true) {
|
||||
insert = screw_insert(screw);
|
||||
|
||||
stl_colour(name ? pp2_colour : pp1_colour)
|
||||
@@ -133,12 +133,10 @@ assembly(str("corner_block_M", 20 * screw_radius(screw))) {
|
||||
module fastened_corner_block_assembly(thickness, screw = def_screw, thickness_below = undef, thickness_side2 = undef, name = false, show_block = true, star_washers = true) { //! Printed block with all fasteners
|
||||
thickness2 = !is_undef(thickness_below) ? thickness_below : thickness;
|
||||
thickness3 = !is_undef(thickness_side2) ? thickness_side2 : thickness;
|
||||
washer = screw_washer(screw);
|
||||
insert = screw_insert(screw);
|
||||
function screw_length(t) = screw_shorter_than((star_washers ? 2 : 1) * washer_thickness(washer) + t + insert_length(insert) + overshoot);
|
||||
screw_length = screw_length(thickness);
|
||||
screw_length2 = screw_length(thickness2);
|
||||
screw_length3 = screw_length(thickness3);
|
||||
function screw_len(t) = screw_length(screw, t + overshoot, star_washers ? 2 : 1, true);
|
||||
screw_length = screw_len(thickness);
|
||||
screw_length2 = screw_len(thickness2);
|
||||
screw_length3 = screw_len(thickness3);
|
||||
|
||||
if(show_block)
|
||||
corner_block_assembly(screw, name) children();
|
||||
|
@@ -54,44 +54,44 @@ module door_hinge_hole_positions(dir = 0) { //! Position chidren
|
||||
}
|
||||
|
||||
module door_hinge(door_thickness) { //! Generates STL for the moving part of the hinge
|
||||
stl(str("door_hinge_", door_thickness));
|
||||
|
||||
hole_pitch = width - 10;
|
||||
|
||||
union() {
|
||||
rotate([90, 0, 0])
|
||||
linear_extrude(width, center = true)
|
||||
stl(str("door_hinge_", door_thickness))
|
||||
union() {
|
||||
rotate([90, 0, 0])
|
||||
linear_extrude(width, center = true)
|
||||
difference() {
|
||||
hull() {
|
||||
translate([dia / 2, thickness + door_thickness / 2])
|
||||
intersection() {
|
||||
rotate(180)
|
||||
teardrop(r = dia / 2, h = 0, truncate = false);
|
||||
|
||||
square([dia + 1, 2 * thickness + door_thickness], center = true);
|
||||
}
|
||||
|
||||
square([1, thickness + door_thickness]);
|
||||
}
|
||||
translate([dia / 2, thickness + door_thickness / 2])
|
||||
teardrop_plus(r = screw_clearance_radius(pin_screw), h = 0);
|
||||
}
|
||||
linear_extrude(thickness)
|
||||
difference() {
|
||||
hull() {
|
||||
translate([dia / 2, thickness + door_thickness / 2])
|
||||
intersection() {
|
||||
rotate(180)
|
||||
teardrop(r = dia / 2, h = 0, truncate = false);
|
||||
translate([0, -width / 2])
|
||||
square([1, width]);
|
||||
|
||||
square([dia + 1, 2 * thickness + door_thickness], center = true);
|
||||
}
|
||||
|
||||
square([1, thickness + door_thickness]);
|
||||
for(side = [-1, 1])
|
||||
translate([-width + rad, side * (width / 2 - rad)])
|
||||
circle4n(rad);
|
||||
}
|
||||
translate([dia / 2, thickness + door_thickness / 2])
|
||||
teardrop_plus(r = screw_clearance_radius(pin_screw), h = 0);
|
||||
rotate(180)
|
||||
vflip()
|
||||
door_hinge_hole_positions()
|
||||
poly_circle(screw_clearance_radius(screw));
|
||||
}
|
||||
linear_extrude(thickness)
|
||||
difference() {
|
||||
hull() {
|
||||
translate([0, -width / 2])
|
||||
square([1, width]);
|
||||
|
||||
for(side = [-1, 1])
|
||||
translate([-width + rad, side * (width / 2 - rad)])
|
||||
circle4n(rad);
|
||||
}
|
||||
rotate(180)
|
||||
vflip()
|
||||
door_hinge_hole_positions()
|
||||
poly_circle(screw_clearance_radius(screw));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module door_hinge_6_stl() door_hinge(6);
|
||||
@@ -136,8 +136,7 @@ module door_hinge_assembly(top, door_thickness = 6) { //! The moving assembly th
|
||||
dir = top ? -1 : 1;
|
||||
pin_x = door_hinge_pin_x();
|
||||
pin_y = door_hinge_pin_y();
|
||||
washer = screw_washer(screw);
|
||||
screw_length = screw_shorter_than(thickness + door_thickness + washer_thickness(washer));
|
||||
screw_length = screw_length(screw, thickness + door_thickness, 1);
|
||||
|
||||
translate([0, pin_y - (thickness + door_thickness / 2), dir * width / 2]) {
|
||||
rotate([90, 0, 180])
|
||||
@@ -148,20 +147,20 @@ module door_hinge_assembly(top, door_thickness = 6) { //! The moving assembly th
|
||||
screw_and_washer(screw, screw_length);
|
||||
}
|
||||
|
||||
translate([pin_x, pin_y, top ? 0 : -washer_thickness(screw_washer(pin_screw))])
|
||||
washer(screw_washer(pin_screw));
|
||||
washer = screw_washer(pin_screw);
|
||||
wt = washer_thickness(washer);
|
||||
translate([pin_x, pin_y, top ? 0 : -wt])
|
||||
washer(washer);
|
||||
|
||||
translate([pin_x, pin_y, top ? washer_thickness(screw_washer(pin_screw)) + stat_width : width])
|
||||
screw_and_washer(pin_screw, screw_longer_than(2 * washer_thickness(screw_washer(pin_screw)) + width + stat_width));
|
||||
translate([pin_x, pin_y, top ? wt + stat_width : width])
|
||||
screw_and_washer(pin_screw, screw_length(pin_screw, width + stat_width, 2, longer = true));
|
||||
}
|
||||
|
||||
module door_hinge_static_assembly(top, sheet_thickness = 3) { //! The stationary assembly
|
||||
dir = top ? -1 : 1;
|
||||
pin_x = door_hinge_pin_x();
|
||||
|
||||
stat_washer = screw_washer(stat_screw);
|
||||
stat_nut = screw_nut(stat_screw);
|
||||
stat_screw_length = screw_longer_than(thickness + sheet_thickness + 2 * washer_thickness(stat_washer) + nut_thickness(stat_nut, true));
|
||||
stat_screw_length = screw_length(stat_screw, thickness + sheet_thickness, 2, nyloc = true);
|
||||
|
||||
translate([pin_x, 0, -dir * (stat_width / 2 + washer_thickness(screw_washer(pin_screw)))])
|
||||
rotate([90, 0, 0]) {
|
||||
@@ -169,9 +168,10 @@ module door_hinge_static_assembly(top, sheet_thickness = 3) { //! The stationary
|
||||
|
||||
door_hinge_stat_hole_positions() {
|
||||
screw_and_washer(stat_screw, stat_screw_length);
|
||||
|
||||
translate_z(-thickness - sheet_thickness)
|
||||
vflip()
|
||||
nut_and_washer(stat_nut, true);
|
||||
nut_and_washer(screw_nut(stat_screw), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -38,30 +38,30 @@ function door_latch_offset() = width / 2 + 1; //! Offset of the axle from the do
|
||||
nut_trap_depth = round_to_layer(screw_head_height(screw)) + 4 * layer_height;
|
||||
|
||||
module door_latch_stl() { //! Generates the STL for the printed part
|
||||
stl("door_latch");
|
||||
|
||||
ridge = 4;
|
||||
difference() {
|
||||
union() {
|
||||
hull() {
|
||||
rounded_rectangle([length, width, thickness - tan(30) * (width - ridge) / 2], rad, center = false);
|
||||
|
||||
translate_z(thickness / 2)
|
||||
cube([length, ridge, thickness], center = true);
|
||||
stl("door_latch")
|
||||
difference() {
|
||||
union() {
|
||||
hull() {
|
||||
rounded_rectangle([length, width, thickness - tan(30) * (width - ridge) / 2], rad, center = false);
|
||||
|
||||
translate_z(thickness / 2)
|
||||
cube([length, ridge, thickness], center = true);
|
||||
}
|
||||
|
||||
cylinder(d = width, h = height);
|
||||
}
|
||||
|
||||
cylinder(d = width, h = height);
|
||||
hanging_hole(nut_trap_depth, screw_clearance_radius(screw))
|
||||
circle(r = nut_trap_radius(screw_nut(screw)), $fn = 6);
|
||||
}
|
||||
hanging_hole(nut_trap_depth, screw_clearance_radius(screw))
|
||||
circle(r = nut_trap_radius(screw_nut(screw)), $fn = 6);
|
||||
}
|
||||
}
|
||||
|
||||
module door_latch_assembly(sheet_thickness = 3) { //! The assembly for a specified sheet thickess
|
||||
washer = screw_washer(screw);
|
||||
nut = screw_nut(screw);
|
||||
|
||||
screw_length = screw_longer_than(height - nut_trap_depth + sheet_thickness + 2 * washer_thickness(washer) + nut_thickness(nut, true));
|
||||
screw_length = screw_length(screw, height - nut_trap_depth + sheet_thickness, 2, nyloc = true);
|
||||
|
||||
translate([0, -height - washer_thickness(washer)])
|
||||
rotate([-90, 0, 0]) {
|
||||
|
@@ -251,7 +251,7 @@ module drag_chain_link(type, start = false, end = false, check_kids = true) { //
|
||||
}
|
||||
|
||||
// Need to use a wrapper because can't define nested modules in an assembly
|
||||
module _drag_chain_assembly(type, pos = 0) {
|
||||
module _drag_chain_assembly(type, pos = 0, render = false) {
|
||||
s = drag_chain_size(type);
|
||||
x = (1 + exploded()) * s.x;
|
||||
r = drag_chain_radius(type) * x / s.x;
|
||||
@@ -278,8 +278,11 @@ module _drag_chain_assembly(type, pos = 0) {
|
||||
module link(n) // Position and colour link with origin at the hinge hole
|
||||
translate([-z / 2, 0, -z / 2]) {
|
||||
stl_colour(n < 0 || n == npoints - 1 ? pp3_colour : n % 2 ? pp1_colour : pp2_colour)
|
||||
drag_chain_link(type, start = n == -1, end = n == npoints - 1, check_kids = false)
|
||||
let($fasteners = 0) children();
|
||||
render_if(render)
|
||||
drag_chain_link(type, start = n == -1, end = n == npoints - 1, check_kids = false)
|
||||
let($fasteners = 0)
|
||||
children();
|
||||
|
||||
let($fasteners = 1) children();
|
||||
}
|
||||
|
||||
@@ -307,15 +310,15 @@ module _drag_chain_assembly(type, pos = 0) {
|
||||
|
||||
//! 1. Remove the support material from the links with side cutters.
|
||||
//! 1. Clip the links together with the special ones at the ends.
|
||||
module drag_chain_assembly(type, pos = 0) //! Drag chain assembly
|
||||
assembly(str(drag_chain_name(type), "_drag_chain"), big = true)
|
||||
module drag_chain_assembly(type, pos = 0, render = false) //! Drag chain assembly
|
||||
assembly(str(drag_chain_name(type), "_drag_chain"), big = true, ngb = true)
|
||||
if($children == 2)
|
||||
_drag_chain_assembly(type, pos) {
|
||||
_drag_chain_assembly(type, pos, render) {
|
||||
children(0);
|
||||
children(1);
|
||||
}
|
||||
else if($children == 1)
|
||||
_drag_chain_assembly(type, pos)
|
||||
_drag_chain_assembly(type, pos, render)
|
||||
children(0);
|
||||
else
|
||||
_drag_chain_assembly(type, pos);
|
||||
_drag_chain_assembly(type, pos, render);
|
||||
|
@@ -71,42 +71,42 @@ module fixing_block_h_hole_2D(screw = def_screw) //! Position 2D child on the ho
|
||||
children();
|
||||
|
||||
module fixing_block(screw = def_screw) { //! Generate the STL
|
||||
stl(str("fixing_block_M", screw_radius(screw) * 20));
|
||||
r = 1;
|
||||
r = 1;
|
||||
insert = screw_insert(screw);
|
||||
corner_rad = insert_outer_d(insert) / 2 + wall;
|
||||
fb_width = fixing_block_width(screw);
|
||||
fb_height = fixing_block_height(screw);
|
||||
fb_depth = fixing_block_depth(screw);
|
||||
|
||||
difference() {
|
||||
union() {
|
||||
linear_extrude(fb_height, convexity = 5)
|
||||
difference() {
|
||||
hull() {
|
||||
for(side = [-1, 1]) {
|
||||
translate([side * (fb_width / 2 - corner_rad), fb_depth - corner_rad])
|
||||
circle4n(corner_rad);
|
||||
stl(str("fixing_block_M", screw_radius(screw) * 20))
|
||||
difference() {
|
||||
union() {
|
||||
linear_extrude(fb_height, convexity = 5)
|
||||
difference() {
|
||||
hull() {
|
||||
for(side = [-1, 1]) {
|
||||
translate([side * (fb_width / 2 - corner_rad), fb_depth - corner_rad])
|
||||
circle4n(corner_rad);
|
||||
|
||||
translate([side * (fb_width / 2 - r), r])
|
||||
circle4n(r);
|
||||
translate([side * (fb_width / 2 - r), r])
|
||||
circle4n(r);
|
||||
}
|
||||
}
|
||||
fixing_block_v_holes(screw)
|
||||
poly_circle(screw_clearance_radius(screw));
|
||||
}
|
||||
fixing_block_v_holes(screw)
|
||||
poly_circle(screw_clearance_radius(screw));
|
||||
}
|
||||
}
|
||||
translate_z(fb_height)
|
||||
fixing_block_v_holes(screw)
|
||||
insert_hole(insert);
|
||||
}
|
||||
translate_z(fb_height)
|
||||
fixing_block_v_holes(screw)
|
||||
insert_hole(insert);
|
||||
|
||||
fixing_block_h_hole(screw)
|
||||
insert_hole(insert, 10, true);
|
||||
}
|
||||
fixing_block_h_hole(screw)
|
||||
insert_hole(insert, 10, true);
|
||||
}
|
||||
}
|
||||
|
||||
module fixing_block_assembly(screw = def_screw) pose([55, 180, 25], [0, 4.8, 4.8]) //! Printed part with the inserts inserted
|
||||
assembly(str("fixing_block_M", 20 * screw_radius(screw))) {
|
||||
assembly(str("fixing_block_M", 20 * screw_radius(screw)), ngb = true) {
|
||||
translate_z(fixing_block_height(screw))
|
||||
rotate([0, 180, 0])
|
||||
stl_colour(pp1_colour) render() fixing_block(screw);
|
||||
@@ -122,9 +122,7 @@ assembly(str("fixing_block_M", 20 * screw_radius(screw))) {
|
||||
|
||||
module fastened_fixing_block_assembly(thickness, screw = def_screw, screw2 = undef, thickness2 = undef, show_block = true, star_washers = true) { //! Assembly with fasteners in place
|
||||
module fb_screw(screw, thickness) {
|
||||
washer = screw_washer(screw);
|
||||
insert = screw_insert(screw);
|
||||
screw_length = screw_longer_than((star_washers ? 2 : 1) * washer_thickness(washer) + thickness + insert_length(insert));
|
||||
screw_length = screw_length(screw, thickness, star_washers ? 2 : 1, true, longer = true);
|
||||
|
||||
if(thickness)
|
||||
translate_z(thickness)
|
||||
|
@@ -65,8 +65,6 @@ module hinge_screw_positions(type) { //! Place children at the screw positions
|
||||
}
|
||||
|
||||
module hinge_male(type, female = false) { //! The half with the stationary pin
|
||||
stl(str("hinge_", female ? "fe": "", "male_", type[0]));
|
||||
|
||||
r = hinge_radius(type);
|
||||
w = hinge_width(type);
|
||||
t = hinge_thickness(type);
|
||||
@@ -85,37 +83,40 @@ module hinge_male(type, female = false) { //! The half with the stationary
|
||||
teardrop_r = kr / cos(22.5); // The corner on the teardrop
|
||||
inset = sqrt(sqr(teardrop_r + gap) - sqr(kr - t)) - kr;
|
||||
|
||||
linear_extrude(t)
|
||||
difference() {
|
||||
hull() {
|
||||
for(side = [-1, 1])
|
||||
translate([side * (w / 2 - r), hinge_depth(type) - r])
|
||||
circle4n(r);
|
||||
stl(str("hinge_", female ? "fe": "", "male_", type[0]))
|
||||
union() {
|
||||
linear_extrude(t)
|
||||
difference() {
|
||||
hull() {
|
||||
for(side = [-1, 1])
|
||||
translate([side * (w / 2 - r), hinge_depth(type) - r])
|
||||
circle4n(r);
|
||||
|
||||
translate([-w / 2, inset])
|
||||
square([w, eps]);
|
||||
}
|
||||
hinge_screw_positions(type)
|
||||
poly_circle(screw_clearance_radius(hinge_screw(type)));
|
||||
translate([-w / 2, inset])
|
||||
square([w, eps]);
|
||||
}
|
||||
hinge_screw_positions(type)
|
||||
poly_circle(screw_clearance_radius(hinge_screw(type)));
|
||||
}
|
||||
|
||||
pitch = mw + gap + fw + gap;
|
||||
dir = female ? -1 : 1;
|
||||
translate([0, -kr, kr])
|
||||
rotate([90, 0, -90])
|
||||
for(z = [0 : (female ? fn : mn) - 1])
|
||||
translate_z(-dir * w / 2 + z * dir * pitch + (female ? -fw - mw - gap : 0))
|
||||
linear_extrude(female ? fw : mw)
|
||||
difference() {
|
||||
hull() {
|
||||
rotate(180)
|
||||
teardrop(r = kr, h = 0);
|
||||
|
||||
translate([-kr - 1, -kr])
|
||||
square(1);
|
||||
}
|
||||
teardrop_plus(r = pr + (female ? gap : 0), h = 0);
|
||||
}
|
||||
}
|
||||
|
||||
pitch = mw + gap + fw + gap;
|
||||
dir = female ? -1 : 1;
|
||||
translate([0, -kr, kr])
|
||||
rotate([90, 0, -90])
|
||||
for(z = [0 : (female ? fn : mn) - 1])
|
||||
translate_z(-dir * w / 2 + z * dir * pitch + (female ? -fw - mw - gap : 0))
|
||||
linear_extrude(female ? fw : mw)
|
||||
difference() {
|
||||
hull() {
|
||||
rotate(180)
|
||||
teardrop(r = kr, h = 0);
|
||||
|
||||
translate([-kr - 1, -kr])
|
||||
square(1);
|
||||
}
|
||||
teardrop_plus(r = pr + (female ? gap : 0), h = 0);
|
||||
}
|
||||
}
|
||||
|
||||
module hinge_female(type) hinge_male(type, true);
|
||||
@@ -129,7 +130,7 @@ module hinge_both(type) { //! Both parts together for printing
|
||||
}
|
||||
|
||||
module hinge_assembly(type, angle = 0)
|
||||
assembly(str("hinge_", type[0])) { //! Assembled hinge
|
||||
assembly(str("hinge_", type[0]), ngb = true) { //! Assembled hinge
|
||||
kr = hinge_knuckle_dia(type) / 2;
|
||||
hr = hinge_pin_dia(type) / 2;
|
||||
w = hinge_width(type);
|
||||
@@ -155,9 +156,7 @@ module hinge_fastened_assembly(type, thickness1, thickness2, angle, show_hinge =
|
||||
hinge_assembly(type, angle);
|
||||
|
||||
screw = hinge_screw(type);
|
||||
washer_t = 2 * washer_thickness(screw_washer(screw));
|
||||
nut = screw_nut(screw);
|
||||
nut_t = nut_thickness(nut, true);
|
||||
t = hinge_thickness(type);
|
||||
kr = hinge_knuckle_dia(type) / 2;
|
||||
|
||||
@@ -165,7 +164,7 @@ module hinge_fastened_assembly(type, thickness1, thickness2, angle, show_hinge =
|
||||
if(thickness)
|
||||
hinge_screw_positions(type) {
|
||||
translate_z(t)
|
||||
screw_and_washer(screw, screw_longer_than(t + thickness + washer_t + nut_t));
|
||||
screw_and_washer(screw, screw_length(screw, t + thickness, 2, nyloc = true));
|
||||
|
||||
translate_z(-thickness)
|
||||
vflip()
|
||||
|
@@ -39,7 +39,6 @@ function foot_screw(type = foot) = type[4]; //! Screw type
|
||||
function foot_slant(type = foot) = type[5]; //! Taper angle
|
||||
|
||||
module foot(type = foot) { //! Generate STL
|
||||
stl("foot");
|
||||
h = foot_height(type);
|
||||
t = foot_thickness(type);
|
||||
r1 = washer_radius(screw_washer(foot_screw(type)));
|
||||
@@ -47,32 +46,32 @@ module foot(type = foot) { //! Generate STL
|
||||
r2 = r3 - h * tan(foot_slant(type));
|
||||
r = foot_rad(type);
|
||||
|
||||
union() {
|
||||
rotate_extrude(convexity = 3) {
|
||||
hull() {
|
||||
translate([r1, 0])
|
||||
square([r3 - r1, eps]);
|
||||
stl("foot")
|
||||
union() {
|
||||
rotate_extrude(convexity = 3) {
|
||||
hull() {
|
||||
translate([r1, 0])
|
||||
square([r3 - r1, eps]);
|
||||
|
||||
for(x = [r1 + r, r2 - r])
|
||||
translate([x, h - r])
|
||||
circle4n(r);
|
||||
for(x = [r1 + r, r2 - r])
|
||||
translate([x, h - r])
|
||||
circle4n(r);
|
||||
}
|
||||
}
|
||||
linear_extrude(t)
|
||||
difference() {
|
||||
circle(r1 + eps);
|
||||
|
||||
poly_circle( screw_clearance_radius(foot_screw(type)));
|
||||
}
|
||||
}
|
||||
linear_extrude(t)
|
||||
difference() {
|
||||
circle(r1 + eps);
|
||||
|
||||
poly_circle( screw_clearance_radius(foot_screw(type)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module foot_assembly(t = 0, type = foot, flip = false) { //! Assembly with fasteners in place for specified sheet thickness
|
||||
screw = foot_screw(type);
|
||||
washer = screw_washer(screw);
|
||||
nut = screw_nut(screw);
|
||||
squeeze = 0.5;
|
||||
screw_length = screw_longer_than(foot_thickness(type) + t + 2 * washer_thickness(washer) + nut_thickness(nut, true) - squeeze);
|
||||
screw_length = screw_length(screw, foot_thickness(type) + t - squeeze, 2, nyloc = true);
|
||||
|
||||
vflip() explode(15, true) {
|
||||
stl_colour(pp4_colour) foot(type);
|
||||
@@ -94,7 +93,6 @@ module foot_assembly(t = 0, type = foot, flip = false) { //! Assembly with faste
|
||||
}
|
||||
|
||||
module insert_foot(type = insert_foot) { //! Generate STL for foot with insert
|
||||
stl("insert_foot");
|
||||
h = foot_height(type);
|
||||
r3 = foot_diameter(type) / 2;
|
||||
r2 = r3 - h * tan(foot_slant(type));
|
||||
@@ -104,36 +102,37 @@ module insert_foot(type = insert_foot) { //! Generate STL for foot with insert
|
||||
h2 = insert_hole_length(insert);
|
||||
r4 = insert_hole_radius(insert);
|
||||
r5 = r4 + 1;
|
||||
union() {
|
||||
rotate_extrude() {
|
||||
union() {
|
||||
hull() {
|
||||
translate([r5, 0]) {
|
||||
square([r3 - r5, eps]);
|
||||
square([eps, h]);
|
||||
}
|
||||
stl("insert_foot")
|
||||
union() {
|
||||
rotate_extrude() {
|
||||
union() {
|
||||
hull() {
|
||||
translate([r5, 0]) {
|
||||
square([r3 - r5, eps]);
|
||||
square([eps, h]);
|
||||
}
|
||||
|
||||
translate([r2 - r, h - r])
|
||||
circle4n(r);
|
||||
translate([r2 - r, h - r])
|
||||
circle4n(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
linear_extrude(h2 + eps)
|
||||
difference() {
|
||||
circle(r5 + eps);
|
||||
|
||||
poly_circle(r4);
|
||||
}
|
||||
|
||||
translate_z(h2)
|
||||
cylinder(r = r5 + eps, h = h - h2);
|
||||
}
|
||||
linear_extrude(h2 + eps)
|
||||
difference() {
|
||||
circle(r5 + eps);
|
||||
|
||||
poly_circle(r4);
|
||||
}
|
||||
|
||||
translate_z(h2)
|
||||
cylinder(r = r5 + eps, h = h - h2);
|
||||
}
|
||||
}
|
||||
//
|
||||
//! Place the insert in the bottom of the foot and push home with a soldering iron with a conical bit heated to 200°C.
|
||||
//
|
||||
module insert_foot_assembly(type = insert_foot) //! Printed part with insert in place
|
||||
assembly("insert_foot") {
|
||||
assembly("insert_foot", ngb = true) {
|
||||
screw = foot_screw(type);
|
||||
insert = screw_insert(screw);
|
||||
|
||||
@@ -146,9 +145,7 @@ assembly("insert_foot") {
|
||||
|
||||
module fastened_insert_foot_assembly(t = 3, type = insert_foot) { //! Assembly with fasteners in place for specified sheet thickness
|
||||
screw = foot_screw(type);
|
||||
washer = screw_washer(screw);
|
||||
insert = screw_insert(screw);
|
||||
screw_length = screw_shorter_than(insert_length(insert) + t + 2 * washer_thickness(washer));
|
||||
screw_length = screw_length(screw, t, 2, insert = true);
|
||||
|
||||
explode(-10) insert_foot_assembly(type);
|
||||
|
||||
|
@@ -46,8 +46,6 @@ module handle_holes(h = 100) //! Drills holes for the screws
|
||||
drill(screw_clearance_radius(screw), h);
|
||||
|
||||
module handle_stl() { //! generate the STL
|
||||
stl("handle");
|
||||
|
||||
module end(end)
|
||||
translate([end * pitch / 2, 0])
|
||||
rotate_extrude()
|
||||
@@ -59,29 +57,30 @@ module handle_stl() { //! generate the STL
|
||||
square([dia / 2 + 1, dia + 1]);
|
||||
}
|
||||
|
||||
translate_z(dia / 2)
|
||||
union() {
|
||||
hull() {
|
||||
end(-1);
|
||||
stl("handle")
|
||||
translate_z(dia / 2)
|
||||
union() {
|
||||
hull() {
|
||||
end(-1);
|
||||
|
||||
end(1);
|
||||
}
|
||||
|
||||
handle_screw_positions()
|
||||
render() difference() {
|
||||
h = height + dia / 2;
|
||||
cylinder(d = dia, h = h);
|
||||
|
||||
translate_z(h)
|
||||
insert_hole(insert, 6);
|
||||
end(1);
|
||||
}
|
||||
}
|
||||
|
||||
handle_screw_positions()
|
||||
render() difference() {
|
||||
h = height + dia / 2;
|
||||
cylinder(d = dia, h = h);
|
||||
|
||||
translate_z(h)
|
||||
insert_hole(insert, 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
//! Place inserts in the bottom of the posts and push them home with a soldering iron with a conical bit heated to 200°C.
|
||||
//
|
||||
module handle_assembly() pose([225, 0, 150], [0, 0, 14]) //! Printed part with inserts in place
|
||||
assembly("handle") {
|
||||
assembly("handle", ngb = true) {
|
||||
translate_z(handle_height())
|
||||
stl_colour(pp1_colour) vflip() handle_stl();
|
||||
|
||||
@@ -91,7 +90,7 @@ assembly("handle") {
|
||||
}
|
||||
|
||||
module handle_fastened_assembly(thickness) { //! Assembly with fasteners in place
|
||||
screw_length = screw_longer_than(thickness + insert_length(insert) + 2 * washer_thickness(screw_washer(screw)));
|
||||
screw_length = screw_length(screw, thickness, 2, true, longer = true);
|
||||
|
||||
handle_assembly();
|
||||
|
||||
|
@@ -66,35 +66,35 @@ module pcb_mount_washer_stl() //! A plastic washer to clamp a PCB
|
||||
pcb_mount_ring();
|
||||
|
||||
module pcb_mount(pcb, height = 5, washers = true) { //! Make the STL of a pcb mount for the specified PCB.
|
||||
stl(str("pcb_mount_", pcb[0], "_", height));
|
||||
|
||||
y_pitch = pcb_width(pcb) > 4 * pillar_r + 4 ? pillar_r + 1
|
||||
: pcb_width(pcb) / 2 + frame_w + 1 + pillar_r;
|
||||
|
||||
if(washers)
|
||||
for(x = [-1, 1], y = [-1, 1])
|
||||
translate([x * (pillar_r + 1), y * y_pitch, 0])
|
||||
pcb_mount_washer_stl();
|
||||
stl(str("pcb_mount_", pcb[0], "_", height)) union() {
|
||||
if(washers)
|
||||
for(x = [-1, 1], y = [-1, 1])
|
||||
translate([x * (pillar_r + 1), y * y_pitch, 0])
|
||||
pcb_mount_washer_stl();
|
||||
|
||||
for(x = [-1, 1])
|
||||
translate([x * pillar_x_pitch(pcb) / 2, 0, frame_t / 2])
|
||||
cube([frame_w, pillar_y_pitch(pcb) - 2 * wall, frame_t], center = true);
|
||||
for(x = [-1, 1])
|
||||
translate([x * pillar_x_pitch(pcb) / 2, 0, frame_t / 2])
|
||||
cube([frame_w, pillar_y_pitch(pcb) - 2 * wall, frame_t], center = true);
|
||||
|
||||
for(y = [-1, 1])
|
||||
translate([0, y * pillar_y_pitch(pcb) / 2, frame_t / 2])
|
||||
cube([pillar_x_pitch(pcb) - 2 * wall, frame_w, frame_t], center = true);
|
||||
for(y = [-1, 1])
|
||||
translate([0, y * pillar_y_pitch(pcb) / 2, frame_t / 2])
|
||||
cube([pillar_x_pitch(pcb) - 2 * wall, frame_w, frame_t], center = true);
|
||||
|
||||
pcb_mount_screw_positions(pcb)
|
||||
linear_extrude(height)
|
||||
pcb_mount_ring();
|
||||
|
||||
linear_extrude(height + pcb_thickness(pcb) - layer_height)
|
||||
difference() {
|
||||
pcb_mount_screw_positions(pcb)
|
||||
pcb_mount_screw_positions(pcb)
|
||||
linear_extrude(height)
|
||||
pcb_mount_ring();
|
||||
|
||||
square([pcb_length(pcb) + 2 * clearance, pcb_width(pcb) + 2 * clearance], center = true);
|
||||
}
|
||||
linear_extrude(height + pcb_thickness(pcb) - layer_height)
|
||||
difference() {
|
||||
pcb_mount_screw_positions(pcb)
|
||||
pcb_mount_ring();
|
||||
|
||||
square([pcb_length(pcb) + 2 * clearance, pcb_width(pcb) + 2 * clearance], center = true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module pcb_mount_assembly(pcb, thickness, height = 5) { //! A PCB mount assembly with fasteners
|
||||
@@ -103,10 +103,9 @@ module pcb_mount_assembly(pcb, thickness, height = 5) { //! A PCB mount assembly
|
||||
|
||||
stl_colour(pp1_colour) pcb_mount(pcb, washers = false);
|
||||
|
||||
washer = screw_washer(screw);
|
||||
nut = screw_nut(screw);
|
||||
t = pcb_thickness(pcb);
|
||||
screw_length = screw_longer_than(height + t + washer_thickness + thickness + washer_thickness(washer) + nut_thickness(nut, true));
|
||||
screw_length = screw_length(screw, height + t + washer_thickness + thickness, 1, nyloc = true);
|
||||
|
||||
pcb_mount_screw_positions(pcb) {
|
||||
translate_z(height + t) {
|
||||
|
@@ -65,10 +65,8 @@ function pbox_insert(type) = screw_insert(pbox_screw(type)); //! The insert for
|
||||
function pbox_washer(type) = screw_washer(pbox_screw(type)); //! The washer for the base screws
|
||||
|
||||
function pbox_screw_length(type, panel_thickness = 0) = //! Length of the base screw
|
||||
let(foot = pbox_foot(type))
|
||||
screw_shorter_than(pbox_base(type) + washer_thickness(pbox_washer(type))
|
||||
+ insert_length(pbox_insert(type))
|
||||
+ (foot ? foot_thickness(foot) : panel_thickness));
|
||||
let(foot = pbox_foot(type), screw = pbox_screw(type))
|
||||
screw_length(screw, pbox_base(type) + (foot ? foot_thickness(foot) : panel_thickness), 1, true);
|
||||
|
||||
function pbox_mid_offset(type) = pbox_ridges(type).y + pbox_wall(type) / 2; // Offset to wall midpoint
|
||||
|
||||
@@ -131,28 +129,27 @@ module pbox_outer_shape(type) //! 2D outer shape of the box
|
||||
offset(pbox_wall(type) / 2) pbox_mid_shape(type);
|
||||
|
||||
module pbox_base(type) { //! Generate the STL for the base
|
||||
stl(str(pbox_name(type),"_base"));
|
||||
t = pbox_base(type);
|
||||
difference() {
|
||||
union() {
|
||||
linear_extrude(t)
|
||||
offset(base_outset - 0.2)
|
||||
pbox_inner_shape(type);
|
||||
|
||||
if($children > 0)
|
||||
children(0);
|
||||
stl(str(pbox_name(type),"_base"))
|
||||
difference() {
|
||||
union() {
|
||||
linear_extrude(t)
|
||||
offset(base_outset - 0.2)
|
||||
pbox_inner_shape(type);
|
||||
|
||||
if($children > 0)
|
||||
children(0);
|
||||
}
|
||||
pbox_screw_positions(type)
|
||||
poly_cylinder(r = screw_clearance_radius(pbox_screw(type)), h = 2 * t + eps, center = true);
|
||||
|
||||
if($children > 1)
|
||||
children(1);
|
||||
}
|
||||
pbox_screw_positions(type)
|
||||
poly_cylinder(r = screw_clearance_radius(pbox_screw(type)), h = 2 * t + eps, center = true);
|
||||
|
||||
if($children > 1)
|
||||
children(1);
|
||||
}
|
||||
}
|
||||
|
||||
module pbox(type) { //! Generate the STL for the main case
|
||||
stl(pbox_name(type));
|
||||
|
||||
height = pbox_height(type);
|
||||
total_height = pbox_total_height(type);
|
||||
top_thickness = pbox_top(type);
|
||||
@@ -161,60 +158,61 @@ module pbox(type) { //! Generate the STL for the main case
|
||||
ledge_inset = base_outset - base_overlap;
|
||||
ledge_h = pbox_base(type) ? (ledge_outset - ledge_inset) * 2 : 0;
|
||||
|
||||
difference() {
|
||||
union() {
|
||||
linear_extrude(total_height)
|
||||
pbox_outer_shape(type);
|
||||
|
||||
if($children > 2)
|
||||
children(2);
|
||||
}
|
||||
stl(pbox_name(type))
|
||||
difference() {
|
||||
translate_z(top_thickness)
|
||||
union() {
|
||||
linear_extrude(height + eps)
|
||||
offset(-wall / 2) pbox_mid_shape(type);
|
||||
union() {
|
||||
linear_extrude(total_height)
|
||||
pbox_outer_shape(type);
|
||||
|
||||
translate_z(height) // Recess for the base
|
||||
linear_extrude(total_height - height)
|
||||
offset(base_outset)
|
||||
pbox_inner_shape(type);
|
||||
}
|
||||
// Ledge to support the lid
|
||||
if(ledge_h)
|
||||
translate_z(top_thickness + height - ledge_h)
|
||||
difference() {
|
||||
rounded_rectangle([pbox_width(type) + 2 * outset, pbox_depth(type) + 2 * outset, ledge_h], 1, center = false);
|
||||
if($children > 2)
|
||||
children(2);
|
||||
}
|
||||
difference() {
|
||||
translate_z(top_thickness)
|
||||
union() {
|
||||
linear_extrude(height + eps)
|
||||
offset(-wall / 2) pbox_mid_shape(type);
|
||||
|
||||
hull() {
|
||||
linear_extrude(ledge_h + eps)
|
||||
offset(ledge_inset)
|
||||
translate_z(height) // Recess for the base
|
||||
linear_extrude(total_height - height)
|
||||
offset(base_outset)
|
||||
pbox_inner_shape(type);
|
||||
|
||||
linear_extrude(eps)
|
||||
offset(ledge_outset)
|
||||
pbox_inner_shape(type);
|
||||
}
|
||||
pbox_screw_positions(type)
|
||||
insert_hole(pbox_insert(type));
|
||||
}
|
||||
// Ledge to support the lid
|
||||
if(ledge_h)
|
||||
translate_z(top_thickness + height - ledge_h)
|
||||
difference() {
|
||||
rounded_rectangle([pbox_width(type) + 2 * outset, pbox_depth(type) + 2 * outset, ledge_h], 1, center = false);
|
||||
|
||||
// Corner lugs for inserts
|
||||
outset = wall + pbox_ridges(type).y;
|
||||
or = pbox_radius(type) + outset;
|
||||
inset = pbox_screw_inset(type) + outset;
|
||||
br = insert_boss_radius(pbox_insert(type), wall);
|
||||
ext = sqrt(2) * inset - or * (sqrt(2) - 1) - br;
|
||||
translate_z(height + top_thickness)
|
||||
pbox_screw_positions(type)
|
||||
insert_lug(pbox_insert(type), wall, counter_bore = 0, extension = ext, corner_r = or);
|
||||
hull() {
|
||||
linear_extrude(ledge_h + eps)
|
||||
offset(ledge_inset)
|
||||
pbox_inner_shape(type);
|
||||
|
||||
if($children > 0)
|
||||
children(0);
|
||||
linear_extrude(eps)
|
||||
offset(ledge_outset)
|
||||
pbox_inner_shape(type);
|
||||
}
|
||||
pbox_screw_positions(type)
|
||||
insert_hole(pbox_insert(type));
|
||||
}
|
||||
|
||||
// Corner lugs for inserts
|
||||
outset = wall + pbox_ridges(type).y;
|
||||
or = pbox_radius(type) + outset;
|
||||
inset = pbox_screw_inset(type) + outset;
|
||||
br = insert_boss_radius(pbox_insert(type), wall);
|
||||
ext = sqrt(2) * inset - or * (sqrt(2) - 1) - br;
|
||||
translate_z(height + top_thickness)
|
||||
pbox_screw_positions(type)
|
||||
insert_lug(pbox_insert(type), wall, counter_bore = 0, extension = ext, corner_r = or);
|
||||
|
||||
if($children > 0)
|
||||
children(0);
|
||||
}
|
||||
if($children > 1)
|
||||
children(1);
|
||||
}
|
||||
if($children > 1)
|
||||
children(1);
|
||||
}
|
||||
}
|
||||
|
||||
module pbox_inserts(type) //! Place the inserts for the base screws
|
||||
|
200
printed/printed_pulleys.scad
Normal file
@@ -0,0 +1,200 @@
|
||||
//
|
||||
// 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/>.
|
||||
//
|
||||
//! Printed pulleys are a remix of droftarts's (see <https://www.thingiverse.com/droftarts/designs>) Parametric Pulleys
|
||||
//! on Thingiverse (see <https://www.thingiverse.com/thing:16627>) and are licensed under the
|
||||
//! Creative Commons - Attribution - Share Alike license (see <https://creativecommons.org/licenses/by-sa/3.0/>)
|
||||
//
|
||||
|
||||
include <../core.scad>
|
||||
include <../vitamins/pulleys.scad>
|
||||
|
||||
printed_pulley_GT2_profile = [[0.747183,-0.5],[0.747183,0],[0.647876,0.037218],[0.598311,0.130528],[0.578556,0.238423],[0.547158,0.343077],[0.504649,0.443762],[0.451556,0.53975],[0.358229,0.636924],[0.2484,0.707276],[0.127259,0.750044],[0,0.76447],[-0.127259,0.750044],[-0.2484,0.707276],[-0.358229,0.636924],[-0.451556,0.53975],[-0.504797,0.443762],[-0.547291,0.343077],[-0.578605,0.238423],[-0.598311,0.130528],[-0.648009,0.037218],[-0.747183,0],[-0.747183,-0.5]];
|
||||
|
||||
function printed_pulley_inverted(type) = pulley_hub_dia(type) < pulley_flange_dia(type); //! Need to print upside down to prevent overhang
|
||||
|
||||
function printed_pulley_od(tooth_count, tooth_pitch, pitch_line_offset)
|
||||
= tooth_count * tooth_pitch / PI - 2 * pitch_line_offset;
|
||||
|
||||
module printed_pulley_teeth_from_profile(tooth_count, tooth_depth, tooth_width, tooth_profile) {
|
||||
pulley_od = printed_pulley_od(tooth_count, 2, 0.254);
|
||||
|
||||
difference() {
|
||||
rotate (90 / tooth_count)
|
||||
circle(r = pulley_od / 2, $fn = tooth_count * 4);
|
||||
tooth_distance_from_centre = sqrt(pulley_od * pulley_od - (tooth_width + 0.2) * (tooth_width + 0.2)) / 2;
|
||||
for(i = [1 : tooth_count])
|
||||
rotate(i * 360 / tooth_count)
|
||||
translate([0, -tooth_distance_from_centre])
|
||||
scale([(tooth_width + 0.2) / tooth_width, 1])
|
||||
polygon(tooth_profile);
|
||||
}
|
||||
}
|
||||
|
||||
module printed_pulley_GT2_teeth(type) {
|
||||
tooth_count = pulley_teeth(type);
|
||||
if (tooth_count == 0)
|
||||
circle(r = pulley_od(type) / 2);
|
||||
else
|
||||
printed_pulley_teeth_from_profile(tooth_count, 0.764, 1.494, printed_pulley_GT2_profile);
|
||||
}
|
||||
|
||||
|
||||
module printed_pulley_teeth(type) { //! Draw the pulley's teeth
|
||||
tooth_count = pulley_teeth(type);
|
||||
tw = pulley_od(type) * PI / (tooth_count * 2);
|
||||
ir = pulley_ir(type);
|
||||
or = pulley_od(type) / 2;
|
||||
|
||||
T_angle = 40;
|
||||
GT_r = 0.555;
|
||||
for (i = [0 : 1 : tooth_count - 1])
|
||||
rotate(i * 360 / tooth_count)
|
||||
if (pulley_type(type)[0] == "G")
|
||||
translate([0, ir + GT_r])
|
||||
hull() {
|
||||
circle(GT_r);
|
||||
translate([0, GT_r])
|
||||
square(2 * GT_r, center = true);
|
||||
}
|
||||
else
|
||||
translate([0, (ir + or) / 2])
|
||||
hull() {
|
||||
for(side = [-1, 1])
|
||||
translate([side * tw / 2, 0])
|
||||
rotate(-side * T_angle / 2)
|
||||
square([eps, (or - ir)], center = true);
|
||||
|
||||
translate([0, 1])
|
||||
square([tw, eps], center = true);
|
||||
}
|
||||
}
|
||||
|
||||
module printed_pulley(type) { //! Draw a printable pulley
|
||||
ft = pulley_flange_thickness(type);
|
||||
hl = pulley_hub_length(type);
|
||||
w = pulley_width(type);
|
||||
r1 = pulley_bore(type) / 2;
|
||||
or = pulley_od(type) / 2;
|
||||
screw_z = pulley_screw_z(type);
|
||||
|
||||
|
||||
module core() {
|
||||
translate_z(pulley_hub_length(type) + ft)
|
||||
linear_extrude(w + 1) let($fa = 1, $fs = 0.1)
|
||||
if ("GT2" == str(pulley_type(type)[0], pulley_type(type)[1], pulley_type(type)[2]))
|
||||
difference() {
|
||||
printed_pulley_GT2_teeth(type);
|
||||
circle(d = pulley_bore(type));
|
||||
}
|
||||
else
|
||||
difference() {
|
||||
circle(or);
|
||||
printed_pulley_teeth(type);
|
||||
circle(d = pulley_bore(type));
|
||||
}
|
||||
}
|
||||
|
||||
module screw_holes() {
|
||||
if(pulley_screws(type))
|
||||
translate_z(screw_z)
|
||||
for(i = [0 : pulley_screws(type) - 1])
|
||||
rotate([-90, 180, i * -90])
|
||||
if(show_supports())
|
||||
teardrop(r = screw_pilot_hole(pulley_screw(type)), h = pulley_flange_dia(type) / 2 + 1, center = false);
|
||||
else
|
||||
cylinder(r = screw_radius(pulley_screw(type)), h = pulley_flange_dia(type) / 2 + 1);
|
||||
}
|
||||
|
||||
module hub()
|
||||
linear_extrude(hl)
|
||||
difference() {
|
||||
circle(d= pulley_hub_dia(type));
|
||||
circle(d = pulley_bore(type));
|
||||
}
|
||||
|
||||
stl(str("printed_pulley_", type[0]))
|
||||
translate_z(printed_pulley_inverted(type) ? - hl : 0) {
|
||||
// hub
|
||||
if(hl)
|
||||
translate_z(printed_pulley_inverted(type) ? hl + w + 2 * ft : 0)
|
||||
if(screw_z && screw_z < hl)
|
||||
render()
|
||||
difference() {
|
||||
hub();
|
||||
|
||||
screw_holes();
|
||||
}
|
||||
else
|
||||
hub();
|
||||
|
||||
// bottom flange
|
||||
translate_z(hl)
|
||||
linear_extrude(ft)
|
||||
difference() {
|
||||
circle(d = pulley_flange_dia(type));
|
||||
circle(d = pulley_bore(type));
|
||||
}
|
||||
|
||||
// top flange
|
||||
translate_z(hl + ft + w) {
|
||||
// inner part, supported by core
|
||||
linear_extrude(ft)
|
||||
difference() {
|
||||
circle(r = or);
|
||||
circle(d = pulley_bore(type));
|
||||
}
|
||||
// outer part at 45 degrees for printing
|
||||
rotate_extrude()
|
||||
translate([or - eps, ft])
|
||||
vflip()
|
||||
right_triangle(ft, ft);
|
||||
}
|
||||
|
||||
if(screw_z && screw_z > hl)
|
||||
render()
|
||||
difference() { // T5 pulleys have screws through the teeth
|
||||
core();
|
||||
|
||||
translate_z(printed_pulley_inverted(type) ? pulley_height(type) + hl - 2 * screw_z : 0)
|
||||
screw_holes();
|
||||
}
|
||||
else
|
||||
core();
|
||||
}
|
||||
}
|
||||
|
||||
module printed_pulley_assembly(type, colour = pp1_colour) //! Draw a printed pulley with its grub screws in place
|
||||
assembly(str("printed_pulley_", type[0]), ngb = true) {
|
||||
translate_z(pulley_offset(type)) {
|
||||
stl_colour(colour)
|
||||
if(printed_pulley_inverted(type))
|
||||
translate_z(pulley_height(type))
|
||||
hflip()
|
||||
printed_pulley(type);
|
||||
else
|
||||
printed_pulley(type);
|
||||
|
||||
if(pulley_screws(type))
|
||||
translate_z(pulley_screw_z(type))
|
||||
for(i = [0 : pulley_screws(type) - 1])
|
||||
rotate([-90, 0, i * -90])
|
||||
translate_z(pulley_bore(type) / 2 + pulley_screw_length(type))
|
||||
screw(pulley_screw(type), pulley_screw_length(type));
|
||||
}
|
||||
}
|
@@ -79,8 +79,6 @@ module psu_shroud_holes(type, cable_d, cables = 1) {
|
||||
}
|
||||
|
||||
module psu_shroud(type, cable_d, name, cables = 1) { //! Generate the STL file for a specified ssr and cable
|
||||
stl(str("psu_shroud_", name));
|
||||
|
||||
extent = psu_shroud_extent(type);
|
||||
depth = psu_shroud_depth(type);
|
||||
width = psu_shroud_width(type);
|
||||
@@ -109,41 +107,43 @@ module psu_shroud(type, cable_d, name, cables = 1) { //! Generate the STL file f
|
||||
}
|
||||
}
|
||||
|
||||
// base and sides
|
||||
translate([centre_x, -centre_y]) {
|
||||
rounded_rectangle([depth - eps, width - eps, top], rad, center = false);
|
||||
stl(str("psu_shroud_", name)) {
|
||||
// base and sides
|
||||
translate([centre_x, -centre_y]) {
|
||||
rounded_rectangle([depth - eps, width - eps, top], rad, center = false);
|
||||
|
||||
linear_extrude(height)
|
||||
difference() {
|
||||
linear_extrude(height)
|
||||
difference() {
|
||||
shape();
|
||||
|
||||
translate([depth / 2, width / 2 - 5])
|
||||
square([2 * (depth - extent + terminal_clearance), 10], center = true);
|
||||
}
|
||||
linear_extrude(height - terminal_block_height(tb) - psu_terminal_block_z(type) - terminal_clearance)
|
||||
shape();
|
||||
|
||||
translate([depth / 2, width / 2 - 5])
|
||||
square([2 * (depth - extent + terminal_clearance), 10], center = true);
|
||||
}
|
||||
linear_extrude(height - terminal_block_height(tb) - psu_terminal_block_z(type) - terminal_clearance)
|
||||
shape();
|
||||
}
|
||||
// cable slots
|
||||
for(i = [0 : 1 : cables - 1])
|
||||
translate([centre_x - depth / 2 + wall / 2, -centre_y + (i - cables / 2 + 0.5) * psu_shroud_cable_pitch(cable_d), height / 2])
|
||||
rotate([90, 0, 90])
|
||||
linear_extrude(wall, center = true)
|
||||
difference() {
|
||||
square([cable_d + eps, height], center = true);
|
||||
// cable slots
|
||||
for(i = [0 : 1 : cables - 1])
|
||||
translate([centre_x - depth / 2 + wall / 2, -centre_y + (i - cables / 2 + 0.5) * psu_shroud_cable_pitch(cable_d), height / 2])
|
||||
rotate([90, 0, 90])
|
||||
linear_extrude(wall, center = true)
|
||||
difference() {
|
||||
square([cable_d + eps, height], center = true);
|
||||
|
||||
translate([0, height / 2])
|
||||
vertical_tearslot(h = 0, r = cable_d / 2, l = cable_d);
|
||||
}
|
||||
// insert lugs
|
||||
mirror([0, 1, 0])
|
||||
psu_shroud_hole_positions(type)
|
||||
translate_z(height)
|
||||
rotate($side * 90)
|
||||
insert_lug(insert, wall, counter_bore);
|
||||
}
|
||||
translate([0, height / 2])
|
||||
vertical_tearslot(h = 0, r = cable_d / 2, l = cable_d);
|
||||
}
|
||||
// insert lugs
|
||||
mirror([0, 1, 0])
|
||||
psu_shroud_hole_positions(type)
|
||||
translate_z(height)
|
||||
rotate($side * 90)
|
||||
insert_lug(insert, wall, counter_bore);
|
||||
}
|
||||
}
|
||||
|
||||
module psu_shroud_assembly(type, cable_d, name, cables = 1) //! The printed parts with inserts fitted
|
||||
assembly(str("PSU_shroud_", name)) {
|
||||
assembly(str("PSU_shroud_", name), ngb = true) {
|
||||
|
||||
translate_z(psu_shroud_height(type))
|
||||
vflip()
|
||||
@@ -156,8 +156,7 @@ assembly(str("PSU_shroud_", name)) {
|
||||
|
||||
module psu_shroud_fastened_assembly(type, cable_d, thickness, name, cables = 1) //! Assembly with screws in place
|
||||
{
|
||||
washer = screw_washer(screw);
|
||||
screw_length = screw_shorter_than(2 * washer_thickness(washer) + thickness + insert_length(insert) + counter_bore);
|
||||
screw_length = screw_length(screw,thickness + counter_bore, 2, true);
|
||||
|
||||
psu_shroud_assembly(type, cable_d, name, cables);
|
||||
|
||||
|
@@ -47,7 +47,6 @@ module ribbon_clamp_holes(ways, h = 20, screw = screw) //! Drill screw holes
|
||||
|
||||
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, screw);
|
||||
d = ribbon_clamp_width(screw);
|
||||
@@ -55,34 +54,35 @@ module ribbon_clamp(ways, screw = screw) { //! Generate STL for given number of
|
||||
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, screw), d, t], center = true);
|
||||
stl(str("ribbon_clamp_", ways, screw_d != 3 ? str("_", screw_d) : ""))
|
||||
difference() {
|
||||
union() {
|
||||
hull() {
|
||||
translate_z(h - t / 2)
|
||||
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);
|
||||
translate_z(1)
|
||||
cube([pitch, max(wall, d - 2 * (h - t)), 2], center = true);
|
||||
}
|
||||
ribbon_clamp_hole_positions(ways, screw, -1)
|
||||
cylinder(d = d, h = h);
|
||||
|
||||
ribbon_clamp_hole_positions(ways, screw, 1)
|
||||
cylinder(d = d, h = h);
|
||||
}
|
||||
ribbon_clamp_hole_positions(ways, screw, -1)
|
||||
cylinder(d = d, h = h);
|
||||
|
||||
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, screw)
|
||||
translate_z(h)
|
||||
rotate(22.5)
|
||||
insert_hole(insert, ribbon_clamp_screw_depth(screw) - insert_length(insert));
|
||||
}
|
||||
cube([ribbon_clamp_slot(ways), d + 1, ribbon_clamp_slot_depth() * 2], center = true);
|
||||
|
||||
ribbon_clamp_hole_positions(ways, screw)
|
||||
translate_z(h)
|
||||
rotate(22.5)
|
||||
insert_hole(insert, ribbon_clamp_screw_depth(screw) - insert_length(insert));
|
||||
}
|
||||
}
|
||||
|
||||
module ribbon_clamp_assembly(ways, screw = 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) : "")) {
|
||||
assembly(let(screw_d = screw_radius(screw) * 2)str("ribbon_clamp_", ways, screw_d != 3 ? str("_", screw_d) : ""), ngb = true) {
|
||||
h = ribbon_clamp_height(screw);
|
||||
insert = screw_insert(screw);
|
||||
|
||||
@@ -101,8 +101,7 @@ 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 + ribbon_clamp_screw_depth(screw));
|
||||
screw_length = screw_length(screw, thickness + ribbon_clamp_screw_depth(screw), 2);
|
||||
|
||||
ribbon_clamp_assembly(ways, screw);
|
||||
|
||||
|
@@ -34,32 +34,31 @@ knob_height = knob_stem_h + knob_thickness;
|
||||
function knob_height() = knob_height;
|
||||
|
||||
module screw_knob(screw) { //! Generate the STL for a knob to fit the specified hex screw
|
||||
stl(str("screw_knob_M", screw_radius(screw) * 20));
|
||||
|
||||
knob_stem_r = nut_trap_radius(screw_nut(screw)) + knob_wall;
|
||||
|
||||
function wave(a) = knob_r + sin(a * knob_waves) * knob_wave;
|
||||
|
||||
union() {
|
||||
render() difference() {
|
||||
cylinder(r = knob_stem_r, h = knob_thickness + knob_stem_h);
|
||||
stl(str("screw_knob_M", screw_radius(screw) * 20))
|
||||
union() {
|
||||
render() difference() {
|
||||
cylinder(r = knob_stem_r, h = knob_thickness + knob_stem_h);
|
||||
|
||||
hanging_hole(knob_nut_trap_depth(screw), screw_clearance_radius(screw))
|
||||
rotate(45)
|
||||
circle(r = nut_trap_radius(screw_nut(screw)), $fn = 6);
|
||||
}
|
||||
linear_extrude(knob_thickness, convexity = 3)
|
||||
difference() {
|
||||
polygon(points = [for(a = [0 : 359]) [wave(a) * sin(a), wave(a) * cos(a)]]);
|
||||
|
||||
circle(knob_stem_r - eps);
|
||||
hanging_hole(knob_nut_trap_depth(screw), screw_clearance_radius(screw))
|
||||
rotate(45)
|
||||
circle(r = nut_trap_radius(screw_nut(screw)), $fn = 6);
|
||||
}
|
||||
}
|
||||
linear_extrude(knob_thickness, convexity = 3)
|
||||
difference() {
|
||||
polygon(points = [for(a = [0 : 359]) [wave(a) * sin(a), wave(a) * cos(a)]]);
|
||||
|
||||
circle(knob_stem_r - eps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Place the screw through the printed part
|
||||
module screw_knob_assembly(screw, length) //! Assembly with the screw in place
|
||||
assembly(str("screw_knob_M", 20 * screw_radius(screw), "_", length)) {
|
||||
assembly(str("screw_knob_M", 20 * screw_radius(screw), "_", length), ngb = true) {
|
||||
translate_z(knob_height)
|
||||
vflip()
|
||||
stl_colour(pp1_colour) screw_knob(screw);
|
||||
|
@@ -41,7 +41,6 @@ height = base_thickness + box_height;
|
||||
function socket_box_depth() = height; //! Outside depth of the backbox
|
||||
|
||||
module socket_box(type) { //! Generate STL of the backbox for the specified socket
|
||||
stl(str("socket_box_",type[0]));
|
||||
|
||||
screw = mains_socket_screw(type);
|
||||
screw_clearance_radius = screw_clearance_radius(screw);
|
||||
@@ -51,37 +50,38 @@ module socket_box(type) { //! Generate STL of the backbox for the specified sock
|
||||
insert_boss = mains_socket_insert_boss(type);
|
||||
insert_hole_radius = insert_hole_radius(insert);
|
||||
|
||||
difference() {
|
||||
linear_extrude(height, convexity = 5)
|
||||
face_plate(type);
|
||||
|
||||
stl(str("socket_box_",type[0]))
|
||||
difference() {
|
||||
translate_z(base_thickness)
|
||||
linear_extrude(height, convexity = 5)
|
||||
offset(-wall) offset(1) face_plate(type);
|
||||
linear_extrude(height, convexity = 5)
|
||||
face_plate(type);
|
||||
|
||||
for(side = [-1, 1])
|
||||
hull()
|
||||
for(x = [1, 2])
|
||||
translate([side * mains_socket_pitch(type) / x, 0])
|
||||
cylinder(d = insert_boss, h = 100);
|
||||
}
|
||||
//
|
||||
// Socket holes
|
||||
//
|
||||
translate_z(height)
|
||||
mains_socket_hole_positions(type) {
|
||||
poly_cylinder(r = screw_clearance_radius, h = 2 * box_height, center = true);
|
||||
difference() {
|
||||
translate_z(base_thickness)
|
||||
linear_extrude(height, convexity = 5)
|
||||
offset(-wall) offset(1) face_plate(type);
|
||||
|
||||
poly_cylinder(r = insert_hole_radius, h = 2 * insert_length, center = true);
|
||||
for(side = [-1, 1])
|
||||
hull()
|
||||
for(x = [1, 2])
|
||||
translate([side * mains_socket_pitch(type) / x, 0])
|
||||
cylinder(d = insert_boss, h = 100);
|
||||
}
|
||||
//
|
||||
// Cable hole
|
||||
//
|
||||
translate([cable_x, cable_y(type), cable_z])
|
||||
rotate([90, 0, 0])
|
||||
teardrop_plus(r = cable_d / 2, h = 30);
|
||||
}
|
||||
//
|
||||
// Socket holes
|
||||
//
|
||||
translate_z(height)
|
||||
mains_socket_hole_positions(type) {
|
||||
poly_cylinder(r = screw_clearance_radius, h = 2 * box_height, center = true);
|
||||
|
||||
poly_cylinder(r = insert_hole_radius, h = 2 * insert_length, center = true);
|
||||
}
|
||||
//
|
||||
// Cable hole
|
||||
//
|
||||
translate([cable_x, cable_y(type), cable_z])
|
||||
rotate([90, 0, 0])
|
||||
teardrop_plus(r = cable_d / 2, h = 30);
|
||||
}
|
||||
}
|
||||
|
||||
module socket_box_MKLOGIC_stl() socket_box(MKLOGIC);
|
||||
@@ -105,8 +105,7 @@ module socket_box_MKLOGIC_assembly() socket_box_assembly(MKLOGIC);
|
||||
|
||||
module socket_box_fastened_assembly(type, thickness) { //! The socket and backbox on each side of the specified panel thickness
|
||||
screw = mains_socket_screw(type);
|
||||
insert = screw_insert(screw);
|
||||
screw_length = screw_longer_than(mains_socket_height(type) + thickness + insert_length(insert));
|
||||
screw_length = screw_length(screw, mains_socket_height(type) + thickness, 0, true, longer = true);
|
||||
|
||||
explode(-50)
|
||||
translate_z(-height - thickness)
|
||||
|
@@ -61,53 +61,54 @@ module ssr_shroud_holes(type, cable_d) { //! Drill the screw and ziptie holes
|
||||
}
|
||||
|
||||
module ssr_shroud(type, cable_d, name) { //! Generate the STL file for a specified ssr and cable
|
||||
stl(str("ssr_shroud_", name));
|
||||
|
||||
width = ssr_shroud_width(type);
|
||||
depth = ssr_length(type) / 3 + ssr_shroud_extent(type, cable_d);
|
||||
height = ssr_shroud_height(type);
|
||||
cable_x = ssr_shroud_cable_x(type, cable_d);
|
||||
center_x = -ssr_length(type) / 6 - depth / 2;
|
||||
|
||||
// base and sides
|
||||
translate([center_x, 0]) {
|
||||
rounded_rectangle([depth - eps, width - eps, top], rad, center = false);
|
||||
|
||||
linear_extrude(height) difference() {
|
||||
round(or = wall / 2 - eps, ir = 0) difference() {
|
||||
rounded_square([depth, width], rad);
|
||||
stl(str("ssr_shroud_", name)) {
|
||||
// base and sides
|
||||
translate([center_x, 0]) {
|
||||
rounded_rectangle([depth - eps, width - eps, top], rad, center = false);
|
||||
|
||||
rounded_square([depth - 2 * wall, width - 2 * wall], rad - wall);
|
||||
linear_extrude(height) difference() {
|
||||
round(or = wall / 2 - eps, ir = 0) difference() {
|
||||
rounded_square([depth, width], rad);
|
||||
|
||||
translate([depth / 2, 0])
|
||||
square([2 * rad, width], center = true);
|
||||
rounded_square([depth - 2 * wall, width - 2 * wall], rad - wall);
|
||||
|
||||
translate([depth / 2, 0])
|
||||
square([2 * rad, width], center = true);
|
||||
|
||||
}
|
||||
translate([cable_x - center_x, 0])
|
||||
square([cable_d, width + 1], center = true);
|
||||
}
|
||||
translate([cable_x - center_x, 0])
|
||||
square([cable_d, width + 1], center = true);
|
||||
}
|
||||
}
|
||||
// cable slots
|
||||
for(side = [-1, 1])
|
||||
translate([cable_x, side * (width / 2 - wall / 2), height / 2])
|
||||
rotate([90, 0, 0])
|
||||
linear_extrude(wall, center = true)
|
||||
difference() {
|
||||
square([cable_d + eps, height], center = true);
|
||||
// cable slots
|
||||
for(side = [-1, 1])
|
||||
translate([cable_x, side * (width / 2 - wall / 2), height / 2])
|
||||
rotate([90, 0, 0])
|
||||
linear_extrude(wall, center = true)
|
||||
difference() {
|
||||
square([cable_d + eps, height], center = true);
|
||||
|
||||
translate([0, height / 2])
|
||||
vertical_tearslot(h = 0, r = cable_d / 2, l = cable_d);
|
||||
}
|
||||
// insert boss
|
||||
ssr_shroud_hole_positions(type)
|
||||
vflip()
|
||||
translate_z(height)
|
||||
rotate($side * 90)
|
||||
insert_lug(insert, wall, counter_bore);
|
||||
translate([0, height / 2])
|
||||
vertical_tearslot(h = 0, r = cable_d / 2, l = cable_d);
|
||||
}
|
||||
// insert boss
|
||||
ssr_shroud_hole_positions(type)
|
||||
vflip()
|
||||
translate_z(height)
|
||||
rotate($side * 90)
|
||||
insert_lug(insert, wall, counter_bore);
|
||||
}
|
||||
}
|
||||
|
||||
module ssr_shroud_assembly(type, cable_d, name) //! The printed parts with inserts fitted
|
||||
assembly(str("SSR_shroud_", name)) {
|
||||
assembly(str("SSR_shroud_", name), ngb = true) {
|
||||
|
||||
translate_z(ssr_shroud_height(type))
|
||||
vflip()
|
||||
@@ -119,8 +120,7 @@ assembly(str("SSR_shroud_", name)) {
|
||||
|
||||
module ssr_shroud_fastened_assembly(type, cable_d, thickness, name) //! Assembly with screws in place
|
||||
{
|
||||
washer = screw_washer(screw);
|
||||
screw_length = screw_shorter_than(2 * washer_thickness(washer) + thickness + insert_length(insert) + counter_bore);
|
||||
screw_length = screw_length(screw, thickness + counter_bore, 2, true);
|
||||
|
||||
ssr_shroud_assembly(type, cable_d, name);
|
||||
|
||||
|
@@ -75,32 +75,29 @@ module strap_holes(length, type = strap, h = 100) //! The panel cut outs
|
||||
strap_boss_shape(type);
|
||||
|
||||
module strap(length, type = strap) { //! Generate the STL for the rubber strap
|
||||
stl("strap");
|
||||
|
||||
len = length - 2 * (wall + clearance);
|
||||
w = strap_width(type);
|
||||
|
||||
linear_extrude(strap_thickness(type), convexity = 3)
|
||||
difference() {
|
||||
rounded_square([len, w], w / 2 - eps);
|
||||
stl("strap")
|
||||
linear_extrude(strap_thickness(type), convexity = 3)
|
||||
difference() {
|
||||
rounded_square([len, w], w / 2 - eps);
|
||||
|
||||
for(end = [-1, 1])
|
||||
translate([end * (len / 2 - strap_min_width(type) - strap_boss_r(type) - clearance), 0])
|
||||
rotate(end * 90 + 90)
|
||||
hull() {
|
||||
offset(clearance)
|
||||
strap_boss_shape(type);
|
||||
|
||||
translate([strap_extension(type) / 2, 0])
|
||||
for(end = [-1, 1])
|
||||
translate([end * (len / 2 - strap_min_width(type) - strap_boss_r(type) - clearance), 0])
|
||||
rotate(end * 90 + 90)
|
||||
hull() {
|
||||
offset(clearance)
|
||||
strap_boss_shape(type);
|
||||
}
|
||||
}
|
||||
|
||||
translate([strap_extension(type) / 2, 0])
|
||||
offset(clearance)
|
||||
strap_boss_shape(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module strap_end(type = strap) { //! Generate the STL for end piece
|
||||
stl("strap_end");
|
||||
|
||||
z1 = strap_height(type) - strap_thickness(type) - clearance;
|
||||
z2 = strap_height(type) + strap_key(type);
|
||||
r1 = strap_boss_r(type) - 1;
|
||||
@@ -121,48 +118,49 @@ module strap_end(type = strap) { //! Generate the STL for end piece
|
||||
circle(r1);
|
||||
}
|
||||
|
||||
union() {
|
||||
linear_extrude(z1)
|
||||
with_hole()
|
||||
outer();
|
||||
|
||||
translate_z(z1)
|
||||
linear_extrude(strap_height(type) - z1)
|
||||
difference() {
|
||||
stl("strap_end")
|
||||
union() {
|
||||
linear_extrude(z1)
|
||||
with_hole()
|
||||
outer();
|
||||
|
||||
hull() {
|
||||
translate([0, -strap_width(type) / 2 - clearance])
|
||||
square([strap_boss_r(type) + overlap, strap_width(type) + 2 * clearance]);
|
||||
translate_z(z1)
|
||||
linear_extrude(strap_height(type) - z1)
|
||||
difference() {
|
||||
outer();
|
||||
|
||||
translate([-strap_extension(type) / 2, 0])
|
||||
circle(d = strap_width(type) + 2 * clearance);
|
||||
hull() {
|
||||
translate([0, -strap_width(type) / 2 - clearance])
|
||||
square([strap_boss_r(type) + overlap, strap_width(type) + 2 * clearance]);
|
||||
|
||||
translate([-strap_extension(type) / 2, 0])
|
||||
circle(d = strap_width(type) + 2 * clearance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
linear_extrude(strap_height(type) - layer_height)
|
||||
with_hole()
|
||||
strap_boss_shape(type);
|
||||
linear_extrude(strap_height(type) - layer_height)
|
||||
with_hole()
|
||||
strap_boss_shape(type);
|
||||
|
||||
linear_extrude(z2)
|
||||
with_hole()
|
||||
offset(cnc_bit_r)
|
||||
offset(-step - cnc_bit_r)
|
||||
strap_boss_shape(type);
|
||||
linear_extrude(z2)
|
||||
with_hole()
|
||||
offset(cnc_bit_r)
|
||||
offset(-step - cnc_bit_r)
|
||||
strap_boss_shape(type);
|
||||
|
||||
render() difference() {
|
||||
cylinder(r = r1 + eps, h = z2);
|
||||
render() difference() {
|
||||
cylinder(r = r1 + eps, h = z2);
|
||||
|
||||
translate_z(z2)
|
||||
insert_hole(strap_insert(type), counterbore);
|
||||
translate_z(z2)
|
||||
insert_hole(strap_insert(type), counterbore);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
//! * Place the insert into the hole and push home with a soldering iron with a tapered bit heated to 200°C.
|
||||
//
|
||||
module strap_end_assembly(type = strap)
|
||||
assembly("strap_end") {
|
||||
assembly("strap_end", ngb = true) {
|
||||
stl_colour(pp1_colour)
|
||||
strap_end(type);
|
||||
|
||||
@@ -172,11 +170,9 @@ assembly("strap_end") {
|
||||
|
||||
module strap_assembly(length, type = strap) { //! Assembly with screws in place
|
||||
screw = strap_screw(type);
|
||||
washer = screw_washer(screw);
|
||||
penny = penny_washer(washer);
|
||||
insert = strap_insert(type);
|
||||
penny = penny_washer(screw_washer(screw));
|
||||
|
||||
screw_length = screw_shorter_than(washer_thickness(washer) + washer_thickness(penny) + insert_length(insert) + panel_clearance + counterbore);
|
||||
screw_length = screw_length(screw, washer_thickness(penny) + panel_clearance + counterbore, 1, true);
|
||||
|
||||
stl_colour(pp4_colour) strap(length, type);
|
||||
|
||||
|
210
readme.md
@@ -37,12 +37,12 @@ See [usage](docs/usage.md) for requirements, installation instructions and a usa
|
||||
<tr><td> <a href = "#Extrusions">Extrusions</a> </td><td> <a href = "#Opengrab">Opengrab</a> </td><td> <a href = "#Stepper_motors">Stepper_motors</a> </td><td> <a href = "#PSU_shroud">PSU_shroud</a> </td><td> <a href = "#Rounded_right_triangle">Rounded_right_triangle</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Fans">Fans</a> </td><td> <a href = "#PCB">PCB</a> </td><td> <a href = "#Swiss_clips">Swiss_clips</a> </td><td> <a href = "#Press_fit">Press_fit</a> </td><td> <a href = "#Sector">Sector</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Fuseholder">Fuseholder</a> </td><td> <a href = "#PCBs">PCBs</a> </td><td> <a href = "#Toggles">Toggles</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 = "#Geared_steppers">Geared_steppers</a> </td><td> <a href = "#PSUs">PSUs</a> </td><td> <a href = "#Transformers">Transformers</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 = "#Green_terminals">Green_terminals</a> </td><td> <a href = "#Panel_meters">Panel_meters</a> </td><td> <a href = "#Tubings">Tubings</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 = "#Hot_ends">Hot_ends</a> </td><td> <a href = "#Pillars">Pillars</a> </td><td> <a href = "#Variacs">Variacs</a> </td><td> <a href = "#Screw_knob">Screw_knob</a> </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 = "#Veroboard">Veroboard</a> </td><td> <a href = "#Socket_box">Socket_box</a> </td><td></td><td></td></tr>
|
||||
<tr><td> <a href = "#IECs">IECs</a> </td><td> <a href = "#Pulleys">Pulleys</a> </td><td> <a href = "#Washers">Washers</a> </td><td> <a href = "#Strap_handle">Strap_handle</a> </td><td></td><td></td></tr>
|
||||
<tr><td> <a href = "#Inserts">Inserts</a> </td><td></td><td> <a href = "#Wire">Wire</a> </td><td></td><td></td><td></td></tr>
|
||||
<tr><td> <a href = "#Geared_steppers">Geared_steppers</a> </td><td> <a href = "#PSUs">PSUs</a> </td><td> <a href = "#Transformers">Transformers</a> </td><td> <a href = "#Printed_pulleys">Printed_pulleys</a> </td><td> <a href = "#Thread">Thread</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 = "#Tubings">Tubings</a> </td><td> <a href = "#Ribbon_clamp">Ribbon_clamp</a> </td><td> <a href = "#Tube">Tube</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Hot_ends">Hot_ends</a> </td><td> <a href = "#Pillars">Pillars</a> </td><td> <a href = "#Variacs">Variacs</a> </td><td> <a href = "#SSR_shroud">SSR_shroud</a> </td><td></td><td></td></tr>
|
||||
<tr><td> <a href = "#Hygrometer">Hygrometer</a> </td><td> <a href = "#Pin_headers">Pin_headers</a> </td><td> <a href = "#Veroboard">Veroboard</a> </td><td> <a href = "#Screw_knob">Screw_knob</a> </td><td></td><td></td></tr>
|
||||
<tr><td> <a href = "#IECs">IECs</a> </td><td> <a href = "#Pulleys">Pulleys</a> </td><td> <a href = "#Washers">Washers</a> </td><td> <a href = "#Socket_box">Socket_box</a> </td><td></td><td></td></tr>
|
||||
<tr><td> <a href = "#Inserts">Inserts</a> </td><td></td><td> <a href = "#Wire">Wire</a> </td><td> <a href = "#Strap_handle">Strap_handle</a> </td><td></td><td></td></tr>
|
||||
<tr><td></td><td></td><td> <a href = "#Zipties">Zipties</a> </td><td></td><td></td><td></td></tr>
|
||||
</table>
|
||||
|
||||
@@ -313,7 +313,7 @@ Models of radial blowers.
|
||||
| 4 | `screw(M2_cap_screw, 8)` | Screw M2 cap x 8mm |
|
||||
| 3 | `screw(M3_cap_screw, 20)` | Screw M3 cap x 20mm |
|
||||
| 2 | `screw(M4_cap_screw, 25)` | Screw M4 cap x 25mm |
|
||||
| 1 | `blower(BL40x10)` | Square radial 4010 |
|
||||
| 1 | `blower(BL40x10)` | Square radial fan 4010 |
|
||||
| 4 | `washer(M2_washer)` | Washer M2 x 5mm x 0.3mm |
|
||||
| 3 | `washer(M3_washer)` | Washer M3 x 7mm x 0.5mm |
|
||||
| 2 | `washer(M4_washer)` | Washer M4 x 9mm x 0.8mm |
|
||||
@@ -1048,10 +1048,12 @@ Parametric green terminal blocks
|
||||
### Vitamins
|
||||
| Qty | Module call | BOM entry |
|
||||
| ---:|:--- |:---|
|
||||
| 1 | `green_terminal(gt_6p35, 2)` | Terminal block 2 way 0.25" |
|
||||
| 1 | `green_terminal(gt_5p08, 3)` | Terminal block 3 way 0.2" |
|
||||
| 1 | `green_terminal(gt_3p5, 4)` | Terminal block 4 way 3.5mm |
|
||||
| 1 | `green_terminal(gt_2p54, 5)` | Terminal block 5 way 0.1" |
|
||||
| 1 | `green_terminal(gt_5x17, 2)` | Terminal block 2 way 5mm |
|
||||
| 1 | `green_terminal(gt_5x11, 3)` | Terminal block 3 way 5mm |
|
||||
| 1 | `green_terminal(gt_6p35, 4)` | Terminal block 4 way 0.25" |
|
||||
| 1 | `green_terminal(gt_5p08, 5)` | Terminal block 5 way 0.2" |
|
||||
| 1 | `green_terminal(gt_3p5, 6)` | Terminal block 6 way 3.5mm |
|
||||
| 1 | `green_terminal(gt_2p54, 7)` | Terminal block 7 way 0.1" |
|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
@@ -1102,17 +1104,17 @@ Needs updating as mostly obsolete versions.
|
||||
### Vitamins
|
||||
| Qty | Module call | BOM entry |
|
||||
| ---:|:--- |:---|
|
||||
| 2 | `tubing(HSHRNK16)` | Heatshrink sleeving ID 1.6mm x 15mm |
|
||||
| 2 | `tubing(HSHRNK16)` | Heatshrink sleeving ID 1.6mm x 15mm - not shown |
|
||||
| 4 | `tubing(HSHRNK64, 60)` | Heatshrink sleeving ID 6.4mm x 60mm |
|
||||
| 1 | `e3d_hot_end(E3Dv5, 3)` | Hot end E3D V5 direct 3mm |
|
||||
| 1 | `e3d_hot_end(E3Dv6, 3)` | Hot end E3D V6 direct 3mm |
|
||||
| 1 | `e3d_hot_end(E3D_clone, 3)` | Hot end E3D clone aliexpress 3mm |
|
||||
| 1 | `jhead_hot_end(JHeadMk5, 3)` | Hot end JHead MK5 3mm |
|
||||
| 2 | `tubing(PTFE07, 62)` | PTFE sleeving OD 1.2mm ID 0.71mm x 62mm |
|
||||
| 2 | `tubing(PTFE20, 45)` | PTFE sleeving OD 2.6mm ID 2mm x 45mm |
|
||||
| 1 | `resistor(RIE1212UB5C5R6)` | Resistor UB5C 5R6F 5R6 3W vitreous enamel |
|
||||
| 2 | `tubing(PTFE07, 62)` | PTFE sleeving OD 1.2mm ID 0.71mm x 62mm - not shown |
|
||||
| 2 | `tubing(PTFE20, 45)` | PTFE sleeving OD 2.6mm ID 2mm x 45mm - not shown |
|
||||
| 1 | `resistor(RIE1212UB5C5R6)` | Resistor UB5C 5R6F 5R6 3W vitreous enamel - not shown |
|
||||
| 1 | | Tape self amalgamating silicone 110mm x 25mm |
|
||||
| 1 | `resistor(Epcos)` | Thermistor Epcos B57560G104F 100K 1% |
|
||||
| 1 | `resistor(Epcos)` | Thermistor Epcos B57560G104F 100K 1% - not shown |
|
||||
| 2 | | Wire Red PTFE 16/0.2mm strands, length 170mm |
|
||||
| 4 | `ziptie(small_ziptie, 8)` | Ziptie 2.5mm x 100mm min length |
|
||||
|
||||
@@ -1748,7 +1750,11 @@ UK 13A sockets at the moment.
|
||||
---
|
||||
<a name="Microswitches"></a>
|
||||
## Microswitches
|
||||
Used for limit switches.
|
||||
Used for limit switches. Currently only the button type is supported as the lever and roller types are less accurate.
|
||||
|
||||
The switch is drawn with the button at the nominal operation point. This can be plus or minus `microswitch_op_tol(type)`.
|
||||
|
||||
When the button is released it comes out by a maximum of `microswitch_fp_max(type)` from the nominal operating point.
|
||||
|
||||
[vitamins/microswitches.scad](vitamins/microswitches.scad) Object definitions.
|
||||
|
||||
@@ -1761,14 +1767,16 @@ Used for limit switches.
|
||||
|:--- |:--- |
|
||||
| `microswitch_body_clr(type)` | Body colour |
|
||||
| `microswitch_button_clr(type)` | Button colour |
|
||||
| `microswitch_button_pos(type)` | Button position |
|
||||
| `microswitch_button_pos(type)` | Button position at operating point |
|
||||
| `microswitch_button_t(type)` | Button thickness |
|
||||
| `microswitch_button_w(type)` | Button width |
|
||||
| `microswitch_fp_max(type)` | Free position maximum |
|
||||
| `microswitch_hole_d(type)` | Screw hole diameter |
|
||||
| `microswitch_holes(type)` | Hole positions |
|
||||
| `microswitch_leg(type)` | Leg types |
|
||||
| `microswitch_legs(type)` | Leg positions |
|
||||
| `microswitch_length(type)` | Body length |
|
||||
| `microswitch_op_tol(type)` | Operating position +/- tolerance |
|
||||
| `microswitch_radius(type)` | Body corner radius |
|
||||
| `microswitch_thickness(type)` | Body thickness |
|
||||
| `microswitch_width(type)` | Body width |
|
||||
@@ -2303,25 +2311,30 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
|
||||
| ---:|:--- |:---|
|
||||
| 1 | `pcb(ArduinoLeonardo)` | Arduino Leonardo |
|
||||
| 1 | `pcb(ArduinoUno3)` | Arduino Uno R3 |
|
||||
| 1 | `pcb(BTT_SKR_MINI_E3_V2_0)` | BigTreeTech SKR Mini E3 v2.0 |
|
||||
| 1 | `pcb(BTT_SKR_V1_4_TURBO)` | BigTreeTech SKR v1.4 Turbo |
|
||||
| 1 | | Cat 5 patch cable 300mm |
|
||||
| 1 | `d_plug(DCONN15, pcb = true)` | D-type 15 way PCB mount plug |
|
||||
| 1 | `pcb(DuetE)` | Duet 2 Ethernet electronics |
|
||||
| 1 | `pcb(Duex2)` | Duex2 expansion board |
|
||||
| 1 | `pcb(Duex2)` | Duex2 expansion board - not shown |
|
||||
| 1 | `pcb(Duex5)` | Duex5 expansion board |
|
||||
| 1 | `pcb(ESP-01)` | ESP-01 |
|
||||
| 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 - not shown |
|
||||
| 4 | | Micro SD card |
|
||||
| 1 | | Micro SD card - not shown |
|
||||
| 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 |
|
||||
| 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 |
|
||||
| 17 | `nut(M3_nut, nyloc = true)` | Nut M3 x 2.4mm nyloc |
|
||||
| 8 | `nut(M4_nut, nyloc = true)` | Nut M4 x 3.2mm nyloc |
|
||||
| 1 | `pcb(PI_IO)` | PI_IO V2 |
|
||||
| 1 | `pcb(PSU12V1A)` | PSU 12V 1A |
|
||||
| 1 | `pcb(PSU12V1A)` | PSU 12V 1A - not shown |
|
||||
| 1 | `pcb(PERF60x40)` | Perfboard 60 x 40mm |
|
||||
| 1 | `pcb(PERF70x30)` | Perfboard 70 x 30mm |
|
||||
| 1 | `pcb(PERF70x50)` | Perfboard 70 x 50mm |
|
||||
@@ -2337,19 +2350,21 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
|
||||
| 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(M2p5_pan_screw, 30)` | Screw M2.5 pan x 30mm |
|
||||
| 4 | `screw(M3_cap_screw, 16)` | Screw M3 cap x 16mm |
|
||||
| 8 | `screw(M3_cap_screw, 30)` | Screw M3 cap x 30mm |
|
||||
| 12 | `screw(M4_cap_screw, 35)` | Screw M4 cap x 35mm |
|
||||
| 4 | `screw(M3_cap_screw, 30)` | Screw M3 cap x 30mm |
|
||||
| 9 | `screw(M3_cap_screw, 35)` | Screw M3 cap x 35mm |
|
||||
| 8 | `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 - not shown |
|
||||
| 1 | `pcb(WD2002SJ)` | WD2002SJ Buck Boost DC-DC converter |
|
||||
| 16 | `washer(M2_washer)` | Washer M2 x 5mm x 0.3mm |
|
||||
| 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 |
|
||||
| 17 | `washer(M3_washer)` | Washer M3 x 7mm x 0.5mm |
|
||||
| 8 | `washer(M4_washer)` | Washer M4 x 9mm x 0.8mm |
|
||||
| 1 | `pcb(ZC_A0591)` | ZC-A0591 ULN2003 driver PCB |
|
||||
|
||||
### Printed
|
||||
@@ -2359,21 +2374,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_spacer25110.stl |
|
||||
| 4 | pcb_spacer25120.stl |
|
||||
| 4 | pcb_spacer25130.stl |
|
||||
| 4 | pcb_spacer25140_2.stl |
|
||||
| 4 | pcb_spacer25140.stl |
|
||||
| 4 | pcb_spacer25150_2.stl |
|
||||
| 4 | pcb_spacer25160_2.stl |
|
||||
| 4 | pcb_spacer25170_2.stl |
|
||||
| 4 | pcb_spacer25190.stl |
|
||||
| 4 | pcb_spacer25200.stl |
|
||||
| 2 | pcb_spacer2580.stl |
|
||||
| 4 | pcb_spacer30170.stl |
|
||||
| 4 | pcb_spacer30180.stl |
|
||||
| 5 | pcb_spacer30210.stl |
|
||||
| 4 | pcb_spacer30220.stl |
|
||||
| 4 | pcb_spacer3050.stl |
|
||||
| 4 | pcb_spacer40210.stl |
|
||||
| 4 | pcb_spacer40220.stl |
|
||||
| 4 | pcb_spacer40230.stl |
|
||||
| 4 | pcb_spacer40240.stl |
|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
@@ -2603,8 +2618,8 @@ Timing belt pulleys, both toothed and plain with internal bearings for idlers.
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| `pulley(type)` | Draw a pulley |
|
||||
| `pulley_assembly(type)` | Draw a pulley with its grub screws in place |
|
||||
| `pulley(type, colour = silver)` | Draw a pulley |
|
||||
| `pulley_assembly(type, colour = silver)` | Draw a pulley with its grub screws in place |
|
||||
|
||||

|
||||
|
||||
@@ -2651,13 +2666,15 @@ Linear rails with carriages.
|
||||
| `carriage_length(type)` | Overall length |
|
||||
| `carriage_pitch_x(type)` | Screw hole x pitch |
|
||||
| `carriage_pitch_y(type)` | Screw hole y pitch |
|
||||
| `carriage_rail(type)` | Rail type |
|
||||
| `carriage_screw(type)` | Carriage screw type |
|
||||
| `carriage_width(type)` | Width of carriage |
|
||||
| `rail_bore(type)` | Counter bore diameter for screw head |
|
||||
| `rail_bore_depth(type)` | Counter bore depth |
|
||||
| `rail_carriage(type)` | Carriage type |
|
||||
| `rail_end(type)` | Minimum distance screw can be from the end |
|
||||
| `rail_end_screw(type)` | Screw used for ends only (Countersink used for better location) |
|
||||
| `rail_groove_offset(type)` | Offset of centre of groove from top of rail |
|
||||
| `rail_groove_width(type)` | Groove width |
|
||||
| `rail_height(type)` | Height of rail section |
|
||||
| `rail_hole(type)` | Screw hole diameter |
|
||||
| `rail_pitch(type)` | Distance between screws |
|
||||
@@ -2669,17 +2686,17 @@ Linear rails with carriages.
|
||||
|:--- |:--- |
|
||||
| `carriage_screw_depth(type)` | Carriage thread depth |
|
||||
| `carriage_size(type)` | Size of carriage |
|
||||
| `carriage_travel(type, rail_length)` | How far the carriage can travel on a given length rail |
|
||||
| `rail_holes(type, length)` | Number of holes in a rail given its `length` |
|
||||
| `rail_screw_height(type, screw)` | Position screw taking into account countersink into counterbored hole |
|
||||
| `rail_travel(type, length)` | How far the carriage can travel |
|
||||
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| `carriage(type, rail, end_colour = grey(20)` | Draw the specified carriage |
|
||||
| `carriage(type, end_colour = grey(20)` | Draw the specified carriage |
|
||||
| `carriage_hole_positions(type)` | Position children over screw holes |
|
||||
| `rail(type, length)` | Draw the specified rail |
|
||||
| `rail_assembly(type, length, pos, carriage_end_colour = grey(20)` | Rail and carriage assembly |
|
||||
| `rail(type, length, colour = grey(90)` | Draw the specified rail |
|
||||
| `rail_assembly(carriage, length, pos, carriage_end_colour = grey(20)` | Rail and carriage assembly |
|
||||
| `rail_hole_positions(type, length, first = 0, screws = 100, both_ends = true)` | Position children over screw holes |
|
||||
| `rail_screws(type, length, thickness, screws = 100, index_screws = undef)` | Place screws in the rail |
|
||||
|
||||
@@ -2688,8 +2705,7 @@ Linear rails with carriages.
|
||||
### Vitamins
|
||||
| Qty | Module call | BOM entry |
|
||||
| ---:|:--- |:---|
|
||||
| 1 | `rail(MGN12, 200)` | Linear rail MGN12 x 200mm |
|
||||
| 1 | `rail(MGN12H, 200)` | Linear rail MGN12H x 200mm |
|
||||
| 2 | `rail(MGN12, 200)` | Linear rail MGN12 x 200mm |
|
||||
| 1 | `rail(MGN15, 200)` | Linear rail MGN15 x 200mm |
|
||||
| 1 | `rail(MGN5, 200)` | Linear rail MGN5 x 200mm |
|
||||
| 1 | `rail(MGN7, 200)` | Linear rail MGN7 x 200mm |
|
||||
@@ -2897,10 +2913,11 @@ For an explanation of `screw_polysink()` see <https://hydraraptor.blogspot.com/2
|
||||
|:--- |:--- |
|
||||
| `screw_boss_diameter(type)` | Boss big enough for nut trap and washer |
|
||||
| `screw_head_depth(type, d = 0)` | How far a counter sink head will go into a straight hole diameter d |
|
||||
| `screw_longer_than(x)` | Returns shortest screw length longer or equal to x |
|
||||
| `screw_length(screw, thickness, washers, insert = false, nyloc = false, nut = false, longer = false)` | Returns the length of the longest or shortest screw that will got through `thickness` and `washers` and possibly an `insert`, `nut` or `nyloc` |
|
||||
| `screw_longer_than(x)` | Returns the length of the shortest screw length longer or equal to x |
|
||||
| `screw_nut_radius(type)` | Radius of matching nut |
|
||||
| `screw_polysink_r(type, z)` | Countersink hole profile corrected for rounded staircase extrusions. |
|
||||
| `screw_shorter_than(x)` | Returns longest screw length shorter than or equal to x |
|
||||
| `screw_shorter_than(x)` | Returns the length of the longest screw shorter than or equal to x |
|
||||
|
||||
### Modules
|
||||
| Module | Description |
|
||||
@@ -2936,6 +2953,7 @@ For an explanation of `screw_polysink()` see <https://hydraraptor.blogspot.com/2
|
||||
| 1 | `screw(M4_pan_screw, 30)` | Screw M4 pan x 30mm |
|
||||
| 1 | `screw(M5_cap_screw, 30)` | Screw M5 cap x 30mm |
|
||||
| 1 | `screw(M5_cs_cap_screw, 30)` | Screw M5 cs cap x 30mm |
|
||||
| 1 | `screw(M5_dome_screw, 30)` | Screw M5 dome x 30mm |
|
||||
| 1 | `screw(M5_hex_screw, 30)` | Screw M5 hex x 30mm |
|
||||
| 1 | `screw(M5_pan_screw, 30)` | Screw M5 pan x 30mm |
|
||||
| 1 | `screw(M6_cap_screw, 30)` | Screw M6 cap x 30mm |
|
||||
@@ -3776,6 +3794,7 @@ Veroboard with mounting holes, track breaks, removed tracks, solder points and c
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| `vero_length(type)` | Length of the board |
|
||||
| `vero_size(type)` | Board size |
|
||||
| `vero_thickness(type)` | Thickness of the substrate |
|
||||
| `vero_track_thickness(type)` | Thickness of the tracks |
|
||||
| `vero_track_width(type)` | The width of the tracks |
|
||||
@@ -3789,7 +3808,7 @@ Veroboard with mounting holes, track breaks, removed tracks, solder points and c
|
||||
| `vero_mounting_hole_positions(type)` | Positions children at the mounting holes |
|
||||
| `vero_mounting_holes(type, h = 100)` | Drill mounting holes in a panel |
|
||||
| `veroboard(type)` | Draw specified veroboard with missing tracks and track breaks |
|
||||
| `veroboard_assembly(type, height, thickness, flip = false)` | Draw the assembly with components and fasteners in place |
|
||||
| `veroboard_assembly(type, height, thickness, flip = false, ngb = false)` | Draw the assembly with components and fasteners in place |
|
||||
|
||||

|
||||
|
||||
@@ -4558,7 +4577,7 @@ to the assembly, for example to add inserts.
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| `drag_chain_assembly(type, pos = 0)` | Drag chain assembly |
|
||||
| `drag_chain_assembly(type, pos = 0, render = false)` | Drag chain assembly |
|
||||
| `drag_chain_link(type, start = false, end = false, check_kids = true)` | One link of the chain, special case for start and end |
|
||||
| `drag_chain_screw_positions(type, end)` | Place children at the screw positions, end = 0 for the start, 1 for the end |
|
||||
| `screw_lug(screw, h = 0)` | Create a D shaped lug for a screw |
|
||||
@@ -5038,6 +5057,73 @@ It can also have printed feet on the base with the screws doubling up to hold th
|
||||
| 1 | box2_assembly |
|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
|
||||
---
|
||||
<a name="Printed_pulleys"></a>
|
||||
## Printed_pulleys
|
||||
Printed pulleys are a remix of droftarts's (see <https://www.thingiverse.com/droftarts/designs>) Parametric Pulleys
|
||||
on Thingiverse (see <https://www.thingiverse.com/thing:16627>) and are licensed under the
|
||||
Creative Commons - Attribution - Share Alike license (see <https://creativecommons.org/licenses/by-sa/3.0/>)
|
||||
|
||||
[printed/printed_pulleys.scad](printed/printed_pulleys.scad) Implementation.
|
||||
|
||||
[tests/printed_pulleys.scad](tests/printed_pulleys.scad) Code for this example.
|
||||
|
||||
### Functions
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| `printed_pulley_inverted(type)` | Need to print upside down to prevent overhang |
|
||||
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| `printed_pulley(type)` | Draw a printable pulley |
|
||||
| `printed_pulley_assembly(type, colour = pp1_colour)` | Draw a printed pulley with its grub screws in place |
|
||||
| `printed_pulley_teeth(type)` | Draw the pulley's teeth |
|
||||
|
||||

|
||||
|
||||
### Vitamins
|
||||
| Qty | Module call | BOM entry |
|
||||
| ---:|:--- |:---|
|
||||
| 1 | `screw(M3_grub_screw, 3)` | Screw M3 grub x 3mm |
|
||||
| 2 | `screw(M3_grub_screw, 4.5)` | Screw M3 grub x 4.5mm |
|
||||
| 2 | `screw(M3_grub_screw, 4)` | Screw M3 grub x 4mm |
|
||||
| 4 | `screw(M3_grub_screw, 6)` | Screw M3 grub x 6mm |
|
||||
| 1 | `screw(M4_grub_screw, 6)` | Screw M4 grub x 6mm |
|
||||
|
||||
### Printed
|
||||
| Qty | Filename |
|
||||
| ---:|:--- |
|
||||
| 1 | printed_pulley_GT2x12_pulley.stl |
|
||||
| 1 | printed_pulley_GT2x16_plain_idler.stl |
|
||||
| 1 | printed_pulley_GT2x16_pulley.stl |
|
||||
| 1 | printed_pulley_GT2x16_toothed_idler.stl |
|
||||
| 1 | printed_pulley_GT2x16x7_plain_idler.stl |
|
||||
| 1 | printed_pulley_GT2x20_plain_idler.stl |
|
||||
| 1 | printed_pulley_GT2x20_toothed_idler.stl |
|
||||
| 1 | printed_pulley_GT2x20ob_pulley.stl |
|
||||
| 1 | printed_pulley_GT2x20um_pulley.stl |
|
||||
| 1 | printed_pulley_T2p5x16_pulley.stl |
|
||||
| 1 | printed_pulley_T5x10_pulley.stl |
|
||||
|
||||
### Assemblies
|
||||
| Qty | Name |
|
||||
| ---:|:--- |
|
||||
| 1 | printed_pulley_GT2x12_pulley_assembly |
|
||||
| 1 | printed_pulley_GT2x16_plain_idler_assembly |
|
||||
| 1 | printed_pulley_GT2x16_pulley_assembly |
|
||||
| 1 | printed_pulley_GT2x16_toothed_idler_assembly |
|
||||
| 1 | printed_pulley_GT2x16x7_plain_idler_assembly |
|
||||
| 1 | printed_pulley_GT2x20_plain_idler_assembly |
|
||||
| 1 | printed_pulley_GT2x20_toothed_idler_assembly |
|
||||
| 1 | printed_pulley_GT2x20ob_pulley_assembly |
|
||||
| 1 | printed_pulley_GT2x20um_pulley_assembly |
|
||||
| 1 | printed_pulley_T2p5x16_pulley_assembly |
|
||||
| 1 | printed_pulley_T5x10_pulley_assembly |
|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
|
||||
---
|
||||
@@ -5736,7 +5822,8 @@ Cylinder with a rounded end.
|
||||
---
|
||||
<a name="Rounded_polygon"></a>
|
||||
## Rounded_polygon
|
||||
Draw a polygon with rounded corners. Each element of the vector is the XY coordinate and a radius. Radius can be negative for a concave corner.
|
||||
Draw a polygon with rounded corners. Each element of the vector is the XY coordinate and a radius in clockwise order.
|
||||
Radius can be negative for a concave corner.
|
||||
|
||||
Because the tangents need to be calculated to find the length these can be calculated separately and re-used when drawing to save calculating them twice.
|
||||
|
||||
@@ -5747,6 +5834,7 @@ Because the tangents need to be calculated to find the length these can be calcu
|
||||
### Functions
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| `circle_tangent(p1, p2)` | Compute the clockwise tangent between two circles represented as [x,y,r] |
|
||||
| `rounded_polygon_length(points, tangents)` | Calculate the length given the point list and the list of tangents computed by ` rounded_polygon_tangents` |
|
||||
| `rounded_polygon_tangents(points)` | Compute the straight sections needed to draw and to compute the lengths |
|
||||
|
||||
@@ -5894,6 +5982,7 @@ Simple tube or ring
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| `rectangular_tube(size, center = true, thickness = 1, fillet = 0.5)` | Create a retangular tube with filleted corners |
|
||||
| `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 |
|
||||
@@ -5913,9 +6002,16 @@ Assembly views shown in the instructions can be large or small and this is deduc
|
||||
parts are used.
|
||||
This heuristic isn't always correct, so the default can be overridden by setting the `big` parameter of `assembly` to `true` or `false`.
|
||||
|
||||
Setting the `ngb` parameter of `assembly` to `true` removes its column from the global BOM and merges it parts into its parent assembly column of the global BOM.
|
||||
This is to prevent the global BOM page becoming too wide in large projects by having it include just the major assemblies.
|
||||
|
||||
The example below shows how to define a vitamin and incorporate it into an assembly with sub-assemblies and make an exploded view.
|
||||
The resulting flat BOM is shown but heirachical BOMs are also generated for real projects.
|
||||
|
||||
If the code to make an STL or DXF is made a child of the `stl()` or `dxf()` module then the STL or DXF will be used in the assembly views generated by `views.py` instead of generating
|
||||
it with code.
|
||||
This can speed up the generation of the build instructions greatly but isn't compatible with STLs that include support structures.
|
||||
|
||||
[utils/core/bom.scad](utils/core/bom.scad) Implementation.
|
||||
|
||||
[tests/BOM.scad](tests/BOM.scad) Code for this example.
|
||||
@@ -5932,7 +6028,7 @@ The resulting flat BOM is shown but heirachical BOMs are also generated for real
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| `assembly(name, big = undef)` | Name an assembly that will appear on the BOM, there needs to a module named `<name>_assembly` to make it. `big` can force big or small assembly diagrams. |
|
||||
| `assembly(name, big = undef, ngb = false)` | Name an assembly that will appear on the BOM, there needs to a module named `<name>_assembly` to make it. `big` can force big or small assembly diagrams. |
|
||||
| `dxf(name)` | Name a dxf that will appear on the BOM, there needs to a module named `<name>_dxf` to make it |
|
||||
| `explode(d, explode_children = false, offset = [0,0,0])` | Explode children by specified Z distance or vector `d`, option to explode grand children |
|
||||
| `hidden()` | Make item invisible, except on the BOM |
|
||||
@@ -5944,7 +6040,9 @@ The resulting flat BOM is shown but heirachical BOMs are also generated for real
|
||||
| `pose_vflip(exploded = undef)` | Pose an STL or assembly for rendering to png by flipping around the X axis, `exploded = true for` just the exploded view or `false` for unexploded only. |
|
||||
| `stl(name)` | Name an stl that will appear on the BOM, there needs to a module named `<name>_stl` to make it |
|
||||
| `stl_colour(colour = pp1_colour, alpha = 1)` | Colour an stl where it is placed in an assembly. `alpha` can be used to make it appear transparent. |
|
||||
| `vitamin(description)` | Describe a vitamin for the BOM entry and precede it with a module call that creates it, eg. "wigit(42): Type 42 widget" |
|
||||
| `use_dxf(name)` | Import a DXF to make a build panel |
|
||||
| `use_stl(name)` | Import an STL to make a build platter |
|
||||
| `vitamin(description)` | Describe a vitamin for the BOM entry and precede it with a module call that creates it, eg. "widget(42): Widget size 42" |
|
||||
|
||||

|
||||
|
||||
@@ -5971,9 +6069,9 @@ The resulting flat BOM is shown but heirachical BOMs are also generated for real
|
||||
### Assemblies
|
||||
| Qty | Name |
|
||||
| ---:|:--- |
|
||||
| 1 | widget_assembly |
|
||||
| 1 | widget_base_assembly |
|
||||
| 1 | widget_top_assembly |
|
||||
| 1 | widgit_base_assembly |
|
||||
| 1 | wigdit_assembly |
|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
@@ -6180,12 +6278,12 @@ do not intrude into the circle. See <https://hydraraptor.blogspot.com/2020/07/ho
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| `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 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 |
|
||||
| `semi_teardrop(h, r, d = undef, center = true, chamfer = 0, chamfer_both_ends = true, plus = false)` | A semi teardrop in the positive Y domain |
|
||||
| `teardrop(h, r, center = true, truncate = true, chamfer = 0, chamfer_both_ends = true, 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, chamfer_both_ends)` | Helper module for adding chamfer to a teardrop |
|
||||
| `teardrop_plus(h, r, center = true, truncate = true, chamfer = 0, chamfer_both_ends = true)` | Slightly elongated teardrop to allow for the 3D printing staircase effect |
|
||||
| `tearslot(h, r, w, center = true, chamfer = 0, chamfer_both_ends = true, plus = false)` | A horizontal slot that doesn't need support material |
|
||||
| `vertical_tearslot(h, r, l, center = true, chamfer = 0, chamfer_both_ends = true, plus = false)` | A vertical slot that doesn't need support material |
|
||||
|
||||

|
||||
|
||||
|
@@ -60,6 +60,7 @@ class BOM:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.big = None
|
||||
self.ngb = False
|
||||
self.count = 1
|
||||
self.vitamins = {}
|
||||
self.printed = {}
|
||||
@@ -73,6 +74,7 @@ class BOM:
|
||||
return {
|
||||
"name" : self.name,
|
||||
"big" : self.big,
|
||||
"ngb" : self.ngb,
|
||||
"count" : self.count,
|
||||
"assemblies" : assemblies,
|
||||
"vitamins" : {v : self.vitamins[v].data() for v in self.vitamins},
|
||||
@@ -249,7 +251,7 @@ def boms(target = None, assembly = None):
|
||||
#
|
||||
# Run openscad
|
||||
#
|
||||
openscad.run("-D", "$bom=2", "-D", "$preview=true", "--hardwarnings", "-o", "openscad.echo", "-d", bom_dir + "/bom.deps", bom_maker_name)
|
||||
openscad.run("-D", "$bom=2", "-D", "$preview=true", "-o", "openscad.echo", "-d", bom_dir + "/bom.deps", bom_maker_name)
|
||||
os.remove(bom_maker_name)
|
||||
print("Generating bom ...", end=" ")
|
||||
|
||||
|
@@ -72,10 +72,11 @@ def make_parts(target, part_type, parts = None):
|
||||
#
|
||||
# Decide which files to make
|
||||
#
|
||||
all_parts = bom_to_parts(bom_dir, part_type)
|
||||
if parts:
|
||||
targets = list(parts) #copy the list so we dont modify the list passed in
|
||||
else:
|
||||
targets = bom_to_parts(bom_dir, part_type)
|
||||
targets = list(all_parts)
|
||||
for file in os.listdir(target_dir):
|
||||
if file.endswith('.' + part_type):
|
||||
if not file in targets:
|
||||
@@ -150,4 +151,4 @@ def make_parts(target, part_type, parts = None):
|
||||
for part in targets:
|
||||
print("Could not find a module called", part[:-4] + module_suffix, "to make", part)
|
||||
usage(part_type)
|
||||
times.print_times()
|
||||
times.print_times(all_parts)
|
||||
|
@@ -25,7 +25,7 @@ from __future__ import print_function
|
||||
import subprocess, sys
|
||||
|
||||
def run_list(args, silent = False, verbose = False):
|
||||
cmd = ["openscad"] + args
|
||||
cmd = ["openscad", "--hardwarnings"] + args
|
||||
if not silent:
|
||||
for arg in cmd:
|
||||
print(arg, end=" ")
|
||||
|
@@ -72,7 +72,9 @@ def plateup(target, part_type, usage = None):
|
||||
changed = check_deps(part_file, dname)
|
||||
if changed:
|
||||
print(changed)
|
||||
openscad.run("-D$bom=1", "-d", dname, "-o", part_file, src_file)
|
||||
target_def = ['-D$target="%s"' % target] if target else []
|
||||
cwd_def = ['-D$cwd="%s"' % os.getcwd().replace('\\', '/')]
|
||||
openscad.run_list(["-D$bom=1"] + target_def + cwd_def + ["-d", dname, "-o", part_file, src_file])
|
||||
if part_type == 'stl':
|
||||
c14n_stl.canonicalise(part_file)
|
||||
log_name = 'openscad.log'
|
||||
|
@@ -50,13 +50,16 @@ def do_cmd(cmd, output = sys.stdout):
|
||||
return subprocess.call(cmd, stdout = output, stderr = output)
|
||||
|
||||
def compare_images(a, b, c):
|
||||
if not os.path.isfile(b):
|
||||
print(Fore.MAGENTA + "Failed to generate %s while making %s" % (b, a), Fore.WHITE)
|
||||
sys.exit(1)
|
||||
if not os.path.isfile(a):
|
||||
return -1
|
||||
log_name = 'magick.log'
|
||||
with open(log_name, 'w') as output:
|
||||
do_cmd(("magick compare -metric AE -fuzz %d%% %s %s %s" % (fuzz, a, b, c)).split(), output = output)
|
||||
with open(log_name, 'r') as f:
|
||||
pixels = int(f.read().strip())
|
||||
pixels = int(float(f.read().strip()))
|
||||
os.remove(log_name)
|
||||
return pixels
|
||||
|
||||
@@ -126,14 +129,13 @@ def tests(tests):
|
||||
#
|
||||
# List of individual part files
|
||||
#
|
||||
|
||||
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('\n'+base_name)
|
||||
print(base_name)
|
||||
cap_name = base_name[0].capitalize() + base_name[1:]
|
||||
base_name = base_name.lower()
|
||||
scad_name = scad_dir + '/' + scad
|
||||
@@ -240,6 +242,7 @@ def tests(tests):
|
||||
BOM = bom.parse_bom()
|
||||
with open(bom_name, 'wt') as outfile:
|
||||
json.dump(BOM.flat_data(), outfile, indent = 4)
|
||||
print()
|
||||
|
||||
with open(bom_name, "rt") as bom_file:
|
||||
BOM = json.load(bom_file)
|
||||
|
@@ -52,23 +52,34 @@ def add_time(name, start):
|
||||
del times[name.lower()]
|
||||
times[name] = round(time.time() - start, 3)
|
||||
|
||||
def print_times():
|
||||
write_times()
|
||||
def print_times(files = None):
|
||||
sorted_times = sorted(times.items(), key=lambda kv: kv[1])
|
||||
total = 0
|
||||
old_total = 0
|
||||
for entry in sorted_times:
|
||||
colour = Fore.WHITE
|
||||
key = entry[0]
|
||||
new = entry[1]
|
||||
delta = 0
|
||||
if key in last_times:
|
||||
old = last_times[key]
|
||||
delta = new - old
|
||||
if delta > 0.3:
|
||||
colour = Fore.RED
|
||||
if delta < -0.3:
|
||||
colour = Fore.GREEN
|
||||
print(colour + "%5.1f %5.1f %s" % (new, delta, key))
|
||||
total += new
|
||||
if files and not key in files:
|
||||
del times[key]
|
||||
else:
|
||||
new = entry[1]
|
||||
delta = 0
|
||||
colour = Fore.WHITE
|
||||
if key in last_times:
|
||||
old = last_times[key]
|
||||
old_total += old
|
||||
delta = new - old
|
||||
if delta > 0.3:
|
||||
colour = Fore.RED
|
||||
if delta < -0.3:
|
||||
colour = Fore.GREEN
|
||||
print(colour + "%6.1f %5.1f %s" % (new, delta, key))
|
||||
total += new
|
||||
write_times()
|
||||
if sorted_times:
|
||||
print(Fore.WHITE + "%5.1f" % total)
|
||||
colour = Fore.WHITE
|
||||
delta = total - old_total
|
||||
if delta > 1:
|
||||
colour = Fore.RED
|
||||
if delta < -1:
|
||||
colour = Fore.GREEN
|
||||
print(colour + "%6.1f %5.1f TOTAL%s" % (total, delta, Fore.WHITE))
|
||||
|
437
scripts/views.py
@@ -36,6 +36,7 @@ import blurb
|
||||
import bom
|
||||
import shutil
|
||||
import re
|
||||
import copy
|
||||
from colorama import Fore
|
||||
|
||||
def is_assembly(s):
|
||||
@@ -74,19 +75,17 @@ def bom_to_assemblies(bom_dir, bounds_map):
|
||||
# Remove the main assembly if it is a shell
|
||||
#
|
||||
if flat_bom:
|
||||
ass = flat_bom[-1]
|
||||
ass = flat_bom[-1]
|
||||
if len(ass["assemblies"]) < 2 and not ass["vitamins"] and not ass["printed"] and not ass["routed"]:
|
||||
flat_bom = flat_bom[:-1]
|
||||
return [assembly["name"] for assembly in flat_bom]
|
||||
|
||||
def eop(print_mode, doc_file, last = False, first = False):
|
||||
if print_mode:
|
||||
print('\n<div style="page-break-after: always;"></div>', file = doc_file)
|
||||
else:
|
||||
if not first:
|
||||
print('[Top](#TOP)', file = doc_file)
|
||||
if not last:
|
||||
print("\n---", file = doc_file)
|
||||
def eop(doc_file, last = False, first = False):
|
||||
print('<span></span>', file = doc_file) # An invisable marker for page breaks because markdown takes much longer if the document contains a div
|
||||
if not first:
|
||||
print('[Top](#TOP)', file = doc_file)
|
||||
if not last:
|
||||
print("\n---", file = doc_file)
|
||||
|
||||
def pad(s, before, after = 0):
|
||||
return ' ' * before + str(s) + ' ' * after
|
||||
@@ -103,6 +102,27 @@ def usage():
|
||||
print("\nusage:\n\t views [target_config] [<name1>_assembly] ... [<nameN>_assembly] - Create assembly images and readme.")
|
||||
sys.exit(1)
|
||||
|
||||
types = ["vitamins", "printed", "routed"]
|
||||
|
||||
def merged(bom):
|
||||
bom = copy.deepcopy(bom)
|
||||
for aname in bom["assemblies"]:
|
||||
count = bom["assemblies"][aname]
|
||||
for ass in flat_bom:
|
||||
if ass['name'] == aname and ass['ngb']:
|
||||
merged_assembly = merged(ass)
|
||||
total = ass['count']
|
||||
for t in types:
|
||||
for thing in merged_assembly[t]:
|
||||
items = merged_assembly[t][thing]['count'] * count // total
|
||||
if thing in bom[t]:
|
||||
bom[t][thing]['count'] += items
|
||||
else:
|
||||
bom[t][thing] = merged_assembly[t][thing]
|
||||
bom[t][thing]['count'] = items
|
||||
break
|
||||
return bom
|
||||
|
||||
def views(target, do_assemblies = None):
|
||||
done_assemblies = []
|
||||
#
|
||||
@@ -139,6 +159,7 @@ def views(target, do_assemblies = None):
|
||||
# Find all the scad files
|
||||
#
|
||||
main_blurb = None
|
||||
pngs = []
|
||||
for dir in source_dirs(bom_dir):
|
||||
if os.path.isdir(dir):
|
||||
for filename in os.listdir(dir):
|
||||
@@ -165,15 +186,21 @@ def views(target, do_assemblies = None):
|
||||
if not "blurb" in ass:
|
||||
ass["blurb"] = blurb.scrape_module_blurb(lines[:line_no])
|
||||
break
|
||||
if not do_assemblies or real_name in do_assemblies:
|
||||
|
||||
#
|
||||
# Run openscad on the created file
|
||||
#
|
||||
dname = deps_name(deps_dir, filename)
|
||||
for explode in [0, 1]:
|
||||
#
|
||||
# Run openscad on the created file
|
||||
# Generate png name
|
||||
#
|
||||
dname = deps_name(deps_dir, filename)
|
||||
for explode in [0, 1]:
|
||||
png_name = target_dir + '/' + real_name + '.png'
|
||||
if not explode:
|
||||
png_name = png_name.replace('_assembly', '_assembled')
|
||||
png_name = target_dir + '/' + real_name + '.png'
|
||||
if not explode:
|
||||
png_name = png_name.replace('_assembly', '_assembled')
|
||||
pngs.append(png_name)
|
||||
|
||||
if not do_assemblies or real_name in do_assemblies:
|
||||
changed = check_deps(png_name, dname)
|
||||
changed = times.check_have_time(changed, png_name)
|
||||
changed = options.have_changed(changed, png_name)
|
||||
@@ -188,7 +215,9 @@ def views(target, do_assemblies = None):
|
||||
f.write("use <%s/%s>\n" % (dir, filename))
|
||||
f.write("%s();\n" % module);
|
||||
t = time.time()
|
||||
openscad.run_list(options.list() + ["-D$pose=1", "-D$explode=%d" % explode, colour_scheme, "--projection=p", "--imgsize=4096,4096", "--autocenter", "--viewall", "-d", dname, "-o", tmp_name, png_maker_name]);
|
||||
target_def = ['-D$target="%s"' % target] if target else []
|
||||
cwd_def = ['-D$cwd="%s"' % os.getcwd().replace('\\', '/')]
|
||||
openscad.run_list(options.list() + target_def + cwd_def + ["-D$pose=1", "-D$explode=%d" % explode, colour_scheme, "--projection=p", "--imgsize=4096,4096", "--autocenter", "--viewall", "-d", dname, "-o", tmp_name, png_maker_name]);
|
||||
times.add_time(png_name, t)
|
||||
do_cmd(["magick", tmp_name, "-trim", "-resize", "1004x1004", "-bordercolor", background, "-border", "10", tmp_name])
|
||||
update_image(tmp_name, png_name)
|
||||
@@ -202,193 +231,217 @@ def views(target, do_assemblies = None):
|
||||
if module == 'main_assembly':
|
||||
main_blurb = blurb.scrape_module_blurb(lines[:line_no])
|
||||
line_no += 1
|
||||
times.print_times()
|
||||
#
|
||||
# Build the document
|
||||
#
|
||||
for print_mode in [True, False]:
|
||||
doc_name = top_dir + "readme.md"
|
||||
with open(doc_name, "wt") as doc_file:
|
||||
#
|
||||
# Title, description and picture
|
||||
#
|
||||
project = ' '.join(word[0].upper() + word[1:] for word in os.path.basename(os.getcwd()).split('_'))
|
||||
print('<a name="TOP"></a>\n# %s' % project, file = doc_file)
|
||||
main_file = bom.find_scad_file('main_assembly')
|
||||
if not main_file:
|
||||
raise Exception("can't find source for main_assembly")
|
||||
text = blurb.scrape_blurb(source_dir + '/' + main_file)
|
||||
blurbs = blurb.split_blurb(text)
|
||||
if len(text):
|
||||
print(blurbs[0], file = doc_file)
|
||||
else:
|
||||
if print_mode:
|
||||
print(Fore.MAGENTA + "Missing project description" + Fore.WHITE)
|
||||
#
|
||||
# Only add the image if the first blurb section doesn't contain one.
|
||||
#
|
||||
if not re.search(r'\!\[.*\]\(.*\)', blurbs[0], re.MULTILINE):
|
||||
print('\n' % flat_bom[-1]["name"].replace('_assembly', '_assembled'), file = doc_file)
|
||||
eop(print_mode, doc_file, first = True)
|
||||
#
|
||||
# Build TOC
|
||||
#
|
||||
print('## Table of Contents', file = doc_file)
|
||||
print('1. [Parts list](#Parts_list)', file = doc_file)
|
||||
for ass in flat_bom:
|
||||
name = ass["name"]
|
||||
cap_name = titalise(name)
|
||||
print('1. [%s](#%s)' % (cap_name, name), file = doc_file)
|
||||
print(file = doc_file)
|
||||
if len(blurbs) > 1:
|
||||
print(blurbs[1], file = doc_file)
|
||||
eop(print_mode, doc_file)
|
||||
#
|
||||
# Global BOM
|
||||
#
|
||||
print('<a name="Parts_list"></a>\n## Parts list', file = doc_file)
|
||||
types = ["vitamins", "printed", "routed"]
|
||||
headings = {"vitamins" : "vitamins", "printed" : "3D printed parts", "routed" : "CNC routed parts"}
|
||||
things = {}
|
||||
doc_name = top_dir + "readme.md"
|
||||
with open(doc_name, "wt") as doc_file:
|
||||
#
|
||||
# Title, description and picture
|
||||
#
|
||||
project = ' '.join(word[0].upper() + word[1:] for word in os.path.basename(os.getcwd()).split('_'))
|
||||
print('<a name="TOP"></a>', file = doc_file)
|
||||
print('# %s' % project, file = doc_file)
|
||||
main_file = bom.find_scad_file('main_assembly')
|
||||
if not main_file:
|
||||
raise Exception("can't find source for main_assembly")
|
||||
text = blurb.scrape_blurb(source_dir + '/' + main_file)
|
||||
blurbs = blurb.split_blurb(text)
|
||||
if len(text):
|
||||
print(blurbs[0], file = doc_file)
|
||||
else:
|
||||
print(Fore.MAGENTA + "Missing project description" + Fore.WHITE)
|
||||
#
|
||||
# Only add the image if the first blurb section doesn't contain one.
|
||||
#
|
||||
if not re.search(r'\!\[.*\]\(.*\)', blurbs[0], re.MULTILINE):
|
||||
print('\n' % flat_bom[-1]["name"].replace('_assembly', '_assembled'), file = doc_file)
|
||||
eop(doc_file, first = True)
|
||||
#
|
||||
# Build TOC
|
||||
#
|
||||
print('## Table of Contents', file = doc_file)
|
||||
print('1. [Parts list](#Parts_list)', file = doc_file)
|
||||
for ass in flat_bom:
|
||||
name = ass["name"]
|
||||
cap_name = titalise(name)
|
||||
print('1. [%s](#%s)' % (cap_name, name), file = doc_file)
|
||||
print(file = doc_file)
|
||||
if len(blurbs) > 1:
|
||||
print(blurbs[1], file = doc_file)
|
||||
eop(doc_file)
|
||||
#
|
||||
# Global BOM
|
||||
#
|
||||
global_bom = [merged(ass) for ass in flat_bom if not ass['ngb']]
|
||||
print('<a name="Parts_list"></a>\n## Parts list', file = doc_file)
|
||||
headings = {"vitamins" : "vitamins", "printed" : "3D printed parts", "routed" : "CNC routed parts"}
|
||||
things = {}
|
||||
for t in types:
|
||||
things[t] = {}
|
||||
for ass in flat_bom:
|
||||
for t in types:
|
||||
things[t] = {}
|
||||
for ass in flat_bom:
|
||||
for t in types:
|
||||
for thing in ass[t]:
|
||||
if thing in things[t]:
|
||||
things[t][thing] += ass[t][thing]["count"]
|
||||
else:
|
||||
things[t][thing] = ass[t][thing]["count"]
|
||||
for ass in flat_bom:
|
||||
name = titalise(ass["name"][:-9]).replace(' ',' ')
|
||||
print('| <span style="writing-mode: vertical-rl; text-orientation: mixed;">%s</span> ' % name, file = doc_file, end = '')
|
||||
print('| <span style="writing-mode: vertical-rl; text-orientation: mixed;">TOTALS</span> | |', file = doc_file)
|
||||
for thing in ass[t]:
|
||||
if thing in things[t]:
|
||||
things[t][thing] += ass[t][thing]["count"]
|
||||
else:
|
||||
things[t][thing] = ass[t][thing]["count"]
|
||||
for ass in global_bom:
|
||||
name = titalise(ass["name"][:-9]).replace(' ',' ')
|
||||
if ass["count"] > 1:
|
||||
name = "%d x %s" % (ass["count"], name)
|
||||
print('| <span style="writing-mode: vertical-rl; text-orientation: mixed;">%s</span> ' % name, file = doc_file, end = '')
|
||||
print('| <span style="writing-mode: vertical-rl; text-orientation: mixed;">TOTALS</span> | |', file = doc_file)
|
||||
print(('|---:' * len(global_bom) + '|---:|:---|'), file = doc_file)
|
||||
|
||||
print(('|---:' * len(flat_bom) + '|---:|:---|'), file = doc_file)
|
||||
|
||||
for t in types:
|
||||
if things[t]:
|
||||
totals = {}
|
||||
heading = headings[t][0:1].upper() + headings[t][1:]
|
||||
print(('| ' * len(flat_bom) + '| | **%s** |') % heading, file = doc_file)
|
||||
for thing in sorted(things[t], key = lambda s: s.split(":")[-1]):
|
||||
for ass in flat_bom:
|
||||
count = ass[t][thing]["count"] if thing in ass[t] else 0
|
||||
print('| %s ' % pad(count if count else '.', 2, 1), file = doc_file, end = '')
|
||||
name = ass["name"]
|
||||
if name in totals:
|
||||
totals[name] += count
|
||||
else:
|
||||
totals[name] = count
|
||||
print('| %s | %s |' % (pad(things[t][thing], 2, 1), pad(thing.split(":")[-1], 2)), file = doc_file)
|
||||
|
||||
grand_total = 0
|
||||
for ass in flat_bom:
|
||||
for t in types:
|
||||
if things[t]:
|
||||
totals = {}
|
||||
grand_total2 = 0
|
||||
heading = headings[t][0].upper() + headings[t][1:]
|
||||
print(('| ' * len(global_bom) + '| | **%s** |') % heading, file = doc_file)
|
||||
for thing in sorted(things[t], key = lambda s: s.split(":")[-1]):
|
||||
for ass in global_bom:
|
||||
count = ass[t][thing]["count"] if thing in ass[t] else 0
|
||||
print('| %s ' % pad(count if count else '.', 2, 1), file = doc_file, end = '')
|
||||
name = ass["name"]
|
||||
total = totals[name] if name in totals else 0
|
||||
print('| %s ' % pad(total if total else '.', 2, 1), file = doc_file, end = '')
|
||||
grand_total += total
|
||||
print("| %s | %s |" % (pad(grand_total, 2, 1), pad('Total %s count' % headings[t], 2)), file = doc_file)
|
||||
if name in totals:
|
||||
totals[name] += count
|
||||
else:
|
||||
totals[name] = count
|
||||
grand_total2 += count
|
||||
print('| %s | %s |' % (pad(things[t][thing], 2, 1), pad(thing.split(":")[-1], 2)), file = doc_file)
|
||||
|
||||
print(file = doc_file)
|
||||
if len(blurbs) > 2:
|
||||
print(blurbs[2], file = doc_file)
|
||||
eop(print_mode, doc_file)
|
||||
#
|
||||
# Assembly instructions
|
||||
#
|
||||
for ass in flat_bom:
|
||||
name = ass["name"]
|
||||
cap_name = titalise(name)
|
||||
|
||||
if ass["count"] > 1:
|
||||
print('<a name="%s"></a>\n## %d x %s' % (name, ass["count"], cap_name), file = doc_file)
|
||||
else:
|
||||
print('<a name="%s"></a>\n## %s' % (name, cap_name), file = doc_file)
|
||||
vitamins = ass["vitamins"]
|
||||
if vitamins:
|
||||
print("### Vitamins", file = doc_file)
|
||||
print("|Qty|Description|", file = doc_file)
|
||||
print("|---:|:----------|", file = doc_file)
|
||||
for v in sorted(vitamins, key = lambda s: s.split(":")[-1]):
|
||||
print("|%d|%s|" % (vitamins[v]["count"], v.split(":")[1]), file = doc_file)
|
||||
print("\n", file = doc_file)
|
||||
|
||||
printed = ass["printed"]
|
||||
if printed:
|
||||
print('### 3D Printed parts', file = doc_file)
|
||||
keys = sorted(list(printed.keys()))
|
||||
for i, p in enumerate(keys):
|
||||
print('%s %d x %s |' % ('\n|' if not (i % 3) else '', printed[p]["count"], p), file = doc_file, end = '')
|
||||
if (i % 3) == 2 or i == len(printed) - 1:
|
||||
n = (i % 3) + 1
|
||||
print('\n|%s' % ('---|' * n), file = doc_file)
|
||||
for j in range(n):
|
||||
part = keys[i - n + j + 1]
|
||||
print('|  %s' % (part, part.replace('.stl','.png'), '|\n' if j == j - 1 else ''), end = '', file = doc_file)
|
||||
print('\n', file = doc_file)
|
||||
print('\n', file = doc_file)
|
||||
|
||||
routed = ass["routed"]
|
||||
if routed:
|
||||
print("### CNC Routed parts", file = doc_file)
|
||||
keys = sorted(list(routed.keys()))
|
||||
for i, r in enumerate(keys):
|
||||
print('%s %d x %s |' % ('\n|' if not (i % 3) else '', routed[r]["count"], r), file = doc_file, end = '')
|
||||
if (i % 3) == 2 or i == len(routed) - 1:
|
||||
n = (i % 3) + 1
|
||||
print('\n|%s' % ('---|' * n), file = doc_file)
|
||||
for j in range(n):
|
||||
part = keys[i - n + j + 1]
|
||||
print('|  %s' % (part, part.replace('.dxf','.png'), '|\n' if j == j - 1 else ''), end = '', file = doc_file)
|
||||
print('\n', file = doc_file)
|
||||
print('\n', file = doc_file)
|
||||
|
||||
sub_assemblies = ass["assemblies"]
|
||||
if sub_assemblies:
|
||||
print("### Sub-assemblies", file = doc_file)
|
||||
keys = sorted(list(sub_assemblies.keys()))
|
||||
for i, a in enumerate(keys):
|
||||
print('%s %d x %s |' % ('\n|' if not (i % 3) else '', sub_assemblies[a], a), file = doc_file, end = '')
|
||||
if (i % 3) == 2 or i == len(keys) - 1:
|
||||
n = (i % 3) + 1
|
||||
print('\n|%s' % ('---|' * n), file = doc_file)
|
||||
for j in range(n):
|
||||
a = keys[i - n + j + 1].replace('_assembly', '_assembled')
|
||||
print('|  %s' % (a, a + '_tn.png', '|\n' if j == j - 1 else ''), end = '', file = doc_file)
|
||||
print('\n', file = doc_file)
|
||||
print('\n', file = doc_file)
|
||||
|
||||
small = not ass["big"]
|
||||
suffix = '_tn.png' if small else '.png'
|
||||
print('### Assembly instructions', file = doc_file)
|
||||
print('\n' % (name, name + suffix), file = doc_file)
|
||||
|
||||
if "blurb" in ass and ass["blurb"]:
|
||||
print(ass["blurb"], file = doc_file)
|
||||
else:
|
||||
if print_mode:
|
||||
print(Fore.MAGENTA + "Missing instructions for %s" % name, Fore.WHITE)
|
||||
|
||||
name = name.replace('_assembly', '_assembled')
|
||||
print('\n' % (name, name + suffix), file = doc_file)
|
||||
eop(print_mode, doc_file, last = ass == flat_bom[-1] and not main_blurb)
|
||||
#
|
||||
# If main module is suppressed print any blurb here
|
||||
#
|
||||
if main_blurb:
|
||||
print(main_blurb, file = doc_file)
|
||||
eop(print_mode, doc_file, last = True)
|
||||
grand_total = 0
|
||||
for ass in global_bom:
|
||||
name = ass["name"]
|
||||
total = totals[name] if name in totals else 0
|
||||
print('| %s ' % pad(total if total else '.', 2, 1), file = doc_file, end = '')
|
||||
grand_total += total
|
||||
print("| %s | %s |" % (pad(grand_total, 2, 1), pad('Total %s count' % headings[t], 2)), file = doc_file)
|
||||
assert grand_total == grand_total2
|
||||
print(file = doc_file)
|
||||
if len(blurbs) > 2:
|
||||
print(blurbs[2], file = doc_file)
|
||||
eop(doc_file)
|
||||
#
|
||||
# Convert to HTML
|
||||
# Assembly instructions
|
||||
#
|
||||
html_name = "printme.html" if print_mode else "readme.html"
|
||||
with open(top_dir + html_name, "wt") as html_file:
|
||||
do_cmd(("python -m markdown -x tables -x sane_lists " + doc_name).split(), html_file)
|
||||
for ass in flat_bom:
|
||||
name = ass["name"]
|
||||
cap_name = titalise(name)
|
||||
|
||||
print('<a name="%s"></a>' % name, file = doc_file)
|
||||
if ass["count"] > 1:
|
||||
print('## %d x %s' % (ass["count"], cap_name), file = doc_file)
|
||||
else:
|
||||
print('## %s' % cap_name, file = doc_file)
|
||||
vitamins = ass["vitamins"]
|
||||
if vitamins:
|
||||
print("### Vitamins", file = doc_file)
|
||||
print("|Qty|Description|", file = doc_file)
|
||||
print("|---:|:----------|", file = doc_file)
|
||||
for v in sorted(vitamins, key = lambda s: s.split(":")[-1]):
|
||||
print("|%d|%s|" % (vitamins[v]["count"], v.split(":")[1]), file = doc_file)
|
||||
print("\n", file = doc_file)
|
||||
|
||||
printed = ass["printed"]
|
||||
if printed:
|
||||
print('### 3D Printed parts', file = doc_file)
|
||||
keys = sorted(list(printed.keys()))
|
||||
for i, p in enumerate(keys):
|
||||
print('%s %d x %s |' % ('\n|' if not (i % 3) else '', printed[p]["count"], p), file = doc_file, end = '')
|
||||
if (i % 3) == 2 or i == len(printed) - 1:
|
||||
n = (i % 3) + 1
|
||||
print('\n|%s' % ('---|' * n), file = doc_file)
|
||||
for j in range(n):
|
||||
part = keys[i - n + j + 1]
|
||||
print('|  %s' % (part, part.replace('.stl','.png'), '|\n' if j == j - 1 else ''), end = '', file = doc_file)
|
||||
print('\n', file = doc_file)
|
||||
print('\n', file = doc_file)
|
||||
|
||||
routed = ass["routed"]
|
||||
if routed:
|
||||
print("### CNC Routed parts", file = doc_file)
|
||||
keys = sorted(list(routed.keys()))
|
||||
for i, r in enumerate(keys):
|
||||
print('%s %d x %s |' % ('\n|' if not (i % 3) else '', routed[r]["count"], r), file = doc_file, end = '')
|
||||
if (i % 3) == 2 or i == len(routed) - 1:
|
||||
n = (i % 3) + 1
|
||||
print('\n|%s' % ('---|' * n), file = doc_file)
|
||||
for j in range(n):
|
||||
part = keys[i - n + j + 1]
|
||||
print('|  %s' % (part, part.replace('.dxf','.png'), '|\n' if j == j - 1 else ''), end = '', file = doc_file)
|
||||
print('\n', file = doc_file)
|
||||
print('\n', file = doc_file)
|
||||
|
||||
sub_assemblies = ass["assemblies"]
|
||||
if sub_assemblies:
|
||||
print("### Sub-assemblies", file = doc_file)
|
||||
keys = sorted(list(sub_assemblies.keys()))
|
||||
for i, a in enumerate(keys):
|
||||
print('%s %d x %s |' % ('\n|' if not (i % 3) else '', sub_assemblies[a], a), file = doc_file, end = '')
|
||||
if (i % 3) == 2 or i == len(keys) - 1:
|
||||
n = (i % 3) + 1
|
||||
print('\n|%s' % ('---|' * n), file = doc_file)
|
||||
for j in range(n):
|
||||
a = keys[i - n + j + 1].replace('_assembly', '_assembled')
|
||||
print('|  %s' % (a, a + '_tn.png', '|\n' if j == j - 1 else ''), end = '', file = doc_file)
|
||||
print('\n', file = doc_file)
|
||||
print('\n', file = doc_file)
|
||||
|
||||
small = not ass["big"]
|
||||
suffix = '_tn.png' if small else '.png'
|
||||
print('### Assembly instructions', file = doc_file)
|
||||
print('\n' % (name, name + suffix), file = doc_file)
|
||||
|
||||
if "blurb" in ass and ass["blurb"]:
|
||||
print(ass["blurb"], file = doc_file)
|
||||
else:
|
||||
print(Fore.MAGENTA + "Missing instructions for %s" % name, Fore.WHITE)
|
||||
|
||||
name = name.replace('_assembly', '_assembled')
|
||||
print('\n' % (name, name + suffix), file = doc_file)
|
||||
eop(doc_file, last = ass == flat_bom[-1] and not main_blurb)
|
||||
#
|
||||
# If main module is suppressed print any blurb here
|
||||
#
|
||||
if main_blurb:
|
||||
print(main_blurb, file = doc_file)
|
||||
eop(doc_file, last = True)
|
||||
#
|
||||
# Convert to HTML
|
||||
#
|
||||
html_name = top_dir + 'readme.html'
|
||||
t = time.time()
|
||||
with open(html_name, "wt") as html_file:
|
||||
do_cmd(("python -m markdown -x tables -x sane_lists " + doc_name).split(), html_file)
|
||||
times.add_time(html_name, t)
|
||||
times.print_times(pngs + [html_name])
|
||||
#
|
||||
# Make the printme.html by replacing empty spans that invisbly mark the page breaks by page break divs.
|
||||
#
|
||||
with open(html_name, 'rt') as src:
|
||||
lines = src.readlines()
|
||||
|
||||
i = 0
|
||||
with open(top_dir + 'printme.html', 'wt') as dst:
|
||||
while i < len(lines):
|
||||
line = lines[i]
|
||||
if line.startswith('<p><span></span>'): # Empty span used to mark page breaks
|
||||
i += 1
|
||||
if lines[i].startswith('<a href="#TOP">Top</a>'): # The first page break won't have one
|
||||
i += 1
|
||||
if i < len(lines) and lines[i] == '<hr />\n': # The last page break doesn't have one
|
||||
dst.write('<div style="page-break-after: always;"></div>\n')
|
||||
i += 1
|
||||
else:
|
||||
dst.write(line)
|
||||
i += 1
|
||||
#
|
||||
# Spell check
|
||||
#
|
||||
do_cmd('codespell -L od readme.md'.split())
|
||||
do_cmd(('codespell -L od ' + top_dir + 'readme.md').split())
|
||||
#
|
||||
# List the ones we didn't find
|
||||
#
|
||||
|
@@ -30,7 +30,6 @@ sheet = PMMA3;
|
||||
height = 10;
|
||||
|
||||
insert = screw_insert(screw);
|
||||
washer = screw_washer(screw);
|
||||
|
||||
module widget(thickness) {
|
||||
vitamin(str("widget(", thickness, "): Rivit like thing for ", thickness, "mm sheets"));
|
||||
@@ -44,31 +43,29 @@ module widget(thickness) {
|
||||
}
|
||||
}
|
||||
|
||||
module widgit_stl() {
|
||||
stl("widget");
|
||||
module widget_stl() {
|
||||
stl("widget")
|
||||
union() {
|
||||
rounded_rectangle([30, 30, 3], 2);
|
||||
|
||||
union() {
|
||||
rounded_rectangle([30, 30, 3], 2);
|
||||
|
||||
render() insert_boss(insert, height, 2.2);
|
||||
}
|
||||
render() insert_boss(insert, height, 2.2);
|
||||
}
|
||||
}
|
||||
|
||||
module widgit_dxf() {
|
||||
dxf("widget");
|
||||
module widget_dxf() {
|
||||
dxf("widget")
|
||||
difference() {
|
||||
sheet_2D(sheet, 20, 20, 1);
|
||||
|
||||
difference() {
|
||||
sheet_2D(sheet, 20, 20, 1);
|
||||
|
||||
drill(screw_clearance_radius(screw), 0);
|
||||
}
|
||||
drill(screw_clearance_radius(screw), 0);
|
||||
}
|
||||
}
|
||||
|
||||
//! * Push the insert into the base with a soldering iron heated to 200°C
|
||||
module widgit_base_assembly()
|
||||
assembly("widgit_base") {
|
||||
module widget_base_assembly()
|
||||
assembly("widget_base") {
|
||||
stl_colour(pp1_colour)
|
||||
widgit_stl();
|
||||
widget_stl();
|
||||
|
||||
translate_z(height)
|
||||
insert(insert);
|
||||
@@ -81,18 +78,18 @@ assembly("widget_top") {
|
||||
widget(sheet_thickness(sheet));
|
||||
|
||||
render_2D_sheet(sheet) // Must be last because it is transparent
|
||||
widgit_dxf();
|
||||
widget_dxf();
|
||||
}
|
||||
|
||||
//! * Screw the two assemblies together
|
||||
module widgit_assembly()
|
||||
assembly("wigdit") {
|
||||
module widget_assembly()
|
||||
assembly("widget") {
|
||||
|
||||
widgit_base_assembly(); // Note this is not exloded because it is sub-assembly
|
||||
widget_base_assembly(); // Note this is not exloded because it is sub-assembly
|
||||
|
||||
translate_z(height) {
|
||||
translate_z(sheet_thickness(sheet))
|
||||
screw_and_washer(screw, screw_longer_than(sheet_thickness(sheet) + 2 * washer_thickness(washer) + 3), true);
|
||||
screw_and_washer(screw, screw_length(screw, sheet_thickness(sheet) + 3, 2, longer = true), true);
|
||||
|
||||
explode(5)
|
||||
translate_z(sheet_thickness(sheet) / 2 + eps)
|
||||
@@ -101,7 +98,7 @@ assembly("wigdit") {
|
||||
}
|
||||
|
||||
module boms() {
|
||||
widgit_assembly();
|
||||
widget_assembly();
|
||||
}
|
||||
|
||||
boms();
|
||||
|
@@ -21,8 +21,10 @@ include <../vitamins/pcbs.scad>
|
||||
|
||||
use <../utils/layout.scad>
|
||||
|
||||
function spacing(p) = let(w = pcb_width(p)) w < 22 ? w + 3 : w + 10;
|
||||
|
||||
module pcbs() {
|
||||
layout([for(p = pcbs) pcb_width(p)], 10)
|
||||
layout([for(p = pcbs) spacing(p)], 0)
|
||||
translate([0, pcb_length(pcbs[$i]) / 2])
|
||||
rotate(90)
|
||||
pcb_assembly(pcbs[$i], 5 + $i, 3);
|
||||
@@ -31,6 +33,10 @@ module pcbs() {
|
||||
layout([for(p = perfboards) pcb_length(p)], 10)
|
||||
translate([0, -pcb_width(perfboards[$i]) / 2])
|
||||
pcb_assembly(perfboards[$i], 5 + $i, 3);
|
||||
|
||||
for(p = pcbs_not_shown)
|
||||
hidden()
|
||||
pcb(p);
|
||||
}
|
||||
if($preview)
|
||||
pcbs();
|
||||
|
@@ -24,16 +24,13 @@ include <../vitamins/blowers.scad>
|
||||
module blowers()
|
||||
layout([for(b = blowers) blower_width(b)], 10, true) let(b = blowers[$i]){
|
||||
screw = blower_screw(b);
|
||||
washer = screw_washer(screw);
|
||||
h = blower_lug(b);
|
||||
|
||||
blower(b);
|
||||
|
||||
blower_hole_positions(b)
|
||||
translate_z(h)
|
||||
screw_and_washer(screw, screw_longer_than(h + washer_thickness(washer) + 5));
|
||||
|
||||
|
||||
screw_and_washer(screw, screw_length(screw, h + 5, 1, longer = true));
|
||||
}
|
||||
|
||||
if($preview)
|
||||
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 77 KiB |
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 102 KiB |
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 153 KiB |
BIN
tests/png/printed_pulleys.png
Normal file
After Width: | Height: | Size: 116 KiB |
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 154 KiB |
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 148 KiB |
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 43 KiB |
45
tests/printed_pulleys.scad
Normal file
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// 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>
|
||||
include <../vitamins/pulleys.scad>
|
||||
include <../printed/printed_pulleys.scad>
|
||||
use <../utils/layout.scad>
|
||||
|
||||
|
||||
module printed_pulley_test(show_metal = false) {
|
||||
layout([for (p = pulleys) pulley_flange_dia(p)]) let(p = pulleys[$i]) {
|
||||
rotate(-145)
|
||||
if($preview)
|
||||
printed_pulley_assembly(p);
|
||||
else
|
||||
printed_pulley(p);
|
||||
|
||||
if(show_metal)
|
||||
not_on_bom()
|
||||
translate([0, 20])
|
||||
rotate(-145)
|
||||
pulley_assembly(p);
|
||||
}
|
||||
}
|
||||
|
||||
if($preview)
|
||||
printed_pulley_test(true);
|
||||
else
|
||||
printed_pulley_test();
|
@@ -23,7 +23,7 @@ include <../vitamins/pulleys.scad>
|
||||
|
||||
module pulleys()
|
||||
layout([for(p = pulleys) pulley_flange_dia(p)])
|
||||
rotate(-45)
|
||||
rotate(-145)
|
||||
pulley_assembly(pulleys[$i]);
|
||||
|
||||
if($preview)
|
||||
|
@@ -26,15 +26,16 @@ sheet = 3;
|
||||
pos = 1; //[-1 : 0.1 : 1]
|
||||
|
||||
module rails()
|
||||
layout([for(l = rails) carriage_width(rail_carriage(l))], 20)
|
||||
layout([for(l = carriages) carriage_width(l)], 20)
|
||||
rotate(-90) {
|
||||
rail = rails[$i];
|
||||
carriage = carriages[$i];
|
||||
rail = carriage_rail(carriage);
|
||||
length = 200;
|
||||
screw = rail_screw(rail);
|
||||
nut = screw_nut(screw);
|
||||
washer = screw_washer(screw);
|
||||
|
||||
rail_assembly(rail, length, pos * rail_travel(rail, length) / 2, $i<2 ? grey(20) : "green", $i<2 ? grey(20) : "red");
|
||||
rail_assembly(carriage, length, pos * carriage_travel(carriage, length) / 2, $i<2 ? grey(20) : "green", $i<2 ? grey(20) : "red");
|
||||
|
||||
rail_screws(rail, length, sheet + nut_thickness(nut, true) + washer_thickness(washer));
|
||||
|
||||
|
@@ -27,6 +27,9 @@ module tubes() {
|
||||
|
||||
translate([50, 10])
|
||||
tube(10, 8, 30);
|
||||
|
||||
translate([100, 10])
|
||||
rectangular_tube([10, 20, 30]);
|
||||
}
|
||||
|
||||
tubes();
|
||||
|
@@ -25,8 +25,15 @@
|
||||
//! parts are used.
|
||||
//! This heuristic isn't always correct, so the default can be overridden by setting the `big` parameter of `assembly` to `true` or `false`.
|
||||
//!
|
||||
//! Setting the `ngb` parameter of `assembly` to `true` removes its column from the global BOM and merges it parts into its parent assembly column of the global BOM.
|
||||
//! This is to prevent the global BOM page becoming too wide in large projects by having it include just the major assemblies.
|
||||
//!
|
||||
//! The example below shows how to define a vitamin and incorporate it into an assembly with sub-assemblies and make an exploded view.
|
||||
//! The resulting flat BOM is shown but heirachical BOMs are also generated for real projects.
|
||||
//!
|
||||
//! If the code to make an STL or DXF is made a child of the `stl()` or `dxf()` module then the STL or DXF will be used in the assembly views generated by `views.py` instead of generating
|
||||
//! it with code.
|
||||
//! This can speed up the generation of the build instructions greatly but isn't compatible with STLs that include support structures.
|
||||
//
|
||||
function bom_mode(n = 1) = $_bom >= n && (is_undef($on_bom) || $on_bom); //! Current BOM mode, 0 = none, 1 = printed and routed parts and assemblies, 2 includes vitamins as well
|
||||
function exploded() = is_undef($exploded_parent) ? $exploded : 0; //! Returns the value of `$exploded` if it is defined, else `0`
|
||||
@@ -84,9 +91,9 @@ module pose_vflip(exploded = undef) //! Pose an STL or assembly for render
|
||||
children();
|
||||
|
||||
|
||||
module assembly(name, big = undef) { //! Name an assembly that will appear on the BOM, there needs to a module named `<name>_assembly` to make it. `big` can force big or small assembly diagrams.
|
||||
module assembly(name, big = undef, ngb = false) { //! Name an assembly that will appear on the BOM, there needs to a module named `<name>_assembly` to make it. `big` can force big or small assembly diagrams.
|
||||
if(bom_mode()) {
|
||||
args = is_undef(big) ? "" : str("(big=", big, ")");
|
||||
args = is_undef(big) && !ngb ? "" : str("(big=", big, ", ngb=", ngb, ")");
|
||||
echo(str("~", name, "_assembly", args, "{"));
|
||||
}
|
||||
no_pose()
|
||||
@@ -108,19 +115,47 @@ module stl_colour(colour = pp1_colour, alpha = 1) { //! Colour an stl where it i
|
||||
}
|
||||
|
||||
module stl(name) { //! Name an stl that will appear on the BOM, there needs to a module named `<name>_stl` to make it
|
||||
if(bom_mode()) {
|
||||
if(bom_mode() && is_undef($in_stl)) {
|
||||
colour = is_undef($stl_colour) ? pp1_colour : $stl_colour;
|
||||
echo(str("~", name, ".stl(colour='", colour, "')"));
|
||||
}
|
||||
if($children)
|
||||
if(is_undef($pose))
|
||||
let($in_stl = true)
|
||||
children();
|
||||
else {
|
||||
path = is_undef($target) ? "/stls/" : str("/", $target, "/stls/");
|
||||
import(str($cwd, path, name, ".stl"));
|
||||
}
|
||||
}
|
||||
|
||||
module dxf(name) { //! Name a dxf that will appear on the BOM, there needs to a module named `<name>_dxf` to make it
|
||||
if(bom_mode()) {
|
||||
if(bom_mode() && is_undef($in_dxf)) {
|
||||
if(is_undef($dxf_colour))
|
||||
echo(str("~", name, ".dxf"));
|
||||
else
|
||||
echo(str("~", name, ".dxf(colour='", $dxf_colour, "')"));
|
||||
}
|
||||
if($children)
|
||||
if(is_undef($pose))
|
||||
let($in_dfx = true)
|
||||
children();
|
||||
else {
|
||||
path = is_undef($target) ? "/dxfs/" : str("/", $target, "/dxfs/");
|
||||
import(str($cwd, path, name, ".dxf"));
|
||||
}
|
||||
}
|
||||
|
||||
module use_stl(name) { //! Import an STL to make a build platter
|
||||
stl(name);
|
||||
path = is_undef($target) ? "/stls/" : str("/", $target, "/stls/");
|
||||
import(str($cwd, path, name, ".stl"));
|
||||
}
|
||||
|
||||
module use_dxf(name) { //! Import a DXF to make a build panel
|
||||
dxf(name);
|
||||
path = is_undef($target) ? "/dxfs/" : str("/", $target, "/dxfs/");
|
||||
import(str($cwd, path, name, ".dxf"));
|
||||
}
|
||||
|
||||
function value_string(value) = is_string(value) ? str("\"", value, "\"") : str(value); //! Convert `value` to a string or quote it if it is already a string
|
||||
@@ -130,7 +165,7 @@ function arg(value, default, name = "") = //! Create string for arg if not def
|
||||
: name ? str(", ", name, " = ", value_string(value))
|
||||
: str(", ", value_string(value));
|
||||
|
||||
module vitamin(description) { //! Describe a vitamin for the BOM entry and precede it with a module call that creates it, eg. "wigit(42): Type 42 widget"
|
||||
module vitamin(description) { //! Describe a vitamin for the BOM entry and precede it with a module call that creates it, eg. "widget(42): Widget size 42"
|
||||
if(bom_mode(2))
|
||||
echo(str("~", description, !is_undef($hidden) ? " - not shown" : ""));
|
||||
}
|
||||
|
@@ -25,15 +25,3 @@ include <../../global_defs.scad>
|
||||
// Global functions and modules
|
||||
//
|
||||
use <global.scad>
|
||||
|
||||
module use_stl(name) { //! Import an STL to make a build platter
|
||||
stl(name);
|
||||
path = is_undef($target) ? "../stls/" : str("../", $target, "/stls/");
|
||||
import(str(path, name, ".stl"));
|
||||
}
|
||||
|
||||
module use_dxf(name) { //! Import a DXF to make a build panel
|
||||
dxf(name);
|
||||
path = is_undef($target) ? "../dxfs/" : str("../", $target, "/dxfs/");
|
||||
import(str(path, name, ".dxf"));
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@
|
||||
//! 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, 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(h, r, center = true, truncate = true, chamfer = 0, chamfer_both_ends = true, 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) {
|
||||
er = layer_height / 2 - eps; // Extrustion edge radius
|
||||
R = plus ? r + er : r; // Corrected radius
|
||||
@@ -52,7 +52,7 @@ module teardrop(h, r, center = true, truncate = true, chamfer = 0, plus = false)
|
||||
extrude_if(h, center)
|
||||
teardrop_2d(r, truncate);
|
||||
|
||||
teardrop_chamfer(h, center, chamfer) {
|
||||
teardrop_chamfer(h, center, chamfer, chamfer_both_ends) {
|
||||
linear_extrude(eps, center = true)
|
||||
teardrop_2d(r + chamfer / 2, truncate);
|
||||
|
||||
@@ -62,7 +62,7 @@ module teardrop(h, r, center = true, truncate = true, chamfer = 0, plus = false)
|
||||
}
|
||||
}
|
||||
|
||||
module semi_teardrop(h, r, d = undef, center = true, chamfer = 0, plus = false) { //! A semi teardrop in the positive Y domain
|
||||
module semi_teardrop(h, r, d = undef, center = true, chamfer = 0, chamfer_both_ends = true, plus = false) { //! A semi teardrop in the positive Y domain
|
||||
module semi_teardrop_2d(r, d)
|
||||
intersection() {
|
||||
R = is_undef(d) ? r : d / 2;
|
||||
@@ -77,7 +77,7 @@ module semi_teardrop(h, r, d = undef, center = true, chamfer = 0, plus = false)
|
||||
extrude_if(h, center)
|
||||
semi_teardrop_2d(r, d);
|
||||
|
||||
teardrop_chamfer(h, center, chamfer) {
|
||||
teardrop_chamfer(h, center, chamfer, chamfer_both_ends) {
|
||||
linear_extrude(eps, center = true)
|
||||
semi_teardrop_2d(r + chamfer / 2, d);
|
||||
|
||||
@@ -87,10 +87,10 @@ module semi_teardrop(h, r, d = undef, center = true, chamfer = 0, plus = false)
|
||||
}
|
||||
}
|
||||
|
||||
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 teardrop_plus(h, r, center = true, truncate = true, chamfer = 0, chamfer_both_ends = true) //! Slightly elongated teardrop to allow for the 3D printing staircase effect
|
||||
teardrop(h, r, center, truncate, chamfer, chamfer_both_ends, plus = true);
|
||||
|
||||
module tearslot(h, r, w, center = true, chamfer = 0, plus = false) { //! A horizontal slot that doesn't need support material
|
||||
module tearslot(h, r, w, center = true, chamfer = 0, chamfer_both_ends = true, plus = false) { //! A horizontal slot that doesn't need support material
|
||||
module tearslot_2d(r, w)
|
||||
hull()
|
||||
for(x = [-1, 1])
|
||||
@@ -99,7 +99,7 @@ module tearslot(h, r, w, center = true, chamfer = 0, plus = false) { //! A horiz
|
||||
extrude_if(h, center)
|
||||
tearslot_2d(r, w);
|
||||
|
||||
teardrop_chamfer(h, center, chamfer) {
|
||||
teardrop_chamfer(h, center, chamfer, chamfer_both_ends) {
|
||||
linear_extrude(eps, center = true)
|
||||
tearslot_2d(r + chamfer / 2, w);
|
||||
|
||||
@@ -109,7 +109,7 @@ module tearslot(h, r, w, center = true, chamfer = 0, plus = false) { //! A horiz
|
||||
}
|
||||
}
|
||||
|
||||
module vertical_tearslot(h, r, l, center = true, chamfer = 0, plus = false) { //! A vertical slot that doesn't need support material
|
||||
module vertical_tearslot(h, r, l, center = true, chamfer = 0, chamfer_both_ends = true, plus = false) { //! A vertical slot that doesn't need support material
|
||||
module vertical_tearslot_2d(r, l)
|
||||
hull()
|
||||
for(y = [-1, 1])
|
||||
@@ -119,7 +119,7 @@ module vertical_tearslot(h, r, l, center = true, chamfer = 0, plus = false) { //
|
||||
extrude_if(h, center)
|
||||
vertical_tearslot_2d(r, l);
|
||||
|
||||
teardrop_chamfer(h, center, chamfer) {
|
||||
teardrop_chamfer(h, center, chamfer, chamfer_both_ends) {
|
||||
linear_extrude(eps, center = true)
|
||||
vertical_tearslot_2d(r + chamfer / 2, l);
|
||||
|
||||
@@ -129,10 +129,10 @@ module vertical_tearslot(h, r, l, center = true, chamfer = 0, plus = false) { //
|
||||
}
|
||||
}
|
||||
|
||||
module teardrop_chamfer(h, center, chamfer) { //! Helper module for adding chamfer to a teardrop
|
||||
module teardrop_chamfer(h, center, chamfer, chamfer_both_ends) { //! Helper module for adding chamfer to a teardrop
|
||||
if(h && chamfer)
|
||||
translate_z(center ? 0 : h / 2)
|
||||
for(m = [0, 1])
|
||||
for(m = chamfer_both_ends ? [0, 1] : [1])
|
||||
mirror([0, 0, m])
|
||||
translate_z((h - eps ) / 2)
|
||||
hull()
|
||||
|
@@ -18,13 +18,14 @@
|
||||
//
|
||||
|
||||
//
|
||||
//! Draw a polygon with rounded corners. Each element of the vector is the XY coordinate and a radius. Radius can be negative for a concave corner.
|
||||
//! Draw a polygon with rounded corners. Each element of the vector is the XY coordinate and a radius in clockwise order.
|
||||
//! Radius can be negative for a concave corner.
|
||||
//!
|
||||
//! Because the tangents need to be calculated to find the length these can be calculated separately and re-used when drawing to save calculating them twice.
|
||||
//
|
||||
include <../utils/core/core.scad>
|
||||
|
||||
function circle_tangent(p1, p2) =
|
||||
function circle_tangent(p1, p2) = //! Compute the clockwise tangent between two circles represented as [x,y,r]
|
||||
let(
|
||||
r1 = p1[2],
|
||||
r2 = p2[2],
|
||||
@@ -32,11 +33,8 @@ function circle_tangent(p1, p2) =
|
||||
dy = p2.y - p1.y,
|
||||
d = sqrt(dx * dx + dy * dy),
|
||||
theta = atan2(dy, dx) + acos((r1 - r2) / d),
|
||||
xa = p1.x +(cos(theta) * r1),
|
||||
ya = p1.y +(sin(theta) * r1),
|
||||
xb = p2.x +(cos(theta) * r2),
|
||||
yb = p2.y +(sin(theta) * r2)
|
||||
)[ [xa, ya], [xb, yb] ];
|
||||
v = [cos(theta), sin(theta)]
|
||||
)[ p1 + r1 * v, p2 + r2 * v ];
|
||||
|
||||
function rounded_polygon_tangents(points) = //! Compute the straight sections needed to draw and to compute the lengths
|
||||
let(len = len(points))
|
||||
|
@@ -21,7 +21,7 @@
|
||||
//! Draw a 3D right triangle with rounded edges. Intended to be embedded in other parts. Can be optionally offset by the filleted amount.
|
||||
//
|
||||
include <../utils/core/core.scad>
|
||||
include <NopSCADlib/utils/core/rounded_rectangle.scad>
|
||||
include <..//utils/core/rounded_rectangle.scad>
|
||||
|
||||
module rounded_right_triangle(x, y, z, fillet, center = true, offset = false) { //! Draw a 3D right triangle with rounded edges.
|
||||
fillet = max(fillet, eps);
|
||||
@@ -43,4 +43,3 @@ module rounded_right_triangle(x, y, z, fillet, center = true, offset = false) {
|
||||
rounded_rectangle([size.z, 2 * fillet, eps], fillet - eps, center = false, xy_center = false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -68,3 +68,11 @@ module woven_tube(or, ir, h, center= true, colour = grey(30), colour2, warp = 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module rectangular_tube(size, center = true, thickness = 1, fillet = 0.5) { //! Create a retangular tube with filleted corners
|
||||
extrude_if(size.z, center = center)
|
||||
difference() {
|
||||
rounded_square([size.x, size.y], fillet);
|
||||
rounded_square([size.x - 2 * thickness, size.y - 2 * thickness], fillet);
|
||||
}
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@
|
||||
// h h s t t
|
||||
RB5015 = ["RB5015", "Blower Runda RB5015", 51.3, 51, 15, 31.5, M4_cap_screw, 26, [27.3, 25.4], 4.5, [[4.3, 45.4], [47.3,7.4]], 20, 14, 1.5, 1.3, 1.2, 15];
|
||||
PE4020 = ["PE4020", "Blower Pengda Technology 4020", 40, 40, 20, 27.5, M3_cap_screw, 22, [21.5, 20 ], 3.2, [[37,3],[3,37],[37,37]], 29.3, 17, 1.7, 1.2, 1.3, 13];
|
||||
BL40x10 =["BL40x10","Square radial 4010", 40, 40,9.5, 27, M2_cap_screw, 16, [24, 20 ], 2.4, [[2,2],[38,2],[2,38],[38,38]], 30 , 9.5, 1.5, 1.5, 1.1, 1.5];
|
||||
BL40x10 =["BL40x10","Square radial fan 4010", 40, 40,9.5, 27, M2_cap_screw, 16, [24, 20 ], 2.4, [[2,2],[38,2],[2,38],[38,38]], 30 , 9.5, 1.5, 1.5, 1.1, 1.5];
|
||||
|
||||
blowers = [BL40x10, PE4020, RB5015];
|
||||
|
||||
|
@@ -73,39 +73,54 @@ SSD1963_4p3 = ["SSD1963_4p3", "LCD display SSD1963 4.3\"", 105.5, 67.2, 3.4, SSD
|
||||
[[0, -34.5], [12, -31.5]],
|
||||
];
|
||||
|
||||
|
||||
/* Dimensions taken from:
|
||||
https://github.com/bigtreetech/BIGTREETECH-TFT35-V3.0/blob/master/Hardware/TFT35%20V3.0-SIZE-TOP.pdf
|
||||
and
|
||||
https://github.com/bigtreetech/BIGTREETECH-TFT35-V3.0/blob/master/Hardware/TFT35%20V3.0-SIZE-BOT.pdf
|
||||
*/
|
||||
|
||||
BigTreeTech_TFT35v3_0_PCB = ["", "",
|
||||
110, 55.77, 1.6, 0, 3, 0, "green", false,
|
||||
[ [-3.12, 3.17], [-3.12, -3.17], [3.12, -3.17], [3.12, 3.17] ],
|
||||
[
|
||||
[ 10, 7.5, 0, "-button_6mm" ],
|
||||
[ 9, 43, 0, "-buzzer", 5, 9 ],
|
||||
[ 9, 27, 0, "-potentiometer" ],
|
||||
[ 102,28.82, 0, "uSD", [26.5, 16, 3] ],
|
||||
[16.5, 5.9, 0, "2p54boxhdr", 5, 2 ],
|
||||
[36.5, 5.9, 0, "2p54boxhdr", 5, 2 ],
|
||||
[56.5, 5.9, 0, "2p54boxhdr", 5, 2 ],
|
||||
[82.5, 4, 0, "jst_xh", 5 ],
|
||||
[26.5, 52.8, 180, "jst_xh", 2 ],
|
||||
[39.5, 52.8, 180, "jst_xh", 3 ],
|
||||
[52.5, 52.8, 180, "jst_xh", 3 ],
|
||||
[65.5, 52.8, 180, "jst_xh", 3 ],
|
||||
[78.5, 52.8, 180, "jst_xh", 3 ],
|
||||
[94.5, 52.8, 180, "jst_xh", 5 ],
|
||||
[ 8, 43, 180, "usb_A" ],
|
||||
[ 97, 4, 0, "chip", 9, 3.5, 1, grey(20) ],
|
||||
// ESP-8266
|
||||
[ 23, 28, 90, "2p54socket", 4, 2 ],
|
||||
110, 55.77, 1.6, // size
|
||||
0, // corner radius
|
||||
3, // mounting hole diameter
|
||||
0, // pad around mounting hole
|
||||
"green", // color
|
||||
false, // true if parts should be separate BOM items
|
||||
[ // hole positions
|
||||
[-3.12, 3.17], [-3.12, -3.17], [3.12, -3.17], [3.12, 3.17]
|
||||
],
|
||||
[]
|
||||
[ // components
|
||||
[ 9, -( 8.46 + 17.45)/2, 0, "-buzzer", 5, 9 ],
|
||||
[ 9, -(23.76 + 34.94)/2, 0, "-potentiometer" ],
|
||||
[ (6.84 + 12.85)/2, -(45.73 + 51.73)/2, 0, "-button_6mm" ],
|
||||
[ 102, (15.57 + 42.07)/2, 0, "uSD", [26.5, 16, 3] ],
|
||||
[ 8, -( 6.76 + 18.76)/2, 180, "usb_A" ],
|
||||
[ 23, (23.32 + 33.64)/2, 90, "2p54socket", 4, 2 ], // ESP-8266
|
||||
|
||||
[ 16.5, 5.9, 0, "2p54boxhdr", 5, 2 ],
|
||||
[ 36.5, 5.9, 0, "2p54boxhdr", 5, 2 ],
|
||||
[ 56.5, 5.9, 0, "2p54boxhdr", 5, 2 ],
|
||||
[ 82.5, 4, 0, "jst_xh", 5 ],
|
||||
[ 26.5, 52.8, 180, "jst_xh", 2 ],
|
||||
[ 39.5, 52.8, 180, "jst_xh", 3 ],
|
||||
[ 52.5, 52.8, 180, "jst_xh", 3 ],
|
||||
[ 65.5, 52.8, 180, "jst_xh", 3 ],
|
||||
[ 78.5, 52.8, 180, "jst_xh", 3 ],
|
||||
[ 94.5, 52.8, 180, "jst_xh", 5 ],
|
||||
[ 97, 4, 0, "chip", 9, 3.5, 1, grey(20) ],
|
||||
],
|
||||
[] // accessories
|
||||
];
|
||||
|
||||
BigTreeTech_TFT35v3_0 = ["BigTreeTech_TFT35v3_0", "BigTreeTech TFT35 v3.0",
|
||||
84.5, 54.5, 4, BigTreeTech_TFT35v3_0_PCB,
|
||||
[-6, 0, 0], // pcb offset
|
||||
84.5, 54.5, 4, // size
|
||||
BigTreeTech_TFT35v3_0_PCB, // pcb
|
||||
[7 - (110 - 84.5)/2, 0, 0], // pcb offset from center
|
||||
[[-40, -26.5], [41.5, 26.5, 0.5]], // aperture
|
||||
[], // touch screen
|
||||
0, // thread length
|
||||
[], // clearance need for the ts ribbon
|
||||
[], // touch screen position and size
|
||||
0, // length that studs protrude from the PCB holes
|
||||
[], // keep out region for ribbon cable
|
||||
];
|
||||
|
||||
|
||||
|
@@ -151,10 +151,8 @@ function fan_screw_depth(type, full_depth = false) = fan_boss_d(type) || full_de
|
||||
|
||||
function fan_screw_length(type, thickness, full_depth = false) =
|
||||
let(depth = fan_screw_depth(type, full_depth),
|
||||
washers = depth == fan_depth(type) ? 2 : 1,
|
||||
washer = screw_washer(fan_screw(type)),
|
||||
nut = screw_nut(fan_screw(type)))
|
||||
screw_longer_than(thickness + depth + washer_thickness(washer) * washers + nut_thickness(nut, true)); //! Screw length required
|
||||
washers = depth == fan_depth(type) ? 2 : 1)
|
||||
screw_length(fan_screw(type), thickness + depth, washers, nyloc = true); //! Screw length required
|
||||
|
||||
module fan_assembly(type, thickness, include_fan = true, screw = false, full_depth = false) { //! Fan with its fasteners
|
||||
translate_z(-fan_depth(type) / 2) {
|
||||
|
@@ -31,7 +31,9 @@ gt_2p54 = ["gt_2p54", 2.54, 6.6, 10, 3, 6, 0.4, 6.4, 1, 1, 0.2, 2,
|
||||
gt_3p5 = ["gt_3p5", 3.5, 7.3, 8.5, 4, 5, 0.4, 4, 0, 1.35, 0.4, 1.8, 2, 2, 0, 0, 0];
|
||||
gt_5p08 = ["gt_5p08", 5.08, 7.9, 10, 5.0, 7, 0.0, 6.8, 1.45, 1.95, 0.5, 4.0, 5.4, 0.5, 0, 0, 0];
|
||||
gt_6p35 = ["gt_6p35", 6.35, 12.6, 17.4, 6.8, 12, 0.4, 11, 2, 2.7, 0.8, 3.4, 4.2, 2, 1.8, 1.1, 21.4];
|
||||
gt_5x11 = ["gt_5x11", 5, 8, 11, 5, 7, 0.4, 7, 1.5, 1.5, 1, 2.5, 6, 0, 0, 0, 0];
|
||||
gt_5x17 = ["gt_5x17", 5, 10, 17, 5, 11, 0.4, 9, 2, 1.5, 1, 3, 6, 0, 0, 0, 0];
|
||||
|
||||
green_terminals = [gt_2p54, gt_3p5, gt_5p08, gt_6p35];
|
||||
green_terminals = [gt_2p54, gt_3p5, gt_5p08, gt_6p35, gt_5x11, gt_5x17];
|
||||
|
||||
use <green_terminal.scad>
|
||||
|
@@ -34,15 +34,16 @@ hygrometer_hole_r = 21.3;
|
||||
slot_w = 5.5;
|
||||
|
||||
module hygrometer_hole(h = 0) { //! Drill the hole for a hygrometer
|
||||
round(cnc_bit_r) {
|
||||
intersection() {
|
||||
drill(hygrometer_hole_r, h);
|
||||
extrude_if(h)
|
||||
round(cnc_bit_r) {
|
||||
intersection() {
|
||||
drill(hygrometer_hole_r, 0);
|
||||
|
||||
rotate(30)
|
||||
square([slot_w + 2 * cnc_bit_r, 100], center = true);
|
||||
rotate(30)
|
||||
square([slot_w + 2 * cnc_bit_r, 100], center = true);
|
||||
}
|
||||
drill((od + 0.2) / 2, 0);
|
||||
}
|
||||
drill((od + 0.2) / 2, h);
|
||||
}
|
||||
}
|
||||
|
||||
function hygrometer_or() = flange_d / 2; //! The outside radius of a hygrometer
|
||||
@@ -54,13 +55,13 @@ module hygrometer() { //! Draw a hygrometer
|
||||
color(grey(30))
|
||||
rotate_extrude()
|
||||
polygon([
|
||||
[0, 0],
|
||||
[aperture_d / 2, 0],
|
||||
[aperture_d / 2, flange_t],
|
||||
[flange_d2 / 2, flange_t2],
|
||||
[flange_d / 2, flange_t],
|
||||
[flange_d / 2, 0],
|
||||
[od / 2, 0],
|
||||
[0, 0],
|
||||
[aperture_d / 2, 0],
|
||||
[aperture_d / 2, flange_t],
|
||||
[flange_d2 / 2, flange_t2],
|
||||
[flange_d / 2, flange_t],
|
||||
[flange_d / 2, 0],
|
||||
[od / 2, 0],
|
||||
[od / 2, -h],
|
||||
[0, -h]
|
||||
]);
|
||||
|
@@ -247,10 +247,7 @@ module iec_inserts(type) { //! Place the inserts
|
||||
|
||||
module iec_assembly(type, thickness) { //! Assembly with fasteners given panel thickness
|
||||
screw = iec_screw(type);
|
||||
washer = screw_washer(screw);
|
||||
nut = screw_nut(screw);
|
||||
insert = screw_insert(screw);
|
||||
screw_length = thickness ? screw_longer_than(iec_flange_t(type) + thickness + washer_thickness(washer) + nut_thickness(nut, true))
|
||||
screw_length = thickness ? screw_length(screw, iec_flange_t(type) + thickness, 1, nyloc = true)
|
||||
: insert_screw_length;
|
||||
|
||||
iec(type);
|
||||
@@ -262,6 +259,6 @@ module iec_assembly(type, thickness) { //! Assembly with fasteners given panel
|
||||
if(thickness)
|
||||
translate_z(-thickness)
|
||||
vflip()
|
||||
nut_and_washer(nut, true);
|
||||
nut_and_washer(screw_nut(screw), true);
|
||||
}
|
||||
}
|
||||
|
@@ -194,12 +194,14 @@ module jhead_hot_end_assembly(type, filament, naked = false) { //! Assembly with
|
||||
if(exploded())
|
||||
heater_components();
|
||||
else
|
||||
intersection() {
|
||||
heater_components();
|
||||
if(naked) // hide the wires when not exploded
|
||||
intersection() {
|
||||
heater_components();
|
||||
|
||||
if(naked)
|
||||
color("grey") cylinder(r = 12, h = 100, center = true);
|
||||
else
|
||||
cube(1, true); // hide the wires when not exploded
|
||||
}
|
||||
color("grey")
|
||||
cylinder(r = 12, h = 100, center = true);
|
||||
}
|
||||
else
|
||||
hidden() // hidden by the tape
|
||||
heater_components();
|
||||
}
|
||||
|
@@ -18,7 +18,11 @@
|
||||
//
|
||||
|
||||
//
|
||||
//! Used for limit switches.
|
||||
//! Used for limit switches. Currently only the button type is supported as the lever and roller types are less accurate.
|
||||
//!
|
||||
//! The switch is drawn with the button at the nominal operation point. This can be plus or minus `microswitch_op_tol(type)`.
|
||||
//!
|
||||
//! When the button is released it comes out by a maximum of `microswitch_fp_max(type)` from the nominal operating point.
|
||||
//
|
||||
include <../utils/core/core.scad>
|
||||
|
||||
@@ -32,11 +36,13 @@ function microswitch_hole_d(type) = type[6]; //! Screw hole diameter
|
||||
function microswitch_holes(type) = type[7]; //! Hole positions
|
||||
function microswitch_button_w(type) = type[8]; //! Button width
|
||||
function microswitch_button_t(type) = type[9]; //! Button thickness
|
||||
function microswitch_button_pos(type)= type[10]; //! Button position
|
||||
function microswitch_legs(type) = type[11]; //! Leg positions
|
||||
function microswitch_leg(type) = type[12]; //! Leg types
|
||||
function microswitch_body_clr(type) = type[13]; //! Body colour
|
||||
function microswitch_button_clr(type)= type[14]; //! Button colour
|
||||
function microswitch_button_pos(type)= type[10]; //! Button position at operating point
|
||||
function microswitch_op_tol(type) = type[11]; //! Operating position +/- tolerance
|
||||
function microswitch_fp_max(type) = type[12]; //! Free position maximum
|
||||
function microswitch_legs(type) = type[13]; //! Leg positions
|
||||
function microswitch_leg(type) = type[14]; //! Leg types
|
||||
function microswitch_body_clr(type) = type[15]; //! Body colour
|
||||
function microswitch_button_clr(type)= type[16]; //! Button colour
|
||||
|
||||
function microswitch_lower_extent(type) = let(leg = microswitch_leg(type)) min([for(pos = microswitch_legs(type)) pos.y - leg.y / 2]); //! How far legs extend downwards
|
||||
function microswitch_right_extent(type) = let(leg = microswitch_leg(type)) max([microswitch_length(type) / 2, for(pos = microswitch_legs(type)) pos.x + leg.x / 2]); //! How far legs extend right
|
||||
|
@@ -23,10 +23,19 @@
|
||||
small_leg = [0.9, 3.3, 0.4, 0];
|
||||
medium_leg = [0.5, 3.9, 3.2, 1.6, [0, -0.5]];
|
||||
large_leg = [11.4, 0.8, 6.3, 1.8, [1.7, 0]];
|
||||
|
||||
small_microswitch = ["small_microswitch", "DM1-00P-110-3", 5.8, 6.5, 12.8, 0, 2, [[-3.25, -1.65], [3.25, -1.65]], 2.9, 1.2, [-1.95, 3.75], [[-5.08, -4.95], [0, -4.9], [5.08, -4.9] ], small_leg, grey(20), "white" ];
|
||||
medium_microswitch = ["medium_microswitch","SS-01 or SS-5GL", 6.4, 10.2, 19.8, 1, 2.35, [[-4.8, -2.6 ], [4.7, -2.6 ]], 3.2, 2, [-2.8, 5.8 ], [[-8.05, -7.05], [0.75, -7.05], [8.05, -7.05] ], medium_leg, grey(20), "burlywood" ];
|
||||
large_microswitch = ["large_microswitch", "Saia G3 low force", 10.4, 15.9, 28.0, 2, 3.1, [[-11.1, -5.15], [11.2, 5.15]], 4, 2.75,[-9.1, 9.55], [[19.7, 2.19], [19.7, -3.45], [8.3, -10.45] ], large_leg, "ivory", "white" ];
|
||||
// t w l r h h b b b o f l l b b
|
||||
// h i e a o o u u u p p e e o u
|
||||
// i d n d l l t t t g g d t
|
||||
// c t g i e e t t t t m y t
|
||||
// k h t u o o o o a p t o
|
||||
// n h s d p n n n l x o y c n
|
||||
// e i o s p l
|
||||
// s a s w t p n e r c
|
||||
// n n o s l
|
||||
// s s r
|
||||
small_microswitch = ["small_microswitch", "DM1-00P-110-3", 5.8, 6.5, 12.8, 0, 2, [[-3.25, -1.65], [3.25, -1.65]], 2.9, 1.2, [-1.95, 3.75], 0.2, 0.55, [[-5.08, -4.95], [0, -4.9], [5.08, -4.9] ], small_leg, grey(20), "white" ];
|
||||
medium_microswitch = ["medium_microswitch","SS-01 or SS-5GL", 6.4, 10.2, 19.8, 1, 2.35, [[-4.8, -2.6 ], [4.7, -2.6 ]], 3.2, 2, [-2.8, 5.8 ], 0.5, 1.00, [[-8.05, -7.05], [0.75, -7.05], [8.05, -7.05] ], medium_leg, grey(20), "burlywood" ];
|
||||
large_microswitch = ["large_microswitch", "Saia G3 low force", 10.4, 15.9, 28.0, 2, 3.1, [[-11.1, -5.15], [11.2, 5.15]], 4, 2.75,[-9.1, 9.55], 0.3, 1.2, [[19.7, 2.19], [19.7, -3.45], [8.3, -10.45] ], large_leg, "ivory", "white" ]; //G3M1T1PUL
|
||||
|
||||
microswitches = [small_microswitch, medium_microswitch, large_microswitch];
|
||||
|
||||
|
@@ -129,15 +129,13 @@ module mod_screw_positions(type) //! Position children at the screw positions
|
||||
|
||||
module module_assembly(type, thickness) { //! Module with its fasteners in place
|
||||
screw = mod_screw(type);
|
||||
washer = screw_washer(screw);
|
||||
nut = screw_nut(screw);
|
||||
screw_length = screw_longer_than(thickness + mod_screw_z(type) + 2 * washer_thickness(washer) + nut_thickness(nut, true));
|
||||
screw_length = screw_length(screw, thickness + mod_screw_z(type), 2, nyloc = true);
|
||||
|
||||
mod(type);
|
||||
|
||||
mod_screw_positions(type) {
|
||||
translate_z(mod_screw_z(type))
|
||||
nut_and_washer(nut, true);
|
||||
nut_and_washer(screw_nut(screw), true);
|
||||
|
||||
translate_z(-thickness)
|
||||
vflip()
|
||||
|
@@ -1121,9 +1121,7 @@ module pcb_assembly(type, height, thickness) { //! Draw PCB assembly with spaces
|
||||
|
||||
screw = pcb_screw(type);
|
||||
if(!is_undef(screw)) {
|
||||
washer = screw_washer(screw);
|
||||
nut = screw_nut(screw);
|
||||
screw_length = screw_longer_than(height + thickness + pcb_thickness(type) + washer_thickness(washer) + nut_thickness(nut, true));
|
||||
screw_length = screw_length(screw, height + thickness + pcb_thickness(type), 1, nyloc = true);
|
||||
|
||||
taper = screw_smaller_than(pcb_hole_d(type)) > 2 * screw_radius(screw); // Arduino?
|
||||
pcb_screw_positions(type) {
|
||||
@@ -1138,7 +1136,7 @@ module pcb_assembly(type, height, thickness) { //! Draw PCB assembly with spaces
|
||||
|
||||
translate_z(-thickness)
|
||||
vflip()
|
||||
nut_and_washer(nut, true);
|
||||
nut_and_washer(screw_nut(screw), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -21,6 +21,7 @@ include <d_connectors.scad>
|
||||
include <leds.scad>
|
||||
include <axials.scad>
|
||||
include <smds.scad>
|
||||
include <green_terminals.scad>
|
||||
|
||||
//
|
||||
// l w t r h l c b h
|
||||
@@ -195,6 +196,219 @@ Duex5 = ["Duex5", "Duex5 expansion board",
|
||||
]),
|
||||
[]];
|
||||
|
||||
BTT_SKR_MINI_E3_V2_0 = [
|
||||
"BTT_SKR_MINI_E3_V2_0", "BigTreeTech SKR Mini E3 v2.0",
|
||||
100.75, 70.25, 1.6, // size
|
||||
1, // corner radius
|
||||
3, // mounting hole diameter
|
||||
5, // pad around mounting hole
|
||||
grey(30), // color
|
||||
false, // true if parts should be separate BOM items
|
||||
[ // hole positions
|
||||
for (i = [ [0, 0], [62.15, 0] ])
|
||||
(i + [20.3, -2.89]),
|
||||
for (i = [ [0, -34.98], [31.80, -37.63], [95.68, -64.47] ])
|
||||
(i + [2.535, -2.89])
|
||||
],
|
||||
[ // components
|
||||
// cpu
|
||||
[ 55, 33, 0, "chip", 10, 10, 1, grey(15) ],
|
||||
// driver chips
|
||||
for (x = [10.5, 30.5, 50.5, 70.5])
|
||||
[ x, -17.5, 0, "chip", 5, 5, 1, grey(15) ],
|
||||
// mock up heat sinks over the chips
|
||||
for (x = [10.5, 30.5, 50.5, 70.5])
|
||||
[ x, -17.5, 0, "block", 9, 8.5, 2, "DeepSkyBlue" ],
|
||||
for(x = [10.5, 30.5, 50.5, 70.5], y = [-4,-2,0,2,4])
|
||||
[ x, -17.5 + y, 0, "block", 9, 0.75, 11, "DeepSkyBlue" ],
|
||||
// heat dissipation for drivers under board
|
||||
[ 43, -17.5, 0, "-block", 85, 8, 0.1, gold ],
|
||||
|
||||
// heated bed
|
||||
[ 26, 16, 0, "chip", 9.5, 8.5, 4, grey(15) ],
|
||||
[ 27, 19, 0, "-block", 13, 14, 0.1, gold ],
|
||||
// hotend
|
||||
[ 37, 14, 0, "chip", 6, 6, 2.5, grey(15) ],
|
||||
[ 40, 16, 0, "-block", 10, 8, 0.1, gold ],
|
||||
|
||||
// voltage regulator heat dissipation
|
||||
[ 12, 28.5, 0, "-block", 11, 7, 0.1, gold ],
|
||||
|
||||
// terminals
|
||||
[ 5.25, 5.3, 180, "gterm", gt_5x17, 2, undef, grey(20) ],
|
||||
[ 18.1, 5.1, -90, "gterm", gt_5x17, 2, undef, grey(20) ],
|
||||
[ 29.3, 5.1, -90, "gterm", gt_5x17, 2, undef, grey(20) ],
|
||||
[ 40.5, 5.1, -90, "gterm", gt_5x11, 2, undef, grey(20) ],
|
||||
// SD and USB
|
||||
[ -3, -(22.27 + 29.92)/2, 0, "usb_uA" ],
|
||||
[ -8, -( 2.13 + 17.17)/2, 0, "uSD", [17.17 - 2.13, 16, 2] ],
|
||||
// EXP
|
||||
[ -4.5, 17, -90, "2p54boxhdr", 5, 2 ],
|
||||
// TFT
|
||||
[ 66.1, 21.7, 0, "2p54header", 5, 1 ],
|
||||
// FAN0
|
||||
[ 50.25, 3.8, 0, "jst_xh", 2, false, grey(20) ],
|
||||
// FAN1
|
||||
[ 49.9, 16.1, 0, "jst_xh", 2, false, grey(20) ],
|
||||
// PS-ON
|
||||
[ 58.1, 16.1, 0, "jst_xh", 2, false, grey(20) ],
|
||||
// PWR-DET
|
||||
[ 67.5, 16.0, 0, "jst_xh", 3, false, grey(20) ],
|
||||
// E0-STOP
|
||||
[ 78.2, 16.0, 0, "jst_xh", 3, false, grey(20) ],
|
||||
// Z-PROBE
|
||||
[ 87.2, 20.5, -90,"jst_xh", 5, false, grey(20) ],
|
||||
// NEO Pixel
|
||||
[ 78.2, 27.1, 0, "jst_xh", 3, false, grey(20) ],
|
||||
// end stops
|
||||
[ 58.60, 3.8, 0, "jst_xh", 2, false, grey(20) ],
|
||||
[ 66.70, 3.8, 0, "jst_xh", 2, false, grey(20) ],
|
||||
[ 74.90, 3.8, 0, "jst_xh", 2, false, grey(20) ],
|
||||
// thermistors
|
||||
[ 83.00, 3.8, 0, "jst_xh", 2, false, grey(20) ],
|
||||
[ 91.10, 3.8, 0, "jst_xh", 2, false, grey(20) ],
|
||||
// motor connections
|
||||
[ 10.15, -4.2, 0, "jst_xh", 4, false, grey(20) ],
|
||||
[ 30.35, -4.2, 0, "jst_xh", 4, false, grey(20) ],
|
||||
[ 43.90, -4.2, 0, "jst_xh", 4, false, grey(20) ],
|
||||
[ 57.25, -4.2, 0, "jst_xh", 4, false, grey(20) ],
|
||||
[ 70.75, -4.2, 0, "jst_xh", 4, false, grey(20) ],
|
||||
// motor jumpers
|
||||
[ 20.6, 44.1, 0, "2p54header", 2, 1 ],
|
||||
[ 39.6, 44.2, 0, "2p54header", 2, 1 ],
|
||||
[ 60.1, 44.1, 0, "2p54header", 2, 1 ],
|
||||
[ 80.3, 44.1, 0, "2p54header", 2, 1 ],
|
||||
// SWD
|
||||
[ 43.9, 39.2, 0, "2p54header", 1, 5 ],
|
||||
// SPI
|
||||
[ -3.1, 31.9, 0, "2p54header", 2, 3 ],
|
||||
// PWR-1
|
||||
[ -12.8, 30.3, 0, "2p54header", 3, 1 ],
|
||||
// VOUT
|
||||
[ -14.0, 34.4, 0, "2p54header", 2, 2 ],
|
||||
// VIN
|
||||
[ 17.3, 19.6, 0, "2p54header", 2, 2 ],
|
||||
],
|
||||
[] // accessories
|
||||
];
|
||||
|
||||
TMC2130 = [
|
||||
"TMC2130", "TMC2130",
|
||||
20, 14, 1.6, // size
|
||||
0, 0, 0, // corner radius, mounting hole diameter, pad around mounting hole
|
||||
grey(95), // colour
|
||||
false, // true if parts should be separate BOM items
|
||||
[], // hole positions
|
||||
[
|
||||
[ 10, 1, 0, "-2p54header", 8, 1 ],
|
||||
[ 10, 13, 0, "-2p54header", 8, 1 ],
|
||||
[ 12, 7, 0, "-chip", 6, 4, 1, grey(20) ],
|
||||
// mock up a heat sink
|
||||
[ 10, 7, 0, "block", 9, 8.5, 2, "DeepSkyBlue" ],
|
||||
for (y = [-4,-2,0,2,4]) [ 10, 7 + y, 0, "block", 9, 0.75, 11, "DeepSkyBlue" ],
|
||||
],
|
||||
[]
|
||||
];
|
||||
|
||||
BTT_SKR_V1_4_TURBO = [
|
||||
"BTT_SKR_V1_4_TURBO", "BigTreeTech SKR v1.4 Turbo",
|
||||
110, 85, 1.6, // size
|
||||
1, // corner radius
|
||||
3, // mounting hole diameter
|
||||
4, // pad around mounting hole
|
||||
grey(30), // colour
|
||||
false, // true if parts should be separate BOM items
|
||||
[ // hole positions
|
||||
[-4, 4], [-4, -4], [4, -4], [4, 4]
|
||||
],
|
||||
[ // components
|
||||
[ (29.15+31.5)/2, 8, -90, "usb_B" ],
|
||||
[ (46.9+51.55)/2, 7, -90, "uSD", [14, 14, 2] ],
|
||||
[ 105, 13, 0, "button_6mm" ],
|
||||
[ 58, 43, 0, "chip", 15, 15, 1, grey(20) ],
|
||||
// ESP-01 socket
|
||||
[ 69.8, 4, 0, "2p54socket", 4, 2 ],
|
||||
// terminals
|
||||
[ 5.3, 13.2, 180, "gterm", gt_5x17, 2, undef, grey(20)],
|
||||
[ 5.3, 25.8, 180, "gterm", gt_5x17, 2, undef, grey(20)],
|
||||
[ 5.3, 37.2, 180, "gterm", gt_5x11, 2, undef, grey(20)],
|
||||
[ 5.3, 47.2, 180, "gterm", gt_5x11, 2, undef, grey(20)],
|
||||
|
||||
[ 2.8, 56.7, -90, "jst_xh", 2, false, grey(20) ],
|
||||
[ 10.9, 56.7, 90, "jst_xh", 2, false, grey(20) ],
|
||||
[ 82, 4, 0, "jst_xh", 2, false, grey(20) ],
|
||||
[ 90, 4, 0, "jst_xh", 2, false, grey(20) ],
|
||||
[ 98, 4, 0, "jst_xh", 2, false, grey(20) ],
|
||||
|
||||
[ 87.7, 29.0, -90, "jst_xh", 3, false, grey(20) ],
|
||||
[ 87.7, 39.5, -90, "jst_xh", 3, false, grey(20) ],
|
||||
[ 87.7, 50.1, -90, "jst_xh", 3, false, grey(20) ],
|
||||
[ 95.3, 29.0, -90, "jst_xh", 3, false, grey(20) ],
|
||||
[ 95.3, 39.5, -90, "jst_xh", 3, false, grey(20) ],
|
||||
[ 95.3, 50.1, -90, "jst_xh", 3, false, grey(20) ],
|
||||
|
||||
[ 85.7, 18.2, 180, "jst_xh", 3, false, grey(20) ],
|
||||
[ 94.9, 18.2, 180, "jst_xh", 2, false, grey(20) ],
|
||||
[ 77.2, 19.6, -90, "jst_xh", 3, false, grey(20) ],
|
||||
[ 69.8, 11.0, 0, "jst_xh", 5, false, grey(20) ],
|
||||
|
||||
[ 69.0, 19.2, 0, "2p54header", 4, 1 ],
|
||||
[ 57.8, 18.0, 0, "2p54header", 3, 2 ],
|
||||
[ 28.0, 19.7, 0, "2p54header", 2, 2 ],
|
||||
|
||||
[ 37.6, 28.8, 0, "2p54header", 1, 3, undef, "red" ],
|
||||
[ 77.8, 27.5, 0, "2p54header", 2, 2 ],
|
||||
[ 81.8, 26.4, 0, "2p54header", 1, 3, undef, "red" ],
|
||||
[ 43.8, 42.8, 0, "2p54header", 1, 5 ],
|
||||
|
||||
// EXP1 & EXP2
|
||||
[ -6.6, 29.4, 90, "2p54boxhdr", 5, 2 ],
|
||||
[ -6.6, 50.4, 90, "2p54boxhdr", 5, 2 ],
|
||||
|
||||
// motor axes connections
|
||||
[ 11.2, -3.75, 180, "jst_xh", 2, false, grey(20) ],
|
||||
[ 21.8, -3.75, 180, "jst_xh", 4, false, grey(20) ],
|
||||
[ 35.0, -3.75, 180, "jst_xh", 4, false, grey(20) ],
|
||||
[ 48.2, -3.75, 180, "jst_xh", 4, false, grey(20) ],
|
||||
[ 61.4, -3.75, 180, "jst_xh", 4, false, grey(20) ],
|
||||
[ 74.7, -3.75, 180, "jst_xh", 4, false, grey(20) ],
|
||||
[ 87.9, -3.75, 180, "jst_xh", 4, false, grey(20) ],
|
||||
[ 98.5, -3.75, 180, "jst_xh", 2, false, grey(20) ],
|
||||
|
||||
// stepper drivers
|
||||
[ 11.5, 62.5, 0, "2p54socket", 8, 1, undef, undef, undef, "red" ],
|
||||
[ 11.5, 75.2, 0, "2p54socket", 8, 1 ],
|
||||
[ 2.6, 66.3, 90, "2p54socket", 2, 1, undef, undef, undef, "red" ],
|
||||
[ 11.5, 68.85, 0, "pcb", 11, TMC2130 ],
|
||||
|
||||
[ 33.1, 62.5, 0, "2p54socket", 8, 1, undef, undef, undef, "red" ],
|
||||
[ 33.1, 75.2, 0, "2p54socket", 8, 1 ],
|
||||
[ 24.2, 66.3, 90, "2p54socket", 2, 1, undef, undef, undef, "red" ],
|
||||
[ 33.1, 68.85, 0, "pcb", 11, TMC2130 ],
|
||||
|
||||
[ 54.8, 62.5, 0, "2p54socket", 8, 1, undef, undef, undef, "red" ],
|
||||
[ 54.8, 75.2, 0, "2p54socket", 8, 1 ],
|
||||
[ 45.9, 66.3, 90, "2p54socket", 2, 1, undef, undef, undef, "red" ],
|
||||
[ 54.8, 68.85, 0, "pcb", 11, TMC2130 ],
|
||||
|
||||
[ 76.4, 62.5, 0, "2p54socket", 8, 1, undef, undef, undef, "red" ],
|
||||
[ 76.4, 75.2, 0, "2p54socket", 8, 1 ],
|
||||
[ 67.5, 66.3, 90, "2p54socket", 2, 1, undef, undef, undef, "red" ],
|
||||
[ 76.4, 68.85, 0, "pcb", 11, TMC2130 ],
|
||||
|
||||
[ 98.1, 62.5, 0, "2p54socket", 8, 1, undef, undef, undef, "red" ],
|
||||
[ 98.1, 75.2, 0, "2p54socket", 8, 1 ],
|
||||
[ 89.2, 66.3, 90, "2p54socket", 2, 1, undef, undef, undef, "red" ],
|
||||
|
||||
// closed loop pins
|
||||
[ 24.4, 57.5, 0, "2p54header", 6, 1 ],
|
||||
[ 40.6, 57.5, 0, "2p54header", 6, 1 ],
|
||||
[ 56.7, 57.5, 0, "2p54header", 6, 1 ],
|
||||
[ 72.9, 57.5, 0, "2p54header", 6, 1 ],
|
||||
[ 89.1, 57.5, 0, "2p54header", 6, 1 ],
|
||||
],
|
||||
[] // accessories
|
||||
];
|
||||
|
||||
Melzi = ["Melzi", "Melzi electronics", 203.2, 49.53, 1.6, 3.81, 3.1, 6, "green", false, [[3.81, 3.81], [-3.81, 3.81], [-3.81, -3.81], [3.81, -3.81]],
|
||||
[],
|
||||
@@ -414,8 +628,35 @@ RAMPSEndstop = ["RAMPSEndstop", "RAMPS Endstop Switch",
|
||||
],
|
||||
[]];
|
||||
|
||||
ESP_01 = [
|
||||
"ESP-01", "ESP-01",
|
||||
24.8, 14.6, 1, // size
|
||||
0, // corner radius
|
||||
0, // mounting hole diameter
|
||||
0, // pad around mounting hole
|
||||
grey(25), // color
|
||||
false, // true if parts should be separate BOM items
|
||||
[], // hole positions
|
||||
[ // components
|
||||
[ 2.8, -7.25, 0, "-2p54header", 2, 4 ],
|
||||
[ -14.55, -11.3, 0, "chip", 5.25, 5.25, 2.25, grey(15) ],
|
||||
[ -14, -5.2, 0, "chip", 4.5, 4.75, 1.1, grey(15) ],
|
||||
// antenna
|
||||
for (y = [ 2.8 : 2.3 : 7.4 ]) [ -0.7, -y, 0, "block", 0.7, 1.75, 0.1, gold ],
|
||||
for (y = [ 4 : 2.3 : 10.6 ]) [ -4.3, -y, 0, "block", 0.7, 1.75, 0.1, gold ],
|
||||
for (y = [ 3.4 : 2.3 : 10.1 ]) [ -2.5, -y, 0, "block", 4.3, 0.7, 0.1, gold ],
|
||||
for (y = [ 4.55 : 2.3 : 11.2 ]) [ -2.5, -y, 0, "block", 4.3, 0.7, 0.1, gold ],
|
||||
|
||||
pcbs = [MP1584EN, TP4056, MT3608, RAMPSEndstop, ExtruderPCB, PI_IO, ZC_A0591, RPI0, EnviroPlus, ArduinoUno3, ArduinoLeonardo, Keyes5p1, PSU12V1A, WD2002SJ, RPI3, RPI4, DuetE, Duex2, Duex5];
|
||||
[ -0.7, -10.85, 0, "block", 0.7,3.75, 0.1, gold ],
|
||||
[ -6.6, -5.8, 0, "block", 0.7, 7.5, 0.1, gold ],
|
||||
[ -4.8, -2.3, 0, "block", 8.8, 0.7, 0.1, gold ],
|
||||
],
|
||||
[] // accessories
|
||||
];
|
||||
|
||||
pcbs = [MP1584EN, TP4056, ESP_01, RAMPSEndstop, MT3608, PI_IO, ExtruderPCB, ZC_A0591, RPI0, EnviroPlus, ArduinoUno3, ArduinoLeonardo, Keyes5p1, WD2002SJ, RPI3, RPI4, BTT_SKR_MINI_E3_V2_0, BTT_SKR_V1_4_TURBO, DuetE, Duex5];
|
||||
|
||||
pcbs_not_shown = [Melzi, Duex2, PSU12V1A];
|
||||
|
||||
perfboards = [PERF74x51, PERF70x50, PERF60x40, PERF70x30, PERF80x20];
|
||||
|
||||
|
@@ -53,7 +53,7 @@ function pulley_extent(type) = max(pulley_flange_dia(type), pulley_hub_dia(type)
|
||||
T_angle = 40;
|
||||
GT_r = 0.555;
|
||||
|
||||
module pulley(type) { //! Draw a pulley
|
||||
module pulley(type, colour = silver) { //! Draw a pulley
|
||||
teeth = pulley_teeth(type);
|
||||
od = pulley_od(type);
|
||||
|
||||
@@ -64,6 +64,7 @@ module pulley(type) { //! Draw a pulley
|
||||
hl = pulley_hub_length(type);
|
||||
w = pulley_width(type);
|
||||
r1 = pulley_bore(type) / 2;
|
||||
screw_z = pulley_screw_z(type);
|
||||
|
||||
or = od / 2;
|
||||
ir = pulley_ir(type);
|
||||
@@ -100,39 +101,48 @@ module pulley(type) { //! Draw a pulley
|
||||
}
|
||||
}
|
||||
|
||||
module screw_holes() {
|
||||
if(pulley_screws(type))
|
||||
translate_z(pulley_screw_z(type))
|
||||
for(i = [0 : pulley_screws(type) - 1])
|
||||
rotate([-90, 0, i * -90])
|
||||
cylinder(r = screw_radius(pulley_screw(type)), h = 100);
|
||||
}
|
||||
module hub()
|
||||
rotate_extrude() translate([r1, 0]) {
|
||||
if(hl)
|
||||
square([pulley_hub_dia(type) / 2 - r1, hl]);
|
||||
|
||||
color("silver") {
|
||||
render() difference() {
|
||||
rotate_extrude() translate([r1, 0]) {
|
||||
if(hl)
|
||||
square([pulley_hub_dia(type) / 2 - r1, hl]);
|
||||
|
||||
for(z = [pulley_hub_length(type), hl + ft + w])
|
||||
translate([0, z])
|
||||
square([pulley_flange_dia(type) / 2 - r1, ft]);
|
||||
}
|
||||
if(pulley_screw_z(type) < hl)
|
||||
screw_holes();
|
||||
for(z = [pulley_hub_length(type), hl + ft + w])
|
||||
translate([0, z])
|
||||
square([pulley_flange_dia(type) / 2 - r1, ft]);
|
||||
}
|
||||
render() difference() { // T5 pulleys have screw through the teeth
|
||||
|
||||
module screw_holes()
|
||||
translate_z(screw_z)
|
||||
for(i = [0 : pulley_screws(type) - 1])
|
||||
rotate([-90, 0, i * -90])
|
||||
cylinder(r = screw_radius(pulley_screw(type)), h = 100);
|
||||
|
||||
color(colour) {
|
||||
if(screw_z && screw_z < hl)
|
||||
render()
|
||||
difference() {
|
||||
hub();
|
||||
|
||||
screw_holes();
|
||||
}
|
||||
else
|
||||
hub();
|
||||
|
||||
if(screw_z && screw_z > hl) // T5 pulleys have screw through the teeth
|
||||
render()
|
||||
difference() {
|
||||
core();
|
||||
|
||||
screw_holes();
|
||||
}
|
||||
else
|
||||
core();
|
||||
|
||||
if(pulley_screw_z(type) > hl)
|
||||
screw_holes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module pulley_assembly(type) { //! Draw a pulley with its grub screws in place
|
||||
module pulley_assembly(type, colour = silver) { //! Draw a pulley with its grub screws in place
|
||||
translate_z(pulley_offset(type)) {
|
||||
pulley(type);
|
||||
pulley(type, colour);
|
||||
|
||||
if(pulley_screws(type))
|
||||
translate_z(pulley_screw_z(type))
|
||||
|
@@ -31,10 +31,11 @@ function rail_bore(type) = type[5]; //! Counter bore diameter for screw
|
||||
function rail_hole(type) = type[6]; //! Screw hole diameter
|
||||
function rail_bore_depth(type) = type[7]; //! Counter bore depth
|
||||
function rail_screw(type) = type[8]; //! Screw type
|
||||
function rail_carriage(type) = type[9]; //! Carriage type
|
||||
function rail_end_screw(type) = type[10]; //! Screw used for ends only (Countersink used for better location)
|
||||
function rail_end_screw(type) = type[9]; //! Screw used for ends only (Countersink used for better location)
|
||||
function rail_groove_offset(type)=type[10]; //! Offset of centre of groove from top of rail
|
||||
function rail_groove_width(type)=type[11]; //! Groove width
|
||||
|
||||
function rail_screw_height(type, screw) = rail_height(type) - rail_bore_depth(type) + screw_head_depth(screw, rail_hole(type)); //! Position screw taking into account countersink into counterbored hole
|
||||
function rail_travel(type, length) = length - carriage_length(rail_carriage(type)); //! How far the carriage can travel
|
||||
|
||||
function carriage_length(type) = type[0]; //! Overall length
|
||||
function carriage_block_length(type) = type[1]; //! Length of the metal part
|
||||
@@ -45,7 +46,9 @@ function carriage_clearance(type) = type[4]; //! Gap under the carriage
|
||||
function carriage_pitch_x(type) = type[5]; //! Screw hole x pitch
|
||||
function carriage_pitch_y(type) = type[6]; //! Screw hole y pitch
|
||||
function carriage_screw(type) = type[7]; //! Carriage screw type
|
||||
function carriage_rail(type) = type[8]; //! Rail type
|
||||
function carriage_screw_depth(type) = 2 * screw_radius(carriage_screw(type)); //! Carriage thread depth
|
||||
function carriage_travel(type, rail_length) = rail_length - carriage_length(type); //! How far the carriage can travel on a given length rail
|
||||
|
||||
function rail_holes(type, length) = //! Number of holes in a rail given its `length`
|
||||
floor((length - 2 * rail_end(type)) / rail_pitch(type)) + 1;
|
||||
@@ -70,7 +73,7 @@ module carriage_hole_positions(type) { //! Position children over screw holes
|
||||
children();
|
||||
}
|
||||
|
||||
module carriage(type, rail, end_colour = grey(20), wiper_colour = grey(20)) { //! Draw the specified carriage
|
||||
module carriage(type, end_colour = grey(20), wiper_colour = grey(20)) { //! Draw the specified carriage
|
||||
total_l = carriage_length(type);
|
||||
block_l = carriage_block_length(type);
|
||||
block_w = carriage_width(type);
|
||||
@@ -82,9 +85,9 @@ module carriage(type, rail, end_colour = grey(20), wiper_colour = grey(20)) { //
|
||||
screw_depth = carriage_screw_depth(type);
|
||||
|
||||
module cutout() {
|
||||
w = rail_width(rail) + 0.4;
|
||||
w = rail_width(carriage_rail(type)) + 0.4;
|
||||
translate([-w / 2, 0])
|
||||
square([w , rail_height(rail) + 0.2]);
|
||||
square([w , rail_height(carriage_rail(type)) + 0.2]);
|
||||
}
|
||||
|
||||
color(grey(90)) {
|
||||
@@ -134,51 +137,53 @@ module carriage(type, rail, end_colour = grey(20), wiper_colour = grey(20)) { //
|
||||
carriage_end(type, end_w, end_h, end_l);
|
||||
}
|
||||
|
||||
module rail(type, length) { //! Draw the specified rail
|
||||
module rail(type, length, colour = grey(90), use_polycircles = false) { //! Draw the specified rail
|
||||
width = rail_width(type);
|
||||
height = rail_height(type);
|
||||
|
||||
vitamin(str("rail(", type[0], ", ", length, "): Linear rail ", type[0], " x ", length, "mm"));
|
||||
|
||||
color(grey(90)) {
|
||||
color(colour) {
|
||||
rbr = rail_bore(type) / 2;
|
||||
w = corrected_radius(rbr) * 2 + 2 * eps; // width of core big enough for the holes
|
||||
linear_extrude(height - rail_bore_depth(type)) difference() {
|
||||
square([length, width], center = true);
|
||||
square([length, w], center = true);
|
||||
|
||||
rail_hole_positions(type, length)
|
||||
circle(d = rail_hole(type));
|
||||
if (use_polycircles)
|
||||
poly_circle(rail_hole(type) / 2);
|
||||
else
|
||||
circle(d = rail_hole(type));
|
||||
}
|
||||
translate_z(rail_height(type) - rail_bore_depth(type))
|
||||
linear_extrude(rail_bore_depth(type)) difference() {
|
||||
square([length, w], center = true);
|
||||
|
||||
translate_z(rail_height(type) - rail_bore_depth(type)) {
|
||||
h1 = rail_bore_depth(type) > 2 ? rail_bore_depth(type) / 3 : rail_bore_depth(type) / 2;
|
||||
h0 = rail_bore_depth(type) > 2 ? (rail_bore_depth(type) - h1) / 2 : 0;
|
||||
h2 = rail_bore_depth(type) - h1 - h0;
|
||||
|
||||
linear_extrude(h0) difference() {
|
||||
square([length, width], center = true);
|
||||
rail_hole_positions(type, length)
|
||||
circle(d = rail_bore(type));
|
||||
if (use_polycircles)
|
||||
poly_circle(rbr);
|
||||
else
|
||||
circle(rbr);
|
||||
}
|
||||
translate_z(h0)
|
||||
linear_extrude(h1) difference() {
|
||||
w1 = max(width - 2, rail_bore(type));
|
||||
square([length, w1], center = true);
|
||||
rail_hole_positions(type, length)
|
||||
circle(d = rail_bore(type));
|
||||
}
|
||||
translate_z(h0 + h1)
|
||||
linear_extrude(h2) difference() {
|
||||
square([length, width], center = true);
|
||||
rail_hole_positions(type, length)
|
||||
circle(d = rail_bore(type));
|
||||
}
|
||||
}
|
||||
|
||||
go = height - rail_groove_offset(type);
|
||||
gw = rail_groove_width(type);
|
||||
gd = gw / 2;
|
||||
sw = (width - w) / 2;
|
||||
for (m = [0, 1])
|
||||
mirror([0, m, 0])
|
||||
translate([0, -width / 2])
|
||||
rotate([0, -90, 0])
|
||||
linear_extrude(length, center = true)
|
||||
polygon([ [0, 0], [0, sw], [height, sw], [height, 0], [go + gw/2, 0], [go, gd], [go - gw/2, 0] ]);
|
||||
}
|
||||
}
|
||||
|
||||
module rail_assembly(type, length, pos, carriage_end_colour = grey(20), carriage_wiper_colour = grey(20)) { //! Rail and carriage assembly
|
||||
rail(type, length);
|
||||
module rail_assembly(carriage, length, pos, carriage_end_colour = grey(20), carriage_wiper_colour = grey(20)) { //! Rail and carriage assembly
|
||||
rail(carriage_rail(carriage), length);
|
||||
|
||||
translate([pos, 0])
|
||||
carriage(rail_carriage(type), type, carriage_end_colour, carriage_wiper_colour);
|
||||
carriage(carriage, carriage_end_colour, carriage_wiper_colour);
|
||||
}
|
||||
|
||||
module rail_screws(type, length, thickness, screws = 100, index_screws = undef) { //! Place screws in the rail
|
||||
|
@@ -17,30 +17,29 @@
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
//
|
||||
// Carriages
|
||||
//
|
||||
// L L1 W H H1 C B
|
||||
MGN5_carriage = [ 16, 9.6, 12, 6, 1.5, 0, 8 , M2_cap_screw ];
|
||||
MGN7_carriage = [ 23, 14.3, 17, 8, 1.5, 8, 12, M2_cap_screw ];
|
||||
MGN9_carriage = [ 29.7, 20.8, 20, 10, 2, 10, 15, M3_cap_screw ];
|
||||
MGN12_carriage = [ 34.7, 21.7, 27, 13, 3, 15, 20, M3_cap_screw ];
|
||||
MGN12H_carriage= [ 45.4, 32.4, 27, 13, 3, 20, 20, M3_cap_screw ];
|
||||
MGN15_carriage = [ 43.3, 27.7, 32, 16, 4, 20, 25, M3_cap_screw ];
|
||||
SSR15_carriage = [ 40.3, 23.3, 34, 24, 4.5, 0, 26, M4_cap_screw ];
|
||||
//
|
||||
// Rails
|
||||
//
|
||||
// Wr Hr E P D d h go gw
|
||||
MGN5 = [ "MGN5", 5, 3.6, 5, 15, 3.6, 2.4, 0.8, M2_cs_cap_screw, M2_cs_cap_screw, 1, 1 ]; // Screw holes too small for M2 heads
|
||||
MGN7 = [ "MGN7", 7, 5, 5, 15, 4.3, 2.4, 2.6, M2_cap_screw, M2_cs_cap_screw, 1.5, 1.5 ];
|
||||
MGN9 = [ "MGN9", 9, 6, 7.5, 20, 6.0, 3.5, 3.5, M3_cap_screw, M3_cs_cap_screw, 1.5, 1.5 ];
|
||||
MGN12 =[ "MGN12", 12, 8, 10, 25, 6.0, 3.5, 4.5, M3_cap_screw, M3_cs_cap_screw, 2.25, 2.75];
|
||||
MGN15 =[ "MGN15", 15, 10, 10, 40, 6.0, 3.5, 5.0, M3_cap_screw, M3_cs_cap_screw, 2.5, 2.75 ];
|
||||
SSR15= [ "SSR15", 15, 12.5, 10, 60, 7.5, 4.5, 5.3, M4_cap_screw, M4_cs_cap_screw, 2.5, 2.75 ];
|
||||
//
|
||||
// Wr Hr E P D d h
|
||||
MGN5 = [ "MGN5", 5, 3.6, 5, 15, 3.6, 2.4, 0.8, M2_cs_cap_screw, MGN5_carriage, M2_cs_cap_screw ]; // Screw holes too small for M2 heads
|
||||
MGN7 = [ "MGN7", 7, 5, 5, 15, 4.3, 2.4, 2.6, M2_cap_screw, MGN7_carriage, M2_cs_cap_screw ];
|
||||
MGN9 = [ "MGN9", 9, 6, 7.5, 20, 6.0, 3.5, 3.5, M3_cap_screw, MGN9_carriage, M3_cs_cap_screw ];
|
||||
MGN12= [ "MGN12", 12, 8, 10, 25, 6.0, 3.5, 4.5, M3_cap_screw, MGN12_carriage, M3_cs_cap_screw ];
|
||||
MGN12H=[ "MGN12H",12, 8, 10, 25, 6.0, 3.5, 4.5, M3_cap_screw, MGN12H_carriage,M3_cs_cap_screw ];
|
||||
MGN15= [ "MGN15", 15, 10, 10, 40, 6.0, 3.5, 5.0, M3_cap_screw, MGN15_carriage, M3_cs_cap_screw ];
|
||||
SSR15= [ "SSR15", 15, 12.5,10, 60, 7.5, 4.5, 5.3, M4_cap_screw, SSR15_carriage, M4_cs_cap_screw ];
|
||||
// Carriages
|
||||
//
|
||||
// L L1 W H H1 C B
|
||||
MGN5_carriage = [ 16, 9.6, 12, 6, 1.5, 0, 8, M2_cap_screw, MGN5 ];
|
||||
MGN7C_carriage = [ 23, 14.3, 17, 8, 1.5, 8, 12, M2_cap_screw, MGN7 ];
|
||||
MGN9C_carriage = [ 29.7, 20.8, 20, 10, 2, 10, 15, M3_cap_screw, MGN9 ];
|
||||
MGN12C_carriage = [ 34.7, 21.7, 27, 13, 3, 15, 20, M3_cap_screw, MGN12 ];
|
||||
MGN12H_carriage = [ 45.4, 32.4, 27, 13, 3, 20, 20, M3_cap_screw, MGN12 ];
|
||||
MGN15C_carriage = [ 43.3, 27.7, 32, 16, 4, 20, 25, M3_cap_screw, MGN15 ];
|
||||
SSR15_carriage = [ 40.3, 23.3, 34, 24, 4.5, 0, 26, M4_cap_screw, SSR15 ];
|
||||
|
||||
rails = [MGN5, MGN7, MGN9, MGN12, MGN12H, MGN15, SSR15];
|
||||
|
||||
carriages = [MGN5_carriage, MGN7C_carriage, MGN9C_carriage, MGN12C_carriage, MGN12H_carriage, MGN15C_carriage, SSR15_carriage];
|
||||
|
||||
use <rail.scad>
|
||||
|
@@ -128,7 +128,7 @@ module ring_terminal_assembly(type, thickness, top = false) { //! Earthing assem
|
||||
screw = ringterm_screw(type);
|
||||
washer = screw_washer(screw);
|
||||
nut = screw_nut(screw);
|
||||
screw_length = screw_longer_than(thickness + 2 * washer_thickness(washer) + nut_thickness(nut, true) + ringterm_thickness(type));
|
||||
screw_length = screw_length(screw, thickness + ringterm_thickness(type), 2, nyloc = true);
|
||||
|
||||
explode(10, true) star_washer(washer)
|
||||
if(top)
|
||||
|
@@ -48,7 +48,7 @@ function screw_head_depth(type, d = 0) = //! How far a counter sink
|
||||
? 0
|
||||
: let(r = screw_radius(type)) screw_head_radius(type) - max(r, d / 2) + r / 5;
|
||||
|
||||
function screw_longer_than(x) = x <= 5 ? 5 : //! Returns shortest screw length longer or equal to x
|
||||
function screw_longer_than(x) = x <= 5 ? 5 : //! Returns the length of the shortest screw length longer or equal to x
|
||||
x <= 6 ? 6 :
|
||||
x <= 8 ? 8 :
|
||||
x <= 10 ? 10 :
|
||||
@@ -56,7 +56,7 @@ function screw_longer_than(x) = x <= 5 ? 5 : //! Returns shortest screw length
|
||||
x <= 16 ? 16 :
|
||||
ceil(x / 5) * 5;
|
||||
|
||||
function screw_shorter_than(x) = x >= 20 ? floor(x / 5) * 5 : //! Returns longest screw length shorter than or equal to x
|
||||
function screw_shorter_than(x) = x >= 20 ? floor(x / 5) * 5 : //! Returns the length of the longest screw shorter than or equal to x
|
||||
x >= 16 ? 16 :
|
||||
x >= 12 ? 12 :
|
||||
x >= 10 ? 10 :
|
||||
@@ -64,6 +64,14 @@ function screw_shorter_than(x) = x >= 20 ? floor(x / 5) * 5 : //! Returns longes
|
||||
x >= 6 ? 6 :
|
||||
5;
|
||||
|
||||
function screw_length(screw, thickness, washers, insert = false, nyloc = false, nut = false, longer = false) = //! Returns the length of the longest or shortest screw that will got through `thickness` and `washers` and possibly an `insert`, `nut` or `nyloc`
|
||||
let(washer = washers ? washers * washer_thickness(screw_washer(screw)) : 0,
|
||||
insert = insert ? insert_length(screw_insert(screw)) : 0,
|
||||
nut = nut || nyloc ? nut_thickness(screw_nut(screw), nyloc) : 0,
|
||||
total = thickness + washer + insert + nut
|
||||
)
|
||||
longer || nut || nyloc ? screw_longer_than(total) : screw_shorter_than(total);
|
||||
|
||||
function screw_smaller_than(d) = d >= 2.5 && d < 3 ? 2.5 : floor(d); // Largest diameter screw less than or equal to specified diameter
|
||||
|
||||
function screw_insert(screw, i = 0) = let(d = screw_radius(screw) * 2)
|
||||
@@ -262,7 +270,7 @@ module screw_countersink(type, drilled = true) { //! Countersink shape
|
||||
if(drilled)
|
||||
cylinder(h = head_height + eps, r1 = 0, r2 = head_rad + head_t);
|
||||
else
|
||||
intersection() {
|
||||
render() intersection() {
|
||||
cylinder(h = head_height + eps, r1 = 0, r2 = head_rad + head_t);
|
||||
|
||||
cylinder(h = head_height + eps, r = head_rad + eps);
|
||||
|
@@ -83,6 +83,7 @@ M5_cs_cap_screw = ["M5_cs_cap","M5 cs cap", hs_cs_cap,5,10.0, 0, 3.00,3.0
|
||||
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];
|
||||
M5_dome_screw = ["M5_dome", "M5 dome", hs_dome, 5, 9.5, 2.75, 1.56,3.0, 22, M5_washer, M5_nut, M5_tap_radius, M5_clearance_radius];
|
||||
|
||||
M2p5_pan_screw = ["M2p5_pan", "M2.5 pan", hs_pan, 2.5, 4.7, 1.7, 0, 0, 0, M2p5_washer, M2p5_nut, M2p5_tap_radius, M2p5_clearance_radius];
|
||||
M3_pan_screw = ["M3_pan", "M3 pan", hs_pan, 3, 5.4, 2.0, 0, 0, 0, M3_washer, M3_nut, M3_tap_radius, M3_clearance_radius];
|
||||
@@ -111,7 +112,7 @@ screw_lists = [
|
||||
[ 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],
|
||||
[ M2_cs_cap_screw, 0, M3_cs_cap_screw, M4_cs_cap_screw, M5_cs_cap_screw],
|
||||
[ M2_dome_screw, 0, M3_dome_screw, M4_dome_screw],
|
||||
[ M2_dome_screw, 0, M3_dome_screw, M4_dome_screw, M5_dome_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],
|
||||
[ No2_screw, 0, No4_screw, No6_screw, No6_cs_screw],
|
||||
|
@@ -71,15 +71,13 @@ use <nut.scad>
|
||||
use <washer.scad>
|
||||
|
||||
module ssr_assembly(type, screw, thickness) { //! Assembly with fasteners in place
|
||||
nut = screw_nut(screw);
|
||||
washer = screw_washer(screw);
|
||||
screw_length = screw_longer_than(2 * washer_thickness(washer) + thickness + ssr_base_t(type) + nut_thickness(nut, true));
|
||||
screw_length = screw_length(screw, thickness + ssr_base_t(type), 2, nyloc = true);
|
||||
|
||||
ssr(type);
|
||||
|
||||
ssr_hole_positions(type) {
|
||||
translate_z(ssr_base_t(type))
|
||||
nut_and_washer(nut, true);
|
||||
nut_and_washer(screw_nut(screw), true);
|
||||
|
||||
translate_z(-thickness)
|
||||
vflip()
|
||||
|
@@ -41,6 +41,8 @@ function vero_track_width(type) = vero_pitch(type) * 0.8; //! The width of th
|
||||
function vero_length(type) = vero_holes(type) * vero_pitch(type); //! Length of the board
|
||||
function vero_width(type) = vero_strips(type) * vero_pitch(type); //! Width of the board
|
||||
|
||||
function vero_size(type) = [vero_length(type), vero_width(type), vero_thickness(type)]; //! Board size
|
||||
|
||||
module solder_meniscus(type) {
|
||||
h = 1;
|
||||
r = vero_track_width(type) / 2;
|
||||
@@ -141,12 +143,11 @@ module vero_components(type, cutouts = false, angle = undef)
|
||||
|
||||
module vero_cutouts(type, angle = undef) vero_components(type, true, angle); //! Make cutouts to clear components
|
||||
|
||||
module veroboard_assembly(type, height, thickness, flip = false) //! Draw the assembly with components and fasteners in place
|
||||
assembly(vero_assembly(type)) {
|
||||
module veroboard_assembly(type, height, thickness, flip = false, ngb = false) //! Draw the assembly with components and fasteners in place
|
||||
assembly(vero_assembly(type), ngb = ngb) {
|
||||
screw = vero_screw(type);
|
||||
washer = screw_washer(screw);
|
||||
nut = screw_nut(screw);
|
||||
screw_length = screw_longer_than(height + thickness + vero_thickness(type) + 2 * washer_thickness(washer) + nut_thickness(nut, true));
|
||||
screw_length = screw_length(screw, height + thickness + vero_thickness(type), 2, nyloc = true);
|
||||
|
||||
translate_z(height) {
|
||||
veroboard(type);
|
||||
|