misc: fix v_sum, add v_abs

misc: fix v_sum, add v_abs

use <scad-utils/linalg.scad>
use <scad-utils/lists.scad>

function posvec(path_vec) = [for(v=path_vec) translation_part(v)];
function posvec_x(path_vec) = [for(v=path_vec) translation_part(v)[0]];
function posvec_y(path_vec) = [for(v=path_vec) translation_part(v)[1]];
function posvec_z(path_vec) = [for(v=path_vec) translation_part(v)[2]];

function vec_i(v3,i) = [for(v=v3) v[i]];
function vec_0(v3) = vec_i(v3,0);
function vec_1(v3) = vec_i(v3,1);
function vec_2(v3) = vec_i(v3,2);

function vec_add(vec,v) = [for(vv=vec) vv+v];

function v_itrlen(vec) = [0:1:len(vec)-1];

function range1(v1) = [min(v1), max(v1)];
function range3(v3) = [range1(vec_0(v3)), range1(vec_1(v3)), range1(vec_2(v3))];
function bbox(r) = [ [r[0][0],r[1][0],r[2][0]], [r[0][1],r[1][1],r[2][1]] ];
function transform_pp(vec_m, t_pre, t_post) = [for(m=vec_m) (t_pre*m)*t_post];
function transform_pre(vec_m, t) = [for(m=vec_m) t*m];
function transform_post(vec_m, t) = [for(m=vec_m) m*t];

// from the start (or s'th element) to the e'th element - remember elements are zero based
function v_sum(v,e=undef,start=0) =
let(e_= e==undef ? len(v)-1 : e)
(e==start ? v[e] : v[e_] + v_sum(v,e_-1,start));

function v_abs(v, start=0) = [for(i=[start:1:len(v)-1]) abs(v[i])];

// cumulative sum of vector [1,2,3] = [1,3,6]
function v_cumsum(v, start=0) = [for(i=[start:1:len(v)-1]) v_sum(v,i)];

// filter/remove a val from a vec
function filter(vec,val=undef) = [for(v=vec) if(v!=val) v];

function vec_pair_double_transform_post(vec,t1,t2)=
    flatten(
        [for(v=vec)
            [transform_post(v,t1),transform_post(v,t2)]
        ]);

function vec_pair_double(vec)=flatten([for(v=vec) [v,v] ]);

/** Calculates length of hypotenuse according to pythagoras */
function pythag_hyp(a, b)=sqrt(a*a+b*b);
function pythag_leg(b, c)=sqrt(c*c-b*b);

//-- Calculate the module of a vector
function v_mod(v) = (sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]));

//-- Calculate the cros product of two vectors
function v_cross(u,v) = [
  u[1]*v[2] - v[1]*u[2],
  -(u[0]*v[2] - v[0]*u[2]) ,
  u[0]*v[1] - v[0]*u[1]];

//-- Calculate the dot product of two vectors
function v_dot(u,v) = u[0]*v[0]+u[1]*v[1]+u[2]*v[2];

//-- Return the unit vector of a vector
function v_unitv(v) = v/v_mod(v);

//-- Return the angle between two vectores
function v_anglev(u,v) = acos( v_dot(u,v) / (v_mod(u)*v_mod(v)) );

function _orient_angles(zaxis)=
[-asin(zaxis.y / norm(zaxis)),
    atan2(zaxis.x, zaxis.z),
    0];

//matrix rotation functions
function _rotate_x_matrix(a)=
[[1,0,0,0],
    [0,cos(a),-sin(a),0],
    [0,sin(a),cos(a),0],
    [0,0,0,1]];

function _rotate_y_matrix(a)=
[[cos(a),0,sin(a),0],
    [0,1,0,0],
    [-sin(a),0,cos(a),0],
    [0,0,0,1]];

function _rotate_z_matrix(a)=
[[cos(a),-sin(a),0,0],
    [sin(a),cos(a),0,0],
    [0,0,1,0],
    [0,0,0,1]];

function _rotate_matrix(a)=_rotate_z_matrix(a.z)*_rotate_y_matrix(a.y)*_rotate_x_matrix(a.x);

//hadamard product (aka "component-wise" product) for vectors
function hadamard(v1,v2) = [v1.x*v2.x, v1.y*v2.y, v1.z*v2.z];

// search in a dictionary (vector w/key-value pairs) and replace the value for a given key
function dict_replace(dict, key, newvalue)=[
        for(kv=dict)
        kv[0] == key ?
            [key, newvalue]
            :
            kv
        ];

function dict_replace_multiple(dict, newvaluesdict)=[
    for(kv_old=dict)
    let(r = search(kv_old[0], newvaluesdict, num_returns_per_match=0, index_col_num=0))
    r==[]?kv_old:newvaluesdict[r[0]]
    ];

function sinh(x) = (1 - pow(e, -2 * x)) / (2 * pow(e, -x));
function cosh(x) = (1 + pow(e, -2 * x)) / (2 * pow(e, -x));
function tanh(x) = sinh(x) / cosh(x);
function cot(x) = 1 / tan(x);

function factorial(n) = n == 0 ? 1 : factorial(n - 1) * n;

if(false)
{
    vec=[ 10, 20, 30, 40 ];
    echo("v_sum=", v_sum(vec,2,1)); // is 20+30=50
    echo("v_sum=", v_sum(vec));
    echo("v_cumsum=", v_cumsum(vec));
}

use <scad-utils/linalg.scad>
use <scad-utils/lists.scad>

function posvec(path_vec) = [for(v=path_vec) translation_part(v)];
function posvec_x(path_vec) = [for(v=path_vec) translation_part(v)[0]];
function posvec_y(path_vec) = [for(v=path_vec) translation_part(v)[1]];
function posvec_z(path_vec) = [for(v=path_vec) translation_part(v)[2]];

function vec_i(v3,i) = [for(v=v3) v[i]];
function vec_0(v3) = vec_i(v3,0);
function vec_1(v3) = vec_i(v3,1);
function vec_2(v3) = vec_i(v3,2);

function vec_add(vec,v) = [for(vv=vec) vv+v];

