fancier box

fancier box

use <roundedsquare.scad>;

//<params>
includeBottom = 1; // [1:yes, 0:no]
includeTop = 1; // [1:yes, 0:no]
includeGamecubePort = 1; // [1:yes, 0:no]
includeEllipticalPort = 0; // [1:yes, 0:no]
includeNunchuckPort = 0; // [1:yes, 0:no]
// TODO:
includeSwitchPort = 0; // [1:yes, 0:no]
innerLength = 80;
extraWidth = 15;
sideWall = 1.5;
topWall = 1.6;
bottomWall = 2;
bottomScrewLength = 8;
topScrewLength = 5.7;
screwDiameter = 2.12;
screwHeadDiameter = 4.11;
thinPillarDiameter = 5.5;
fatPillarDiameter = 9;
stm32Width = 24.35;
stm32Length = 57.2;
tolerance = 0.2;
pcbThickness = 1.25;
bottomOverlap = 4;
topUnderlap = 4.8;
stm32ScrewYSpacing=18.8;
stm32ScrewXSpacing=52;
stm32ScrewOffset=2.4;
gcCableDiameter=3.7;
ellipticalCableMajorDiameter=5.32;
ellipticalCableMinorDiameter=2.66;
topOffset = 4.8;
topScrewX1 = 6;
topScrewXSpacing = 54.66;
buttonHoleDiameter = 4.9;
button1OffsetFromHole = 12.7;
button2OffsetFromHole = 5.78;
ledHoleDiameter = 4;
led1XOffsetFromButton1 = 10.16;
led1YOffsetFromButton1 = 1.27;
ledSpacing = 5.08;
pcbToPCBSpacing = 12;
usbPortWidth = 10;
usbPortHeight = 4.5;
nunchuckPortTolerance = 0.3;
nunchuckPortHeight = 7.36;
nunchuckPortWidth = 12.24;
nunchuckPortInsetDepth = 1.28;
nunchuckPortInsetWidth = 4.59;
nunchuckPortPillarTopFromCenter = 4.8;
nunchuckPortZOffset = 2;
nunchuckScrewHoleYMinusFromCenterOfPort = 6.99;
nunchuckScrewHoleXMinusFromOutsideOfWall = 12.91;
nunchuckScrewHoleYSpacing = 2.54*5;
nunchuckScrewHoleXSpacing = 2.54*6;
//</params>

module dummy() {}

$fn = 32;
nudge = 0.001;

innerWidth = extraWidth+stm32Width+fatPillarDiameter*2;
bottomOffset = bottomScrewLength-pcbThickness;
bottomHeight = bottomWall+bottomOffset+pcbThickness;
bottomFatPillarLength = bottomHeight+bottomOverlap;
topHeight = topWall + topOffset + pcbThickness + max(topUnderlap,pcbToPCBSpacing);
topFatPillarLength = topHeight-topUnderlap;
nunchuckPillarLength = bottomHeight + nunchuckPortZOffset - nunchuckPortPillarTopFromCenter;

fatPillarLocations = [
    [-sideWall+fatPillarDiameter/2,-sideWall+fatPillarDiameter/2,0],
    [-sideWall+fatPillarDiameter/2,innerWidth+sideWall-fatPillarDiameter/2,0],
    [innerLength+sideWall-fatPillarDiameter/2,-sideWall+fatPillarDiameter/2,0],
    [innerLength+sideWall-fatPillarDiameter/2,innerWidth+sideWall-fatPillarDiameter/2,0]
];
stm32ScrewX1 = stm32ScrewOffset;
stm32ScrewY1 = fatPillarLocations[0][1]+fatPillarDiameter/2+thinPillarDiameter/2;

ellipticalCableY = fatPillarLocations[1][1]-fatPillarDiameter-1.5*ellipticalCableMinorDiameter;
gcPortY = stm32ScrewY1+stm32ScrewYSpacing/2;

nunchuckPortY = innerWidth+sideWall-fatPillarDiameter-nunchuckPortWidth/2-nunchuckPortTolerance*2;// (stm32ScrewY1+stm32ScrewYSpacing+thinPillarDiameter+innerWidth-fatPillarDiameter)*0.5;
nx0 = innerLength+sideWall-nunchuckScrewHoleXMinusFromOutsideOfWall;
ny0 = nunchuckPortY-nunchuckScrewHoleYMinusFromCenterOfPort;
nunchuckPillarLocations = [
    [nx0,ny0],
    [nx0-nunchuckScrewHoleXSpacing,ny0],
    [nx0-nunchuckScrewHoleXSpacing,ny0+nunchuckScrewHoleYSpacing],
    [nx0,ny0+nunchuckScrewHoleYSpacing]];
echo(nunchuckPillarLocations);

topScrewY = innerWidth-stm32ScrewY1-stm32ScrewYSpacing/2;
bottomThinPillarLocations = [
    [stm32ScrewX1,stm32ScrewY1,0],
    [stm32ScrewX1+stm32ScrewXSpacing,stm32ScrewY1,0],
    [stm32ScrewX1,stm32ScrewY1+stm32ScrewYSpacing,0],
    [stm32ScrewX1+stm32ScrewXSpacing,stm32ScrewY1+stm32ScrewYSpacing,0] ];

module base(inset=0) {
    translate([-sideWall+inset,-sideWall+inset])
    roundedSquare([innerLength+2*sideWall-2*inset,innerWidth+2*sideWall-2*inset], radius=fatPillarDiameter/2-inset);
}

module ellipticalCable() {
    rotate([0,90,0])
    translate([0,0,-nudge-sideWall])
    linear_extrude(height=3*sideWall+2*nudge)
    hull() {
        translate([-(ellipticalCableMajorDiameter-ellipticalCableMinorDiameter)/2-tolerance,0,0])
        circle(d=ellipticalCableMinorDiameter);
        translate([(ellipticalCableMajorDiameter-ellipticalCableMinorDiameter)/2+tolerance,0,0])
        circle(d=ellipticalCableMinorDiameter);
    }
}

nunchuckPortHeight = 7.36;
nunchuckPortWidth = 12.24;
nunchuckPortInsetDepth = 1.28;
nunchuckPortInsetWidth = 4.59;

module nunchuckConnector() {
    h = nunchuckPortHeight + 2*nunchuckPortTolerance;
    w = nunchuckPortWidth + 2*nunchuckPortTolerance;
    insetDepth = nunchuckPortInsetDepth;
    insetWidth = nunchuckPortInsetWidth+2*nunchuckPortTolerance;
    rotate([0,90,0])
    translate([0,0,-nudge])
    linear_extrude(height=sideWall+2*nudge)
    polygon([[-h/2,-w/2],[h/2,-w/2],[h/2,w/2],[-h/2,w/2],[-h/2,insetWidth/2],[-h/2+insetDepth,insetWidth/2],[-h/2+insetDepth,-insetWidth/2],[-h/2,-insetWidth/2]]);
}

module sideWalls() {
    difference() {
        base();
        base(inset=sideWall);
    }
}

module tweakedSideWalls() {
    difference() {
        base(inset=-sideWall);
        base(inset=sideWall+tolerance);
    }
}

module fatPillar(hole=false,bottom=true) {
    fatPillarLength = bottom?bottomFatPillarLength:topFatPillarLength;
    if (!hole)
        cylinder(d=fatPillarDiameter,fatPillarLength);
    else {
        if (bottom)
            cylinder(d=screwHeadDiameter+2*tolerance,h=fatPillarLength-(bottom?bottomWall:topWall));
        cylinder(d=screwDiameter+2*tolerance,h=fatPillarLength+nudge);
    }
}

module thinPillar(hole=false,height=10) {
    if (!hole)
        cylinder(d=thinPillarDiameter,h=height);
    else {
        cylinder(d=screwDiameter+2*tolerance,h=height);
    }
}

module bottom() {
    render(convexity=2)
    difference() {
        union() {
            linear_extrude(height=bottomWall+nudge) base();
            for (p=fatPillarLocations)
                translate(p) fatPillar();
            linear_extrude(height=bottomHeight+nudge) sideWalls();
            for (p=bottomThinPillarLocations)
                translate(p) thinPillar(height=bottomWall+bottomOffset);
            if (includeNunchuckPort)
            for (p=nunchuckPillarLocations)
                translate(p) thinPillar(height=nunchuckPillarLength);
       if (includeGamecubePort)
            translate([innerLength-2*sideWall,gcPortY-gcCableDiameter*1.5,0]) cube([2*sideWall+nudge,3*gcCableDiameter,bottomHeight]);
       if (includeEllipticalPort)
            translate([-nudge,ellipticalCableY-ellipticalCableMinorDiameter*1.5,0]) cube([2*sideWall+nudge,3*ellipticalCableMinorDiameter,bottomHeight]);
        }
        for (p=fatPillarLocations)
            translate(p) fatPillar(hole=true);
        translate([0,0,bottomHeight]) linear_extrude(height=bottomOverlap+nudge) tweakedSideWalls();
            if (includeNunchuckPort)
            for (p=nunchuckPillarLocations)
                translate([0,0,bottomWall]) translate(p) thinPillar(height=nunchuckPillarLength,hole=true);
        for (p=bottomThinPillarLocations)
            translate([0,0,bottomWall]) translate(p) thinPillar(hole=true,height=bottomHeight+nudge);
       if (includeNunchuckPort)
           translate([innerLength,nunchuckPortY,bottomHeight+nunchuckPortZOffset]) nunchuckConnector();
       if (includeGamecubePort)
       translate([innerLength-2*sideWall,gcPortY,bottomHeight]) rotate([0,90,0]) cylinder(d=gcCableDiameter,h=3*sideWall+2*nudge);
       if (includeEllipticalPort)
        translate([0,ellipticalCableY,bottomHeight]) ellipticalCable();
    }
}

