Compare commits
122 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
07766d8cf0 | ||
|
ceac5cdb27 | ||
|
c5b35daeac | ||
|
ffb4512523 | ||
|
35ffbad74c | ||
|
fb685a0f42 | ||
|
5d42b2e1ab | ||
|
2fe815d1bd | ||
|
5c577cccd0 | ||
|
1dbfafd366 | ||
|
68b3dfb098 | ||
|
25dceee20a | ||
|
d70ddf5359 | ||
|
70b60522ce | ||
|
ecba7eaea4 | ||
|
f751dd9a73 | ||
|
3f359f6839 | ||
|
3e5947c161 | ||
|
66dc430541 | ||
|
4dc83d62cb | ||
|
ebbec3c903 | ||
|
9944aab73e | ||
|
eb9bcf0ada | ||
|
ff5e8c0372 | ||
|
17ebf36e27 | ||
|
e38d9abfa0 | ||
|
fc7fd5482e | ||
|
cee1202fd9 | ||
|
6e342441c6 | ||
|
072c38f955 | ||
|
b342549d74 | ||
|
2b83a15e5d | ||
|
ab81c6538c | ||
|
27b0a442e4 | ||
|
38acef9e27 | ||
|
5415beb80d | ||
|
040985c0db | ||
|
0216093a68 | ||
|
30302431c0 | ||
|
1fb429e9a5 | ||
|
9571e68629 | ||
|
b01e6a673c | ||
|
9239c6da3c | ||
|
ba5e5fa390 | ||
|
c7dfdd0fb9 | ||
|
814ce4f15d | ||
|
f661cf6934 | ||
|
305d2146f2 | ||
|
e39ee1797d | ||
|
520569cb30 | ||
|
f73a7b46a2 | ||
|
fb9eca85c6 | ||
|
166ed05d4a | ||
|
ce6aec428d | ||
|
4e9d169c31 | ||
|
1810160103 | ||
|
0c9ae8d60c | ||
|
9a0bad4e61 | ||
|
90047815b0 | ||
|
b583202fb7 | ||
|
eac0086199 | ||
|
03beaec470 | ||
|
51c649cc53 | ||
|
5fa33d7c4d | ||
|
78ce51d045 | ||
|
23cbadf6df | ||
|
c9c2ffafba | ||
|
2e0e833d40 | ||
|
6c51f8726c | ||
|
0b035dbd15 | ||
|
34b58e3b64 | ||
|
df43fe7dc6 | ||
|
b5fe03fcb2 | ||
|
1658f6f0b4 | ||
|
7b126f9792 | ||
|
479207fd4f | ||
|
3ee55981f9 | ||
|
8c2b4a20fe | ||
|
1529759406 | ||
|
c4a986aa21 | ||
|
ebee729d08 | ||
|
90e7f1a315 | ||
|
e39af154bb | ||
|
933fea687c | ||
|
a7803b1efb | ||
|
1255e71271 | ||
|
b11c5914b3 | ||
|
ac60057801 | ||
|
332933a4fd | ||
|
6b0132c32e | ||
|
afac5f9737 | ||
|
8d8df3cb8a | ||
|
81eb183db9 | ||
|
c99ed98a64 | ||
|
7f65e5d539 | ||
|
ffb7f87cc5 | ||
|
d0513c7299 | ||
|
d1429a3b7d | ||
|
70513993bd | ||
|
9eb35accfd | ||
|
7276f18566 | ||
|
d944198dc4 | ||
|
04f2499a9e | ||
|
1eb8b378e9 | ||
|
362dbdb4fc | ||
|
57d223d84b | ||
|
699385342f | ||
|
547a418cea | ||
|
b6d25048bc | ||
|
4cdab218d9 | ||
|
b6147e5684 | ||
|
966ba536ed | ||
|
2419d50641 | ||
|
02211c2034 | ||
|
77d73b075d | ||
|
cb54a3131b | ||
|
3cf275579c | ||
|
fb41f218fe | ||
|
e6a26bc7b1 | ||
|
cb4fa40643 | ||
|
6a26903514 | ||
|
d08d949887 |
@@ -18,7 +18,7 @@
|
||||
//
|
||||
|
||||
//
|
||||
// Include this file to use the miniumum library plus screws, nuts and washers
|
||||
// Include this file to use the minimum library plus screws, nuts and washers
|
||||
//
|
||||
include <utils/core/core.scad>
|
||||
//
|
||||
|
@@ -33,7 +33,7 @@ $exploded = is_undef($explode) ? 0 : $explode; // 1 f
|
||||
layer_height = is_undef($layer_height) ? 0.25 : $layer_height; // layer heigth when printing
|
||||
extrusion_width = is_undef($extrusion_width) ? 0.5 : $extrusion_width; // filament width when printing
|
||||
nozzle = is_undef($nozzle) ? 0.45 : $nozzle; // 3D printer nozzle
|
||||
cnc_bit_r = is_undef($cnc_bit_r) ? 1.2 : $cnc_bit_r; // miniumum tool radius when milling 2D objects
|
||||
cnc_bit_r = is_undef($cnc_bit_r) ? 1.2 : $cnc_bit_r; // minimum tool radius when milling 2D objects
|
||||
pp1_colour = is_undef($pp1_colour) ? [0, 146/255, 0] : $pp1_colour; // printed part colour 1, RepRap logo colour
|
||||
pp2_colour = is_undef($pp2_colour) ? "red" : $pp2_colour; // printed part colour 2
|
||||
pp3_colour = is_undef($pp3_colour) ? "blue" : $pp3_colour; // printed part colour 3
|
||||
|
2
lib.scad
@@ -43,6 +43,7 @@ include <vitamins/ldrs.scad>
|
||||
include <vitamins/leadnuts.scad>
|
||||
include <vitamins/led_meter.scad>
|
||||
include <vitamins/light_strips.scad>
|
||||
include <vitamins/magnets.scad>
|
||||
include <vitamins/mains_sockets.scad>
|
||||
include <vitamins/modules.scad>
|
||||
include <vitamins/panel_meters.scad>
|
||||
@@ -53,6 +54,7 @@ include <vitamins/ring_terminals.scad>
|
||||
include <vitamins/rails.scad>
|
||||
include <vitamins/rod.scad>
|
||||
include <vitamins/scs_bearing_blocks.scad>
|
||||
include <vitamins/shaft_couplings.scad>
|
||||
include <vitamins/sheets.scad>
|
||||
include <vitamins/sk_brackets.scad>
|
||||
include <vitamins/spools.scad>
|
||||
|
BIN
libtest.png
Before Width: | Height: | Size: 813 KiB After Width: | Height: | Size: 851 KiB |
55
libtest.scad
@@ -17,6 +17,23 @@
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
//!# NopSCADlib
|
||||
//! An ever expanding library of parts modelled in OpenSCAD useful for 3D printers and enclosures for electronics, etc.
|
||||
//!
|
||||
//! It contains lots of vitamins (the RepRap term for non-printed parts), some general purpose printed parts and some utilities.
|
||||
//! There are also Python scripts to generate Bills of Materials (BOMs),
|
||||
//! STL files for all the printed parts, DXF files for CNC routed parts in a project and a manual containing assembly
|
||||
//! instructions and exploded views by scraping markdown embedded in OpenSCAD comments, [see scripts](scripts/readme.md).
|
||||
//!
|
||||
//! A simple example project can be found [here](examples/MainsBreakOutBox/readme.md).
|
||||
//!
|
||||
//! For more examples of what it can make see the [gallery](gallery/readme.md).
|
||||
//!
|
||||
//! The license is GNU General Public License v3.0, see [COPYING](COPYING).
|
||||
//!
|
||||
//! See [usage](docs/usage.md) for requirements, installation instructions and a usage guide.
|
||||
//!
|
||||
//! <img src="libtest.png" width="100%"/>
|
||||
//
|
||||
// This file shows all the parts in the library.
|
||||
//
|
||||
@@ -30,10 +47,12 @@ use <tests/bulldogs.scad>
|
||||
use <tests/buttons.scad>
|
||||
use <tests/cable_strips.scad>
|
||||
use <tests/cameras.scad>
|
||||
use <tests/camera_housing.scad>
|
||||
use <tests/circlips.scad>
|
||||
use <tests/components.scad>
|
||||
use <tests/d_connectors.scad>
|
||||
use <tests/displays.scad>
|
||||
use <tests/drag_chain.scad>
|
||||
use <tests/extrusions.scad>
|
||||
use <tests/extrusion_brackets.scad>
|
||||
use <tests/fans.scad>
|
||||
@@ -50,6 +69,7 @@ use <tests/LEDs.scad>
|
||||
use <tests/light_strips.scad>
|
||||
use <tests/linear_bearings.scad>
|
||||
use <tests/LED_meters.scad>
|
||||
use <tests/magnets.scad>
|
||||
use <tests/microswitches.scad>
|
||||
use <tests/modules.scad>
|
||||
use <tests/nuts.scad>
|
||||
@@ -58,6 +78,7 @@ use <tests/opengrab.scad>
|
||||
use <tests/panel_meters.scad>
|
||||
use <tests/PCBs.scad>
|
||||
use <tests/pillars.scad>
|
||||
use <tests/press_fit.scad>
|
||||
use <tests/PSUs.scad>
|
||||
use <tests/pulleys.scad>
|
||||
use <tests/rails.scad>
|
||||
@@ -67,6 +88,7 @@ use <tests/rod.scad>
|
||||
use <tests/screws.scad>
|
||||
use <tests/SCS_bearing_blocks.scad>
|
||||
use <tests/sealing_strip.scad>
|
||||
use <tests/shaft_couplings.scad>
|
||||
use <tests/sheets.scad>
|
||||
use <tests/SK_brackets.scad>
|
||||
use <tests/spades.scad>
|
||||
@@ -116,17 +138,20 @@ cable_grommets_y = 0;
|
||||
translate([x5, cable_grommets_y])
|
||||
cable_grommets();
|
||||
|
||||
translate([x5, cable_grommets_y + 50])
|
||||
feet();
|
||||
translate([x5 + 50, cable_grommets_y])
|
||||
ribbon_clamps();
|
||||
|
||||
translate([x5, cable_grommets_y + 75])
|
||||
translate([x5 + 95, cable_grommets_y])
|
||||
press_fits();
|
||||
|
||||
translate([x5, cable_grommets_y + 60])
|
||||
fixing_blocks();
|
||||
|
||||
translate([x5, cable_grommets_y + 100])
|
||||
translate([x5, cable_grommets_y + 90])
|
||||
corner_blocks();
|
||||
|
||||
translate([x5, cable_grommets_y + 150])
|
||||
ribbon_clamps();
|
||||
feet();
|
||||
|
||||
translate([x5 + 70, cable_grommets_y + 150])
|
||||
screw_knobs();
|
||||
@@ -271,8 +296,9 @@ translate([x1, leadnuts_y])
|
||||
|
||||
leds_y = 0;
|
||||
carriers_y = leds_y + 40;
|
||||
spades_y = carriers_y + 40;
|
||||
buttons_y = spades_y + 40;
|
||||
magnets_y = carriers_y + 40;
|
||||
spades_y = magnets_y + 20;
|
||||
buttons_y = spades_y + 20;
|
||||
jacks_y = buttons_y + 40;
|
||||
microswitches_y = jacks_y + 40;
|
||||
rockers_y = microswitches_y + 40;
|
||||
@@ -288,6 +314,9 @@ translate([x2 + 35, leds_y])
|
||||
translate([x2 + 8, carriers_y])
|
||||
carriers();
|
||||
|
||||
translate([x2, magnets_y])
|
||||
magnets();
|
||||
|
||||
translate([x2 + 20, carriers_y])
|
||||
led_meters();
|
||||
|
||||
@@ -341,6 +370,9 @@ translate([x3 + 170, veroboard_y + 16])
|
||||
translate([x3, d_connectors_y])
|
||||
d_connectors();
|
||||
|
||||
translate([x3 + 170, d_connectors_y - 10])
|
||||
camera_housings();
|
||||
|
||||
translate([x3, iecs_y])
|
||||
iecs();
|
||||
|
||||
@@ -390,12 +422,16 @@ translate([x4 + 200, belts_y + 58]) {
|
||||
|
||||
translate([0, 60])
|
||||
opengrab_test();
|
||||
|
||||
}
|
||||
|
||||
translate([x4 + 175, belts_y, -20])
|
||||
drag_chains();
|
||||
|
||||
translate([x4, rails_y + 130])
|
||||
rails();
|
||||
|
||||
translate([800, fans_y + 50])
|
||||
translate([770, fans_y + 50])
|
||||
cable_strips();
|
||||
|
||||
translate([x4, kp_pillow_blocks_y])
|
||||
@@ -407,6 +443,9 @@ translate([x4, sk_brackets_y])
|
||||
translate([x4, extrusion_brackets_y])
|
||||
extrusion_brackets();
|
||||
|
||||
translate([x4 + 120, extrusion_brackets_y])
|
||||
shaft_couplings();
|
||||
|
||||
translate([x4, scs_bearing_blocks_y])
|
||||
scs_bearing_blocks();
|
||||
|
||||
|
392
printed/camera_housing.scad
Normal file
@@ -0,0 +1,392 @@
|
||||
//
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
//
|
||||
//! Housings for PCB cameras.
|
||||
//
|
||||
include <../core.scad>
|
||||
include <../vitamins/cameras.scad>
|
||||
use <../vitamins/pcb.scad>
|
||||
use <../vitamins/insert.scad>
|
||||
|
||||
wall = 1.75;
|
||||
min_wall = 2 * extrusion_width;
|
||||
clearance = 0.2;
|
||||
|
||||
connector_size = [23, 6, 2.65]; // Worst case size of flat flex connector
|
||||
|
||||
cam_back_clearance = round_to_layer(1.5); // Clearance for components on the back of the pcb
|
||||
cam_back_overlap = 1; // How much the back overlaps the edge of the pcb
|
||||
cam_back_wall = min_wall;
|
||||
|
||||
function cam_front_clearance(cam) = round_to_layer(camera_connector_size(cam).z + clearance);
|
||||
|
||||
function cam_back_size(cam) = let(
|
||||
pcb = camera_pcb(cam),
|
||||
pcb_size = pcb_size(pcb),
|
||||
nut = screw_nut(pcb_screw(pcb)),
|
||||
holes = [for(h = pcb_holes(pcb)) pcb_coord(pcb, h).x],
|
||||
pitch = max(holes) - min(holes),
|
||||
length = pitch + 2 * (nut_radius(nut) + min_wall),
|
||||
width = pcb_size.y + (length - pcb_size.x) * cos(30)
|
||||
) [length, width, wall + max(connector_size.z, cam_back_clearance + nut_trap_depth(nut))];
|
||||
|
||||
|
||||
function cam_front_size(cam) = cam_back_size(cam) + [ //! Outside dimensions of the case
|
||||
2 * (wall + clearance),
|
||||
2 * (wall + clearance),
|
||||
pcb_thickness(camera_pcb(cam)) + cam_front_clearance(cam) + wall
|
||||
];
|
||||
|
||||
hinge_screw = M2_cap_screw;
|
||||
hinge_nut = screw_nut(hinge_screw);
|
||||
hinge_screw_length = 12;
|
||||
|
||||
hinge_r = nut_trap_radius(hinge_nut) + 3 * extrusion_width;
|
||||
hinge_h = wall + nut_trap_depth(hinge_nut);
|
||||
hinge_offset = hinge_r + 1;
|
||||
|
||||
bracket_screw = M3_dome_screw;
|
||||
|
||||
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));
|
||||
|
||||
function hinge_z(cam) = cam_screw_length(cam) - hinge_r;
|
||||
|
||||
module cam_holes(cam) {
|
||||
pcb = camera_pcb(cam);
|
||||
lens_y = camera_lens_offset(cam).y;
|
||||
two_holes = !!len([for (h = pcb_holes(pcb)) if(abs(pcb_coord(pcb, h).y - lens_y) < 1) true]);
|
||||
pcb_screw_positions(pcb) // screw holes
|
||||
if($i > 1 || !two_holes)
|
||||
children();
|
||||
}
|
||||
|
||||
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;
|
||||
hole_r2 = 5 / 2;
|
||||
thickness = 3;
|
||||
flutes = 8;
|
||||
angle = 180 / flutes;
|
||||
x = rad / (sin(angle / 2) + cos(angle / 2));
|
||||
r = x * sin(angle / 2);
|
||||
|
||||
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 + angle])
|
||||
translate([x, 0])
|
||||
circle(r);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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_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);
|
||||
pcb_size = pcb_size(pcb);
|
||||
lens_offset = camera_lens_offset(cam);
|
||||
screw = pcb_screw(pcb);
|
||||
|
||||
shelf = front.z - back.z;
|
||||
|
||||
connector_slot = connector_size + 2 * [clearance, 0, layer_height];
|
||||
rad = wall;
|
||||
led_hole_r = 1;
|
||||
led_clearance = [5, 2, 1 * 2];
|
||||
res_clearance = [3.5, 2, 1 * 2];
|
||||
|
||||
conn_pos = camera_connector_pos(cam);
|
||||
conn = camera_connector_size(cam);
|
||||
sensor_length = conn_pos.y + conn.y / 2 - lens_offset.y + clearance;
|
||||
|
||||
module hinge_pos()
|
||||
if(!is_undef(hinge))
|
||||
rotate(hinge * 90)
|
||||
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);
|
||||
|
||||
translate_z(rad)
|
||||
sphere(rad);
|
||||
|
||||
cylinder(r = rad * (sqrt(2) - 1), h = eps);
|
||||
}
|
||||
|
||||
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([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);
|
||||
|
||||
hflip()
|
||||
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));
|
||||
|
||||
module camera_bracket_screw_positions(cam) { //! Position children at the bracket screw positions
|
||||
r = washer_radius(screw_washer(bracket_screw)) + 0.5;
|
||||
wide = bracket_thickness(cam) == wall;
|
||||
pitch = wide ? cam_front_size(cam).x / 2 - r : hinge_h + 1 + r;
|
||||
|
||||
for(side = [-1, 1])
|
||||
translate([side * pitch, 0])
|
||||
children();
|
||||
}
|
||||
|
||||
module camera_bracket_position(cam) //! Position children at the bracket position
|
||||
translate([0, cam_front_size(cam).y / 2 + hinge_offset])
|
||||
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);
|
||||
}
|
||||
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()
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
module camera_assembly(cam, angle = 0) //! Camera case assembly
|
||||
assembly(str("camera_", cam[0])) {
|
||||
front = cam_front_size(cam);
|
||||
screw = pcb_screw(camera_pcb(cam));
|
||||
nut = screw_nut(screw);
|
||||
screw_length = cam_screw_length(cam);
|
||||
hinge_z = hinge_z(cam);
|
||||
hinge_pos = [0, front.y / 2 + hinge_offset, -hinge_r];
|
||||
|
||||
camera_bracket_position(cam) {
|
||||
nut = screw_nut(hinge_screw);
|
||||
|
||||
stl_colour(pp1_colour) render()
|
||||
camera_bracket(cam);
|
||||
|
||||
translate([-hinge_h, 0, hinge_z(cam)])
|
||||
rotate([-90, 0, 90]) {
|
||||
vflip()
|
||||
translate_z(2 * hinge_h - nut_trap_depth(nut))
|
||||
nut(nut, true);
|
||||
|
||||
screw_and_washer(hinge_screw, screw_longer_than(2 * hinge_h));
|
||||
}
|
||||
}
|
||||
|
||||
translate_z(hinge_z(cam) + hinge_r)
|
||||
translate(hinge_pos)
|
||||
rotate([-angle, 0, 0])
|
||||
translate(-hinge_pos) {
|
||||
translate_z(cam_back_size(cam).z - front.z)
|
||||
camera(cam);
|
||||
|
||||
stl_colour(pp1_colour) render()
|
||||
translate_z(-front.z)
|
||||
camera_back(cam);
|
||||
|
||||
cam_holes(cam) {
|
||||
screw_and_washer(screw, screw_length);
|
||||
|
||||
translate_z(-front.z + nut_trap_depth(nut))
|
||||
vflip()
|
||||
nut(nut, true);
|
||||
}
|
||||
|
||||
*translate(camera_lens_offset(cam))
|
||||
translate_z(1.5)
|
||||
stl_colour(pp1_colour) render()
|
||||
rpi_camera_focus_ring_stl();
|
||||
|
||||
stl_colour(pp2_colour) render()
|
||||
hflip()
|
||||
camera_front(cam, 0);
|
||||
}
|
||||
}
|
||||
|
||||
module camera_fastened_assembly(cam, thickness, angle = 0) {
|
||||
camera_assembly(cam, angle);
|
||||
|
||||
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));
|
||||
vflip()
|
||||
translate_z(thickness)
|
||||
screw_and_washer(bracket_screw, screw_length);
|
||||
|
||||
translate_z(t)
|
||||
nut_and_washer(nut, true);
|
||||
}
|
||||
}
|
||||
|
||||
module camera_back_rpi_camera_stl() camera_back(rpi_camera);
|
||||
module camera_back_rpi_camera_v1_stl() camera_back(rpi_camera_v1);
|
||||
module camera_back_rpi_camera_v2_stl() camera_back(rpi_camera_v2);
|
||||
|
||||
module camera_front_rpi_camera_stl() camera_front(rpi_camera);
|
||||
module camera_front_rpi_camera_v1_stl() camera_front(rpi_camera_v1);
|
||||
module camera_front_rpi_camera_v2_stl() camera_front(rpi_camera_v2);
|
||||
|
||||
module camera_bracket_rpi_camera_stl() camera_bracket(rpi_camera);
|
||||
module camera_bracket_rpi_camera_v1_stl() camera_bracket(rpi_camera_v1);
|
||||
module camera_bracket_rpi_camera_v2_stl() camera_bracket(rpi_camera_v2);
|
||||
|
||||
module camera_rpi_camera_assembly() camera_assembly(rpi_camera);
|
||||
module camera_rpi_camera_v1_assembly() camera_assembly(rpi_camera_v1);
|
||||
module camera_rpi_camera_v2_assembly() camera_assembly(rpi_camera_v2);
|
||||
|
||||
module camera_housing(cam) {
|
||||
front = cam_front_size(cam);
|
||||
|
||||
camera_front(cam, 0);
|
||||
|
||||
translate([front.x, 0])
|
||||
camera_back(cam);
|
||||
|
||||
translate([-front.x / 2 - 2 - hinge_r, 0])
|
||||
rotate(90)
|
||||
camera_bracket(cam);
|
||||
}
|
||||
|
||||
cam = rpi_camera_v2;
|
||||
if($preview)
|
||||
camera_fastened_assembly(cam, 3);
|
||||
else
|
||||
camera_housing(cam);
|
@@ -74,7 +74,7 @@ module door_hinge(door_thickness) { //! Generates STL fo
|
||||
square([1, thickness + door_thickness]);
|
||||
}
|
||||
translate([dia / 2, thickness + door_thickness / 2])
|
||||
teardrop(r = screw_clearance_radius(pin_screw), h = 0);
|
||||
teardrop_plus(r = screw_clearance_radius(pin_screw), h = 0);
|
||||
}
|
||||
linear_extrude(thickness)
|
||||
difference() {
|
||||
@@ -127,7 +127,7 @@ module door_hinge_stat_stl() { //! Generates the STL for the stationary part
|
||||
square([dia, 1], center = true);
|
||||
}
|
||||
translate([0, dia / 2 + stat_clearance])
|
||||
teardrop(r = screw_clearance_radius(pin_screw), h = 0);
|
||||
teardrop_plus(r = screw_clearance_radius(pin_screw), h = 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
308
printed/drag_chain.scad
Normal file
@@ -0,0 +1,308 @@
|
||||
//
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
//
|
||||
//! Parametric cable drag chain to limit the bend radius of a cable run.
|
||||
//!
|
||||
//! Each link has a maximum bend angle of 45°, so the mininium radius is proportional to the link length.
|
||||
//!
|
||||
//! The travel property is how far it can move in each direction, i.e. half the maximum travel if the chain is mounted in the middle of the travel.
|
||||
//!
|
||||
//! The ends can have screw lugs with four screw positions to choose from, specified by a list of two arrays of four bools.
|
||||
//! If none are enabled then a child object is expected to customise the end and this gets unioned with the blank end.
|
||||
//! If both ends are customised then two children are expected.
|
||||
//! Each child is called twice, once with ```$fasteners``` set to 0 to augment the STL and again with ```$fasteners``` set to 1 to add
|
||||
//! to the assembly, for example to add inserts.
|
||||
//
|
||||
|
||||
include <../core.scad>
|
||||
use <../utils/horiholes.scad>
|
||||
use <../utils/maths.scad>
|
||||
|
||||
clearance = 0.1;
|
||||
|
||||
function drag_chain_name(type) = type[0]; //! The name to allow more than one in a project
|
||||
function drag_chain_size(type) = type[1]; //! The internal size and link length
|
||||
function drag_chain_travel(type) = type[2]; //! X travel
|
||||
function drag_chain_wall(type) = type[3]; //! Side wall thickness
|
||||
function drag_chain_bwall(type) = type[4]; //! Bottom wall
|
||||
function drag_chain_twall(type) = type[5]; //! Top wall
|
||||
function drag_chain_screw(type) = type[6]; //! Mounting screw for the ends
|
||||
function drag_chain_screw_lists(type) = type[7]; //! Two lists of four bools to say which screws positions are used
|
||||
|
||||
function drag_chain_clearance() = clearance; //! Clearance around joints.
|
||||
|
||||
function drag_chain_radius(type) = //! The bend radius at the pivot centres
|
||||
let(s = drag_chain_size(type))
|
||||
s.x / 2 / sin(360 / 16);
|
||||
|
||||
function drag_chain_z(type) = //! Outside dimension of a 180 bend
|
||||
let(os = drag_chain_outer_size(type), s = drag_chain_size(type))
|
||||
2 * drag_chain_radius(type) + os.z;
|
||||
|
||||
function drag_chain(name, size, travel, wall = 1.6, bwall = 1.5, twall = 1.5, screw = M2_cap_screw, screw_lists = [[1,0,0,1],[1,0,0,1]]) = //! Constructor
|
||||
[name, size, travel, wall, bwall, twall, screw, screw_lists];
|
||||
|
||||
function drag_chain_outer_size(type) = //! Link outer dimensions
|
||||
let(s = drag_chain_size(type), z = s.z + drag_chain_bwall(type) + drag_chain_twall(type))
|
||||
[s.x + z, s.y + 4 * drag_chain_wall(type) + 2 * clearance, z];
|
||||
|
||||
function screw_lug_radius(screw) = //! Radius if a screw lug
|
||||
corrected_radius(screw_clearance_radius(screw)) + 3.1 * extrusion_width;
|
||||
|
||||
module screw_lug(screw, h = 0) //! Create a D shaped lug for a screw
|
||||
extrude_if(h, center = false)
|
||||
difference() {
|
||||
r = screw_lug_radius(screw);
|
||||
hull() {
|
||||
circle4n(r);
|
||||
|
||||
translate([-r, -r])
|
||||
square([2 * r, eps]);
|
||||
}
|
||||
poly_circle(screw_clearance_radius(screw));
|
||||
}
|
||||
|
||||
function bool2int(b) = b ? 1 : 0;
|
||||
|
||||
module drag_chain_screw_positions(type, end) {//! Place children at the screw positions, end = 0 for the start, 1 for the end
|
||||
r = screw_lug_radius(drag_chain_screw(type));
|
||||
s = drag_chain_size(type);
|
||||
os = drag_chain_outer_size(type);
|
||||
R = os.z / 2;
|
||||
x0 = end ? R + norm([drag_chain_cam_x(type), R - drag_chain_twall(type)]) + clearance + r : r;
|
||||
x1 = end ? os.x - r : os.x - 2 * R - clearance - r;
|
||||
for(i = [0 : 3]) {
|
||||
x = i % 2;
|
||||
y = bool2int(i > 1);
|
||||
if(drag_chain_screw_lists(type)[bool2int(end)][i])
|
||||
translate([(x0 + x1) / 2, 0])
|
||||
mirror([x, 0])
|
||||
mirror([0, y])
|
||||
translate([(x1 - x0) / 2, s.y / 2 + r])
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
function drag_chain_cam_x(type) = // how far the cam sticks out
|
||||
let(s = drag_chain_size(type),
|
||||
r = drag_chain_outer_size(type).z / 2,
|
||||
wall = drag_chain_wall(type),
|
||||
cam_r = s.x - 2 * clearance - wall - r, // inner_x_normal - clearance - r
|
||||
twall = drag_chain_twall(type)
|
||||
) min(sqrt(max(sqr(cam_r) - sqr(r - twall), 0)), r);
|
||||
|
||||
|
||||
module drag_chain_link(type, start = false, end = false) { //! One link of the chain, special case for start and end
|
||||
stl(str(drag_chain_name(type), "_drag_chain_link", start ? "_start" : end ? "_end" : ""));
|
||||
|
||||
s = drag_chain_size(type);
|
||||
wall = drag_chain_wall(type);
|
||||
bwall = drag_chain_bwall(type);
|
||||
twall = drag_chain_twall(type);
|
||||
os = drag_chain_outer_size(type);
|
||||
r = os.z / 2;
|
||||
pin_r = r / 2;
|
||||
|
||||
socket_x = r;
|
||||
pin_x = socket_x + s.x;
|
||||
|
||||
outer_normal_x = pin_x - r - clearance; // s.x - clearance
|
||||
outer_end_x = end ? os.x : outer_normal_x;
|
||||
|
||||
inner_x = start ? 0 : outer_normal_x - wall; // s.x - clearance - wall
|
||||
|
||||
roof_x_normal = 2 * r - twall;
|
||||
roof_x = start ? 0 : roof_x_normal;
|
||||
|
||||
floor_x = start ? 0 : 2 * r;
|
||||
cam_x = drag_chain_cam_x(type);
|
||||
assert(r + norm([drag_chain_cam_x(type), r - drag_chain_twall(type)]) + clearance <= inner_x || start, "Link must be longer");
|
||||
|
||||
difference() {
|
||||
union() {
|
||||
for(side = [-1, 1])
|
||||
rotate([90, 0, 0]) {
|
||||
// Outer cheeks
|
||||
translate_z(side * (os.y / 2 - wall / 2))
|
||||
linear_extrude(wall, center = true)
|
||||
difference() {
|
||||
hull() {
|
||||
if(start)
|
||||
square([eps, os.z]);
|
||||
else
|
||||
translate([socket_x, r])
|
||||
rotate(180)
|
||||
teardrop(r = r, h = 0);
|
||||
|
||||
translate([outer_end_x - eps, 0])
|
||||
square([eps, os.z]);
|
||||
}
|
||||
if(!start)
|
||||
translate([socket_x, r])
|
||||
horihole(pin_r, r);
|
||||
}
|
||||
// Inner cheeks
|
||||
translate_z(side * (s.y / 2 + wall / 2))
|
||||
linear_extrude(wall, center = true)
|
||||
difference() {
|
||||
union() {
|
||||
hull() {
|
||||
if(!end) {
|
||||
translate([pin_x, r])
|
||||
rotate(180)
|
||||
teardrop(r = r, h = 0);
|
||||
|
||||
translate([pin_x, twall])
|
||||
square([cam_x, eps]);
|
||||
}
|
||||
else
|
||||
translate([os.x - eps, 0])
|
||||
square([eps, os.z]);
|
||||
|
||||
translate([inner_x, 0])
|
||||
square([eps, os.z]);
|
||||
}
|
||||
}
|
||||
// Cutout for top wall
|
||||
if(!end)
|
||||
intersection() {
|
||||
translate([pin_x - r, 0])
|
||||
square([3 * r, twall]); // When straight
|
||||
|
||||
translate([pin_x, r])
|
||||
rotate(-45)
|
||||
translate([-r + roof_x_normal, -r - twall]) // When bent fully
|
||||
square(os.z);
|
||||
}
|
||||
}
|
||||
// Pin
|
||||
if(!end)
|
||||
translate([pin_x, r, side * (s.y / 2 + wall + clearance)])
|
||||
horicylinder(r = pin_r, z = r, h = 2 * wall);
|
||||
|
||||
// Cheek joint
|
||||
translate([inner_x, 0, side * (s.y / 2 + wall) - 0.5])
|
||||
cube([outer_end_x - inner_x, os.z, 1]);
|
||||
}
|
||||
|
||||
// Roof, actually the floor when printed
|
||||
roof_end = end ? s.x + 2 * r : s.x + r - twall - clearance;
|
||||
translate([roof_x, -s.y / 2 - 0.5])
|
||||
cube([roof_end - roof_x , s.y + 1, twall]);
|
||||
|
||||
translate([roof_x, -os.y / 2 + 0.5])
|
||||
cube([s.x - clearance - roof_x, os.y - 1, twall]);
|
||||
|
||||
// Floor, actually the roof when printed
|
||||
floor_end = end ? s.x + 2 * r : s.x + r;
|
||||
translate([floor_x, -s.y / 2 - wall, os.z - bwall])
|
||||
cube([floor_end - floor_x, s.y + 2 * wall, bwall]);
|
||||
|
||||
translate([floor_x, -os.y / 2 + 0.5, os.z - bwall])
|
||||
cube([s.x - floor_x - clearance, os.y -1, bwall]);
|
||||
|
||||
if(start || end) {
|
||||
drag_chain_screw_positions(type, end)
|
||||
screw_lug(drag_chain_screw(type), os.z);
|
||||
|
||||
children();
|
||||
}
|
||||
}
|
||||
if(start || end)
|
||||
translate_z(-eps)
|
||||
drag_chain_screw_positions(type, end)
|
||||
poly_cylinder(r = screw_clearance_radius(drag_chain_screw(type)), h = os.z + 2 * eps, center = false);
|
||||
|
||||
}
|
||||
|
||||
if(show_supports() && !end) {
|
||||
for(side = [-1, 1]) {
|
||||
w = 2.1 * extrusion_width;
|
||||
translate([s.x + r + cam_x - w / 2, side * (s.y / 2 + wall / 2), twall / 2])
|
||||
cube([w, wall, twall], center = true);
|
||||
|
||||
h = round_to_layer(r - pin_r / sqrt(2));
|
||||
y = s.y / 2 + max(wall + w / 2 + clearance, 2 * wall + clearance - w / 2);
|
||||
translate([s.x + r, side * y, h / 2])
|
||||
cube([pin_r * sqrt(2), w, h], center = true);
|
||||
|
||||
gap = cam_x - pin_r / sqrt(2) + extrusion_width;
|
||||
translate([s.x + r + cam_x - gap / 2, side * (s.y / 2 + wall + clearance / 2), layer_height / 2])
|
||||
cube([gap, 2 * wall + clearance, layer_height], center = true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! 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
|
||||
s = drag_chain_size(type);
|
||||
x = (1 + exploded()) * s.x;
|
||||
r = drag_chain_radius(type) * x / s.x;
|
||||
travel = drag_chain_travel(type);
|
||||
links = ceil(travel / s.x);
|
||||
actual_travel = links * s.x;
|
||||
z = drag_chain_outer_size(type).z;
|
||||
|
||||
zb = z / 2; // z of bottom track
|
||||
c = [actual_travel / 2 + pos / 2, 0, r + zb]; // centre of bend
|
||||
|
||||
points = [ // Calculate list of hinge points
|
||||
for(i = 0, p = [0, 0, z / 2 + 2 * r]; i < links + 5;
|
||||
i = i + 1,
|
||||
dx = p.z > c.z ? x : -x,
|
||||
p = max(p.x + dx, p.x) <= c.x ? p + [dx, 0, 0] // Straight sections
|
||||
: let(q = circle_intersect(p, x, c, r))
|
||||
q.x <= c.x ? [p.x - sqrt(sqr(x) - sqr(p.z - zb)), 0, zb] // Transition back to straight
|
||||
: q) // Circular section
|
||||
p
|
||||
];
|
||||
npoints = len(points);
|
||||
|
||||
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)
|
||||
let($fasteners = 0) children();
|
||||
let($fasteners = 1) children();
|
||||
}
|
||||
|
||||
screws = drag_chain_screw_lists(type);
|
||||
custom_start = screws[0] == [0, 0, 0, 0];
|
||||
custom_end = screws[1] == [0, 0, 0, 0];
|
||||
assert($children == bool2int(custom_start) + bool2int(custom_end), "wrong number of children for end customisation");
|
||||
assembly(str(drag_chain_name(type), "_drag_chain")) {
|
||||
for(i = [0 : npoints - 2]) let(v = points[i+1] - points[i])
|
||||
translate(points[i])
|
||||
rotate([0, -atan2(v.z, v.x), 0])
|
||||
link(i);
|
||||
|
||||
translate(points[0] - [x, 0, 0])
|
||||
link(-1)
|
||||
if(custom_start)
|
||||
children(0);
|
||||
|
||||
translate(points[npoints - 1])
|
||||
hflip()
|
||||
link(npoints - 1)
|
||||
if(custom_end)
|
||||
children(custom_start ? 1 : 0);
|
||||
}
|
||||
}
|
50
printed/press_fit.scad
Normal file
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
//
|
||||
//! Utility for making printed press fit connectors to join printed parts.
|
||||
//!
|
||||
//! Add solvent or glue to make a permanent fixture.
|
||||
//
|
||||
include <../core.scad>
|
||||
|
||||
interference = 0.0;
|
||||
|
||||
bridge_droop = layer_height; //sqrt(4 * layer_height * filament_width / PI) - layer_height;
|
||||
|
||||
module press_fit_socket(w = 5, h = 50, horizontal = false) { //! Make a square hole to accept a peg
|
||||
h = horizontal ? h : h + bridge_droop;
|
||||
|
||||
cube([w, w, 2 * h], center = true);
|
||||
}
|
||||
|
||||
module press_fit_peg(h, w = 5, horizontal = false) { //! Make a rounded chamfered peg for easy insertion
|
||||
module chamfered_square(w, horizontal) {
|
||||
h = horizontal ? w - bridge_droop : w;
|
||||
rounded_square([w, h], 1);
|
||||
}
|
||||
|
||||
translate_z(-eps)
|
||||
linear_extrude(height = h + eps - layer_height)
|
||||
chamfered_square(w + interference, horizontal);
|
||||
|
||||
translate_z(h - layer_height - eps)
|
||||
linear_extrude(height = layer_height + eps)
|
||||
chamfered_square(w - layer_height, horizontal);
|
||||
}
|
@@ -24,69 +24,72 @@ include <../core.scad>
|
||||
use <../vitamins/insert.scad>
|
||||
use <../vitamins/cable_strip.scad>
|
||||
|
||||
wall = 2;
|
||||
wall = 1.6;
|
||||
min_wall = 2 * extrusion_width;
|
||||
screw = M3_cap_screw;
|
||||
insert = screw_insert(screw);
|
||||
screw_depth = insert_length(insert) + 1;
|
||||
|
||||
function ribbon_clamp_hole_pitch(ways) = ribbon_clamp_slot(ways) + 2 * min_wall + 2 * corrected_radius(insert_hole_radius(insert)); //! Hole pitch
|
||||
function ribbon_clamp_width() = 2 * (insert_hole_radius(insert) + wall); //! Width
|
||||
function ribbon_clamp_length(ways) = ribbon_clamp_hole_pitch(ways) + ribbon_clamp_width(); //! Length given ways
|
||||
function ribbon_clamp_height() = screw_depth + 1; //! Height
|
||||
function ribbon_clamp_screw_depth(screw = screw) = insert_length(screw_insert(screw)) + 1;
|
||||
function ribbon_clamp_hole_pitch(ways, screw = screw) =
|
||||
ribbon_clamp_slot(ways) + 2 * min_wall + 2 * corrected_radius(insert_hole_radius(screw_insert(screw))); //! Hole pitch
|
||||
|
||||
module ribbon_clamp_hole_positions(ways, side = undef) //! Place children at hole positions
|
||||
function ribbon_clamp_width(screw = screw) = 2 * (insert_hole_radius(screw_insert(screw)) + wall); //! Width
|
||||
function ribbon_clamp_length(ways, screw = screw) = ribbon_clamp_hole_pitch(ways, screw) + ribbon_clamp_width(screw); //! Length given ways
|
||||
function ribbon_clamp_height(screw = screw) = ribbon_clamp_screw_depth(screw) + 1; //! Height
|
||||
|
||||
module ribbon_clamp_hole_positions(ways, screw = screw, side = undef) //! Place children at hole positions
|
||||
for(x = is_undef(side) ? [-1, 1] : side)
|
||||
translate([x * ribbon_clamp_hole_pitch(ways) / 2, 0])
|
||||
translate([x * ribbon_clamp_hole_pitch(ways, screw) / 2, 0])
|
||||
children();
|
||||
|
||||
module ribbon_clamp_holes(ways, h = 20) //! Drill screw holes
|
||||
ribbon_clamp_hole_positions(ways)
|
||||
module ribbon_clamp_holes(ways, h = 20, screw = screw) //! Drill screw holes
|
||||
ribbon_clamp_hole_positions(ways, screw)
|
||||
drill(screw_clearance_radius(screw), h);
|
||||
|
||||
module ribbon_clamp(ways) { //! Generate STL for given number of ways
|
||||
stl(str("ribbon_clamp_", ways));
|
||||
module ribbon_clamp(ways, screw = screw) { //! Generate STL for given number of ways
|
||||
screw_d = screw_radius(screw) * 2;
|
||||
stl(str("ribbon_clamp_", ways, screw_d != 3 ? str("_", screw_d) : ""));
|
||||
|
||||
pitch = ribbon_clamp_hole_pitch(ways);
|
||||
d = ribbon_clamp_width();
|
||||
h = ribbon_clamp_height();
|
||||
t = h - ribbon_clamp_slot_depth() - wall;
|
||||
pitch = ribbon_clamp_hole_pitch(ways, screw);
|
||||
d = ribbon_clamp_width(screw);
|
||||
h = ribbon_clamp_height(screw);
|
||||
t = round_to_layer(ribbon_clamp_slot_depth() + wall);
|
||||
insert = screw_insert(screw);
|
||||
|
||||
difference() {
|
||||
union() {
|
||||
hull() {
|
||||
translate_z(h - t / 2)
|
||||
cube([ribbon_clamp_hole_pitch(ways), d, t], center = true);
|
||||
cube([ribbon_clamp_hole_pitch(ways, screw), d, t], center = true);
|
||||
|
||||
translate_z(1)
|
||||
cube([pitch, max(wall, d - 2 * (h - t)), 2], center = true);
|
||||
}
|
||||
ribbon_clamp_hole_positions(ways, -1)
|
||||
ribbon_clamp_hole_positions(ways, screw, -1)
|
||||
cylinder(d = d, h = h);
|
||||
|
||||
ribbon_clamp_hole_positions(ways, 1)
|
||||
ribbon_clamp_hole_positions(ways, screw, 1)
|
||||
cylinder(d = d, h = h);
|
||||
|
||||
}
|
||||
|
||||
translate_z(h)
|
||||
cube([ribbon_clamp_slot(ways), d + 1, ribbon_clamp_slot_depth() * 2], center = true);
|
||||
|
||||
ribbon_clamp_hole_positions(ways)
|
||||
ribbon_clamp_hole_positions(ways, screw)
|
||||
translate_z(h)
|
||||
rotate(22.5)
|
||||
insert_hole(insert, screw_depth - insert_length(insert));
|
||||
insert_hole(insert, ribbon_clamp_screw_depth(screw) - insert_length(insert));
|
||||
}
|
||||
}
|
||||
|
||||
module ribbon_clamp_assembly(ways) pose([55, 180, 25]) //! Printed part with inserts in place
|
||||
assembly(str("ribbon_clamp_", ways)) {
|
||||
h = ribbon_clamp_height();
|
||||
module ribbon_clamp_assembly(ways, screw = screw) pose([55, 180, 25]) //! Printed part with inserts in place
|
||||
assembly(let(screw_d = screw_radius(screw) * 2)str("ribbon_clamp_", ways, screw_d != 3 ? str("_", screw_d) : "")) {
|
||||
h = ribbon_clamp_height(screw);
|
||||
insert = screw_insert(screw);
|
||||
|
||||
stl_colour(pp1_colour) render()
|
||||
translate_z(h) vflip() ribbon_clamp(ways);
|
||||
translate_z(h) vflip() ribbon_clamp(ways, screw);
|
||||
|
||||
ribbon_clamp_hole_positions(ways)
|
||||
ribbon_clamp_hole_positions(ways, screw)
|
||||
vflip()
|
||||
insert(insert);
|
||||
}
|
||||
@@ -99,20 +102,28 @@ module ribbon_clamp_fastened_assembly(ways, thickness, screw = screw) { //! Clam
|
||||
vitamin(str(": Tape self amalgamating silicone ",tape_l," x 25mm"));
|
||||
|
||||
washer = screw_washer(screw);
|
||||
screw_length = screw_shorter_than(2 * washer_thickness(washer) + thickness + screw_depth);
|
||||
screw_length = screw_shorter_than(2 * washer_thickness(washer) + thickness + ribbon_clamp_screw_depth(screw));
|
||||
|
||||
ribbon_clamp_assembly(ways);
|
||||
ribbon_clamp_assembly(ways, screw);
|
||||
|
||||
color("red") translate_z(tape_thickness / 2)
|
||||
cube([tape_l, tape_width, tape_thickness], center = true);
|
||||
|
||||
ribbon_clamp_hole_positions(ways)
|
||||
ribbon_clamp_hole_positions(ways, screw)
|
||||
vflip()
|
||||
translate_z(thickness)
|
||||
screw_and_washer(screw, screw_length, true);
|
||||
}
|
||||
|
||||
module ribbon_clamp_20_stl() ribbon_clamp(20);
|
||||
module ribbon_clamp_8_2_stl() ribbon_clamp(8, M2_dome_screw);
|
||||
module ribbon_clamp_7_2_stl() ribbon_clamp(8, M2_dome_screw);
|
||||
|
||||
//! * Place inserts into the holes and press home with a soldering iron with a conical bit heated to 200°C.
|
||||
module ribbon_clamp_20_assembly() ribbon_clamp_assembly(20);
|
||||
|
||||
//! * Place inserts into the holes and press home with a soldering iron with a conical bit heated to 200°C.
|
||||
module ribbon_clamp_8_2_assembly() ribbon_clamp_assembly(8, M2_dome_screw);
|
||||
|
||||
//! * Place inserts into the holes and press home with a soldering iron with a conical bit heated to 200°C.
|
||||
module ribbon_clamp_7_2_assembly() ribbon_clamp_assembly(8, M2_dome_screw);
|
||||
|
527
readme.md
@@ -1,10 +1,12 @@
|
||||
# NopSCADlib
|
||||
An ever expanding library of parts modelled in OpenSCAD useful for 3D printers and enclosures for electronics, etc.
|
||||
|
||||
It contains lots of vitamins (the RepRap term for non-printed parts), some general purpose printed parts and
|
||||
some utilities. There are also Python scripts to generate Bills of Materials (BOMs),
|
||||
STL files for all the printed parts, DXF files for CNC routed parts in a project and a manual containing assembly
|
||||
instructions and exploded views by scraping markdown embedded in OpenSCAD comments, [see scripts](scripts/readme.md). A simple example project can be found [here](examples/MainsBreakOutBox/readme.md).
|
||||
It contains lots of vitamins (the RepRap term for non-printed parts), some general purpose printed parts and some utilities.
|
||||
There are also Python scripts to generate Bills of Materials (BOMs),
|
||||
STL files for all the printed parts, DXF files for CNC routed parts in a project and a manual containing assembly
|
||||
instructions and exploded views by scraping markdown embedded in OpenSCAD comments, [see scripts](scripts/readme.md).
|
||||
|
||||
A simple example project can be found [here](examples/MainsBreakOutBox/readme.md).
|
||||
|
||||
For more examples of what it can make see the [gallery](gallery/readme.md).
|
||||
|
||||
@@ -20,28 +22,29 @@ See [usage](docs/usage.md) for requirements, installation instructions and a usa
|
||||
<th align="left"> Vitamins A-I </th><th align="left"> Vitamins J-Q </th><th align="left"> Vitamins R-Z </th><th align="left"> Printed </th><th align="left"> Utilities </th><th align="left"> Core Utilities </th></tr>
|
||||
<tr><td> <a href = "#Axials">Axials</a> </td><td> <a href = "#Jack">Jack</a> </td><td> <a href = "#Rails">Rails</a> </td><td> <a href = "#Box">Box</a> </td><td> <a href = "#Annotation">Annotation</a> </td><td> <a href = "#BOM">BOM</a> </td></tr>
|
||||
<tr><td> <a href = "#Ball_bearings">Ball_bearings</a> </td><td> <a href = "#KP_pillow_blocks">KP_pillow_blocks</a> </td><td> <a href = "#Ring_terminals">Ring_terminals</a> </td><td> <a href = "#Butt_box">Butt_box</a> </td><td> <a href = "#Bezier">Bezier</a> </td><td> <a href = "#Clip">Clip</a> </td></tr>
|
||||
<tr><td> <a href = "#Batteries">Batteries</a> </td><td> <a href = "#LDRs">LDRs</a> </td><td> <a href = "#Rockers">Rockers</a> </td><td> <a href = "#Cable_grommets">Cable_grommets</a> </td><td> <a href = "#Dogbones">Dogbones</a> </td><td> <a href = "#Global">Global</a> </td></tr>
|
||||
<tr><td> <a href = "#Belts">Belts</a> </td><td> <a href = "#LED_meters">LED_meters</a> </td><td> <a href = "#Rod">Rod</a> </td><td> <a href = "#Carriers">Carriers</a> </td><td> <a href = "#Fillet">Fillet</a> </td><td> <a href = "#Polyholes">Polyholes</a> </td></tr>
|
||||
<tr><td> <a href = "#Blowers">Blowers</a> </td><td> <a href = "#LEDs">LEDs</a> </td><td> <a href = "#SCS_bearing_blocks">SCS_bearing_blocks</a> </td><td> <a href = "#Corner_block">Corner_block</a> </td><td> <a href = "#Gears">Gears</a> </td><td> <a href = "#Rounded_rectangle">Rounded_rectangle</a> </td></tr>
|
||||
<tr><td> <a href = "#Bulldogs">Bulldogs</a> </td><td> <a href = "#Leadnuts">Leadnuts</a> </td><td> <a href = "#SK_brackets">SK_brackets</a> </td><td> <a href = "#Door_hinge">Door_hinge</a> </td><td> <a href = "#Hanging_hole">Hanging_hole</a> </td><td> <a href = "#Sphere">Sphere</a> </td></tr>
|
||||
<tr><td> <a href = "#Buttons">Buttons</a> </td><td> <a href = "#Light_strips">Light_strips</a> </td><td> <a href = "#SMDs">SMDs</a> </td><td> <a href = "#Door_latch">Door_latch</a> </td><td> <a href = "#Layout">Layout</a> </td><td> <a href = "#Teardrops">Teardrops</a> </td></tr>
|
||||
<tr><td> <a href = "#Cable_strips">Cable_strips</a> </td><td> <a href = "#Linear_bearings">Linear_bearings</a> </td><td> <a href = "#SSRs">SSRs</a> </td><td> <a href = "#Fan_guard">Fan_guard</a> </td><td> <a href = "#Maths">Maths</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Cameras">Cameras</a> </td><td> <a href = "#Mains_sockets">Mains_sockets</a> </td><td> <a href = "#Screws">Screws</a> </td><td> <a href = "#Fixing_block">Fixing_block</a> </td><td> <a href = "#Offset">Offset</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Circlips">Circlips</a> </td><td> <a href = "#Microswitches">Microswitches</a> </td><td> <a href = "#Sealing_strip">Sealing_strip</a> </td><td> <a href = "#Flat_hinge">Flat_hinge</a> </td><td> <a href = "#Quadrant">Quadrant</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Components">Components</a> </td><td> <a href = "#Microview">Microview</a> </td><td> <a href = "#Sheets">Sheets</a> </td><td> <a href = "#Foot">Foot</a> </td><td> <a href = "#Round">Round</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#DIP">DIP</a> </td><td> <a href = "#Modules">Modules</a> </td><td> <a href = "#Spades">Spades</a> </td><td> <a href = "#Handle">Handle</a> </td><td> <a href = "#Rounded_cylinder">Rounded_cylinder</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#D_connectors">D_connectors</a> </td><td> <a href = "#Nuts">Nuts</a> </td><td> <a href = "#Spools">Spools</a> </td><td> <a href = "#PCB_mount">PCB_mount</a> </td><td> <a href = "#Rounded_polygon">Rounded_polygon</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Displays">Displays</a> </td><td> <a href = "#O_ring">O_ring</a> </td><td> <a href = "#Springs">Springs</a> </td><td> <a href = "#PSU_shroud">PSU_shroud</a> </td><td> <a href = "#Sector">Sector</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Extrusion_brackets">Extrusion_brackets</a> </td><td> <a href = "#Opengrab">Opengrab</a> </td><td> <a href = "#Stepper_motors">Stepper_motors</a> </td><td> <a href = "#Printed_box">Printed_box</a> </td><td> <a href = "#Sweep">Sweep</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Extrusions">Extrusions</a> </td><td> <a href = "#PCB">PCB</a> </td><td> <a href = "#Swiss_clips">Swiss_clips</a> </td><td> <a href = "#Ribbon_clamp">Ribbon_clamp</a> </td><td> <a href = "#Thread">Thread</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Fans">Fans</a> </td><td> <a href = "#PCBs">PCBs</a> </td><td> <a href = "#Toggles">Toggles</a> </td><td> <a href = "#SSR_shroud">SSR_shroud</a> </td><td> <a href = "#Tube">Tube</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Fuseholder">Fuseholder</a> </td><td> <a href = "#PSUs">PSUs</a> </td><td> <a href = "#Transformers">Transformers</a> </td><td> <a href = "#Screw_knob">Screw_knob</a> </td><td></td><td></td></tr>
|
||||
<tr><td> <a href = "#Geared_steppers">Geared_steppers</a> </td><td> <a href = "#Panel_meters">Panel_meters</a> </td><td> <a href = "#Tubings">Tubings</a> </td><td> <a href = "#Socket_box">Socket_box</a> </td><td></td><td></td></tr>
|
||||
<tr><td> <a href = "#Green_terminals">Green_terminals</a> </td><td> <a href = "#Pillars">Pillars</a> </td><td> <a href = "#Variacs">Variacs</a> </td><td> <a href = "#Strap_handle">Strap_handle</a> </td><td></td><td></td></tr>
|
||||
<tr><td> <a href = "#Hot_ends">Hot_ends</a> </td><td> <a href = "#Pin_headers">Pin_headers</a> </td><td> <a href = "#Veroboard">Veroboard</a> </td><td></td><td></td><td></td></tr>
|
||||
<tr><td> <a href = "#Hygrometer">Hygrometer</a> </td><td> <a href = "#Pulleys">Pulleys</a> </td><td> <a href = "#Washers">Washers</a> </td><td></td><td></td><td></td></tr>
|
||||
<tr><td> <a href = "#IECs">IECs</a> </td><td></td><td> <a href = "#Wire">Wire</a> </td><td></td><td></td><td></td></tr>
|
||||
<tr><td> <a href = "#Inserts">Inserts</a> </td><td></td><td> <a href = "#Zipties">Zipties</a> </td><td></td><td></td><td></td></tr>
|
||||
<tr><td> <a href = "#Batteries">Batteries</a> </td><td> <a href = "#LDRs">LDRs</a> </td><td> <a href = "#Rockers">Rockers</a> </td><td> <a href = "#Cable_grommets">Cable_grommets</a> </td><td> <a href = "#Catenary">Catenary</a> </td><td> <a href = "#Global">Global</a> </td></tr>
|
||||
<tr><td> <a href = "#Belts">Belts</a> </td><td> <a href = "#LED_meters">LED_meters</a> </td><td> <a href = "#Rod">Rod</a> </td><td> <a href = "#Camera_housing">Camera_housing</a> </td><td> <a href = "#Dogbones">Dogbones</a> </td><td> <a href = "#Polyholes">Polyholes</a> </td></tr>
|
||||
<tr><td> <a href = "#Blowers">Blowers</a> </td><td> <a href = "#LEDs">LEDs</a> </td><td> <a href = "#SCS_bearing_blocks">SCS_bearing_blocks</a> </td><td> <a href = "#Carriers">Carriers</a> </td><td> <a href = "#Fillet">Fillet</a> </td><td> <a href = "#Rounded_rectangle">Rounded_rectangle</a> </td></tr>
|
||||
<tr><td> <a href = "#Bulldogs">Bulldogs</a> </td><td> <a href = "#Leadnuts">Leadnuts</a> </td><td> <a href = "#SK_brackets">SK_brackets</a> </td><td> <a href = "#Corner_block">Corner_block</a> </td><td> <a href = "#Gears">Gears</a> </td><td> <a href = "#Sphere">Sphere</a> </td></tr>
|
||||
<tr><td> <a href = "#Buttons">Buttons</a> </td><td> <a href = "#Light_strips">Light_strips</a> </td><td> <a href = "#SMDs">SMDs</a> </td><td> <a href = "#Door_hinge">Door_hinge</a> </td><td> <a href = "#Hanging_hole">Hanging_hole</a> </td><td> <a href = "#Teardrops">Teardrops</a> </td></tr>
|
||||
<tr><td> <a href = "#Cable_strips">Cable_strips</a> </td><td> <a href = "#Linear_bearings">Linear_bearings</a> </td><td> <a href = "#SSRs">SSRs</a> </td><td> <a href = "#Door_latch">Door_latch</a> </td><td> <a href = "#Horiholes">Horiholes</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Cameras">Cameras</a> </td><td> <a href = "#Magnets">Magnets</a> </td><td> <a href = "#Screws">Screws</a> </td><td> <a href = "#Drag_chain">Drag_chain</a> </td><td> <a href = "#Layout">Layout</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Circlips">Circlips</a> </td><td> <a href = "#Mains_sockets">Mains_sockets</a> </td><td> <a href = "#Sealing_strip">Sealing_strip</a> </td><td> <a href = "#Fan_guard">Fan_guard</a> </td><td> <a href = "#Maths">Maths</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Components">Components</a> </td><td> <a href = "#Microswitches">Microswitches</a> </td><td> <a href = "#Shaft_couplings">Shaft_couplings</a> </td><td> <a href = "#Fixing_block">Fixing_block</a> </td><td> <a href = "#Offset">Offset</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#DIP">DIP</a> </td><td> <a href = "#Microview">Microview</a> </td><td> <a href = "#Sheets">Sheets</a> </td><td> <a href = "#Flat_hinge">Flat_hinge</a> </td><td> <a href = "#Quadrant">Quadrant</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#D_connectors">D_connectors</a> </td><td> <a href = "#Modules">Modules</a> </td><td> <a href = "#Spades">Spades</a> </td><td> <a href = "#Foot">Foot</a> </td><td> <a href = "#Round">Round</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Displays">Displays</a> </td><td> <a href = "#Nuts">Nuts</a> </td><td> <a href = "#Spools">Spools</a> </td><td> <a href = "#Handle">Handle</a> </td><td> <a href = "#Rounded_cylinder">Rounded_cylinder</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Extrusion_brackets">Extrusion_brackets</a> </td><td> <a href = "#O_ring">O_ring</a> </td><td> <a href = "#Springs">Springs</a> </td><td> <a href = "#PCB_mount">PCB_mount</a> </td><td> <a href = "#Rounded_polygon">Rounded_polygon</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#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 = "#Sector">Sector</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Fans">Fans</a> </td><td> <a href = "#PCB">PCB</a> </td><td> <a href = "#Swiss_clips">Swiss_clips</a> </td><td> <a href = "#Press_fit">Press_fit</a> </td><td> <a href = "#Sweep">Sweep</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#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 = "#Thread">Thread</a> </td><td></td></tr>
|
||||
<tr><td> <a href = "#Geared_steppers">Geared_steppers</a> </td><td> <a href = "#PSUs">PSUs</a> </td><td> <a href = "#Transformers">Transformers</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 = "#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></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></td><td></td><td> <a href = "#Zipties">Zipties</a> </td><td></td><td></td><td></td></tr>
|
||||
</table>
|
||||
|
||||
---
|
||||
@@ -85,6 +88,7 @@ Axial components for PCBs.
|
||||
| 1 | ```ax_res(res1_4, 47000)``` | Resistor 47000 Ohms 5% 0.25W |
|
||||
| 1 | ```ax_res(res1_2, 8200)``` | Resistor 8200 Ohms 5% 0.5W |
|
||||
| 1 | ```ax_res(res1_2, 8250, tol = 1)``` | Resistor 8250 Ohms 1% 0.5W |
|
||||
| 1 | ```wire_link(0.8, 10.16)``` | Wire link 0.8mm x 0.4" |
|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
@@ -204,11 +208,12 @@ exposing enough information to make a battery box.
|
||||
<a name="Belts"></a>
|
||||
## Belts
|
||||
Models timing belt running over toothed or smooth pulleys and calculates an accurate length.
|
||||
Only models 2D paths, so not core XY!
|
||||
Only models 2D paths, so not crossed belt core XY!
|
||||
|
||||
To make the back of the belt run against a smooth pulley on the outside of the loop specify a negative pitch radius.
|
||||
|
||||
By default the path is a closed loop but a gap length and position can be specified to make open loops.
|
||||
To draw the gap its XY position is specified by ```gap_pos```. ```gap_pos.z``` can be used to specify a rotation if the gap is not at the bottom of the loop.
|
||||
|
||||
Individual teeth are not drawn, instead they are represented by a lighter colour.
|
||||
|
||||
@@ -223,6 +228,7 @@ Individual teeth are not drawn, instead they are represented by a lighter colour
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| ```belt_pitch(type)``` | Pitch in mm |
|
||||
| ```belt_pitch_height(type)``` | Offset of the pitch radius from the tips of the teeth |
|
||||
| ```belt_thickness(type)``` | Total thickness including teeth |
|
||||
| ```belt_tooth_height(type)``` | Tooth height |
|
||||
| ```belt_width(type)``` | Width in mm |
|
||||
@@ -231,12 +237,12 @@ Individual teeth are not drawn, instead they are represented by a lighter colour
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| ```belt_length(points, gap = 0)``` | Compute belt length given path and optional gap |
|
||||
| ```belt_pitch_height(type)``` | Offset of the pitch radius from the tips of the teeth |
|
||||
| ```belt_pitch_to_back(type)``` | Offset of the back from the pitch radius |
|
||||
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| ```belt(type, points, gap = 0, gap_pt = undef, belt_colour = grey(20)``` | Draw a belt path given a set of points and pitch radii where the pulleys are. Closed loop unless a gap is specified |
|
||||
| ```belt(type, points, gap = 0, gap_pos = undef, belt_colour = grey(20)``` | Draw a belt path given a set of points and pitch radii where the pulleys are. Closed loop unless a gap is specified |
|
||||
|
||||

|
||||
|
||||
@@ -244,15 +250,16 @@ Individual teeth are not drawn, instead they are represented by a lighter colour
|
||||
| Qty | Module call | BOM entry |
|
||||
| ---:|:--- |:---|
|
||||
| 1 | ```belt(GT2x6, [ ... ])``` | Belt GT2 x 6mm x 128mm |
|
||||
| 1 | ```belt(GT2x6, [ ... ], 80, [0, 0.81])``` | Belt GT2 x 6mm x 694mm |
|
||||
| 2 | ```belt(GT2x6, [ ... ], 80, [0, 0])``` | Belt GT2 x 6mm x 572mm |
|
||||
| 1 | ```belt(T2p5x6, [ ... ])``` | Belt T2.5 x 6mm x 130mm |
|
||||
| 1 | ```belt(T5x10, [ ... ])``` | Belt T5 x 10mm x 130mm |
|
||||
| 1 | ```belt(T5x6, [ ... ])``` | Belt T5 x 6mm x 130mm |
|
||||
| 1 | ```insert(F1BM3)``` | Heatfit insert M3 |
|
||||
| 2 | ```pulley(GT2x20_toothed_idler)``` | Pulley GT2 idler 20 teeth |
|
||||
| 2 | ```insert(F1BM3)``` | Heatfit insert M3 |
|
||||
| 2 | ```pulley(GT2x16_toothed_idler)``` | Pulley GT2 idler 16 teeth |
|
||||
| 4 | ```pulley(GT2x20_toothed_idler)``` | Pulley GT2 idler 20 teeth |
|
||||
| 2 | ```pulley(GT2x16_plain_idler)``` | Pulley GT2 idler smooth 9.63mm |
|
||||
| 2 | ```pulley(GT2x20ob_pulley)``` | Pulley GT2OB 20 teeth |
|
||||
| 1 | ```screw(M3_cs_cap_screw, 20)``` | Screw M3 cs cap x 20mm |
|
||||
| 2 | ```screw(M3_cs_cap_screw, 20)``` | Screw M3 cs cap x 20mm |
|
||||
| 4 | ```screw(M3_grub_screw, 6)``` | Screw M3 grub x 6mm |
|
||||
|
||||
|
||||
@@ -289,11 +296,18 @@ Models of radial blowers.
|
||||
| ```blower_wall(type)``` | Side wall thickness |
|
||||
| ```blower_width(type)``` | Width of enclosing rectangle |
|
||||
|
||||
### Functions
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| ```blower_casing_is_square(type)``` | True for square radial fans, false for spiral shape radial blowers |
|
||||
| ```blower_exit_offset(type)``` | Offset of exit's centre from the edge |
|
||||
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| ```blower(type)``` | Draw specified blower |
|
||||
| ```blower_hole_positions(type)``` | Translate children to screw hole positions |
|
||||
| ```blower_square(type)``` | Draw a square blower |
|
||||
|
||||

|
||||
|
||||
@@ -302,8 +316,11 @@ Models of radial blowers.
|
||||
| ---:|:--- |:---|
|
||||
| 1 | ```blower(PE4020)``` | Blower Pengda Technology 4020 |
|
||||
| 1 | ```blower(RB5015)``` | Blower Runda RB5015 |
|
||||
| 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 |
|
||||
| 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 |
|
||||
|
||||
@@ -400,7 +417,7 @@ PCB mounted buttons. Can optionally have a coloured cap
|
||||
## Cable_strips
|
||||
A strip of polypropylene used with ribbon cable to make a cable flexible in one direction only.
|
||||
|
||||
Modelled with a Bezier spline, which is not quite the same as a miniumum energy curve but very close, epecially
|
||||
Modelled with a Bezier spline, which is not quite the same as a minimum energy curve but very close, epecially
|
||||
near the extreme positions, where the model needs to be accurate.
|
||||
|
||||
When the sides are constrained then a circular model is more accurate.
|
||||
@@ -457,8 +474,8 @@ PCB cameras.
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| ```camera(type)``` | Draw specified PCB camera |
|
||||
| ```camera_lens(type, offset = 0)``` | Draw the lens stack, with optional offset for making a clearance hole |
|
||||
| ```camera(type, show_lens = true)``` | Draw specified PCB camera |
|
||||
| ```camera_lens(type, offset = 0, show_lens = true)``` | Draw the lens stack, with optional offset for making a clearance hole |
|
||||
|
||||

|
||||
|
||||
@@ -751,6 +768,7 @@ LCD dispays.
|
||||
### Vitamins
|
||||
| Qty | Module call | BOM entry |
|
||||
| ---:|:--- |:---|
|
||||
| 1 | ```display(BigTreeTech_TFT35v3_0)``` | BigTreeTech TFT35 v3.0 |
|
||||
| 1 | ```display(HDMI5)``` | HDMI display 5" |
|
||||
| 1 | ```display(LCD1602A)``` | LCD display 1602A |
|
||||
| 1 | ```display(LCDS7282B)``` | LCD display S-7282B |
|
||||
@@ -900,7 +918,7 @@ Can draw three styles: solid, open frame and open frame with screw bosses.
|
||||
| ---:|:--- |:---|
|
||||
| 1 | ```fan(fan120x25)``` | Fan 120mm x 25mm |
|
||||
| 1 | ```fan(fan17x8)``` | Fan 17mm x 8mm |
|
||||
| 1 | ```fan(fan25x10)``` | Fan 25mm x 10mm |
|
||||
| 1 | ```fan(fan25.4x10)``` | Fan 25.4mm x 10mm |
|
||||
| 1 | ```fan(fan30x10)``` | Fan 30mm x 10mm |
|
||||
| 1 | ```fan(fan40x11)``` | Fan 40mm x 11mm |
|
||||
| 1 | ```fan(fan50x15)``` | Fan 50mm x 15mm |
|
||||
@@ -1099,7 +1117,7 @@ Needs updating as mostly obsolete versions.
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| ```hot_end(type, filament, naked = false, resistor_wire_rotate = [0,0,0])``` | Draw specified hot end |
|
||||
| ```hot_end(type, filament, naked = false, resistor_wire_rotate = [0,0,0], bowden = false)``` | Draw specified hot end |
|
||||
|
||||

|
||||
|
||||
@@ -1250,6 +1268,7 @@ Heatfit threaded inserts. Can be pushed into thermoplastics using a soldering ir
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| ```insert_boss_radius(type, wall)``` | Compute the outer radius of an insert boss |
|
||||
| ```insert_nose_length(type, d)``` | The length before the second ring. |
|
||||
|
||||
### Modules
|
||||
| Module | Description |
|
||||
@@ -1264,7 +1283,7 @@ Heatfit threaded inserts. Can be pushed into thermoplastics using a soldering ir
|
||||
### Vitamins
|
||||
| Qty | Module call | BOM entry |
|
||||
| ---:|:--- |:---|
|
||||
| 1 | ```insert(F1BM)``` | Heatfit insert M2 |
|
||||
| 1 | ```insert(F1BM2)``` | Heatfit insert M2 |
|
||||
| 1 | ```insert(F1BM2p5)``` | Heatfit insert M2.5 |
|
||||
| 1 | ```insert(F1BM3)``` | Heatfit insert M3 |
|
||||
| 1 | ```insert(F1BM4)``` | Heatfit insert M4 |
|
||||
@@ -1673,6 +1692,36 @@ LMnUU linear bearings.
|
||||
| 1 | ```linear_bearing(LM8UU)``` | Linear bearing LM8UU |
|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
|
||||
---
|
||||
<a name="Magnets"></a>
|
||||
## Magnets
|
||||
Cylindrical and ring magnets.
|
||||
|
||||
|
||||
[vitamins/magnets.scad](vitamins/magnets.scad) Object definitions.
|
||||
|
||||
[vitamins/magnet.scad](vitamins/magnet.scad) Implementation.
|
||||
|
||||
[tests/magnets.scad](tests/magnets.scad) Code for this example.
|
||||
|
||||
### Properties
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| ```magnet_h(type)``` | Height |
|
||||
| ```magnet_id(type)``` | Inside diameter if a ring |
|
||||
| ```magnet_od(type)``` | Outer diameter |
|
||||
| ```magnet_r(type)``` | Corner radius |
|
||||
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| ```magnet(type)``` | Draw specified magnet |
|
||||
|
||||

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

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

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

|
||||
@@ -2290,14 +2347,14 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
|
||||
| 1 | ```pcb(EnviroPlus)``` | Enviro+ |
|
||||
| 1 | ```pcb(ExtruderPCB)``` | Extruder connection PCB |
|
||||
| 1 | ```pcb(Keyes5p1)``` | Keyes5.1 Arduino Uno expansion board |
|
||||
| 1 | ```pcb(MP1584EN)``` | MP1584EN 3A buck converter |
|
||||
| 1 | ```pcb(MT3608)``` | MT3608 boost converter module |
|
||||
| 1 | ```pcb(Melzi)``` | Melzi electronics |
|
||||
| 4 | | Micro SD card |
|
||||
| 1 | ```molex_254(2)``` | Molex KK header 2 way |
|
||||
| 1 | ```molex_254(3)``` | Molex KK header 3 way |
|
||||
| 16 | ```nut(M2_nut, nyloc = true)``` | Nut M2 x 1.6mm nyloc |
|
||||
| 30 | ```nut(M2p5_nut, nyloc = true)``` | Nut M2.5 x 2.2mm nyloc |
|
||||
| 16 | ```nut(M3_nut, nyloc = true)``` | Nut M3 x 2.4mm nyloc |
|
||||
| 34 | ```nut(M2p5_nut, nyloc = true)``` | Nut M2.5 x 2.2mm nyloc |
|
||||
| 12 | ```nut(M3_nut, nyloc = true)``` | Nut M3 x 2.4mm nyloc |
|
||||
| 12 | ```nut(M4_nut, nyloc = true)``` | Nut M4 x 3.2mm nyloc |
|
||||
| 1 | ```pcb(PI_IO)``` | PI_IO V2 |
|
||||
| 1 | ```pcb(PSU12V1A)``` | PSU 12V 1A |
|
||||
@@ -2309,28 +2366,25 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
|
||||
| 1 | ```pin_socket(2p54header, 13, 2, right_angle = true)``` | Pin socket 13 x 2 right_angle |
|
||||
| 1 | ```pcb(RAMPSEndstop)``` | RAMPS Endstop Switch |
|
||||
| 1 | ```pcb(RPI3)``` | Raspberry Pi 3 |
|
||||
| 1 | ```pcb(RPI4)``` | Raspberry Pi 4 |
|
||||
| 1 | ```pcb(RPI0)``` | Raspberry Pi Zero |
|
||||
| 12 | ```screw(M2_cap_screw, 16)``` | Screw M2 cap x 16mm |
|
||||
| 4 | ```screw(M2_cap_screw, 20)``` | Screw M2 cap x 20mm |
|
||||
| 2 | ```screw(M2p5_cap_screw, 16)``` | Screw M2.5 cap x 16mm |
|
||||
| 4 | ```screw(M2p5_cap_screw, 20)``` | Screw M2.5 cap x 20mm |
|
||||
| 4 | ```screw(M2p5_cap_screw, 25)``` | Screw M2.5 cap x 25mm |
|
||||
| 4 | ```screw(M2p5_cap_screw, 30)``` | Screw M2.5 cap x 30mm |
|
||||
| 2 | ```screw(M2p5_cap_screw, 20)``` | Screw M2.5 cap x 20mm |
|
||||
| 8 | ```screw(M2p5_cap_screw, 25)``` | Screw M2.5 cap x 25mm |
|
||||
| 8 | ```screw(M2p5_cap_screw, 30)``` | Screw M2.5 cap x 30mm |
|
||||
| 4 | ```screw(M2p5_pan_screw, 20)``` | Screw M2.5 pan x 20mm |
|
||||
| 12 | ```screw(M2p5_pan_screw, 25)``` | Screw M2.5 pan x 25mm |
|
||||
| 4 | ```screw(M3_cap_screw, 16)``` | Screw M3 cap x 16mm |
|
||||
| 8 | ```screw(M3_cap_screw, 30)``` | Screw M3 cap x 30mm |
|
||||
| 4 | ```screw(M3_cap_screw, 35)``` | Screw M3 cap x 35mm |
|
||||
| 4 | ```screw(M4_cap_screw, 30)``` | Screw M4 cap x 30mm |
|
||||
| 8 | ```screw(M4_cap_screw, 35)``` | Screw M4 cap x 35mm |
|
||||
| 12 | ```screw(M4_cap_screw, 35)``` | Screw M4 cap x 35mm |
|
||||
| 1 | ```pcb(TP4056)``` | TP4056 Li-lon Battery charger module |
|
||||
| 3 | ```terminal_35(2)``` | Terminal block 2 way 3.5mm |
|
||||
| 2 | ```green_terminal(gt_2p54, 4)``` | Terminal block 4 way 0.1" |
|
||||
| 1 | | USB A to Mini B lead |
|
||||
| 1 | ```pcb(WD2002SJ)``` | WD2002SJ Buck Boost DC-DC converter |
|
||||
| 16 | ```washer(M2_washer)``` | Washer M2 x 5mm x 0.3mm |
|
||||
| 30 | ```washer(M2p5_washer)``` | Washer M2.5 x 5.9mm x 0.5mm |
|
||||
| 16 | ```washer(M3_washer)``` | Washer M3 x 7mm x 0.5mm |
|
||||
| 34 | ```washer(M2p5_washer)``` | Washer M2.5 x 5.9mm x 0.5mm |
|
||||
| 12 | ```washer(M3_washer)``` | Washer M3 x 7mm x 0.5mm |
|
||||
| 12 | ```washer(M4_washer)``` | Washer M4 x 9mm x 0.8mm |
|
||||
| 1 | ```pcb(ZC_A0591)``` | ZC-A0591 ULN2003 driver PCB |
|
||||
|
||||
@@ -2341,21 +2395,21 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
|
||||
| 4 | pcb_spacer2070.stl |
|
||||
| 4 | pcb_spacer2080.stl |
|
||||
| 4 | pcb_spacer2090.stl |
|
||||
| 4 | pcb_spacer25100.stl |
|
||||
| 4 | pcb_spacer25110.stl |
|
||||
| 4 | pcb_spacer25120.stl |
|
||||
| 4 | pcb_spacer25130_2.stl |
|
||||
| 4 | pcb_spacer25130.stl |
|
||||
| 4 | pcb_spacer25140_2.stl |
|
||||
| 4 | pcb_spacer25150_2.stl |
|
||||
| 4 | pcb_spacer25180.stl |
|
||||
| 2 | pcb_spacer2570.stl |
|
||||
| 4 | pcb_spacer30160.stl |
|
||||
| 4 | pcb_spacer25160_2.stl |
|
||||
| 4 | pcb_spacer25190.stl |
|
||||
| 4 | pcb_spacer25200.stl |
|
||||
| 2 | pcb_spacer2580.stl |
|
||||
| 4 | pcb_spacer30170.stl |
|
||||
| 4 | pcb_spacer30220.stl |
|
||||
| 4 | pcb_spacer30180.stl |
|
||||
| 4 | pcb_spacer3050.stl |
|
||||
| 4 | pcb_spacer40190.stl |
|
||||
| 4 | pcb_spacer40200.stl |
|
||||
| 4 | pcb_spacer40210.stl |
|
||||
| 4 | pcb_spacer40220.stl |
|
||||
| 4 | pcb_spacer40230.stl |
|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
@@ -2424,19 +2478,24 @@ Pin headers and sockets, etc.
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| ```hdr_base_colour(type)``` | Header insulator colour |
|
||||
| ```hdr_box_size(type)``` | Box header outside dimensions |
|
||||
| ```hdr_box_wall(type)``` | Box header wall thickness |
|
||||
| ```hdr_pin_below(type)``` | Header pin length underneath |
|
||||
| ```hdr_pin_colour(type)``` | Header pin colour |
|
||||
| ```hdr_pin_length(type)``` | Header pin length |
|
||||
| ```hdr_pin_width(type)``` | Header pin size |
|
||||
| ```hdr_pitch(type)``` | Header pitch |
|
||||
| ```hdr_ra_box_offset(type)``` | Offset between back of the box and the pins |
|
||||
| ```hdr_ra_height(type)``` | Height of right angle connector |
|
||||
| ```hdr_socket_depth(type)``` | Socket depth for female housing |
|
||||
| ```hdr_y_offset(type)``` | Y offset of pins from center of the box |
|
||||
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| ```box_header(type, cols = 1, rows = 1, smt = false, cutout = false)``` | Draw box header |
|
||||
| ```idc_transition(type, cols = 5, skip = [], cutout = false)``` | Draw IDC transition header |
|
||||
| ```jst_xh_header(type, pin_count, right_angle=false, colour, pin_colour)``` | Draw JST XH connector |
|
||||
| ```jst_xh_header(type, pin_count, right_angle = false, colour = false, pin_colour = false)``` | Draw JST XH connector |
|
||||
| ```pin(type, length = undef)``` | Draw a header pin |
|
||||
| ```pin_header(type, cols = 1, rows = 1, smt = false, right_angle = false, cutout = false, colour)``` | Draw pin header |
|
||||
| ```pin_socket(type, cols = 1, rows = 1, right_angle = false, height = 0, smt = false, cutout = false, colour)``` | Draw pin socket |
|
||||
@@ -2447,11 +2506,18 @@ Pin headers and sockets, etc.
|
||||
| Qty | Module call | BOM entry |
|
||||
| ---:|:--- |:---|
|
||||
| 1 | ```box_header(2p54header, 10, 2)``` | Box header 10 x 2 |
|
||||
| 1 | ```box_header(2p54header, 8, 1)``` | Box header 8 x 1 |
|
||||
| 1 | ```idc_transition(2p54header, 10)``` | IDC transition header 10 x 2 |
|
||||
| 1 | ```pin_header(2p54header, 10, 2)``` | Pin header 10 x 2 |
|
||||
| 1 | ```pin_header(2p54header, 10, 2, right_angle = true)``` | Pin header 10 x 2 right_angle |
|
||||
| 1 | ```pin_header(2p54header, 3, 1, right_angle = true)``` | Pin header 3 x 1 right_angle |
|
||||
| 1 | ```pin_header(2p54header, 3, 2, right_angle = true)``` | Pin header 3 x 2 right_angle |
|
||||
| 1 | ```pin_header(2p54header, 3, 3, right_angle = true)``` | Pin header 3 x 3 right_angle |
|
||||
| 1 | ```pin_header(2p54header, 8, 1)``` | Pin header 8 x 1 |
|
||||
| 1 | ```pin_socket(2p54header, 10, 2)``` | Pin socket 10 x 2 |
|
||||
| 1 | ```pin_socket(2p54header, 10, 2, right_angle = true)``` | Pin socket 10 x 2 right_angle |
|
||||
| 1 | ```pin_socket(2p54header, 3, 1, right_angle = true)``` | Pin socket 3 x 1 right_angle |
|
||||
| 1 | ```pin_socket(2p54header, 3, 2, right_angle = true)``` | Pin socket 3 x 2 right_angle |
|
||||
| 1 | ```pin_socket(2p54header, 3, 3, right_angle = true)``` | Pin socket 3 x 3 right_angle |
|
||||
| 1 | ```pin_socket(2p54header, 8, 1)``` | Pin socket 8 x 1 |
|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
@@ -2589,6 +2655,7 @@ Timing belt pulleys, both toothed and plain with internal bearings for idlers.
|
||||
| 1 | ```pulley(GT2x20_toothed_idler)``` | Pulley GT2 idler 20 teeth |
|
||||
| 1 | ```pulley(GT2x20_plain_idler)``` | Pulley GT2 idler smooth 12mm |
|
||||
| 1 | ```pulley(GT2x16_plain_idler)``` | Pulley GT2 idler smooth 9.63mm |
|
||||
| 1 | ```pulley(GT2x16x7_plain_idler)``` | Pulley GT2 idler smooth 9.63mm |
|
||||
| 1 | ```pulley(GT2x20ob_pulley)``` | Pulley GT2OB 20 teeth |
|
||||
| 1 | ```pulley(GT2x12_pulley)``` | Pulley GT2RD 12 teeth |
|
||||
| 1 | ```pulley(GT2x20um_pulley)``` | Pulley GT2UM 20 teeth |
|
||||
@@ -2640,6 +2707,7 @@ Linear rails with carriages.
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| ```carriage_screw_depth(type)``` | Carriage thread depth |
|
||||
| ```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 |
|
||||
|
||||
@@ -2882,6 +2950,7 @@ Machine screws and wood screws with various head styles.
|
||||
| 1 | ```screw(No632_pan_screw, 30)``` | Screw 6-32 pan x 30mm |
|
||||
| 1 | ```screw(M2_cap_screw, 10)``` | Screw M2 cap x 10mm |
|
||||
| 1 | ```screw(M2_cs_cap_screw, 10)``` | Screw M2 cs cap x 10mm |
|
||||
| 1 | ```screw(M2_dome_screw, 10)``` | Screw M2 dome x 10mm |
|
||||
| 1 | ```screw(M2p5_cap_screw, 10)``` | Screw M2.5 cap x 10mm |
|
||||
| 1 | ```screw(M2p5_pan_screw, 10)``` | Screw M2.5 pan x 10mm |
|
||||
| 1 | ```screw(M3_cap_screw, 10)``` | Screw M3 cap x 10mm |
|
||||
@@ -2999,6 +3068,41 @@ Sealing strip from B&Q used to seal around the door of 3D printers.
|
||||
| 1 | ```sealing_strip(100)``` | Sealing strip 10mm x 4mm x 100mm |
|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
|
||||
---
|
||||
<a name="Shaft_couplings"></a>
|
||||
## Shaft_couplings
|
||||
Shaft couplings
|
||||
|
||||
|
||||
[vitamins/shaft_couplings.scad](vitamins/shaft_couplings.scad) Object definitions.
|
||||
|
||||
[vitamins/shaft_coupling.scad](vitamins/shaft_coupling.scad) Implementation.
|
||||
|
||||
[tests/shaft_couplings.scad](tests/shaft_couplings.scad) Code for this example.
|
||||
|
||||
### Properties
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| ```sc_diameter(type)``` | Coupling outer diameter |
|
||||
| ```sc_diameter1(type)``` | Diameter of smaller shaft |
|
||||
| ```sc_diameter2(type)``` | Diameter of larger shaft |
|
||||
| ```sc_length(type)``` | Coupling length |
|
||||
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| ```shaft_coupling(type, colour = "silver")``` | Draw the shaft coupling |
|
||||
|
||||

|
||||
|
||||
### Vitamins
|
||||
| Qty | Module call | BOM entry |
|
||||
| ---:|:--- |:---|
|
||||
| 1 | ```shaft_coupling(SC_5x8_rigid)``` | Shaft coupling SC_5x8_rigid |
|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
|
||||
---
|
||||
@@ -3359,6 +3463,7 @@ NEMA stepper motor model.
|
||||
| ```NEMA_body_radius(type)``` | Body radius |
|
||||
| ```NEMA_boss_height(type)``` | Boss height |
|
||||
| ```NEMA_boss_radius(type)``` | Boss around the spindle radius |
|
||||
| ```NEMA_cap_heights(type)``` | Height of the end cap at the corner and the side |
|
||||
| ```NEMA_hole_pitch(type)``` | Screw hole pitch |
|
||||
| ```NEMA_length(type)``` | Body length |
|
||||
| ```NEMA_radius(type)``` | End cap radius |
|
||||
@@ -3375,7 +3480,7 @@ NEMA stepper motor model.
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| ```NEMA(type, shaft_angle = 0)``` | Draw specified NEMA stepper motor |
|
||||
| ```NEMA(type, shaft_angle = 0, jst_connector = false)``` | Draw specified NEMA stepper motor |
|
||||
| ```NEMA_outline(type)``` | 2D outline |
|
||||
| ```NEMA_screw_positions(type, n = 4)``` | Positions children at the screw holes |
|
||||
| ```NEMA_screws(type, screw, n = 4, screw_length = 8, earth = undef)``` | Place screws and optional earth tag |
|
||||
@@ -3582,16 +3687,22 @@ Tubing and sleeving. The internal diameter can be forced to stretch it over some
|
||||
| ```tubing_material(type)``` | Material description |
|
||||
| ```tubing_od(type)``` | Outside diameter |
|
||||
|
||||
### Functions
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| ```tubing_or(type)``` | Outside radius |
|
||||
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| ```tubing(type, length = 15, forced_id = 0)``` | Draw specified tubing with optional forced internal diameter |
|
||||
| ```tubing(type, length = 15, forced_id = 0, center = true)``` | Draw specified tubing with optional forced internal diameter |
|
||||
|
||||

|
||||
|
||||
### Vitamins
|
||||
| Qty | Module call | BOM entry |
|
||||
| ---:|:--- |:---|
|
||||
| 1 | ```tubing(CBNFIB10)``` | Carbon fiber OD 10mm ID 8mm x 15mm |
|
||||
| 1 | ```tubing(HSHRNK16)``` | Heatshrink sleeving ID 1.6mm x 15mm |
|
||||
| 1 | ```tubing(HSHRNK100)``` | Heatshrink sleeving ID 10mm x 15mm |
|
||||
| 1 | ```tubing(HSHRNK24)``` | Heatshrink sleeving ID 2.4mm x 15mm |
|
||||
@@ -3599,7 +3710,10 @@ Tubing and sleeving. The internal diameter can be forced to stretch it over some
|
||||
| 1 | ```tubing(NEOP85)``` | Neoprene tubing OD 8mm ID 5mm x 15mm |
|
||||
| 1 | ```tubing(PTFE07)``` | PTFE sleeving OD 1.2mm ID 0.71mm x 15mm |
|
||||
| 1 | ```tubing(PTFE20)``` | PTFE sleeving OD 2.6mm ID 2mm x 15mm |
|
||||
| 1 | ```tubing(PTFE2_3)``` | PTFE tubing OD 3mm ID 2mm x 15mm |
|
||||
| 1 | ```tubing(PF7)``` | PTFE tubing OD 4.6mm ID 3.84mm x 15mm |
|
||||
| 1 | ```tubing(PTFE2_4)``` | PTFE tubing OD 4mm ID 2mm x 15mm |
|
||||
| 1 | ```tubing(PTFE4_6)``` | PTFE tubing OD 6mm ID 4mm x 15mm |
|
||||
| 1 | ```tubing(PVC64)``` | PVC aquarium tubing OD 6mm ID 4mm x 15mm |
|
||||
| 1 | ```tubing(PVC85)``` | PVC aquarium tubing OD 8mm ID 5mm x 15mm |
|
||||
|
||||
@@ -4160,6 +4274,72 @@ of conductive panels, an extra layer of insulation.
|
||||
| 1 | round_grommet_top_60_3.stl |
|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
|
||||
---
|
||||
<a name="Camera_housing"></a>
|
||||
## Camera_housing
|
||||
Housings for PCB cameras.
|
||||
|
||||
|
||||
[printed/camera_housing.scad](printed/camera_housing.scad) Implementation.
|
||||
|
||||
[tests/camera_housing.scad](tests/camera_housing.scad) Code for this example.
|
||||
|
||||
### Functions
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| ```cam_front_size(cam)``` | Outside dimensions of the case |
|
||||
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| ```camera_assembly(cam, angle = 0)``` | Camera case assembly |
|
||||
| ```camera_back(cam)``` | Make the STL for a camera case back |
|
||||
| ```camera_bracket(cam)``` | Make the STL for the camera bracket |
|
||||
| ```camera_bracket_position(cam)``` | Position children at the bracket position |
|
||||
| ```camera_bracket_screw_positions(cam)``` | Position children at the bracket screw positions |
|
||||
| ```camera_front(cam, hinge = 0)``` | Make the STL for a camera case front |
|
||||
| ```rpi_camera_focus_ring_stl()``` | Focus ring the glue onto RPI lens |
|
||||
|
||||

|
||||
|
||||
### Vitamins
|
||||
| Qty | Module call | BOM entry |
|
||||
| ---:|:--- |:---|
|
||||
| 7 | ```nut(M2_nut, nyloc = true)``` | Nut M2 x 1.6mm nyloc |
|
||||
| 10 | ```nut(M3_nut, nyloc = true)``` | Nut M3 x 2.4mm nyloc |
|
||||
| 1 | ```camera(rpi_camera_v1)``` | Raspberry Pi camera V1 |
|
||||
| 1 | ```camera(rpi_camera_v2)``` | Raspberry Pi camera V2 |
|
||||
| 1 | ```camera(rpi_camera)``` | Raspberry Pi focusable camera |
|
||||
| 7 | ```screw(M2_cap_screw, 10)``` | Screw M2 cap x 10mm |
|
||||
| 4 | ```screw(M3_cap_screw, 16)``` | Screw M3 cap x 16mm |
|
||||
| 4 | ```screw(M3_dome_screw, 10)``` | Screw M3 dome x 10mm |
|
||||
| 2 | ```screw(M3_dome_screw, 12)``` | Screw M3 dome x 12mm |
|
||||
| 7 | ```washer(M2_washer)``` | Washer M2 x 5mm x 0.3mm |
|
||||
| 16 | ```washer(M3_washer)``` | Washer M3 x 7mm x 0.5mm |
|
||||
|
||||
### Printed
|
||||
| Qty | Filename |
|
||||
| ---:|:--- |
|
||||
| 1 | camera_back_rpi_camera.stl |
|
||||
| 1 | camera_back_rpi_camera_v1.stl |
|
||||
| 1 | camera_back_rpi_camera_v2.stl |
|
||||
| 1 | camera_bracket_rpi_camera.stl |
|
||||
| 1 | camera_bracket_rpi_camera_v1.stl |
|
||||
| 1 | camera_bracket_rpi_camera_v2.stl |
|
||||
| 1 | camera_front_rpi_camera.stl |
|
||||
| 1 | camera_front_rpi_camera_v1.stl |
|
||||
| 1 | camera_front_rpi_camera_v2.stl |
|
||||
|
||||
### Assemblies
|
||||
| Qty | Name |
|
||||
| ---:|:--- |
|
||||
| 1 | camera_rpi_camera_assembly |
|
||||
| 1 | camera_rpi_camera_v1_assembly |
|
||||
| 1 | camera_rpi_camera_v2_assembly |
|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
|
||||
---
|
||||
@@ -4241,7 +4421,7 @@ Star washers can be omitted by setting ```star_washers``` to false.
|
||||
### Vitamins
|
||||
| Qty | Module call | BOM entry |
|
||||
| ---:|:--- |:---|
|
||||
| 3 | ```insert(F1BM)``` | Heatfit insert M2 |
|
||||
| 3 | ```insert(F1BM2)``` | Heatfit insert M2 |
|
||||
| 3 | ```insert(F1BM2p5)``` | Heatfit insert M2.5 |
|
||||
| 3 | ```insert(F1BM3)``` | Heatfit insert M3 |
|
||||
| 3 | ```insert(F1BM4)``` | Heatfit insert M4 |
|
||||
@@ -4370,6 +4550,73 @@ Door latch for 6mm acrylic door for 3D printer. See [door_hinge](#door_hinge).
|
||||
| 1 | door_latch.stl |
|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
|
||||
---
|
||||
<a name="Drag_chain"></a>
|
||||
## Drag_chain
|
||||
Parametric cable drag chain to limit the bend radius of a cable run.
|
||||
|
||||
Each link has a maximum bend angle of 45°, so the mininium radius is proportional to the link length.
|
||||
|
||||
The travel property is how far it can move in each direction, i.e. half the maximum travel if the chain is mounted in the middle of the travel.
|
||||
|
||||
The ends can have screw lugs with four screw positions to choose from, specified by a list of two arrays of four bools.
|
||||
If none are enabled then a child object is expected to customise the end and this gets unioned with the blank end.
|
||||
If both ends are customised then two children are expected.
|
||||
Each child is called twice, once with ```$fasteners``` set to 0 to augment the STL and again with ```$fasteners``` set to 1 to add
|
||||
to the assembly, for example to add inserts.
|
||||
|
||||
|
||||
[printed/drag_chain.scad](printed/drag_chain.scad) Implementation.
|
||||
|
||||
[tests/drag_chain.scad](tests/drag_chain.scad) Code for this example.
|
||||
|
||||
### Properties
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| ```drag_chain_bwall(type)``` | Bottom wall |
|
||||
| ```drag_chain_name(type)``` | The name to allow more than one in a project |
|
||||
| ```drag_chain_screw(type)``` | Mounting screw for the ends |
|
||||
| ```drag_chain_screw_lists(type)``` | Two lists of four bools to say which screws positions are used |
|
||||
| ```drag_chain_size(type)``` | The internal size and link length |
|
||||
| ```drag_chain_travel(type)``` | X travel |
|
||||
| ```drag_chain_twall(type)``` | Top wall |
|
||||
| ```drag_chain_wall(type)``` | Side wall thickness |
|
||||
|
||||
### Functions
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| ```drag_chain(name, size, travel, wall = 1.6, bwall = 1.5, twall = 1.5, screw = M2_cap_screw, screw_lists = [[1,0,0,1],[1,0,0,1]])``` | Constructor |
|
||||
| ```drag_chain_clearance()``` | Clearance around joints. |
|
||||
| ```drag_chain_outer_size(type)``` | Link outer dimensions |
|
||||
| ```drag_chain_radius(type)``` | The bend radius at the pivot centres |
|
||||
| ```drag_chain_z(type)``` | Outside dimension of a 180 bend |
|
||||
| ```screw_lug_radius(screw)``` | Radius if a screw lug |
|
||||
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| ```drag_chain_assembly(type, pos = 0)``` | Drag chain assembly |
|
||||
| ```drag_chain_link(type, start = false, end = false)``` | 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 |
|
||||
|
||||

|
||||
|
||||
### Printed
|
||||
| Qty | Filename |
|
||||
| ---:|:--- |
|
||||
| 14 | x_drag_chain_link.stl |
|
||||
| 1 | x_drag_chain_link_end.stl |
|
||||
| 1 | x_drag_chain_link_start.stl |
|
||||
|
||||
### Assemblies
|
||||
| Qty | Name |
|
||||
| ---:|:--- |
|
||||
| 1 | x_drag_chain_assembly |
|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
|
||||
---
|
||||
@@ -4403,7 +4650,7 @@ The ring spacing as well as the number of spokes can be specified, if zero a gas
|
||||
| ---:|:--- |
|
||||
| 1 | fan_guard_120.stl |
|
||||
| 1 | fan_guard_17.stl |
|
||||
| 1 | fan_guard_25.stl |
|
||||
| 1 | fan_guard_25.4.stl |
|
||||
| 1 | fan_guard_30.stl |
|
||||
| 1 | fan_guard_40.stl |
|
||||
| 1 | fan_guard_50.stl |
|
||||
@@ -4461,7 +4708,7 @@ Star washers can be omitted by setting ```star_washers``` to false.
|
||||
### Vitamins
|
||||
| Qty | Module call | BOM entry |
|
||||
| ---:|:--- |:---|
|
||||
| 3 | ```insert(F1BM)``` | Heatfit insert M2 |
|
||||
| 3 | ```insert(F1BM2)``` | Heatfit insert M2 |
|
||||
| 3 | ```insert(F1BM2p5)``` | Heatfit insert M2.5 |
|
||||
| 3 | ```insert(F1BM3)``` | Heatfit insert M3 |
|
||||
| 3 | ```insert(F1BM4)``` | Heatfit insert M4 |
|
||||
@@ -4731,6 +4978,29 @@ The stl must be given a parameterless wrapper in the project that uses it.
|
||||
| 1 | pcb_mount_PI_IO_5.stl |
|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
|
||||
---
|
||||
<a name="Press_fit"></a>
|
||||
## Press_fit
|
||||
Utility for making printed press fit connectors to join printed parts.
|
||||
|
||||
Add solvent or glue to make a permanent fixture.
|
||||
|
||||
|
||||
[printed/press_fit.scad](printed/press_fit.scad) Implementation.
|
||||
|
||||
[tests/press_fit.scad](tests/press_fit.scad) Code for this example.
|
||||
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| ```press_fit_peg(h, w = 5, horizontal = false)``` | Make a rounded chamfered peg for easy insertion |
|
||||
| ```press_fit_socket(w = 5, h = 50, horizontal = false)``` | Make a square hole to accept a peg |
|
||||
|
||||

|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
|
||||
---
|
||||
@@ -4791,7 +5061,7 @@ It can also have printed feet on the base with the screws doubling up to hold th
|
||||
### Vitamins
|
||||
| Qty | Module call | BOM entry |
|
||||
| ---:|:--- |:---|
|
||||
| 4 | ```insert(F1BM)``` | Heatfit insert M2 |
|
||||
| 4 | ```insert(F1BM2)``` | Heatfit insert M2 |
|
||||
| 4 | ```insert(F1BM3)``` | Heatfit insert M3 |
|
||||
| 4 | ```screw(M2_cap_screw, 6)``` | Screw M2 cap x 6mm |
|
||||
| 3 | ```screw(M3_pan_screw, 6)``` | Screw M3 pan x 6mm |
|
||||
@@ -4890,41 +5160,48 @@ Clamp for ribbon cable and polypropylene strip.
|
||||
### Functions
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| ```ribbon_clamp_height()``` | Height |
|
||||
| ```ribbon_clamp_hole_pitch(ways)``` | Hole pitch |
|
||||
| ```ribbon_clamp_length(ways)``` | Length given ways |
|
||||
| ```ribbon_clamp_width()``` | Width |
|
||||
| ```ribbon_clamp_height(screw = screw)``` | Height |
|
||||
| ```ribbon_clamp_length(ways, screw = screw)``` | Length given ways |
|
||||
| ```ribbon_clamp_width(screw = screw)``` | Width |
|
||||
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| ```ribbon_clamp(ways)``` | Generate STL for given number of ways |
|
||||
| ```ribbon_clamp_assembly(ways)``` | Printed part with inserts in place |
|
||||
| ```ribbon_clamp(ways, screw = screw)``` | Generate STL for given number of ways |
|
||||
| ```ribbon_clamp_assembly(ways, screw = screw)``` | Printed part with inserts in place |
|
||||
| ```ribbon_clamp_fastened_assembly(ways, thickness, screw = screw)``` | Clamp with fasteners in place |
|
||||
| ```ribbon_clamp_hole_positions(ways, side = undef)``` | Place children at hole positions |
|
||||
| ```ribbon_clamp_holes(ways, h = 20)``` | Drill screw holes |
|
||||
| ```ribbon_clamp_hole_positions(ways, screw = screw, side = undef)``` | Place children at hole positions |
|
||||
| ```ribbon_clamp_holes(ways, h = 20, screw = screw)``` | Drill screw holes |
|
||||
|
||||

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

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

|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
|
||||
---
|
||||
@@ -5254,6 +5561,7 @@ The origin of the rack is the left end of the pitch line and its width is below
|
||||
|:--- |:--- |
|
||||
| ```centre_distance(m, z1, z2, pa = 20)``` | Calculate distance between centres taking profile shift into account |
|
||||
| ```involute(r, u)``` | Involute of circle radius r at angle u in radians |
|
||||
| ```involute_gear_od(m, z, pa = 20)``` | involute gear outside diameter given modulus, tooth count and pressure angle |
|
||||
| ```involute_rack_tooth_profile(m, pa = 20, clearance = undef)``` | Calculate rack tooth profile given module and pressure angle |
|
||||
| ```involute_worm_profile(m, pa = 20, clearance = undef)``` | Calculate worm profile suitable for passing to thread() |
|
||||
| ```profile_shift(z, pa)``` | Calculate profile shift for small gears |
|
||||
@@ -5287,6 +5595,35 @@ Method to print holes in mid air. See <https://hydraraptor.blogspot.com/2014/03/
|
||||

|
||||
|
||||
|
||||
<a href="#top">Top</a>
|
||||
|
||||
---
|
||||
<a name="Horiholes"></a>
|
||||
## Horiholes
|
||||
Utilities for depicting the staircase slicing of horizontal holes made with [`teardrop_plus()`](#teardrops), see <https://hydraraptor.blogspot.com/2020/07/horiholes-2.html>
|
||||
|
||||
```horicylinder()``` makes cylinders that fit inside a round hole. Layers that are less than 2 filaments wide and layers that need more than a 45 degree overhang are omitted.
|
||||
|
||||
|
||||
[utils/horiholes.scad](utils/horiholes.scad) Implementation.
|
||||
|
||||
[tests/horiholes.scad](tests/horiholes.scad) Code for this example.
|
||||
|
||||
### Functions
|
||||
| Function | Description |
|
||||
|:--- |:--- |
|
||||
| ```teardrop_minus_x(r, y, h)``` | Calculate the ordinate of a compensated teardrop given y and layer height. |
|
||||
| ```teardrop_plus_x(r, y, h)``` | Calculate the ordinate of a compensated teardrop given y and layer height. |
|
||||
|
||||
### Modules
|
||||
| Module | Description |
|
||||
|:--- |:--- |
|
||||
| ```horicylinder(r, z, h = 0, center = true)``` | For making horizontal cylinders that don't need support material and are correct dimensions |
|
||||
| ```horihole(r, z, h = 0, center = true)``` | For making horizontal holes that don't need support material and are correct dimensions |
|
||||
|
||||

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

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

|
||||
|
||||
@@ -5725,10 +6072,13 @@ Global constants, functions and modules. This file is used directly or indirectl
|
||||
| ```foot(x)``` | Foot to mm conversion |
|
||||
| ```in(list, x)``` | Returns true if ```x``` is an element in the ```list``` |
|
||||
| ```inch(x)``` | Inch to mm conversion (For fractional inches, 'inch(1 + 7/8)' will work as expected.) |
|
||||
| ```limit(x, min, max)``` | Force x in range min <= x <= max |
|
||||
| ```m(x)``` | m to mm conversion |
|
||||
| ```mm(x)``` | Explicit mm specified |
|
||||
| ```no_point(str)``` | Replace decimal point in string with 'p' |
|
||||
| ```r2sides(r)``` | Replicates the OpenSCAD logic to calculate the number of sides from the radius |
|
||||
| ```r2sides4n(r)``` | Round up the number of sides to a multiple of 4 to ensure points land on all axes |
|
||||
| ```slice(list, start = 0, end = undef)``` | Slice a list or string with Python type semantics |
|
||||
| ```sqr(x)``` | Returns the square of ```x``` |
|
||||
| ```yard(x)``` | Yard to mm conversion |
|
||||
|
||||
@@ -5738,11 +6088,11 @@ Global constants, functions and modules. This file is used directly or indirectl
|
||||
| ```circle4n(r, d = undef)``` | Circle with multiple of 4 vertices |
|
||||
| ```ellipse(xr, yr)``` | Draw an ellipse |
|
||||
| ```extrude_if(h, center = true)``` | Extrudes 2D object to 3D when ```h``` is nonzero, otherwise leaves it 2D |
|
||||
| ```hflip()``` | Invert children by doing a 180° flip around the Y axis |
|
||||
| ```hflip(flip=true)``` | Invert children by doing a 180° flip around the Y axis |
|
||||
| ```right_triangle(width, height, h, center = true)``` | A right angled triangle with the 90° corner at the origin. 3D when ```h``` is nonzero, otherwise 2D |
|
||||
| ```semi_circle(r, d = undef)``` | A semi circle in the positive Y domain |
|
||||
| ```translate_z(z)``` | Shortcut for Z only translations |
|
||||
| ```vflip()``` | Invert children by doing a 180° flip around the X axis |
|
||||
| ```vflip(flip=true)``` | Invert children by doing a 180° flip around the X axis |
|
||||
|
||||

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

|
||||
|
||||
|
@@ -87,24 +87,25 @@ def plateup(target, part_type, usage = None):
|
||||
match = re.match(r'^ECHO: "~(.*?\.' + part_type + r').*"$', line)
|
||||
if match:
|
||||
used.append(match.group(1))
|
||||
#
|
||||
# Copy file that are not included
|
||||
#
|
||||
copied = []
|
||||
for file in os.listdir(parts_dir):
|
||||
if file.endswith('.' + part_type) and not file in used:
|
||||
src = parts_dir + '/' + file
|
||||
dst = target_dir + '/' + file
|
||||
if mtime(src) > mtime(dst):
|
||||
print("Copying %s to %s" % (src, dst))
|
||||
copyfile(src, dst)
|
||||
copied.append(file)
|
||||
#
|
||||
# Remove any cruft
|
||||
#
|
||||
targets = [file[:-4] + part_type for file in all_sources]
|
||||
for file in os.listdir(target_dir):
|
||||
if file.endswith('.' + part_type):
|
||||
if not file in targets and not file in copied:
|
||||
print("Removing %s" % file)
|
||||
os.remove(target_dir + '/' + file)
|
||||
if all_sources:
|
||||
#
|
||||
# Copy files that are not included
|
||||
#
|
||||
for file in os.listdir(parts_dir):
|
||||
if file.endswith('.' + part_type) and not file in used:
|
||||
src = parts_dir + '/' + file
|
||||
dst = target_dir + '/' + file
|
||||
if mtime(src) > mtime(dst):
|
||||
print("Copying %s to %s" % (src, dst))
|
||||
copyfile(src, dst)
|
||||
copied.append(file)
|
||||
#
|
||||
# Remove any cruft
|
||||
#
|
||||
targets = [file[:-4] + part_type for file in all_sources]
|
||||
for file in os.listdir(target_dir):
|
||||
if file.endswith('.' + part_type):
|
||||
if not file in targets and not file in copied:
|
||||
print("Removing %s" % file)
|
||||
os.remove(target_dir + '/' + file)
|
||||
|
@@ -97,7 +97,6 @@ def tests(tests):
|
||||
for dir in [deps_dir, png_dir, bom_dir]:
|
||||
if not os.path.isdir(dir):
|
||||
os.makedirs(dir)
|
||||
doc_name = "readme.md"
|
||||
index = {}
|
||||
bodies = {}
|
||||
done = []
|
||||
@@ -108,19 +107,33 @@ def tests(tests):
|
||||
#
|
||||
png_name = "libtest.png"
|
||||
scad_name = "libtest.scad"
|
||||
if not os.path.isfile(png_name):
|
||||
openscad.run(colour_scheme, "--projection=p", "--imgsize=%d,%d" % (w, h), "--camera=0,0,0,50,0,340,500", "--autocenter", "--viewall", "-o", png_name, scad_name);
|
||||
do_cmd(["magick", png_name, "-trim", "-resize", "1280", "-bordercolor", background, "-border", "10", png_name])
|
||||
if os.path.isfile(scad_name):
|
||||
libtest = True
|
||||
lib_blurb = scrape_blurb(scad_name)
|
||||
if not os.path.isfile(png_name):
|
||||
openscad.run(colour_scheme, "--projection=p", "--imgsize=%d,%d" % (w, h), "--camera=0,0,0,50,0,340,500", "--autocenter", "--viewall", "-o", png_name, scad_name);
|
||||
do_cmd(["magick", png_name, "-trim", "-resize", "1280", "-bordercolor", background, "-border", "10", png_name])
|
||||
else:
|
||||
#
|
||||
# Project tests so just a title
|
||||
#
|
||||
libtest = False
|
||||
project = ' '.join(word[0].upper() + word[1:] for word in os.path.basename(os.getcwd()).split('_'))
|
||||
lib_blurb = '#' + project + ' Tests\n'
|
||||
|
||||
doc_base_name = "readme" if libtest else "tests"
|
||||
doc_name = doc_base_name + ".md"
|
||||
#
|
||||
# List of individual part files
|
||||
#
|
||||
scads = [i for i in sorted(os.listdir(scad_dir), key = lambda s: s.lower()) if i[-5:] == ".scad"]
|
||||
|
||||
scads = [i for i in sorted(os.listdir(scad_dir), key = lambda s: s.lower()) if i[-5:] == ".scad"]
|
||||
types = []
|
||||
for scad in scads:
|
||||
base_name = scad[:-5]
|
||||
if not tests or base_name in tests:
|
||||
done.append(base_name)
|
||||
print(base_name)
|
||||
print('\n'+base_name)
|
||||
cap_name = base_name[0].capitalize() + base_name[1:]
|
||||
base_name = base_name.lower()
|
||||
scad_name = scad_dir + '/' + scad
|
||||
@@ -132,29 +145,42 @@ def tests(tests):
|
||||
if is_plural(base_name) and os.path.isfile(vits_name):
|
||||
objects_name = vits_name
|
||||
|
||||
locations = [
|
||||
('vitamins/' + depluralise(base_name) + '.scad', 'Vitamins'),
|
||||
('printed/' + base_name + '.scad', 'Printed'),
|
||||
('utils/' + base_name + '.scad', 'Utilities'),
|
||||
('utils/core/' + base_name + '.scad', 'Core Utilities'),
|
||||
]
|
||||
locations = []
|
||||
if os.path.isdir('vitamins'):
|
||||
locations.append(('vitamins/' + depluralise(base_name) + '.scad', 'Vitamins'))
|
||||
if os.path.isdir('printed'):
|
||||
locations.append(('printed/' + base_name + '.scad', 'Printed'))
|
||||
if os.path.isdir('utils'):
|
||||
locations.append(('utils/' + base_name + '.scad', 'Utilities'))
|
||||
if libtest and os.path.isdir('utils/core'):
|
||||
locations.append(('utils/core/' + base_name + '.scad', 'Core Utilities'))
|
||||
|
||||
for name, type in locations:
|
||||
if os.path.isfile(name):
|
||||
impl_name = name
|
||||
break
|
||||
else:
|
||||
print("Can't find implementation!")
|
||||
continue
|
||||
if libtest:
|
||||
print("Can't find implementation!")
|
||||
continue
|
||||
else:
|
||||
type = 'Tests' # OK when testing part of a project
|
||||
impl_name = None
|
||||
|
||||
vsplit = "AJR" + chr(ord('Z') + 1)
|
||||
vtype = locations[0][1]
|
||||
types = [vtype + ' ' + vsplit[i] + '-' + chr(ord(vsplit[i + 1]) - 1) for i in range(len(vsplit) - 1)] + [loc[1] for loc in locations[1 :]]
|
||||
if type == vtype:
|
||||
for i in range(1, len(vsplit)):
|
||||
if cap_name[0] < vsplit[i]:
|
||||
type = types[i - 1]
|
||||
break
|
||||
if libtest:
|
||||
vsplit = "AJR" + chr(ord('Z') + 1)
|
||||
vtype = locations[0][1]
|
||||
types = [vtype + ' ' + vsplit[i] + '-' + chr(ord(vsplit[i + 1]) - 1) for i in range(len(vsplit) - 1)] + [loc[1] for loc in locations[1 :]]
|
||||
if type == vtype:
|
||||
for i in range(1, len(vsplit)):
|
||||
if cap_name[0] < vsplit[i]:
|
||||
type = types[i - 1]
|
||||
break
|
||||
else:
|
||||
if not types:
|
||||
types = [loc[1] for loc in locations] # No need to split up the vitamin list
|
||||
if not type in types: # Will happen when implementation is not found and type is set to Tests
|
||||
types.append(type)
|
||||
|
||||
for t in types:
|
||||
if not t in bodies:
|
||||
@@ -250,24 +276,7 @@ def tests(tests):
|
||||
usage()
|
||||
|
||||
with open(doc_name, "wt") as doc_file:
|
||||
print('# NopSCADlib', file = doc_file)
|
||||
print('''\
|
||||
An ever expanding library of parts modelled in OpenSCAD useful for 3D printers and enclosures for electronics, etc.
|
||||
|
||||
It contains lots of vitamins (the RepRap term for non-printed parts), some general purpose printed parts and
|
||||
some utilities. There are also Python scripts to generate Bills of Materials (BOMs),
|
||||
STL files for all the printed parts, DXF files for CNC routed parts in a project and a manual containing assembly
|
||||
instructions and exploded views by scraping markdown embedded in OpenSCAD comments, [see scripts](scripts/readme.md). A simple example project can be found [here](examples/MainsBreakOutBox/readme.md).
|
||||
|
||||
For more examples of what it can make see the [gallery](gallery/readme.md).
|
||||
|
||||
The license is GNU General Public License v3.0, see [COPYING](COPYING).
|
||||
|
||||
See [usage](docs/usage.md) for requirements, installation instructions and a usage guide.
|
||||
|
||||
<img src="libtest.png" width="100%"/>\n
|
||||
''', file = doc_file)
|
||||
|
||||
print(lib_blurb, file = doc_file)
|
||||
print('## Table of Contents<a name="top"/>', file = doc_file)
|
||||
print('<table><tr>', file = doc_file)
|
||||
n = 0
|
||||
@@ -288,10 +297,10 @@ See [usage](docs/usage.md) for requirements, installation instructions and a usa
|
||||
for type in types:
|
||||
for line in bodies[type]:
|
||||
print(line, file = doc_file)
|
||||
with open("readme.html", "wt") as html_file:
|
||||
do_cmd("python -m markdown -x tables readme.md".split(), html_file)
|
||||
with open(doc_base_name + ".html", "wt") as html_file:
|
||||
do_cmd(("python -m markdown -x tables " + doc_name).split(), html_file)
|
||||
times.print_times()
|
||||
do_cmd('codespell -L od readme.md'.split())
|
||||
do_cmd(('codespell -L od ' + doc_name).split())
|
||||
|
||||
if __name__ == '__main__':
|
||||
for arg in sys.argv[1:]:
|
||||
|
@@ -86,10 +86,13 @@ test_pcb = ["TestPCB", "Test PCB",
|
||||
[ 5, 218, 180, "hdmi"],
|
||||
[ 3, 235, 180, "mini_hdmi"],
|
||||
[ 6, 175, 180, "uSD", [12, 11.5, 1.4]],
|
||||
|
||||
[ 65, 9, 0, "link", inch(0.4)],
|
||||
[ 65, 12, 0, "ax_res", res1_8, 1000],
|
||||
[ 65, 17, 0, "ax_res", res1_4, 10000],
|
||||
[ 65, 22, 0, "ax_res", res1_2, 100000],
|
||||
|
||||
[ 80, 9, 0, "link", inch(0.2), inch(0.4)],
|
||||
[ 80, 12, 0, "ax_res", res1_8, 1000000, 1, inch(0.1)],
|
||||
[ 80, 17, 0, "ax_res", res1_4, 100, 2, inch(0.1)],
|
||||
[ 80, 22, 0, "ax_res", res1_2, 10, 10, inch(0.2)],
|
||||
@@ -118,7 +121,8 @@ test_pcb = ["TestPCB", "Test PCB",
|
||||
[ 70, 130, 180, "term35", 3, "lime"],
|
||||
[ 50, 150, 0, "transition", 5],
|
||||
[ 50, 160, 0, "block", 10, 5, 8, "orange"],
|
||||
[ 50, 170, 0, "button_6mm"],
|
||||
[ 45, 170, 0, "button_6mm"],
|
||||
[ 55, 170, 0, "button_4p5mm"],
|
||||
[ 50, 185, 0, "microswitch", small_microswitch],
|
||||
[ 52, 200, 0, "pcb", 11, TMC2130 ],
|
||||
[ 80, 200, 0, "pdip", 24, "27C32", true, inch(0.6) ],
|
||||
|
@@ -23,46 +23,52 @@ use <../vitamins/insert.scad>
|
||||
use <../utils/layout.scad>
|
||||
|
||||
module belt_test() {
|
||||
p1 = [75, -50];
|
||||
p2 = [-75, -50];
|
||||
p3 = [-75, 100];
|
||||
p4 = [75, 100];
|
||||
|
||||
p5 = [75 - pulley_pr(GT2x20ob_pulley) - pulley_pr(GT2x16_plain_idler), -pulley_pr(GT2x16_plain_idler)];
|
||||
p6 = [-75 + pulley_pr(GT2x20ob_pulley) + pulley_pr(GT2x16_plain_idler), -pulley_pr(GT2x16_plain_idler)];
|
||||
p5 = [75 + pulley_pr(GT2x20ob_pulley) - pulley_pr(GT2x16_plain_idler), +pulley_pr(GT2x16_plain_idler)];
|
||||
p6 = [-75 + pulley_pr(GT2x20ob_pulley) + pulley_pr(GT2x16_plain_idler), -pulley_pr(GT2x16_plain_idler)];
|
||||
|
||||
translate(p1) pulley_assembly(GT2x20ob_pulley);
|
||||
translate(p2) pulley_assembly(GT2x20ob_pulley);
|
||||
translate(p3) pulley_assembly(GT2x20_toothed_idler);
|
||||
translate(p4) pulley_assembly(GT2x20_toothed_idler);
|
||||
module pulleys(flip = false) {
|
||||
translate(p2) rotate([0, flip ? 180 : 0, 0]) pulley_assembly(GT2x20ob_pulley);
|
||||
translate(p3) pulley_assembly(GT2x20_toothed_idler);
|
||||
translate(p4) pulley_assembly(GT2x20_toothed_idler);
|
||||
translate(p5) {
|
||||
pulley = GT2x16_toothed_idler;
|
||||
screw = find_screw(hs_cs_cap, pulley_bore(pulley));
|
||||
insert = screw_insert(screw);
|
||||
|
||||
translate(p5) {
|
||||
pulley = GT2x16_plain_idler;
|
||||
screw = find_screw(hs_cs_cap, pulley_bore(pulley));
|
||||
insert = screw_insert(screw);
|
||||
|
||||
pulley_assembly(pulley);
|
||||
translate_z(pulley_height(pulley) + pulley_offset(pulley) + screw_head_depth(screw, pulley_bore(pulley)))
|
||||
screw(screw, 20);
|
||||
|
||||
translate_z(pulley_offset(pulley) - insert_length(insert))
|
||||
vflip()
|
||||
insert(insert);
|
||||
hflip(flip) {
|
||||
pulley_assembly(pulley);
|
||||
translate_z(pulley_height(pulley) + pulley_offset(pulley) + screw_head_depth(screw, pulley_bore(pulley)))
|
||||
screw(screw, 20);
|
||||
|
||||
translate_z(pulley_offset(pulley) - insert_length(insert))
|
||||
vflip()
|
||||
insert(insert);
|
||||
}
|
||||
}
|
||||
translate(p6) pulley_assembly(GT2x16_plain_idler);
|
||||
}
|
||||
translate(p6) pulley_assembly(GT2x16_plain_idler);
|
||||
|
||||
path = [ [p1.x, p1.y, pulley_pr(GT2x20ob_pulley)],
|
||||
[p5.x, p5.y, -pulley_pr(GT2x16_plain_idler)],
|
||||
path = [ [p5.x, p5.y, pulley_pr(GT2x16_plain_idler)],
|
||||
[p6.x, p6.y, -pulley_pr(GT2x16_plain_idler)],
|
||||
[p2.x, p2.y, pulley_pr(GT2x20ob_pulley)],
|
||||
[p3.x, p3.y, pulley_pr(GT2x20ob_pulley)],
|
||||
[p4.x, p4.y, pulley_pr(GT2x20ob_pulley)]
|
||||
];
|
||||
belt = GT2x6;
|
||||
belt(belt, path, 80, [0, belt_pitch_height(belt) - belt_thickness(belt) / 2]);
|
||||
|
||||
translate([-25, 0])
|
||||
belt = GT2x6;
|
||||
belt(belt, path, 80, [0, 0]);
|
||||
pulleys();
|
||||
translate_z(20)
|
||||
hflip() {
|
||||
belt(belt, path, 80, [0, 0], belt_colour = grey(90), tooth_colour = grey(50));
|
||||
pulleys(flip=true);
|
||||
}
|
||||
|
||||
translate([-25, 0, 10])
|
||||
layout([for(b = belts) belt_width(b)], 10)
|
||||
rotate([0, 90, 0])
|
||||
belt(belts[$i], [[0, 0, 20], [0, 1, 20]], belt_colour = $i%2==0 ? grey(90) : grey(20), tooth_colour = $i%2==0 ? grey(70) : grey(50));
|
||||
|
33
tests/camera_housing.scad
Normal file
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// NopSCADlib Copyright Chris Palmer 2020
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// This file is part of NopSCADlib.
|
||||
//
|
||||
// NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
|
||||
// GNU General Public License as published by the Free Software Foundation, either version 3 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// See the GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with NopSCADlib.
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
include <../core.scad>
|
||||
use <../utils/layout.scad>
|
||||
|
||||
use <../printed/camera_housing.scad>
|
||||
|
||||
include <../vitamins/cameras.scad>
|
||||
|
||||
use <../vitamins/pcb.scad>
|
||||
|
||||
module camera_housings()
|
||||
layout([for(c = cameras) pcb_length(camera_pcb(c))], 15, false) let(c = cameras[$i])
|
||||
camera_fastened_assembly(c, 3);
|
||||
|
||||
if($preview)
|
||||
camera_housings();
|
@@ -24,7 +24,7 @@ include <../vitamins/cameras.scad>
|
||||
use <../vitamins/pcb.scad>
|
||||
|
||||
module cameras()
|
||||
layout([for(c = cameras) pcb_length(camera_pcb(c))], 10, false) let(c = cameras[$i])
|
||||
layout([for(c = cameras) pcb_length(camera_pcb(c))], 15, false) let(c = cameras[$i])
|
||||
camera(c);
|
||||
|
||||
if($preview)
|
||||
|
56
tests/catenary.scad
Normal file
@@ -0,0 +1,56 @@
|
||||
//
|
||||
// NopSCADlib Copyright Chris Palmer 2020
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// This file is part of NopSCADlib.
|
||||
//
|
||||
// NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
|
||||
// GNU General Public License as published by the Free Software Foundation, either version 3 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// See the GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with NopSCADlib.
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
l = 250; // [1: 1000]
|
||||
x = 200; // [1: 1000]
|
||||
y = 50; //[-500 : 500]
|
||||
|
||||
include <../utils/core/core.scad>
|
||||
use <../utils/catenary.scad>
|
||||
use <../utils/sweep.scad>
|
||||
use <../utils/annotation.scad>
|
||||
|
||||
module catenaries() {
|
||||
//
|
||||
// catenary curve path from control points
|
||||
//
|
||||
curve = [for(p = catenary_points(l, x, y)) [p.x, p.y, 0]];
|
||||
//
|
||||
// Draw the curve
|
||||
//
|
||||
r = 0.5;
|
||||
sweep(curve, circle_points(r, $fn = 64));
|
||||
//
|
||||
// Minimum Z
|
||||
//
|
||||
min_z = catenary_points(l, x, y, 0);
|
||||
|
||||
color("blue") {
|
||||
translate([min_z.x, min_z.y + r])
|
||||
rotate([-90, 0, 0])
|
||||
arrow();
|
||||
|
||||
translate([min_z.x, min_z.y - r])
|
||||
rotate([90, 0, 0])
|
||||
arrow();
|
||||
}
|
||||
}
|
||||
|
||||
if($preview)
|
||||
rotate(is_undef($bom) ? 0 : [70, 0, 315])
|
||||
catenaries();
|
59
tests/drag_chain.scad
Normal file
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
// Link length between hinges
|
||||
x = 10; //[8 : 30]
|
||||
|
||||
// Link inner width
|
||||
y = 10; //[5 : 30]
|
||||
|
||||
// Link inner height
|
||||
z = 5; //[4 : 11]
|
||||
// Side wall thickness
|
||||
wall = 1.6; //[0.9: 0.1: 3]
|
||||
// Bottom wall thickness
|
||||
bwall = 1.5; //[1: 0.25: 3]
|
||||
// Top wall thickness
|
||||
twall = 1.5; //[1: 0.25: 3]
|
||||
// Max travel in each direction
|
||||
travel = 100;
|
||||
// Current position
|
||||
pos = 50; // [-100 : 1 : 100]
|
||||
|
||||
include <../core.scad>
|
||||
use <../printed/drag_chain.scad>
|
||||
|
||||
include <../vitamins/leadnuts.scad>
|
||||
|
||||
drag_chain = drag_chain("x", [x, y, z], travel, wall = wall, bwall = bwall, twall = twall);
|
||||
|
||||
module drag_chains()
|
||||
drag_chain_assembly(drag_chain, pos);
|
||||
|
||||
if($preview)
|
||||
drag_chains();
|
||||
else {
|
||||
drag_chain_link(drag_chain);
|
||||
|
||||
translate([-x * 2, 0])
|
||||
drag_chain_link(drag_chain, start = true);
|
||||
|
||||
translate([x * 2, 0])
|
||||
drag_chain_link(drag_chain, end = true);
|
||||
}
|
@@ -21,14 +21,14 @@ use <../printed/foot.scad>
|
||||
|
||||
module feet()
|
||||
if($preview) {
|
||||
translate([50, 0])
|
||||
translate([40, 0])
|
||||
foot_assembly(3);
|
||||
|
||||
translate([foot_diameter(insert_foot()) / 2, 0])
|
||||
fastened_insert_foot_assembly(3);
|
||||
}
|
||||
else {
|
||||
translate([50, 0])
|
||||
translate([40, 0])
|
||||
foot();
|
||||
|
||||
insert_foot();
|
||||
|
@@ -29,6 +29,23 @@ module globals() {
|
||||
translate([50, 0])
|
||||
right_triangle(10, 20, 0);
|
||||
}
|
||||
assert(slice("ABCD") == "ABCD");
|
||||
assert(slice("ABCD", 1) == "BCD");
|
||||
assert(slice("ABCD", 2) == "CD");
|
||||
assert(slice("ABCD", 3) == "D");
|
||||
assert(slice("ABCD", 4) == "");
|
||||
assert(slice("ABCD", 1, -1) == "BC");
|
||||
assert(slice("ABCD", 2, -1) == "C");
|
||||
assert(slice("ABCD", 3, -1) == "");
|
||||
assert(slice("ABCD", 4, -1) == "");
|
||||
assert(slice("ABCD", 0, -1) == "ABC");
|
||||
assert(slice("ABCD", 0, -2) == "AB");
|
||||
assert(slice("ABCD", 0, -3) == "A");
|
||||
assert(slice("ABCD", 0, -4) == "");
|
||||
assert(slice("ABCD", 0, 0) == "");
|
||||
assert(slice("ABCD", 0, 1) == "A");
|
||||
assert(slice("ABCD", 0, 2) == "AB");
|
||||
assert(slice("ABCD", 0, 3) == "ABC");
|
||||
}
|
||||
|
||||
rotate([70, 0, 315]) globals();
|
||||
|
94
tests/horiholes.scad
Normal file
@@ -0,0 +1,94 @@
|
||||
//
|
||||
// NopSCADlib Copyright Chris Palmer 2020
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// This file is part of NopSCADlib.
|
||||
//
|
||||
// NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
|
||||
// GNU General Public License as published by the Free Software Foundation, either version 3 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// See the GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with NopSCADlib.
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
$layer_height = 0.25;
|
||||
include <../utils/core/core.scad>
|
||||
use <../utils/horiholes.scad>
|
||||
|
||||
show_disc = true;
|
||||
use_horihole = true;
|
||||
thickness = 6;
|
||||
length = 60;
|
||||
height = 20;
|
||||
overlap_x = 15;
|
||||
overlap_y = 10;
|
||||
|
||||
module hole_positions() {
|
||||
x0 = (length - 40) / 2;
|
||||
for($i = [0 : 4], $z = 5 + $i * layer_height / 5, $r = 3)
|
||||
translate([x0 + $i * 10, $z])
|
||||
children();
|
||||
|
||||
for($i = [0 : 4], $z = 15 + $i * layer_height / 5, $r = 0.5 + $i / 2)
|
||||
translate([x0 + $i * 10, $z])
|
||||
children();
|
||||
}
|
||||
|
||||
module horiholes_stl(t = thickness) {
|
||||
rotate([90, 0, 0])
|
||||
difference() {
|
||||
linear_extrude(t, center = true) {
|
||||
difference() {
|
||||
square([length, height]);
|
||||
|
||||
hole_positions()
|
||||
if(use_horihole)
|
||||
horihole($r, $z);
|
||||
else
|
||||
teardrop_plus(h = 0, r = $r);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(t == thickness)
|
||||
translate([length / 2, 0])
|
||||
rounded_rectangle([length + 2 * overlap_x, thickness + 2 * overlap_y, 2], 5);
|
||||
}
|
||||
|
||||
module horiholes() {
|
||||
stl_colour(pp1_colour)
|
||||
rotate([-90, 0, 0])
|
||||
horiholes_stl(eps);
|
||||
|
||||
if(show_disc)
|
||||
hole_positions()
|
||||
color(silver)
|
||||
cylinder(r = $r, h = eps, center = true, $fn = 360);
|
||||
|
||||
hole_positions()
|
||||
color("blue")
|
||||
horicylinder(r = $r, z = $z, h = 2 * eps, center = true, $fn = 360);
|
||||
|
||||
hole_positions()
|
||||
color("red")
|
||||
linear_extrude(3 * eps, center = true)
|
||||
intersection() {
|
||||
difference() {
|
||||
square(8, center = true);
|
||||
|
||||
horihole($r, $z);
|
||||
}
|
||||
|
||||
circle($r, $fn = 360);
|
||||
}
|
||||
}
|
||||
|
||||
if($preview)
|
||||
rotate(is_undef($bom) ? 0 : [70, 0, 315])
|
||||
horiholes();
|
||||
else
|
||||
horiholes_stl();
|
@@ -25,7 +25,7 @@ module hot_ends()
|
||||
layout([for(h = hot_ends) 40])
|
||||
translate([-20, 0])
|
||||
rotate(90)
|
||||
hot_end(hot_ends[$i], 3);
|
||||
hot_end(hot_ends[$i], 3, bowden = $i == 3);
|
||||
|
||||
if($preview)
|
||||
hot_ends();
|
||||
|
29
tests/magnets.scad
Normal file
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// NopSCADlib Copyright Chris Palmer 2020
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// This file is part of NopSCADlib.
|
||||
//
|
||||
// NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
|
||||
// GNU General Public License as published by the Free Software Foundation, either version 3 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// See the GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with NopSCADlib.
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
include <../core.scad>
|
||||
use <../utils/layout.scad>
|
||||
|
||||
include <../vitamins/magnets.scad>
|
||||
|
||||
module magnets()
|
||||
layout([for(m = magnets) magnet_od(m)], 5)
|
||||
magnet(magnets[$i]);
|
||||
|
||||
if($preview)
|
||||
magnets();
|
@@ -69,6 +69,33 @@ module maths() {
|
||||
// Test Euler
|
||||
//
|
||||
assert(euler(rotate(r)) == r, "euler() failed");
|
||||
//
|
||||
// Circle intersect
|
||||
//
|
||||
r1 = 10;
|
||||
c1 = [50, 0, 10];
|
||||
r2 = 20;
|
||||
c2 = [67, 0, 0];
|
||||
p1 = circle_intersect(c1, r1, c2, r2);
|
||||
p2 = circle_intersect(c2, r2, c1, r1);
|
||||
|
||||
rotate(90) {
|
||||
color(grey(90))
|
||||
translate(c1) rotate([90, 0, 0]) cylinder(r = r1, h = 4 * eps, center = true);
|
||||
|
||||
color(grey(80))
|
||||
translate(c2) rotate([90, 0, 0]) cylinder(r = r2, h = eps, center = true);
|
||||
|
||||
color("red")
|
||||
translate(p1) rotate([90, 0, 0]) cylinder(r = 0.1, h = 6 * eps, center = true);
|
||||
|
||||
color("blue")
|
||||
translate(p2) rotate([90, 0, 0]) cylinder(r = 0.1, h = 6 * eps, center = true);
|
||||
|
||||
translate(p1) arrow();
|
||||
|
||||
translate(p2) vflip() arrow();
|
||||
}
|
||||
}
|
||||
|
||||
rotate(45)
|
||||
|
@@ -21,11 +21,11 @@ include <../utils/core/core.scad>
|
||||
use <../vitamins/opengrab.scad>
|
||||
|
||||
module opengrab_test() {
|
||||
opengrab_target();
|
||||
|
||||
rotate(45)
|
||||
translate_z(opengrab_target_thickness())
|
||||
opengrab();
|
||||
opengrab_target();
|
||||
|
||||
translate_z(opengrab_target_thickness())
|
||||
opengrab();
|
||||
}
|
||||
|
||||
if($preview)
|
||||
|
@@ -23,26 +23,56 @@ include <../vitamins/pin_headers.scad>
|
||||
|
||||
pins = 10;
|
||||
|
||||
module pin_headers()
|
||||
module pin_headers() {
|
||||
layout([for(p = pin_headers) hdr_pitch(p) * pins], 15) {
|
||||
idc_transition(pin_headers[$i], 10);
|
||||
|
||||
translate([0, 20])
|
||||
pin_header(pin_headers[$i], 10, 2, right_angle = true);
|
||||
pin_header(pin_headers[$i], 3, 2, right_angle = true);
|
||||
|
||||
translate([-10, 20])
|
||||
pin_header(pin_headers[$i], 3, 1, right_angle = true);
|
||||
|
||||
translate([10, 20])
|
||||
pin_header(pin_headers[$i], 3, 3, right_angle = true);
|
||||
|
||||
translate([0, 30])
|
||||
pin_header(pin_headers[$i], 8, 1);
|
||||
|
||||
translate([0, 40])
|
||||
pin_header(pin_headers[$i], 10, 2);
|
||||
|
||||
translate([0, 50])
|
||||
box_header(pin_headers[$i], 8, 1);
|
||||
|
||||
translate([0, 60])
|
||||
box_header(pin_headers[$i], 10, 2);
|
||||
|
||||
translate([0, 70])
|
||||
pin_socket(pin_headers[$i], 8, 1);
|
||||
|
||||
translate([0, 80])
|
||||
pin_socket(pin_headers[$i], 10, 2);
|
||||
|
||||
translate([0, 110])
|
||||
pin_socket(pin_headers[$i], 10, 2, right_angle = true);
|
||||
translate([-10, 105])
|
||||
pin_socket(pin_headers[$i], 3, 1, right_angle = true);
|
||||
|
||||
translate([0, 105])
|
||||
pin_socket(pin_headers[$i], 3, 2, right_angle = true);
|
||||
|
||||
translate([10, 105])
|
||||
pin_socket(pin_headers[$i], 3, 3, right_angle = true);
|
||||
}
|
||||
|
||||
for(i = [0, 1], p = [5, 2][i], j = [0 , 1]) {
|
||||
h = [jst_ph_header, jst_xh_header][j];
|
||||
translate([-20 * (i + 1), 0 + j * 40])
|
||||
jst_xh_header(h, p);
|
||||
|
||||
translate([-20 * (i + 1), 20 + j * 40])
|
||||
jst_xh_header(h, p, true);
|
||||
}
|
||||
}
|
||||
|
||||
if($preview)
|
||||
pin_headers();
|
||||
|
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 95 KiB |
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 133 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 112 KiB |
BIN
tests/png/camera_housing.png
Normal file
After Width: | Height: | Size: 106 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 68 KiB |
BIN
tests/png/catenary.png
Normal file
After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 118 KiB |
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 76 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 74 KiB |
BIN
tests/png/drag_chain.png
Normal file
After Width: | Height: | Size: 133 KiB |
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 119 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 117 KiB |
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 148 KiB |
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 102 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
BIN
tests/png/horiholes.png
Normal file
After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 118 KiB |
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 85 KiB |
BIN
tests/png/magnets.png
Normal file
After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 97 KiB |
Before Width: | Height: | Size: 172 KiB After Width: | Height: | Size: 174 KiB |
Before Width: | Height: | Size: 161 KiB After Width: | Height: | Size: 152 KiB |
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 166 KiB |
BIN
tests/png/press_fit.png
Normal file
After Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 137 KiB After Width: | Height: | Size: 137 KiB |
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 90 KiB |
Before Width: | Height: | Size: 188 KiB After Width: | Height: | Size: 188 KiB |
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 84 KiB |
BIN
tests/png/shaft_couplings.png
Normal file
After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 160 KiB |
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 104 KiB |
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 150 KiB |
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 72 KiB |
71
tests/press_fit.scad
Normal file
@@ -0,0 +1,71 @@
|
||||
//
|
||||
// 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 <../printed/press_fit.scad>
|
||||
|
||||
module press_fits()
|
||||
{
|
||||
thickness = 2;
|
||||
width = 20;
|
||||
vthickness = 4;
|
||||
|
||||
translate([0, width + 2])
|
||||
difference() {
|
||||
cube([width, width, thickness]);
|
||||
|
||||
for(x = [0.25, 0.75])
|
||||
for(y = [0.25, 0.75])
|
||||
translate([x * width, y * width])
|
||||
press_fit_socket();
|
||||
}
|
||||
|
||||
union() {
|
||||
cube([width, width, thickness]);
|
||||
|
||||
for(x = [0.25, 0.75])
|
||||
for(y = [0.25, 0.75])
|
||||
translate([x * width, y * width, thickness])
|
||||
press_fit_peg(h = thickness);
|
||||
}
|
||||
|
||||
translate([width + 2, width + 2])
|
||||
difference() {
|
||||
cube([width, vthickness, width]);
|
||||
|
||||
for(x = [0.25, 0.75])
|
||||
for(y = [0.25, 0.75])
|
||||
translate([x, 0, y] * width)
|
||||
rotate([90, 0, 0])
|
||||
press_fit_socket();
|
||||
}
|
||||
|
||||
translate([width + 2, 0])
|
||||
union() {
|
||||
cube([width, width, thickness]);
|
||||
|
||||
for(x = [0.25, 0.75])
|
||||
for(y = [0.25, 0.75])
|
||||
translate([x * width, y * width, thickness])
|
||||
press_fit_peg(h = vthickness, horizontal = true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
press_fits();
|
@@ -67,7 +67,7 @@ module box1_external_additions() {
|
||||
|
||||
module box1_holes() {
|
||||
box1_feet_positions()
|
||||
teardrop(r = screw_pilot_hole(foot_screw(foot)), h = 10, center = true);
|
||||
teardrop_plus(r = screw_pilot_hole(foot_screw(foot)), h = 10, center = true);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -23,6 +23,7 @@ use <../utils/layout.scad>
|
||||
use <../vitamins/nut.scad>
|
||||
|
||||
sheet = 3;
|
||||
pos = 1; //[-1 : 0.1 : 1]
|
||||
|
||||
module rails()
|
||||
layout([for(l = rails) carriage_width(rail_carriage(l))], 20)
|
||||
@@ -33,7 +34,7 @@ module rails()
|
||||
nut = screw_nut(screw);
|
||||
washer = screw_washer(screw);
|
||||
|
||||
rail_assembly(rail, length, rail_travel(rail, length) / 2, $i<2 ? grey(20) : "green", $i<2 ? grey(20) : "red");
|
||||
rail_assembly(rail, length, pos * rail_travel(rail, length) / 2, $i<2 ? grey(20) : "green", $i<2 ? grey(20) : "red");
|
||||
|
||||
rail_screws(rail, length, sheet + nut_thickness(nut, true) + washer_thickness(washer));
|
||||
|
||||
|
@@ -16,20 +16,22 @@
|
||||
// You should have received a copy of the GNU General Public License along with NopSCADlib.
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
include <../utils/core/core.scad>
|
||||
include <../core.scad>
|
||||
use <../printed/ribbon_clamp.scad>
|
||||
use <../vitamins/wire.scad>
|
||||
|
||||
ways = 20;
|
||||
ways = [8, 20];
|
||||
screws = [M2_dome_screw, M3_cap_screw];
|
||||
|
||||
module ribbon_clamps()
|
||||
translate([ribbon_clamp_length(ways) / 2, 0])
|
||||
if($preview) {
|
||||
ribbon_clamp_fastened_assembly(ways, 3);
|
||||
for(i = [0 : len(screws) - 1])
|
||||
translate([ribbon_clamp_length(ways[i]) / 2, i * 30])
|
||||
if($preview) {
|
||||
ribbon_clamp_fastened_assembly(ways[i], 3, screws[i]);
|
||||
|
||||
ribbon_cable(ways, 100);
|
||||
}
|
||||
else
|
||||
ribbon_clamp(ways);
|
||||
ribbon_cable(ways[i], 100);
|
||||
}
|
||||
else
|
||||
ribbon_clamp(ways[i], screws[i]);
|
||||
|
||||
ribbon_clamps();
|
||||
|
30
tests/shaft_couplings.scad
Normal file
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// NopSCADlib Copyright Chris Palmer 2018
|
||||
// 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/shaft_couplings.scad>
|
||||
|
||||
use <../utils/layout.scad>
|
||||
|
||||
module shaft_couplings()
|
||||
layout([for(s = shaft_couplings) sc_diameter(s)],5)
|
||||
shaft_coupling(shaft_couplings[$i]);
|
||||
|
||||
if($preview)
|
||||
shaft_couplings();
|
||||
|
@@ -22,12 +22,12 @@ include <../vitamins/stepper_motors.scad>
|
||||
use <../utils/layout.scad>
|
||||
|
||||
module stepper_motors()
|
||||
layout([for(s = stepper_motors) NEMA_width(s)], 5) {
|
||||
layout([for(s = stepper_motors) NEMA_width(s)], 5) let(m = stepper_motors[$i]) {
|
||||
rotate(180)
|
||||
NEMA(stepper_motors[$i]);
|
||||
NEMA(m, 0, m == NEMA17M || m == NEMA17M8);
|
||||
|
||||
translate_z(4)
|
||||
NEMA_screws(stepper_motors[$i], M3_pan_screw, n = $i, earth = $i > 4 ? undef : $i - 1);
|
||||
NEMA_screws(m, M3_pan_screw, n = $i, earth = $i > 4 ? undef : $i - 1);
|
||||
}
|
||||
|
||||
if($preview)
|
||||
|
@@ -41,7 +41,10 @@ module teardrops() {
|
||||
|
||||
translate([20, 10])
|
||||
semi_teardrop(h = 0, r = 3);
|
||||
}
|
||||
|
||||
translate([20, 20])
|
||||
teardrop(h = 0, r = 3, truncate = false, plus = true);
|
||||
}
|
||||
}
|
||||
translate([40, 0, 1.5]) {
|
||||
h = 3 + eps;
|
||||
@@ -61,6 +64,9 @@ module teardrops() {
|
||||
|
||||
translate([20, 10])
|
||||
semi_teardrop(h = h, r = 3, chamfer = chamfer);
|
||||
|
||||
translate([20, 20])
|
||||
teardrop(h = h, r = 3, truncate = false, plus = false, chamfer = chamfer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -22,7 +22,7 @@ use <../utils/layout.scad>
|
||||
include <../vitamins/tubings.scad>
|
||||
|
||||
module tubings()
|
||||
layout([for(t = tubings) tubing_od(t)], 10)
|
||||
layout([for(t = tubings) tubing_od(t)], 8)
|
||||
tubing(tubings[$i]);
|
||||
|
||||
if($preview)
|
||||
|
52
utils/catenary.scad
Normal file
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// NopSCADlib Copyright Chris Palmer 2020
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// This file is part of NopSCADlib.
|
||||
//
|
||||
// NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
|
||||
// GNU General Public License as published by the Free Software Foundation, either version 3 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// See the GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with NopSCADlib.
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
//
|
||||
//! Catenary curve to model hanging wires, etc.
|
||||
//!
|
||||
//! Although the equation of the curve is simply ```y = a cosh(x / a)``` there is no explicit formula to calculate the constant ```a``` or the range of ```x``` given the
|
||||
//! length of the cable and the end point coordinates. See <https://en.wikipedia.org/wiki/Catenary#Determining_parameters>. The Newton-Raphson method is used to find
|
||||
//! ```a``` numerically, see <https://en.wikipedia.org/wiki/Newton%27s_method>.
|
||||
//!
|
||||
//! The coordinates of the lowest point on the curve can be retrieved by calling ```catenary_points()``` with ```steps``` equal to zero.
|
||||
//
|
||||
include <core/core.scad>
|
||||
use <maths.scad>
|
||||
|
||||
function catenary(t, a) = let(u = argsinh(t)) a * [u, cosh(u)]; //! Parametric catenary function linear along the length of the curve.
|
||||
function catenary_s(d, a) = 2 * a * sinh(d / a); //! Length of a symmetric catenary with width ```2d```.
|
||||
function catenary_ds_by_da(d, a) = 2 * sinh(d / a) - 2 * d / a * cosh(d / a); //! First derivative of the length with respect to ```a```.
|
||||
|
||||
function catenary_find_a(d, l, a = 1, best_e = inf, best_a = 1) = //! Find the catenary constant ```a```, given half the horizontal span and the length.
|
||||
assert(l > 2 * d, "Not long enough to span the gap") assert(d) let(error = abs(catenary_s(d, a) - l))
|
||||
error >= best_e && error < 0.0001 ? best_a
|
||||
: catenary_find_a(d, l, max(a - (catenary_s(d, a) - l) / catenary_ds_by_da(d, a), d / argsinh(1e99)), error, a);
|
||||
|
||||
function catenary_points(l, x, y, steps = 100) = //! Returns a list of 2D points on the curve that goes from the origin to ```(x,y)``` and has length ```l```.
|
||||
let(
|
||||
d = x / 2,
|
||||
a = catenary_find_a(d, sqrt(sqr(l) - sqr(y))), // Find a to get the correct length
|
||||
offset = argsinh(y / catenary_s(d, a)),
|
||||
t0 = sinh(-d / a + offset),
|
||||
t1 = sinh( d / a + offset),
|
||||
h = a * cosh(-d / a + offset) - a,
|
||||
lowest = offset > d / a ? [0, 0] : offset < -d / a ? [x, y] : [d - offset * a, -h],
|
||||
p0 = catenary(t0, a)
|
||||
)
|
||||
steps ? [for(t = [t0 : (t1 - t0) / steps : t1]) catenary(t, a) - p0] : lowest;
|
@@ -18,7 +18,7 @@
|
||||
//
|
||||
|
||||
//
|
||||
// Include this file to use the miniumum library
|
||||
// Include this file to use the minimum library
|
||||
//
|
||||
include <../../global_defs.scad>
|
||||
//
|
||||
|
@@ -31,16 +31,27 @@ function m(x) = x * 1000.0;
|
||||
|
||||
function sqr(x) = x * x; //! Returns the square of ```x```
|
||||
function echoit(x) = echo(x) x; //! Echo expression and return it, useful for debugging
|
||||
function no_point(str) = chr([for(c = str(str)) if(c == ".") ord("p") else ord(c)]);//! Replace decimal point in string with 'p'
|
||||
function in(list, x) = !!len([for(v = list) if(v == x) true]); //! Returns true if ```x``` is an element in the ```list```
|
||||
function Len(x) = is_list(x) ? len(x) : 0; //! Returns the length of a list or 0 if ```x``` is not a list
|
||||
function r2sides(r) = $fn ? $fn : ceil(max(min(360/ $fa, r * 2 * PI / $fs), 5)); //! Replicates the OpenSCAD logic to calculate the number of sides from the radius
|
||||
function r2sides4n(r) = floor((r2sides(r) + 3) / 4) * 4; //! Round up the number of sides to a multiple of 4 to ensure points land on all axes
|
||||
function limit(x, min, max) = max(min(x, max), min); //! Force x in range min <= x <= max
|
||||
|
||||
module translate_z(z) translate([0, 0, z]) children(); //! Shortcut for Z only translations
|
||||
module vflip() rotate([180, 0, 0]) children(); //! Invert children by doing a 180° flip around the X axis
|
||||
module hflip() rotate([0, 180, 0]) children(); //! Invert children by doing a 180° flip around the Y axis
|
||||
module vflip(flip=true) rotate([flip ? 180 : 0, 0, 0]) children(); //! Invert children by doing a 180° flip around the X axis
|
||||
module hflip(flip=true) rotate([0, flip ? 180: 0, 0]) children(); //! Invert children by doing a 180° flip around the Y axis
|
||||
module ellipse(xr, yr) scale([1, yr / xr]) circle4n(xr); //! Draw an ellipse
|
||||
|
||||
function slice_str(str, start, end, s ="") = start >= end ? s : slice_str(str, start + 1, end, str(s, str[start])); // Helper for slice()
|
||||
|
||||
function slice(list, start = 0, end = undef) = let( //! Slice a list or string with Python type semantics
|
||||
len = len(list),
|
||||
start = limit(start < 0 ? len + start : start, 0, len),
|
||||
end = is_undef(end) ? len : limit(end < 0 ? len + end : end, 0, len)
|
||||
) is_string(list) ? slice_str(list, start, end) : [for(i = [start : 1 : end - 1]) list[i]];
|
||||
|
||||
|
||||
module extrude_if(h, center = true) //! Extrudes 2D object to 3D when ```h``` is nonzero, otherwise leaves it 2D
|
||||
if(h)
|
||||
linear_extrude(h, center = center, convexity = 2) // 3D
|
||||
|
@@ -32,10 +32,14 @@ module poly_circle(r, sides = 0) { //! Make a circle adjusted to print the corre
|
||||
circle(r = corrected_radius(r,n), $fn = n);
|
||||
}
|
||||
|
||||
module poly_cylinder(r, h, center = false, sides = 0) //! Make a cylinder adjusted to print the correct size
|
||||
module poly_cylinder(r, h, center = false, sides = 0, chamfer = false) {//! Make a cylinder adjusted to print the correct size
|
||||
extrude_if(h, center)
|
||||
poly_circle(r, sides);
|
||||
|
||||
if(h && chamfer)
|
||||
poly_cylinder(r + layer_height, center ? layer_height * 2 : layer_height, center, sides = sides ? sides : sides(r));
|
||||
}
|
||||
|
||||
module poly_ring(or, ir, sides = 0) { //! Make a 2D ring adjusted to have the correct internal radius
|
||||
cir = corrected_radius(ir, sides);
|
||||
filaments = (or - cir) / extrusion_width;
|
||||
|
@@ -20,17 +20,32 @@
|
||||
//
|
||||
//! For making horizontal holes that don't need support material.
|
||||
//! Small holes can get away without it, but they print better with truncated teardrops.
|
||||
//!
|
||||
//! Using teardrop_plus() or setting the plus option on other modules will elongate the teardrop vertically by the layer height, so when sliced the staircase tips
|
||||
//! do not intrude into the circle. See <https://hydraraptor.blogspot.com/2020/07/horiholes-2.html>
|
||||
//
|
||||
module teardrop(h, r, center = true, truncate = true, chamfer = 0) { //! For making horizontal holes that don't need support material, set ```truncate = false``` to make traditional RepRap teardrops that don't even need bridging
|
||||
module teardrop(h, r, center = true, truncate = true, chamfer = 0, plus = false) { //! For making horizontal holes that don't need support material, set ```truncate = false``` to make traditional RepRap teardrops that don't even need bridging
|
||||
module teardrop_2d(r, truncate) {
|
||||
hull() {
|
||||
circle4n(r);
|
||||
if(truncate)
|
||||
translate([0, r / 2])
|
||||
square([2 * r * (sqrt(2) - 1), r], center = true);
|
||||
else
|
||||
polygon([[0, 0], [eps, 0], [0, r * sqrt(2)]]);
|
||||
}
|
||||
er = layer_height / 2 - eps; // Extrustion edge radius
|
||||
R = plus ? r + er : r; // Corrected radius
|
||||
offset = plus ? -er : 0; // Offset inwards
|
||||
hull()
|
||||
for(side = [0 : 1])
|
||||
mirror([side, 0, 0])
|
||||
intersection() {
|
||||
hull()
|
||||
translate([offset, 0]) {
|
||||
circle4n(R);
|
||||
|
||||
if(truncate)
|
||||
translate([0, R / 2])
|
||||
square([2 * R * (sqrt(2) - 1), R], center = true);
|
||||
else
|
||||
polygon([[0, 0], [eps, 0], [0, R * sqrt(2)]]);
|
||||
}
|
||||
translate([0, -2 * R])
|
||||
square([R, 4 * R]);
|
||||
}
|
||||
}
|
||||
|
||||
render(convexity = 5)
|
||||
@@ -40,23 +55,23 @@ module teardrop(h, r, center = true, truncate = true, chamfer = 0) { //! For mak
|
||||
teardrop_chamfer(h, center, chamfer) {
|
||||
linear_extrude(eps, center = true)
|
||||
teardrop_2d(r + chamfer / 2, truncate);
|
||||
|
||||
translate_z(-chamfer / 2)
|
||||
linear_extrude(eps, center = true)
|
||||
teardrop_2d(r, truncate);
|
||||
}
|
||||
}
|
||||
|
||||
module semi_teardrop(h, r, d = undef, center = true, chamfer = 0) { //! A semi teardrop in the positive Y domain
|
||||
module semi_teardrop_2d(r, d) {
|
||||
module semi_teardrop(h, r, d = undef, center = true, chamfer = 0, plus = false) { //! A semi teardrop in the positive Y domain
|
||||
module semi_teardrop_2d(r, d)
|
||||
intersection() {
|
||||
R = is_undef(d) ? r : d / 2;
|
||||
teardrop(r = R, h = 0);
|
||||
teardrop(r = R, h = 0, plus = plus);
|
||||
|
||||
sq = R + 1;
|
||||
translate([-sq, 0])
|
||||
square([2 * sq, sq]);
|
||||
}
|
||||
}
|
||||
|
||||
render(convexity = 5)
|
||||
extrude_if(h, center)
|
||||
@@ -65,22 +80,21 @@ module semi_teardrop(h, r, d = undef, center = true, chamfer = 0) { //! A semi t
|
||||
teardrop_chamfer(h, center, chamfer) {
|
||||
linear_extrude(eps, center = true)
|
||||
semi_teardrop_2d(r + chamfer / 2, d);
|
||||
|
||||
translate_z(-chamfer / 2)
|
||||
linear_extrude(eps, center = true)
|
||||
semi_teardrop_2d(r, d);
|
||||
}
|
||||
}
|
||||
|
||||
module teardrop_plus(h, r, center = true, truncate = true, chamfer = 0) //! Slightly bigger teardrop to allow for the 3D printing staircase effect
|
||||
teardrop(h, r + layer_height / 4, center, truncate, chamfer);
|
||||
module teardrop_plus(h, r, center = true, truncate = true, chamfer = 0) //! Slightly elongated teardrop to allow for the 3D printing staircase effect
|
||||
teardrop(h, r, center, truncate, chamfer, plus = true);
|
||||
|
||||
module tearslot(h, r, w, center = true, chamfer = 0) { //! A horizontal slot that doesn't need support material
|
||||
module tearslot_2d(r, w) {
|
||||
hull() {
|
||||
translate([-w / 2, 0]) teardrop(r = r, h = 0);
|
||||
translate([w / 2, 0]) teardrop(r = r, h = 0);
|
||||
}
|
||||
}
|
||||
module tearslot(h, r, w, center = true, chamfer = 0, plus = false) { //! A horizontal slot that doesn't need support material
|
||||
module tearslot_2d(r, w)
|
||||
hull()
|
||||
for(x = [-1, 1])
|
||||
translate([x * w / 2, 0]) teardrop(r = r, h = 0, plus = plus);
|
||||
|
||||
extrude_if(h, center)
|
||||
tearslot_2d(r, w);
|
||||
@@ -88,19 +102,19 @@ module tearslot(h, r, w, center = true, chamfer = 0) { //! A horizontal slot tha
|
||||
teardrop_chamfer(h, center, chamfer) {
|
||||
linear_extrude(eps, center = true)
|
||||
tearslot_2d(r + chamfer / 2, w);
|
||||
|
||||
translate_z(-chamfer / 2)
|
||||
linear_extrude(eps, center = true)
|
||||
tearslot_2d(r, w);
|
||||
}
|
||||
}
|
||||
|
||||
module vertical_tearslot(h, r, l, center = true, chamfer = 0) { //! A vertical slot that doesn't need support material
|
||||
module vertical_tearslot_2d(r, l) {
|
||||
hull() {
|
||||
translate([0, l / 2]) teardrop(0, r, true);
|
||||
translate([0, -l / 2]) circle4n(r);
|
||||
}
|
||||
}
|
||||
module vertical_tearslot(h, r, l, center = true, chamfer = 0, plus = false) { //! A vertical slot that doesn't need support material
|
||||
module vertical_tearslot_2d(r, l)
|
||||
hull()
|
||||
for(y = [-1, 1])
|
||||
translate([0, y * l / 2])
|
||||
teardrop(0, r, true, plus = plus);
|
||||
|
||||
extrude_if(h, center)
|
||||
vertical_tearslot_2d(r, l);
|
||||
@@ -108,6 +122,7 @@ module vertical_tearslot(h, r, l, center = true, chamfer = 0) { //! A vertical s
|
||||
teardrop_chamfer(h, center, chamfer) {
|
||||
linear_extrude(eps, center = true)
|
||||
vertical_tearslot_2d(r + chamfer / 2, l);
|
||||
|
||||
translate_z(-chamfer / 2)
|
||||
linear_extrude(eps, center = true)
|
||||
vertical_tearslot_2d(r, l);
|
||||
@@ -123,4 +138,3 @@ module teardrop_chamfer(h, center, chamfer) { //! Helper module for adding chamf
|
||||
hull()
|
||||
children();
|
||||
}
|
||||
|
||||
|
@@ -46,6 +46,9 @@ function profile_shift(z, pa) = z ? max(1 - z * sqr(sin(pa)) / 2, 0) : 0; //! Ca
|
||||
function centre_distance(m, z1, z2, pa = 20) = //! Calculate distance between centres taking profile shift into account
|
||||
let(x1 = profile_shift(z1, pa), x2 = profile_shift(z2, pa)) m * (z1/2 + z2/2 + x1 + x2);
|
||||
|
||||
function involute_gear_od(m, z, pa = 20) = //! involute gear outside diameter given modulus, tooth count and pressure angle
|
||||
m * (z + 2 * profile_shift(z, pa) + 2);
|
||||
|
||||
module involute_gear_profile(m, z, pa = 20, clearance = undef, steps = 20) { //! Calculate gear profile given module, number of teeth and pressure angle
|
||||
assert(z >= 7, "Gears must have at least 7 teeth.");
|
||||
d = m * z; // Reference pitch circle diameter
|
||||
|
@@ -39,11 +39,13 @@ module hanging_hole(z, ir, h = 100, h2 = 100) { //! Hole radius ```ir``` hanging
|
||||
infill_angle = z % (2 * layer_height) ? -45 : 45;
|
||||
below = min(z + eps, h2);
|
||||
big = 1000;
|
||||
|
||||
render(convexity = 3) translate_z(z)
|
||||
union() {
|
||||
translate_z(2 * layer_height)
|
||||
polyhole(ir - eps, h - 2 * layer_height);
|
||||
if(sides(ir) > 4)
|
||||
polyhole(ir - eps, h - 2 * layer_height);
|
||||
else
|
||||
poly_cylinder(ir, h - 2 * layer_height);
|
||||
|
||||
difference() {
|
||||
translate_z(-below)
|
||||
|
83
utils/horiholes.scad
Normal file
@@ -0,0 +1,83 @@
|
||||
//
|
||||
// NopSCADlib Copyright Chris Palmer 2020
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// This file is part of NopSCADlib.
|
||||
//
|
||||
// NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
|
||||
// GNU General Public License as published by the Free Software Foundation, either version 3 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// See the GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with NopSCADlib.
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
//
|
||||
//! Utilities for depicting the staircase slicing of horizontal holes made with [`teardrop_plus()`](#teardrops), see <https://hydraraptor.blogspot.com/2020/07/horiholes-2.html>
|
||||
//!
|
||||
//! ```horicylinder()``` makes cylinders that fit inside a round hole. Layers that are less than 2 filaments wide and layers that need more than a 45 degree overhang are omitted.
|
||||
//
|
||||
include <../utils/core/core.scad>
|
||||
|
||||
function teardrop_plus_x(r, y, h) = //! Calculate the ordinate of a compensated teardrop given y and layer height.
|
||||
let(fr = h / 2,
|
||||
hpot = r + fr,
|
||||
x2 = sqr(hpot) - sqr(y),
|
||||
x = x2 > 0 ? sqrt(x2) : 0
|
||||
)
|
||||
max(0,
|
||||
y < hpot / sqrt(2) ? x - fr :
|
||||
y < hpot ? hpot * sqrt(2) - y - fr :
|
||||
0);
|
||||
|
||||
module horihole(r, z, h = 0, center = true) { //! For making horizontal holes that don't need support material and are correct dimensions
|
||||
bot_layer = floor((z - r) / layer_height);
|
||||
top_layer = ceil((z + r) / layer_height);
|
||||
render(convexity = 5)
|
||||
extrude_if(h, center)
|
||||
for(i = [bot_layer : top_layer]) {
|
||||
Z = i * layer_height;
|
||||
y = Z - z + layer_height / 2;
|
||||
x = teardrop_plus_x(r, y, layer_height);
|
||||
if(x > 0)
|
||||
translate([0, y])
|
||||
difference() {
|
||||
square([2 * x + layer_height, layer_height], center = true);
|
||||
|
||||
for(end = [-1, 1])
|
||||
translate([end * (x + layer_height / 2), 0])
|
||||
circle(d = layer_height, $fn = 32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function teardrop_minus_x(r, y, h) = //! Calculate the ordinate of a compensated teardrop given y and layer height.
|
||||
let(fr = h / 2,
|
||||
hpot = r - fr,
|
||||
x2 = sqr(hpot) - sqr(y),
|
||||
x = x2 > 0 ? sqrt(x2) : 0,
|
||||
X = y >= -hpot / sqrt(2) ? x + fr : 0
|
||||
)
|
||||
X >= extrusion_width ? X : 0;
|
||||
|
||||
module horicylinder(r, z, h = 0, center = true) { //! For making horizontal cylinders that don't need support material and are correct dimensions
|
||||
bot_layer = floor((z - r) / layer_height);
|
||||
top_layer = ceil((z + r) / layer_height);
|
||||
render(convexity = 5)
|
||||
extrude_if(h, center)
|
||||
for(i = [bot_layer : top_layer]) {
|
||||
Z = i * layer_height;
|
||||
y = Z - z + layer_height / 2;
|
||||
x = teardrop_minus_x(r, y, layer_height);
|
||||
if(x >= extrusion_width)
|
||||
hull()
|
||||
for(end = [-1, 1])
|
||||
translate([end * (x - layer_height / 2), y])
|
||||
circle(d = layer_height, $fn = 32);
|
||||
}
|
||||
}
|
@@ -24,6 +24,14 @@ function sqr(x) = x * x; //! Square x
|
||||
function radians(degrees) = degrees * PI / 180; //! Convert radians to degrees
|
||||
function degrees(radians) = radians * 180 / PI; //! Convert degrees to radians
|
||||
|
||||
function sinh(x) = (exp(x) - exp(-x)) / 2; //! hyperbolic sine
|
||||
function cosh(x) = (exp(x) + exp(-x)) / 2; //! hyperbolic cosine
|
||||
function tanh(x) = sinh(x) / cosh(x); //! hyperbolic tangent
|
||||
function coth(x) = cosh(x) / sinh(x); //! hyperbolic cotangent
|
||||
function argsinh(x) = ln(x + sqrt(sqr(x) + 1)); //! inverse hyperbolic sine
|
||||
function argcosh(x) = ln(x + sqrt(sqr(x) - 1)); //! inverse hyperbolic cosine
|
||||
function argtanh(x) = ln((1 + x) / (1 - x)) / 2;//! inverse hyperbolic tangent
|
||||
function argcoth(x) = ln((x + 1) / (x - 1)) / 2;//! inverse hyperbolic cotangent
|
||||
|
||||
function translate(v) = let(u = is_list(v) ? len(v) == 2 ? [v.x, v.y, 0] //! Generate a 4x4 translation matrix, ```v``` can be ```[x, y]```, ```[x, y, z]``` or ```z```
|
||||
: v
|
||||
@@ -138,3 +146,10 @@ function invert(m) = let(n =len(m), m = solve(augment(m))) [ //! Invert a matrix
|
||||
each m[i][j]
|
||||
]
|
||||
];
|
||||
|
||||
function circle_intersect(c1, r1, c2, r2) = //! Calculate one point where two circles in the X-Z plane intersect, clockwise around c1
|
||||
let(
|
||||
v = c1 - c2, // Line between centres
|
||||
d = norm(v), // Distance between centres
|
||||
a = atan2(v.z, v.x) - acos((sqr(d) + sqr(r2) - sqr(r1)) / (2 * d * r2)) // Cosine rule to find angle from c2
|
||||
) c2 + r2 * [cos(a), 0, sin(a)]; // Point on second circle
|
||||
|
@@ -23,18 +23,21 @@
|
||||
include <../utils/core/core.scad>
|
||||
|
||||
module quadrant(w, r, center = false) { //! Draw a square with one rounded corner, can be centered on the arc centre, when ```center``` is ```true```.
|
||||
offset = center ? r - w : 0;
|
||||
translate([offset, offset])
|
||||
h = is_list(w) ? w.y : w;
|
||||
w = is_list(w) ? w.x : w;
|
||||
offset_w = center ? r - w : 0;
|
||||
offset_h = center ? r - h : 0;
|
||||
translate([offset_w, offset_h])
|
||||
hull() {
|
||||
intersection() {
|
||||
translate([w - r, w - r])
|
||||
translate([w - r, h - r])
|
||||
circle4n(r);
|
||||
|
||||
square(w);
|
||||
square([w, h]);
|
||||
}
|
||||
|
||||
square([w, eps]);
|
||||
|
||||
square([eps, w]);
|
||||
square([eps, h]);
|
||||
}
|
||||
}
|
||||
|
@@ -34,14 +34,22 @@ function transpose3(m) = [ [m[0].x, m[1].x, m[2].x],
|
||||
[m[0].y, m[1].y, m[2].y],
|
||||
[m[0].z, m[1].z, m[2].z] ];
|
||||
//
|
||||
// Find the first non-colinear point
|
||||
//
|
||||
tiny = 0.00001;
|
||||
function find_curve(tangents, i = 1) =
|
||||
i >= len(tangents) - 1 || norm(cross(tangents[0], tangents[i] - tangents[0])) > tiny ? i
|
||||
: find_curve(tangents, i + 1);
|
||||
//
|
||||
// Frenet-Serret frame
|
||||
//
|
||||
function fs_frame(tangents) =
|
||||
let(tangent = tangents[0],
|
||||
normal = tangents[1] - tangents[0],
|
||||
i = find_curve(tangents),
|
||||
normal = tangents[i] - tangents[0],
|
||||
binormal = cross(tangent, normal),
|
||||
z = unit(tangent),
|
||||
x = assert(norm(binormal) > 0.00001, "first three points are colinear") unit(binormal),
|
||||
x = assert(norm(binormal) > tiny, "all points are colinear") unit(binormal),
|
||||
y = unit(cross(z, x))
|
||||
) [[x.x, y.x, z.x],
|
||||
[x.y, y.y, z.y],
|
||||
@@ -70,7 +78,6 @@ function orientate(p, r) =
|
||||
[x.y, y.y, z.y],
|
||||
[x.z, y.z, z.z],
|
||||
[p.x, p.y, p.z]];
|
||||
|
||||
//
|
||||
// Rotate around z
|
||||
//
|
||||
@@ -145,10 +152,10 @@ function sweep(path, profile, loop = false, twist = 0) = //! Generate the point
|
||||
faces = loop ? skin_faces : concat([cap(facets)], skin_faces, [cap(facets, npoints - 1)])
|
||||
) [points, faces];
|
||||
|
||||
module sweep(path, profile, loop = false, twist = 0) { //! Draw a polyhedron that is the swept volume
|
||||
module sweep(path, profile, loop = false, twist = 0, convexity = 1) { //! Draw a polyhedron that is the swept volume
|
||||
mesh = sweep(path, profile, loop, twist);
|
||||
|
||||
polyhedron(points = mesh[0], faces = mesh[1]);
|
||||
polyhedron(points = mesh[0], faces = mesh[1], convexity = convexity);
|
||||
}
|
||||
|
||||
function path_length(path, i = 0, length = 0) = //! Calculated the length along a path
|
||||
|
@@ -31,3 +31,41 @@ module ring(or, ir) //! Create a ring with specified external and internal radii
|
||||
module tube(or, ir, h, center = true) //! Create a tube with specified external and internal radii and height ```h```
|
||||
linear_extrude(h, center = center, convexity = 5)
|
||||
ring(or, ir);
|
||||
|
||||
module woven_tube(or, ir, h, center= true, colour = grey(30), colour2, warp = 2, weft) {//! Create a woven tube with specified external and internal radii, height ```h```, colours, warp and weft
|
||||
colour2 = colour2 ? colour2 : colour * 0.8;
|
||||
weft = weft ? weft : warp;
|
||||
warp_count = max(floor(PI * or / warp), 0.5);
|
||||
angle = 360 / (2 * warp_count);
|
||||
|
||||
module layer(weft) {
|
||||
points = [[ir, weft / 2], [or, weft / 2], [or, -weft / 2], [ir, -weft / 2]];
|
||||
color(colour)
|
||||
for (i = [0 : warp_count])
|
||||
rotate(2 * i * angle)
|
||||
rotate_extrude(angle = angle)
|
||||
polygon(points);
|
||||
color(colour2)
|
||||
for (i = [0 : warp_count])
|
||||
rotate((2 * i + 1) * angle)
|
||||
rotate_extrude(angle = angle)
|
||||
polygon(points);
|
||||
}
|
||||
|
||||
translate_z(center ? -h / 2 : 0) {
|
||||
weft_count = floor(h / weft);
|
||||
if (weft_count > 0)
|
||||
for (i = [0 : weft_count - 1]) {
|
||||
translate_z(i * weft + weft / 2)
|
||||
rotate(i * angle)
|
||||
layer(weft);
|
||||
}
|
||||
remainder = h - weft * weft_count;
|
||||
if (remainder) {
|
||||
translate_z(weft_count * weft + remainder / 2)
|
||||
rotate(weft_count * angle)
|
||||
layer(remainder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -24,6 +24,7 @@ include <../utils/core/core.scad>
|
||||
include <../utils/round.scad>
|
||||
|
||||
module wire_link(d, l, h = 1, tail = 3) { //! Draw a wire jumper link.
|
||||
vitamin(str("wire_link(", d, ", ", l, arg(h, 1, "h"), arg(tail, 3, "tail"), "): Wire link ", d, "mm x ", l / inch(1), "\""));
|
||||
r = d;
|
||||
$fn = 32;
|
||||
|
||||
@@ -57,13 +58,16 @@ module orientate_axial(length, height, pitch, wire_d) { // Orient horizontal or
|
||||
min_pitch = ceil((length + 1) / inch(0.1)) * inch(0.1);
|
||||
lead_pitch = pitch ? pitch : min_pitch;
|
||||
if(lead_pitch >= min_pitch) {
|
||||
wire_link(wire_d, lead_pitch, height);
|
||||
not_on_bom()
|
||||
wire_link(wire_d, lead_pitch, height);
|
||||
|
||||
translate_z(height)
|
||||
rotate([0, 90, 0])
|
||||
children();
|
||||
}
|
||||
else {
|
||||
wire_link(wire_d, lead_pitch, length + 0.7 + wire_d);
|
||||
not_on_bom()
|
||||
wire_link(wire_d, lead_pitch, length + 0.7 + wire_d);
|
||||
|
||||
translate([-pitch / 2, 0, length / 2 + 0.2])
|
||||
children();
|
||||
|
@@ -52,21 +52,21 @@ module ball_bearing(type) { //! Draw a ball bearing
|
||||
rim_chamfer = rim / 6;
|
||||
rotate_extrude()
|
||||
hull() {
|
||||
translate([or - rim / 2, 0])
|
||||
square([rim, h - 2 * rim_chamfer], center = true);
|
||||
translate([or - rim, -h / 2 + rim_chamfer])
|
||||
square([rim, h - 2 * rim_chamfer]);
|
||||
|
||||
translate([or - rim / 2 - rim_chamfer, 0])
|
||||
square([rim - rim_chamfer, h], center = true);
|
||||
translate([or - rim, -h / 2])
|
||||
square([rim - rim_chamfer, h]);
|
||||
}
|
||||
|
||||
hub_chamfer = hub / 6;
|
||||
rotate_extrude()
|
||||
hull() {
|
||||
translate([ir + hub / 2, 0])
|
||||
square([hub, h - 2 * hub_chamfer], center = true);
|
||||
translate([ir, -h / 2 + hub_chamfer])
|
||||
square([hub, h - 2 * hub_chamfer]);
|
||||
|
||||
translate([ir + hub / 2 + hub_chamfer, 0])
|
||||
square([hub - hub_chamfer, h], center = true);
|
||||
translate([ir + hub_chamfer, -h / 2])
|
||||
square([hub - hub_chamfer, h]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -19,61 +19,67 @@
|
||||
|
||||
//
|
||||
//! Models timing belt running over toothed or smooth pulleys and calculates an accurate length.
|
||||
//! Only models 2D paths, so not core XY!
|
||||
//! Only models 2D paths, so not crossed belt core XY!
|
||||
//!
|
||||
//! To make the back of the belt run against a smooth pulley on the outside of the loop specify a negative pitch radius.
|
||||
//!
|
||||
//! By default the path is a closed loop but a gap length and position can be specified to make open loops.
|
||||
//! To draw the gap its XY position is specified by ```gap_pos```. ```gap_pos.z``` can be used to specify a rotation if the gap is not at the bottom of the loop.
|
||||
//!
|
||||
//! Individual teeth are not drawn, instead they are represented by a lighter colour.
|
||||
//
|
||||
include <../utils/core/core.scad>
|
||||
use <../utils/rounded_polygon.scad>
|
||||
use <../utils/maths.scad>
|
||||
|
||||
function belt_pitch(type) = type[1]; //! Pitch in mm
|
||||
function belt_width(type) = type[2]; //! Width in mm
|
||||
function belt_thickness(type) = type[3]; //! Total thickness including teeth
|
||||
function belt_tooth_height(type) = type[4]; //! Tooth height
|
||||
function belt_pitch_height(type) = belt_tooth_height(type) + type[4]; //! Offset of the pitch radius from the tips of the teeth
|
||||
function belt_pitch_height(type) = type[5] + belt_tooth_height(type); //! Offset of the pitch radius from the tips of the teeth
|
||||
|
||||
function no_point(str) = chr([for(c = str) if(c == ".") ord("p") else ord(c)]);
|
||||
function belt_pitch_to_back(type) = belt_thickness(type) - belt_pitch_height(type); //! Offset of the back from the pitch radius
|
||||
//
|
||||
// We model the belt path at the pitch radius of the pulleys and the pitch line of the belt to get an accurate length.
|
||||
// The belt is then drawn by offseting each side from the pitch line.
|
||||
//
|
||||
module belt(type, points, gap = 0, gap_pt = undef, belt_colour = grey(20), tooth_colour = grey(50)) { //! Draw a belt path given a set of points and pitch radii where the pulleys are. Closed loop unless a gap is specified
|
||||
module belt(type, points, gap = 0, gap_pos = undef, belt_colour = grey(20), tooth_colour = grey(50)) { //! Draw a belt path given a set of points and pitch radii where the pulleys are. Closed loop unless a gap is specified
|
||||
width = belt_width(type);
|
||||
pitch = belt_pitch(type);
|
||||
thickness = belt_thickness(type);
|
||||
part = str(type[0],pitch);
|
||||
vitamin(str("belt(", no_point(part), "x", width, ", ", points, arg(gap, 0), arg(gap_pt, undef), "): Belt ", part," x ", width, "mm x ", length, "mm"));
|
||||
vitamin(str("belt(", no_point(part), "x", width, ", ", points, arg(gap, 0), arg(gap_pos, undef), "): Belt ", part," x ", width, "mm x ", length, "mm"));
|
||||
|
||||
len = len(points);
|
||||
|
||||
tangents = rounded_polygon_tangents(points);
|
||||
|
||||
length = ceil((rounded_polygon_length(points, tangents) - gap) / pitch) * pitch;
|
||||
length = ceil((rounded_polygon_length(points, tangents) - (is_list(gap) ? gap.x + gap.y : gap)) / pitch) * pitch;
|
||||
|
||||
module shape() rounded_polygon(points, tangents);
|
||||
|
||||
ph = belt_pitch_height(type);
|
||||
th = belt_tooth_height(type);
|
||||
module gap()
|
||||
if(gap)
|
||||
translate(gap_pt)
|
||||
square([gap, thickness + eps], center = true);
|
||||
translate([gap_pos.x, gap_pos.y])
|
||||
rotate(is_undef(gap_pos.z) ? 0 : gap_pos.z)
|
||||
translate([0, ph - thickness / 2])
|
||||
square(is_list(gap) ? [gap.x, gap.y + thickness + eps] : [gap, thickness + eps], center = true);
|
||||
|
||||
color(belt_colour)
|
||||
linear_extrude(width, center = true)
|
||||
difference() {
|
||||
offset(thickness - belt_pitch_height(type)) shape();
|
||||
offset(-belt_pitch_height(type) + belt_tooth_height(type)) shape();
|
||||
offset(-ph + thickness ) shape();
|
||||
offset(-ph + th) shape();
|
||||
gap();
|
||||
|
||||
}
|
||||
|
||||
color(tooth_colour)
|
||||
linear_extrude(width, center = true)
|
||||
difference() {
|
||||
offset(-belt_pitch_height(type) + belt_tooth_height(type)) shape();
|
||||
offset(-belt_pitch_height(type)) shape();
|
||||
offset(-ph + th) shape();
|
||||
offset(-ph) shape();
|
||||
gap();
|
||||
}
|
||||
}
|
||||
|
@@ -22,6 +22,8 @@
|
||||
//
|
||||
include <../utils/core/core.scad>
|
||||
use <../utils/rounded_cylinder.scad>
|
||||
use <../utils/quadrant.scad>
|
||||
use <screw.scad>
|
||||
|
||||
function blower_length(type) = type[2]; //! Length of enclosing rectangle
|
||||
function blower_width(type) = type[3]; //! Width of enclosing rectangle
|
||||
@@ -39,8 +41,87 @@ function blower_top(type) = type[14]; //! Thickness of the top
|
||||
function blower_wall(type) = type[15]; //! Side wall thickness
|
||||
function blower_lug(type) = type[16]; //! Height of the lugs
|
||||
|
||||
function blower_casing_is_square(type) = len(blower_screw_holes(type)) > 3; //! True for square radial fans, false for spiral shape radial blowers
|
||||
function blower_exit_offset(type) = blower_casing_is_square(type) ? blower_length(type) / 2 : blower_exit(type) / 2; //! Offset of exit's centre from the edge
|
||||
|
||||
fan_colour = grey(20);
|
||||
|
||||
module blower_fan(type, casing_is_square) {
|
||||
module squarish(s, n) {
|
||||
polygon([
|
||||
for(i = [0 : n]) [i * s.x / n, s.y + (i % 2) * eps],
|
||||
for(i = [0 : n]) [s.x - i * s.x / n, (i % 2) * eps],
|
||||
]);
|
||||
}
|
||||
|
||||
depth = blower_depth(type);
|
||||
blade_ir = blower_hub(type) / 2 + 0.5; // slight gap between main part of blades and hub
|
||||
blade_len = casing_is_square
|
||||
? (blower_bore(type) - 1) / 2 - blade_ir // fan constrained by bore hole
|
||||
: blower_width(type) - blower_axis(type).x- blower_wall(type) - blade_ir; // fan extends to casing
|
||||
blade_thickness = 0.75;
|
||||
blade_count = 25;
|
||||
|
||||
base_offset = 1;
|
||||
translate([blower_axis(type).x, blower_axis(type).y, blower_base(type) + base_offset])
|
||||
linear_extrude(blower_hub_height(type) - 0.5 - blower_base(type) - base_offset, center = false, convexity = 4, twist = -30, slices = round(depth / 2))
|
||||
for(i = [0 : blade_count - 1])
|
||||
rotate((360 * i) / blade_count)
|
||||
translate([blade_ir, -blade_thickness / 2])
|
||||
squarish([blade_len, blade_thickness], round(blade_len / 2));
|
||||
}
|
||||
|
||||
module blower_square(type) { //! Draw a square blower
|
||||
width = blower_width(type);
|
||||
depth = blower_depth(type);
|
||||
wall = blower_wall(type);
|
||||
hole_pitch = (blower_screw_holes(type)[1].x - blower_screw_holes(type)[0].x) / 2;
|
||||
corner_radius = width / 2 - hole_pitch;
|
||||
corner_inset = (width - blower_exit(type)) / 2;
|
||||
|
||||
module square_inset_corners(remove_center = false)
|
||||
difference() {
|
||||
//overall outside
|
||||
square([width, width], center = false);
|
||||
|
||||
if (remove_center) {
|
||||
// cut out the inside, leaving the corners
|
||||
translate([corner_inset + wall, -eps])
|
||||
square([width - 2 * (wall + corner_inset), width - wall + eps], center = false);
|
||||
|
||||
translate([wall, corner_inset + wall])
|
||||
square([width - 2 * wall, width - 2 * (wall + corner_inset)], center = false);
|
||||
} else {
|
||||
// cut out the bore for the fan
|
||||
translate(blower_axis(type))
|
||||
circle(d = blower_bore(type));
|
||||
}
|
||||
// corner inset
|
||||
translate([width / 2, width / 2])
|
||||
for(i = [0 : 3])
|
||||
rotate(i * 90)
|
||||
translate([-width / 2 - eps, -width/ 2 - eps])
|
||||
quadrant(corner_inset, corner_inset - corner_radius);
|
||||
}
|
||||
|
||||
base_height = blower_base(type);
|
||||
linear_extrude(base_height)
|
||||
difference () {
|
||||
rounded_square([width, width], corner_radius, center = false);
|
||||
|
||||
blower_hole_positions(type)
|
||||
circle(d = blower_screw_hole(type));
|
||||
}
|
||||
|
||||
translate_z(base_height)
|
||||
linear_extrude(depth - base_height)
|
||||
square_inset_corners(remove_center = true);
|
||||
|
||||
translate_z(depth - base_height)
|
||||
linear_extrude(blower_top(type))
|
||||
square_inset_corners();
|
||||
}
|
||||
|
||||
module blower(type) { //! Draw specified blower
|
||||
length = blower_length(type);
|
||||
width = blower_width(type);
|
||||
@@ -70,55 +151,63 @@ module blower(type) { //! Draw specified blower
|
||||
|
||||
vitamin(str("blower(", type[0], "): ", type[1]));
|
||||
|
||||
is_square = blower_casing_is_square(type); // Description starts with square!
|
||||
color(fan_colour) {
|
||||
// screw lugs
|
||||
linear_extrude(blower_lug(type), center = false)
|
||||
for(hole = blower_screw_holes(type))
|
||||
difference() {
|
||||
hull() {
|
||||
if (is_square) {
|
||||
blower_square(type);
|
||||
} else {
|
||||
// screw lugs
|
||||
linear_extrude(blower_lug(type), center = false)
|
||||
for(hole = blower_screw_holes(type))
|
||||
difference() {
|
||||
hull() {
|
||||
translate(hole)
|
||||
circle(d = blower_screw_hole(type) + 2 * blower_wall(type));
|
||||
|
||||
translate(blower_axis(type))
|
||||
circle(d = blower_screw_hole(type) + 2 * blower_wall(type) + 7);
|
||||
}
|
||||
translate(hole)
|
||||
circle(d = blower_screw_hole(type) + 2 * blower_wall(type));
|
||||
circle(d = blower_screw_hole(type));
|
||||
|
||||
translate(blower_axis(type))
|
||||
circle(d = blower_screw_hole(type) + 2 * blower_wall(type) + 7);
|
||||
}
|
||||
translate(hole)
|
||||
circle(d = blower_screw_hole(type));
|
||||
shape(true);
|
||||
}
|
||||
|
||||
shape(true);
|
||||
}
|
||||
// rotor
|
||||
translate(concat(blower_axis(type), [blower_base(type) + 1]))
|
||||
rounded_cylinder(r = blower_hub(type) / 2, h = blower_hub_height(type) - blower_base(type) - 1, r2 = 1);
|
||||
*%square([length, width]);
|
||||
|
||||
*%square([length, width]);
|
||||
|
||||
// base
|
||||
linear_extrude(blower_base(type))
|
||||
difference() {
|
||||
shape();
|
||||
|
||||
translate(concat(blower_axis(type), [blower_base(type)]))
|
||||
circle(d = 2);
|
||||
}
|
||||
// sides
|
||||
linear_extrude(depth)
|
||||
difference() {
|
||||
shape();
|
||||
|
||||
offset(-blower_wall(type))
|
||||
shape(true);
|
||||
}
|
||||
|
||||
// top
|
||||
translate_z(depth -blower_top(type))
|
||||
linear_extrude(blower_top(type))
|
||||
// base
|
||||
linear_extrude(blower_base(type))
|
||||
difference() {
|
||||
shape();
|
||||
|
||||
translate(concat(blower_axis(type), [blower_base(type)]))
|
||||
circle(d = blower_bore(type));
|
||||
}
|
||||
circle(d = 2);
|
||||
}
|
||||
|
||||
// sides
|
||||
linear_extrude(depth)
|
||||
difference() {
|
||||
shape();
|
||||
|
||||
offset(-blower_wall(type))
|
||||
shape(true);
|
||||
}
|
||||
|
||||
// top
|
||||
translate_z(depth -blower_top(type))
|
||||
linear_extrude(blower_top(type))
|
||||
difference() {
|
||||
shape();
|
||||
|
||||
translate(concat(blower_axis(type), [blower_base(type)]))
|
||||
circle(d = blower_bore(type));
|
||||
}
|
||||
}
|
||||
// rotor
|
||||
translate(concat(blower_axis(type), [blower_base(type) + 1]))
|
||||
rounded_cylinder(r = blower_hub(type) / 2, h = blower_hub_height(type) - blower_base(type) - 1, r2 = 1);
|
||||
|
||||
blower_fan(type, is_square);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -16,10 +16,16 @@
|
||||
// You should have received a copy of the GNU General Public License along with NopSCADlib.
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
// l w d b s h a s s e h b t w l
|
||||
// e i e o c u x c c x u a o a u
|
||||
// n d p r r b i r r i b s p l g
|
||||
// g t t e e s e e t e l
|
||||
// t h h w d w w t
|
||||
// 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];
|
||||
|
||||
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];
|
||||
|
||||
blowers = [PE4020, RB5015];
|
||||
blowers = [BL40x10, PE4020, RB5015];
|
||||
|
||||
use <blower.scad>
|
||||
|
@@ -20,7 +20,7 @@
|
||||
//
|
||||
//! A strip of polypropylene used with ribbon cable to make a cable flexible in one direction only.
|
||||
//!
|
||||
//! Modelled with a Bezier spline, which is not quite the same as a miniumum energy curve but very close, epecially
|
||||
//! Modelled with a Bezier spline, which is not quite the same as a minimum energy curve but very close, epecially
|
||||
//! near the extreme positions, where the model needs to be accurate.
|
||||
//!
|
||||
//! When the sides are constrained then a circular model is more accurate.
|
||||
|
@@ -29,7 +29,7 @@ function camera_lens(type) = type[4]; //! Stack of lens parts, can be r
|
||||
function camera_connector_pos(type) = type[5]; //! The flex connector block for the camera itself's position
|
||||
function camera_connector_size(type)= type[6]; //! The flex connector block for the camera itself's size
|
||||
|
||||
module camera_lens(type, offset = 0) //! Draw the lens stack, with optional offset for making a clearance hole
|
||||
module camera_lens(type, offset = 0, show_lens = true) //! Draw the lens stack, with optional offset for making a clearance hole
|
||||
color(grey(20))
|
||||
translate(camera_lens_offset(type))
|
||||
for(p = camera_lens(type)) {
|
||||
@@ -39,24 +39,25 @@ module camera_lens(type, offset = 0) //! Draw the lens stack, with optional offs
|
||||
if(size.x)
|
||||
rounded_rectangle(size + [2 * offset, 2 * offset, round_to_layer(offset)], r, center = false);
|
||||
else
|
||||
translate_z(size.y)
|
||||
rotate_extrude()
|
||||
difference() {
|
||||
square([r, size.z + round_to_layer(offset)]);
|
||||
if (show_lens)
|
||||
translate_z(size.y)
|
||||
rotate_extrude()
|
||||
difference() {
|
||||
square([r, size.z + round_to_layer(offset)]);
|
||||
|
||||
if(app)
|
||||
translate([0, size.z])
|
||||
hull() {
|
||||
translate([0, -eps])
|
||||
square([app.y, eps * 2]);
|
||||
if(app)
|
||||
translate([0, size.z])
|
||||
hull() {
|
||||
translate([0, -eps])
|
||||
square([app.y, eps * 2]);
|
||||
|
||||
translate([0, -app.z])
|
||||
square([app.x, app.z]);
|
||||
}
|
||||
}
|
||||
translate([0, -app.z])
|
||||
square([app.x, app.z]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module camera(type) { //! Draw specified PCB camera
|
||||
module camera(type, show_lens = true) { //! Draw specified PCB camera
|
||||
vitamin(str("camera(", type[0], "): ", type[1]));
|
||||
pcb = camera_pcb(type);
|
||||
|
||||
@@ -64,7 +65,7 @@ module camera(type) { //! Draw specified PCB camera
|
||||
pcb(pcb);
|
||||
|
||||
translate_z(pcb_thickness(pcb)) {
|
||||
camera_lens(type);
|
||||
camera_lens(type, show_lens = show_lens);
|
||||
|
||||
conn = camera_connector_size(type);
|
||||
if(conn) {
|
||||
|
@@ -68,6 +68,6 @@ rpi_camera = ["rpi_camera", "Raspberry Pi focusable camera", rpi_camera_pcb, [0,
|
||||
[0, 18 - 1.5 - 2.5], [8, 5, 1.6]
|
||||
];
|
||||
|
||||
cameras = [rpi_camera_v1, rpi_camera, rpi_camera_v2];
|
||||
cameras = [rpi_camera_v1, rpi_camera_v2, rpi_camera];
|
||||
|
||||
use <camera.scad>
|
||||
|
@@ -161,13 +161,13 @@ module al_clad_resistor(type, value, leads = true) { //! Draw an aluminium clad
|
||||
}
|
||||
linear_extrude(thickness)
|
||||
difference() {
|
||||
for(end = [-1, 1])
|
||||
translate([end * (length - tab) / 2, end * (width - width / 2) / 2])
|
||||
square([tab, width / 2], center = true);
|
||||
union()
|
||||
for(end = [-1, 1])
|
||||
translate([end * (length - tab) / 2, end * (width - width / 2) / 2])
|
||||
square([tab, width / 2], center = true);
|
||||
|
||||
al_clad_resistor_hole_positions(type)
|
||||
circle(d = al_clad_hole(type));
|
||||
|
||||
}
|
||||
if(leads) {
|
||||
translate_z(height / 2)
|
||||
|
@@ -73,6 +73,42 @@ SSD1963_4p3 = ["SSD1963_4p3", "LCD display SSD1963 4.3\"", 105.5, 67.2, 3.4, SSD
|
||||
[[0, -34.5], [12, -31.5]],
|
||||
];
|
||||
|
||||
displays = [HDMI5, SSD1963_4p3, LCD1602A, LCDS7282B];
|
||||
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 ],
|
||||
],
|
||||
[]
|
||||
];
|
||||
|
||||
BigTreeTech_TFT35v3_0 = ["BigTreeTech_TFT35v3_0", "BigTreeTech TFT35 v3.0",
|
||||
84.5, 54.5, 4, BigTreeTech_TFT35v3_0_PCB,
|
||||
[-6, 0, 0], // pcb offset
|
||||
[[-40, -26.5], [41.5, 26.5, 0.5]], // aperture
|
||||
[], // touch screen
|
||||
0, // thread length
|
||||
[], // clearance need for the ts ribbon
|
||||
];
|
||||
|
||||
|
||||
displays = [HDMI5, SSD1963_4p3, BigTreeTech_TFT35v3_0, LCD1602A, LCDS7282B];
|
||||
|
||||
use <display.scad>
|
||||
|
@@ -26,6 +26,8 @@ include <tubings.scad>
|
||||
include <zipties.scad>
|
||||
include <fans.scad>
|
||||
|
||||
use <../utils/rounded_cylinder.scad>
|
||||
use <../utils/thread.scad>
|
||||
use <../utils/tube.scad>
|
||||
|
||||
rad_dia = 22; // Diam of the part with ailettes
|
||||
@@ -94,7 +96,34 @@ module heater_block(type, naked = false, resistor_wire_rotate = [0,0,0]) {
|
||||
}
|
||||
}
|
||||
|
||||
module bowden_connector(cap_colour = grey(20)) {
|
||||
ir = 4.25 / 2;
|
||||
body_colour = silver;
|
||||
|
||||
color(body_colour) {
|
||||
translate_z(-4.5) {
|
||||
tube(or = 2.5, ir = ir, h = 4.5, center = false);
|
||||
male_metric_thread(6, metric_coarse_pitch(5), length = 4.5, center = false, solid = false, colour = body_colour);
|
||||
}
|
||||
tube(or = 7.7 / 2, ir = ir, h = 2, center = false);
|
||||
translate_z(2)
|
||||
linear_extrude(6.5)
|
||||
difference() {
|
||||
circle(d = 11.55, $fn = 6);
|
||||
circle(r = ir);
|
||||
}
|
||||
translate_z(8.5)
|
||||
rounded_cylinder(r = 9.8 / 2, h = 2, r2 = 1.5, ir = ir);
|
||||
translate_z(10.5)
|
||||
tube(or = 3.5, ir = ir, h = 0.5, center = false);
|
||||
}
|
||||
color(cap_colour) {
|
||||
translate_z(11)
|
||||
tube(or = 3, ir = ir, h = 1, center = false);
|
||||
translate_z(12)
|
||||
tube(or = 5.5, ir = ir, h = 1.75, center = false);
|
||||
}
|
||||
}
|
||||
|
||||
module e3d_fan_duct(type) {
|
||||
color("DeepSkyBlue")
|
||||
@@ -123,7 +152,7 @@ module e3d_fan(type) {
|
||||
fan(fan30x10);
|
||||
}
|
||||
|
||||
module e3d_hot_end(type, filament, naked = false, resistor_wire_rotate = [0,0,0]) {
|
||||
module e3d_hot_end(type, filament, naked = false, resistor_wire_rotate = [0,0,0], bowden = false) {
|
||||
insulator_length = hot_end_insulator_length(type);
|
||||
inset = hot_end_inset(type);
|
||||
h_ailettes = rad_len / (2 * rad_nb_ailettes - 1);
|
||||
@@ -150,6 +179,10 @@ module e3d_hot_end(type, filament, naked = false, resistor_wire_rotate = [0,0,0]
|
||||
square([100, hot_end_groove(type)]);
|
||||
}
|
||||
|
||||
if(bowden)
|
||||
translate_z(inset)
|
||||
bowden_connector();
|
||||
|
||||
rotate(90)
|
||||
heater_block(type, naked, resistor_wire_rotate);
|
||||
|
||||
@@ -158,10 +191,10 @@ module e3d_hot_end(type, filament, naked = false, resistor_wire_rotate = [0,0,0]
|
||||
e3d_fan();
|
||||
}
|
||||
|
||||
module e3d_hot_end_assembly(type, filament, naked = false, resistor_wire_rotate = [0,0,0]) {
|
||||
module e3d_hot_end_assembly(type, filament, naked = false, resistor_wire_rotate = [0,0,0], bowden = false) {
|
||||
bundle = 3.2;
|
||||
|
||||
e3d_hot_end(type, filament, naked, resistor_wire_rotate);
|
||||
e3d_hot_end(type, filament, naked, resistor_wire_rotate, bowden);
|
||||
|
||||
// Wire and ziptie
|
||||
if(!naked)
|
||||
|
@@ -17,28 +17,28 @@
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
// w d b h s h t o b b a
|
||||
// i e o o c u h u l o p
|
||||
// d p r l r b i t a s p
|
||||
// t t e e e c e d s e
|
||||
// h h w d k r e r
|
||||
// p i n s d t
|
||||
// i a e d u
|
||||
// t s i r
|
||||
// c s a e
|
||||
// h
|
||||
// w d b h s h t o b b a
|
||||
// i e o o c u h u l o p
|
||||
// d p r l r b i t a s p
|
||||
// t t e e e c e d s e
|
||||
// h h w d k r e r
|
||||
// p i n s d t
|
||||
// i a e d u
|
||||
// t s i r
|
||||
// c s a e
|
||||
// h
|
||||
//
|
||||
fan120x25= [120,25, 116,52.5, M4_dome_screw, 41, 4, 140, 9, 0, 137];
|
||||
fan80x38 = [80, 38, 75, 35.75, M4_dome_screw, 40, 4.3, 84, 7, 0, 85];
|
||||
fan80x25 = [80, 25, 75, 35.75, M4_dome_screw, 40, 4.3, 84, 7, 0, 85];
|
||||
fan70x15 = [70, 15, 66, 30.75, M4_dome_screw, 29, 3.8, 70 ,7, 0, undef];
|
||||
fan60x25 = [60, 25, 57, 25, M4_dome_screw, 31.5, 3.6, 64, 7, 0, 63];
|
||||
fan60x15 = [60, 15, 57, 25, M4_dome_screw, 29, 2.4, 60, 7, 7.7, 63];
|
||||
fan50x15 = [50, 15, 48, 20, M4_dome_screw, 25, 12.5,100,7, 0, undef];
|
||||
fan40x11 = [40, 11, 37, 16, M3_dome_screw, 25, 7.5,100, 9, 0, undef];
|
||||
fan30x10 = [30, 10, 27, 12, M3_dome_screw, 17, 10, 100, 5, 0, undef];
|
||||
fan25x10 = [25, 10, 24, 10, M2p5_pan_screw, 16, 10, 100, 5, 0, undef];
|
||||
fan17x8 = [17, 8, 16, 6.75, M2_cap_screw, 12.6, 8, 100, 7, 0, undef];
|
||||
fan120x25= [120, 25, 116,52.5, M4_dome_screw, 41, 4, 140, 9, 0, 137];
|
||||
fan80x38 = [80, 38, 75, 35.75, M4_dome_screw, 40, 4.3, 84, 7, 0, 85];
|
||||
fan80x25 = [80, 25, 75, 35.75, M4_dome_screw, 40, 4.3, 84, 7, 0, 85];
|
||||
fan70x15 = [70, 15, 66, 30.75, M4_dome_screw, 29, 3.8, 70 ,7, 0, undef];
|
||||
fan60x25 = [60, 25, 57, 25, M4_dome_screw, 31.5, 3.6, 64, 7, 0, 63];
|
||||
fan60x15 = [60, 15, 57, 25, M4_dome_screw, 29, 2.4, 60, 7, 7.7, 63];
|
||||
fan50x15 = [50, 15, 48, 20, M4_dome_screw, 25, 12.5,100, 7, 0, undef];
|
||||
fan40x11 = [40, 11, 37, 16, M3_dome_screw, 25, 7.5,100, 9, 0, undef];
|
||||
fan30x10 = [30, 10, 27, 12, M3_dome_screw, 17, 10, 100, 5, 0, undef];
|
||||
fan25x10 = [25.4,10, 24, 10, M2p5_pan_screw, 16, 10, 100, 5, 0, undef];
|
||||
fan17x8 = [17, 8, 16, 6.75, M2_cap_screw, 12.6, 8, 100, 7, 0, undef];
|
||||
|
||||
fans = [fan17x8, fan25x10, fan30x10, fan40x11, fan50x15, fan60x15, fan60x25, fan70x15, fan80x25, fan80x38, fan120x25];
|
||||
|
||||
|