function v_itrlen(vec) = [0:1:len(vec)-1];

function range1(v1) = [min(v1), max(v1)];
function range3(v3) = [range1(vec_0(v3)), range1(vec_1(v3)), range1(vec_2(v3))];
function bbox(r) = [ [r[0][0],r[1][0],r[2][0]], [r[0][1],r[1][1],r[2][1]] ];
function transform_pp(vec_m, t_pre, t_post) = [for(m=vec_m) (t_pre*m)*t_post];
function transform_pre(vec_m, t) = [for(m=vec_m) t*m];
function transform_post(vec_m, t) = [for(m=vec_m) m*t];

// sum a vector up to position i
function v_sum(v, i) = i >= 0 ? v[i] + v_sum(v, i - 1) : 0;

// cumulative sum of vector [1,2,3] = [1,3,6]
function v_cumsum(v, start=0) = [for(i=[start:1:len(v)-1]) v_sum(v,i)];

// filter/remove a val from a vec
function filter(vec,val=undef) = [for(v=vec) if(v!=val) v];

function vec_pair_double_transform_post(vec,t1,t2)=
    flatten(
        [for(v=vec)
            [transform_post(v,t1),transform_post(v,t2)]
        ]);

function vec_pair_double(vec)=flatten([for(v=vec) [v,v] ]);

/** Calculates length of hypotenuse according to pythagoras */
function pythag_hyp(a, b)=sqrt(a*a+b*b);
function pythag_leg(b, c)=sqrt(c*c-b*b);

//-- Calculate the module of a vector
function v_mod(v) = (sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]));

//-- Calculate the cros product of two vectors
function v_cross(u,v) = [
  u[1]*v[2] - v[1]*u[2],
  -(u[0]*v[2] - v[0]*u[2]) ,
  u[0]*v[1] - v[0]*u[1]];

//-- Calculate the dot product of two vectors
function v_dot(u,v) = u[0]*v[0]+u[1]*v[1]+u[2]*v[2];

//-- Return the unit vector of a vector
function v_unitv(v) = v/v_mod(v);

//-- Return the angle between two vectores
function v_anglev(u,v) = acos( v_dot(u,v) / (v_mod(u)*v_mod(v)) );

function _orient_angles(zaxis)=
[-asin(zaxis.y / norm(zaxis)),
    atan2(zaxis.x, zaxis.z),
    0];

//matrix rotation functions
function _rotate_x_matrix(a)=
[[1,0,0,0],
    [0,cos(a),-sin(a),0],
    [0,sin(a),cos(a),0],
    [0,0,0,1]];

function _rotate_y_matrix(a)=
[[cos(a),0,sin(a),0],
    [0,1,0,0],
    [-sin(a),0,cos(a),0],
    [0,0,0,1]];

function _rotate_z_matrix(a)=
[[cos(a),-sin(a),0,0],
    [sin(a),cos(a),0,0],
    [0,0,1,0],
    [0,0,0,1]];

function _rotate_matrix(a)=_rotate_z_matrix(a.z)*_rotate_y_matrix(a.y)*_rotate_x_matrix(a.x);

//hadamard product (aka "component-wise" product) for vectors
function hadamard(v1,v2) = [v1.x*v2.x, v1.y*v2.y, v1.z*v2.z];

// search in a dictionary (vector w/key-value pairs) and replace the value for a given key
function dict_replace(dict, key, newvalue)=[
        for(kv=dict)
        kv[0] == key ?
            [key, newvalue]
            :
            kv
        ];

function dict_replace_multiple(dict, newvaluesdict)=[
    for(kv_old=dict)
    let(r = search(kv_old[0], newvaluesdict, num_returns_per_match=0, index_col_num=0))
    r==[]?kv_old:newvaluesdict[r[0]]
    ];

function sinh(x) = (1 - pow(e, -2 * x)) / (2 * pow(e, -x));
function cosh(x) = (1 + pow(e, -2 * x)) / (2 * pow(e, -x));
function tanh(x) = sinh(x) / cosh(x);
function cot(x) = 1 / tan(x);

function factorial(n) = n == 0 ? 1 : factorial(n - 1) * n;


todo: arm spacers and elbow screw holes

todo: arm spacers and elbow screw holes

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 = 60;
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(bearing6807_2RS_d - iFitAdjust, bearing6807_2RS_D + iFitAdjust, shoulderBaseHeight, shoulderBaseDiameter, shaftBossDiameter, mountScrewDiameter);
// shoulder lower 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(bearing6807_2RS_d - iFitAdjust, bearing6807_2RS_D + iFitAdjust, shoulderBaseHeight, shoulderBaseDiameter, shaftBossDiameter, mountScrewDiameter);
// upper shoulder bearing
translate([0, 0, shoulderBaseHeight + (3 * bearing6807_2RS_B) + (7 * bearingStep)])
    %bearing6807_2RS();
// shoulder upper stepper
rotate([0, 0, 180])
    translate([-8, 0, 10 + 2 * shoulderBaseHeight + (4 * bearing6807_2RS_B) + (8 * bearingStep)])
        StepMotor28BYJ();
// shoulder spacers
color([.7, .6, .2])
shoulderSpacers(bearing6807_2RS_D + iFitAdjust, 0 * shoulderBaseHeight + (4 * bearing6807_2RS_B) + (8 * bearingStep));
color([.7, .6, .2])
translate([baseDeckExtension / 3, 0, 0])
shoulderSpacers(bearing6807_2RS_D + iFitAdjust, 0 * shoulderBaseHeight + (4 * bearing6807_2RS_B) + (8 * bearingStep));
// end shoulder

// 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 upper stepper
translate([-armLength + 8, 0, shoulderBaseHeight + ( 3*bearing6807_2RS_B) + (16 * bearingStep) - (.5 * bearingStep)])
    rotate([0, 0, 180])
        StepMotor28BYJ();
// arm lower stepper
rotate([0, 180, 0])
    translate([armLength - 8, 0, bearingStep * 2])
        StepMotor28BYJ();
