laser mount effector on forearm for testing

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

// global rendering parameters
$fn = 64; // production
//$fn = 48; // development
//$fn = 24; // LQ
echo($fn);

// 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;
iFitAdjust_d = .25;

// 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;
// forearm manipulator
sharpieDiameter = 13;
laserDiodeDiameter = 2 * 3.05;
// 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
// shoulder base
module shoulderBasePlate() { // make me
color([.7, .7, 1])
    shoulderBase(bearing6807_2RS_d - iFitAdjust_d, bearing6807_2RS_D + iFitAdjust, shoulderBaseHeight, shoulderBaseDiameter, shaftBossDiameter, mountScrewDiameter);
}
shoulderBasePlate();
// 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_d, 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
module shoulderSpacerSet() { // make me
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));
}
shoulderSpacerSet();
// end shoulder

// lower arm including the shoulder - arm joint
module armSection() { // make me
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);
}
//render()
armSection();
// 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
module armSpacerSet() { // make me
color([.6, .6, .3])
    armSpacers(bearing6807_2RS_D + iFitAdjust, 0 * shoulderBaseHeight + (4 * bearing6807_2RS_B) + (8 * bearingStep));
}
armSpacerSet();
// end arm

// forearm pieces
// lower
module forearmSection() { // make me
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_d, bearing6807_2RS_D + iFitAdjust, bearingStep, bearingStep, hubHeight + (bearing6807_2RS_B / 2) + (bearingStep/2), hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, forearmLength, boundingBox);
}
forearmSection();
// upper
render()
color([.2, .8, .2])
translate([-armLength, 0, shoulderBaseHeight + (bearing6807_2RS_B * 2) + (4 *bearingStep)])
    rotate([180, 0, 0])
        forearmLower(bearing6807_2RS_d - iFitAdjust_d, 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
// none at this time

//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() {
                        cylinder(h = screwSpacerHeight, r = setScrewRadius * 2);
                        cylinder(h = screwSpacerHeight / 4, r = setScrewRadius);
                        translate([0, 0, screwSpacerHeight * .75])
                            cylinder(h = screwSpacerHeight/4, 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
        translate([- armLength, 0, 0])
        rotate([0, 0, -30])
        radial_array_partial(vec = [0, 0, 1], n = 6, 2)
            translate([bearingOD / 2 + (setScrewRadius * 8), 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);
        }
    }
}

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

        }
               difference() {
               hull() {
                   translate([- armLength, 0, bearingStep])
                    linear_extrude(height = 2 * bearingStep, center = true, twist = 0)
                        polygon(points=[[0, -bearingOD/2 - setScrewRadius/2], [bearingOD / 2 + (setScrewRadius * 8), -armWidth / 2], [bearingOD / 2 + (setScrewRadius * 8), armWidth / 2], [0, bearingOD/2 + setScrewRadius/2]]);
                translate([- armLength, 0, 0])
                    rotate([0, 0, -30])
                    radial_array_partial(vec = [0, 0, 1], n = 6, 2)
                        translate([bearingOD / 2 + (setScrewRadius * 8), 0, 0])
                            cylinder(h = 2 * bearingStep, r = setScrewRadius * 2);

                    }
                translate([- armLength, 0, 0])
                    rotate([0, 0, -30])
                    radial_array_partial(vec = [0, 0, 1], n = 6, 2)
                        translate([bearingOD / 2 + (setScrewRadius * 8), 0, 0])
                        cylinder(h = 2 * bearingStep, r = setScrewRadius);

                 translate([-armLength + (bearingOD / 2) + (boundingBox / 2), -(armWidth / 2) + boundingBoxHalf, 0])
                    cube([armLength - bearingOD - boundingBox, armWidth - boundingBox, bearingStep * 2], center = false);
             translate([-armLength, 0, 0])
                cylinder(h = bearingStep * 2, d = bearingOD);

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

    //render()
    union() {
        difference() {
            union() {
                translate([0, 0, -(bearingStep * 2)])
                    difference() { // base w/ cutout for seeing into the joint

                        cylinder(h = bearingStep * 2, d = bearingOD + bearingStep);
                    intersection() { // cutout
                        difference() {
                            cylinder(h = bearingStep * 2, d = .85 * bearingOD);
                            cylinder(h = bearingStep * 2, d = .35 * bearingOD);
                        }
                        translate([-bearingOD, -bearingOD/2, 0])
                            cube([bearingOD, bearingOD, bearingStep * 2], center = false);
                    }
                }
                translate([0, 0, bearingStep * 2])
                    rotate([0, 180, 0])
                        bearingOuterStep(bearingOD, bearingStep, bearingStep);
                // spokes
                rotate([0, 0, 150])
                radial_array_partial(vec=[0, 0, 1], n = 6, 2)
                translate([hubRadius - (bearingStep / 2), -(spokeWidth / 2), -(bearingStep * 2)])
                    cube([(bearingOD / 2) - hubRadius, spokeWidth, bearingStep], center = false);
            }
            // 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 * 1.2])
                    cube([(bearingOD / 2) - hubRadius, spokeWidth, stepHeight * .8], 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);
 /* original */
            translate([-forearmLength, 0, 0])
                 cylinder(h = bearingStep * 2, d = laserDiodeDiameter);
                 // 4 on next line comes from dividing the bearingOD on the above line
            translate([-forearmLength + laserDiodeDiameter, -(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);
                }
            }
        // laser mount
        union() {
            translate([-forearmLength, 0, 0])
                difference() {
                    union() {
                        cylinder(h = bearingStep * 2, d = laserDiodeDiameter * 2);
                        translate([-laserDiodeDiameter * 1.75, -1.5, 0])
                            cube([laserDiodeDiameter + 4 * setScrewRadius, 3, bearingStep * 2]);
                    }
                    cylinder(h = bearingStep * 2, d = laserDiodeDiameter);
                    #translate([ - laserDiodeDiameter * 1.75, -.5, 0])
                        cube([laserDiodeDiameter + 4 * setScrewRadius, 1, bearingStep * 2], center = false);
                    translate([-laserDiodeDiameter - 1.5 * setScrewRadius, laserDiodeDiameter * 2, bearingStep])
                        rotate([90, 0, 0])
                            cylinder(h = laserDiodeDiameter * 4, r = setScrewRadius);
                }
            }

    }
}

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 = 64; // production
//$fn = 48; // development
//$fn = 24; // LQ
echo($fn);

// 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;
iFitAdjust_d = .25;

// 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
// shoulder base
module shoulderBasePlate() { // make me
color([.7, .7, 1])
    shoulderBase(bearing6807_2RS_d - iFitAdjust_d, bearing6807_2RS_D + iFitAdjust, shoulderBaseHeight, shoulderBaseDiameter, shaftBossDiameter, mountScrewDiameter);
}
shoulderBasePlate();
// 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_d, 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
module shoulderSpacerSet() { // make me
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));
}
shoulderSpacerSet();
// end shoulder

// lower arm including the shoulder - arm joint
module armSection() { // make me
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);
}
//render()
armSection();
// 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
module armSpacerSet() { // make me
color([.6, .6, .3])
    armSpacers(bearing6807_2RS_D + iFitAdjust, 0 * shoulderBaseHeight + (4 * bearing6807_2RS_B) + (8 * bearingStep));
}
armSpacerSet();
// end arm

