// -*- C -*- // filamentspool.scad // 3D design for filament spools to hold coils as supplied by Faberdashery // // // Copyright 2012,2013,2016 Ian Jackson // // This work 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. // // This work 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 this work. If not, see // // // Each spool is a hub with 3 or 4 arms. Each arm has a cup for // holding the filament. The effective diameter can be adjusted by // setting the cup into a different seat in the arm. The cups are // held on with simple clips, so the filement coil can easily be // removed and replaced. // // This file (and its includes) can generate: // // - Heavy duty 4-armed spool suitable for holding a 100m // Faberdashery coil on the spool arm of a Lulzbot TAZ-5. // // Set // fdia=2.85 // lightduty=false // And print following parts // Hub // ArmEnd x 4 // FilamentCup x 4 (or FilamentCupPair x 2) // CupSecuringClup x 4 // // You will also need 4 x M4 machine screws and nuts // // - Light duty 3-armed spool suitable for up to around 30m // of Faberdashery 2.85mm PLA. // // Set // fdia=2.85 // lightduty=true // And print following parts // Hub // ArmEnd x 3 // FilamentCup x 3 (or FilamentCup + FilamentCupPair) // CupSecuringClup x 3 // TowerDoveClipPin x 6 // // When assembling, insert one TowerDoveClipPin from each side, // joining each ArmEnd to the Hub with two TowerDoveClipPins. // Modest force with pliers is good to seat them properly. // // (note that the light duty and heavy duty CupSecuringClips // are slightly different) // // For the above, I generally used the Cura `Standard' PLA profile. // // - Storage arm suitable for screwing to walls, bookshelves, // etc. (requires non-countersunk M4 screws); will hold two // heavy duty spools each with a 100m coil. // // Set // fdia=2.85 // lightduty=false // And print one of these, according to taste // StorageArmLeft // StorageArmRight // // NB that the `light duty' version of this is shorter and // will only take two `light duty' spools. // // For the above, I used the Cura `High detail' PLA profile because // I wanted it pretty, but the `Standard' profile should do fine. // // - Spool (in many parts) for handing 1.75mm filament, printable // on, and with parts for mounting on, a Reprappro Huxley. fdia=2.85; // or 1.75 lightduty=false; // or true slop=0.5; bigslop=slop*2; function selsz(sm,lt,lg) = fdia < 2 ? sm : lightduty ? lt : lg; function usedove() = selsz(true,true,false); num_arms = selsz(3,3,4); channelslop=selsz(slop,0.75,slop); exteffrad = 70; hubeffrad = selsz(30, 82, 40); hubbigrad = selsz(20, 38, 38); hublwidth = selsz(3, 2.5, 4); hubstemwidth = 2; hublthick = 10; hubaxlerad = selsz(5, 28/2, 28/2); totalheightfromtower = 240; axletowerfudgebend = 0; axleaxlefudgebend = 3; axlepadlen = 1.0; armend_length = 120; prongthick=selsz(5,4,5); prongwidth=selsz(5,4,5); prongribwidth=3; prongribheight=selsz(0,0,4); ratchetstep=15; ratchettooth=3; ratchettoothheight=5; ratchettoothsmoothr=1; ratchettoothslope=0.75; overlap=0.5; cupwidth=selsz(40,25,50); cupheight=selsz(55,25,55); cupstrong_dx=selsz(0,0,-10); propxshift = -6; doveclipheight = 10; teethh=3; teethgapx=4+fdia; prongstalkxwidth=3; stalklength=selsz(35,25,55); overclipcupgap=5; overclipdepth=15; overcliproundr=2.0; overclipthick=1.0; overclipcupnextgap=selsz(20,15,20); hubaxlelen = selsz(25, 62.5, 77.5); echo(hubaxlelen); overclipsmaller=-2.5; overclipbigger=0.0; wingspoke=2.5; wingsize=6; wingthick=3; armendwallthick=selsz(2.5, 1.8, 2.5); armendbasethick=selsz(1.2, 1.2, 1.2); axlehorizoffset = 12.5; axlevertheight = 100; towercliph = 16; towerclipcount = 3; towerpillarw = 5; axlepinrad = 2; axlepintabrad = 5; washerthick = 1.2; washerthinthick = 0.8; washerverythinthick = 0.4; washerrad = hubaxlerad + 7.5; frictionwasherarmwidth = 3; frictionwasherextrapush = 1.0; ratchetpawl=ratchetstep-ratchettooth-bigslop*2; nondove_armhole_x = 32; nondove_armhole_hole = 4 + 0.8; nondove_armhole_support = 7; nondove_armhole_wall = 3.2; nondove_armhole_slop = 0.5; nondove_armhole_slop_x = 0.5; nondove_armbase = nondove_armhole_x + nondove_armhole_hole/2 + nondove_armhole_support; echo(nondove_armbase); include include include include channelwidth = prongthick + channelslop; channeldepth = prongwidth + ratchettoothheight; totalwidth = armendwallthick*2 + channelwidth; totalheight = channeldepth + armendbasethick; stalkwidth = prongwidth + prongstalkxwidth; module ArmEnd(length=armend_length){ ////toplevel if (usedove()) { translate([ratchettoothsmoothr, channelwidth/2, -armendbasethick]) { rotate([0,0,-90]) DoveClipPairBase(h=doveclipheight); } } else { difference(){ translate([1, -armendwallthick, -armendbasethick]) mirror([1,0,0]) cube([nondove_armbase+1, totalwidth, totalheight]); translate([-nondove_armbase + nondove_armhole_x, -armendwallthick + totalwidth/2, -armendbasethick -1]) cylinder(r= nondove_armhole_hole/2, h=totalheight+2, $fn=10); } } difference(){ translate([0, -armendwallthick, -armendbasethick]) cube([length, totalwidth, totalheight]); translate([-1, 0, 0]) cube([length+1 - ratchettooth, channelwidth, channeldepth+1]); translate([-1, 0, ratchettoothheight]) cube([length+2, channelwidth, channeldepth+1]); } for (dx = [0 : ratchetstep : length - ratchetstep]) translate([dx,0,0]) { translate([ratchettoothsmoothr+0.5, armendwallthick/2, 0]) minkowski(){ rotate([90,0,0]) cylinder($fn=20, r=ratchettoothsmoothr, h=armendwallthick); multmatrix([ [ 1, 0, ratchettoothslope, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ]]) cube([ratchettooth - ratchettoothsmoothr*2, channelwidth, ratchettoothheight - ratchettoothsmoothr]); } } } module FilamentCupHandle(){ pawlusewidth = ratchetpawl-ratchettoothsmoothr*2; mirror([0,1,0]) { cube([stalklength, stalkwidth, prongthick]); translate([stalklength, stalkwidth/2, 0]) cylinder(r=stalkwidth/2, h=prongthick, $fn=20); translate([ratchettoothsmoothr, stalkwidth, 0]) { minkowski(){ cylinder($fn=20,r=ratchettoothsmoothr, h=1); multmatrix([ [ 1, -ratchettoothslope, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ]]) cube([pawlusewidth, ratchettoothheight - ratchettoothsmoothr, prongthick - 1]); } } } } module FilamentCupCup(){ for (my=[0,1]) mirror([0,my,0]) { translate([0, cupwidth/2, 0]) cube([cupheight + prongwidth, prongwidth, prongthick]); } } module FilamentCup() { ////toplevel FilamentCupHandle(); gapy = prongwidth; dy = cupwidth/2 + gapy + overclipcupgap; baselen = dy+cupwidth/2; translate([0, dy, 0]) FilamentCupCup(); cube([prongwidth, baselen+1, prongthick]); translate([cupstrong_dx, prongwidth, 0]) { cube([prongwidth, baselen-prongwidth, prongthick]); for (y = [0, .33, .67, 1]) translate([0, (baselen - prongwidth) * y, 0]) cube([-cupstrong_dx + 1, prongwidth, prongthick]); } if (cupstrong_dx != 0) { rotate([0,0,45]) translate([-prongwidth*.55, -prongwidth*2.1, 0]) cube([prongwidth*(2.65), prongwidth*4.2, prongthick]); } translate([0, -0.2, 0]) cube([prongribwidth, baselen, prongthick + prongribheight]); if (prongribheight > 0) { translate([-prongwidth, baselen, 0]) cube([cupheight/2, prongwidth + prongribheight, prongribwidth]); } midrad = cupwidth/2 + prongwidth/2; propshift = stalklength - overclipdepth - prongthick + propxshift; proptaken = propshift; echo(midrad, propshift, proptaken); translate([propshift, -1, 0]) { // something is wrong with the y calculation cube([prongwidth, gapy+2, prongthick]); } for (y = [overclipcupgap, overclipcupgap+overclipcupnextgap]) { translate([cupstrong_dx, y + prongwidth, 0]) rotate([0,0, 102 + fdia]) FilamentTeeth(fdia=fdia, h=teethh); } for (x = [-0.3, -1.3]) { translate([cupheight + overclipcupnextgap*x, baselen + prongwidth, 0]) rotate([0,0, 12 + fdia]) FilamentTeeth(fdia=fdia, h=teethh); } } module CupSecuringClipSolid(w,d,h1,h2){ rotate([0,-90,0]) translate([0,-h1/2,-w/2]) linear_extrude(height=w) { polygon(points=[[0,0], [d,0], [d,h2], [0,h1]]); } } module CupSecuringClipSolidSmooth(xrad=0, xdepth=0){ hbase = totalheight + prongstalkxwidth - overcliproundr*2; minkowski(){ CupSecuringClipSolid(w=totalwidth, d=overclipdepth + xdepth, h1=hbase - overclipsmaller, h2=hbase + overclipbigger); cylinder($fn=20, h=0.01, r=overcliproundr+xrad); } } module CupSecuringClip(){ ////toplevel wingswidth = wingspoke*2 + overclipthick*2 + overcliproundr*2 + totalwidth; difference(){ union(){ CupSecuringClipSolidSmooth(xrad=overclipthick, xdepth=0); translate([-wingswidth/2, -wingsize/2, 0]) cube([wingswidth, wingsize, wingthick]); translate([-wingsize/2, -wingswidth/2, 0]) cube([wingsize, wingswidth, wingthick]); } translate([0,0,-0.1]) CupSecuringClipSolidSmooth(xrad=0, xdepth=0.2); } } module ArmDoveClipPin(){ ////toplevel DoveClipPin(h=doveclipheight); } module TowerDoveClipPin(){ ////toplevel DoveClipPin(h=towercliph/2); } module Hub(){ ////toplevel axlerad = hubaxlerad + slop; xmin = axlerad+hublwidth/2; xmax = hubbigrad-hublwidth/2; hole = hubeffrad - hubbigrad - DoveClip_depth() - hublwidth*2; holewidth = DoveClipPairSane_width() - hubstemwidth*2; nondove_allwidth = nondove_armhole_wall*2 + totalwidth; difference(){ union(){ difference(){ cylinder($fn=60, h=hublthick, r=hubbigrad); translate([0,0,-1]) cylinder($fn=30, h=hublthick+2, r=(hubbigrad-hublwidth)); } cylinder(h=hubaxlelen, r=axlerad+hublwidth); for (ang=[0 : 360/num_arms : 359]) rotate([0,0,ang]) { if (usedove()){ difference() { translate([hubeffrad,0,0]) DoveClipPairSane(h=doveclipheight, baseextend = (hubeffrad - DoveClip_depth() - hubbigrad + hublwidth)); if (hole>hublwidth && holewidth > 2) { translate([hubbigrad + hublwidth, -holewidth/2, -1]) cube([hole, holewidth, hublthick+2]); } } } else { difference(){ translate([0, -nondove_allwidth/2, 0]) cube([hubeffrad + nondove_armhole_x + nondove_armhole_hole/2 + nondove_armhole_support, nondove_allwidth, nondove_armhole_wall + totalheight]); translate([hubeffrad - nondove_armhole_slop_x, -nondove_allwidth/2 + nondove_armhole_wall - nondove_armhole_slop, nondove_armhole_wall]) cube([nondove_armhole_x + 50, totalwidth + nondove_armhole_slop*2, totalheight + 1]); translate([hubeffrad + nondove_armhole_x, 0, -20]) cylinder(r= nondove_armhole_hole/2, h=50, $fn=10); } } } for (ang = [0 : 180/num_arms : 359]) rotate([0,0,ang]) rotate([90,0,0]) { translate([0,0,-hublwidth/2]) linear_extrude(height=hublwidth) polygon([[xmin,0.05], [xmax,0.05], [xmax,hublthick-0.2], [xmin, hubaxlelen-0.2]]); } } translate([0,0,-1]) cylinder($fn=60, h=hubaxlelen+2, r=axlerad); } } module ArmExtender(){ ////toplevel DoveClipExtender(length=exteffrad-hubeffrad, ha=doveclipheight, hb=doveclipheight); } module FsAxlePin(){ ////toplevel AxlePin(hubaxlerad, washerrad*2, axlepinrad, axlepintabrad, slop); } module Axle(){ ////toplevel pillarswidth = DoveClipPairSane_width(towerclipcount); rotate([0,0, -( axleaxlefudgebend + atan(slop/hubaxlelen) ) ]) translate([-axlehorizoffset, -axlevertheight, 0]) { rotate([0,0,-axletowerfudgebend]) rotate([0,0,-90]) DoveClipPairSane(h=towercliph, count=towerclipcount, baseextend=3); translate([0, DoveClip_depth(), 0]) rotate([0,0,90]) ExtenderPillars(axlevertheight - DoveClip_depth(), pillarswidth, towercliph, pillarw=towerpillarw); } axleclearlen = hubaxlelen + slop*4 + washerthick*2 + axlepadlen; axlerad = hubaxlerad-slop; bump = axlerad * 0.2; shift = axlerad-bump; joinbelowallow = 3; intersection(){ translate([0, 0, shift]) { difference() { union(){ translate([-1, 0, 0]) rotate([0,90,0]) cylinder($fn=60, r = axlerad, h = 1 + axleclearlen + axlepinrad*2 + 2); mirror([1,0,0]) rotate([0,90,0]) cylinder(r = axlerad*1.75, h = 3); intersection(){ mirror([1,0,0]) translate([axlehorizoffset - pillarswidth/2, 0, 0]) rotate([0,90,0]) cylinder($fn=60, r = towercliph - shift, h = pillarswidth); translate([-50, -joinbelowallow, -50]) cube([100, joinbelowallow+50, 100]); } } rotate([90,0,0]) translate([axleclearlen + axlepinrad/2, 0, -25]) cylinder(r = axlepinrad + slop, h=50); } } translate([-50,-50,0]) cube([100,100,100]); } } module washer(thick){ Washer(hubaxlerad, washerrad, thick, slop); } module AxleWasher(){ ////toplevel washer(thick=washerthick); } module AxleThinWasher(){ ////toplevel washer(thick=washerthinthick); } module AxleVeryThinWasher(){ ////toplevel washer(thick=washerverythinthick); } module AxleFrictionWasher(){ ////toplevel difference(){ cylinder(h=washerthick, r=washerrad); translate([0,0,-1]) cylinder(h=washerthick+2, r=hubaxlerad+slop); } frarmr = hubbigrad; frarmw = frictionwasherarmwidth; frarmpawlr = hublwidth; frarmpawlpush = slop*4 + frictionwasherextrapush; for (ang=[0,180]) rotate([0,0,ang]) { translate([washerrad-1, -frarmw/2, 0]) cube([frarmr - washerrad + 1, frarmw, washerthick]); intersection(){ translate([frarmr - frarmpawlr, -50, 0]) cube([frarmpawlr, 100, 50]); rotate([0,90,0]) cylinder(h = 50, r = frarmpawlpush, $fn=36); } } } module TowerExtender(){ ////toplevel l = totalheightfromtower - axlevertheight; echo("TowerExtender",l); DoveClipExtender(length = l, ha = towercliph, hb = towercliph, counta = towerclipcount, countb = towerclipcount, pillarw = towerpillarw); } module FilamentCupPair(){ ////toplevel FilamentCup(); translate([cupheight + prongthick*3, cupwidth/2*1.7, 0]) rotate([0,0,180]) FilamentCup(); } //----- storarm ----- storarm_hooklen = 8; storarm_hookheight = 5; storarm_thick = 10; storarm_axleslop = 4; storarm_base_w = 30; storarm_base_h = 100; storarm_base_d = 15; storarm_base_mind = 2; storarm_cope_hubaxle_mk1 = true; storarm_screw_hole = 4; storarm_screw_hole_slop = 0.5; storarm_besides_hole = 4; storarm_under_hole = 5; storarm_screw_hole_head = 8.8; storarm_screw_hole_head_slop = 1.5; // calculated storarm_axlerad = hubaxlerad - storarm_axleslop; storarm_mainlen = hubaxlelen*2 + storarm_axleslop + (storarm_cope_hubaxle_mk1 ? 10 : 0); storarm_totlen = storarm_mainlen + storarm_hooklen; storarm_mid_off_y = storarm_axlerad; storarm_base_off_y = storarm_mid_off_y + storarm_base_h/2; module StorageArmDiagPartSide(xmin, xmax){ xsz = xmax-xmin; yuse = storarm_thick/2; intersection(){ translate([xmin-1, -storarm_axlerad, storarm_thick/2]) rotate([0,90,0]) cylinder(r=storarm_axlerad, h=xsz+2, $fn=60); translate([xmin, -yuse, 0]) cube([xsz, yuse, storarm_thick]); } } module StorageArmDiagPart(xmin, xmax, shear, adjbot){ hull(){ StorageArmDiagPartSide(xmin,xmax); multmatrix([[1,0,0,0], [shear,1,0,0], [0,0,1,0], [0,0,0,1]]) translate([0, -storarm_axlerad*2 + adjbot, 0]) mirror([0,1,0]) StorageArmDiagPartSide(xmin,xmax); } } module StorageArmBaseTemplate(){ square([storarm_base_w, storarm_base_h]); } module StorageArmAtMountingHoles(){ bes = storarm_besides_hole + storarm_screw_hole; x0 = bes; x1 = storarm_base_w-bes; y1 = storarm_base_h - bes; y0 = bes; for (pos=[ [x0, y1], [x1, y1], [x1, y0] ]) { rotate([0,90,0]) translate([pos[0] - storarm_base_w, pos[1] - storarm_base_off_y, -storarm_base_d]) children(); } } module StorageArmRight(){ ////toplevel shear = storarm_hookheight / (storarm_mainlen/2); StorageArmDiagPart(-1, storarm_mainlen/2+1, shear, 0); StorageArmDiagPart(storarm_mainlen/2-1, storarm_mainlen+1, shear/2, storarm_hookheight/2); translate([0, storarm_hookheight, 0]) StorageArmDiagPart(storarm_mainlen, storarm_totlen, shear/2, -storarm_hookheight/2); difference(){ union(){ hull(){ translate([-storarm_base_d, -storarm_base_off_y, storarm_base_w]) rotate([0,90,0]) linear_extrude(height=storarm_base_mind) StorageArmBaseTemplate(); StorageArmDiagPart(-1, 0, shear, 0); } StorageArmAtMountingHoles(){ cylinder(r= storarm_screw_hole_head/2, h=10); } } StorageArmAtMountingHoles(){ translate([0,0,-1]) cylinder(r= (storarm_screw_hole + storarm_screw_hole_slop)/2 , h=20); translate([0,0,storarm_under_hole]) cylinder(r= (storarm_screw_hole_head + storarm_screw_hole_head_slop)/2, h=20); } } } module StorageArmLeft(){ ////toplevel mirror([1,0,0]) StorageArmRight(); } module StorArmHoleTest(){ ////toplevel sz = storarm_screw_hole_head + storarm_besides_hole*2; intersection(){ StorageArmRight(); translate([-50, -storarm_base_off_y, -1]) cube([100, sz, sz+1]); } } module Demo(){ translate([-hubeffrad-30,50,0]) Hub(); ArmEnd(); translate([0,50,0]) FilamentCup(); } //ArmEnd(); //FilamentCup(); //FilamentCupPair(); //CupSecuringClip(); //Hub(); //ArmExtender(); //Axle(); //AxleWasher(); //AxlePin(); //AxleFrictionWasher(); //StorageArmLeft(); //StorArmHoleTest(); //Demo();