The Smell of Molten Projects in the Morning

Ed Nisley's Blog: Shop notes, electronics, firmware, machinery, 3D printing, laser cuttery, and curiosities. Contents: 100% human thinking, 0% AI slop.

Day: June 12, 2013

  • Portable AC Vent Plug

    This plug for a portable air conditioner’s window vent may be un-buildable with my current state of 3D printer-fu. The top view shows the recess for a disk of insulating foam:

    Portable AC Vent Plug - solid model - top
    Portable AC Vent Plug – solid model – top

    The side view shows the thread profile and the groove for the O-ring seal:

    Portable AC Vent Plug - solid model - side
    Portable AC Vent Plug – solid model – side

    The bottom view shows the hemispheric finger grip recess:

    Portable AC Vent Plug - solid model - bottom
    Portable AC Vent Plug – solid model – bottom

    Basically, that design requires extensive support material no matter how it’s laid out. I tried the obvious way without any support, but that huge flat surface popped off the glass:

    AC Vent Plug - flat build
    AC Vent Plug – flat build

    The thread and groove overhangs in that orientation would require support and then extensive cleanout. Slic3r doesn’t do a good job of supporting internal layers, so the bottom of the recesses tend to flop into the hexagonal infill. I’m not sure building internal support all the way up the inside of the threads would be a Good Thing, though.

    Rotating by 90 degrees and cutting it in half failed because the automagic support structure popped off the platform:

    AC Vent Plug - split build
    AC Vent Plug – split build

    Admittedly, that was before I started using hairspray (on the platform!), but both orientations require far too much support. In fact, the rotated version might weigh half a kilo…

    I’m also generating the thread elements incorrectly; the joints don’t meet smoothly at the junctions. I think tapering each element so the smaller end nests inside the larger end will work better. Perhaps using a scaled hexagonal element would be better / faster than the current extruded 2D shape?

    I think the correct way to proceed will be a 3D print of the finger grip and flange section, oriented so the hemisphere points upward, with the threaded section made from a length of PVC pipe with lathe-turned threads and O-ring groove, butted against the flange around the grip section.

    Problem: that’s an 8 mm pitch thread and my inch-size lathe doesn’t do metric:

    • Need: 8 mm = 0.315 in → 3.175 TPI
    • Closest: 3-1/4 TPI → 0.308 in = 7.82 mm
    • Worse: 3 TPI → 0.333 in = 8.47 mm

    The plug needs about three turns, which means the 3-1/4 TPI = 7.82 mm pitch thread would be off by 0.54 mm, roughly a third of the thread form’s crest. That might actually work, as the “thread” on the inside of the pipe this thing fits into is actually a thin ridge, rather than an actual thread shape, and the plug is supposed to jam against the flange anyway.

    Maybe a four-axis setup in the Sherline, with the rotary table holding the PVC pipe (or whatever) aligned with the X axis? It would just barely fit under the spindle with the end mill in a collet.

    The pipe rack doesn’t hold any suitable plastic pipe.

    The OpenSCAD source code:

    // Portable AC Vent Plug
    // Ed Nisley KE4ZNU - June 2013
    
    Layout = "Show";			// Show Build Grip Helix HelixUnit Ring Plug Stiffener
    //-------
    //- Extrusion parameters must match reality!
    //  Print with +0 shells and 3 solid layers
    
    ThreadThick = 0.25;
    ThreadWidth = 0.40;
    
    HoleWindage = 0.3;
    
    Protrusion = 0.1;			// make holes end cleanly
    
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    
    //-------
    // Plug Dimensions
    
    PlugLength = 53.0;
    PlugOD = 128.0;
    
    FlangeThick = 5.0;
    FlangeWidth = 4.0;
    FlangeOD = 2*FlangeWidth + PlugOD;
    
    HelixPitch = 8.0;
    HelixOffset = 29.0 - HelixPitch/2;		// add half turn to ensure snug fit against flange
    HelixLength = PlugLength - HelixOffset;
    HelixDepth = 3.0;
    HelixBase = 3.5;
    HelixTip = 1.8;
    
    ORingDia = 3.4;
    ORingDepth = 0.75 * ORingDia;
    ORingOffset = ORingDia/2;
    
    GripOD = 90.0;
    GripDepth = 20.0;
    GripBar = 15.0;
    
    AlignDia = 3.0;
    AlignDepth = 5.0;
    
    FoamOD = PlugOD - 4*HelixDepth;
    FoamDepth = PlugLength - GripDepth;
    
    NumSides = 12*4;
    $fn = NumSides;
    
    echo("Flange OD: ",FlangeOD);
    echo("Overall length:",(FlangeThick + PlugLength));
    
    module PolyCyl(Dia,Height,ForceSides=0) {			// based on nophead's polyholes
    
      Sides = (ForceSides != 0) ? ForceSides : (ceil(Dia) + 2);
    
      FixDia = Dia / cos(180/Sides);
    
      cylinder(r=(FixDia + HoleWindage)/2,h=Height,$fn=Sides);
    }
    
    module ShowPegGrid(Space = 10.0,Size = 1.0) {
    
      RangeX = floor(100 / Space);
      RangeY = floor(125 / Space);
    
    	for (x=[-RangeX:RangeX])
    	  for (y=[-RangeY:RangeY])
    		translate([x*Space,y*Space,Size/2])
    		  %cube(Size,center=true);
    
    }
    
    //-------
    // Recessed finger grip
    // Includes Protrusion below Z=0 for clean removal from plug
    
    module GripShape(Length,Width,Depth) {
    
    Radius = (pow(Depth,2) + pow(Length,2)/4) / (2*Depth);
    
    	difference(convexity=2) {
    		intersection() {
    			translate([0,0,(-Radius + Depth)])
    				sphere(r=Radius);
    			translate([0,0,(Depth/2 - Protrusion)])
    				cube([2*Radius,2*Radius,(Depth + Protrusion)],center=true);
    		}
    		translate([0,0,Depth/2])
    			cube([2*Radius,Width,(Depth + Protrusion)],center=true);
    	}
    }
    
    //-------
    // One section of the screw thread helix
    
    module HelixUnit() {
    
    UnitAdjust = 1.25;
    
    	linear_extrude(height=UnitAdjust*PI*PlugOD/NumSides,center=true)
    		polygon(points=[
    				[0,0],
    				[-HelixDepth,(HelixBase - HelixTip)/2],
    				[-HelixDepth,HelixBase - (HelixBase - HelixTip)/2],
    				[0,HelixBase],
    				[Protrusion,HelixBase],
    				[Protrusion,0],
    				[0,0]
    		]);
    }
    
    //-------
    // Helix Element Shape
    
    module HelixShape() {
    
        Turns = HelixLength/HelixPitch;
        Slices = Turns*NumSides;
        RotIncr = 1/NumSides;
        PitchRad = PlugOD/2;
        ZIncr = HelixLength/Slices;
        helixangle = atan(HelixPitch/(3.14159265358979*PlugOD));
    
        for (i = [0:Slices-1]) {
    		translate([PitchRad*cos(360*i/NumSides),PitchRad*sin(360*i/NumSides),i*ZIncr])
    			rotate([90+helixangle,0,360*i/NumSides])
    				HelixUnit();
    	}
    
    }
    
    //-------
    // O Ring Shape
    
    module ORingShape(MajorDia,MinorDia,Recess) {
    	rotate_extrude()
    		translate([MajorDia/2,0,0])
    			polygon(points=[[0,0],
    							[-Recess,0.25*MinorDia],
    							[-Recess,0.75*MinorDia],
    							[0,MinorDia],
    							[Protrusion,MinorDia],
    							[Protrusion,0],
    							[0,0]]);
    }
    
    //-------
    // Overall plug shape
    
    module PlugShape() {
    
    	difference(convexity=5) {
    		union() {
    			cylinder(r=FlangeOD/2,h=FlangeThick);
    			cylinder(r=PlugOD/2,h=(PlugLength + FlangeThick));
    		}
    		translate([0,0,(PlugLength + FlangeThick - FoamDepth)])
    			cylinder(r=FoamOD/2,h=(FoamDepth + Protrusion));
    		translate([0,0,(ORingOffset + FlangeThick - ORingDia/2)])
    			ORingShape(PlugOD,ORingDia,ORingDepth);
    		GripShape(GripOD,GripBar,GripDepth);
    /*		for (x=[-1,1])
    			translate([(x*PlugOD/4),AlignDepth,(FlangeThick + PlugLength/2)])
    				rotate([90,0,0])
    					PolyCyl(AlignDia,2*AlignDepth,6);
    */
    	}
    }
    
    //-------
    // Plug assembly
    
    module PlugAssembly() {
    
    	difference(convexity=5) {
    		render(convexity=5) PlugShape();
    		translate([0,0,(FlangeThick + HelixOffset)])
    			HelixShape();
    	}
    }
    
    //-------
    // Build it!
    
    ShowPegGrid();
    
    if (Layout == "Plug") {
    	PlugShape();
    }
    
    if (Layout == "Show") {
    	PlugAssembly();
    }
    
    if (Layout == "Build") {
    	difference() {
    		intersection(convexity=10) {
    			translate([0,0,FlangeOD/2])
    				cube([2*FlangeOD,3*PlugLength,FlangeOD],center=true);
    			union() {
    				translate([0,10,0])
    					rotate([90,0,180])
    						PlugAssembly();
    				translate([0,-10,0])
    					rotate([-90,0,180])
    						PlugAssembly();
    			}
    		}
    	}
    }
    
    if (Layout == "Grip")
    	GripShape(GripOD,GripBar,GripDepth);
    
    if (Layout == "Ring")
    	ORingShape(PlugOD,ORingDia,ORingDepth);
    
    if (Layout == "HelixUnit")
    	HelixUnit();
    
    if (Layout == "Helix")
    	HelixShape();