/* TransiDupe Duplicate tansmissive film. (We are running out of names for slide duplicators.) 1/5/2016 Version .9.005 Remixed from "DupliHood -- a slide copying attachment" by Hank Dietz http://www.thingiverse.com/thing:431624 http://www.instructables.com/id/3D-Printed-Slide-Copy-Attachment/ Modified to work with the PhotoSolve Xtend-a-Slide https://www.photosolve.com/main/product/xtendaslide/index.html TransiDupe is released under the Creative Commons - attribution license http://creativecommons.org/licenses/by/3.0/ */ /* Global */ // How many sections? (each section is 26mm) // "2" (ea.) is typical for a P&S + closeup lens // "3" (ea.) works for an APS-C (crop) camera + 60mm macro lens for 35mm slides/negatives // "7" (ea.) works for an APS-C (crop) camera + 100mm macro lens for 35mm slides/negatives // Sections are 50mm in diameter. So probably shouldn't make more than 1 or 2 rear sections // for film6x6 (AKA 120 film) which has approx. 70mm diagonal. number_of_rear_sections=3; // [1:8] number_of_front_sections=3; // [1:8] // Also, see reardiskdiameter, below. // Which part do you want to make? part = "exploded"; // [fronttube:The front tube,reartube:The tube that attaches to the lens, springpart:The spring cap that holds the slide, diffuser:The optional diffuser,exploded:Exploded view of all three parts (for viewing, not printing),calslide:Blank slide for calibration,playpen1:For experimenting,xslidecarrier:Xtend-a-Slide slide carrier] // What is the slide format? film = "film35"; // [film6x6:Mounted 6x6cm slides,film35:Mounted 35mm (135 format) slides] /* [Hidden] */ // Debugging. "true" makes some parts thinner/shorter for making test prints // Anything other than "true" == false; "truex" == false // i.e., debug="truex" to make normal sized prints. debug="truex"; // For making test prints to see if the parts fit // (Shorter print time and use less filament.) num_rear_sections=((debug == "true") ? 1.4 : number_of_rear_sections); num_front_sections=((debug == "true") ? 1.4 : number_of_front_sections); // Make the round plates on the tubes makeroundplate = "true"; // Make the tubes maketube = "true"; // Set reardiskdiameter to the diameter of the step-up ring that is mounted on your lens. // (Or maybe slightly smaller.) reardiskdiameter=67; // Make "sectionheight" be small (5) if you want // to make a test tube to check that the parts fit together properly // before you make the full size part. // 26mm is the height of an Xtend-a-slide section //sectionheight = 26; sectionheight=((debug == "true") ? 10 : 23 ); cutoutfilmarea = "true"; // Cut out the film area on the Xtend-a-Slide slide carrier // Yes, if supplying your own diffusion // No, if you are printing the carrier in white and it will // be the diffuser. /* I don't think that "exploded" is printable. It is handy to see all the parts together. You can load an .stl file into netfabb to see how many cubic centimeter of filiment that all the parts will use. */ filmx=((film == "film6x6") ? 60 : 36); filmy=((film == "film6x6") ? 60 : 24); framex=((film == "film6x6") ? 70 : 50); framey=((film == "film6x6") ? 70 : 50); /* filmx=36; filmy=24; framex=50; framey=50; framez=3.25; */ framez=((debug == "true") ? 0 : 3.25); frametol=1; lip=2; //diag=sqrt(((framex+frametol)*(framex+frametol))+((framey+frametol)*(framey+frametol))); //diag=88; innertall=80; //overlap=5; overlap=((debug == "true") ? 1.8 : 5); spring=1; // Xtend-a-Slide dimensions // Front tube //frontdiskdiameter=87; frontdiskdiameter=((film == "film6x6") ? 110 : 87); //frontdiskheight=3.65; frontdiskheight=((debug == "true") ? 1 : 3.65 ); fronttubebackindia=50; fronttubefrontindia=framex; fronttubethickness=3.33; frontrimheight=((debug == "true") ? 3 : 8 ); // Rear tube // Set reardiskdiameter to the diameter of the step-up ring that is mounted on your lens. //reardiskdiameter=67; //reardiskheight=2; reardiskheight=((debug == "true") ? 1 : 2 ); reartubeoutdia=49.5; reartubethickness=2.35; // Xtend-a-Slide carrier // length of notch to fish the slide out of the carrier with your finger xslidefingernotchlength=31; xslidefingernotchwidth=22.5; // diameter of slide carrier xslidedia=88; //xfrontdiskheight=((debug == "true") ? 1 : 2.7); xfrontdiskheight=2.7; slidethickness=1.12; length_of_both_tubes = (num_rear_sections+num_front_sections)*sectionheight; // $fn=90; //$fn=((debug == "true") ? 60 : 90); tol=0.25; module calslide () { echo(str("Making calibration slide for ", film, ".")); echo(str("Slide Thickness = ", slidethickness, "mm. ")); difference() { cube([framex+frametol, framey+frametol, slidethickness], center=true); //translate([framex-filmx, framey-filmx, 0]) { cube([filmx,filmy, slidethickness*2], center=true) //cylinder(h=slidethickness*2,r=slidethickness,center=true) ; //} for (i=[1:8]) { translate ([(framex/10*i)- framex/2.25, framey/3.75 , 0]) { cube([slidethickness*2, slidethickness/3, slidethickness*2], center=true); cube([slidethickness/3, slidethickness*1, slidethickness*2], center=true); //cylinder(h=slidethickness*2,r=slidethickness,center=true); } } for (i=[1:8]) { translate ([(framex/10*i)- framex/2.25, -(framey/3.85), 0]) { cube([slidethickness*2, slidethickness/3, slidethickness*3], center=true); cube([slidethickness/3, slidethickness*1, slidethickness*2], center=true); //cylinder(h=slidethickness*2,r=slidethickness,center=true); } } } } module playpen1() { union() { echo(str("Playpen1 ", film, ".")); echo(str("frontdiskdiameter = ", frontdiskdiameter, ". ")); //translate([0, 500-(framey/2)+frametol/4, 0]) //color("red") cube([framex+frametol, 1.5, framex+frametol], center=true) difference() { // outer rim //cylinder(r=frontdiskdiameter/2+lip+lip, h=framez+spring+overlap); //cylinder(r=frontdiskdiameter/2, h=framez+spring+overlap); // slide holder translate([0, 0, framez+spring]) cylinder(r=frontdiskdiameter/2+lip, h=1000) ; // slide removal access, shifted up as of 20140824 translate([0, 500-(framey/2)+frametol/4, 0]) //color("red") //cube([framex+frametol, 1000, 1000], center=true) ; } } } module springpart() { union() { echo(str("Making Spring Holder for ", film, ".")); echo(str("frontdiskdiameter = ", frontdiskdiameter, "mm. ")); difference() { // outer rim cylinder(r=frontdiskdiameter/2+lip+lip, h=framez+spring+overlap); //cylinder(r=frontdiskdiameter/2, h=framez+spring+overlap); // slide holder translate([0, 0, framez+spring]) cylinder(r=frontdiskdiameter/2+lip, h=1000) ; // slide removal access, shifted up as of 20140824 translate([0, 500-(framey/2)+frametol/4, 0]) //color("red") cube([framex+frametol, 1000, 1000], center=true) ; } difference() { union() { // spring translate([0, 0, spring/2]) cube([framex, (framey+frametol)*1, spring], center=true); // bump on the spring, thicker as of 20140824 difference() { translate([0, filmy/7, -filmy*2+spring*3]) rotate([0, 90, 0]) if (debug == "true") { cylinder(r=filmy*1.94, h=framex*1, center=true, $fn=180); } else { cylinder(r=filmy*2, h=framex, center=true, $fn=180); } translate([0, 0, -500]) cube([1000, 1000, 1000], center=true) ; } } // clear film area + double tolerance as of 20140824 translate([0, 500-(filmy+frametol)/2-frametol, 0]) cube([filmx+2*frametol, 1000, 1000], center=true) ; } } } // Slide carrier for Xtend-a-Slide. // (You need to add a layer of Staples adhesive rubber magnet. // that you cut out yourself.) module xslidecarrier () { echo(str("Making slide carrier for ", film, ".")); echo(str("thickness is ", xfrontdiskheight, ".")); difference() { cylinder(r=xslidedia/2, h=xfrontdiskheight); // Bottom plate if (cutoutfilmarea == "true") { cube([filmy+1, filmx+1, xfrontdiskheight+20], center=true); // Cut out the film area } translate([xslidedia/2-13,0,-5]) { // Make pieces for finger notch cylinder(r=xslidefingernotchwidth/2, h=xfrontdiskheight+20); translate([0,-xslidefingernotchwidth/2,0]) cube([xslidefingernotchlength,xslidefingernotchwidth,xfrontdiskheight+20],center=false); } } translate([0,0,xfrontdiskheight*.9]) { // Need to lower it a bit to pervent (mesh) holes difference() { // h=xfrontdiskheight-1.7 sets height of top layer cylinder(r=xslidedia/2, h=xfrontdiskheight-1.9); // 2nd layer translate([-(framex+frametol)/2, -(framex+frametol)/2,0]) // Cut out area for slide cube([(framex+frametol)*2, framey+frametol, xfrontdiskheight*1.1], center=false); // Add bevels to the end of the slide cutout. translate([framex/2,framey/5,0]) rotate([0,0,15]) cube([(framex+frametol)*.5, (framey+frametol)*.3, xfrontdiskheight*2.5], center=false); translate([framex/2,-framey*.5,0]) rotate([0,0,-15]) cube([(framex+frametol)*.5, (framey+frametol)*.3, xfrontdiskheight*2.5], center=false); } } } module fronttube( sections=3, buildplate="true", buildtube="true", slits="true") { echo(str("Making front tube for ", film, ".")); echo(str(sections, " sections, sectionheight ", sectionheight, "mm, total length: ",sections*sectionheight, "mm.")); shortsection=(sections*sectionheight)-(sectionheight*.0); // Start with adding an outer rim on the front disk difference() { cylinder(r=(frontdiskdiameter/2)+(lip*.9), h=frontrimheight); cylinder(r=((frontdiskdiameter-fronttubethickness)/2)+(lip*.9), h=frontrimheight+1); } difference() { // Temporarily change to "union()" to see what is subtracted // First build a solid front plate and tube union() { if (buildplate == "true" ) { cylinder(r=(frontdiskdiameter/2)+(lip*.9), h=frontdiskheight); } // Then the tube. Solid, at this point if (buildtube == "true" ) { // cylinder(r1=(fronttubefrontindia+fronttubethickness)/2, r2=(fronttubebackindia+fronttubethickness)/2-(fronttubethickness*0), h=shortsection); } } // Now difference() kicks in and eliminates these translate([0, 0, (sections*sectionheight)/2+0]) //translate([0, 0, -2]) // Eliminate the inner tube cylinder(r1=fronttubefrontindia/2, r2=fronttubebackindia/2, h=shortsection+2,center=true); // make slits by rotating a skinny rectangle around the tube (which are eliminated with "difference()") } translate([0, 0, (sections*sectionheight)-(sectionheight*.2)]) { difference() { if (buildtube == "true" ) { difference() { cylinder(r=(fronttubebackindia+fronttubethickness)/2, h=sectionheight/2); translate([0,0,-2]); cylinder(r=(fronttubebackindia)/2, h=sectionheight/2+4); } } if (slits == "true") { //translate([0,0, (sectionheight*sections)-(sectionheight*.5)]) translate([0,0,-(sectionheight*.5)]) for (i=[1:24:360]) { // Rotate 360 degrees, in 36 degree steps rotate([0,0,i]) cube([fronttubebackindia+(fronttubebackindia*.0001), 1.1, sectionheight*1],center=false); } } } } } module reartube(sections=3, buildplate="true", buildtube="true") { echo(str("Making rear tube for ", film, ".")); //echo(str(sections, " sections.")); echo(str(sections, " sections, sectionheight ", sectionheight, "mm, total length: ",sections*sectionheight, "mm.")); difference() { // Temporarily change to "union()" to see what is subtracted union() { if (buildplate == "true" ) { cylinder(r=(reardiskdiameter/2)+(lip*.0), h=reardiskheight); } if (buildtube == "true" ) { //translate([0, 0, reardiskheight]) cylinder(r=reartubeoutdia/2, h=sections*sectionheight); } } // Eliminate the inner tube. translate([0, 0, (sections*sectionheight)/2]) cylinder(r=(reartubeoutdia-reartubethickness)/2, h=(sections*sectionheight)+20,center=true); } } module diffuser() { echo(str("Making optional diffuser for ", film, ".")); echo(str("frontdiskdiameter = ", frontdiskdiameter, "mm. ")); translate([0, 0, overlap*2+1]) mirror([0, 0, 1]) union() { difference() { // outer rim cylinder(r=frontdiskdiameter/2+lip+lip+lip, h=overlap); cylinder(r=frontdiskdiameter/2+lip+lip, h=1000, center=true); } translate([0, 0, overlap]) difference() { cylinder(r=frontdiskdiameter/2+lip+lip+lip, h=overlap+1); cylinder(r1=frontdiskdiameter/2+lip+lip-1, r2=frontdiskdiameter/2+lip+lip+lip-1, h=overlap); translate([0, 0, -500]) cube([1000, 1000, 1000], center=true); } } } print_part(); // Colors only affect F5 (CGS) preview mode; // These colors go away after F6 (CGAL) render mode module print_part() { min_length = length_of_both_tubes - sectionheight; max_length = length_of_both_tubes - 10; echo(str("Working length of both tubes is approx. ", min_length , "mm through ", max_length, "mm.")); if (part == "fronttube") { color ("gray") fronttube(sections=num_front_sections, buildplate=makeroundplate, buildtube=maketube); } else if (part == "reartube") { color ("gray") reartube(sections=num_rear_sections, buildplate=makeroundplate, buildtube=maketube); } else if (part == "springpart") { color("white") springpart(); } else if (part == "xslidecarrier") { color("white") xslidecarrier(); } else if (part == "diffuser") { color ("white") diffuser(); } else if (part == "calslide") { color ("white") calslide(); } else if (part == "playpen1") { color ("white") playpen1(); } else if (part == "exploded") { union() { color("white") diffuser(); translate([0, 0, (lip*1)+overlap*2+1]) union() { color("red") springpart(); translate([0, 0, lip*6]) color("blue") fronttube(sections=num_front_sections, buildplate=makeroundplate, buildtube=maketube); translate([0, 0, (num_front_sections*sectionheight)+ (sectionheight*.35)+lip*7]) color("green") reartube(sections=num_rear_sections, buildplate=makeroundplate, buildtube=maketube); color("white") translate([0, 0, (num_rear_sections+num_front_sections)*sectionheight+(sectionheight*.4)+lip*8]) // So you can look down through the tubes in "exploded", in debug mode if (debug != "true") { calslide(); } else { //calslide(); } ; } } } else { // ; } }