module top() {
    render(convexity=2)
    difference() {
        union() {
            linear_extrude(height=topWall+nudge) base();
            for (p=fatPillarLocations)
                translate(p) fatPillar(bottom=false);
            linear_extrude(height=topHeight+nudge) sideWalls();
            translate([topScrewX1,topScrewY,0])
                thinPillar(height=topWall+topOffset);
            translate([topScrewX1+topScrewXSpacing,topScrewY,0])
                thinPillar(height=topWall+topOffset);
       if (includeGamecubePort)
            translate([innerLength-2*sideWall,innerWidth-gcPortY-gcCableDiameter*1.5,0]) cube([2*sideWall+nudge,3*gcCableDiameter,topHeight]);
       if (includeEllipticalPort)
            translate([-nudge,innerWidth-ellipticalCableY-ellipticalCableMinorDiameter*1.5,0]) cube([2*sideWall+nudge,3*ellipticalCableMinorDiameter,topHeight]);
        }
        for (p=fatPillarLocations)
            translate([0,0,topWall]) translate(p) fatPillar(hole=true,bottom=false);
            translate([topScrewX1,topScrewY,0.5])
                thinPillar(height=topWall+topOffset,hole=true);
            translate([topScrewX1+topScrewXSpacing,topScrewY,0.5])
                thinPillar(height=topWall+topOffset,hole=true);

    y0=innerWidth-(stm32ScrewY1+stm32ScrewYSpacing/2);
       if (includeNunchuckPort)
           translate([innerLength,innerWidth-nunchuckPortY,topHeight-nunchuckPortZOffset]) rotate([180,0,0]) nunchuckConnector();
       if (includeGamecubePort)
       translate([innerLength-2*sideWall,innerWidth-gcPortY,topHeight]) rotate([0,90,0]) cylinder(d=gcCableDiameter,h=3*sideWall+2*nudge);
       if (includeEllipticalPort)
        translate([0,innerWidth-ellipticalCableY,topHeight]) ellipticalCable();
        translate([-sideWall-nudge,y0-usbPortWidth/2,topHeight-usbPortHeight]) cube([sideWall+2*nudge,usbPortWidth,usbPortHeight+nudge]);
        translate([-sideWall*0.25-tolerance,y0-(stm32Width+2*tolerance)/2,topHeight-pcbThickness-tolerance]) cube([sideWall*0.25+tolerance+nudge,stm32Width+2*tolerance,pcbThickness+tolerance+nudge]);
        translate([topScrewX1+button1OffsetFromHole,topScrewY,-nudge]) cylinder(d=buttonHoleDiameter,h=topWall+2*nudge);
        translate([topScrewX1+topScrewXSpacing-button2OffsetFromHole,topScrewY,-nudge]) cylinder(d=buttonHoleDiameter,h=topWall+2*nudge);
        for(i=[0:3]) translate([topScrewX1+button1OffsetFromHole+led1XOffsetFromButton1+i*ledSpacing,topScrewY+led1YOffsetFromButton1,-nudge]) cylinder(d=ledHoleDiameter,h=topWall+2*nudge);
    }
}

if (includeBottom)
    bottom();
if (includeTop)
    translate([0,innerWidth+sideWall+8,0])
    top();

use <roundedsquare.scad>;

//<params>
includeBottom = 1; // [1:yes, 0:no]
includeTop = 1; // [1:yes, 0:no]
innerLength = 80;
extraWidth = 15;
sideWall = 1.5;
topWall = 1.6;
bottomWall = 2;
bottomScrewLength = 8;
topScrewLength = 5.7;
screwDiameter = 2.12;
screwHeadDiameter = 4.11;
thinPillarDiameter = 5.5;
fatPillarDiameter = 9;
stm32Width = 24.35;
stm32Length = 57.2;
tolerance = 0.2;
pcbThickness = 1.25;
bottomOverlap = 4;
topUnderlap = 4.8;
stm32ScrewYSpacing=18.8;
stm32ScrewXSpacing=52;
stm32ScrewOffset=2.4;
cableDiameter=3.7;
topOffset = 4.8;
topScrewX1 = 6;
topScrewXSpacing = 54.66;
buttonHoleDiameter = 4.9;
button1OffsetFromHole = 12.7;
button2OffsetFromHole = 5.78;
ledHoleDiameter = 4;
led1XOffsetFromButton1 = 10.16;
led1YOffsetFromButton1 = 1.27;
ledSpacing = 5.08;
pcbToPCBSpacing = 12;
usbPortWidth = 10;
usbPortHeight = 4.5;
//</params>

module dummy() {}

$fn = 32;
nudge = 0.001;

innerWidth = extraWidth+stm32Width+fatPillarDiameter*2;
bottomOffset = bottomScrewLength-pcbThickness;
bottomHeight = bottomWall+bottomOffset+pcbThickness;
bottomFatPillarLength = bottomHeight+bottomOverlap;
topHeight = topWall + topOffset + pcbThickness + max(topUnderlap,pcbToPCBSpacing);
topFatPillarLength = topHeight-topUnderlap;

fatPillarLocations = [
    [-sideWall+fatPillarDiameter/2,-sideWall+fatPillarDiameter/2,0],
    [-sideWall+fatPillarDiameter/2,innerWidth+sideWall-fatPillarDiameter/2,0],
    [innerLength+sideWall-fatPillarDiameter/2,-sideWall+fatPillarDiameter/2,0],
    [innerLength+sideWall-fatPillarDiameter/2,innerWidth+sideWall-fatPillarDiameter/2,0]
];
stm32ScrewX1 = stm32ScrewOffset;
stm32ScrewY1 = fatPillarLocations[0][1]+fatPillarDiameter/2+thinPillarDiameter/2;
topScrewY = innerWidth-stm32ScrewY1-stm32ScrewYSpacing/2;
bottomThinPillarLocations = [
    [stm32ScrewX1,stm32ScrewY1,0],
    [stm32ScrewX1+stm32ScrewXSpacing,stm32ScrewY1,0],
    [stm32ScrewX1,stm32ScrewY1+stm32ScrewYSpacing,0],
    [stm32ScrewX1+stm32ScrewXSpacing,stm32ScrewY1+stm32ScrewYSpacing,0] ];

module base(inset=0) {
    translate([-sideWall+inset,-sideWall+inset])
    roundedSquare([innerLength+2*sideWall-2*inset,innerWidth+2*sideWall-2*inset], radius=fatPillarDiameter/2-inset);
}

module sideWalls() {
    difference() {
        base();
        base(inset=sideWall);
    }
}

module tweakedSideWalls() {
    difference() {
        base(inset=-sideWall);
        base(inset=sideWall+tolerance);
    }
}

module fatPillar(hole=false,bottom=true) {
    fatPillarLength = bottom?bottomFatPillarLength:topFatPillarLength;
    if (!hole)
        cylinder(d=fatPillarDiameter,fatPillarLength);
    else {
        if (bottom)
            cylinder(d=screwHeadDiameter+2*tolerance,h=fatPillarLength-(bottom?bottomWall:topWall));
        cylinder(d=screwDiameter+2*tolerance,h=fatPillarLength+nudge);
    }
}

module thinPillar(hole=false,height=10) {
    if (!hole)
        cylinder(d=thinPillarDiameter,h=height);
    else {
        cylinder(d=screwDiameter+2*tolerance,h=height);
    }
}

module bottom() {
    render(convexity=2)
    difference() {
        union() {
            linear_extrude(height=bottomWall+nudge) base();
            for (p=fatPillarLocations)
                translate(p) fatPillar();
            linear_extrude(height=bottomHeight+nudge) sideWalls();
            for (p=bottomThinPillarLocations)
                translate(p) thinPillar(height=bottomWall+bottomOffset);
            translate([innerLength-2*sideWall,stm32ScrewY1+stm32ScrewYSpacing/2-cableDiameter*1.5,0]) cube([2*sideWall+nudge,3*cableDiameter,bottomHeight]);
        }
        for (p=fatPillarLocations)
            translate(p) fatPillar(hole=true);
        translate([0,0,bottomHeight]) linear_extrude(height=bottomOverlap+nudge) tweakedSideWalls();
        for (p=bottomThinPillarLocations)
            translate([0,0,bottomWall]) translate(p) thinPillar(hole=true,height=bottomHeight+nudge);
       translate([innerLength-2*sideWall,stm32ScrewY1+stm32ScrewYSpacing/2,bottomHeight]) rotate([0,90,0]) cylinder(d=cableDiameter,h=3*sideWall+2*nudge);
    }
}