// arm spacers
color([.6, .6, .3])
    armSpacers(bearing6807_2RS_D + iFitAdjust, 0 * shoulderBaseHeight + (4 * bearing6807_2RS_B) + (8 * bearingStep));
// end arm

// 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)])
    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();
// forearm spacers

/*
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);
    }
}

module shoulderSpacers(bearingOD, screwSpacerHeight) {
    union() {
        // screw holes for joining to arm
        rotate([0, 0, -30])
        radial_array_partial(vec = [0, 0, 1], n = 6, 2)
            translate([bearingOD / 2 + (setScrewRadius * 8), 0, shoulderBaseHeight * 1.0])
        difference() {
            union () {
                cylinder(h = screwSpacerHeight, r = setScrewRadius * 2);

                }
            cylinder(h = screwTabHeight, r = setScrewRadius);
        }
    }
}

module armSpacers(bearingOD, screwSpacerHeight) {
    union() {
        // screw holes for joining to arm
        radial_array(vec = [0, 0, 1], n = 4)
            translate([bearingOD / 2 + (setScrewRadius * 2), 0, shoulderBaseHeight + bearing6807_2RS_B + 2 * bearingStep])
        difference() {
            union () {
                cylinder(h = bearing6807_2RS_B * 2 + 4 * bearingStep, r = setScrewRadius * 2);

                }
            cylinder(h = bearing6807_2RS_B * 2 + 4 * bearingStep, r = setScrewRadius);
        }
        // TODO: put in spacers along arm, make sure holes exist in arm
    }
}

// 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(bearingID, bearingOD, 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));
        // upper to lower spacer screw holes
        rotate([0, 0, -30])
            radial_array_partial(vec = [0, 0, 1], n = 6, 2)
                translate([bearingOD / 2 + (setScrewRadius * 8), 0, shoulderBaseHeight * 0])
                    cylinder(h = screwTabHeight, r = setScrewRadius);
           translate([baseDeckExtension / 3, 0, 0])
            rotate([0, 0, -30])
            radial_array_partial(vec = [0, 0, 1], n = 6, 2)
                translate([bearingOD / 2 + (setScrewRadius * 8), 0, shoulderBaseHeight * 0])
                    cylinder(h = screwTabHeight, r = setScrewRadius);
    }
    // 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();
    }
}

module radial_array_partial(vec = [0,0,1], n = 4, j = 2) {
    for ( i = [0 : n - 1] )
    {
        if (i < j)
            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 = 60;
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(bearing6807_2RS_d - iFitAdjust, bearing6807_2RS_D + iFitAdjust, shoulderBaseHeight, shoulderBaseDiameter, shaftBossDiameter, mountScrewDiameter);
// shoulder lower 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(bearing6807_2RS_d - iFitAdjust, bearing6807_2RS_D + iFitAdjust, shoulderBaseHeight, shoulderBaseDiameter, shaftBossDiameter, mountScrewDiameter);
// upper shoulder bearing
translate([0, 0, shoulderBaseHeight + (3 * bearing6807_2RS_B) + (7 * bearingStep)])
    %bearing6807_2RS();
// shoulder upper stepper
rotate([0, 0, 180])
    translate([-8, 0, 10 + 2 * shoulderBaseHeight + (4 * bearing6807_2RS_B) + (8 * bearingStep)])
        StepMotor28BYJ();
// shoulder spacers
color([.7, .6, .2])
shoulderSpacers(bearing6807_2RS_D + iFitAdjust, 0 * shoulderBaseHeight + (4 * bearing6807_2RS_B) + (8 * bearingStep));
color([.7, .6, .2])
translate([baseDeckExtension / 3, 0, 0])
shoulderSpacers(bearing6807_2RS_D + iFitAdjust, 0 * shoulderBaseHeight + (4 * bearing6807_2RS_B) + (8 * bearingStep));
// end shoulder

// 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 upper stepper
translate([-armLength + 8, 0, shoulderBaseHeight + ( 3*bearing6807_2RS_B) + (16 * bearingStep) - (.5 * bearingStep)])
    rotate([0, 0, 180])
        StepMotor28BYJ();
// arm lower stepper
rotate([0, 180, 0])
    translate([armLength - 8, 0, bearingStep * 2])
        StepMotor28BYJ();
// arm spacers
color([.6, .6, .3])
    armSpacers(bearing6807_2RS_D + iFitAdjust, 0 * shoulderBaseHeight + (4 * bearing6807_2RS_B) + (8 * bearingStep));
// end arm

// 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)])
    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();
// forearm spacers

/*
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);
    }
}

module shoulderSpacers(bearingOD, screwSpacerHeight) {
    union() {
        // screw holes for joining to arm
        rotate([0, 0, -30])
        radial_array_partial(vec = [0, 0, 1], n = 6, 2)
            translate([bearingOD / 2 + (setScrewRadius * 8), 0, shoulderBaseHeight * 1.0])
        difference() {
            union () {
                cylinder(h = screwSpacerHeight, r = setScrewRadius * 2);

                }
            cylinder(h = screwTabHeight, r = setScrewRadius);
        }
    }
}

module armSpacers(bearingOD, screwSpacerHeight) {
    union() {
        // screw holes for joining to arm
        radial_array(vec = [0, 0, 1], n = 4)
            translate([bearingOD / 2 + (setScrewRadius * 2), 0, shoulderBaseHeight + bearing6807_2RS_B + 2 * bearingStep])
        difference() {
            union () {
                cylinder(h = bearing6807_2RS_B * 2 + 4 * bearingStep, r = setScrewRadius * 2);

                }
            cylinder(h = bearing6807_2RS_B * 2 + 4 * bearingStep, r = setScrewRadius);
        }
        // TODO: put in spacers along arm, make sure holes exist in arm
    }
}

// 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(bearingID, bearingOD, 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));
        // upper to lower spacer screw holes
        rotate([0, 0, -30])
            radial_array_partial(vec = [0, 0, 1], n = 6, 2)
                translate([bearingOD / 2 + (setScrewRadius * 8), 0, shoulderBaseHeight * 0])
                    cylinder(h = screwTabHeight, r = setScrewRadius);
           translate([baseDeckExtension / 3, 0, 0])
            rotate([0, 0, -30])
            radial_array_partial(vec = [0, 0, 1], n = 6, 2)
                translate([bearingOD / 2 + (setScrewRadius * 8), 0, shoulderBaseHeight * 0])
                    cylinder(h = screwTabHeight, r = setScrewRadius);
    }
    // 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();
    }
}

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


[scad] parameterize kube dimensions

[scad] parameterize kube dimensions

/*
	_h = height
	_w = width
	_r = radius
	_t = tolerance
*/

