Files
spoolmount/unfuck-the-mmu/upstream/configurable-spool-holder-v3.1.scad
T

331 lines
15 KiB
OpenSCAD

/*
This OpenSCAD script can produce a spool holder with different spindle lengths, a spindle extension piece, and a bracket that has two different spindle mounting points.
Before printing the full set, use the 'test_pieces' module to generate a couple of parts that check the fitment of the male and female threads, and the size of the recessed nut slot.
Use the spindle_thread_tol parameter to alter the tightness of the threaded sections - a bigger value will make the parts fit less tightly.
Use the hex_ap parameter to adjust the size of the recessed nut slot - it represents the 'across points' dimension of the hexagonal nut slot.
By default the script produces a bracket for the top-right-front corner of the enclosure, which is the regular spindle location. This bracket will also fit the bottom-left-front, the top-left-rear and bottom-right-rear
Use the if_mirror option to flip the geometry. When mirrored, the bracket will fit the top_left_front, bottom-right-front, bottom-left-rear and top-right-rear
(Note that simply mirroring the model in the slicer will not work, since the screw threads will be reversed)
CJH 26 April 2023
Updated 17 April 2024 with V3 bracket design abd mirrored geometry option
Updated 28 April 2023 with new 3rd mounting hole location and addition of spare spindle storage
Updated 8th April 2024 with the if_mirror option, the option to specify a reduced depth for the hexagon lattice and spindle reinforcing bosses, and an adjustment to the location of the spare spindle so that it can be screwed all the way in without foulong the enclosure screw.
*/
$fa = 1;// minimum angle for a fragment } smaller values will improve STL resolution
$fs = 0.3;// minimum size of a fragment } but will increase rendering time
// } Beware - 0.1 can take a very long time to render!
include<threads-scad-master/threads.scad>
//*************************** Parameter Definitions **************************************
layer_ht = 0.3;//used to create the 'bridge helper' support layers for the 'suspended' bolt hole above the nut hole. 0.3mm works for a 0.2mm layer height, but not vice versa
//bracket options
second_spindle = false;//include an additional 'high capacity' spindle location
spare_spindle = false;//include a threaded hole to store a spare spindle or extension
if_mirror = true;//flip the geometry, but retain normal screw threads
third_hole = false;//include a third screw hole along the top edge of the enclosure frame
depth = 18.5;//depth, or thickness, of the bracket
frame_width = 8;//8;// width of main frame around hexagon lattice
//Spindle definitions
spindle_diam = 24;//the outer diameter of the spindle
spindle_length = 75;//the (default) length of the spindle (and the extension). Can be overriden with the 'length=' parameter.
spindle_thread = spindle_diam-6;//the outside diameter of the threaded sections - allows a 3mm 'landing' face
spindle_thread_tol = 0.6;//the difference between the male and female thread diameters, to allow for printing inaccuracies
spindle_end_diam = spindle_diam+10;//defines the diameter of the conical end of the spindle
x_offset = -50; //difference between the 'default' spindle location [0,0]
y_offset = -20; //and the 'high capacity' spindle location
hole_spindle = [x_offset,y_offset]; //
extra_spare_offset = 11.5;//11.5 places the spare spindle between the enclosure frame screws, so that it can be screwed fully in
hole_spare = [58.2+extra_spare_offset,81.65+extra_spare_offset]; //
//Screw hole definitions
hole1 = [43.95,95.9,0];// coordinates of the three screw/nut holes
hole2 = [72.45,67.4,0];// relative to main spindle origin
hole3 = [43.95-60,95.9,0]; //version 2 location of third mounting hole
//hole3 = [72.45,7.4,0]; //version 1 location of third mounting hole
hex_ap=6.3;//'across points' dimension of hex nut slot, allowing for printing inaccuracies.
//6.3 works for M3 nuts with Prusament PETG on my Prusa MK4, and gives tight push-fit. YMMV. Use the test pieces to check
//Any over-extrusion will make the nut holes smaller and may make the nuts difficult to insert.
//parameters to define the pattern of hexagons in the main bracket
hex_rad = 20;//15;//the radius of a circle that encloses the hexagon
hex_sepn = 3;//4;//the width of the dividing lines between adjacent hexagons
hex_cols = 5;//the number of columns and rows of hexagons to fill the bracket space
hex_rows = 6;//increase or decrease so that there are enough hexagons with the specified dimensions to cover the bracket
hex_depth = 12;//depth/2;// depth of hexagon lattice. Also defines the depth of the spindle reinforcing bosses
mirror = if_mirror ? [1,0,0]:[0,0,0];//create mirror vector depending on 'if_mirror' option
//*************************** Create the STLs **************************************
// prints the complete set of bracket, four spindles and two extension pieces
full_set(if_bracket=true,if_ext=false,if_ext50=false,if_75=false,if_90=false,if_125=false,if_165=false);
//print a couple of test pieces to check screw threads and nut slot dimensions for a given filament/printer setting
//test_pieces();
//generate modifiers for use in PrusaSlicer in case different settings are required for the thread sections
//modifiers();
//make a piece to test the spare spindle location
//spare_test();
//*************************** Component modules **************************************
module full_set(if_bracket=false,if_ext=false,if_50=false,if_75=false,if_90=false,if_125=false,if_165=false){// makes the complete set of bracket, 75mm, 90mm and 165mm spindles, and 75mm extension
if(if_bracket) bracket();
if(if_ext) translate([70,20,0]) spindle_ext();
if(if_ext50) translate([75,-15,0]) spindle_ext(length=50);
if(if_75) translate([60,70,0]) spindle();
if(if_90) translate([45,120,0]) spindle(length=90);
if(if_125) translate([-14,130,0]) spindle(length=125);
if(if_165) translate([-60,130,0]) spindle(length=165);
}
module test_pieces(){//makes a couple of test pieces to test the fit between the male and femaile threads, and the dimensions of a deep nut slot
translate([40,0,0])
difference(){
cylinder(d=spindle_diam,h=25);
female_thread();
}
difference(){
translate([0,0,0]) spindle(length=25);
translate([0,0,depth]) rotate([180,0,0]) deep_nut_slot();
}
}
module bracket(){// makes the main mounting bracket
mirror(mirror)
translate([0,0,depth]) rotate([180,0,180]) {
difference(){
raw_bracket();
translate(hole1) rotate([0,0,-15]) deep_nut_slot();
translate(hole2) rotate([0,0,-15]) deep_nut_slot();
if (third_hole) translate(hole3) deep_nut_slot();
mirror(mirror) female_thread();//spindle hole at [0,0]
if(second_spindle) translate(hole_spindle) mirror(mirror) female_thread();//spindle hole for larger diameter spools
if(spare_spindle) translate(hole_spare) mirror(mirror) female_thread();//spindle hole for spare storage
}
}
}
module spindle(length=spindle_length){//makes a spindle with a specified length. Defaults to 'spindle_length'
cylinder(h=2,d=spindle_end_diam);
translate([0,0,2]) cylinder(h=4,d1=spindle_end_diam,d2=spindle_diam);
translate([0,0,6]) cylinder(d=spindle_diam,h=length);
translate([0,0,length+6]) male_thread();
}
module spindle_ext(length=spindle_length){//makes a spindle extension with a specified length. Defaults to 'spindle_length'
difference(){
cylinder(d=spindle_diam,h=length);
female_thread();
}
translate([0,0,length]) male_thread();
}
module raw_bracket(){//makes the basic bracket before adding the nut slots and spindle screw threads
//hexagon lattice
translate([0,0,depth-hex_depth])
difference(){
// linear_extrude(depth) outline();
linear_extrude(hex_depth) offset(r=-0.1) outline();
translate([45,40,0]) rotate([90,0,0]) hexagons(r=hex_rad,s=hex_sepn,n_cols=hex_cols,n_rows=hex_rows);
}
//outer frame
difference(){
linear_extrude(depth) outline();
// linear_extrude(depth) offset(r=-8) outline();
linear_extrude(depth) offset(r=-frame_width) outline();
}
//screw hole 1
intersection(){
linear_extrude(depth) outline();
translate(hole1) cylinder(d=18,h=depth);
}
//screw hole 2
intersection(){
linear_extrude(depth) outline();
translate(hole2) cylinder(d=18,h=depth);
}
//screw hole 3
if (third_hole){
intersection(){
linear_extrude(depth) outline();
translate(hole3) cylinder(d=18,h=depth);
}
}
//default spindle with boss
intersection(){
linear_extrude(depth) outline();
// cylinder(d=34.5,h=depth);
translate([0,0,depth-hex_depth]) cylinder(d=spindle_thread+2*frame_width,h=hex_depth);
}
intersection(){
linear_extrude(depth) outline();
// cylinder(d=34.5,h=depth);
translate([0,0,0]) cylinder(d=spindle_diam,h=depth);
}
//high capacity spindle with boss
if(second_spindle){
intersection(){
linear_extrude(depth) outline();
// translate(hole_spindle) cylinder(d=34.5,h=depth);
translate(hole_spindle) translate([0,0,depth-hex_depth]) cylinder(d=spindle_thread+2*frame_width,h=hex_depth);
}
intersection(){
linear_extrude(depth) outline();
// translate(hole_spindle) cylinder(d=34.5,h=depth);
translate(hole_spindle) cylinder(d=spindle_diam,h=depth);
}
}
//extra lip around mounting holes
// translate([0,0,-1.5])
translate([0,0,-0.75])
intersection(){
// translate([30.8,104.3,0])
translate([60,85.6,0])
// rotate([0,0,-45]) cube([75,15,1.5]);
rotate([0,0,-45]) cube([80,15,1.51],center=true);
linear_extrude(depth) outline();
}
//spare spindle storage hole
if (spare_spindle) {
overlap = 0.1;//to ensure spare overlaps the bracket everywhere, to avoid meshing errors
translate([0,0,4])
linear_extrude(depth-4)
hull(){
translate(hole_spare) circle(d=((64.38-54.2)^2+(77.65-87.82)^2)^0.5+2*frame_width+2*overlap);
translate([64.38,77.65,0]) circle(d=9.95+overlap);
translate([54.2,87.82,0]) circle(d=9.95+overlap);
}
}
}
module modifiers(){//makes modifiers for screw thread sections - may be useful for defining different print settings for screw threads
translate([0,0,depth]) rotate([180,0,180]) {
translate(hole_spindle) cylinder(d=spindle_diam,h=depth);
translate([0,0,0]) cylinder(d=spindle_diam,h=depth);
if(second_spindle) translate([0,0,4]) translate(hole_spare) cylinder(h=depth-4,d=spindle_diam);
}
}
module male_thread(length = depth, diam=spindle_thread,taper=true, trim=true){//makes the male threaded section for the spindle and the spindle extension
translate([0,0,length])
rotate([180,0,0])
difference(){
ScrewThread(outer_diam=diam, height=length, pitch=0, tooth_angle=30, tolerance=0.4, tip_height=0, tooth_height=0, tip_min_fract=0);
if(taper){
difference(){
translate([0,0,0]) cylinder(h=5,d1=diam*0.8+9,d2=diam+6);
translate([0,0,0]) cylinder(h=5,d1=diam*0.8,d2=diam);
}
}
if(trim){
difference(){
cylinder(d=spindle_thread+5,h=depth);
cylinder(d=spindle_thread-1,h=depth);
}
}
}
}
module female_thread(length=depth+1,diam=spindle_thread+spindle_thread_tol,taper=false){//makes the female threaded section for subtracting from the spindle extension and the main bracket
male_thread(length = length, diam=diam,taper=false, trim=false);
cylinder(d=diam-3,h=depth+1);
}
module outline(){//defines the outline of the bracket
difference(){
hull(){
translate(hole1) circle(d=18);
translate(hole2) circle(d=18);
if (third_hole) translate(hole3) circle(d=18);
// translate(hole_spindle) circle(d=33);
// circle(d=33);
if(second_spindle) translate(hole_spindle) circle(d=spindle_thread+2*frame_width);
circle(d=spindle_thread+2*frame_width);
// translate(hole_spare) circle(d=33);
}
hull(){
translate([64.38,77.65,0]) circle(d=9.95);
translate([54.2,87.82,0]) circle(d=9.95);
translate([64.38+10,77.65+10,0]) circle(d=9.95);
translate([54.2+10,87.82+10,0]) circle(d=9.95);
}
}
}
module deep_nut_slot(){//makes a nut slot for use in deep sections. Uses a wider slot above the main nut slot, as used by Prusa in the original spool holder
translate([0,0,10.4]) rotate([180,0,0]) basic_nut_slot(hex_diam = hex_ap,bolt_diam = 3.2,recess = 3.6,bolt_length = 10.4+1.6);
translate([0,0,10]) linear_extrude(2.1,scale=1.8) hex_nut(r=hex_ap/2,points=false);
translate([0,0,10+2.1]) linear_extrude(5.9) hex_nut(r=1.8*hex_ap/2,points=false);
translate([0,0,10+2.1+5.9]) linear_extrude(0.6,scale=1.2) hex_nut(r=1.8*hex_ap/2,points=false);
}
module basic_nut_slot(hex_diam,bolt_diam,recess,bolt_length){//makes a basic nut slot, with small circular holes at the vertices of the hexagonal nut
//hex_diam = diameter of circle enclosing the hexagon
//bolt_diam = diameter of threaded part of bolt
//recess = depth of nut recess
//bolt_length = total length of bolt hole, including nut recess
cylinder(d=bolt_diam,h=bolt_length);
linear_extrude(recess) hex_nut(r=hex_diam/2);
intersection(){
linear_extrude(recess+layer_ht) hex_nut(r=hex_diam/2);
translate([-hex_diam/2,-bolt_diam/2,0]) cube([hex_diam,bolt_diam,recess+layer_ht]);
}
translate([-bolt_diam/2,-bolt_diam/2,0]) cube([bolt_diam,bolt_diam,recess+2*layer_ht]);
}
module hexagons(r,s,n_cols,n_rows){//makes a panel of extruded hexagons
cols = round(n_cols/2)==n_cols/2 ? n_cols : n_cols+1;//make cols an even number
l = 2*r*cos(30)+s;
for(col = [-cols/2 : cols/2]){
for(row = [-n_rows/2 : n_rows/2]){
offset_y = round(col/2)==col/2 ? l/2 : 0;
translate([col*l*cos(30),0,row*l+offset_y]) hexagon(r);
}
}
}
module hexagon(r){//makes a single hexagon extruded to the depth of the bracket
rotate([0,30,0])
rotate([-90,0,0])
linear_extrude(depth)
hex_nut(r,points=false);
}
module hex_nut(r,points=true){//makes a 2D hexagon with a specified radius. The boolean 'points' parameter specifies whether ther should be small circles at the vertices of the hexagon.
x = r*cos(30);
y = r*sin(30);
hex = [
[x,y],
[0,r],
[-x,y],
[-x,-y],
[0,-r],
[x,-y]
];
polygon(hex);
if(points) for(p=hex) translate(p) circle(d=r/6);
}
module spare_test(){//makes a test piece to test the location of the spare spindle
difference(){
rotate([0,0,45]) bracket();
translate([-50,-30,0]) cube([100,122,depth]);
}
}