module top() {
    render(convexity=2)
    difference() {
        union() {
            linear_extrude(height=topWall+nudge) base();
            for (p=fatPillarLocations)
                translate(p) fatPillar(bottom=false);
            linear_extrude(height=topHeight+nudge) sideWalls();
            translate([topScrewX1,topScrewY,0])
                thinPillar(height=topWall+topOffset);
            translate([topScrewX1+topScrewXSpacing,topScrewY,0])
                thinPillar(height=topWall+topOffset);
            translate([innerLength-2*sideWall,innerWidth-(stm32ScrewY1+stm32ScrewYSpacing/2)-cableDiameter*1.5,0]) cube([2*sideWall+nudge,3*cableDiameter,topHeight]);
        }
        for (p=fatPillarLocations)
            translate([0,0,topWall]) translate(p) fatPillar(hole=true,bottom=false);
            translate([topScrewX1,topScrewY,0.5])
                thinPillar(height=topWall+topOffset,hole=true);
            translate([topScrewX1+topScrewXSpacing,topScrewY,0.5])
                thinPillar(height=topWall+topOffset,hole=true);

    y0=innerWidth-(stm32ScrewY1+stm32ScrewYSpacing/2);
       translate([innerLength-2*sideWall,y0,topHeight]) rotate([0,90,0]) cylinder(d=cableDiameter,h=3*sideWall+2*nudge);
        translate([-sideWall-nudge,y0-usbPortWidth/2,topHeight-usbPortHeight]) cube([sideWall+2*nudge,usbPortWidth,usbPortHeight+nudge]);
        translate([-sideWall*0.25-tolerance,y0-(stm32Width+2*tolerance)/2,topHeight-pcbThickness-tolerance]) cube([sideWall*0.25+tolerance+nudge,stm32Width+2*tolerance,pcbThickness+tolerance+nudge]);
        translate([topScrewX1+button1OffsetFromHole,topScrewY,-nudge]) cylinder(d=buttonHoleDiameter,h=topWall+2*nudge);
        translate([topScrewX1+topScrewXSpacing-button2OffsetFromHole,topScrewY,-nudge]) cylinder(d=buttonHoleDiameter,h=topWall+2*nudge);
        for(i=[0:3]) translate([topScrewX1+button1OffsetFromHole+led1XOffsetFromButton1+i*ledSpacing,topScrewY+led1YOffsetFromButton1,-nudge]) cylinder(d=ledHoleDiameter,h=topWall+2*nudge);
//        translate([fatPillarDiameter-sideWall+ventMargin,-sideWall-nudge,topWall+ventMargin]) vent(innerLength+2*sideWall-2*ventMargin,ventMargin,sideWall+2*nudge);
//        translate([fatPillarDiameter-sideWall+ventMargin,innerWidth-nudge,topWall+ventMargin]) vent(innerLength+2*sideWall-2*ventMargin,ventMargin,sideWall+2*nudge);
    }
}

if (includeBottom)
    bottom();
if (includeTop)
    translate([0,innerWidth+sideWall+8,0])
    top();


The height variable was removed as a global variable.

// Ths OpenSCAD script is a direvative of:
// Customizable Gimbal v1.0
// by TheNewHobbyist 2014 (http://thenewhobbyist.com)
// http://www.thingiverse.com/thing:340948
// https://github.com/thenewhobbyist/OpenSCAD/tree/master/Customizable%20Gimble
//
// "Customizable Gimbal" as well as this script are licensed under a
// Creative Commons Attribution-NonCommercial 3.0 Unported License.
//
// "Customizable Gimbal" Description:
// This model was insirped by DesignMakeTeach's print in place gimbal designs
// on Thingiverse. Below I have linked an example. I personalized one of these
// for myself and thought I'd make it a full on Customizer model. To do this
// I recreated something similar to DesignMakeTeach's design in OpenSCAD and
// used the Stencil-o-Matic from Benjamin to add in some easy customization.
//
// TheNewHobbyist's Inspiration and attribution from:
//
// Printrbot Gimbal by DesignMakeTeach
// http://www.thingiverse.com/thing:317778
// Licensed under the Creative Commons - Attribution - Share Alike license.
//
// Stencil-o-Matic by Benjamin
// http://www.thingiverse.com/thing:55821
// Licensed under the Creative Commons - Attribution - Non-Commercial license.

// Coin and pendant features were added by Roberto Marquez - http://electronics.onebeartoe.org/

use <spur/spurs-rotated/spurs-rotated.scad>;

/* [Dimensions] */

// Paste your Sencil-o-Matic code here
input ="default_TNH";

// Move image left/right
Move_X = 0; // [-50:50]

// Move image up/down
Move_Y = 0; // [-50:50]

// Resize your image
image_size = 26.5; // [1:50]

includeGimbal = "yes"; // [yes, no]

/* [Hidden] */

  ///////////////////////////
 // Stencil-o-Matic Stuff //
///////////////////////////

stencil_thickness = 5;
offX = 0;
offY = 0;
margin = 0;
dispo_width = image_size;

points_array = (input=="default_TNH"? [[133,286],[[234.27,6.02],[231.55,7.45],[227.5,10.88],[222.85,15.67],[218.69,20.35],[214.95,25.17],[211.32,30.24],[208.44,34.98],[206.52,39],[205.31,48.23],[204.14,65.5],[202.43,96.43],[199.95,138.5],[197.65,174.91],[196.37,192.25],[195.44,195.38],[192.95,196],[190.58,196.5],[189.09,197.84],[188.55,199.75],[188.65,201.77],[188.28,204.15],[185.74,207.18],[181.17,210.7],[175.06,214.5],[168.61,218.79],[163.29,223.5],[159.05,228.64],[155.24,233.98],[152.19,239.17],[149.77,243.98],[148.11,250.02],[146.97,258.66],[145.84,267.33],[144.06,272.66],[141.97,276.16],[139.87,279.16],[138.4,281.78],[138.36,284.3],[139.83,286.58],[143.12,288.43],[150.09,289.9],[162.38,291.02],[181.28,291.67],[205.5,291.95],[229.79,291.67],[248.86,291],[261.56,289.87],[267.86,288.28],[270.76,286.27],[271.82,283.7],[271.26,280.36],[268.97,275.96],[266.18,270.14],[264.49,261.76],[263.22,253.76],[262.03,247.53],[260.34,242.46],[257.87,237.27],[254.58,232.07],[250.91,227.01],[246.01,222],[239.74,216.91],[233.89,213.03],[230,210.88],[227.72,209.34],[225.75,206.9],[224.51,204.05],[224,201.5],[223.82,199.39],[223.39,197.58],[222.07,196.41],[219.45,196],[216.94,195.74],[215.57,195.11],[215.61,179.54],[216.5,143.36],[217.84,100.02],[218.98,67.24],[219.99,41.97],[223.5,34.86],[227.01,28.44],[230.51,22.99],[232.97,19.44],[234,17.58],[234.64,16.25],[236.17,13.98],[237.73,11.12],[237.19,8.52],[235.86,6.75],[234.27,6.02]],[[212.84,76.5],[212.5,59.5],[211.74,69.5],[210.48,90.08],[208.53,125.5],[206.63,159.58],[205.5,176.93],[204.81,181.12],[203.95,183.56],[203.18,185.98],[202.73,190.13],[202.5,195.5],[206.22,195.81],[209.36,195.65],[210.42,193.81],[211.09,177.78],[212.04,142.5],[212.75,102.9],[212.84,76.5]],[[206,209],[195.82,209.28],[191.5,210],[194.92,210.74],[206,211],[217.08,210.74],[220.5,210],[216.18,209.28],[206,209]],[[205.86,215.72],[183.79,215.5],[178.37,218.41],[172.58,222.55],[166.23,228.5],[160.29,235.76],[156.27,243.19],[153.68,250.66],[151.96,258.09],[150.89,264.79],[149.83,270.5],[148.37,275.16],[146.32,279.34],[144.69,282.17],[144.25,283.58],[147.3,284.15],[154.07,284.97],[173.01,285.68],[205.29,285.98],[237.8,285.68],[256.79,284.92],[263.77,284.03],[266.92,283.42],[266.23,281.75],[264,278.35],[260.66,273.7],[259.87,264.1],[259.05,256.44],[258.15,251.5],[256.85,248.06],[255.05,244],[252.96,239.81],[250.98,236.07],[248.08,232.07],[243.79,227.28],[238.5,222.61],[233.21,218.93],[227.93,215.94],[205.86,215.72]],[[156.85,278.42],[154.78,278.35],[153.53,278.95],[153.45,279.83],[154.19,280.46],[157.32,281.08],[163,281.96],[173.19,282.99],[187.17,283.97],[203.88,284.41],[220.67,283.98],[234.91,283.01],[245.5,281.96],[251.42,280.91],[254.43,279.94],[254.97,279.17],[254.93,278.6],[251.4,278.77],[243.5,279.76],[228.64,280.99],[205,281.42],[182.42,281.13],[168.5,280.22],[161.36,279.17],[156.85,278.42]]]: input);
input_width = points_array[0][0];
input_height= points_array[0][1];
sTrace = dispo_width/input_width;
//stencil_height = input_height*sTrace + 2*margin;

$fn=100;
// preview[view:south, tilt:top]

ornament();

module ornament(height = 3)
{
    {
        union()
        {
            if(includeGimbal == "yes")
            {
                ring1();
                ring2();
                ring3();
            }

            difference()
            {
                color("blue")
                pattern(height);

                clipOversizedImages(center=true);
            }
        }
    }
}

module pattern(height)
{
    union()
    {
    	scale([sTrace, -sTrace, 1])
    	{
    		union()
    		{
    		    coin(height=height);
			}
		}
	}
}

module clipOversizedImages()
{
	difference()
	{
		cylinder(r=200, h=10, center=true);
		cylinder(r=11, h=11, center=true);
	}
}

module ring1()
{
	difference()
	{
//TODO: MAKE ALL THE HIGHT VALUES 5 AS A VARIABLE!!!!
//    	cylinder(r=19.35, h=15, center=true);
    	cylinder(r=19.35, h=3, center=true);

    	cylinder(r=17.35, h=56, center=true);
    	translate([17.45,0,0]) rotate([0,90,0]) cylinder(r1=1.7, r2=0, h=2.1, center=true);
    	translate([-17.45,0,0]) rotate([0,270,0]) cylinder(r1=1.7, r2=0, h=2.1, center=true);
	}
}

module ring2()
{
	translate([16.95,0,0]) rotate([0,90,0]) cylinder(r1=1.7, r2=0, h=2.1, center=true);
	translate([-16.95,0,0]) rotate([0,270,0]) cylinder(r1=1.7, r2=0, h=2.1, center=true);
	difference()
	{
		cylinder(r=15.95, h=3, center=true);
		cylinder(r=13.95, h=56, center=true);
		translate([0,-14.2,0]) rotate([90,0,0]) cylinder(r1=1.7, r2=0, h=2.1, center=true);
		translate([0,14.2,0]) rotate([270,0,0]) cylinder(r1=1.7, r2=0, h=2.1, center=true);
	}
}