magnet_h = 5;
magnet_r = 13.5;
magnet_t = 0.2;

flk_h = 23.5;
flk_w = 30.5;
flk_t = 0.5;

wall_w = 2;

support_r = 5;
support_h = outer_w - wall_w - flk_h;

inner_w = flk_w + flk_t;
outer_w = inner_w + 2*wall_w;

module kube()
{
	difference() {
		cube(outer_w);
		translate([wall_w, wall_w, wall_w + magnet_h]) {
			cube(inner_w, inner_w, outer_w - (wall_w + magnet_h));
		}
		translate([outer_w/2, outer_w/2, wall_w]) {
			cylinder(r=magnet_r + magnet_t, h=magnet_h);
		}
	}

	translate([outer_w/2, outer_w/2, wall_w]) {
		cylinder(r=support_r, h=support_h);
	}
}

kube();


finalized gantry cart big size

finalized gantry cart big size

include <../scad/vslot_gantry_plate.scad>
include <../scad/ob_wheel.scad>
use <../scad/ob_spacer.scad>
use <../scad/shim.scad>

gantry_cart_wheel_mid = 15.5;

module gantry_cart_big(sections = 1, wheelstop = 2, wheelsbottom = 2) {
  wheels_top = [
    [],
    [[], [10], [ 9,11], [ 9,10,11]],
    [[], [ 7], [ 6, 8], [ 6, 7, 8]],
    [[], [ 4], [ 3, 5], [ 3, 4, 5]],
    [[], [ 1], [ 0, 2], [ 0, 1, 2]]
  ];
  wheels_bottom = [
    [],
    [[], [22], [21,23], [21,22,23]],
    [[], [19], [18,20], [18,19,20]],
    [[], [16], [15,17], [15,16,17]],
    [[], [13], [12,14], [12,13,14]]
  ];
  translate([0,0,vslot_gantry_plate_height/2])
    vslot_gantry_plate_big(sections, wheelstop, wheelsbottom);
  translate([0,0,vslot_gantry_plate_height]) {
    for(s = wheels_top[sections][wheelstop]) {
      translate(vslot_gantry_plate_holes_big[s]) {
        ob_eccentric_spacer();
        translate([0,0,6.85]) {
          precision_shim_10x5x1();
          translate([0,0,ob_wheel_half_width])
            ob_solid_wheel();
        }
      }
    }
    for(s = wheels_bottom[sections][wheelsbottom]) {
      translate(vslot_gantry_plate_holes_big[s]) {
        ob_spacer(6.35);
        translate([0,0,6.85]) {
          precision_shim_10x5x1();
          translate([0,0,ob_wheel_half_width])
            ob_solid_wheel();
        }
      }
    }
  }
}

include <../scad/or_gantry_plate.scad>
include <../scad/ob_wheel.scad>
use <../scad/ob_spacer.scad>
use <../scad/shim.scad>

module gantry_cart(mod = 1) {
  translate([0,0,or_gantry_plate_height/2])
    or_gantry_plate(mod);
  eccentric_spacers = [[],[2,10]];
  spacers = [[],[1,9]];
  translate([0,0,or_gantry_plate_height]) {
    for(s = eccentric_spacers[mod])
      translate(or_gantry_plate_holes[mod][s][0]) {
        ob_eccentric_spacer();
        translate([0,0,6.85]) {
          precision_shim_10x5x1();
          translate([0,0,ob_wheel_half_width])
            ob_solid_wheel();
        }
      }
    for(s = spacers[mod])
      translate(or_gantry_plate_holes[mod][s][0]) {
        ob_spacer(6.35);
        translate([0,0,6.85]) {
          precision_shim_10x5x1();
          translate([0,0,ob_wheel_half_width])
            ob_solid_wheel();
        }
      }
  }
}


power_panel: define part

power_panel: define part

include <config.scad>
include <thing_libutils/units.scad>
include <thing_libutils/shapes.scad>
include <thing_libutils/metric-screw.scad>
//use <boxes.scad>
use <MCAD/boxes.scad>
/*use <GoblinOne.scad>*/

//3 Pin IEC320 C14 Inlet Male Power Socket w Fuse Switch 10A 250V
//http://www.amazon.com/IEC320-Inlet-Power-Socket-Switch/dp/B00511QVVK
//http://www.uxcell.com/pin-iec320-c14-inlet-male-power-socket-fuse-switch-10a-250v-p-104813.html

//position X/Y offset
IEC_offset = [0,0];

//mounting width of IEC switch/fuse/socket
IEC_width = 47*mm + .2*mm;

//mounting height of IEC switch/fuse/socket
IEC_height = 27*mm + .2*mm;

//mounting flange depth of IEC switch/fuse/socket
IEC_depth = 1;

//width of flange before returning to full panel thickness
IEC_rim = 1.5;

//side length of the corner cutout on the IEC connect end of the power module
IEC_corner = 6-.5;

power_panel_iec320_width = IEC_width+15*mm;
power_panel_iec320_height = main_lower_dist_z+extrusion_size;
power_panel_iec320_thickness = 3.8*mm;

//horizontal distance from edge to mounting hole
power_panel_iec320_hole_hedge_w = 5*mm;

//vertical spacing of mounting holes
power_panel_iec320_hole_vspace = main_lower_dist_z;

mount_hole_d = 5*mm;

