mirror of
https://github.com/nophead/NopSCADlib.git
synced 2025-09-09 14:40:44 +02:00
Moved printed parts to their own directory.
This commit is contained in:
471
printed/box.scad
Normal file
471
printed/box.scad
Normal file
@@ -0,0 +1,471 @@
|
||||
//
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
//
|
||||
//! A box made from routed or laser cut sheet sheets and printed profiles and bezels. It can be arbitrarily large
|
||||
//! compared to the 3D printed parts because they can be cut into interlocking sections and solvent welded
|
||||
//! together. The box panels can be customised to have holes and parts mounted on them by overriding the
|
||||
//! definitions of `box_base()`, `box_front()`, etc.
|
||||
//!
|
||||
//! `box.scad` should be ```use```d and `box_assembly.scad` ```include```d.
|
||||
//!
|
||||
//! A box is defined with a list that specifies the inside dimensions, top, bottom and side sheet materials, the
|
||||
//! screw type and printed part wall thickness. This diagram shows how the various dimensions are labelled:
|
||||
//! 
|
||||
//!
|
||||
//! Normally the side sheets are the same type but they can be overridden individually as long as the substitute has the same thickness.
|
||||
//
|
||||
include <../core.scad>
|
||||
use <../vitamins/sheet.scad>
|
||||
use <../vitamins/screw.scad>
|
||||
use <../vitamins/washer.scad>
|
||||
|
||||
include <../vitamins/inserts.scad>
|
||||
use <../utils/quadrant.scad>
|
||||
|
||||
bezel_clearance = 0.2;
|
||||
sheet_end_clearance = 1;
|
||||
sheet_slot_clearance = 0.2;
|
||||
|
||||
function box_screw(type) = type[0]; //! Screw type to be used at the corners
|
||||
function box_wall(type) = type[1]; //! Wall thickness of 3D parts
|
||||
function box_sheets(type) = type[2]; //! Sheet type used for the sides
|
||||
function box_top_sheet(type) = type[3]; //! Sheet type for the top
|
||||
function box_base_sheet(type)= type[4]; //! Sheet type for the bottom
|
||||
function box_feet(type) = type[5]; //! True to enable feet on the bottom bezel
|
||||
function box_width(type) = type[6]; //! Internal width
|
||||
function box_depth(type) = type[7]; //! Internal depth
|
||||
function box_height(type) = type[8]; //! Internal height
|
||||
|
||||
function box_bezel_clearance(type) = bezel_clearance;
|
||||
|
||||
function box_corner_gap(type) = 3; //! Gap between box_sheets at the corners to connect inside and outside profiles
|
||||
function box_profile_overlap(type) = 3 + sheet_end_clearance / 2;
|
||||
|
||||
function box_washer(type) = screw_washer(box_screw(type));
|
||||
function box_insert(type) = screw_insert(box_screw(type));
|
||||
|
||||
function box_hole_inset(type) = washer_radius(box_washer(type)) + 1;
|
||||
function box_insert_r(type) = insert_hole_radius(box_insert(type));
|
||||
function box_insert_l(type) = insert_length(box_insert(type));
|
||||
function box_boss_r(type) = ceil(corrected_radius(box_insert_r(type)) + box_wall(type));
|
||||
|
||||
function box_sheet_slot(type) = sheet_thickness(box_sheets(type)) + sheet_slot_clearance; // add some clearance
|
||||
function box_corner_overlap(type) = box_wall(type);
|
||||
|
||||
function box_corner_rad(type) = box_sheet_slot(type) - sheet_slot_clearance / 2 + box_corner_gap(type) + box_corner_overlap(type);
|
||||
function box_sheet_r(type) = box_corner_rad(type) - box_sheet_slot(type) - box_corner_overlap(type);
|
||||
|
||||
function box_screw_length(type, top) = screw_longer_than(2 * washer_thickness(box_washer(type))
|
||||
+ sheet_thickness(top ? box_top_sheet(type) : box_base_sheet(type))
|
||||
+ box_corner_gap(type) + box_profile_overlap(type) + box_insert_l(type) - 1);
|
||||
|
||||
function box_wall_clearance(type) = box_sheet_slot(type) / 2 - sheet_thickness(box_sheets(type)) / 2;
|
||||
function box_margin(type) = box_profile_overlap(type) + box_corner_gap(type); //! How much the bezel intrudes on the specified height
|
||||
function box_intrusion(type) = box_hole_inset(type) + box_boss_r(type); //! Corner profile intrusion
|
||||
function sheet_reduction(type) = 2 * box_corner_gap(type) + sheet_end_clearance;
|
||||
function box_outset(type) = box_sheet_slot(type) + box_wall(type) - sheet_slot_clearance / 2; //! How much the bezel expands the specified internal size
|
||||
function box_inset(type) = box_wall(type) + sheet_slot_clearance / 2; //! How much the bezel intrudes on the specified width and length, away from the corners
|
||||
function box_bezel_height(type, bottom) = //! Bezel height for top or bottom
|
||||
let(t1 = sheet_thickness(box_base_sheet(type)), t2 = sheet_thickness(box_top_sheet(type)))
|
||||
box_corner_rad(type) + box_profile_overlap(type) + (bottom ? max(t1, t2) : t2) - sheet_thickness(box_sheets(type));
|
||||
|
||||
grill_hole = 5;
|
||||
grill_gap = 1.9;
|
||||
module grill(width, height, r = 1000, poly = false, h = 0) { //! A staggered array of 5mm holes to make grills in sheets. Can be constrained to be circular. Set ```poly``` ```true``` for printing, ```false``` for milling.
|
||||
nx = floor(width / (grill_hole + grill_gap));
|
||||
xpitch = width / nx;
|
||||
ny = floor(height / ((grill_hole + grill_gap) * cos(30)));
|
||||
ypitch = height / ny;
|
||||
|
||||
extrude_if(h)
|
||||
for(y = [0 : ny - 1], x = [0 : nx - 1 - (y % 2)]) {
|
||||
x = -width / 2 + (x + 0.5 + (y % 2) / 2) * xpitch;
|
||||
y = -height / 2 + (y + 0.5) * ypitch;
|
||||
if(sqrt(sqr(x) + sqr(y)) + grill_hole / 2 <= r)
|
||||
translate([x, y])
|
||||
if(poly)
|
||||
poly_circle(r = grill_hole / 2);
|
||||
else
|
||||
circle(d = grill_hole);
|
||||
}
|
||||
}
|
||||
|
||||
module box_corner_profile_2D(type) { //! The 2D shape of the corner profile.
|
||||
t = box_sheet_slot(type);
|
||||
difference() {
|
||||
union() {
|
||||
quadrant(box_hole_inset(type) + box_boss_r(type), box_boss_r(type)); // inside corner
|
||||
|
||||
translate([box_corner_gap(type) + box_profile_overlap(type), box_corner_gap(type) + box_profile_overlap(type)])
|
||||
rotate(180)
|
||||
quadrant(box_profile_overlap(type) + box_corner_rad(type), box_corner_rad(type)); // outside corner
|
||||
}
|
||||
translate([box_corner_gap(type), -t + sheet_slot_clearance / 2])
|
||||
square([100, t]);
|
||||
|
||||
translate([-t + sheet_slot_clearance / 2, box_corner_gap(type)])
|
||||
square([t, 100]);
|
||||
}
|
||||
}
|
||||
|
||||
module box_corner_profile(type) { //! Generates the corner profile STL for 3D printing.
|
||||
stl("box_corner_profile");
|
||||
|
||||
length = box_height(type) - 2 * box_margin(type);
|
||||
difference() {
|
||||
linear_extrude(height = length, center = true, convexity = 5)
|
||||
box_corner_profile_2D(type);
|
||||
|
||||
for(z = [-1, 1])
|
||||
translate([box_hole_inset(type), box_hole_inset(type), z * length / 2])
|
||||
insert_hole(box_insert(type), 5);
|
||||
}
|
||||
}
|
||||
|
||||
module box_corner_profile_section(type, section, sections) { //! Generates interlocking sections of the corner profile to allow it to be taller than the printer
|
||||
overlap = 4;
|
||||
length = box_height(type) - 2 * box_margin(type);
|
||||
section_length = round_to_layer((length - overlap) / sections);
|
||||
last_section = section >= sections - 1;
|
||||
h = last_section ? length - (sections - 1) * section_length : section_length;
|
||||
overlap_wall = 2;
|
||||
|
||||
difference() {
|
||||
union() {
|
||||
linear_extrude(height = h, convexity = 5)
|
||||
box_corner_profile_2D(type);
|
||||
|
||||
if(!last_section) // male end always at the top
|
||||
translate_z(section_length - 1)
|
||||
for(i = [0 : 1], offset = i * layer_height)
|
||||
linear_extrude(height = overlap + 1 - offset)
|
||||
offset(1 + offset - layer_height)
|
||||
offset(-overlap_wall - 1)
|
||||
box_corner_profile_2D(type);
|
||||
}
|
||||
if(section > 0)
|
||||
translate_z(last_section ? h : 0) { // female at bottom unless last section
|
||||
linear_extrude(height = 2 * (overlap + layer_height), center = true, convexity = 5)
|
||||
offset(-overlap_wall)
|
||||
box_corner_profile_2D(type);
|
||||
|
||||
linear_extrude(height = 2 * layer_height, center = true, convexity = 5)
|
||||
offset(-overlap_wall + layer_height)
|
||||
box_corner_profile_2D(type);
|
||||
}
|
||||
if(!section || last_section) // insert holes always at the bottom
|
||||
translate([box_hole_inset(type), box_hole_inset(type)])
|
||||
insert_hole(box_insert(type), 5);
|
||||
}
|
||||
}
|
||||
|
||||
module box_corner_quadrants(type, width, depth)
|
||||
for(corner = [0:3]) {
|
||||
x = [-1,1,1,-1][corner];
|
||||
y = [-1,-1,1,1][corner];
|
||||
|
||||
translate([x * width / 2, y * depth / 2, 0])
|
||||
rotate(corner * 90)
|
||||
quadrant(box_intrusion(type), box_boss_r(type));
|
||||
}
|
||||
|
||||
module box_bezel(type, bottom) { //! Generates top and bottom bezel STLs
|
||||
stl(bottom ? "bottom_bezel" : "top_bezel");
|
||||
feet = bottom && box_feet(type);
|
||||
t = box_sheet_slot(type);
|
||||
outset = box_outset(type);
|
||||
inner_r = box_sheet_r(type);
|
||||
foot_height = box_corner_gap(type) + sheet_thickness(box_base_sheet(type)) + washer_thickness(box_washer(type)) + screw_head_height(box_screw(type)) + box_profile_overlap(type) + 2;
|
||||
foot_length = box_corner_rad(type) * 2;
|
||||
height = box_bezel_height(type, bottom);
|
||||
foot_extension = foot_height - height;
|
||||
|
||||
difference() {
|
||||
translate_z(-box_profile_overlap(type)) difference() {
|
||||
rounded_rectangle([box_width(type) + 2 * outset, box_depth(type) + 2 * outset, feet ? foot_height : height], box_corner_rad(type), false);
|
||||
//
|
||||
// Remove edges between the feet
|
||||
//
|
||||
if(feet)
|
||||
hull() {
|
||||
translate_z(height + 0.5)
|
||||
cube([box_width(type) - 2 * foot_length, box_depth(type) + 2 * outset + 1, 1], center = true);
|
||||
|
||||
translate_z(foot_height + 1)
|
||||
cube([box_width(type) - 2 * (foot_length - foot_extension), box_depth(type) + 2 * outset + 1, 1], center = true);
|
||||
}
|
||||
if(feet)
|
||||
hull() {
|
||||
translate_z(height + 0.5)
|
||||
cube([box_width(type) + 2 * outset + 1, box_depth(type) - 2 * foot_length, 1], center = true);
|
||||
|
||||
translate_z(foot_height + 1)
|
||||
cube([box_width(type) + 2 * outset + 1, box_depth(type) - 2 * (foot_length - foot_extension), 1], center = true);
|
||||
}
|
||||
}
|
||||
//
|
||||
// slots for side panels
|
||||
//
|
||||
translate_z(-box_profile_overlap(type))
|
||||
linear_extrude(height = 2 * box_profile_overlap(type), center = true)
|
||||
for(i = [-1, 1]) {
|
||||
translate([i * (box_width(type) / 2 + t / 2 - sheet_slot_clearance / 2), 0])
|
||||
square([t, box_depth(type) - 2 * box_corner_gap(type)], center = true);
|
||||
|
||||
translate([0, i * (box_depth(type) / 2 + t / 2 - sheet_slot_clearance / 2)])
|
||||
square([box_width(type) - 2 * box_corner_gap(type), t], center = true);
|
||||
}
|
||||
//
|
||||
// recess for top / bottom panel
|
||||
//
|
||||
translate_z(box_corner_gap(type))
|
||||
rounded_rectangle([box_width(type) + bezel_clearance, box_depth(type) + bezel_clearance, height], inner_r + bezel_clearance / 2, false);
|
||||
//
|
||||
// leave plastic over the corner profiles
|
||||
//
|
||||
translate_z(-box_profile_overlap(type) - 1)
|
||||
linear_extrude(height = box_profile_overlap(type) + box_corner_gap(type) + 2)
|
||||
union() {
|
||||
difference() {
|
||||
square([box_width(type) - 2 * box_inset(type),
|
||||
box_depth(type) - 2 * box_inset(type)], center = true);
|
||||
|
||||
box_corner_quadrants(type, box_width(type), box_depth(type));
|
||||
}
|
||||
box_screw_hole_positions(type)
|
||||
poly_circle(screw_clearance_radius(box_screw(type)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dowel_length = 20;
|
||||
dowel_wall = extrusion_width * 3;
|
||||
dowel_h_wall = layer_height * 6;
|
||||
|
||||
|
||||
module box_bezel_section(type, bottom, rows, cols, x, y) { //! Generates interlocking sections of the bezel to allow it to be bigger than the printer
|
||||
w = (box_width(type) + 2 * box_outset(type)) / cols;
|
||||
h = (box_depth(type) + 2 * box_outset(type)) / rows;
|
||||
bw = box_outset(type) - bezel_clearance / 2;
|
||||
bw2 = box_outset(type) + box_inset(type);
|
||||
|
||||
dw = bw - 2 * dowel_wall;
|
||||
dh = box_bezel_height(type, bottom) - dowel_h_wall;
|
||||
|
||||
dh2 = box_profile_overlap(type) + box_corner_gap(type) - dowel_h_wall;
|
||||
|
||||
end_clearance = 0.5;
|
||||
module male() {
|
||||
rotate([90, 0, 90])
|
||||
linear_extrude(height = dowel_length - 2 * end_clearance, center = true)
|
||||
difference() {
|
||||
union() {
|
||||
h = dh - layer_height;
|
||||
h2 = dh2 - layer_height;
|
||||
hull() {
|
||||
translate([bw / 2, h / 2])
|
||||
square([dw - 1, h], center = true);
|
||||
|
||||
translate([bw / 2, (h - 1) / 2])
|
||||
square([dw, h - 1], center = true);
|
||||
}
|
||||
|
||||
hull() {
|
||||
translate([bw2 / 2, h2 / 2])
|
||||
square([bw2 - 2 * dowel_wall - 1, h2], center = true);
|
||||
|
||||
translate([bw2 / 2, (h2 - 1) / 2])
|
||||
square([bw2 - 2 * dowel_wall, h2 - 1], center = true);
|
||||
}
|
||||
}
|
||||
translate([bw2 / 2, 0])
|
||||
square([box_sheet_slot(type), 2 * box_profile_overlap(type)], center = true);
|
||||
}
|
||||
}
|
||||
|
||||
module female() {
|
||||
union() {
|
||||
translate([0, bw / 2, dh / 2])
|
||||
cube([dowel_length, dw, dh], center = true);
|
||||
|
||||
translate([0, bw2 / 2])
|
||||
cube([dowel_length, bw2 - 2 * dowel_wall, dh2 * 2], center = true);
|
||||
|
||||
hull() {
|
||||
translate([0, bw / 2, dh / 2])
|
||||
cube([2, dw, dh], center = true);
|
||||
|
||||
translate([0, bw / 2, dh / 2])
|
||||
cube([eps, dw + 2 * extrusion_width, dh], center = true);
|
||||
|
||||
}
|
||||
hull() {
|
||||
translate([0, bw2 / 2, dh2 / 2])
|
||||
cube([2, bw2 - 2 * dowel_wall, dh2], center = true);
|
||||
|
||||
translate([0, bw2 / 2, dh2 / 2])
|
||||
cube([eps, bw2 - 2 * dowel_wall + 2 * extrusion_width, dh2], center = true);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module support() {
|
||||
if(!$preview)
|
||||
translate([0, bw / 2 + dw / 2])
|
||||
cube([dowel_length / 2 - 0.25, 2 * extrusion_width + 0.2, dh2]);
|
||||
}
|
||||
|
||||
union() {
|
||||
render() difference() {
|
||||
union() {
|
||||
clip(xmin = 0, xmax = w, ymin = 0, ymax = h)
|
||||
translate([box_width(type) / 2 + box_outset(type) - x * w, box_depth(type) / 2 + box_outset(type) - y * h, box_profile_overlap(type)])
|
||||
box_bezel(type, bottom);
|
||||
|
||||
if(x < cols - 1 && y == 0)
|
||||
translate([w, 0])
|
||||
male();
|
||||
|
||||
if(x > 0 && y == rows - 1)
|
||||
translate([0, h])
|
||||
rotate(180)
|
||||
male();
|
||||
|
||||
if(y < rows - 1 && x == cols - 1)
|
||||
translate([w, h])
|
||||
rotate(90)
|
||||
male();
|
||||
|
||||
if(y > 0 && x == 0)
|
||||
rotate(-90)
|
||||
male();
|
||||
}
|
||||
|
||||
if(x < cols - 1 && y == rows - 1)
|
||||
translate([w, h])
|
||||
rotate(180)
|
||||
female();
|
||||
|
||||
if(x > 0 && y == 0)
|
||||
female();
|
||||
|
||||
if(y < rows - 1 && x == 0)
|
||||
translate([0, h])
|
||||
rotate(-90)
|
||||
female();
|
||||
|
||||
if(y > 0 && x == cols - 1)
|
||||
translate([w, 0])
|
||||
rotate(90)
|
||||
female();
|
||||
}
|
||||
if(x < cols - 1 && y == rows - 1)
|
||||
translate([w, h])
|
||||
rotate(180)
|
||||
support();
|
||||
|
||||
if(x > 0 && y == 0)
|
||||
support();
|
||||
|
||||
if(y < rows - 1 && x == 0)
|
||||
translate([0, h])
|
||||
rotate(-90)
|
||||
support();
|
||||
|
||||
if(y > 0 && x == cols - 1)
|
||||
translate([w, 0])
|
||||
rotate(90)
|
||||
support();
|
||||
}
|
||||
}
|
||||
|
||||
module box_shelf_blank(type) { //! Generates a 2D template for a shelf sheet
|
||||
dxf("box_shelf");
|
||||
|
||||
difference() {
|
||||
sheet_2D(box_sheets(type), box_width(type) - bezel_clearance, box_depth(type) - bezel_clearance, 1);
|
||||
|
||||
offset(bezel_clearance / 2)
|
||||
box_corner_quadrants(type, box_width(type), box_depth(type));
|
||||
}
|
||||
}
|
||||
|
||||
module box_screw_hole_positions(type)
|
||||
for(x = [-1, 1], y = [-1, 1])
|
||||
translate([x * (box_width(type) / 2 - box_hole_inset(type)), y * (box_depth(type) / 2 - box_hole_inset(type))])
|
||||
children();
|
||||
|
||||
module box_base_blank(type) { //! Generates a 2D template for the base sheet
|
||||
dxf("box_base");
|
||||
|
||||
difference() {
|
||||
sheet_2D(box_base_sheet(type), box_width(type), box_depth(type), box_sheet_r(type));
|
||||
|
||||
box_screw_hole_positions(type)
|
||||
drill(screw_clearance_radius(box_screw(type)), 0);
|
||||
}
|
||||
}
|
||||
|
||||
module box_top_blank(type) { //! Generates a 2D template for the top sheet
|
||||
dxf("box_top");
|
||||
|
||||
difference() {
|
||||
sheet_2D(box_top_sheet(type), box_width(type), box_depth(type), box_sheet_r(type));
|
||||
|
||||
box_screw_hole_positions(type)
|
||||
drill(screw_clearance_radius(box_screw(type)), 0);
|
||||
}
|
||||
}
|
||||
|
||||
function subst_sheet(type, sheet) =
|
||||
let(s = box_sheets(type))
|
||||
sheet ? assert(sheet_thickness(sheet) == sheet_thickness(s)) sheet : s;
|
||||
|
||||
module box_left_blank(type, sheet = false) { //! Generates a 2D template for the left sheet, ```sheet``` can be set to override the type
|
||||
dxf("box_left");
|
||||
|
||||
sheet_2D(subst_sheet(type, sheet), box_depth(type) - sheet_reduction(type), box_height(type) - sheet_reduction(type), 1);
|
||||
}
|
||||
|
||||
module box_right_blank(type, sheet = false) { //! Generates a 2D template for the right sheet, ```sheet``` can be set to override the type
|
||||
dxf("box_right");
|
||||
|
||||
sheet_2D(subst_sheet(type, sheet), box_depth(type) - sheet_reduction(type), box_height(type) - sheet_reduction(type), 1);
|
||||
}
|
||||
|
||||
module box_front_blank(type, sheet = false) { //! Generates a 2D template for the front sheet, ```sheet``` can be set to override the type
|
||||
dxf("box_front");
|
||||
|
||||
sheet_2D(subst_sheet(type, sheet), box_width(type) - sheet_reduction(type), box_height(type) - sheet_reduction(type), 1);
|
||||
}
|
||||
|
||||
module box_back_blank(type, sheet = false) { //! Generates a 2D template for the back sheet, ```sheet``` can be set to override the type
|
||||
dxf("box_back");
|
||||
|
||||
sheet_2D(subst_sheet(type, sheet), box_width(type) - sheet_reduction(type), box_height(type) - sheet_reduction(type), 1);
|
||||
}
|
||||
|
||||
module box_base(type) render_2D_sheet(box_base_sheet(type)) box_base_blank(type); //! Default base, can be overridden to customise
|
||||
module box_top(type) render_2D_sheet(box_top_sheet(type)) box_top_blank(type); //! Default top, can be overridden to customise
|
||||
module box_back(type) render_2D_sheet(box_sheets(type)) box_back_blank(type); //! Default back, can be overridden to customise
|
||||
module box_front(type) render_2D_sheet(box_sheets(type)) box_front_blank(type); //! Default front, can be overridden to customise
|
||||
module box_left(type) render_2D_sheet(box_sheets(type)) box_left_blank(type); //! Default left side, can be overridden to customise
|
||||
module box_right(type) render_2D_sheet(box_sheets(type)) box_right_blank(type); //! Default right side, can be overridden to customise
|
94
printed/box_assembly.scad
Normal file
94
printed/box_assembly.scad
Normal file
@@ -0,0 +1,94 @@
|
||||
//
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
//
|
||||
// The assembly is ```include```d so the panel definitions can be overridden to add holes and components.
|
||||
// The _box_module also needs to be wrapped in the file that uses it so it can be called without
|
||||
// parameters to make the assembly views. E.g. module box_assembly() _box_assembly(box);
|
||||
//
|
||||
module _box_assembly(type, top = true, base = true, left = true, right = true, back = true, front = true, bezels = true, corners = 4)
|
||||
assembly("box") {
|
||||
echo("Box:", box_width(type), box_depth(type), box_height(type));
|
||||
|
||||
t = sheet_thickness(box_sheets(type));
|
||||
|
||||
for(corner = [0 : corners - 1]) {
|
||||
x = [-1,1,1,-1][corner];
|
||||
y = [-1,-1,1,1][corner];
|
||||
translate([x * (box_width(type) / 2 + 25 * exploded()), y * (box_depth(type) / 2 + 25 * exploded())])
|
||||
rotate(corner * 90) {
|
||||
color(pp2_colour) render()
|
||||
box_corner_profile(type);
|
||||
|
||||
translate([box_hole_inset(type), box_hole_inset(type)])
|
||||
for(z = [-1, 1])
|
||||
rotate([z * 90 -90, 0, 0])
|
||||
translate_z(box_height(type) / 2 - box_margin(type))
|
||||
insert(box_insert(type));
|
||||
}
|
||||
}
|
||||
|
||||
for(z = [-1, 1]) {
|
||||
sheet_thickness = sheet_thickness(z > 0 ? box_top_sheet(type) : box_base_sheet(type));
|
||||
|
||||
translate_z(z * (box_height(type) / 2 - box_corner_gap(type) + 50 * exploded()))
|
||||
rotate([z * 90 - 90, 0, 0])
|
||||
if(bezels && (z > 0 ? top : base))
|
||||
color(pp1_colour) render() box_bezel(type, z < 0);
|
||||
|
||||
translate_z(z * (box_height(type) / 2 + sheet_thickness + 50 * exploded()))
|
||||
box_screw_hole_positions(type)
|
||||
rotate([z * 90 -90, 0, 0])
|
||||
explode(50, true)
|
||||
screw_and_washer(box_screw(type), box_screw_length(type, z > 0), true);
|
||||
}
|
||||
for(x = [-1, 1])
|
||||
translate([x * (box_width(type) / 2 + t / 2 + 25 * exploded()), 0])
|
||||
rotate([90, 0, x * 90])
|
||||
if(x > 0) {
|
||||
if(right)
|
||||
box_right(type);
|
||||
}
|
||||
else
|
||||
if(left)
|
||||
box_left(type);
|
||||
|
||||
for(y = [-1, 1])
|
||||
translate([0, y * (box_depth(type) / 2 + t / 2 + 25 * exploded())])
|
||||
rotate([90, 0, y * 90 + 90])
|
||||
if(y < 0) {
|
||||
if(front)
|
||||
box_front(type);
|
||||
}
|
||||
else
|
||||
if(back)
|
||||
box_back(type);
|
||||
|
||||
for(z = [-1, 1]) {
|
||||
sheet_thickness = sheet_thickness(z > 0 ? box_top_sheet(type) : box_base_sheet(type));
|
||||
translate_z(z * (box_height(type) / 2 + sheet_thickness / 2 + eps + 100 * exploded()))
|
||||
if(z > 0) {
|
||||
if(top)
|
||||
box_top(type);
|
||||
}
|
||||
else
|
||||
if(base)
|
||||
box_base(type);
|
||||
}
|
||||
}
|
261
printed/butt_box.scad
Normal file
261
printed/butt_box.scad
Normal file
@@ -0,0 +1,261 @@
|
||||
//
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
//
|
||||
//! A box made from CNC cut panels butted together using printed fixing blocks. Useful for making large
|
||||
//! boxes with minimal 3D printing. More blocks are added as the box gets bigger.
|
||||
//!
|
||||
//! Needs to be ```include```d rather than ```use```d to allow the panel definitions to be overridden to add holes
|
||||
//! and mounted components.
|
||||
//!
|
||||
//! A list specifies the internal dimensions, screw type, top, bottom and side sheet types and the block
|
||||
//! maximum spacing.
|
||||
//!
|
||||
//! Uses [fixing blocks](#fixing_block) and [corner blocks](#corner_block).
|
||||
//
|
||||
|
||||
use <fixing_block.scad>
|
||||
use <corner_block.scad>
|
||||
use <../utils/maths.scad>
|
||||
|
||||
function bbox_screw(type) = type[0]; //! Screw type for corner blocks
|
||||
function bbox_sheets(type) = type[1]; //! Sheet type for the sides
|
||||
function bbox_base_sheet(type)= type[2]; //! Sheet type for the base
|
||||
function bbox_top_sheet(type) = type[3]; //! Sheet type for the top
|
||||
function bbox_span(type) = type[4]; //! Maximum span between fixing blocks
|
||||
function bbox_width(type) = type[5]; //! Internal width
|
||||
function bbox_depth(type) = type[6]; //! Internal depth
|
||||
function bbox_height(type) = type[7]; //! Internal height
|
||||
|
||||
module bbox_shelf_blank(type) { //! 2D template for a shelf
|
||||
dxf("bbox_shelf");
|
||||
|
||||
sheet_2D(bbox_sheets(type), bbox_width(type), bbox_depth(type), 1);
|
||||
}
|
||||
|
||||
function corner_block_positions(type) = let(
|
||||
width = bbox_width(type),
|
||||
depth = bbox_depth(type),
|
||||
height = bbox_height(type)
|
||||
)
|
||||
[for(corner = [0 : 3], z = [-1, 1])
|
||||
let(
|
||||
x = [-1,1,1,-1][corner],
|
||||
y = [-1,-1,1,1][corner]
|
||||
) translate([x * (width / 2), y * (depth / 2), z * height / 2]) *
|
||||
rotate([z > 0 ? 180 : 0, 0, corner * 90 + (z > 0 ? 90 : 0)])
|
||||
|
||||
];
|
||||
|
||||
module corner_block_positions(type) {
|
||||
bt = sheet_thickness(bbox_base_sheet(type));
|
||||
tt = sheet_thickness(bbox_top_sheet(type));
|
||||
for(p = corner_block_positions(type))
|
||||
let($thickness = transform([0, 0, 0], p).z > 0 ? tt : bt)
|
||||
multmatrix(p)
|
||||
children();
|
||||
}
|
||||
|
||||
function corner_holes(type) = [for(p = corner_block_positions(type), q = corner_block_holes(bbox_screw(type))) p * q];
|
||||
|
||||
function fixing_block_positions(type) = let(
|
||||
width = bbox_width(type),
|
||||
depth = bbox_depth(type),
|
||||
height = bbox_height(type),
|
||||
span = bbox_span(type),
|
||||
wspans = floor(width / span),
|
||||
wspan = width / (wspans + 1),
|
||||
dspans = floor(depth / span),
|
||||
dspan = depth / (dspans + 1),
|
||||
hspans = floor(height / span),
|
||||
hspan = height / (hspans + 1)
|
||||
)
|
||||
[
|
||||
for(i = [0 : 1 : wspans - 1], y = [-1, 1], z = [-1, 1])
|
||||
translate([(i - (wspans - 1) / 2) * wspan, y * depth / 2, z * height / 2]) *
|
||||
rotate([0, z * 90 + 90, y * 90 + 90]),
|
||||
|
||||
for(i = [0 : 1 : dspans - 1], x = [-1, 1], z = [-1, 1])
|
||||
translate([x * width / 2, (i - (dspans - 1) / 2) * dspan, z * height / 2]) *
|
||||
rotate([0, z * 90 + 90, x * 90]),
|
||||
|
||||
for(i = [0 : 1 : hspans - 1], x = [-1, 1], y = [-1, 1])
|
||||
translate([x * width / 2, y * depth / 2, (i - (hspans - 1) / 2) * hspan]) *
|
||||
rotate([y > 0 ? 180 : 0, x * y * 90]),
|
||||
|
||||
];
|
||||
|
||||
function side_holes(type) = [for(p = fixing_block_positions(type), q = fixing_block_holes(bbox_screw(type))) p * q];
|
||||
|
||||
module fixing_block_positions(type) {
|
||||
t = sheet_thickness(bbox_sheets(type));
|
||||
bt = sheet_thickness(bbox_base_sheet(type));
|
||||
tt = sheet_thickness(bbox_top_sheet(type));
|
||||
h = bbox_height(type) / 2 - 1;
|
||||
for(p = fixing_block_positions(type))
|
||||
let(z = transform([0, 0, 0], p).z, $thickness = z > h ? tt : z < -h ? bt : t)
|
||||
multmatrix(p)
|
||||
children();
|
||||
}
|
||||
|
||||
module drill_holes(type, t)
|
||||
for(list = [corner_holes(type), side_holes(type)], p = list)
|
||||
let(q = t * p)
|
||||
if(abs(transform([0, 0, 0], q).z) < eps)
|
||||
multmatrix(q)
|
||||
drill(screw_clearance_radius(bbox_screw(type)), 0);
|
||||
|
||||
module bbox_base_blank(type) { //! 2D template for the base
|
||||
dxf("bbox_base");
|
||||
|
||||
difference() {
|
||||
sheet_2D(bbox_base_sheet(type), bbox_width(type), bbox_depth(type), 1);
|
||||
|
||||
drill_holes(type, translate(bbox_height(type) / 2));
|
||||
}
|
||||
}
|
||||
|
||||
module bbox_top_blank(type) { //! 2D template for the top
|
||||
dxf("bbox_top");
|
||||
|
||||
t = sheet_thickness(bbox_sheets(type));
|
||||
|
||||
difference() {
|
||||
translate([0, t / 2])
|
||||
sheet_2D(bbox_top_sheet(type), bbox_width(type) + 2 * t, bbox_depth(type) + t);
|
||||
|
||||
drill_holes(type, translate(-bbox_height(type) / 2));
|
||||
}
|
||||
}
|
||||
|
||||
module bbox_left_blank(type) { //! 2D template for the left side
|
||||
dxf("bbox_left");
|
||||
|
||||
t = sheet_thickness(bbox_sheets(type));
|
||||
bb = sheet_thickness(bbox_base_sheet(type));
|
||||
|
||||
difference() {
|
||||
translate([-t / 2, -bb / 2])
|
||||
sheet_2D(bbox_sheets(type), bbox_depth(type) + t, bbox_height(type) + bb);
|
||||
|
||||
drill_holes(type, rotate([0, 90, 90]) * translate([bbox_width(type) / 2, 0]));
|
||||
}
|
||||
}
|
||||
|
||||
module bbox_right_blank(type) { //! 2D template for the right side
|
||||
dxf("bbox_right");
|
||||
|
||||
t = sheet_thickness(bbox_sheets(type));
|
||||
bb = sheet_thickness(bbox_base_sheet(type));
|
||||
|
||||
difference() {
|
||||
translate([t / 2, -bb / 2])
|
||||
sheet_2D(bbox_sheets(type), bbox_depth(type) + t, bbox_height(type) + bb);
|
||||
|
||||
drill_holes(type, rotate([0, -90, 90]) * translate([-bbox_width(type) / 2, 0]));
|
||||
}
|
||||
}
|
||||
|
||||
module bbox_front_blank(type) { //! 2D template for the front
|
||||
dxf("bbox_front");
|
||||
|
||||
t = sheet_thickness(bbox_sheets(type));
|
||||
bb = sheet_thickness(bbox_base_sheet(type));
|
||||
bt = sheet_thickness(bbox_top_sheet(type));
|
||||
|
||||
difference() {
|
||||
translate([0, (bt - bb) / 2])
|
||||
sheet_2D(bbox_sheets(type), bbox_width(type) + 2 * t, bbox_height(type) + bb + bt);
|
||||
|
||||
drill_holes(type, rotate([-90, 0, 0]) * translate([0, bbox_depth(type) / 2]));
|
||||
}
|
||||
}
|
||||
|
||||
module bbox_back_blank(type) { //! 2D template for the back
|
||||
dxf("bbox_back");
|
||||
|
||||
bb = sheet_thickness(bbox_base_sheet(type));
|
||||
t = sheet_thickness(bbox_sheets(type));
|
||||
|
||||
difference() {
|
||||
translate([0, -bb / 2])
|
||||
sheet_2D(bbox_sheets(type), bbox_width(type), bbox_height(type) + bb);
|
||||
|
||||
drill_holes(type, rotate([90, 0, 0]) * translate([0, -bbox_depth(type) / 2]));
|
||||
}
|
||||
}
|
||||
|
||||
module bbox_base(type) render_2D_sheet(bbox_base_sheet(type)) bbox_base_blank(type); //! Default base, can be overridden to customise
|
||||
module bbox_top(type) render_2D_sheet(bbox_top_sheet(type)) bbox_top_blank(type); //! Default top, can be overridden to customise
|
||||
module bbox_back(type) render_2D_sheet(bbox_sheets(type)) bbox_back_blank(type); //! Default back, can be overridden to customise
|
||||
module bbox_front(type) render_2D_sheet(bbox_sheets(type)) bbox_front_blank(type); //! Default front, can be overridden to customise
|
||||
module bbox_left(type) render_2D_sheet(bbox_sheets(type)) bbox_left_blank(type); //! Default left side, can be overridden to customise
|
||||
module bbox_right(type) render_2D_sheet(bbox_sheets(type)) bbox_right_blank(type); //! Default right side, can be overridden to customise
|
||||
|
||||
module _bbox_assembly(type, top = true, base = true, left = true, right = true, back = true, front = true) //! The box assembly, wrap with a local copy without parameters
|
||||
assembly("bbox") {
|
||||
width = bbox_width(type);
|
||||
depth = bbox_depth(type);
|
||||
height = bbox_height(type);
|
||||
echo("Box:", width, depth, height);
|
||||
|
||||
t = sheet_thickness(bbox_sheets(type));
|
||||
bt = sheet_thickness(bbox_base_sheet(type));
|
||||
tt = sheet_thickness(bbox_top_sheet(type));
|
||||
|
||||
corner_block_positions(type)
|
||||
fastened_corner_block_assembly(t, bbox_screw(type), $thickness);
|
||||
|
||||
fixing_block_positions(type)
|
||||
fastened_fixing_block_assembly(t, bbox_screw(type), thickness2 = $thickness);
|
||||
|
||||
for(x = [-1, 1])
|
||||
translate([x * (width / 2 + t / 2 + eps + 25 * exploded()), 0])
|
||||
rotate([90, 0, x * 90])
|
||||
if(x > 0) {
|
||||
if(right)
|
||||
bbox_right(type);
|
||||
}
|
||||
else
|
||||
if(left)
|
||||
bbox_left(type);
|
||||
|
||||
for(y = [-1, 1])
|
||||
translate([0, y * (depth / 2 + t / 2 + eps + 25 * exploded())])
|
||||
rotate([90, 0, y * 90 + 90])
|
||||
if(y < 0) {
|
||||
if(front)
|
||||
bbox_front(type);
|
||||
}
|
||||
else
|
||||
if(back)
|
||||
bbox_back(type);
|
||||
|
||||
for(z = [-1, 1]) {
|
||||
sheet_thickness = z > 0 ? tt : bt;
|
||||
translate_z(z * (height / 2 + sheet_thickness / 2 + eps + 100 * exploded()))
|
||||
if(z > 0) {
|
||||
if(top)
|
||||
bbox_top(type);
|
||||
}
|
||||
else
|
||||
if(base)
|
||||
bbox_base(type);
|
||||
}
|
||||
}
|
187
printed/cable_grommets.scad
Normal file
187
printed/cable_grommets.scad
Normal file
@@ -0,0 +1,187 @@
|
||||
//
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
//
|
||||
//! Printed cable grommets for passing cables through panels avoiding sharp edges and in the case
|
||||
//! of conductive panels, an extra layer of insulation.
|
||||
//
|
||||
include <../core.scad>
|
||||
use <../vitamins/cable_strip.scad>
|
||||
|
||||
base = 1.25;
|
||||
slot_height = round_to_layer(1.27) + layer_height;
|
||||
wall = 1.6;
|
||||
overlap = 1.5;
|
||||
height = base + slot_height + wall + overlap;
|
||||
rad = wall + overlap;
|
||||
clearance = 0.1;
|
||||
|
||||
module ribbon_grommet_hole(ways, h = 50, expand = true) { //! Generate a hole for a ribbon grommet
|
||||
length = ribbon_clamp_slot(ways) + 2 * wall;
|
||||
rad = cnc_bit_r;
|
||||
height = base + slot_height + wall;
|
||||
extrude_if(h)
|
||||
offset(expand ? clearance : 0)
|
||||
hull() {
|
||||
translate([-length / 2, 0])
|
||||
square([length, base]);
|
||||
|
||||
for(end = [-1, 1])
|
||||
translate([end * (length / 2 - rad), height - rad])
|
||||
drill(rad, 0);
|
||||
}
|
||||
}
|
||||
|
||||
module ribbon_grommet(ways, thickness) { //! Generate the STL for a printed ribbon grommet
|
||||
stl(str("ribbon_grommet_", ways, "_", thickness));
|
||||
|
||||
width = 2 * (wall + clearance) + thickness;
|
||||
slot_length = ribbon_clamp_slot(ways);
|
||||
length = slot_length + 2 * wall + 2 * overlap;
|
||||
|
||||
rotate([90, 0, 0])
|
||||
union() {
|
||||
for(side = [-1, 1])
|
||||
translate_z(side * (width - wall) / 2)
|
||||
linear_extrude(height = wall, center = true, convexity = 5)
|
||||
difference() {
|
||||
hull() {
|
||||
translate([-length / 2, 0])
|
||||
square([length, base]);
|
||||
|
||||
for(end = [-1, 1])
|
||||
translate([end * (length / 2 - rad), height - rad])
|
||||
semi_circle(rad);
|
||||
}
|
||||
translate([-slot_length / 2, base])
|
||||
square([slot_length, slot_height]);
|
||||
}
|
||||
|
||||
linear_extrude(height = width -1, center = true)
|
||||
difference() {
|
||||
ribbon_grommet_hole(ways, expand = false, h = 0);
|
||||
|
||||
translate([-slot_length / 2, base])
|
||||
square([slot_length, slot_height]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module round_grommet_top(diameter, thickness, od = undef) { //! Generate the STL for a round grommet top half
|
||||
stl(str("round_grommet_top_", round(diameter * 10), "_", thickness));
|
||||
chamfer = layer_height;
|
||||
h = wall + thickness + wall;
|
||||
r1 = diameter / 2;
|
||||
r2 = od == undef ? corrected_radius(r1) + wall : od / 2;
|
||||
r3 = r2 + overlap;
|
||||
r0 = r1 + 1;
|
||||
union() {
|
||||
rotate_extrude()
|
||||
polygon([
|
||||
[r0, 0],
|
||||
[r3 - chamfer, 0],
|
||||
[r3, chamfer],
|
||||
[r3, wall],
|
||||
[r2, wall],
|
||||
[r2, h - chamfer],
|
||||
[r2 - chamfer, h],
|
||||
[r0, h],
|
||||
]);
|
||||
|
||||
render() difference() {
|
||||
cylinder(r = r0 + eps, h = h);
|
||||
|
||||
poly_cylinder(r = r1, h = 100, center = true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module round_grommet_bottom(diameter, od = undef) { //! Generate the STL for a round grommet bottom half
|
||||
stl(str("round_grommet_bottom_", round(diameter * 10)));
|
||||
chamfer = layer_height;
|
||||
r1 = diameter / 2;
|
||||
r2 = od == undef ? corrected_radius(r1) + wall : od / 2;
|
||||
r3 = r2 + max(overlap, wall + chamfer);
|
||||
rotate_extrude()
|
||||
polygon([
|
||||
[r2, chamfer],
|
||||
[r2 + chamfer, 0],
|
||||
[r3, 0],
|
||||
[r3, wall - chamfer],
|
||||
[r3 - chamfer, wall],
|
||||
[r2, wall],
|
||||
]);
|
||||
}
|
||||
|
||||
module round_grommet_hole(diameter, h = 100) //! Make a hole for a round grommet
|
||||
drill(diameter / 2 + wall + clearance, h);
|
||||
|
||||
module round_grommet_assembly(diameter, thickness, od = undef) {
|
||||
color(pp1_colour)
|
||||
translate_z(wall)
|
||||
vflip()
|
||||
round_grommet_top(diameter, thickness, od);
|
||||
|
||||
color(pp2_colour)
|
||||
translate_z(-thickness)
|
||||
vflip()
|
||||
round_grommet_bottom(diameter, od);
|
||||
}
|
||||
|
||||
module mouse_grommet_hole(r, h = 50, z = undef, expand = wall + clearance) //! Make a hole for a mouse grommet
|
||||
extrude_if(h)
|
||||
hull(){
|
||||
R = r + expand;
|
||||
translate([0, z == undef ? R : z])
|
||||
semi_circle(R);
|
||||
|
||||
translate([-R, 0])
|
||||
square([2 * R, eps]);
|
||||
}
|
||||
|
||||
module mouse_grommet(r, thickness) { //! Make the STL for a mouse grommet
|
||||
stl(str("mouse_grommet_", r * 10, "_", thickness));
|
||||
|
||||
width = 2 * (wall + clearance) + thickness;
|
||||
length = 2 * r + 2 * wall + 2 * overlap;
|
||||
|
||||
rotate([90, 0, 0])
|
||||
union() {
|
||||
for(side = [-1, 1])
|
||||
translate_z(side * (width - wall) / 2)
|
||||
linear_extrude(height = wall, center = true)
|
||||
difference() {
|
||||
mouse_grommet_hole(r + wall + overlap, z = r + wall, h = 0, expand = 0);
|
||||
|
||||
translate([0, wall])
|
||||
mouse_grommet_hole(r, h = 0, expand = 0);
|
||||
}
|
||||
linear_extrude(height = width - 1, center = true)
|
||||
difference() {
|
||||
mouse_grommet_hole(r, h = 0, z = r + wall, expand = wall);
|
||||
|
||||
translate([0, wall])
|
||||
mouse_grommet_hole(r, h = 0, expand = 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module ribbon_grommet_20_3_stl() ribbon_grommet(20, 3);
|
||||
module mouse_grommet_20_3_stl() mouse_grommet(2,3);
|
||||
module mouse_grommet_30_3_stl() mouse_grommet(3,3);
|
63
printed/carriers.scad
Normal file
63
printed/carriers.scad
Normal file
@@ -0,0 +1,63 @@
|
||||
//
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
//
|
||||
//! Adapts ESP12 module to 0.1" grid. See <https://hydraraptor.blogspot.com/2018/04/esp-12-module-breakout-adaptor.html>.
|
||||
//
|
||||
$extrusion_width = 0.5;
|
||||
|
||||
include <../core.scad>
|
||||
|
||||
module ESP12F_carrier_stl() { //! Generate the STL for an ESP12 carrier
|
||||
stl("ESP12F_carrier");
|
||||
pins = 8;
|
||||
pitch1 = 2;
|
||||
pitch2 = 2.54;
|
||||
hole = pitch1 - squeezed_wall;
|
||||
hole2 = pitch2 - 3 * extrusion_width;
|
||||
length1 = (pins - 1) * pitch1 + hole + squeezed_wall * 2;
|
||||
length2 = (pins - 1) * pitch2 + hole + squeezed_wall * 2;
|
||||
height = 3;
|
||||
|
||||
wpitch1 = (pins - 1) * pitch1;
|
||||
wpitch2 = ceil(wpitch1 / 2.54) * 2.54;
|
||||
|
||||
width1 = wpitch1 + hole + squeezed_wall * 2;
|
||||
width2 = wpitch2 + hole2 + squeezed_wall * 2;
|
||||
|
||||
difference() {
|
||||
hull() {
|
||||
translate_z(height - eps / 2)
|
||||
cube([width1, length1, eps], center = true);
|
||||
|
||||
translate_z(eps / 2)
|
||||
cube([width2, length2, eps], center = true);
|
||||
}
|
||||
|
||||
for(side = [-1, 1])
|
||||
for(i = [0 : pins - 1])
|
||||
hull() {
|
||||
translate([side * wpitch1 / 2, i * pitch1 - (pins - 1) * pitch1 / 2, height])
|
||||
cube([hole, hole, eps], center = true);
|
||||
|
||||
translate([side * wpitch2 / 2, i * pitch2 - (pins - 1) * pitch2 / 2])
|
||||
cube([hole2, hole2, eps], center = true);
|
||||
}
|
||||
}
|
||||
}
|
181
printed/corner_block.scad
Normal file
181
printed/corner_block.scad
Normal file
@@ -0,0 +1,181 @@
|
||||
//
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
//
|
||||
//! Corner brackets using threaded inserts for fastening three sheets together at right angles.
|
||||
//! Defaults to M3 but other screws sizes can be specified provided they have inserts defined.
|
||||
//!
|
||||
//! See [butt_box](#Butt_box) for an example of usage.
|
||||
//!
|
||||
//! Note that the block with its inserts is defined as a sub assembly, but its fasteners get added to the parent assembly.
|
||||
//
|
||||
include <../core.scad>
|
||||
include <../vitamins/screws.scad>
|
||||
include <../vitamins/inserts.scad>
|
||||
use <../utils/rounded_cylinder.scad>
|
||||
use <../utils/maths.scad>
|
||||
|
||||
def_screw = M3_cap_screw;
|
||||
wall = 3;
|
||||
overshoot = 2; // how far screw can overshoot the insert
|
||||
|
||||
function corner_block_screw() = def_screw; //! Default screw type
|
||||
|
||||
function corner_block_hole_offset(screw = def_screw) = //! Hole offset from the edge
|
||||
let(insert = screw_insert(screw))
|
||||
insert_length(insert) + max(overshoot + screw_clearance_radius(screw), insert_hole_radius(insert)) + 1;
|
||||
|
||||
function corner_block_width(screw = def_screw) = //! Block width, depth and height
|
||||
corner_block_hole_offset(screw) + insert_outer_d(screw_insert(screw)) / 2 + wall;
|
||||
|
||||
function corner_block_v_hole(screw = def_screw) = let(offset = corner_block_hole_offset(screw)) translate([offset, offset]) * rotate([180, 0, 0]); //! Transform to bottom hole
|
||||
|
||||
function corner_block_h_holes(screw = def_screw) = //! List of transforms to side holes
|
||||
let(offset = corner_block_hole_offset(screw))
|
||||
[translate([offset, 0, offset]) * rotate([90, 0, 0]),
|
||||
translate([0, offset, offset - layer_height]) * rotate([90, 0, -90])];
|
||||
|
||||
function corner_block_holes(screw) = concat([corner_block_v_hole(screw)], corner_block_h_holes(screw)); //! List of transforms to all holes
|
||||
|
||||
module corner_block_v_hole(screw = def_screw) //! Place children at the bottom screw hole
|
||||
multmatrix(corner_block_v_hole(screw))
|
||||
children();
|
||||
|
||||
module corner_block_h_holes(screw = def_screw) //! Place children at the side screw holes
|
||||
for(p = corner_block_h_holes(screw))
|
||||
multmatrix(p)
|
||||
children();
|
||||
|
||||
module corner_block_holes(screw = def_screw) //! Place children at all the holes
|
||||
for(p = corner_block_holes(screw))
|
||||
multmatrix(p)
|
||||
children();
|
||||
|
||||
module corner_block(screw = def_screw, name = false) { //! Generate the STL for a printed corner block
|
||||
stl(name ? name : str("corner_block", "_M", screw_radius(screw) * 20));
|
||||
|
||||
r = 1;
|
||||
cb_width = corner_block_width(screw);
|
||||
cb_height = cb_width;
|
||||
cb_depth = cb_width;
|
||||
insert = screw_insert(screw);
|
||||
corner_rad = insert_outer_d(insert) / 2 + wall;
|
||||
offset = corner_block_hole_offset(screw);
|
||||
difference() {
|
||||
hull() {
|
||||
translate([r, r])
|
||||
rounded_cylinder(r = r, h = cb_height, r2 = r);
|
||||
|
||||
translate([r, cb_depth - r])
|
||||
cylinder(r = r, h = cb_height - corner_rad);
|
||||
|
||||
translate([cb_width - r, r])
|
||||
cylinder(r = r, h = cb_height - corner_rad);
|
||||
|
||||
translate([offset, offset, offset])
|
||||
sphere(corner_rad);
|
||||
|
||||
translate([offset, offset])
|
||||
cylinder(r = corner_rad, h = offset);
|
||||
|
||||
translate([offset, r, offset])
|
||||
rotate([-90, 0, 180])
|
||||
rounded_cylinder(r = corner_rad, h = r, r2 = r);
|
||||
|
||||
translate([r, offset, offset])
|
||||
rotate([0, 90, 180])
|
||||
rounded_cylinder(r = corner_rad, h = r, r2 = r);
|
||||
}
|
||||
corner_block_v_hole(screw)
|
||||
insert_hole(insert, overshoot);
|
||||
|
||||
corner_block_h_holes(screw)
|
||||
insert_hole(insert, overshoot, true);
|
||||
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
module corner_block_assembly(screw = def_screw, name = false) //! The printed block with inserts
|
||||
assembly(str("corner_block_M", 20 * screw_radius(screw))) {
|
||||
insert = screw_insert(screw);
|
||||
|
||||
color(name ? pp2_colour : pp1_colour)
|
||||
render() corner_block(screw, name) children();
|
||||
|
||||
corner_block_h_holes(screw)
|
||||
insert(insert);
|
||||
|
||||
corner_block_v_hole(screw)
|
||||
insert(insert);
|
||||
}
|
||||
|
||||
module fastened_corner_block_assembly(thickness, screw = def_screw, thickness_below = undef, name = false) { //! Printed block with all fasteners
|
||||
washer = screw_washer(screw);
|
||||
insert = screw_insert(screw);
|
||||
screw_length = screw_shorter_than(2 * washer_thickness(washer) + thickness + insert_length(insert) + overshoot);
|
||||
|
||||
corner_block_assembly(screw, name) children();
|
||||
|
||||
corner_block_h_holes(screw)
|
||||
translate_z(thickness)
|
||||
screw_and_washer(screw, screw_length, true);
|
||||
|
||||
thickness2 = thickness_below ? thickness_below : thickness;
|
||||
screw_length2 = screw_shorter_than(2 * washer_thickness(washer) + thickness2 + insert_length(insert) + overshoot);
|
||||
corner_block_v_hole(screw)
|
||||
translate_z(thickness2)
|
||||
screw_and_washer(screw, screw_length2, true);
|
||||
}
|
||||
|
||||
module corner_block_M20_stl() corner_block(M2_cap_screw);
|
||||
module corner_block_M25_stl() corner_block(M2p5_cap_screw);
|
||||
module corner_block_M30_stl() corner_block(M3_cap_screw);
|
||||
module corner_block_M40_stl() corner_block(M4_cap_screw);
|
||||
//
|
||||
//! 1. Lay the blocks out and place an M2 insert in each upward facing hole.
|
||||
//! 1. Push them home with a soldering iron with a conical bit heated to 200°C.
|
||||
//! When removing the iron it helps to twist it a little anti-clockwise to release it from the thread.
|
||||
//! 1. Lay the blocks on each of their other two flat sides and repeat.
|
||||
//
|
||||
module corner_block_M20_assembly() corner_block_assembly(M2_cap_screw);
|
||||
|
||||
//
|
||||
//! 1. Lay the blocks out and place an M2.5 insert in each upward facing hole.
|
||||
//! 1. Push them home with a soldering iron with a conical bit heated to 200°C.
|
||||
//! When removing the iron it helps to twist it a little anti-clockwise to release it from the thread.
|
||||
//! 1. Lay the blocks on each of their other two flat sides and repeat.
|
||||
//
|
||||
module corner_block_M25_assembly() corner_block_assembly(M2p5_cap_screw);
|
||||
|
||||
//
|
||||
//! 1. Lay the blocks out and place an M3 insert in each upward facing hole.
|
||||
//! 1. Push them home with a soldering iron with a conical bit heated to 200°C.
|
||||
//! When removing the iron it helps to twist it a little anti-clockwise to release it from the thread.
|
||||
//! 1. Lay the blocks on each of their other two flat sides and repeat.
|
||||
//
|
||||
module corner_block_M30_assembly() corner_block_assembly(M3_cap_screw);
|
||||
|
||||
//
|
||||
//! 1. Lay the blocks out and place an M4 insert in each upward facing hole.
|
||||
//! 1. Push them home with a soldering iron with a conical bit heated to 200°C.
|
||||
//! When removing the iron it helps to twist it a little anti-clockwise to release it from the thread.
|
||||
//! 1. Lay the blocks on each of their other two flat sides and repeat.
|
||||
//
|
||||
module corner_block_M40_assembly() corner_block_assembly(M4_cap_screw);
|
187
printed/door_hinge.scad
Normal file
187
printed/door_hinge.scad
Normal file
@@ -0,0 +1,187 @@
|
||||
//
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
//
|
||||
//! Door hinges to hang an acrylic sheet door on a 3D printer, default 6mm thick.
|
||||
//!
|
||||
//! The screws are tapped into the acrylic.
|
||||
//! Rubber door [sealing strip](#sealing_strip) is used to make it airtight and a [door_latch](#door_latch) holds it closed.
|
||||
//
|
||||
include <../core.scad>
|
||||
include <../vitamins/screws.scad>
|
||||
|
||||
width = 18;
|
||||
thickness = 4;
|
||||
rad = 3;
|
||||
dia = 12;
|
||||
|
||||
pin_screw = M3_cap_screw;
|
||||
screw = M3_dome_screw;
|
||||
stat_screw = M4_dome_screw;
|
||||
|
||||
stat_width = 15;
|
||||
stat_length = 34;
|
||||
stat_clearance = 0.75;
|
||||
|
||||
function door_hinge_pin_x() = -dia / 2; //! X offset of the hinge pin
|
||||
function door_hinge_pin_y() = -dia / 2 - stat_clearance; //! Y offset of the hinge pin
|
||||
function door_hinge_screw() = screw; //! Screw type used for hinge pin
|
||||
function door_hinge_stat_screw() = stat_screw; //! Screw use to fasten the stationary part
|
||||
function door_hinge_stat_width() = stat_width; //! Width of the stationary part
|
||||
function door_hinge_stat_length() = stat_length; //! Length of the stationary part
|
||||
|
||||
module door_hinge_hole_positions(dir = 0) { //! Position chidren at the door hole positions
|
||||
hole_pitch = width - 10;
|
||||
|
||||
for(side = [-1, 1])
|
||||
translate([width / 2 + side * hole_pitch / 2, -dir * width / 2 -side * hole_pitch / 2])
|
||||
children();
|
||||
}
|
||||
|
||||
module door_hinge(door_thickness) { //! Generates STL for the moving part of the hinge
|
||||
stl(str("door_hinge_", door_thickness));
|
||||
|
||||
hole_pitch = width - 10;
|
||||
|
||||
union() {
|
||||
rotate([90, 0, 0])
|
||||
linear_extrude(height = width, center = true)
|
||||
difference() {
|
||||
hull() {
|
||||
translate([dia / 2, thickness + door_thickness / 2])
|
||||
intersection() {
|
||||
rotate(180)
|
||||
teardrop(r = dia / 2, h = 0, truncate = false);
|
||||
|
||||
square([dia + 1, 2 * thickness + door_thickness], center = true);
|
||||
}
|
||||
|
||||
square([1, thickness + door_thickness]);
|
||||
}
|
||||
translate([dia / 2, thickness + door_thickness / 2])
|
||||
teardrop(r = screw_clearance_radius(pin_screw), h = 0);
|
||||
}
|
||||
linear_extrude(height = thickness)
|
||||
difference() {
|
||||
hull() {
|
||||
translate([0, -width / 2])
|
||||
square([1, width]);
|
||||
|
||||
for(side = [-1, 1])
|
||||
translate([-width + rad, side * (width / 2 - rad)])
|
||||
circle4n(rad);
|
||||
}
|
||||
rotate(180)
|
||||
vflip()
|
||||
door_hinge_hole_positions()
|
||||
poly_circle(screw_clearance_radius(screw));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module door_hinge_6_stl() door_hinge(6);
|
||||
|
||||
module door_hinge_stat_hole_positions(dir = 0) { //! Position children over the screws holes of the stationary part
|
||||
hole_pitch = dia + (stat_length - dia) / 2;
|
||||
|
||||
for(side = [-1, 1])
|
||||
translate([side * hole_pitch / 2, dir * (stat_width / 2 + washer_thickness(screw_washer(pin_screw))), thickness])
|
||||
children();
|
||||
}
|
||||
|
||||
module door_hinge_stat_stl() { //! Generates the STL for the stationary part
|
||||
stl("door_hinge_stat");
|
||||
|
||||
union() {
|
||||
linear_extrude(height = thickness)
|
||||
difference() {
|
||||
rounded_square([stat_length, stat_width], rad);
|
||||
|
||||
door_hinge_stat_hole_positions()
|
||||
poly_circle(screw_clearance_radius(stat_screw));
|
||||
}
|
||||
|
||||
rotate([90, 0, 0])
|
||||
linear_extrude(height = stat_width, center = true)
|
||||
difference() {
|
||||
hull() {
|
||||
translate([0, dia / 2 + stat_clearance])
|
||||
circle(d = dia);
|
||||
|
||||
translate([0, 0.5])
|
||||
square([dia, 1], center = true);
|
||||
}
|
||||
translate([0, dia / 2 + stat_clearance])
|
||||
teardrop(r = screw_clearance_radius(pin_screw), h = 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module door_hinge_assembly(top, door_thickness = 6) { //! The moving assembly that goes on the door
|
||||
dir = top ? -1 : 1;
|
||||
pin_x = door_hinge_pin_x();
|
||||
pin_y = door_hinge_pin_y();
|
||||
washer = screw_washer(screw);
|
||||
screw_length = screw_shorter_than(thickness + door_thickness + washer_thickness(washer));
|
||||
|
||||
translate([0, pin_y - (thickness + door_thickness / 2), dir * width / 2]) {
|
||||
rotate([90, 0, 180])
|
||||
color("red") door_hinge(door_thickness);
|
||||
|
||||
rotate([90, 0, 0])
|
||||
door_hinge_hole_positions()
|
||||
screw_and_washer(screw, screw_length);
|
||||
}
|
||||
|
||||
translate([pin_x, pin_y, top ? 0 : -washer_thickness(screw_washer(pin_screw))])
|
||||
washer(screw_washer(pin_screw));
|
||||
|
||||
translate([pin_x, pin_y, top ? washer_thickness(screw_washer(pin_screw)) + stat_width : width])
|
||||
screw_and_washer(pin_screw, screw_longer_than(2 * washer_thickness(screw_washer(pin_screw)) + width + stat_width));
|
||||
}
|
||||
|
||||
module door_hinge_static_assembly(top, sheet_thickness = 3) { //! The stationary assembly
|
||||
dir = top ? -1 : 1;
|
||||
pin_x = door_hinge_pin_x();
|
||||
|
||||
stat_washer = screw_washer(stat_screw);
|
||||
stat_nut = screw_nut(stat_screw);
|
||||
stat_screw_length = screw_longer_than(thickness + sheet_thickness + 2 * washer_thickness(stat_washer) + nut_thickness(stat_nut, true));
|
||||
|
||||
translate([pin_x, 0, -dir * (stat_width / 2 + washer_thickness(screw_washer(pin_screw)))])
|
||||
rotate([90, 0, 0]) {
|
||||
color("lime") door_hinge_stat_stl();
|
||||
|
||||
door_hinge_stat_hole_positions() {
|
||||
screw_and_washer(stat_screw, stat_screw_length);
|
||||
translate_z(-thickness - sheet_thickness)
|
||||
vflip()
|
||||
nut_and_washer(stat_nut, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module door_hinge_parts_stl() { //! Generates the STL for both parts of the hinge
|
||||
translate([2, width / 2 + 1])
|
||||
door_hinge_6_stl();
|
||||
|
||||
translate([0, -stat_width / 2 - 1])
|
||||
door_hinge_stat_stl();
|
||||
}
|
81
printed/door_latch.scad
Normal file
81
printed/door_latch.scad
Normal file
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
//
|
||||
//! Door latch for 6mm acrylic door for 3D printer. See [door_hinge](#door_hinge).
|
||||
//
|
||||
include <../core.scad>
|
||||
use <../utils/hanging_hole.scad>
|
||||
include <../vitamins/screws.scad>
|
||||
|
||||
length = 35;
|
||||
width = 12;
|
||||
height = 14.25;
|
||||
|
||||
thickness = 5;
|
||||
rad = 3;
|
||||
|
||||
screw = M4_hex_screw;
|
||||
|
||||
function door_latch_screw() = screw; //! The screw used for the axle
|
||||
function door_latch_offset() = width / 2 + 1; //! Offset of the axle from the door edge
|
||||
|
||||
nut_trap_depth = round_to_layer(screw_head_height(screw)) + 4 * layer_height;
|
||||
|
||||
module door_latch_stl() { //! Generates the STL for the printed part
|
||||
stl("door_latch");
|
||||
|
||||
ridge = 4;
|
||||
difference() {
|
||||
union() {
|
||||
hull() {
|
||||
rounded_rectangle([length, width, thickness - tan(30) * (width - ridge) / 2], rad, center = false);
|
||||
|
||||
translate_z(thickness / 2)
|
||||
cube([length, ridge, thickness], center = true);
|
||||
}
|
||||
|
||||
cylinder(d = width, h = height);
|
||||
}
|
||||
hanging_hole(nut_trap_depth, screw_clearance_radius(screw))
|
||||
circle(r = nut_trap_radius(screw_nut(screw)), $fn = 6);
|
||||
}
|
||||
}
|
||||
|
||||
module door_latch_assembly(sheet_thickness = 3) { //! The assembly for a specified sheet thickess
|
||||
washer = screw_washer(screw);
|
||||
nut = screw_nut(screw);
|
||||
|
||||
screw_length = screw_longer_than(height - nut_trap_depth + sheet_thickness + 2 * washer_thickness(washer) + nut_thickness(nut, true));
|
||||
|
||||
translate([0, -height - washer_thickness(washer)])
|
||||
rotate([-90, 0, 0]) {
|
||||
color("lime") render() door_latch_stl();
|
||||
|
||||
translate_z(nut_trap_depth)
|
||||
vflip()
|
||||
screw(screw, screw_length);
|
||||
|
||||
translate_z(height)
|
||||
washer(washer);
|
||||
|
||||
translate_z(height + sheet_thickness + washer_thickness(washer))
|
||||
nut_and_washer(nut, true);
|
||||
}
|
||||
}
|
92
printed/fan_guard.scad
Normal file
92
printed/fan_guard.scad
Normal file
@@ -0,0 +1,92 @@
|
||||
//
|
||||
// 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/>.
|
||||
|
||||
//
|
||||
//! Pintable fan finger guard to match the specified fan. To be ```include```d, not ```use```d.
|
||||
//!
|
||||
//! The ring spacing as well as the number of spokes can be specified, if zero a gasket is generated instead of a guard.
|
||||
//
|
||||
use <../utils/tube.scad>
|
||||
|
||||
function fan_guard_thickness() = 2; //! Default thickness
|
||||
|
||||
function fan_guard_wall() = extrusion_width - layer_height / 2 + nozzle / 2 + extrusion_width / 2;
|
||||
function fan_guard_corner_r(type) = washer_diameter(screw_washer(fan_screw(type))) / 2 + 0.5; //! Corner radius of the guard
|
||||
function fan_guard_width(type) = max(2 * (fan_hole_pitch(type) + fan_guard_corner_r(type)), fan_bore(type) + 4 * fan_guard_wall()); //! Width of the guard
|
||||
|
||||
module fan_guard(type, name = false, thickness = fan_guard_thickness(), spokes = 4, finger_width = 7, grill = false) { //! Generate the STL
|
||||
if(thickness)
|
||||
stl(name ? name : str("fan_guard_", fan_width(type)));
|
||||
hole_pitch = fan_hole_pitch(type);
|
||||
corner_radius = fan_guard_corner_r(type);
|
||||
wall = grill ? 2 : fan_guard_wall();
|
||||
spoke = grill ? 3 : wall;
|
||||
width = fan_guard_width(type);
|
||||
|
||||
hole = fan_aperture(type) / 2;
|
||||
max_ring_pitch = finger_width + wall;
|
||||
inner_ring = max_ring_pitch / 2;
|
||||
gap = hole + wall / 2 - inner_ring;
|
||||
rings = ceil(gap / max_ring_pitch);
|
||||
ring_pitch = gap / rings;
|
||||
spoke_end = grill && fan_aperture(type) > fan_bore(type) ? hole - ring_pitch : hole;
|
||||
spoke_start = grill && rings > 1 ? inner_ring + ring_pitch : inner_ring;
|
||||
rounding = grill ? 1.5 : 0;
|
||||
|
||||
extrude_if(thickness, center = false) {
|
||||
difference() {
|
||||
offset(-rounding) offset(rounding) {
|
||||
difference() {
|
||||
rounded_square([width, width], r = width / 2 - hole_pitch);
|
||||
|
||||
fan_holes(type, !grill, !grill, h = 0);
|
||||
}
|
||||
if(spokes) {
|
||||
intersection() {
|
||||
union() {
|
||||
for(i = [(grill ? 1 : 0) : 1 : rings - 1]) {
|
||||
r = inner_ring + i * ring_pitch;
|
||||
|
||||
ring(or = r + wall / 2, ir = r - wall / 2);
|
||||
}
|
||||
for(i = [0 : spokes - 1])
|
||||
rotate(i * 360 / spokes + 45)
|
||||
translate([spoke_start, -spoke / 2])
|
||||
square([spoke_end - spoke_start + eps, spoke]);
|
||||
}
|
||||
square(width - eps, center = true);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(grill)
|
||||
fan_hole_positions(type, z = 0)
|
||||
drill(screw_clearance_radius(fan_screw(type)), 0);
|
||||
|
||||
}
|
||||
if(grill)
|
||||
difference() {
|
||||
r = min(inner_ring + ring_pitch, fan_hub(type) / 2);
|
||||
circle(r);
|
||||
|
||||
for(a = [45 : 90 : 360])
|
||||
rotate(a)
|
||||
translate([r / 2, 0])
|
||||
circle(wall);
|
||||
}
|
||||
}
|
||||
}
|
170
printed/fixing_block.scad
Normal file
170
printed/fixing_block.scad
Normal file
@@ -0,0 +1,170 @@
|
||||
//
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
//
|
||||
//! Fixing block to mount two sheets at right angles using threaded inserts.
|
||||
//! Defaults to M3 but other screw sizes can be specified provided they have inserts defined.
|
||||
//!
|
||||
//! See [butt_box](#Butt_box) for an example of usage.
|
||||
//!
|
||||
//! Note that the block with its inserts is defined as a sub assembly, but its fasteners get added to the parent assembly.
|
||||
//
|
||||
include <../core.scad>
|
||||
include <../vitamins/screws.scad>
|
||||
include <../vitamins/inserts.scad>
|
||||
use <../utils/maths.scad>
|
||||
|
||||
def_screw = M3_cap_screw;
|
||||
wall = 2.5;
|
||||
|
||||
function fixing_block_screw() = def_screw; //! Default screw type
|
||||
function fixing_block_width(screw = def_screw) = 4 * wall + 3 * insert_outer_d(screw_insert(screw)); //! Width given screw size
|
||||
function fixing_block_depth(screw = def_screw) = //! Depth given screw size
|
||||
let(insert = screw_insert(screw))
|
||||
max(insert_length(insert) + wall, insert_outer_d(insert) + 2 * wall);
|
||||
|
||||
function fixing_block_height(screw = def_screw) = fixing_block_depth(screw); //! Height given screw size, same as depth
|
||||
|
||||
function fixing_block_h_hole(screw = def_screw) = translate(fixing_block_depth(screw) / 2) * rotate([90, 0, 0]); //! Returns transform to position the horizontal screw
|
||||
function fixing_block_v_holes(screw = def_screw) = //! Returns a list of transforms to position the vertical screws
|
||||
let(pitch = 2 * insert_outer_d(screw_insert(screw)) + 2 * wall, offset = fixing_block_depth(screw) / 2)
|
||||
[for(end = [-1, 1]) translate([end * pitch / 2, offset]) * rotate([180, 0, 0])];
|
||||
|
||||
function fixing_block_holes(screw) = concat([fixing_block_h_hole(screw)], fixing_block_v_holes(screw)); //! Returns a list of transforms to position all the screws
|
||||
|
||||
module fixing_block_h_hole(screw = def_screw) //! Position children on the horizontal hole
|
||||
multmatrix(fixing_block_h_hole(screw))
|
||||
children();
|
||||
|
||||
module fixing_block_v_holes(screw = def_screw) //! Position children on the vertical holes
|
||||
for(p = fixing_block_v_holes(screw))
|
||||
multmatrix(p)
|
||||
children();
|
||||
|
||||
module fixing_block_holes(screw = def_screw) //! Position children on all the holes
|
||||
for(p = fixing_block_holes(screw))
|
||||
multmatrix(p)
|
||||
children();
|
||||
|
||||
module fixing_block_h_hole_2D(screw = def_screw) //! Position 2D child on the horizontal hole
|
||||
translate([0, fixing_block_depth(screw) / 2])
|
||||
children();
|
||||
|
||||
module fixing_block(screw = def_screw) { //! Generate the STL
|
||||
stl(str("fixing_block_M", screw_radius(screw) * 20));
|
||||
r = 1;
|
||||
insert = screw_insert(screw);
|
||||
corner_rad = insert_outer_d(insert) / 2 + wall;
|
||||
fb_width = fixing_block_width(screw);
|
||||
fb_height = fixing_block_height(screw);
|
||||
fb_depth = fixing_block_depth(screw);
|
||||
|
||||
difference() {
|
||||
union() {
|
||||
linear_extrude(height = fb_height, convexity = 5)
|
||||
difference() {
|
||||
hull() {
|
||||
for(side = [-1, 1]) {
|
||||
translate([side * (fb_width / 2 - corner_rad), fb_depth - corner_rad])
|
||||
circle4n(corner_rad);
|
||||
|
||||
translate([side * (fb_width / 2 - r), r])
|
||||
circle4n(r);
|
||||
}
|
||||
}
|
||||
fixing_block_v_holes(screw)
|
||||
poly_circle(screw_clearance_radius(screw));
|
||||
}
|
||||
}
|
||||
translate_z(fb_height)
|
||||
fixing_block_v_holes(screw)
|
||||
insert_hole(insert);
|
||||
|
||||
fixing_block_h_hole(screw)
|
||||
insert_hole(insert, 10, true);
|
||||
}
|
||||
}
|
||||
|
||||
module fixing_block_assembly(screw = def_screw) pose([55, 180, 25], [0, 4.8, 4.8]) //! Printed part with the inserts inserted
|
||||
assembly(str("fixing_block_M", 20 * screw_radius(screw))) {
|
||||
translate_z(fixing_block_height(screw))
|
||||
rotate([0, 180, 0])
|
||||
color(pp1_colour) render() fixing_block(screw);
|
||||
|
||||
insert = screw_insert(screw);
|
||||
|
||||
fixing_block_v_holes(screw)
|
||||
insert(insert);
|
||||
|
||||
fixing_block_h_hole(screw)
|
||||
insert(insert);
|
||||
}
|
||||
|
||||
module fastened_fixing_block_assembly(thickness, screw = def_screw, screw2 = undef, thickness2 = undef) { //! Assembly with fasteners in place
|
||||
module fb_screw(screw, thickness) {
|
||||
washer = screw_washer(screw);
|
||||
insert = screw_insert(screw);
|
||||
screw_length = screw_longer_than(2 * washer_thickness(washer) + thickness + insert_length(insert));
|
||||
|
||||
translate_z(thickness)
|
||||
screw_and_washer(screw, screw_length, true);
|
||||
}
|
||||
|
||||
no_pose() fixing_block_assembly(screw);
|
||||
|
||||
fixing_block_v_holes(screw)
|
||||
fb_screw(screw, thickness2 ? thickness2 : thickness);
|
||||
|
||||
fixing_block_h_hole(screw)
|
||||
fb_screw(screw2 ? screw2 : screw, thickness);
|
||||
}
|
||||
|
||||
module fixing_block_M20_stl() fixing_block(M2_cap_screw);
|
||||
module fixing_block_M25_stl() fixing_block(M2p5_cap_screw);
|
||||
module fixing_block_M30_stl() fixing_block(M3_cap_screw);
|
||||
module fixing_block_M40_stl() fixing_block(M4_cap_screw);
|
||||
|
||||
//
|
||||
//! 1. Lay the blocks out with the two larger holes facing upwards.
|
||||
//! 1. Place two M2 inserts into the two vertical holes of each block and push them home with a soldering iron with a conical bit heated to 200°C.
|
||||
//! When removing the iron it helps to twist it a little anti-clockwise to release it from the thread.
|
||||
//! 1. Lay the blocks on their backs and insert a third insert the same way.
|
||||
//
|
||||
module fixing_block_M20_assembly() fixing_block_assembly(M2_cap_screw);
|
||||
//
|
||||
//! 1. Lay the blocks out with the two larger holes facing upwards.
|
||||
//! 1. Place two M2.5 inserts into the two vertical holes of each block and push them home with a soldering iron with a conical bit heated to 200°C.
|
||||
//! When removing the iron it helps to twist it a little anti-clockwise to release it from the thread.
|
||||
//! 1. Lay the blocks on their backs and insert a third insert the same way.
|
||||
//
|
||||
module fixing_block_M25_assembly() fixing_block_assembly(M2p5_cap_screw);
|
||||
//
|
||||
//! 1. Lay the blocks out with the two larger holes facing upwards.
|
||||
//! 1. Place two M3 inserts into the two vertical holes of each block and push them home with a soldering iron with a conical bit heated to 200°C.
|
||||
//! When removing the iron it helps to twist it a little anti-clockwise to release it from the thread.
|
||||
//! 1. Lay the blocks on their backs and insert a third insert the same way.
|
||||
//
|
||||
module fixing_block_M30_assembly() fixing_block_assembly(M3_cap_screw);
|
||||
//
|
||||
//! 1. Lay the blocks out with the two larger holes facing upwards.
|
||||
//! 1. Place two M4 inserts into the two vertical holes of each block and push them home with a soldering iron with a conical bit heated to 200°C.
|
||||
//! When removing the iron it helps to twist it a little anti-clockwise to release it from the thread.
|
||||
//! 1. Lay the blocks on their backs and insert a third insert the same way.
|
||||
//
|
||||
module fixing_block_M40_assembly() fixing_block_assembly(M4_cap_screw);
|
151
printed/foot.scad
Normal file
151
printed/foot.scad
Normal file
@@ -0,0 +1,151 @@
|
||||
//
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
//
|
||||
//! Customisable printed rubber feet for equipment cases. The insert variant is better for solid feet because
|
||||
//! inserts don't grip well in rubber.
|
||||
//
|
||||
include <../core.scad>
|
||||
include <../vitamins/screws.scad>
|
||||
include <../vitamins/inserts.scad>
|
||||
|
||||
foot = [25, 12, 3, 2, M4_cap_screw, 10];
|
||||
insert_foot = [20, 10, 0, 2, M3_cap_screw, 10];
|
||||
|
||||
function foot() = foot; //! Default foot used unless a list of parameters is passed
|
||||
function insert_foot() = insert_foot; //! Default foot with insert
|
||||
|
||||
function foot_diameter(type = foot) = type[0]; //! Outside maximum diameter
|
||||
function foot_height(type = foot) = type[1]; //! Total height
|
||||
function foot_thickness(type = foot)= type[2]; //! Thickness under the screw
|
||||
function foot_rad(type = foot) = type[3]; //! Rounded corner radius
|
||||
function foot_screw(type = foot) = type[4]; //! Screw type
|
||||
function foot_slant(type = foot) = type[5]; //! Taper angle
|
||||
|
||||
module foot(type = foot) { //! Generate STL
|
||||
stl("foot");
|
||||
h = foot_height(type);
|
||||
t = foot_thickness(type);
|
||||
r1 = washer_radius(screw_washer(foot_screw(type)));
|
||||
r3 = foot_diameter(type) / 2;
|
||||
r2 = r3 - h * tan(foot_slant(type));
|
||||
r = foot_rad(type);
|
||||
|
||||
union() {
|
||||
rotate_extrude(convexity = 3) {
|
||||
hull() {
|
||||
translate([r1, 0])
|
||||
square([r3 - r1, eps]);
|
||||
|
||||
for(x = [r1 + r, r2 - r])
|
||||
translate([x, h - r])
|
||||
circle4n(r);
|
||||
}
|
||||
}
|
||||
linear_extrude(height = t)
|
||||
difference() {
|
||||
circle(r1 + eps);
|
||||
|
||||
poly_circle( screw_clearance_radius(foot_screw(type)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module foot_assembly(t = 0, type = foot) { //! Assembly with fasteners in place for specified sheet thickness
|
||||
screw = foot_screw(type);
|
||||
washer = screw_washer(screw);
|
||||
nut = screw_nut(screw);
|
||||
squeeze = 0.5;
|
||||
screw_length = screw_longer_than(foot_thickness(type) + t + 2 * washer_thickness(washer) + nut_thickness(nut, true) - squeeze);
|
||||
|
||||
vflip() explode(15, true) {
|
||||
color(pp4_colour) foot(type);
|
||||
|
||||
if(t)
|
||||
explode(15, true)
|
||||
translate_z(foot_thickness(type))
|
||||
screw_and_washer(screw, screw_length);
|
||||
}
|
||||
if(t)
|
||||
translate_z(t)
|
||||
nut_and_washer(nut, true);
|
||||
}
|
||||
|
||||
module insert_foot(type = insert_foot) { //! Generate STL for foot with insert
|
||||
stl("insert_foot");
|
||||
h = foot_height(type);
|
||||
r3 = foot_diameter(type) / 2;
|
||||
r2 = r3 - h * tan(foot_slant(type));
|
||||
r = foot_rad(type);
|
||||
|
||||
insert = screw_insert(foot_screw(type));
|
||||
h2 = insert_hole_length(insert);
|
||||
r4 = insert_hole_radius(insert);
|
||||
r5 = r4 + 1;
|
||||
union() {
|
||||
rotate_extrude() {
|
||||
union() {
|
||||
hull() {
|
||||
translate([r5, 0]) {
|
||||
square([r3 - r5, eps]);
|
||||
square([eps, h]);
|
||||
}
|
||||
|
||||
translate([r2 - r, h - r])
|
||||
circle4n(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
linear_extrude(height = h2 + eps)
|
||||
difference() {
|
||||
circle(r5 + eps);
|
||||
|
||||
poly_circle(r4);
|
||||
}
|
||||
|
||||
translate_z(h2)
|
||||
cylinder(r = r5 + eps, h = h - h2);
|
||||
}
|
||||
}
|
||||
//
|
||||
//! Place the insert in the bottom of the foot and push home with a soldering iron with a conical bit heated to 200°C.
|
||||
//
|
||||
module insert_foot_assembly(type = insert_foot) //! Printed part with insert in place
|
||||
assembly("insert_foot") {
|
||||
screw = foot_screw(type);
|
||||
insert = screw_insert(screw);
|
||||
|
||||
vflip()
|
||||
color(pp1_colour) insert_foot(type);
|
||||
|
||||
translate_z(-foot_thickness(type))
|
||||
insert(insert);
|
||||
}
|
||||
|
||||
module fastened_insert_foot_assembly(t = 3, type = insert_foot) { //! Assembly with fasteners in place for specified sheet thickness
|
||||
screw = foot_screw(type);
|
||||
washer = screw_washer(screw);
|
||||
insert = screw_insert(screw);
|
||||
screw_length = screw_shorter_than(insert_length(insert) + t + 2 * washer_thickness(washer));
|
||||
|
||||
explode(-10) insert_foot_assembly(type);
|
||||
|
||||
translate_z(t)
|
||||
screw_and_washer(screw, screw_length, true);
|
||||
}
|
103
printed/handle.scad
Normal file
103
printed/handle.scad
Normal file
@@ -0,0 +1,103 @@
|
||||
//
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
//
|
||||
//! Printed handle that can be printed without needing support material due to its truncated teardrop profile.
|
||||
//
|
||||
include <../core.scad>
|
||||
include <../vitamins/screws.scad>
|
||||
include <../vitamins/inserts.scad>
|
||||
|
||||
dia = 18;
|
||||
length = 90; // inside length
|
||||
height = 30; // inside height
|
||||
screw = M4_cap_screw;
|
||||
insert = screw_insert(screw);
|
||||
|
||||
pitch = length + dia;
|
||||
|
||||
function handle_length() = pitch + dia; //! Outside length
|
||||
function handle_width() = dia; //! The width, i.e. diameter
|
||||
function handle_height() = height + dia; //! Total height
|
||||
function handle_screw() = screw; //! The screw type
|
||||
|
||||
module handle_screw_positions() //! Position children at the screw positions
|
||||
for(end = [-1, 1])
|
||||
translate([end * pitch / 2, 0])
|
||||
children();
|
||||
|
||||
module handle_holes(h = 100) //! Drills holes for the screws
|
||||
handle_screw_positions()
|
||||
drill(screw_clearance_radius(screw), h);
|
||||
|
||||
module handle_stl() { //! generate the STL
|
||||
stl("handle");
|
||||
|
||||
module end(end)
|
||||
translate([end * pitch / 2, 0])
|
||||
rotate_extrude()
|
||||
intersection() {
|
||||
rotate(180)
|
||||
teardrop(r = dia / 2, h = 0);
|
||||
|
||||
translate([0, - (dia + 1) / 2])
|
||||
square([dia / 2 + 1, dia + 1]);
|
||||
}
|
||||
|
||||
translate_z(dia / 2)
|
||||
union() {
|
||||
hull() {
|
||||
end(-1);
|
||||
|
||||
end(1);
|
||||
}
|
||||
|
||||
handle_screw_positions()
|
||||
render() difference() {
|
||||
h = height + dia / 2;
|
||||
cylinder(d = dia, h = h);
|
||||
|
||||
translate_z(h)
|
||||
insert_hole(insert, 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
//! Place inserts in the bottom of the posts and push them home with a soldering iron with a conical bit heated to 200°C.
|
||||
//
|
||||
module handle_assembly() pose([225, 0, 150], [0, 0, 14]) //! Printed part with inserts in place
|
||||
assembly("handle") {
|
||||
translate_z(handle_height())
|
||||
color(pp1_colour) vflip() handle_stl();
|
||||
|
||||
handle_screw_positions()
|
||||
vflip()
|
||||
insert(insert);
|
||||
}
|
||||
|
||||
module handle_fastened_assembly(thickness) { //! Assembly with fasteners in place
|
||||
screw_length = screw_longer_than(thickness + insert_length(insert) + 2 * washer_thickness(screw_washer(screw)));
|
||||
|
||||
handle_assembly();
|
||||
|
||||
handle_screw_positions()
|
||||
vflip()
|
||||
translate_z(thickness)
|
||||
screw_and_washer(screw, screw_length, true);
|
||||
}
|
119
printed/ribbon_clamp.scad
Normal file
119
printed/ribbon_clamp.scad
Normal file
@@ -0,0 +1,119 @@
|
||||
//
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
//
|
||||
//! Clamp for ribbon cable and polypropylene strip.
|
||||
//
|
||||
include <../core.scad>
|
||||
include <../vitamins/screws.scad>
|
||||
include <../vitamins/inserts.scad>
|
||||
use <../vitamins/cable_strip.scad>
|
||||
|
||||
wall = 2;
|
||||
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) + 2); //! 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
|
||||
|
||||
module ribbon_clamp_hole_positions(ways, side = undef) //! Place children at hole positions
|
||||
for(x = is_undef(side) ? [-1, 1] : side)
|
||||
translate([x * ribbon_clamp_hole_pitch(ways) / 2, 0])
|
||||
children();
|
||||
|
||||
module ribbon_clamp_holes(ways, h = 20) //! Drill screw holes
|
||||
ribbon_clamp_hole_positions(ways)
|
||||
drill(screw_clearance_radius(screw), h);
|
||||
|
||||
module ribbon_clamp(ways) { //! Generate STL for given number of ways
|
||||
stl(str("ribbon_clamp_", ways));
|
||||
|
||||
pitch = ribbon_clamp_hole_pitch(ways);
|
||||
d = ribbon_clamp_width();
|
||||
h = ribbon_clamp_height();
|
||||
t = h - ribbon_clamp_slot_depth() - wall;
|
||||
|
||||
difference() {
|
||||
union() {
|
||||
hull() {
|
||||
translate_z(h - t / 2)
|
||||
cube([ribbon_clamp_hole_pitch(ways), d, t], center = true);
|
||||
|
||||
translate_z(1)
|
||||
cube([pitch, max(wall, d - 2 * (h - t)), 2], center = true);
|
||||
}
|
||||
ribbon_clamp_hole_positions(ways, -1)
|
||||
cylinder(d = d, h = h);
|
||||
|
||||
ribbon_clamp_hole_positions(ways, 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)
|
||||
translate_z(h)
|
||||
rotate(22.5)
|
||||
insert_hole(insert, screw_depth - 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();
|
||||
|
||||
color(pp1_colour) render()
|
||||
translate_z(h) vflip() ribbon_clamp(ways);
|
||||
|
||||
ribbon_clamp_hole_positions(ways)
|
||||
vflip()
|
||||
insert(insert);
|
||||
}
|
||||
|
||||
module ribbon_clamp_fastened_assembly(ways, thickness, screw = screw) { //! Clamp with fasteners in place
|
||||
tape_l = floor(ribbon_clamp_slot(ways));
|
||||
tape_width = 25;
|
||||
tape_thickness = 0.5;
|
||||
|
||||
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);
|
||||
|
||||
ribbon_clamp_assembly(ways);
|
||||
|
||||
color("red") translate_z(tape_thickness / 2)
|
||||
cube([tape_l, tape_width, tape_thickness], center = true);
|
||||
|
||||
ribbon_clamp_hole_positions(ways)
|
||||
vflip()
|
||||
translate_z(thickness)
|
||||
screw_and_washer(screw, screw_length, true);
|
||||
}
|
||||
|
||||
module ribbon_clamp_20_stl() ribbon_clamp(20);
|
||||
|
||||
//! * 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);
|
77
printed/screw_knob.scad
Normal file
77
printed/screw_knob.scad
Normal file
@@ -0,0 +1,77 @@
|
||||
//
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
//
|
||||
//! Knob with embedded hex head screw.
|
||||
//
|
||||
include <../core.scad>
|
||||
include <../vitamins/screws.scad>
|
||||
use <../utils/hanging_hole.scad>
|
||||
|
||||
knob_wall = 2;
|
||||
function knob_nut_trap_depth(screw) = round_to_layer(screw_head_height(screw));
|
||||
knob_stem_h = 6;
|
||||
knob_thickness = 4;
|
||||
knob_r = 8;
|
||||
knob_wave = 1;
|
||||
knob_waves = 9;
|
||||
knob_height = knob_stem_h + knob_thickness;
|
||||
function knob_height() = knob_height;
|
||||
|
||||
module screw_knob(screw) { //! Generate the STL foe a knob to fit the specified hex screw
|
||||
stl(str("screw_knob_M", screw_radius(screw) * 20));
|
||||
|
||||
knob_stem_r = nut_trap_radius(screw_nut(screw)) + knob_wall;
|
||||
|
||||
function wave(a) = knob_r + sin(a * knob_waves) * knob_wave;
|
||||
|
||||
union() {
|
||||
render() difference() {
|
||||
cylinder(r = knob_stem_r, h = knob_thickness + knob_stem_h);
|
||||
|
||||
hanging_hole(knob_nut_trap_depth(screw), screw_clearance_radius(screw))
|
||||
rotate(45)
|
||||
circle(r = nut_trap_radius(screw_nut(screw)), $fn = 6);
|
||||
}
|
||||
linear_extrude(height = knob_thickness, convexity = 3)
|
||||
difference() {
|
||||
polygon(points = [for(a = [0 : 359]) [wave(a) * sin(a), wave(a) * cos(a)]]);
|
||||
|
||||
circle(knob_stem_r - eps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Place the screw through the printed part
|
||||
module screw_knob_assembly(screw, length) //! Assembly with the screw in place
|
||||
assembly(str("screw_knob_M", 20 * screw_radius(screw), "_", length)) {
|
||||
translate_z(knob_height)
|
||||
vflip()
|
||||
color(pp1_colour) screw_knob(screw);
|
||||
|
||||
translate_z(knob_height - knob_nut_trap_depth(screw))
|
||||
rotate(-45)
|
||||
screw(screw, length);
|
||||
}
|
||||
|
||||
module screw_knob_M30_stl() screw_knob(M3_hex_screw);
|
||||
module screw_knob_M40_stl() screw_knob(M4_hex_screw);
|
||||
|
||||
module screw_knob_M30_16_assembly() screw_knob_assembly(M3_hex_screw, 16);
|
||||
module screw_knob_M40_16_assembly() screw_knob_assembly(M4_hex_screw, 16);
|
127
printed/socket_box.scad
Normal file
127
printed/socket_box.scad
Normal file
@@ -0,0 +1,127 @@
|
||||
//
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
//
|
||||
//! UK 13A socket and printed backbox with earth terminal for the panel it is mounted on.
|
||||
//
|
||||
include <../core.scad>
|
||||
include <../vitamins/mains_sockets.scad>
|
||||
include <../vitamins/screws.scad>
|
||||
include <../vitamins/inserts.scad>
|
||||
include <../vitamins/ring_terminals.scad>
|
||||
|
||||
box_height = 19;
|
||||
base_thickness = 2;
|
||||
wall = 3.5;
|
||||
|
||||
cable_d = 7;
|
||||
cable_z = cable_d / 2 + base_thickness + 1;
|
||||
function cable_y(type) = -mains_socket_depth(type) / 2;
|
||||
cable_x = 0;
|
||||
|
||||
earth = M3_ringterm;
|
||||
earth_screw = ringterm_screw(earth);
|
||||
|
||||
height = base_thickness + box_height;
|
||||
function socket_box_depth() = height; //! Outside depth of the backbox
|
||||
|
||||
module socket_box(type) { //! Generate STL of the backbox for the specified socket
|
||||
stl(str("socket_box_",type[0]));
|
||||
|
||||
screw = mains_socket_screw(type);
|
||||
screw_clearance_radius = screw_clearance_radius(screw);
|
||||
|
||||
insert = screw_insert(screw);
|
||||
insert_length = insert_length(insert);
|
||||
insert_boss = mains_socket_insert_boss(type);
|
||||
insert_hole_radius = insert_hole_radius(insert);
|
||||
|
||||
difference() {
|
||||
linear_extrude(height = height, convexity = 5)
|
||||
face_plate(type);
|
||||
|
||||
difference() {
|
||||
translate_z(base_thickness)
|
||||
linear_extrude(height = height, convexity = 5)
|
||||
offset(-wall) offset(1) face_plate(type);
|
||||
|
||||
for(side = [-1, 1])
|
||||
hull()
|
||||
for(x = [1, 2])
|
||||
translate([side * mains_socket_pitch(type) / x, 0])
|
||||
cylinder(d = insert_boss, h = 100);
|
||||
}
|
||||
//
|
||||
// Socket holes
|
||||
//
|
||||
translate_z(height)
|
||||
mains_socket_hole_positions(type) {
|
||||
poly_cylinder(r = screw_clearance_radius, h = 2 * box_height, center = true);
|
||||
|
||||
poly_cylinder(r = insert_hole_radius, h = 2 * insert_length, center = true);
|
||||
}
|
||||
//
|
||||
// Cable hole
|
||||
//
|
||||
translate([cable_x, cable_y(type), cable_z])
|
||||
rotate([90, 0, 0])
|
||||
teardrop_plus(r = cable_d / 2, h = 30);
|
||||
}
|
||||
}
|
||||
|
||||
module socket_box_MKLOGIC_stl() socket_box(MKLOGIC);
|
||||
module socket_box_Contactum_stl() socket_box(Contactum);
|
||||
|
||||
module socket_box_assembly(type) //! The box with inserts fitted
|
||||
assembly(str("socket_box_", type[0])) {
|
||||
screw = mains_socket_screw(type);
|
||||
insert = screw_insert(screw);
|
||||
|
||||
color("lime") render() socket_box(type);
|
||||
|
||||
mains_socket_hole_positions(type)
|
||||
translate_z(height)
|
||||
insert(insert);
|
||||
|
||||
}
|
||||
|
||||
//! * Place two inserts into the holes in the lugs and press them home with a soldering iron with a tapered bit heated to 200°C.
|
||||
module socket_box_MKLOGIC_assembly() socket_box_assembly(MKLOGIC);
|
||||
|
||||
module socket_box_fastened_assembly(type, thickness) { //! The socket and backbox on each side of the specified panel thickness
|
||||
screw = mains_socket_screw(type);
|
||||
insert = screw_insert(screw);
|
||||
screw_length = screw_longer_than(mains_socket_height(type) + thickness + insert_length(insert));
|
||||
|
||||
explode(-50)
|
||||
translate_z(-height - thickness)
|
||||
socket_box_assembly(type);
|
||||
|
||||
explode(50, true) {
|
||||
mains_socket(type);
|
||||
|
||||
mains_socket_hole_positions(type)
|
||||
translate_z(mains_socket_height(type))
|
||||
screw(screw, screw_length);
|
||||
}
|
||||
|
||||
mains_socket_earth_position(type)
|
||||
rotate(-90)
|
||||
ring_terminal_assembly(earth, thickness);
|
||||
}
|
189
printed/strap_handle.scad
Normal file
189
printed/strap_handle.scad
Normal file
@@ -0,0 +1,189 @@
|
||||
//
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
//
|
||||
//! Retracting strap handle. Print the strap with flexible filament. Shown with default dimensions but can
|
||||
//! be fully customised by passing a list of properties.
|
||||
//
|
||||
include <../core.scad>
|
||||
include <../vitamins/screws.scad>
|
||||
include <../vitamins/inserts.scad>
|
||||
|
||||
strap = [18, 2, M3_pan_screw, 3, 25];
|
||||
function strap() = strap;
|
||||
|
||||
wall = 2;
|
||||
clearance = 0.5;
|
||||
step = 0.3;
|
||||
overlap = 3;
|
||||
panel_clearance = 0.25;
|
||||
counterbore = 1;
|
||||
|
||||
function strap_width(type = strap) = type[0]; //! Width of strap
|
||||
function strap_thickness(type = strap) = type[1]; //! Thickness of strap
|
||||
function strap_screw(type = strap) = type[2]; //! Screw type
|
||||
function strap_panel(type = strap) = type[3]; //! Panel thickness
|
||||
function strap_extension(type = strap) = type[4]; //! How much length of the strap that can pull out
|
||||
|
||||
function strap_insert(type) = screw_insert(strap_screw(type)); //! The insert type
|
||||
function strap_key(type) = strap_panel(type) - panel_clearance;
|
||||
function strap_height(type) = wall + max(insert_length(strap_insert(type)) - strap_key(type), strap_thickness(type) + clearance); //! Height of the ends
|
||||
function strap_end_width(type = strap) = strap_width(type) + 2 * (wall + clearance); //! Width of the ends
|
||||
function strap_boss_r(type) = wall + insert_hole_radius(strap_insert(type));
|
||||
|
||||
function strap_min_width(type) = (strap_width(type) - 2 * (strap_boss_r(type) + clearance)) / 2;
|
||||
|
||||
module strap_boss_shape(type)
|
||||
hull() {
|
||||
r = strap_boss_r(type);
|
||||
|
||||
circle4n(r);
|
||||
|
||||
translate([r / 2, 0])
|
||||
rounded_square([r, 2 * r], r = 1);
|
||||
}
|
||||
|
||||
module strap_screw_positions(length, type = strap) //! Place children at the screw positions
|
||||
for(end = [-1, 1])
|
||||
translate([end * (length / 2 - wall - 2 * clearance - strap_min_width(type) - strap_boss_r(type) - strap_extension(type) / 2), 0])
|
||||
rotate(end * 90 + 90)
|
||||
children();
|
||||
|
||||
module strap_holes(length, type = strap, h = 100) //! The panel cut outs
|
||||
extrude_if(h)
|
||||
strap_screw_positions(length, type)
|
||||
offset(cnc_bit_r + 0.05)
|
||||
offset(-step - cnc_bit_r)
|
||||
strap_boss_shape(type);
|
||||
|
||||
module strap(length, type = strap) { //! Generate the STL for the rubber strap
|
||||
stl("strap");
|
||||
|
||||
len = length - 2 * (wall + clearance);
|
||||
w = strap_width(type);
|
||||
|
||||
linear_extrude(height = strap_thickness(type), convexity = 3)
|
||||
difference() {
|
||||
rounded_square([len, w], w / 2 - eps);
|
||||
|
||||
for(end = [-1, 1])
|
||||
translate([end * (len / 2 - strap_min_width(type) - strap_boss_r(type) - clearance), 0])
|
||||
rotate(end * 90 + 90)
|
||||
hull() {
|
||||
offset(clearance)
|
||||
strap_boss_shape(type);
|
||||
|
||||
translate([strap_extension(type) / 2, 0])
|
||||
offset(clearance)
|
||||
strap_boss_shape(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module strap_end(type = strap) { //! Generate the STL for end piece
|
||||
stl("strap_end");
|
||||
|
||||
z1 = strap_height(type) - strap_thickness(type) - clearance;
|
||||
z2 = strap_height(type) + strap_key(type);
|
||||
r1 = strap_boss_r(type) - 1;
|
||||
|
||||
module outer()
|
||||
hull() {
|
||||
translate([0, -strap_end_width(type) / 2])
|
||||
square([strap_boss_r(type) + overlap, strap_end_width(type)]);
|
||||
|
||||
translate([-strap_extension(type) / 2, 0])
|
||||
circle(d = strap_end_width(type));
|
||||
}
|
||||
|
||||
module with_hole()
|
||||
difference() {
|
||||
children();
|
||||
|
||||
circle(r1);
|
||||
}
|
||||
|
||||
union() {
|
||||
linear_extrude(height = z1)
|
||||
with_hole()
|
||||
outer();
|
||||
|
||||
translate_z(z1)
|
||||
linear_extrude(height = strap_height(type) - z1)
|
||||
difference() {
|
||||
outer();
|
||||
|
||||
hull() {
|
||||
translate([0, -strap_width(type) / 2 - clearance])
|
||||
square([strap_boss_r(type) + overlap, strap_width(type) + 2 * clearance]);
|
||||
|
||||
translate([-strap_extension(type) / 2, 0])
|
||||
circle(d = strap_width(type) + 2 * clearance);
|
||||
}
|
||||
}
|
||||
|
||||
linear_extrude(height = strap_height(type) - layer_height)
|
||||
with_hole()
|
||||
strap_boss_shape(type);
|
||||
|
||||
linear_extrude(height = z2)
|
||||
with_hole()
|
||||
offset(cnc_bit_r)
|
||||
offset(-step - cnc_bit_r)
|
||||
strap_boss_shape(type);
|
||||
|
||||
render() difference() {
|
||||
cylinder(r = r1 + eps, h = z2);
|
||||
|
||||
translate_z(z2)
|
||||
insert_hole(strap_insert(type), counterbore);
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
//! * Place the insert into the hole and push home with a soldering iron with a tapered bit heated to 200°C.
|
||||
//
|
||||
module strap_end_assembly(type = strap)
|
||||
assembly("strap_end") {
|
||||
color(pp1_colour)
|
||||
strap_end(type);
|
||||
|
||||
translate_z(strap_height(type) + strap_key(type))
|
||||
insert(strap_insert(type));
|
||||
}
|
||||
|
||||
module strap_assembly(length, type = strap) { //! Assembly with screws in place
|
||||
screw = strap_screw(type);
|
||||
washer = screw_washer(screw);
|
||||
penny = penny_washer(washer);
|
||||
insert = strap_insert(type);
|
||||
|
||||
screw_length = screw_shorter_than(washer_thickness(washer) + washer_thickness(penny) + insert_length(insert) + panel_clearance + counterbore);
|
||||
|
||||
color(pp4_colour) strap(length, type);
|
||||
|
||||
strap_screw_positions(length, type)
|
||||
translate_z(strap_height(type))
|
||||
vflip() {
|
||||
explode(-50) strap_end_assembly(type);
|
||||
|
||||
translate_z(strap_height(type) + strap_panel(type))
|
||||
screw_and_washer(screw, screw_length, true, true);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user