module ring3()
{
	translate([0,13.75,0]) rotate([270,0,0]) cylinder(r1=1.7, r2=0, h=2.1, center=true);
	translate([0,-13.75,0]) rotate([90,0,0]) cylinder(r1=1.7, r2=0, h=2.1, center=true);
	difference()
	{
		cylinder(r=12.75, h=3, center=true);
		cylinder(r=10.75, h=56, center=true);
	}
}

// Ths OpenSCAD script is a direvative of:
// Customizable Gimbal v1.0
// by TheNewHobbyist 2014 (http://thenewhobbyist.com)
// http://www.thingiverse.com/thing:340948
// https://github.com/thenewhobbyist/OpenSCAD/tree/master/Customizable%20Gimble
//
// "Customizable Gimbal" as well as this script are licensed under a
// Creative Commons Attribution-NonCommercial 3.0 Unported License.
//
// "Customizable Gimbal" Description:
// This model was insirped by DesignMakeTeach's print in place gimbal designs
// on Thingiverse. Below I have linked an example. I personalized one of these
// for myself and thought I'd make it a full on Customizer model. To do this
// I recreated something similar to DesignMakeTeach's design in OpenSCAD and
// used the Stencil-o-Matic from Benjamin to add in some easy customization.
//
// TheNewHobbyist's Inspiration and attribution from:
//
// Printrbot Gimbal by DesignMakeTeach
// http://www.thingiverse.com/thing:317778
// Licensed under the Creative Commons - Attribution - Share Alike license.
//
// Stencil-o-Matic by Benjamin
// http://www.thingiverse.com/thing:55821
// Licensed under the Creative Commons - Attribution - Non-Commercial license.

// Coin and pendant features were added by Roberto Marquez - http://electronics.onebeartoe.org/

use <spur/spurs-rotated/spurs-rotated.scad>;

/* [Dimensions] */

height = 3;

// Paste your Sencil-o-Matic code here
input ="default_TNH";

// Move image left/right
Move_X = 0; // [-50:50]

// Move image up/down
Move_Y = 0; // [-50:50]

// Resize your image
image_size = 26.5; // [1:50]

includeGimbal = "yes"; // [yes, no]

/* [Hidden] */

  ///////////////////////////
 // Stencil-o-Matic Stuff //
///////////////////////////

stencil_thickness = 5;
offX = 0;
offY = 0;
margin = 0;
dispo_width = image_size;

points_array = (input=="default_TNH"? [[133,286],[[234.27,6.02],[231.55,7.45],[227.5,10.88],[222.85,15.67],[218.69,20.35],[214.95,25.17],[211.32,30.24],[208.44,34.98],[206.52,39],[205.31,48.23],[204.14,65.5],[202.43,96.43],[199.95,138.5],[197.65,174.91],[196.37,192.25],[195.44,195.38],[192.95,196],[190.58,196.5],[189.09,197.84],[188.55,199.75],[188.65,201.77],[188.28,204.15],[185.74,207.18],[181.17,210.7],[175.06,214.5],[168.61,218.79],[163.29,223.5],[159.05,228.64],[155.24,233.98],[152.19,239.17],[149.77,243.98],[148.11,250.02],[146.97,258.66],[145.84,267.33],[144.06,272.66],[141.97,276.16],[139.87,279.16],[138.4,281.78],[138.36,284.3],[139.83,286.58],[143.12,288.43],[150.09,289.9],[162.38,291.02],[181.28,291.67],[205.5,291.95],[229.79,291.67],[248.86,291],[261.56,289.87],[267.86,288.28],[270.76,286.27],[271.82,283.7],[271.26,280.36],[268.97,275.96],[266.18,270.14],[264.49,261.76],[263.22,253.76],[262.03,247.53],[260.34,242.46],[257.87,237.27],[254.58,232.07],[250.91,227.01],[246.01,222],[239.74,216.91],[233.89,213.03],[230,210.88],[227.72,209.34],[225.75,206.9],[224.51,204.05],[224,201.5],[223.82,199.39],[223.39,197.58],[222.07,196.41],[219.45,196],[216.94,195.74],[215.57,195.11],[215.61,179.54],[216.5,143.36],[217.84,100.02],[218.98,67.24],[219.99,41.97],[223.5,34.86],[227.01,28.44],[230.51,22.99],[232.97,19.44],[234,17.58],[234.64,16.25],[236.17,13.98],[237.73,11.12],[237.19,8.52],[235.86,6.75],[234.27,6.02]],[[212.84,76.5],[212.5,59.5],[211.74,69.5],[210.48,90.08],[208.53,125.5],[206.63,159.58],[205.5,176.93],[204.81,181.12],[203.95,183.56],[203.18,185.98],[202.73,190.13],[202.5,195.5],[206.22,195.81],[209.36,195.65],[210.42,193.81],[211.09,177.78],[212.04,142.5],[212.75,102.9],[212.84,76.5]],[[206,209],[195.82,209.28],[191.5,210],[194.92,210.74],[206,211],[217.08,210.74],[220.5,210],[216.18,209.28],[206,209]],[[205.86,215.72],[183.79,215.5],[178.37,218.41],[172.58,222.55],[166.23,228.5],[160.29,235.76],[156.27,243.19],[153.68,250.66],[151.96,258.09],[150.89,264.79],[149.83,270.5],[148.37,275.16],[146.32,279.34],[144.69,282.17],[144.25,283.58],[147.3,284.15],[154.07,284.97],[173.01,285.68],[205.29,285.98],[237.8,285.68],[256.79,284.92],[263.77,284.03],[266.92,283.42],[266.23,281.75],[264,278.35],[260.66,273.7],[259.87,264.1],[259.05,256.44],[258.15,251.5],[256.85,248.06],[255.05,244],[252.96,239.81],[250.98,236.07],[248.08,232.07],[243.79,227.28],[238.5,222.61],[233.21,218.93],[227.93,215.94],[205.86,215.72]],[[156.85,278.42],[154.78,278.35],[153.53,278.95],[153.45,279.83],[154.19,280.46],[157.32,281.08],[163,281.96],[173.19,282.99],[187.17,283.97],[203.88,284.41],[220.67,283.98],[234.91,283.01],[245.5,281.96],[251.42,280.91],[254.43,279.94],[254.97,279.17],[254.93,278.6],[251.4,278.77],[243.5,279.76],[228.64,280.99],[205,281.42],[182.42,281.13],[168.5,280.22],[161.36,279.17],[156.85,278.42]]]: input);
input_width = points_array[0][0];
input_height= points_array[0][1];
sTrace = dispo_width/input_width;
//stencil_height = input_height*sTrace + 2*margin;

$fn=100;
// preview[view:south, tilt:top]

ornament();

module ornament()
{
    {
        union()
        {
            if(includeGimbal == "yes")
            {
                ring1();
                ring2();
                ring3();
            }

            difference()
            {
                color("blue")
                pattern();

                clipOversizedImages(center=true);
            }
        }
    }
}

module pattern()
{
    union()
    {
    	scale([sTrace, -sTrace, 1])
    	{
    		union()
    		{
    		    coin(height=height);
			}
		}
	}
}

module clipOversizedImages()
{
	difference()
	{
		cylinder(r=200, h=10, center=true);
		cylinder(r=11, h=11, center=true);
	}
}

module ring1()
{
	difference()
	{
//TODO: MAKE ALL THE HIGHT VALUES 5 AS A VARIABLE!!!!
//    	cylinder(r=19.35, h=15, center=true);
    	cylinder(r=19.35, h=3, center=true);

    	cylinder(r=17.35, h=56, center=true);
    	translate([17.45,0,0]) rotate([0,90,0]) cylinder(r1=1.7, r2=0, h=2.1, center=true);
    	translate([-17.45,0,0]) rotate([0,270,0]) cylinder(r1=1.7, r2=0, h=2.1, center=true);
	}
}

module ring2()
{
	translate([16.95,0,0]) rotate([0,90,0]) cylinder(r1=1.7, r2=0, h=2.1, center=true);
	translate([-16.95,0,0]) rotate([0,270,0]) cylinder(r1=1.7, r2=0, h=2.1, center=true);
	difference()
	{
		cylinder(r=15.95, h=3, center=true);
		cylinder(r=13.95, h=56, center=true);
		translate([0,-14.2,0]) rotate([90,0,0]) cylinder(r1=1.7, r2=0, h=2.1, center=true);
		translate([0,14.2,0]) rotate([270,0,0]) cylinder(r1=1.7, r2=0, h=2.1, center=true);
	}
}

module ring3()
{
	translate([0,13.75,0]) rotate([270,0,0]) cylinder(r1=1.7, r2=0, h=2.1, center=true);
	translate([0,-13.75,0]) rotate([90,0,0]) cylinder(r1=1.7, r2=0, h=2.1, center=true);
	difference()
	{
		cylinder(r=12.75, h=3, center=true);
		cylinder(r=10.75, h=56, center=true);
	}
}


Added traffic lights model

Added traffic lights model

$fs=0.2; // default 2
$fa=3; // default 12

//pole();
light_holder();
module light_holder() {
  module single() {
    cylinder(d=7, h=5);
  }
  module single_hole() {
    cylinder(d=5, h=30, center=true);
    translate([-1,0,54]) cube([5,100,100],true);
  }
  difference() {
    union() {
      hull() {
        translate([0,0,0]) cylinder(d=7, h=4);;
        translate([14,0,0]) cylinder(d=7, h=4);;
      }
      translate([0,0,0]) single();
      translate([7,0,0]) single();
      translate([14,0,0]) single();
    }
    union() {
      translate([0,0,0]) single_hole();
      translate([7,0,0]) single_hole();
      translate([14,0,0]) single_hole();
    }
  }
  difference() {
    union() {
      translate([3.5,0,-3.5]) cube([0.8,7,7],true);
      translate([10.5,0,-3.5]) cube([0.8,7,7],true);
    }
    translate([0,0,-6]) cube([100,4,10],true);
  }

}