// forearm pieces
// lower
module forearmSection() { // make me
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_d, bearing6807_2RS_D + iFitAdjust, bearingStep, bearingStep, hubHeight + (bearing6807_2RS_B / 2) + (bearingStep/2), hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, forearmLength, boundingBox);
}
forearmSection();
// upper
//render()
color([.2, .8, .2])
translate([-armLength, 0, shoulderBaseHeight + (bearing6807_2RS_B * 2) + (4 *bearingStep)])
    rotate([180, 0, 0])
        forearmLower(bearing6807_2RS_d - iFitAdjust_d, 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
// none at this time

//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() {
                        cylinder(h = screwSpacerHeight, r = setScrewRadius * 2);
                        cylinder(h = screwSpacerHeight / 4, r = setScrewRadius);
                        translate([0, 0, screwSpacerHeight * .75])
                            cylinder(h = screwSpacerHeight/4, 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
        translate([- armLength, 0, 0])
        rotate([0, 0, -30])
        radial_array_partial(vec = [0, 0, 1], n = 6, 2)
            translate([bearingOD / 2 + (setScrewRadius * 8), 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);
        }
    }
}

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

        }
               difference() {
               hull() {
                   translate([- armLength, 0, bearingStep])
                    linear_extrude(height = 2 * bearingStep, center = true, twist = 0)
                        polygon(points=[[0, -bearingOD/2 - setScrewRadius/2], [bearingOD / 2 + (setScrewRadius * 8), -armWidth / 2], [bearingOD / 2 + (setScrewRadius * 8), armWidth / 2], [0, bearingOD/2 + setScrewRadius/2]]);
                translate([- armLength, 0, 0])
                    rotate([0, 0, -30])
                    radial_array_partial(vec = [0, 0, 1], n = 6, 2)
                        translate([bearingOD / 2 + (setScrewRadius * 8), 0, 0])
                            cylinder(h = 2 * bearingStep, r = setScrewRadius * 2);

                    }
                translate([- armLength, 0, 0])
                    rotate([0, 0, -30])
                    radial_array_partial(vec = [0, 0, 1], n = 6, 2)
                        translate([bearingOD / 2 + (setScrewRadius * 8), 0, 0])
                        cylinder(h = 2 * bearingStep, r = setScrewRadius);

                 translate([-armLength + (bearingOD / 2) + (boundingBox / 2), -(armWidth / 2) + boundingBoxHalf, 0])
                    cube([armLength - bearingOD - boundingBox, armWidth - boundingBox, bearingStep * 2], center = false);
             translate([-armLength, 0, 0])
                cylinder(h = bearingStep * 2, d = bearingOD);

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

    //render()
    union() {
        difference() {
            union() {
                translate([0, 0, -(bearingStep * 2)])
                    difference() { // base w/ cutout for seeing into the joint

                        cylinder(h = bearingStep * 2, d = bearingOD + bearingStep);
                    intersection() { // cutout
                        difference() {
                            cylinder(h = bearingStep * 2, d = .85 * bearingOD);
                            cylinder(h = bearingStep * 2, d = .35 * bearingOD);
                        }
                        translate([-bearingOD, -bearingOD/2, 0])
                            cube([bearingOD, bearingOD, bearingStep * 2], center = false);
                    }
                }
                translate([0, 0, bearingStep * 2])
                    rotate([0, 180, 0])
                        bearingOuterStep(bearingOD, bearingStep, bearingStep);
                // spokes
                rotate([0, 0, 150])
                radial_array_partial(vec=[0, 0, 1], n = 6, 2)
                translate([hubRadius - (bearingStep / 2), -(spokeWidth / 2), -(bearingStep * 2)])
                    cube([(bearingOD / 2) - hubRadius, spokeWidth, bearingStep], center = false);
            }
            // 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 * 1.2])
                    cube([(bearingOD / 2) - hubRadius, spokeWidth, stepHeight * .8], 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);
 /* original */
sharpieDiameter = 13;
            translate([-forearmLength, 0, 0])
                 cylinder(h = bearingStep * 2, d = sharpieDiameter);
                 // 4 on next line comes from dividing the bearingOD on the above line
            translate([-forearmLength + sharpieDiameter, -(armWidth / 2) + boundingBoxHalf, 0])
                cube([forearmLength - (bearingOD/2) - (boundingBox + boundingBoxHalf), armWidth - boundingBox, bearingStep * 2], center = false);
/**/
        }

            intersection() {

                translate([-forearmLength + boundingBox, -(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();
    }
}


add strain relief for lugs and wire, fix over height

//
// Enclosure for the larger limit switch, specifically this one:
// "Cylewet V-154-1C25 Micro Limit Switch"
//
use <../common/extrusions.scad>

LARGE = 100;
EPSILON = 0.1;

module switch_cover() {
    base_thick = 3; // Thickness of "base" plate
    base_ro = 2; // Outer radii of base plate

    // Switch dimensions
    switch_w = 28 + 0.2;
    switch_d = 16 + 0.2;
    switch_h = 10.2 + 0.8; // + space for sticky tape or wire

    // Nominal offset in y and x of the lower-left-corner
    // of the switch well.
    switch_off_d0 = 8;
    switch_off_w = 12;

    switch_r = 3; // inner radius of switch well
    top_gap_w = 18.5; // width of gap on the top, from LHS
    top_gap_d = 5; // depth (in y) of the top gap, from the top
    top_wall_thick = 3.5; // thickness (y) of top wall
    right_wall_thick = 3; // thickness (x) of right wall

    bottom_gap_w = 14; // width of bottom gap, from RHS
    bottom_gap_d = 11; // depth (in y) of bottom gap, from bottom

    // These are for screw holes
    hole_dist_x = 16; //Distance of screw holes in x == Tetrix spacing
    hole_dist_y = 8;  // Distance of scew holes in y == Lego spacing
    hole_wall_thick = 3; // Min thickness of walls around a hole
    hole_r = 2.05; // Just enough for 3/32 (imperial) screws to slip through easily

    // Extension to the right for lugs & wire strain relief
    strain_r = 2;
    strain_w = 20; // x
    strain_d = 13; /// y
    strain_h = base_thick + 1; // z. Extends slightly above base to be closer to lugs

    // These are minimum distances to check against when computing
    // how much deep (in y) to start the well for the switch - so that there is
    // enough space around each hole in the y-direction
    bot_hole_check = 2*hole_wall_thick + 2*hole_r;
    top_of_top_hole = 2*hole_wall_thick + hole_r + hole_dist_y + hole_r;
    top_hole_check = top_of_top_hole - (switch_d  - top_gap_d);
    switch_off_d = max(switch_off_d0, bot_hole_check, top_hole_check);

    top_gap_end_x = switch_off_w + top_gap_w;
    bottom_gap_end_x = switch_off_w + bottom_gap_w;
    bottom_gap_end_y = switch_off_d + bottom_gap_d;
    base_d = switch_off_d + switch_d + top_wall_thick;
    tot_thick = base_thick + switch_h;
    hole_x = hole_wall_thick + hole_r;
    hole_y = hole_wall_thick + hole_r;
    base_w = switch_off_w + switch_w + right_wall_thick; // thickness of base

    difference() {
        oblong(base_w, base_d, base_ro, tot_thick); // Starting block
        translate([switch_off_w, switch_off_d, base_thick])
            oblong(switch_w, switch_d, switch_r, LARGE); // remove switch well
        translate([-EPSILON, switch_off_d + switch_d - top_gap_d, base_thick])
            cube([top_gap_end_x+EPSILON, LARGE, LARGE]); // remove top gap
        translate([bottom_gap_end_x, -EPSILON, base_thick])
            cube([LARGE, bottom_gap_end_y + 2*EPSILON, LARGE]); // remove bottom gap
        translate([hole_x, hole_y, -EPSILON])
            cylinder(r=hole_r, h=LARGE); // remove hole 1
        translate([hole_x, hole_y + hole_dist_y, -EPSILON])
            cylinder(r=hole_r, h=LARGE); // remove hole 2
        translate([hole_x  + hole_dist_x, hole_y, -EPSILON])
            cylinder(r=hole_r, h=LARGE); // remove hole 3
    }

    // Add the strain relief extension
    strain_off_x = base_w - strain_r;
    strain_off_y = switch_off_d + (switch_d - strain_d)/2;
    translate([strain_off_x, strain_off_y, 0])
        rotate([90, 0, 90]) oblong(strain_d, strain_h, strain_r, strain_w);
}

module trial1() {
    difference() {
        switch_cover();
        translate([-EPSILON, -EPSILON, -EPSILON]) cube([LARGE, 18, LARGE]);
        translate([-EPSILON, -EPSILON, 6]) cube([LARGE, LARGE, LARGE]);
    }
}

module trial2() {
    difference() {
        switch_cover();
        translate([-EPSILON, -EPSILON, -EPSILON]) cube([30, LARGE, LARGE]);
        translate([35, -EPSILON, -EPSILON]) cube([35, LARGE, LARGE]);
        translate([-EPSILON, -EPSILON, 6]) cube([LARGE, LARGE, LARGE]);
    }
}

$fn = 50;
switch_cover();
//translate([60, 0, 0]) trial1();
//translate([80, 0, 0]) trial2();

//
// Enclosure for the larger limit switch, specifically this one:
// "Cylewet V-154-1C25 Micro Limit Switch"
//
use <../common/extrusions.scad>

LARGE = 100;
EPSILON = 0.1;

module switch_cover() {
    base_thick = 1; // Thickness of "base" plate
    base_ro = 2; // Outer radii of base plate
    switch_thick = 8;

    // Switch dimensions
    switch_w = 28 + 0.2;
    switch_d = 16 + 0.2;
    switch_h = 10 + 0.5; // for sticky tape or wire

    // Nominal offset in y and x of the lower-left-corner
    // of the switch well.
    switch_off_d0 = 8;
    switch_off_w = 12;

    switch_r = 3; // inner radius of switch well
    top_gap_w = 18.5; // width of gap on the top, from LHS
    top_gap_d = 5; // depth (in y) of the top gap, from the top
    top_wall_thick = 3.5; // thickness (y) of top wall
    right_wall_thick = 3; // thickness (x) of right wall

    bottom_gap_w = 14; // width of bottom gap, from RHS
    bottom_gap_d = 11; // depth (in y) of bottom gap, from bottom

    // These are for screw holes
    hole_dist_x = 16; //Distance of screw holes in x == Tetrix spacing
    hole_dist_y = 8;  // Distance of scew holes in y == Lego spacing
    hole_wall_thick = 3; // Min thickness of walls around a hole
    hole_r = 2.05; // Just enough for 3/32 (imperial) screws to slip through easily

    // These are minimum distances to check against when computing
    // how much deep (in y) to start the well for the switch - so that there is
    // enough space around each hole in the y-direction
    bot_hole_check = 2*hole_wall_thick + 2*hole_r;
    top_of_top_hole = 2*hole_wall_thick + hole_r + hole_dist_y + hole_r;
    top_hole_check = top_of_top_hole - (switch_d  - top_gap_d);
    switch_off_d = max(switch_off_d0, bot_hole_check, top_hole_check);

    top_gap_end_x = switch_off_w + top_gap_w;
    bottom_gap_end_x = switch_off_w + bottom_gap_w;
    bottom_gap_end_y = switch_off_d + bottom_gap_d;
    base_d = switch_off_d + switch_d + top_wall_thick;
    tot_thick = base_thick + switch_thick;
    hole_x = hole_wall_thick + hole_r;
    hole_y = hole_wall_thick + hole_r;
    base_w = switch_off_w + switch_w + right_wall_thick; // thickness of base

    difference() {
        oblong(base_w, base_d, base_ro, tot_thick);
        translate([switch_off_w, switch_off_d, base_thick])
            oblong(switch_w, switch_d, switch_r, LARGE);
        translate([-EPSILON, switch_off_d + switch_d - top_gap_d, base_thick])
            cube([top_gap_end_x+EPSILON, LARGE, LARGE]);
        translate([bottom_gap_end_x, -EPSILON, base_thick])
            cube([LARGE, bottom_gap_end_y + 2*EPSILON, LARGE]);
        translate([hole_x, hole_y, -EPSILON])
            cylinder(r=hole_r, h=LARGE);
        translate([hole_x, hole_y + hole_dist_y, -EPSILON])
            cylinder(r=hole_r, h=LARGE);
        translate([hole_x  + hole_dist_x, hole_y, -EPSILON])
            cylinder(r=hole_r, h=LARGE);
    }
}

module trial1() {
    difference() {
        switch_cover();
        translate([-EPSILON, -EPSILON, -EPSILON]) cube([LARGE, 18, LARGE]);
        translate([-EPSILON, -EPSILON, 6]) cube([LARGE, LARGE, LARGE]);
    }
}

module trial2() {
    difference() {
        switch_cover();
        translate([-EPSILON, -EPSILON, -EPSILON]) cube([30, LARGE, LARGE]);
        translate([35, -EPSILON, -EPSILON]) cube([35, LARGE, LARGE]);
        translate([-EPSILON, -EPSILON, 6]) cube([LARGE, LARGE, LARGE]);
    }
}

$fn = 50;
//switch_cover();
translate([60, 0, 0]) trial1();
translate([80, 0, 0]) trial2();


The include path was corrected.

The include path was corrected.

use <../treasure-troll.scad>

// This next commented STL slowed OpenSCAD too much.  So the Blender decimate too was used to reduce the number of faces.
//stlPath = "C:\\home\\world\\versioning\\beto-land-world\\3d-printing\\toys\\treasure-troll\\ercin-gunduz\\troll-doll-planter-1.stl";
stlPath = "C:\\home\\world\\versioning\\beto-land-world\\3d-printing\\toys\\treasure-troll\\ercin-gunduz\\treasure-troll-stl-to-openscad-via-blender-and-back-to-stl-2.stl";

showOriginal  = 0;
showHeadless  = 0;
showHeadOnly  = 1;
showTwoHeaded = 1;

if(showOriginal == 1)
{
    originalTroll(stlPath);
}

if(showHeadless == 1)
{
    headlessTroll(stlPath);
}

if(showHeadOnly == 1)
{
    trollHead(stlPath);
}

if(showTwoHeaded == 1)
{
    twoHeadedTroll(stlPath);
}

use <treasure-troll.scad>

// This next commented STL slowed OpenSCAD too much.  So the Blender decimate too was used to reduce the number of faces.
//stlPath = "C:\\home\\world\\versioning\\beto-land-world\\3d-printing\\toys\\treasure-troll\\ercin-gunduz\\troll-doll-planter-1.stl";
stlPath = "C:\\home\\world\\versioning\\beto-land-world\\3d-printing\\toys\\treasure-troll\\ercin-gunduz\\treasure-troll-stl-to-openscad-via-blender-and-back-to-stl-2.stl";

showOriginal  = 0;
showHeadless  = 0;
showHeadOnly  = 1;
showTwoHeaded = 1;

if(showOriginal == 1)
{
    originalTroll(stlPath);
}

if(showHeadless == 1)
{
    headlessTroll(stlPath);
}

if(showHeadOnly == 1)
{
    trollHead(stlPath);
}

if(showTwoHeaded == 1)
{
    twoHeadedTroll(stlPath);
}


draft of reset button

draft of reset button

module resetButton()
{
  cylinder(r=16/2, h=15);
  // soldering pins:
  translate([0,0,-6])
  {
    translate([-2/2+5,-3/2,0])
      cube([2,3,6]);
    translate([-2/2-5,-3/2,0])
      cube([2,3,6]);
  }
  // mounting cap
  translate([0,0,15-2])
    cylinder(r=22/2, h=2);
  // button's moving part
  translate([0,0,15])
    cylinder(r=16/2-2, h=2);
}

resetButton();

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


gears: add simple test

gears: add simple test

include <system.scad>
include <misc.scad>
include <gears-data.scad>

// SPUR GEARS (all functions assume module/mm system!)
// From http://www.micro-machine-shop.com/module_gear_data.pdf
// Legend:
// M  Metric Module
// C  Circular Pitch (mm)
// DP Diametral Pitch
// N  Number of teeth
// OD Outside Diameter (mm)
// DP Diametral Pitch
// CP Circular Pitch
// A  Addendum
// WD Whole Depth

function spurgear_M_from_PD_N(PD,N) = PD/N;
function spurgear_M_from_C(C) = C/PI;
function spurgear_M_from_DP(DP) = 25.4/DP;
function spurgear_M_from_OD_N(OD, N) = OD/(N+2);

function spurgear_PD_from_M_N(M, N) = M*N;
function spurgear_PD_from_N_OD(N, OD) = (OD*N)/(N+2);
function spurgear_PD_from_OD_M(OD, M) = OD-2*M;

function spurgear_OD_from_M_N(M,N) = (N+2)*M;

function spurgear_DP_from_M(M) = 25.4/M;

function spurgear_CP_from_M(M) = M*PI;

function spurgear_A_from_M(M) = M;

/*function spurgear_WD_from_M(M) = let (DP = spurgear_DP_from_M(M)) DP>=20 ? (2.2/DP+.002) : 2.157*M;*/
function spurgear_WD_from_M(M) = 2.157*M;

function calc_gear_PD(gear) = get(GearMod,gear)*get(GearTeeth,gear);
function calc_gear_OD(gear) = spurgear_OD_from_M_N(get(GearMod,gear),get(GearTeeth,gear));

// CD = (PD1+PD1)/2
function calc_gears_center_distance(A, B) = (calc_gear_PD(A)+calc_gear_PD(B))/2;

if($test_mode)
{
    assert_v(spurgear_M_from_DP(48), 0.529167);

    echo(calc_gear_PD(gear_60t_mod05));
    echo(calc_gears_center_distance(gear_60t_mod05,gear_13t_mod05));

    for(i=[0:1:75])
    echo(i, spurgear_WD_from_M(i));
}

include <system.scad>
include <gears-data.scad>

// SPUR GEARS (all functions assume module/mm system!)
// From http://www.micro-machine-shop.com/module_gear_data.pdf
// Legend:
// M  Metric Module
// C  Circular Pitch (mm)
// DP Diametral Pitch
// N  Number of teeth
// OD Outside Diameter (mm)
// DP Diametral Pitch
// CP Circular Pitch
// A  Addendum
// WD Whole Depth

function spurgear_M_from_PD_N(PD,N) = PD/N;
function spurgear_M_from_C(C) = C/PI;
function spurgear_M_from_DP(DP) = 25.4/DP;
function spurgear_M_from_OD_N(OD, N) = OD/(N+2);

function spurgear_PD_from_M_N(M, N) = M*N;
function spurgear_PD_from_N_OD(N, OD) = (OD*N)/(N+2);
function spurgear_PD_from_OD_M(OD, M) = OD-2*M;

function spurgear_OD_from_M_N(M,N) = (N+2)*M;

function spurgear_DP_from_M(M) = 25.4/M;

function spurgear_CP_from_M(M) = M*PI;

function spurgear_A_from_M(M) = M;

/*function spurgear_WD_from_M(M) = let (DP = spurgear_DP_from_M(M)) DP>=20 ? (2.2/DP+.002) : 2.157*M;*/
function spurgear_WD_from_M(M) = 2.157*M;

function calc_gear_PD(gear) = get(GearMod,gear)*get(GearTeeth,gear);
function calc_gear_OD(gear) = spurgear_OD_from_M_N(get(GearMod,gear),get(GearTeeth,gear));

// CD = (PD1+PD1)/2
function calc_gears_center_distance(A, B) = (calc_gear_PD(A)+calc_gear_PD(B))/2;

if(false)
{
    echo(calc_gear_PD(gear_60t_mod05));
    echo(calc_gears_center_distance(gear_60t_mod05,gear_13t_mod05));

    for(i=[0:1:75])
    echo(i, spurgear_WD_from_M(i));
}


initial model of the coin

initial model of the coin

eps = 0.01;

module qiagen_logo()
{
  translate([-10.5, -9, 0])
    translate([0,0,1+1])
      linear_extrude(1)
//        mirror([1,0,0])
          scale(.42*[1,1])
            import("qiagen_logo.svg");
}

difference()
{
  cylinder(d=30, h=1+1, $fn=100);
  translate([0,0,-eps])
    linear_extrude(1+eps)
      text("#!", size=18, halign="center", valign="center");
}
#qiagen_logo();

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


Added fn variable to add more sides to circles (for rounded corners), now set to 100


bolt heads on the top

bolt heads on the top

tol = 0.5;
screen_tol = 0.8;
pcb_x = 130;
pcb_y = 110;
pcb_z = 4;
bolt_d = 3.6;
shift_bolt = 5;
board_w = 1;
board_h = 1;

// box thickness
th = 2;

shift_x = 4;
shift_y = th + 1;

box_x = pcb_x + shift_x + 4;
box_y = pcb_y + shift_y + th;

pcb_width = 2;
pcb_up = 9;

box_z = th + pcb_up + pcb_width - 1;

socket_h = 15;
socket_w = 10;
socket_n = 5;
socket_int = 20;
start_socket_x = 20 + shift_x;
eps = 1e-1;

usb_type_b_w = 12;
usb_type_b_h = 11;
start_type_b_y = shift_y + 81.5;
//start_type_b_z = th + pcb_z + tol;

usb_type_a_w = 14.4;
usb_type_a_h = 7.8;
start_type_a_y = shift_y + 46;
//start_type_a_z = th + pcb_z + tol;

// programmator
micro_x = 10;
micro_y = 21.1;
micro_start_x = shift_x + 4.75;
micro_start_y = shift_y + pcb_y - 23.3 - micro_y;

contrast_start_x = shift_x + 38.4;
contrast_start_y = shift_y + 25.7;
volume_start_x = shift_x + pcb_x - 39.2;
volume_start_y = contrast_start_y;
pot_d = 7;
under_pcb = 13;
fn = 10;
gaika_h = 4;
gaika_w = 5.5;
stoiki_r = 4;
wide_stoiki_r = stoiki_r + 2;

translate([0,0,-50]) {

difference() {
  union() {
    difference() {
      union() {
        cube([box_x,box_y, box_z-board_h], false);
        translate([th - board_w, th - board_w, 0]) {
          cube([box_x - 2*(th - board_w), box_y - 2*(th -board_w), box_z], false);
        }
      }
      translate([th, th, th]) {
        cube([box_x-2*th+eps, box_y-2*th+eps, box_z-th+eps], false);
      }
    }
    // under_pcb, stoiki
    for (dy = [shift_y+shift_bolt, shift_y+pcb_y-shift_bolt]) {
      for (dx = [shift_x+shift_bolt, shift_x+pcb_x-shift_bolt]) {
//        translate([dx,dy,pcb_up/2+th-eps]) {
//          cube(size=[under_pcb,under_pcb,pcb_up], center=true);
//        }
        translate([dx,dy,th-eps]) {
          cylinder($fn=6, r=stoiki_r, h=pcb_up);
          cylinder($fn=6, r=wide_stoiki_r, h=gaika_h);
        }
      }
    }
    translate([box_x/2, box_y/2, th-eps]) {
      cylinder($fn=6, r=stoiki_r, h=pcb_up);
    }
  }

  // bolts
  for (dx = [shift_x+shift_bolt, shift_x+pcb_x-shift_bolt]) {
    for (dy = [shift_y+shift_bolt, shift_y+pcb_y-shift_bolt]) {
      translate([dx,dy,-eps]) {
        cylinder($fn=fn, r=bolt_d/2, h=th+pcb_up+2*eps);
        // gaika
        cylinder($fn=6, r=gaika_w / 2 / cos(30) + 0.05, h=gaika_h);
      }
    }
  }

//    // usb_in1 type b
//    translate([box_x-th-eps, start_type_b_y-tol, start_type_b_z]) {
//        cube(size=[th+2*eps, usb_type_b_w+2*tol, box_z]);
//    }

//    // usb_out1 type a
//    translate([-eps, start_type_a_y - tol, start_type_a_z]) {
//        cube(size=[th+2*eps, usb_type_a_w + 2*tol, box_z]);
//    }

    // programmator
    translate([micro_start_x-tol,micro_start_y-tol, -eps]) {
      cube(size=[micro_x+2*tol, micro_y+2*tol, th+2*eps]);
    }

    // contrast
    translate([contrast_start_x, contrast_start_y, -eps]) {
      cylinder($fn=fn, r=pot_d/2, h=th+2*eps);
    }

    // volume
//    translate([volume_start_x, volume_start_y, -eps]) {
//      cylinder($fn=20, r=pot_d/2, h=th+2*eps);
//    }
}
}

top_box_z = 15 + th;
stoiki_h = top_box_z - th;
wide_stoiki_h = 4;
pcb_room = 1;
screen_start_x = shift_x + 29;
screen_start_y = shift_y + 38.9;
screen_length_x = 71.2;
screen_length_y = 24.2;
screen_hold_x = 40;
screen_hold_y = 4;
screen_hold_start_z = 12.5;
screen_hold_y_shift = 2;
screen_hold_up_x = 15;
screen_hold_up_x_shift = 5;

master_button_y = shift_y + 10;
master_button_x = shift_x + 43;
master_button_int = 21.8;
master_button_r = 3;
top_bolt_h = 1.5;
top_bolt_r = 3.5;
speaker_shift = 18;
speaker_r = 15;
speaker_h = 15;
speaker_hole_d = 10;
speaker_hole_int = 3;
speaker_hole_w = 1.5;
speaker_shift = 18;

!difference() {
  union() {
    // board
    translate([0, 0, -board_h]) {
	difference() {
	    cube([box_x, box_y, board_h + eps], false);
	    translate([board_w, board_w, -eps]) {
		cube([box_x - 2*board_w, box_y - 2*board_w, board_h + 3*eps], false);
	    }
	}
    }
    difference() {
      cube([box_x,box_y,top_box_z], false);
      translate([th, th, -eps]) {
        cube([box_x-2*th+eps, box_y-2*th+eps, top_box_z-th+eps], false);
      }
    }
    // stoiki
    for (dx = [shift_x+shift_bolt, shift_x+pcb_x-shift_bolt]) {
      for (dy = [shift_y+shift_bolt, shift_y+pcb_y-shift_bolt]) {
        translate([dx,dy,pcb_room]) {
          cylinder($fn=6, r=stoiki_r, h=top_box_z-th+eps);
        }
        translate([dx,dy,top_box_z-th-wide_stoiki_h+eps]) {
          cylinder($fn=6, r=wide_stoiki_r, h=wide_stoiki_h+th-2*eps);
        }
      }
    }
    // screen_hold
    translate([screen_start_x + (screen_length_x - screen_hold_x)/2, screen_start_y - screen_hold_y_shift - screen_hold_y, screen_hold_start_z]) {
	cube([screen_hold_x, screen_hold_y, top_box_z - screen_hold_start_z - th + eps]);
    }
    translate([screen_start_x + screen_length_x - screen_hold_up_x - screen_hold_up_x_shift, screen_start_y + screen_length_y + screen_hold_y_shift, screen_hold_start_z]) {
	cube([screen_hold_up_x, screen_hold_y, top_box_z - screen_hold_start_z - th + eps]);
    }
  }
  // - speaker na stoikah
  translate([shift_x + pcb_x - 18, shift_y + 18, 0]) {
    cylinder(r=speaker_r, h = 15, $fn=20);
  }
  // speaker_hole
  for (dy = [shift_y + speaker_shift - speaker_hole_int - speaker_hole_w*3/2,
             shift_y + speaker_shift - speaker_hole_w/2,
             shift_y + speaker_shift + speaker_hole_int + speaker_hole_w/2]) {
    translate([shift_x + pcb_x - speaker_shift - speaker_hole_d, dy, top_box_z-th-eps]) {
      cube(size=[speaker_hole_d, speaker_hole_w, th + 2*eps]);
    }
  }

  // bolts
  for (dx = [shift_x+shift_bolt, shift_x+pcb_x-shift_bolt]) {
    for (dy = [shift_y+shift_bolt, shift_y+pcb_y-shift_bolt]) {
      translate([dx,dy,-eps]) {
        cylinder($fn=fn, r=bolt_d/2, h=top_box_z+2*eps);
      }
      translate([dx, dy, top_box_z - top_bolt_h]) {
        //cylinder($fn=6, r=gaika_w / 2 / cos(30) + 0.05, h=wide_stoiki_h+eps);
        cylinder($fn=6, r=top_bolt_r, h=top_bolt_h + eps);
      }
    }
  }

  // screen
  translate([screen_start_x - screen_tol, screen_start_y - screen_tol, top_box_z - th - eps]) {
      cube([screen_length_x + 2*screen_tol, screen_length_y + 2*screen_tol, th + 2*eps]);
  }
  // sockets
  for (i = [0:1:socket_n-1]) {
      translate([start_socket_x+i*socket_int - tol, box_y-th-eps, -eps - board_h]) {
        cube(size=[socket_w + 2*tol, th+2*eps, socket_h + board_h]);
      }
  }
  // type_b
  translate([box_x - th - eps, start_type_b_y - tol, -tol - board_h]) {
      cube([th + 2*eps, usb_type_b_w + 2*tol, usb_type_b_h + 2*tol + board_h]);
  }
  // type_a
  translate([-eps, start_type_a_y - tol, -eps - board_h]) {
      cube([th + 2*eps, usb_type_a_w + 2*tol, usb_type_a_h + 2*eps + board_h]);
  }
  // master buttons
  for (i = [0:1:2]) {
    translate([master_button_x + master_button_int*i, master_button_y, top_box_z - th - eps]) {
      cylinder($fn=fn, r=master_button_r + tol, h=th+2*eps);
    }
  }
}

//// bolts
//for (dx = [shift_x+shift_bolt, shift_x+pcb_x-shift_bolt]) {
//  for (dy = [shift_y+shift_bolt, shift_y+pcb_y-shift_bolt]) {
//    difference() {
//      translate([dx,dy,pcb_up/2+th]) {
//        cube(size=[a,a,pcb_up], center=true);
//      }
//      translate([dx,dy,-eps]) {
//        cylinder($fn=20, r=bolt_d/2, h=th+pcb_up+2*eps);
//      }
//    }
//  }
//}

//leg_r = t;
//shift = t/2+leg_r;
//for (dx = [shift, a-shift])
//    for (dy = [shift, b-shift]) {
//        translate([dx, dy, 0]) {
//            cylinder(h=c, r=leg_r, $fn=40);
//        }
//    }

tol = 0.5;
screen_tol = 0.8;
pcb_x = 130;
pcb_y = 110;
pcb_z = 4;
bolt_d = 3.6;
shift_bolt = 5;
board_w = 1;
board_h = 1;

// box thickness
th = 2;

shift_x = 4;
shift_y = th + 1;

box_x = pcb_x + shift_x + 4;
box_y = pcb_y + shift_y + th;

pcb_width = 2;
pcb_up = 9;

box_z = th + pcb_up + pcb_width - 1;

socket_h = 15;
socket_w = 10;
socket_n = 5;
socket_int = 20;
start_socket_x = 20 + shift_x;
eps = 1e-1;

usb_type_b_w = 12;
usb_type_b_h = 11;
start_type_b_y = shift_y + 81.5;
//start_type_b_z = th + pcb_z + tol;

usb_type_a_w = 14.4;
usb_type_a_h = 7.8;
start_type_a_y = shift_y + 46;
//start_type_a_z = th + pcb_z + tol;

// programmator
micro_x = 10;
micro_y = 21.1;
micro_start_x = shift_x + 4.75;
micro_start_y = shift_y + pcb_y - 23.3 - micro_y;

contrast_start_x = shift_x + 38.4;
contrast_start_y = shift_y + 25.7;
volume_start_x = shift_x + pcb_x - 39.2;
volume_start_y = contrast_start_y;
pot_d = 7;
under_pcb = 13;
fn = 10;
gaika_h = 4;
gaika_w = 5.5;
stoiki_r = 4;
wide_stoiki_r = stoiki_r + 2;

translate([0,0,-50]) {

difference() {
  union() {
    difference() {
      union() {
        cube([box_x,box_y, box_z-board_h], false);
        translate([th - board_w, th - board_w, 0]) {
          cube([box_x - 2*(th - board_w), box_y - 2*(th -board_w), box_z], false);
        }
      }
      translate([th, th, th]) {
        cube([box_x-2*th+eps, box_y-2*th+eps, box_z-th+eps], false);
      }
    }
    // under_pcb, stoiki
    for (dy = [shift_y+shift_bolt, shift_y+pcb_y-shift_bolt]) {
      for (dx = [shift_x+shift_bolt, shift_x+pcb_x-shift_bolt]) {
//        translate([dx,dy,pcb_up/2+th-eps]) {
//          cube(size=[under_pcb,under_pcb,pcb_up], center=true);
//        }
        translate([dx,dy,th-eps]) {
          cylinder($fn=6, r=stoiki_r, h=pcb_up);
          cylinder($fn=6, r=wide_stoiki_r, h=gaika_h);
        }
      }
    }
    translate([box_x/2, box_y/2, th-eps]) {
      cylinder($fn=6, r=stoiki_r, h=pcb_up);
    }
  }

  // bolts
  for (dx = [shift_x+shift_bolt, shift_x+pcb_x-shift_bolt]) {
    for (dy = [shift_y+shift_bolt, shift_y+pcb_y-shift_bolt]) {
      translate([dx,dy,-eps]) {
        cylinder($fn=fn, r=bolt_d/2, h=th+pcb_up+2*eps);
        // gaika
        cylinder($fn=6, r=gaika_w / 2 / cos(30) + 0.05, h=gaika_h);
      }
    }
  }

//    // usb_in1 type b
//    translate([box_x-th-eps, start_type_b_y-tol, start_type_b_z]) {
//        cube(size=[th+2*eps, usb_type_b_w+2*tol, box_z]);
//    }

//    // usb_out1 type a
//    translate([-eps, start_type_a_y - tol, start_type_a_z]) {
//        cube(size=[th+2*eps, usb_type_a_w + 2*tol, box_z]);
//    }

    // programmator
    translate([micro_start_x-tol,micro_start_y-tol, -eps]) {
      cube(size=[micro_x+2*tol, micro_y+2*tol, th+2*eps]);
    }

    // contrast
    translate([contrast_start_x, contrast_start_y, -eps]) {
      cylinder($fn=fn, r=pot_d/2, h=th+2*eps);
    }

    // volume
//    translate([volume_start_x, volume_start_y, -eps]) {
//      cylinder($fn=20, r=pot_d/2, h=th+2*eps);
//    }
}
}

top_box_z = 15 + th;
stoiki_h = top_box_z - th;
wide_stoiki_h = 4;
pcb_room = 1;
screen_start_x = shift_x + 29;
screen_start_y = shift_y + 38.9;
screen_length_x = 71.2;
screen_length_y = 24.2;
screen_hold_x = 40;
screen_hold_y = 4;
screen_hold_start_z = 12.5;
screen_hold_y_shift = 2;
screen_hold_up_x = 15;
screen_hold_up_x_shift = 5;

master_button_y = shift_y + 10;
master_button_x = shift_x + 43;
master_button_int = 21.8;
master_button_r = 3;
top_bolt_h = 1.5;
top_bolt_r = 3.5;
speaker_shift = 18;
speaker_r = 15;
speaker_h = 15;
speaker_hole_d = 10;
speaker_hole_int = 3;
speaker_hole_w = 1.5;
speaker_shift = 18;

!difference() {
  union() {
    // board
    translate([0, 0, -board_h]) {
	difference() {
	    cube([box_x, box_y, board_h + eps], false);
	    translate([board_w, board_w, -eps]) {
		cube([box_x - 2*board_w, box_y - 2*board_w, board_h + 3*eps], false);
	    }
	}
    }
    difference() {
      cube([box_x,box_y,top_box_z], false);
      translate([th, th, -eps]) {
        cube([box_x-2*th+eps, box_y-2*th+eps, top_box_z-th+eps], false);
      }
    }
    // stoiki
    for (dx = [shift_x+shift_bolt, shift_x+pcb_x-shift_bolt]) {
      for (dy = [shift_y+shift_bolt, shift_y+pcb_y-shift_bolt]) {
        translate([dx,dy,pcb_room]) {
          cylinder($fn=6, r=stoiki_r, h=top_box_z-th+eps);
        }
        translate([dx,dy,top_box_z-th-wide_stoiki_h+eps]) {
          cylinder($fn=6, r=wide_stoiki_r, h=wide_stoiki_h+th-2*eps);
        }
      }
    }
    // screen_hold
    translate([screen_start_x + (screen_length_x - screen_hold_x)/2, screen_start_y - screen_hold_y_shift - screen_hold_y, screen_hold_start_z]) {
	cube([screen_hold_x, screen_hold_y, top_box_z - screen_hold_start_z - th + eps]);
    }
    translate([screen_start_x + screen_length_x - screen_hold_up_x - screen_hold_up_x_shift, screen_start_y + screen_length_y + screen_hold_y_shift, screen_hold_start_z]) {
	cube([screen_hold_up_x, screen_hold_y, top_box_z - screen_hold_start_z - th + eps]);
    }
  }
  // - speaker na stoikah
  translate([shift_x + pcb_x - 18, shift_y + 18, 0]) {
    cylinder(r=speaker_r, h = 15, $fn=20);
  }
  // speaker_hole
  for (dy = [shift_y + speaker_shift - speaker_hole_int - speaker_hole_w*3/2,
             shift_y + speaker_shift - speaker_hole_w/2,
             shift_y + speaker_shift + speaker_hole_int + speaker_hole_w/2]) {
    translate([shift_x + pcb_x - speaker_shift - speaker_hole_d, dy, top_box_z-th-eps]) {
      cube(size=[speaker_hole_d, speaker_hole_w, th + 2*eps]);
    }
  }

  // bolts
  for (dx = [shift_x+shift_bolt, shift_x+pcb_x-shift_bolt]) {
    for (dy = [shift_y+shift_bolt, shift_y+pcb_y-shift_bolt]) {
      translate([dx,dy,-eps]) {
        cylinder($fn=fn, r=bolt_d/2, h=top_box_z+2*eps);
      }
      translate([dx, dy, top_box_z - wide_stoiki_h]) {
        cylinder($fn=6, r=gaika_w / 2 / cos(30) + 0.05, h=wide_stoiki_h+eps);
        //cylinder($fn=6, r=top_bolt_r, h=top_bolt_h + eps);
      }
    }
  }

  // screen
  translate([screen_start_x - screen_tol, screen_start_y - screen_tol, top_box_z - th - eps]) {
      cube([screen_length_x + 2*screen_tol, screen_length_y + 2*screen_tol, th + 2*eps]);
  }
  // sockets
  for (i = [0:1:socket_n-1]) {
      translate([start_socket_x+i*socket_int - tol, box_y-th-eps, -eps - board_h]) {
        cube(size=[socket_w + 2*tol, th+2*eps, socket_h + board_h]);
      }
  }
  // type_b
  translate([box_x - th - eps, start_type_b_y - tol, -tol - board_h]) {
      cube([th + 2*eps, usb_type_b_w + 2*tol, usb_type_b_h + 2*tol + board_h]);
  }
  // type_a
  translate([-eps, start_type_a_y - tol, -eps - board_h]) {
      cube([th + 2*eps, usb_type_a_w + 2*tol, usb_type_a_h + 2*eps + board_h]);
  }
  // master buttons
  for (i = [0:1:2]) {
    translate([master_button_x + master_button_int*i, master_button_y, top_box_z - th - eps]) {
      cylinder($fn=fn, r=master_button_r + tol, h=th+2*eps);
    }
  }
}

//// bolts
//for (dx = [shift_x+shift_bolt, shift_x+pcb_x-shift_bolt]) {
//  for (dy = [shift_y+shift_bolt, shift_y+pcb_y-shift_bolt]) {
//    difference() {
//      translate([dx,dy,pcb_up/2+th]) {
//        cube(size=[a,a,pcb_up], center=true);
//      }
//      translate([dx,dy,-eps]) {
//        cylinder($fn=20, r=bolt_d/2, h=th+pcb_up+2*eps);
//      }
//    }
//  }
//}

//leg_r = t;
//shift = t/2+leg_r;
//for (dx = [shift, a-shift])
//    for (dy = [shift, b-shift]) {
//        translate([dx, dy, 0]) {
//            cylinder(h=c, r=leg_r, $fn=40);
//        }
//    }


Commented code was removed.

Commented code was removed.

use <../../../shapes/cup/cup.scad>;
use <../../../cutouts/rotated-spiral-cutouts.scad>;

charmCount = 6;

difference()
{
	cup();

	propossedRotatedSpiralCutout(charmCount = 6,
								 xyScale = 0.125,
								 charmStl = "../../../shapes/spurs/spurs-a.stl",
								 yTranslateFactor = 0,
								 yTranslateMinimum = 35,
								 zRotationFactor = 360.0 / charmCount);
}

use <../../../shapes/cup/cup.scad>;
use <../../../cutouts/rotated-spiral-cutouts.scad>;

charmCount = 6;

difference()
{
	cup();

//	originalRotatedSpiralCutout(verticalSpacingFromBottom=35);

	propossedRotatedSpiralCutout(charmCount = 6,
								 xyScale = 0.125,
								 charmStl = "../../../shapes/spurs/spurs-a.stl",
								 yTranslateFactor = 0,
								 yTranslateMinimum = 35,
								 zRotationFactor = 360.0 / charmCount);
}


refactor

refactor

use <../../../basics/rounded-edges/doughnuts/doughnuts.scad>;

use <../../../shapes/geometry/arc/extruded/extruded-arc.scad>;

module halfCirclePhoneStand(height = 19.125,
                            minkowskiSphereRadius = 0.5,
                            arcRadius = 36,
                            arcRadiusExtension = 1.5)
{
    halfCirclePhoneStand_cradle(height = height,
                                minkowskiSphereRadius = minkowskiSphereRadius,
                                radius = arcRadius,
                                radiusExtension = arcRadiusExtension);

    halfCirclePhoneStand_stand(height = height,
                               minkowskiSphereRadius = minkowskiSphereRadius);
}

// sub-modules and functions follow

function halfCirclePhoneStand_cradle_cutout_zLength() = 4.2;

function halfCirclePhoneStand_cradle_cutout_zTranslate(minkowskiSphereRadius,
                                                        bedHeight,
                                                        zLength) = minkowskiSphereRadius + (bedHeight / 2.0) - (zLength / 2.0);

module halfCirclePhoneStand_cradle(height,
                                   minkowskiSphereRadius,
                                   radius,
                                   radiusExtension)
{
    xTranslate = 30;
    yTranslate = 32.7;

    difference()
    {
        halfCirclePhoneStand_cradle_bed(height = height,
                                           minkowskiSphereRadius = minkowskiSphereRadius,
                                           radius = radius,
                                           radiusExtension = radiusExtension,
                                           xTranslate = xTranslate,
                                           yTranslate = yTranslate);

        halfCirclePhoneStand_cradle_cutout(bedHeight = height,
                                        minkowskiSphereRadius = minkowskiSphereRadius,
                                        radius = radius,
                                        radiusExtension = radiusExtension,
                                        bed_xTranslate = xTranslate,
                                        bed_yTranslate = yTranslate);
    }
}

module halfCirclePhoneStand_cradle_bed(height,
                                       minkowskiSphereRadius,
                                       radius,
                                       radiusExtension,
                                       xTranslate,
                                       yTranslate)
{
    zTranslate = minkowskiSphereRadius;
    color("magenta")
    translate([xTranslate, yTranslate, zTranslate])
    rotate([0, 0, 213])
    roundedRectangularArc(angle = 150,
                          height = height,
                          minkowskiRadius = minkowskiSphereRadius,
                          radius = radius,
                          radiusExtension = radiusExtension);
}

module halfCirclePhoneStand_cradle_cutout(bedHeight,
                                          minkowskiSphereRadius,
                                          radius,
                                          radiusExtension,
                                          bed_xTranslate,
                                          bed_yTranslate)
{
    zLength = halfCirclePhoneStand_cradle_cutout_zLength();

    cutoutRadiusExtension = radiusExtension + 3;

    xTranslate = bed_xTranslate + 0.2;
    yTranslate = bed_yTranslate + 0.2;
    zTranslate = halfCirclePhoneStand_cradle_cutout_zTranslate(minkowskiSphereRadius = minkowskiSphereRadius,
                                                                bedHeight = bedHeight,
                                                                zLength = zLength);

    color("DarkTurquoise")
    translate([xTranslate, yTranslate, zTranslate])
    rotate([0, 0, 227])
    roundedRectangularArc(angle = 37,
                          height = zLength,
                          minkowskiRadius = minkowskiSphereRadius,
                          radius = radius,
                          radiusExtension = cutoutRadiusExtension);
}

module halfCirclePhoneStand_stand(height,
                                  minkowskiSphereRadius)
{
//PICK UP HERE

    halfCirclePhoneStand_stand_top(height = height,
                                   minkowskiSphereRadius = minkowskiSphereRadius);

//    halfCirclePhoneStand_stand_connectorBar();

    halfCirclePhoneStand_stand_base(height = height,
                                    minkowskiSphereRadius = minkowskiSphereRadius);
}

module halfCirclePhoneStand_stand_base(height,
                                       minkowskiSphereRadius)
{
    color("green")
    translate([0, 0, minkowskiSphereRadius])
    roundDoughnut(height = height,
                innerRadius = 4.9,      // 4.9
                outerRadius = 5.59,     // 5.59
                minkowskiSphereRadius = minkowskiSphereRadius);
}

module halfCirclePhoneStand_stand_connectorBar()
{
    cube([40, 5, 5]);
}

module halfCirclePhoneStand_stand_top(height,
                                      minkowskiSphereRadius)
{
    xTranslate = 8.105;  // 8.05     // 8.1
    yTranslate = 8.85;  // 8.85     // 8.9

    color("green")
    translate([xTranslate, yTranslate, minkowskiSphereRadius])
    roundDoughnut(height = height,
                innerRadius = 1.9,  // 2.0
                outerRadius = 2.6,  // 2.6
                minkowskiSphereRadius = minkowskiSphereRadius);
}

use <../../../basics/rounded-edges/doughnuts/doughnuts.scad>;

use <../../../shapes/geometry/arc/extruded/extruded-arc.scad>;

module halfCirclePhoneStand(height = 19.125,
                            minkowskiSphereRadius = 0.5,
                            arcRadius = 36,
                            arcRadiusExtension = 1.5)
{
    halfCirclePhoneStand_cradle(height = height,
                                minkowskiSphereRadius = minkowskiSphereRadius,
                                radius = arcRadius,
                                radiusExtension = arcRadiusExtension);

    halfCirclePhoneStand_stand(height = height,
                               minkowskiSphereRadius = minkowskiSphereRadius);
}

// sub-modules and functions follow

module halfCirclePhoneStand_cradle(height,
                                   minkowskiSphereRadius,
                                   radius,
                                   radiusExtension)
{
    xTranslate = 30;
    yTranslate = 32.7;

    difference()
    {
        halfCirclePhoneStand_cradle_bed(height = height,
                                           minkowskiSphereRadius = minkowskiSphereRadius,
                                           radius = radius,
                                           radiusExtension = radiusExtension,
                                           xTranslate = xTranslate,
                                           yTranslate = yTranslate);

        halfCirclePhoneStand_cradle_cutout(bedHeight = height,
                                        minkowskiSphereRadius = minkowskiSphereRadius,
                                        radius = radius,
                                        radiusExtension = radiusExtension,
                                        bed_xTranslate = xTranslate,
                                        bed_yTranslate = yTranslate);
    }
}

module halfCirclePhoneStand_cradle_bed(height,
                                       minkowskiSphereRadius,
                                       radius,
                                       radiusExtension,
                                       xTranslate,
                                       yTranslate)
{
    zTranslate = minkowskiSphereRadius;
    color("magenta")
    translate([xTranslate, yTranslate, zTranslate])
    rotate([0, 0, 213])
    roundedRectangularArc(angle = 150,
                          height = height,
                          minkowskiRadius = minkowskiSphereRadius,
                          radius = radius,
                          radiusExtension = radiusExtension);
}

module halfCirclePhoneStand_cradle_cutout(bedHeight,
                                          minkowskiSphereRadius,
                                          radius,
                                          radiusExtension,
                                          bed_xTranslate,
                                          bed_yTranslate)
{
    zLength = 4.2;

    cutoutRadiusExtension = radiusExtension + 3;

    xTranslate = bed_xTranslate + 0.2;
    yTranslate = bed_yTranslate + 0.2;
    zTranslate = minkowskiSphereRadius + (bedHeight / 2.0) - (zLength / 2.0);

    color("magenta")
    translate([xTranslate, yTranslate, zTranslate])
    rotate([0, 0, 227])
    roundedRectangularArc(angle = 37,
                          height = zLength,
                          minkowskiRadius = minkowskiSphereRadius,
                          radius = radius,
                          radiusExtension = cutoutRadiusExtension);
}

module halfCirclePhoneStand_stand(height,
                                  minkowskiSphereRadius)
{
    halfCirclePhoneStand_stand_top(height = height,
                                   minkowskiSphereRadius = minkowskiSphereRadius);

    halfCirclePhoneStand_stand_connectorBar();

    halfCirclePhoneStand_stand_base(height = height,
                                    minkowskiSphereRadius = minkowskiSphereRadius);
}

module halfCirclePhoneStand_stand_base(height,
                                       minkowskiSphereRadius)
{
    color("green")
    translate([0, 0, minkowskiSphereRadius])
    roundDoughnut(height = height,
                innerRadius = 4.9,      // 4.9
                outerRadius = 5.59,     // 5.59
                minkowskiSphereRadius = minkowskiSphereRadius);
}

module halfCirclePhoneStand_stand_connectorBar()
{

}

module halfCirclePhoneStand_stand_top(height,
                                      minkowskiSphereRadius)
{
    xTranslate = 8.105;  // 8.05     // 8.1
    yTranslate = 8.85;  // 8.85     // 8.9

    color("green")
    translate([xTranslate, yTranslate, minkowskiSphereRadius])
    roundDoughnut(height = height,
                innerRadius = 1.9,  // 2.0
                outerRadius = 2.6,  // 2.6
                minkowskiSphereRadius = minkowskiSphereRadius);
}


Suika frame

Suika frame

MOTOR_DIST_X = 37.5;
MOTOR_DIST_Y = 37.5;
MOTOR_DIAMETER = 6.9;

WIRING_HOLE_OFFSET = 0.7;
WIRING_HOLE_DIAMETER = 2;

ARM_WIDTH = 11;
PLATE_DIMENSIONS = [30, 45];

ZIP_TIE_HOLE_OFFSETS = [0.15, 0.4, 0.6, 0.85];
ZIP_TIE_HOLE_DIAM = 3;

module MainPlate()
{
  motor_positions = [
    [MOTOR_DIST_X, MOTOR_DIST_Y],
    [-MOTOR_DIST_X, MOTOR_DIST_Y],
    [MOTOR_DIST_X, -MOTOR_DIST_Y],
    [-MOTOR_DIST_X, -MOTOR_DIST_Y]
  ];

  module Plate()
  {
    square(PLATE_DIMENSIONS, center=true);
  }

  module MotorCross()
  {
    for(p=motor_positions)
    {
      hull()
      {
        circle(d=ARM_WIDTH);
        translate(p)
          circle(d=ARM_WIDTH);
      }
    }
  }

  module MotorMountingHoles()
  {
    for(p=motor_positions)
    {
      translate(p)
        circle(d=MOTOR_DIAMETER);

      translate(p * WIRING_HOLE_OFFSET)
        circle(d=WIRING_HOLE_DIAMETER);
    }
  }

  module Cutouts()
  {
    half_dim = PLATE_DIMENSIONS / 2;
    translate(-half_dim)
    {
      for(i=ZIP_TIE_HOLE_OFFSETS)
      {
        translate([PLATE_DIMENSIONS[0] * 0.85, PLATE_DIMENSIONS[1] * i])
          circle(d=ZIP_TIE_HOLE_DIAM);
        translate([PLATE_DIMENSIONS[0] * 0.15, PLATE_DIMENSIONS[1] * i])
          circle(d=ZIP_TIE_HOLE_DIAM);
      }
    }
  }

  difference()
  {
    union()
    {
      Plate();
      MotorCross();
    }

    union()
    {
      MotorMountingHoles();
      Cutouts();
    }
  }
}

module MotorRetentionClips()
{
  difference()
  {
    circle(d=ARM_WIDTH);
    circle(d=MOTOR_DIAMETER);
  }
}

$fs = 2;
MainPlate();
translate([0, (PLATE_DIMENSIONS[1] / 2) + 10])
  MotorRetentionClips();

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