module power_panel_iec320(align=[0,0,0], orient=[0,0,-1])
{
    s = [power_panel_iec320_width,power_panel_iec320_height,power_panel_iec320_thickness];
    size_align(size=s, align=align, orient=orient, orient_ref=[0,0,-1])
    rotate ([180,0,180])
    difference ()
    {
        //power_panel_iec320
        rcubea(size=s);

        //socket
        translate(v = [IEC_offset[0], IEC_offset[1], 0])
        difference()
        {
            union()
            {
                translate(v = [0, 0, -IEC_depth])
                cube(size = [IEC_width,IEC_height+IEC_rim*2,power_panel_iec320_thickness], center = true );
                cube(size = [IEC_width,IEC_height,power_panel_iec320_thickness+1], center = true);
            }
            for (x = [-1:2:1])
            translate([(IEC_width-IEC_corner)/2, x*(IEC_height-IEC_corner)/2,0])

            rotate([0,0,x*45])
            translate([0,-(IEC_width+IEC_height)/2,-(power_panel_iec320_thickness+1)/2])
            cube([IEC_width+IEC_height,IEC_width+IEC_height,power_panel_iec320_thickness+1]);
        }

        // extrusion mounting holes
        for (x = [-1,1])
        for (y = [-1,1])
        translate([x*(power_panel_iec320_width/2-power_panel_iec320_hole_hedge_w-mount_hole_d/2), y*(power_panel_iec320_hole_vspace/2), -s[2]/2])
        screw_cut(nut=extrusion_nut, screw_l=12*mm, with_nut=false, align=[0,0,1], orient=[0,0,1]);
    }
}

module part_power_panel_iec320()
{
    power_panel_iec320() ;
}

if(false)
{
    power_panel_iec320() ;
}

include <config.scad>
include <thing_libutils/units.scad>
include <thing_libutils/shapes.scad>
include <thing_libutils/metric-screw.scad>
//use <boxes.scad>
use <MCAD/boxes.scad>
/*use <GoblinOne.scad>*/

//3 Pin IEC320 C14 Inlet Male Power Socket w Fuse Switch 10A 250V
//http://www.amazon.com/IEC320-Inlet-Power-Socket-Switch/dp/B00511QVVK
//http://www.uxcell.com/pin-iec320-c14-inlet-male-power-socket-fuse-switch-10a-250v-p-104813.html

//position X/Y offset
IEC_offset = [0,0];

//mounting width of IEC switch/fuse/socket
IEC_width = 47*mm + .2*mm;

//mounting height of IEC switch/fuse/socket
IEC_height = 27*mm + .2*mm;

//mounting flange depth of IEC switch/fuse/socket
IEC_depth = 1;

//width of flange before returning to full panel thickness
IEC_rim = 1.5;

//side length of the corner cutout on the IEC connect end of the power module
IEC_corner = 6-.5;

power_panel_iec320_width = IEC_width+15*mm;
power_panel_iec320_height = main_lower_dist_z+extrusion_size;
power_panel_iec320_thickness = 3.8*mm;

//horizontal distance from edge to mounting hole
power_panel_iec320_hole_hedge_w = 5*mm;

//vertical spacing of mounting holes
power_panel_iec320_hole_vspace = main_lower_dist_z;

mount_hole_d = 5*mm;

module power_panel_iec320(align=[0,0,0], orient=[0,0,-1])
{
    s = [power_panel_iec320_width,power_panel_iec320_height,power_panel_iec320_thickness];
    size_align(size=s, align=align, orient=orient, orient_ref=[0,0,-1])
    rotate ([180,0,180])
    difference ()
    {
        //power_panel_iec320
        rcubea(size=s);

        //socket
        translate(v = [IEC_offset[0], IEC_offset[1], 0])
        difference()
        {
            union()
            {
                translate(v = [0, 0, -IEC_depth])
                cube(size = [IEC_width,IEC_height+IEC_rim*2,power_panel_iec320_thickness], center = true );
                cube(size = [IEC_width,IEC_height,power_panel_iec320_thickness+1], center = true);
            }
            for (x = [-1:2:1])
            translate([(IEC_width-IEC_corner)/2, x*(IEC_height-IEC_corner)/2,0])

            rotate([0,0,x*45])
            translate([0,-(IEC_width+IEC_height)/2,-(power_panel_iec320_thickness+1)/2])
            cube([IEC_width+IEC_height,IEC_width+IEC_height,power_panel_iec320_thickness+1]);
        }

        // extrusion mounting holes
        for (x = [-1,1])
        for (y = [-1,1])
        translate([x*(power_panel_iec320_width/2-power_panel_iec320_hole_hedge_w-mount_hole_d/2), y*(power_panel_iec320_hole_vspace/2), -s[2]/2])
        screw_cut(nut=extrusion_nut, screw_l=12*mm, with_nut=false, align=[0,0,1], orient=[0,0,1]);
    }
}

if(false)
{
    power_panel_iec320() ;
}


stepper: add motor_outline

stepper: add motor_outline

 // Some code from MCAD/stepper.scad
 // Originally by Hans Häggström, 2010.
 // Dual licenced under Creative Commons Attribution-Share Alike 3.0 and LGPL2 or later

include <system.scad>
include <units.scad>
include <materials.scad>
include <stepper-data.scad>
include <misc.scad>

use <transforms.scad>
use <shapes.scad>

/*test2();*/

module test()
{
    for (size = AllNemaSizes)
    {
        ty(size*100)
        stack(axis=X, dist=100)
        {
            motor(model=Nema34, size=size, dual_axis=true);
            motor(model=Nema23, size=size, dual_axis=true);
            motor(model=Nema17, size=size, dual_axis=true);
            motor(model=Nema14, size=size, dual_axis=true);
            motor(model=Nema11, size=size, dual_axis=true);
            motor(model=Nema08, size=size, dual_axis=true);
        }
    }
}

module test2()
{
    $show_vit=true;
    model = Nema17;
    size = NemaMedium;
    all_axes()
    color($color)
    translate(100*$axis)
    motor_mount(model=model, size=size, thickness=6*mm, dual_axis=true, orient=$axis);
    /*motor(model=model, size=size, thickness=6*mm, dual_axis=true, orient=$axis);*/
}