module head() {
  //cube([10,12,24],true);
  module outer() {
    hull() {
      translate([0,0,0]) cylinder(d=10, h=12);
      translate([14,0,0]) cylinder(d=10, h=12);
    }
  }
  module inner() {
    translate([0,0,1]) hull() {
      translate([0,0,0]) cylinder(d=7, h=12);
      translate([14,0,0]) cylinder(d=7, h=12);
    }
  }
  rotate([0,-90,0]) difference() {
    outer();
    inner();
  }
}
module pole() {

  difference() {
    union() {
      translate([0,0,-6]) cylinder(d=10,h=6);
      translate([0,0,0]) cylinder(d1=14,d2=6,h=10);
      translate([0,0,10]) cylinder(d=6,h=60);
      translate([5,0,73]) head();
    }
    cylinder(d=4,h=170,center=true);
  }
}

error: pathspec 'small/traffic_lights_model.scad' did not match any file(s) known to git


base a funciones

base a funciones

DIAMETER_BASE = 6;
BORDER_RADIUS_BASE = 0.3;

HEIGHT_BODY = 44.5;
GREY = "LightGrey";

module base()
{
    base_cylinder();
    base_border();
}

module base_cylinder()
{
    color(GREY)
        translate([0,0,-(HEIGHT_BODY + BORDER_RADIUS_BASE)])
            cylinder(
                h = BORDER_RADIUS_BASE,
                d = (DIAMETER_BASE - (2 * BORDER_RADIUS_BASE)),
                $fn = 100);
}

module base_border()
{
    color(GREY)
        translate([0,0,-(HEIGHT_BODY)])
            rotate_extrude(convexity = 10, $fn = 100)
                translate([(DIAMETER_BASE/2)-BORDER_RADIUS_BASE, 0, 0])
                    circle(r = BORDER_RADIUS_BASE, $fn = 100);
}

base();

DIAMETER_BASE = 6;
BORDER_RADIUS_BASE = 0.3;

HEIGHT_BODY = 44.5;
GREY = "LightGrey";

module base()
{
   //Base cylinder
color(GREY)
translate([0,0,-(HEIGHT_BODY + BORDER_RADIUS_BASE)])
    cylinder(
        h = BORDER_RADIUS_BASE,
        d = (DIAMETER_BASE - (2 * BORDER_RADIUS_BASE)),
        $fn = 100);

//Base shoulder
color(GREY)
translate([0,0,-(HEIGHT_BODY)])
    rotate_extrude(convexity = 10, $fn = 100)
    translate([(DIAMETER_BASE/2)-BORDER_RADIUS_BASE, 0, 0])
        circle(r = BORDER_RADIUS_BASE, $fn = 100);

}
base();


foot cube - main

foot cube - main

module bed_foot()
{
  h=60;
  d=52;
  cylinder(d=d, h=h, $fn=200);
}

bed_foot();

error: pathspec 'bed_foot/bed_foot.scad' did not match any file(s) known to git


moved back to 1, single shlef, but longer + extra 0.5mm for mount tolerance


parameterize scale values

parameterize scale values

outerRadius = 15;       // [10 : 60]
squareLength = 20;      // [10 : 30]
xScale = 0.5;           // [0.1 : 0.1 : 2.0]
yScale = 0.7;           // [0.1 : 0.1 : 2.0]

use <../lamp-shade.scad>

lampShade(outerRadius = outerRadius,
          squareLength = squareLength,
          xScale = xScale,
          yScale = yScale);

outerRadius = 15;
squareLength = 20;
xScale = 0.5;

use <../lamp-shade.scad>

lampShade(outerRadius = outerRadius,
          squareLength = squareLength,
          xScale = xScale);


'fleshing out' arm

'fleshing out' arm

use <StepMotor_28BYJ-48.scad>;
use <Hub_28BYJ-48.scad>;
include <Bearing_6807-2RS.scad>;

// global rendering parameters
$fn = 24;

// library examples
// translate([100, 100, 10]) { StepMotor28BYJ(); }
// stepperHub(10, 7, 6, 3.1, 1.5, 2.75);
//translate([0, 0, 8]) bearing6807_2RS();
// bearingInnerStep(bearing6807_2RS_d - iFitAdjust, 2, 2);
//shoulderBase(2, 55, 9.1, 3.1);

// interference fit adjustment for 3D printer
iFitAdjust = .4;

// shoulder base parameters
shoulderBaseHeight = 3;
shoulderBaseDiameter = 55;
shaftBossDiameter = 10;
mountScrewDiameter = 3.1;
bearingStep = 2; // size in mm of bearing interface step
// joint parameters
hubHeight = 10;
hubRadius = 7;
shaftHeight = 6;
shaftRadius = 3.1;
setScrewRadius = 1.5;
setScrewHeight = 2.75;
spokeWidth = 3;
spokes = 6;
screwTabs = 4;
screwTabHeight = 4;
armLength = 100;
// misc
baseDeckExtension = 50;
boundingBox = 8;
boundingBoxHalf = boundingBox / 2;
// 8 is distance from shaft center to screw center on x axis
// 35 is screw center to screw center on y axis
shaftCenterToMountHoldCenterXAxis = 8;
mountHoleCenterToMountHoleCenter = 35;
leadScrewDiameter = 8;
// forearm
forearmLength = 75;

/* Pieces in this model
** Shoulder:
*** Base plate
*** Top plate
*** Lower arm
*** Upper arm
** Forearm:
*** ?
** Hand:
*** ?
*/

// shoulder base
color([.7, .7, 1])
    shoulderBase(shoulderBaseHeight, shoulderBaseDiameter, shaftBossDiameter, mountScrewDiameter);
// shoulder stepper
rotate([0, 180, 0])
    translate([-8, 0, 10])
        StepMotor28BYJ();
// lower shoulder bearing
translate([0, 0, shoulderBaseHeight + bearingStep])
    %bearing6807_2RS();
// shoulder top
color([.6, .6, .9])
    translate([0, 0, 2 * shoulderBaseHeight + (4 * bearing6807_2RS_B) + (8 * bearingStep)])
    rotate([180, 0, 0])
        shoulderBase(shoulderBaseHeight, shoulderBaseDiameter, shaftBossDiameter, mountScrewDiameter);
// upper shoulder bearing
translate([0, 0, shoulderBaseHeight + (3 * bearing6807_2RS_B) + (7 * bearingStep)])
    %bearing6807_2RS();
// lower arm including the shoulder - arm joint
//render()
color([1, .7, .7])
    translate([0, 0, shoulderBaseHeight + bearing6807_2RS_B])
        armLower(bearing6807_2RS_D + iFitAdjust, bearingStep, bearingStep, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, screwTabs, screwTabHeight, armLength);
// upper arm
//render()
color([.9, .7, .7])
    translate([0, 0, shoulderBaseHeight + ( 2*bearing6807_2RS_B) + (12 * bearingStep) - (.5 * bearingStep)])
        rotate([180, 0, 0])
            armLower(bearing6807_2RS_D + iFitAdjust, bearingStep, bearingStep, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, screwTabs, screwTabHeight, armLength);
// elbow joint pieces
// lower bearing
translate([-armLength, 0, shoulderBaseHeight + bearing6807_2RS_B + bearingStep])
    %bearing6807_2RS();
// arm stepper
rotate([0, 180, 0])
    translate([armLength - 8, 0, bearingStep * 2])
        StepMotor28BYJ();
// forearm pieces
// lower
color([.1, .7, .1])
translate([-armLength, 0, shoulderBaseHeight + (bearing6807_2RS_B * 2) + (4 *bearingStep)])
//translate([-armLength, 0, shoulderBaseHeight + (bearing6807_2RS_B * 2) + (14 *bearingStep)])
    forearmLower(bearing6807_2RS_d - iFitAdjust, bearing6807_2RS_D + iFitAdjust, bearingStep, bearingStep, hubHeight + (bearing6807_2RS_B / 2) + (bearingStep/2), hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, forearmLength, boundingBox);
// upper
color([.2, .8, .2])
translate([-armLength, 0, shoulderBaseHeight + (bearing6807_2RS_B * 2) + (4 *bearingStep)])
//translate([-armLength, 0, shoulderBaseHeight + (bearing6807_2RS_B * 2) + (14 *bearingStep)])
    rotate([180, 0, 0])
    forearmLower(bearing6807_2RS_d - iFitAdjust, bearing6807_2RS_D + iFitAdjust, bearingStep, bearingStep, hubHeight + (bearing6807_2RS_B / 2) + (bearingStep/2), hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, forearmLength, boundingBox);
// forearm upper bearing
translate([-armLength, 0, shoulderBaseHeight + (2 * bearing6807_2RS_B) + (7 * bearingStep)])
    %bearing6807_2RS();
/*
deprecated
render()
    translate([-armLength, 0, shoulderBaseHeight + bearing6807_2RS_B + (2* bearingStep)])
        armJointSpacer(bearing6807_2RS_d - iFitAdjust, bearing6807_2RS_D + iFitAdjust, bearingStep, shaftBossDiameter, mountScrewDiameter);
*/

//bearingInnerStep(bearing6807_2RS_d - iFitAdjust, 2, 2);
module bearingInnerStep(bearingID, stepHeight, stepWidth) {
    difference() {
        union() {
            // this fits inside of the bearing
            cylinder(h = stepHeight * 2, d = bearingID);
            // this rests on the bearing inner lip
            cylinder(h = stepHeight, d = bearingID + stepWidth);
        }
        // remove center
        cylinder(h = stepHeight * 2, d = bearingID - (stepWidth * 2));
    }
}

//translate([0, 0, 12]) bearingOuterStep(bearing6807_2RS_D + iFitAdjust, 2, 2);
module bearingOuterStep(bearingOD, stepHeight, stepWidth) {
    //render(convexivity = 3)
    difference() {
        cylinder(h = stepHeight * 2, d = bearingOD + stepWidth);
        cylinder(h = stepHeight * 2, d = bearingOD - stepWidth);
        cylinder(h = stepHeight, d = bearingOD);
    }
}

// armJointSpacer(bearing6807_2RS_D - iFitAdjust, bearing6807_2RS_D + iFitAdjust, bearingStep, shaftBossDiameter, mountScrewDiameter);
module armJointSpacer(bearingID, bearingOD, bearingStep, shaftBossDiameter, mountScrewDiameter) {
    union() {
        difference() {
            cylinder(h = bearingStep * 2, d = bearingOD + bearingStep);
            cylinder(h = bearingStep * 2, d = bearingID);
        }
        translate([0, 0, bearingStep * 2])
                bearingInnerStep(bearingID, bearingStep, bearingStep);
        // screw holes for joining to arm
        radial_array(vec = [0, 0, 1], n = screwTabs)
                translate([bearingOD / 2 + (setScrewRadius * 2), 0, (2 * bearingStep) - screwTabHeight])
                    difference() {
                        union () {
                            cylinder(h = screwTabHeight, r = setScrewRadius * 2);
                            translate([-2 * setScrewRadius, - 2 * setScrewRadius, 0])
                                cube([setScrewRadius * 2, 4 * setScrewRadius, screwTabHeight], center = false);
                        }
                        cylinder(h = screwTabHeight, r = setScrewRadius);
                    }
    }
}

//shoulderBase(2, 55, 9.1, 3.1);
// WARNING: has some hard-coded non-parametric values in here!
module shoulderBase(shoulderBaseHeight, shoulderBaseDiameter, shaftBossDiameter, mountScrewDiameter) {
    mountHoleDepth = shoulderBaseHeight;

    //render(convexivity = 3)
    difference() {
        union () {
            cylinder(h = shoulderBaseHeight, d = shoulderBaseDiameter);
            translate([0, 0, shoulderBaseHeight])
                bearingInnerStep(bearing6807_2RS_d - iFitAdjust, bearingStep, bearingStep);
            // 40 is the length of deck extension from the baseplate in x
            translate([0, -shoulderBaseDiameter / 2, 0])
                cube([baseDeckExtension, shoulderBaseDiameter, shoulderBaseHeight], center = false);
        }
        // motor shaft hole
        cylinder(h = shoulderBaseHeight + (bearingStep * 2), d = shaftBossDiameter);
        // mounting holes

        translate([shaftCenterToMountHoldCenterXAxis, mountHoleCenterToMountHoleCenter/2, 0])
            cylinder(h = mountHoleDepth, d = mountScrewDiameter);
        translate([shaftCenterToMountHoldCenterXAxis, -mountHoleCenterToMountHoleCenter/2, 0])
            cylinder(h = mountHoleDepth, d = mountScrewDiameter);
        // lead screw hole
        translate([baseDeckExtension - (leadScrewDiameter * 1.5), 0, 0])
            cylinder(h = shoulderBaseHeight, d = leadScrewDiameter + (leadScrewDiameter / 2));
    }
    // NOTE: need to add LM8UU mounts
}

module armLower(bearingOD, stepHeight, stepWidth, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, screwTabs, screwTabHeight, armLength) {
    armWidth = bearingOD / 2;
    //render(convexivity = 3)
    difference() {
    union() {
        armInnerJoint(bearingOD, bearingStep, bearingStep, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, screwTabs, screwTabHeight);
        translate([-armLength, 0, 0])
            armOuterJointBase(bearingOD, bearingStep, setScrewRadius, screwTabs, screwTabHeight);
        difference() {
            translate([-armLength, -armWidth / 2, 0])
                cube([armLength, armWidth, bearingStep * 2], center=false);
            cylinder(h = bearingStep * 2, d = bearingOD);
            translate([-armLength, 0, 0])
                cylinder(h = bearingStep * 2, d = bearingOD);
            translate([-armLength + (bearingOD / 2) + (boundingBox / 2), -(armWidth / 2) + boundingBoxHalf, 0])
                cube([armLength - bearingOD - (boundingBox + boundingBoxHalf), armWidth - boundingBox, bearingStep * 2], center = false);
        }
        difference() {
            intersection() {

                translate([-armLength + (bearingOD / 2) + (boundingBox / 2), -(armWidth / 2) + boundingBoxHalf, 0])
                    cube([armLength - bearingOD - boundingBox, armWidth - boundingBox, bearingStep * 2], center = false);
                for (i = [ bearingOD / 2 - boundingBoxHalf: armWidth : armLength]) {
                    translate([ -i, 0, bearingStep])
                        rotate([0, 0, 45])
                            cube([spokeWidth, armWidth + boundingBoxHalf, bearingStep * 2], center = true);
                    translate([ -i, 0, bearingStep])
                        rotate([0, 0, -45])
                            cube([spokeWidth, armWidth + boundingBoxHalf, bearingStep * 2], center = true);
                }
            }

        }
   }
           // screw holes for joining to upper
        radial_array(vec = [0, 0, 1], n = screwTabs)
                translate([bearingOD / 2 + (setScrewRadius * 2), 0, (2 * stepHeight) - screwTabHeight])
                       cylinder(h = screwTabHeight, r = setScrewRadius);
   }
}

module armOuterJointBase(bearingOD, bearingStep, setScrewRadius, screwTabs, screwTabHeight) {
    mountHoleDepth = bearingStep * 2;

    union() {
        difference() {
            union() {
                translate([0, 0, -(bearingStep * 2)])
                    cylinder(h = bearingStep * 2, d = bearingOD + bearingStep);
                translate([0, 0, bearingStep * 2])
                    rotate([0, 180, 0])
                        bearingOuterStep(bearingOD, bearingStep, bearingStep);
            }
            // motor shaft hole
            translate([0, 0, -(bearingStep * 2)])
                cylinder(h = shoulderBaseHeight + (bearingStep * 2), d = shaftBossDiameter);
            // mounting holes
            translate([0, 0, -(bearingStep * 2)]) {
                translate([shaftCenterToMountHoldCenterXAxis, mountHoleCenterToMountHoleCenter/2, 0])
                cylinder(h = mountHoleDepth, d = mountScrewDiameter);
                translate([shaftCenterToMountHoldCenterXAxis, -mountHoleCenterToMountHoleCenter/2, 0])
                cylinder(h = mountHoleDepth, d = mountScrewDiameter);
            }
        }

    }
}

//armInnerJoint(bearing6807_2RS_D + iFitAdjust, bearingStep, bearingStep, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, screwTabs, screwTabHeight);
module armInnerJoint(bearingOD, stepHeight, stepWidth, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, screwTabs, screwTabHeight) {
    //translate([0, 0, hubHeight - (2 * stepHeight)])
    difference() {
        union() {
         difference() {
            cylinder(h = bearingStep * 2, d = bearingOD + (setScrewRadius * 6));
            cylinder(h = bearingStep * 2, d = bearingOD);
//            translate([0, -bearingOD, 0])
//                cube([bearingOD, bearingOD * 2, bearingStep * 2]);
        }
        bearingOuterStep(bearingOD, stepHeight, stepWidth);
        // hub
        translate([0, 0, -(hubHeight - (2 * stepHeight))])
            stepperHub(hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight);
        // spokes
        radial_array(vec=[0, 0, 1], n = spokes)
                translate([hubRadius - (stepWidth / 2), -(spokeWidth / 2), stepHeight])
                    cube([(bearingOD / 2) - hubRadius, spokeWidth, stepHeight], center = false);
        // screw tabs for joining to upper
        radial_array(vec = [0, 0, 1], n = screwTabs)
                translate([bearingOD / 2 + (setScrewRadius * 2), 0, (2 * stepHeight) - screwTabHeight])

                        union () {
                            cylinder(h = screwTabHeight, r = setScrewRadius * 2);
                            translate([-2 * setScrewRadius, - 2 * setScrewRadius, 0])
                                cube([setScrewRadius * 2, 4 * setScrewRadius, screwTabHeight], center = false);
                        }

                    }
        // screw holes for joining to upper
        radial_array(vec = [0, 0, 1], n = screwTabs)
                translate([bearingOD / 2 + (setScrewRadius * 2), 0, (2 * stepHeight) - screwTabHeight])
                       cylinder(h = screwTabHeight, r = setScrewRadius);
    }
}

module forearmLower(bearingID, bearingOD, stepHeight, stepWidth, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, forearmLength, boundingBox) {
    armWidth = bearingOD / 2;