function motorWidth(model) = get(NemaSideSize, model);
function motorLength(model, size=NemaMedium) = get(size, model);

module motor_mount(part=U, model, thickness, size=NemaMedium, extra_size=U, dual_axis=false, orient=Z, align=N)
{
    assert(model!=U, "motor_mount(): model==U");
    assert(thickness!=U, "motor_mount(): thickness==U");
    assert(size!=U, "motor_mount(): size==U");

    length = get(size, model);
    side = get(NemaSideSize, model);
    extrSize = get(NemaRoundExtrusionHeight, model);
    extrRad = get(NemaRoundExtrusionDiameter, model) * 0.5;
    holeDist = get(NemaDistanceBetweenMountingHoles, model) * 0.5;
    holeRadius = get(NemaMountingHoleDiameter, model) * 0.5;

    s=[side+fallback(extra_size.x,0), side+fallback(extra_size.y,0), length];
    size_align(size=s, orient=orient, align=align)
    if(part==U)
    {
        material(Mat_Plastic)
        render()
        difference()
        {
            motor_mount(part="pos", model=model, thickness=thickness, size=size, dual_axis=dual_axis);
            motor_mount(part="neg", model=model, thickness=thickness, size=size, dual_axis=dual_axis);
        }

        if($show_vit)
        motor_mount(part="vit", model=model, thickness=thickness, size=size, dual_axis=dual_axis);
    }
    else if(part=="pos")
    {
        rcubea([s.x,s.y,thickness], align=Z);
    }
    else if(part=="neg")
    {
        cylindera(h=thickness+.1, r=extrRad, align=Z, extra_h=.1, extra_align=-Z);

        // main motor
        tz(-s.z)
        cubea(size=[side+.3*mm,side+.3*mm,length], align=Z);

        // Bolt holes
        material(Mat_Aluminium)
        for(x=[-1,1])
        for(y=[-1,1])
        tx(x*holeDist)
        ty(y*holeDist)
        cylindera(h=thickness+.1, r=holeRadius, align=Z, extra_h=.1, extra_align=-Z);

    }
    else if(part=="vit")
    {
        motor(model=model, size=size, dual_axis=dual_axis);
    }
}

module motor_outline(part=U, model, length=5*mm, extra_side=0, orient=Z, align=N)
{
    assert(model!=U, "model == U");
    assert(length!=U, "length == U");
    side = get(NemaSideSize, model) + extra_side;
    cutR = get(NemaMountingHoleCutoutRadius, model);
    lip = get(NemaMountingHoleLip, model);
    roundR = get(NemaEdgeRoundingRadius, model);
    extrSize = get(NemaRoundExtrusionHeight, model);
    extrRad = get(NemaRoundExtrusionDiameter, model) * 0.5;

    s=[side, side, length];
    size_align(size=s, orient=orient, orient_ref=Z, align=align)
    if(part==U)
    {
        difference()
        {
            motor_outline(part="pos", model=model, length=length, extra_side=extra_side);
            motor_outline(part="neg", model=model, length=length, extra_side=extra_side);
        }
        motor_outline(part="vit", model=model, length=length, extra_side=extra_side);
    }
    if(part=="pos")
    {
        material(Mat_BlackPaint)
        /*tz(-s.z)*/
        cubea(s, align=N);
    }
    else if(part=="neg")
    {
        // Corner cutouts
        if (lip > 0)
        material(Mat_BlackPaint)
        tz(-s.z)
        for(x=[-1,1])
        for(y=[-1,1])
        tx(x*side/2)
        ty(y*side/2)
        tz(-lip)
        cylindera(h=length, r=cutR, align=N);

        // Rounded edges
        if (roundR > 0)
        material(Mat_BlackPaint)
        for(x=[-1,1])
        for(y=[-1,1])
        tx(x*side/2)
        ty(y*side/2)
        mirror([x>0?0:1,y>0?0:1,0])
        rz(45)
        cubea(size=[roundR, roundR*2, 4+length + extrSize+2], align=N, extra_size=.1*N, extra_align=-N);
    }
}

module motor(part=U, model, size=NemaMedium, dual_axis=false, orient=Z, align=N)
{
    assert(model!=U, "model == U");
    assert(size!=U, "size == U");
    length = get(size, model);

    side = get(NemaSideSize, model);
    cutR = get(NemaMountingHoleCutoutRadius, model);
    lip = get(NemaMountingHoleLip, model);
    holeDepth = get(NemaMountingHoleDepth, model);

    axleRadius = get(NemaAxleDiameter, model) * 0.5;

    extrSize = get(NemaRoundExtrusionHeight, model);
    extrRad = get(NemaRoundExtrusionDiameter, model) * 0.5;

    holeDist = get(NemaDistanceBetweenMountingHoles, model) * 0.5;
    holeRadius = get(NemaMountingHoleDiameter, model) * 0.5;

    roundR = get(NemaEdgeRoundingRadius, model);

    s=[side, side, length];
    size_align(size=s, orient=orient, orient_ref=Z, align=align)
    if(part==U)
    {
        difference()
        {
            motor(part="pos", model=model, size=size, dual_axis=dual_axis);
            motor(part="neg", model=model, size=size, dual_axis=dual_axis);
        }
        motor(part="vit", model=model, size=size, dual_axis=dual_axis);

        motor_axle(model=model, size=size, dual_axis=dual_axis);
    }
    if(part=="echo")
    {
        echo(str("  Motor: Nema",get(NemaModel, model),", length= ",length,"mm, dual axis=",dual_axis));
    }
    else if(part=="pos")
    {
        material(Mat_BlackPaint)
        tz(-s.z)
        cubea(s, align=Z, extra_size=Z*extrSize, extra_align=Z);
    }
    else if(part=="neg")
    {
        // Axle hole
        material(Mat_Aluminium)
        cylindera(r=axleRadius+.2*mm, h=1000);

        // Corner cutouts
        if (lip > 0)
        material(Mat_BlackPaint)
        tz(-s.z)
        for(x=[-1,1])
        for(y=[-1,1])
        tx(x*side/2)
        ty(y*side/2)
        tz(-lip)
        cylindera(h=length, r=cutR, align=Z);

        // Rounded edges
        if (roundR > 0)
        material(Mat_BlackPaint)
        tz(-s.z)
        for(x=[-1,1])
        for(y=[-1,1])
        tx(x*side/2)
        ty(y*side/2)
        mirror([x>0?0:1,y>0?0:1,0])
        rz(45)
        cubea(size=[roundR, roundR*2, 4+length + extrSize+2], align=Z, extra_size=.1*Z, extra_align=-Z);

        // Bolt holes
        material(Mat_Aluminium)
        for(x=[-1,1])
        for(y=[-1,1])
        tx(x*holeDist)
        ty(y*holeDist)
        cylindera(h=holeDepth+.1*mm, r=holeRadius, align=-Z, extra_h=.1, extra_align=Z);

        // Grinded flat
        material(Mat_BlackPaint)
        difference()
        {
            cubea(size=[side+.1, side+.1, extrSize+.1], align=Z);
            cylindera(h=extrSize, r=extrRad, align=Z);
        }
    }
}

module motor_axle(model=Nema23, size=NemaMedium, dual_axis=false, orient=Z, align=U)
{
    assert(model!=U, "model == U");
    assert(size!=U, "size == U");
    length = get(size, model);

    axleLengthFront = get(NemaFrontAxleLength, model);
    axleLengthBack = get(NemaBackAxleLength, model);
    axleRadius = get(NemaAxleDiameter, model) * 0.5;

    extrSize = get(NemaRoundExtrusionHeight, model);

    roundR = get(NemaEdgeRoundingRadius, model);

    axleFlatDepth = get(NemaAxleFlatDepth, model);
    axleFlatLengthFront = get(NemaAxleFlatLengthFront, model);
    axleFlatLengthBack = get(NemaAxleFlatLengthBack, model);

    material(Mat_Steel)
    render()
    intersection()
    {
        material(Mat_Aluminium)
        tz(-length)
        cylindera(r=axleRadius, h=length+extrSize+axleLengthFront, align=Z, extra_h=dual_axis?axleLengthBack:0, extra_align=-Z);

        material(Mat_Aluminium)
        union()
        {
            tx(axleFlatDepth>0?-axleFlatDepth:0)
            cubea(size=[2*axleRadius, 2*axleRadius, axleLengthFront], align=Z);

            cubea(size=[2*axleRadius, 2*axleRadius, length+.4*mm], align=-Z, extra_size=Z*(extrSize+.4*mm), extra_align=Z);

            tx(axleFlatDepth>0?-axleFlatDepth:0)
            tz(-length)
            cubea(size=[2*axleRadius, 2*axleRadius, axleLengthBack], align=-Z);
        }
    }
}

 // Some code from MCAD/stepper.scad
 // Originally by Hans Häggström, 2010.
 // Dual licenced under Creative Commons Attribution-Share Alike 3.0 and LGPL2 or later

include <system.scad>
include <units.scad>
include <materials.scad>
include <stepper-data.scad>
include <misc.scad>

use <transforms.scad>
use <shapes.scad>

/*test2();*/

module test()
{
    for (size = AllNemaSizes)
    {
        ty(size*100)
        stack(axis=X, dist=100)
        {
            motor(model=Nema34, size=size, dual_axis=true);
            motor(model=Nema23, size=size, dual_axis=true);
            motor(model=Nema17, size=size, dual_axis=true);
            motor(model=Nema14, size=size, dual_axis=true);
            motor(model=Nema11, size=size, dual_axis=true);
            motor(model=Nema08, size=size, dual_axis=true);
        }
    }
}

module test2()
{
    $show_vit=true;
    model = Nema17;
    size = NemaMedium;
    all_axes()
    color($color)
    translate(100*$axis)
    motor_mount(model=model, size=size, thickness=6*mm, dual_axis=true, orient=$axis);
    /*motor(model=model, size=size, thickness=6*mm, dual_axis=true, orient=$axis);*/
}

function motorWidth(model) = get(NemaSideSize, model);
function motorLength(model, size=NemaMedium) = get(size, model);

module motor_mount(part=U, model, thickness, size=NemaMedium, extra_size=U, dual_axis=false, orient=Z, align=N)
{
    assert(model!=U, "motor_mount(): model==U");
    assert(thickness!=U, "motor_mount(): thickness==U");
    assert(size!=U, "motor_mount(): size==U");

    length = get(size, model);
    side = get(NemaSideSize, model);
    extrSize = get(NemaRoundExtrusionHeight, model);
    extrRad = get(NemaRoundExtrusionDiameter, model) * 0.5;
    holeDist = get(NemaDistanceBetweenMountingHoles, model) * 0.5;
    holeRadius = get(NemaMountingHoleDiameter, model) * 0.5;

    s=[side+fallback(extra_size.x,0), side+fallback(extra_size.y,0), length];
    size_align(size=s, orient=orient, align=align)
    if(part==U)
    {
        material(Mat_Plastic)
        render()
        difference()
        {
            motor_mount(part="pos", model=model, thickness=thickness, size=size, dual_axis=dual_axis);
            motor_mount(part="neg", model=model, thickness=thickness, size=size, dual_axis=dual_axis);
        }

        if($show_vit)
        motor_mount(part="vit", model=model, thickness=thickness, size=size, dual_axis=dual_axis);
    }
    else if(part=="pos")
    {
        rcubea([s.x,s.y,thickness], align=Z);
    }
    else if(part=="neg")
    {
        cylindera(h=thickness+.1, r=extrRad, align=Z, extra_h=.1, extra_align=-Z);

        // main motor
        tz(-s.z)
        cubea(size=[side+.3*mm,side+.3*mm,length], align=Z);

        // Bolt holes
        material(Mat_Aluminium)
        for(x=[-1,1])
        for(y=[-1,1])
        tx(x*holeDist)
        ty(y*holeDist)
        cylindera(h=thickness+.1, r=holeRadius, align=Z, extra_h=.1, extra_align=-Z);

    }
    else if(part=="vit")
    {
        motor(model=model, size=size, dual_axis=dual_axis);
    }
}