    rotate([180, 0, 0]) union() {
        boundingBoxHalf = boundingBox / 2;
        difference() {
            cylinder(h = bearingStep * 2, d = bearingOD + bearingStep);
            cylinder(h = bearingStep * 2, d = bearingID - (2 * bearingStep));
        }
        translate([0, 0, bearingStep * 2])
            bearingInnerStep(bearingID, bearingStep, bearingStep);
        // screw holes for joining to arm
        radial_array(vec = [0, 0, 1], n = screwTabs)
                translate([bearingOD / 2 + (setScrewRadius * 2), 0, (2 * bearingStep) - screwTabHeight])
                    difference() {
                        union () {
                            cylinder(h = screwTabHeight, r = setScrewRadius * 2);
                            translate([-2 * setScrewRadius, - 2 * setScrewRadius, 0])
                                cube([setScrewRadius * 2, 4 * setScrewRadius, screwTabHeight], center = false);
                        }
                        cylinder(h = screwTabHeight, r = setScrewRadius);
                    }
        // hub
        translate([0, 0, hubHeight]) rotate([180, 0, 0])
            stepperHub(hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight);
        // spokes
        radial_array(vec=[0, 0, 1], n = spokes)
                translate([hubRadius - (stepWidth / 2), -(spokeWidth / 2), 0])
                    cube([(bearingOD / 2) - hubRadius, spokeWidth, 2 *stepHeight], center = false);
        // forearm extension
             difference() {
            translate([-forearmLength, -armWidth / 2, 0])
                cube([forearmLength, armWidth, bearingStep * 2], center=false);
            cylinder(h = bearingStep * 2, d = bearingOD);
            translate([-forearmLength, 0, 0])
                cylinder(h = bearingStep * 2, d = bearingOD / 2);
                 // 4 on next line comes from dividing the bearingOD on the above line
            translate([-forearmLength + (bearingOD / 4) + (boundingBox / 2), -(armWidth / 2) + boundingBoxHalf, 0])
                cube([forearmLength - (bearingOD/2) - (boundingBox + boundingBoxHalf), armWidth - boundingBox, bearingStep * 2], center = false);
        }

            intersection() {

                translate([-forearmLength + boundingBox * 2, -(armWidth / 2) + boundingBoxHalf, 0])
                    cube([forearmLength - (bearingOD / 2) - boundingBox, armWidth - boundingBox, bearingStep * 2], center = false);
                for (i = [ bearingOD / 2 - boundingBoxHalf: armWidth : forearmLength]) {
                    translate([ -i, 0, bearingStep])
                        rotate([0, 0, 45])
                            cube([spokeWidth, armWidth + boundingBoxHalf, bearingStep * 2], center = true);
                    translate([ -i, 0, bearingStep])
                        rotate([0, 0, -45])
                            cube([spokeWidth, armWidth + boundingBoxHalf, bearingStep * 2], center = true);
                }
            }

    }
}

module copy_mirror(vec=[0,1,0]) {
    children();
    mirror(vec)
        children();
}

module radial_array(vec = [0,0,1], n = 4) {
    for ( i = [0 : n - 1] )
    {
        rotate( i * 360 / n, vec)
            children();
    }
}

use <StepMotor_28BYJ-48.scad>;
use <Hub_28BYJ-48.scad>;
include <Bearing_6807-2RS.scad>;

// global rendering parameters
$fn = 24;

// library examples
// translate([100, 100, 10]) { StepMotor28BYJ(); }
// stepperHub(10, 7, 6, 3.1, 1.5, 2.75);
//translate([0, 0, 8]) bearing6807_2RS();
// bearingInnerStep(bearing6807_2RS_d - iFitAdjust, 2, 2);
//shoulderBase(2, 55, 9.1, 3.1);

// interference fit adjustment for 3D printer
iFitAdjust = .4;

// shoulder base parameters
shoulderBaseHeight = 3;
shoulderBaseDiameter = 55;
shaftBossDiameter = 10;
mountScrewDiameter = 3.1;
bearingStep = 2; // size in mm of bearing interface step
// joint parameters
hubHeight = 10;
hubRadius = 7;
shaftHeight = 6;
shaftRadius = 3.1;
setScrewRadius = 1.5;
setScrewHeight = 2.75;
spokeWidth = 3;
spokes = 6;
screwTabs = 4;
screwTabHeight = 4;
armLength = 100;
// misc
baseDeckExtension = 50;
boundingBox = 8;
boundingBoxHalf = boundingBox / 2;
// 8 is distance from shaft center to screw center on x axis
// 35 is screw center to screw center on y axis
shaftCenterToMountHoldCenterXAxis = 8;
mountHoleCenterToMountHoleCenter = 35;
leadScrewDiameter = 8;
// forearm
forearmLength = 75;

/* Pieces in this model
** Shoulder:
*** Base plate
*** Top plate
*** Lower arm
*** Upper arm
** Forearm:
*** ?
** Hand:
*** ?
*/

// shoulder base
color([.7, .7, 1])
    shoulderBase(shoulderBaseHeight, shoulderBaseDiameter, shaftBossDiameter, mountScrewDiameter);
// shoulder stepper
rotate([0, 180, 0])
    translate([-8, 0, 10])
        StepMotor28BYJ();
// lower shoulder bearing
translate([0, 0, shoulderBaseHeight + bearingStep])
    %bearing6807_2RS();
// lower arm including the shoulder - arm joint
render()
color([1, .7, .7])
    translate([0, 0, shoulderBaseHeight + bearing6807_2RS_B])
        armLower(bearing6807_2RS_D + iFitAdjust, bearingStep, bearingStep, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, screwTabs, screwTabHeight, armLength);
// upper arm
//render()
color([.9, .7, .7])
    translate([0, 0, shoulderBaseHeight + ( 2*bearing6807_2RS_B) + (12 * bearingStep) - (.5 * bearingStep)])
        rotate([180, 0, 0])
            armLower(bearing6807_2RS_D + iFitAdjust, bearingStep, bearingStep, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, screwTabs, screwTabHeight, armLength);
// elbow joint pieces
// lower bearing
translate([-armLength, 0, shoulderBaseHeight + bearing6807_2RS_B + bearingStep])
    %bearing6807_2RS();
// arm stepper
rotate([0, 180, 0])
    translate([armLength - 8, 0, bearingStep * 2])
        StepMotor28BYJ();
// forearm pieces
// lower
color([.1, .7, .1])
translate([-armLength, 0, shoulderBaseHeight + (bearing6807_2RS_B * 2) + (4 *bearingStep)])
//translate([-armLength, 0, shoulderBaseHeight + (bearing6807_2RS_B * 2) + (14 *bearingStep)])
    forearmLower(bearing6807_2RS_d - iFitAdjust, bearing6807_2RS_D + iFitAdjust, bearingStep, bearingStep, hubHeight + (bearing6807_2RS_B / 2) + (bearingStep/2), hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, forearmLength, boundingBox);
// upper
color([.2, .8, .2])
translate([-armLength, 0, shoulderBaseHeight + (bearing6807_2RS_B * 2) + (4 *bearingStep)])
//translate([-armLength, 0, shoulderBaseHeight + (bearing6807_2RS_B * 2) + (14 *bearingStep)])
    rotate([180, 0, 0])
    forearmLower(bearing6807_2RS_d - iFitAdjust, bearing6807_2RS_D + iFitAdjust, bearingStep, bearingStep, hubHeight + (bearing6807_2RS_B / 2) + (bearingStep/2), hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, forearmLength, boundingBox);
// forearm upper bearing
translate([-armLength, 0, shoulderBaseHeight + (2 * bearing6807_2RS_B) + (7 * bearingStep)])
    %bearing6807_2RS();
/*
deprecated
render()
    translate([-armLength, 0, shoulderBaseHeight + bearing6807_2RS_B + (2* bearingStep)])
        armJointSpacer(bearing6807_2RS_d - iFitAdjust, bearing6807_2RS_D + iFitAdjust, bearingStep, shaftBossDiameter, mountScrewDiameter);
*/

//bearingInnerStep(bearing6807_2RS_d - iFitAdjust, 2, 2);
module bearingInnerStep(bearingID, stepHeight, stepWidth) {
    difference() {
        union() {
            // this fits inside of the bearing
            cylinder(h = stepHeight * 2, d = bearingID);
            // this rests on the bearing inner lip
            cylinder(h = stepHeight, d = bearingID + stepWidth);
        }
        // remove center
        cylinder(h = stepHeight * 2, d = bearingID - (stepWidth * 2));
    }
}

//translate([0, 0, 12]) bearingOuterStep(bearing6807_2RS_D + iFitAdjust, 2, 2);
module bearingOuterStep(bearingOD, stepHeight, stepWidth) {
    //render(convexivity = 3)
    difference() {
        cylinder(h = stepHeight * 2, d = bearingOD + stepWidth);
        cylinder(h = stepHeight * 2, d = bearingOD - stepWidth);
        cylinder(h = stepHeight, d = bearingOD);
    }
}

// armJointSpacer(bearing6807_2RS_D - iFitAdjust, bearing6807_2RS_D + iFitAdjust, bearingStep, shaftBossDiameter, mountScrewDiameter);
module armJointSpacer(bearingID, bearingOD, bearingStep, shaftBossDiameter, mountScrewDiameter) {
    union() {
        difference() {
            cylinder(h = bearingStep * 2, d = bearingOD + bearingStep);
            cylinder(h = bearingStep * 2, d = bearingID);
        }
        translate([0, 0, bearingStep * 2])
                bearingInnerStep(bearingID, bearingStep, bearingStep);
        // screw holes for joining to arm
        radial_array(vec = [0, 0, 1], n = screwTabs)
                translate([bearingOD / 2 + (setScrewRadius * 2), 0, (2 * bearingStep) - screwTabHeight])
                    difference() {
                        union () {
                            cylinder(h = screwTabHeight, r = setScrewRadius * 2);
                            translate([-2 * setScrewRadius, - 2 * setScrewRadius, 0])
                                cube([setScrewRadius * 2, 4 * setScrewRadius, screwTabHeight], center = false);
                        }
                        cylinder(h = screwTabHeight, r = setScrewRadius);
                    }
    }
}

//shoulderBase(2, 55, 9.1, 3.1);
// WARNING: has some hard-coded non-parametric values in here!
module shoulderBase(shoulderBaseHeight, shoulderBaseDiameter, shaftBossDiameter, mountScrewDiameter) {
    mountHoleDepth = shoulderBaseHeight;