module motor(part=U, model, size=NemaMedium, dual_axis=false, orient=Z, align=N)
{
    assert(model!=U, "model == U");
    assert(size!=U, "size == U");
    length = get(size, model);

    side = get(NemaSideSize, model);
    cutR = get(NemaMountingHoleCutoutRadius, model);
    lip = get(NemaMountingHoleLip, model);
    holeDepth = get(NemaMountingHoleDepth, model);

    axleRadius = get(NemaAxleDiameter, model) * 0.5;

    extrSize = get(NemaRoundExtrusionHeight, model);
    extrRad = get(NemaRoundExtrusionDiameter, model) * 0.5;

    holeDist = get(NemaDistanceBetweenMountingHoles, model) * 0.5;
    holeRadius = get(NemaMountingHoleDiameter, model) * 0.5;

    mid = side / 2;

    roundR = get(NemaEdgeRoundingRadius, model);

    s=[side, side, length];
    size_align(size=s, orient=orient, orient_ref=Z, align=align)
    if(part==U)
    {
        difference()
        {
            motor(part="pos", model=model, size=size, dual_axis=dual_axis);
            motor(part="neg", model=model, size=size, dual_axis=dual_axis);
        }
        motor(part="vit", model=model, size=size, dual_axis=dual_axis);

        motor_axle(model=model, size=size, dual_axis=dual_axis);
    }
    if(part=="echo")
    {
        echo(str("  Motor: Nema",get(NemaModel, model),", length= ",length,"mm, dual axis=",dual_axis));
    }
    else if(part=="pos")
    {
        material(Mat_BlackPaint)
        tz(-s.z)
        cubea(s, align=Z, extra_size=Z*extrSize, extra_align=Z);
    }
    else if(part=="neg")
    {
        // Axle hole
        material(Mat_Aluminium)
        cylindera(r=axleRadius+.2*mm, h=1000);

        // Corner cutouts
        if (lip > 0)
        material(Mat_BlackPaint)
        tz(-s.z)
        for(x=[-1,1])
        for(y=[-1,1])
        tx(x*side/2)
        ty(y*side/2)
        tz(-lip)
        cylindera(h=length, r=cutR, align=Z);

        // Rounded edges
        if (roundR > 0)
        material(Mat_BlackPaint)
        tz(-s.z)
        for(x=[-1,1])
        for(y=[-1,1])
        tx(x*side/2)
        ty(y*side/2)
        mirror([x>0?0:1,y>0?0:1,0])
        rz(45)
        cubea(size=[roundR, roundR*2, 4+length + extrSize+2], align=Z, extra_size=.1*Z, extra_align=-Z);

        // Bolt holes
        material(Mat_Aluminium)
        for(x=[-1,1])
        for(y=[-1,1])
        tx(x*holeDist)
        ty(y*holeDist)
        cylindera(h=holeDepth+.1*mm, r=holeRadius, align=-Z, extra_h=.1, extra_align=Z);

        // Grinded flat
        material(Mat_BlackPaint)
        difference()
        {
            cubea(size=[side+.1, side+.1, extrSize+.1], align=Z);
            cylindera(h=extrSize, r=extrRad, align=Z);
        }
    }
}

module motor_axle(model=Nema23, size=NemaMedium, dual_axis=false, orient=Z, align=U)
{
    assert(model!=U, "model == U");
    assert(size!=U, "size == U");
    length = get(size, model);

    axleLengthFront = get(NemaFrontAxleLength, model);
    axleLengthBack = get(NemaBackAxleLength, model);
    axleRadius = get(NemaAxleDiameter, model) * 0.5;

    extrSize = get(NemaRoundExtrusionHeight, model);

    roundR = get(NemaEdgeRoundingRadius, model);

    axleFlatDepth = get(NemaAxleFlatDepth, model);
    axleFlatLengthFront = get(NemaAxleFlatLengthFront, model);
    axleFlatLengthBack = get(NemaAxleFlatLengthBack, model);

    material(Mat_Steel)
    render()
    intersection()
    {
        material(Mat_Aluminium)
        tz(-length)
        cylindera(r=axleRadius, h=length+extrSize+axleLengthFront, align=Z, extra_h=dual_axis?axleLengthBack:0, extra_align=-Z);

        material(Mat_Aluminium)
        union()
        {
            tx(axleFlatDepth>0?-axleFlatDepth:0)
            cubea(size=[2*axleRadius, 2*axleRadius, axleLengthFront], align=Z);

            cubea(size=[2*axleRadius, 2*axleRadius, length+.4*mm], align=-Z, extra_size=Z*(extrSize+.4*mm), extra_align=Z);

            tx(axleFlatDepth>0?-axleFlatDepth:0)
            tz(-length)
            cubea(size=[2*axleRadius, 2*axleRadius, axleLengthBack], align=-Z);
        }
    }
}


Getting started on a 3D model of a box for iotsa

module iotsaBoard() {
    module esp12() {
        union() {
            cube([24, 16, 2]); // the esp-12 board
            translate([8, 1.5, 2]) cube([15, 13, 2.5]); // the metal cap
        }
    }
    module regulator() {
        translate([0, 0, 2])
        union() {
            translate([0, 4.5, 0]) cube([10.2, 1.3, 15]);
            translate([0, 0, 0]) cube([10.2, 4.5, 8.5]);
        }
    }
    module powerjack() {
        difference() {
            cube([9, 15, 11]);
            translate([4.5, -1, 7]) rotate([-90, 0, 0]) cylinder(14, d=6);
        }
    }
    union() {
        // The board
        difference() {
            cube([63,43,1.8]);
            translate([2, 2, -0.1]) cylinder(2, d=2, center=false, $fn=12);
            translate([2, 41, -0.1]) cylinder(2, d=2, center=false, $fn=12);
        }
        // The components
        translate([-5, 13.5, 1.8]) esp12();
        translate([20, 15, 1.8]) regulator();
        translate([22, -3, 1.8]) powerjack();
    }
}

iotsaBoard();

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