    //render(convexivity = 3)
    difference() {
        union () {
            cylinder(h = shoulderBaseHeight, d = shoulderBaseDiameter);
            translate([0, 0, shoulderBaseHeight])
                bearingInnerStep(bearing6807_2RS_d - iFitAdjust, bearingStep, bearingStep);
            // 40 is the length of deck extension from the baseplate in x
            translate([0, -shoulderBaseDiameter / 2, 0])
                cube([baseDeckExtension, shoulderBaseDiameter, shoulderBaseHeight], center = false);
        }
        // motor shaft hole
        cylinder(h = shoulderBaseHeight + (bearingStep * 2), d = shaftBossDiameter);
        // mounting holes

        translate([shaftCenterToMountHoldCenterXAxis, mountHoleCenterToMountHoleCenter/2, 0])
            cylinder(h = mountHoleDepth, d = mountScrewDiameter);
        translate([shaftCenterToMountHoldCenterXAxis, -mountHoleCenterToMountHoleCenter/2, 0])
            cylinder(h = mountHoleDepth, d = mountScrewDiameter);
        // lead screw hole
        translate([baseDeckExtension - (leadScrewDiameter * 1.5), 0, 0])
            cylinder(h = shoulderBaseHeight, d = leadScrewDiameter + (leadScrewDiameter / 2));
    }
    // NOTE: need to add LM8UU mounts
}

module armLower(bearingOD, stepHeight, stepWidth, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, screwTabs, screwTabHeight, armLength) {
    armWidth = bearingOD / 2;
    //render(convexivity = 3)
    difference() {
    union() {
        armInnerJoint(bearingOD, bearingStep, bearingStep, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, screwTabs, screwTabHeight);
        translate([-armLength, 0, 0])
            armOuterJointBase(bearingOD, bearingStep, setScrewRadius, screwTabs, screwTabHeight);
        difference() {
            translate([-armLength, -armWidth / 2, 0])
                cube([armLength, armWidth, bearingStep * 2], center=false);
            cylinder(h = bearingStep * 2, d = bearingOD);
            translate([-armLength, 0, 0])
                cylinder(h = bearingStep * 2, d = bearingOD);
            translate([-armLength + (bearingOD / 2) + (boundingBox / 2), -(armWidth / 2) + boundingBoxHalf, 0])
                cube([armLength - bearingOD - (boundingBox + boundingBoxHalf), armWidth - boundingBox, bearingStep * 2], center = false);
        }
        difference() {
            intersection() {

                translate([-armLength + (bearingOD / 2) + (boundingBox / 2), -(armWidth / 2) + boundingBoxHalf, 0])
                    cube([armLength - bearingOD - boundingBox, armWidth - boundingBox, bearingStep * 2], center = false);
                for (i = [ bearingOD / 2 - boundingBoxHalf: armWidth : armLength]) {
                    translate([ -i, 0, bearingStep])
                        rotate([0, 0, 45])
                            cube([spokeWidth, armWidth + boundingBoxHalf, bearingStep * 2], center = true);
                    translate([ -i, 0, bearingStep])
                        rotate([0, 0, -45])
                            cube([spokeWidth, armWidth + boundingBoxHalf, bearingStep * 2], center = true);
                }
            }

        }
   }
           // screw holes for joining to upper
        radial_array(vec = [0, 0, 1], n = screwTabs)
                translate([bearingOD / 2 + (setScrewRadius * 2), 0, (2 * stepHeight) - screwTabHeight])
                       cylinder(h = screwTabHeight, r = setScrewRadius);
   }
}

module armOuterJointBase(bearingOD, bearingStep, setScrewRadius, screwTabs, screwTabHeight) {
    mountHoleDepth = bearingStep * 2;

    union() {
        difference() {
            union() {
                translate([0, 0, -(bearingStep * 2)])
                    cylinder(h = bearingStep * 2, d = bearingOD + bearingStep);
                translate([0, 0, bearingStep * 2])
                    rotate([0, 180, 0])
                        bearingOuterStep(bearingOD, bearingStep, bearingStep);
            }
            // motor shaft hole
            translate([0, 0, -(bearingStep * 2)])
                cylinder(h = shoulderBaseHeight + (bearingStep * 2), d = shaftBossDiameter);
            // mounting holes
            translate([0, 0, -(bearingStep * 2)]) {
                translate([shaftCenterToMountHoldCenterXAxis, mountHoleCenterToMountHoleCenter/2, 0])
                cylinder(h = mountHoleDepth, d = mountScrewDiameter);
                translate([shaftCenterToMountHoldCenterXAxis, -mountHoleCenterToMountHoleCenter/2, 0])
                cylinder(h = mountHoleDepth, d = mountScrewDiameter);
            }
        }

    }
}

//armInnerJoint(bearing6807_2RS_D + iFitAdjust, bearingStep, bearingStep, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, screwTabs, screwTabHeight);
module armInnerJoint(bearingOD, stepHeight, stepWidth, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, screwTabs, screwTabHeight) {
    //translate([0, 0, hubHeight - (2 * stepHeight)])
    difference() {
        union() {
         difference() {
            cylinder(h = bearingStep * 2, d = bearingOD + (setScrewRadius * 6));
            cylinder(h = bearingStep * 2, d = bearingOD);
//            translate([0, -bearingOD, 0])
//                cube([bearingOD, bearingOD * 2, bearingStep * 2]);
        }
        bearingOuterStep(bearingOD, stepHeight, stepWidth);
        // hub
        translate([0, 0, -(hubHeight - (2 * stepHeight))])
            stepperHub(hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight);
        // spokes
        radial_array(vec=[0, 0, 1], n = spokes)
                translate([hubRadius - (stepWidth / 2), -(spokeWidth / 2), stepHeight])
                    cube([(bearingOD / 2) - hubRadius, spokeWidth, stepHeight], center = false);
        // screw tabs for joining to upper
        radial_array(vec = [0, 0, 1], n = screwTabs)
                translate([bearingOD / 2 + (setScrewRadius * 2), 0, (2 * stepHeight) - screwTabHeight])

                        union () {
                            cylinder(h = screwTabHeight, r = setScrewRadius * 2);
                            translate([-2 * setScrewRadius, - 2 * setScrewRadius, 0])
                                cube([setScrewRadius * 2, 4 * setScrewRadius, screwTabHeight], center = false);
                        }

                    }
        // screw holes for joining to upper
        radial_array(vec = [0, 0, 1], n = screwTabs)
                translate([bearingOD / 2 + (setScrewRadius * 2), 0, (2 * stepHeight) - screwTabHeight])
                       cylinder(h = screwTabHeight, r = setScrewRadius);
    }
}

module forearmLower(bearingID, bearingOD, stepHeight, stepWidth, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, forearmLength, boundingBox) {
    armWidth = bearingOD / 2;

    rotate([180, 0, 0]) union() {
        boundingBoxHalf = boundingBox / 2;
        difference() {
            cylinder(h = bearingStep * 2, d = bearingOD + bearingStep);
            cylinder(h = bearingStep * 2, d = bearingID - (2 * bearingStep));
        }
        translate([0, 0, bearingStep * 2])
            bearingInnerStep(bearingID, bearingStep, bearingStep);
        // screw holes for joining to arm
        radial_array(vec = [0, 0, 1], n = screwTabs)
                translate([bearingOD / 2 + (setScrewRadius * 2), 0, (2 * bearingStep) - screwTabHeight])
                    difference() {
                        union () {
                            cylinder(h = screwTabHeight, r = setScrewRadius * 2);
                            translate([-2 * setScrewRadius, - 2 * setScrewRadius, 0])
                                cube([setScrewRadius * 2, 4 * setScrewRadius, screwTabHeight], center = false);
                        }
                        cylinder(h = screwTabHeight, r = setScrewRadius);
                    }
        // hub
        translate([0, 0, hubHeight]) rotate([180, 0, 0])
            stepperHub(hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight);
        // spokes
        radial_array(vec=[0, 0, 1], n = spokes)
                translate([hubRadius - (stepWidth / 2), -(spokeWidth / 2), 0])
                    cube([(bearingOD / 2) - hubRadius, spokeWidth, 2 *stepHeight], center = false);
        // forearm extension
             difference() {
            translate([-forearmLength, -armWidth / 2, 0])
                cube([forearmLength, armWidth, bearingStep * 2], center=false);
            cylinder(h = bearingStep * 2, d = bearingOD);
            translate([-forearmLength, 0, 0])
                cylinder(h = bearingStep * 2, d = bearingOD / 2);
                 // 4 on next line comes from dividing the bearingOD on the above line
            translate([-forearmLength + (bearingOD / 4) + (boundingBox / 2), -(armWidth / 2) + boundingBoxHalf, 0])
                cube([forearmLength - (bearingOD/2) - (boundingBox + boundingBoxHalf), armWidth - boundingBox, bearingStep * 2], center = false);
        }

            intersection() {

                translate([-forearmLength + boundingBox * 2, -(armWidth / 2) + boundingBoxHalf, 0])
                    cube([forearmLength - (bearingOD / 2) - boundingBox, armWidth - boundingBox, bearingStep * 2], center = false);
                for (i = [ bearingOD / 2 - boundingBoxHalf: armWidth : forearmLength]) {
                    translate([ -i, 0, bearingStep])
                        rotate([0, 0, 45])
                            cube([spokeWidth, armWidth + boundingBoxHalf, bearingStep * 2], center = true);
                    translate([ -i, 0, bearingStep])
                        rotate([0, 0, -45])
                            cube([spokeWidth, armWidth + boundingBoxHalf, bearingStep * 2], center = true);
                }
            }

    }
}

module copy_mirror(vec=[0,1,0]) {
    children();
    mirror(vec)
        children();
}

module radial_array(vec = [0,0,1], n = 4) {
    for ( i = [0 : n - 1] )
    {
        rotate( i * 360 / n, vec)
            children();
    }
}