Updated with stepper motor expansion

Updated with stepper motor expansion

//Make passage for cables larger
RobotY = 220;
RobotX = 80;
RobotZ = 5;
BodyHoleR = 20;
BodyHoleSpace = 55;

plateX = 150;
plateZ = 3;
plateY = RobotX;
cablePassageWidht = 8;
plateanchorX = RobotZ;
plateanchorY = 15;
holeradius = 3;
holespace = 3 * holeradius;
borderZ = 30;
border = 8;
T = 0.3;
$fs = 0.01;

stepperSupportHeight = 70;

border = holespace + ((plateX) / holespace - floor((plateX) / holespace)) / 2;
include < TextGenerator.scad > ;

module put_pilogo(mt) {
    fn = "raspberrypi_logo.dxf";
    // calculate the scale and which offset to use

    linear_extrude(height = mt) import (file = fn, scale = scx);
}

module put_Alogo(mt) {
    fn = "arduino.dxf";
    // calculate the scale and which offset to use

    linear_extrude(height = mt) import (file = fn, scale = scx);
}

module put_OAlogo(mt) {
    fn = "ohw-logo.dxf";
    // calculate the scale and which offset to use
    linear_extrude(height = mt) import (file = fn, scale = scx);
}

module SUB_batteryAnchor() {

}

module arduinoLogo(h, r) {

    scale([0.9, .7, 1]) union() {
        difference() {
            cylinder(h = h, r = r);
            cylinder(h = h, r = r - .25 * r);
        }
        translate([1.8 * r, 0, 0]) difference() {
            cylinder(h = h, r = r);
            cylinder(h = h, r = r - .25 * r);
        }

    }
    translate([0, 0, h / 2]) cube([0.6 * r, 0.2 * r, h], center = true);
    translate([2 * r - 0.4 * r, 0, h / 2]) {
        cube([0.6 * r, 0.2 * r, h], center = true);
        rotate([0, 0, 90]) cube([0.6 * r, 0.2 * r, h], center = true);
    }
}

module plate(plateX, plateY, plateZ, borderZ, holes, baseF, baseB, text) {
    difference() {
        linear_extrude(plateZ, center = true, convexity = 0, twist = 0)

        difference() {

            union() {
                square([plateX, plateY], center = true);

                translate([-plateX / 2 - plateanchorX, plateanchorY + RobotX / 8 - (7 * (RobotX / 8) - plateanchorY), 0]) square([plateanchorX, plateanchorY], center = "True");

                mirror([0, 1, 0]) translate([-plateX / 2 - plateanchorX, plateanchorY + RobotX / 8 - (7 * (RobotX / 8) - plateanchorY), 0]) square([plateanchorX, plateanchorY], center = "True");

                translate([+plateX / 2, plateanchorY + RobotX / 8 - (7 * (RobotX / 8) - plateanchorY), 0]) square([plateanchorX, plateanchorY], center = "True");
                mirror([0, 1, 0]) translate([+plateX / 2, plateanchorY + RobotX / 8 - (7 * (RobotX / 8) - plateanchorY), 0]) square([plateanchorX, plateanchorY], center = "True");

            }

            //punchholes at the bottom of the plate
            if (holes == "True") {
                for (j = [border: holespace: plateY - border]) {
                    for (i = [border: holespace: plateX - 2 * border]) {
                        translate([i + border - plateX / 2 - holeradius / 2, j - plateY / 2, 0]) circle(holeradius);
                    }
                }

            }
        }

        //Passage for cables
        translate([-plateX / 2 + cablePassageWidht, j + border - plateY / 2, 0]) cube([cablePassageWidht, 0.5 * plateY, plateZ], center = true);
        translate([plateX / 2 - cablePassageWidht, j + border - plateY / 2, 0]) cube([cablePassageWidht, 0.5 * plateY, plateZ], center = true);

    }
    if (baseF == "True")
        translate([-plateX / 2, plateY / 2 - plateZ, -plateZ / 2]) cube([plateX, plateZ, borderZ]);
    if (baseB == "True")
        translate([-plateX / 2, -plateY / 2, -plateZ / 2]) cube([plateX, plateZ, borderZ]);

    translate([-plateX / 2, -plateY / 2, 5]) rotate(90, [1, 0, 0]) scale([2, 2, 1]) drawtext(text);

}

module SensorsPlate() {
    IRLedD = 3;

    plate(plateX, plateY, plateZ, borderZ, "True", "True", "false", "");
    difference() {
        translate([0, -plateY / 2 + 10, borderZ - plateZ / 2])
        rotate([180, 0, 0]) difference() {
                scale(v = [1, 0.30, 1]) difference() {
                    cylinder(r = plateX / 2, h = borderZ, center = false);
                    cylinder(r = plateX / 2 - 2 * plateZ, h = borderZ, center = false);
                }

                translate([-plateX / 2, -plateY / 2 + 10, 0]) cube([plateX, 0.35 * plateX / 2, plateY / 2]);
            }
            //hole for the IR sensor
        translate([-plateX / 2 + 12, -plateY / 2 + 2, borderZ / 4]) rotate([100, 0, -30]) translate([6, -3.48, 0]) cube([6, 6.95, 10]);
        translate([-8, -plateY / 2 - 10, borderZ / 4]) rotate([100, 0, 0]) translate([6, -3.48, 0]) cube([6, 6.95, 10]);
        translate([+plateX / 2 - 12, -plateY / 2 + 2, borderZ / 4]) rotate([100, 0, 30]) translate([-12, -3.48, 0]) cube([6, 6.95, 10]);

        //holes for sonars and slots for sensors
        translate([0 + 28, -plateY / 2 - 8, borderZ / 2]) rotate([90, 0, 0]) cylinder(r = 16.8 / 2, h = 8);
        translate([0 - 28, -plateY / 2 - 8, borderZ / 2]) rotate([90, 0, 0]) cylinder(r = 16.8 / 2, h = 8);
        translate([0, -plateY / 2 - 8, borderZ / 2]) rotate([90, 0, 0]) cube([3, 1, 5]);
        translate([-plateX / 2 + 12, -plateY / 2 + 2, borderZ / 2]) rotate([90, 0, -30]) cube([3, 1, 5]);
        translate([+plateX / 2 - 12, -plateY / 2 + 2, borderZ / 2]) rotate([90, 0, 30]) cube([3, 1, 5]);

        translate([-plateX / 2 + 12, -plateY / 2 + 2, borderZ / 4]) rotate([100, 0, -30]) cylinder(r = 1.5 + IRLedD, h = 10);
        translate([-8, -plateY / 2 - 10, borderZ / 4]) rotate([100, 0, 0]) cylinder(r = 1.5 + IRLedD, h = 10);
        translate([+plateX / 2 - 12, -plateY / 2 + 2, borderZ / 4]) rotate([100, 0, 30]) cylinder(r = 1.5 + IRLedD, h = 10);
    }

    //Tubes to focus the IR beams
    translate([-plateX / 2, -plateY / 2 - 30, 0]) difference() {
        cylinder(r = 1 + IRLedD, h = 15);
        cylinder(r = IRLedD, h = 15);
    }
    translate([-plateX / 2 + 15, -plateY / 2 - 30, 0]) difference() {
        cylinder(r = 1 + IRLedD, h = 15);
        cylinder(r = IRLedD, h = 15);
    }
    translate([-plateX / 2 + 30, -plateY / 2 - 30, 0]) difference() {
            cylinder(r = 1 + IRLedD, h = 15);
            cylinder(r = IRLedD, h = 15);
        }
        //	translate([-8,-plateY/2-10,borderZ/4]) rotate([100,0,0])difference (){cylinder(r=1.2*IRLedD,h=8); cylinder(r=IRLedD,h=10);}
        //	translate([+plateX/2-12,-plateY/2+2,borderZ/4]) rotate([100,0,30])difference (){cylinder(r=1.2*IRLedD,h=10); cylinder(r=IRLedD,h=8);}
}

module Powerplate() {

    difference() {
        plate(plateX, plateY, plateZ, borderZ, "True", "True", "True", "Power");
        //fix for batteries
        translate([plateX / 2 - 15, plateY / 2 + 5, borderZ / 2]) translate([0, 0, 3]) rotate([90, 0, 0]) cylinder(h = 10, r = 2);
        translate([-plateX / 2 + 15, plateY / 2 + 5, borderZ / 2]) translate([0, 0, 3]) rotate([90, 0, 0]) cylinder(h = 10, r = 2);
        translate([plateX / 2 - 15, -plateY / 2 + 5, borderZ / 2]) translate([0, 0, 3]) rotate([90, 0, 0]) cylinder(h = 10, r = 2);
        translate([-plateX / 2 + 15, -plateY / 2 + 5, borderZ / 2]) translate([0, 0, 3]) rotate([90, 0, 0]) cylinder(h = 10, r = 2);

    }

    translate([plateX / 2 - 15, plateY / 2 + 4, borderZ / 2])
    difference() {
        sphere(2);
        rotate([0, 90, 0]) translate([0.7, 0.6, 0]) cylinder(h = 10, r = 1.1, center = true);
    }
    translate([-plateX / 2 + 15, plateY / 2 + 4, borderZ / 2])
    difference() {
        sphere(2);
        rotate([0, 90, 0]) translate([0.7, 0.6, 0]) cylinder(h = 10, r = 1.1, center = true);
    }
    translate([plateX / 2 - 15, -plateY / 2 - 1, borderZ / 2]) rotate([0, 0, 180])
    difference() {
        sphere(2);
        rotate([0, 90, 0]) translate([0.7, 0.6, 0]) cylinder(h = 10, r = 1.1, center = true);
    }
    translate([-plateX / 2 + 15, -plateY / 2 - 1, borderZ / 2]) rotate([0, 0, 180])
    difference() {
        sphere(2);
        rotate([0, 90, 0]) translate([0.7, 0.6, 0]) cylinder(h = 10, r = 1.1, center = true);
    }

    //mid section
    difference() {
        translate([-plateX / 2, 0, 0]) cube([plateX, plateZ, borderZ]);
        for (i = [1: plateX / 4: plateX]) {
            translate([i + (-plateX / 2) + borderZ / 2, 10, borderZ / 2]) rotate([90, 0, 0]) cylinder(20, r = 0.8 * borderZ / 2);

        }

    }

}

module BrainPlate() {
    plate(plateX, plateY, plateZ, borderZ, "False", "True", "True", "");
    translate([-plateX / 2, -plateY / 2, borderZ / 2]) {
        color("green") rotate([90, 0, 0])
        translate([120, -2, 0]) scale(0.3) arduinoLogo(5, 30);
        translate([5, -12, 0]) scale(0.1) put_pilogo(1.5 / 0.1);
        translate([80, -2, 0]) scale(0.1) put_OAlogo(1.5 / 0.1);
    }
}

module MotorBody() {
    difference() {
        linear_extrude(RobotZ, center = true, convexity = 0, twist = 0) {
                difference() {
                    //eed to redefine the motorbody as a fixed lenght
                    union() {
                        translate([0, RobotX / 2, 0]) square([RobotX, 220 - RobotX - 15]);
                        translate([RobotX / 2, 40, 0]) circle(RobotX / 2);
                    }
                    translate([RobotX / 2, 40, 0]) circle(26 / 2);
                    translate([RobotX / 2, 40, 0]) circle(3);

                    //Motor holes
                    translate([RobotX / 2, 40, 0]) {
                            for (i = [0: 4]) {
                                rotate((i * 360 / 4) + 45)
                                    //datasheet provides distance between holes, we need the radius from the shaft
                                translate([21.92, 0, 0])
                                circle(3);
                            }
                        }
                        //Modules
                    for (i = [112: BodyHoleSpace: RobotY]) {
                        translate([RobotX / 2, i, 0]) circle(BodyHoleR);
                        //Slots for plates
                        translate([RobotX / 8, i - BodyHoleR - 5, 0]) square([1.15 * plateanchorY, 1.15 * plateZ]);
                        translate([7 * (RobotX / 8) - plateanchorY, i - BodyHoleR - 5, 0]) square([plateanchorY, plateZ]);
                        translate([RobotX / 2, i - 25 - plateZ, 0]) circle(3);
                        translate([RobotX / 8, i, 0]) circle(3);
                        translate([7 * RobotX / 8, i, 0]) circle(3);
                    }
                }

            }
            //Connection with body extension
        translate([0, 220 - RobotX + 2, 0]) cube([RobotX, 25, RobotZ / 2]);
        translate([15, 3 * BodyHoleSpace - 25 / 2, -RobotZ / 2]) cylinder(h = 2 * RobotZ, r = 3);
        translate([RobotX - 15, 3 * BodyHoleSpace - 25 / 2, -RobotZ / 2]) cylinder(h = 2 * RobotZ, r = 3);
    }
}

module BodyExtension() {
    difference() {
        linear_extrude(RobotZ, center = true, convexity = 0, twist = 0) {
            difference() {
                square([RobotX, RobotY]);
                for (i = [0: BodyHoleSpace: RobotY]) {
                    translate([RobotX / 2, i, 0]) circle(BodyHoleR);
                    translate([RobotX / 8, i - BodyHoleR - 5, 0]) square([1.15 * plateanchorY, 1.15 * plateZ]);
                    translate([7 * (RobotX / 8) - plateanchorY, i - BodyHoleR - 5, 0]) square([plateanchorY, plateZ]);
                    translate([RobotX / 2, i - 25 - plateZ, 0]) circle(3);
                    translate([RobotX / 8, i, 0]) circle(3);
                    translate([RobotX / 8, i, 0]) circle(3);
                    translate([7 * RobotX / 8, i, 0]) circle(3);

                }

                translate([RobotX / 8, 0, 0]) square([1.05 * plateanchorY, 1.05 * plateZ]);
                translate([7 * (RobotX / 8) - plateanchorY, 0, 0]) square([plateanchorY, plateZ]);
            }

        }

        //creates attachment for other vertical modules
        translate([0, RobotY - 25, 0]) cube([RobotX, 25, RobotZ / 2]);
        translate([15, RobotY - 25 / 2, -RobotZ / 2]) cylinder(h = 2 * RobotZ, r = 3);
        translate([RobotX - 15, RobotY - 25 / 2, -RobotZ / 2]) cylinder(h = 2 * RobotZ, r = 3);

        translate([0, 0, 0]) cube([RobotX, 25, RobotZ / 2]);
        translate([15, 25 / 2, -RobotZ / 2]) cylinder(h = 2 * RobotZ, r = 3);
        translate([RobotX - 15, 25 / 2, -RobotZ / 2]) cylinder(h = 2 * RobotZ, r = 3);
    }

}

module PCBSupport(PCBHoleR) {
    difference() {
        cylinder(h = plateZ + 5, r = holeradius - .2);
        cylinder(h = plateZ + 2, r = holeradius / 2);
        cube([10, 1, 8], center = true);
    }
    translate([0, 0, plateZ + 5]) cylinder(h = 6, r = PCBHoleR);

}

module PCBSupportHole(PCBHoleR, Height) {
    difference() {
        cylinder(h = plateZ + Height, r = holeradius - T);
        cylinder(h = plateZ - 5, r = holeradius / 2);
    }
    translate([0, 0, plateZ + Height]) cylinder(h = 6, r = PCBHoleR);

}

//Draw a prism based on a
//right angled triangle
//l - length of prism
//w - width of triangle
//h - height of triangle
module prism(l, w, h, he) {
    translate([0, l, 0]) rotate(a = [90, 0, 0])
    linear_extrude(height = he) polygon(points = [
        [0, 0],
        [w, 0],
        [0, h]
    ], paths = [
        [0, 1, 2, 0]
    ]);
}

module SUB_nemaMountingPlateHoles() {
        translate([-35 / 2, plateY / 2, 0]) {
            translate([0, 0, 0]) cylinder(h = 15, r = holeradius, center = true);
            translate([35, 0, 0]) cylinder(h = 15, r = holeradius, center = true);
            translate([0, 25, 0]) cylinder(h = 15, r = holeradius, center = true);
            translate([35, 25, 0]) cylinder(h = 15, r = holeradius, center = true);

        }
    }
    //creates attachment for other vertical modules
module base() {
    {
        translate([0, 0, 0]) {
            difference() {
                translate([0, plateY, 25 / 2]) cube([RobotX, RobotZ / 2, 25], center = true);
                translate([BodyHoleSpace / 2 - 3 / 2, plateY, 25 / 2 + 2]) rotate([90, 0, 0]) cylinder(h = 2 * RobotZ, r = 3, center = true);
                translate([-BodyHoleSpace / 2 + 3 / 2, plateY, 25 / 2 + 2]) rotate([90, 0, 0]) cylinder(h = 2 * RobotZ, r = 3, center = true);
            }
        }
        mirror([0, 1, 0]) {
            difference() {
                translate([0, plateY, 25 / 2]) cube([RobotX, RobotZ / 2, 25], center = true);
                translate([BodyHoleSpace / 2 - 3 / 2, plateY, 25 / 2 + 2]) rotate([90, 0, 0]) cylinder(h = 2 * RobotZ, r = 3, center = true);
                translate([-BodyHoleSpace / 2 + 3 / 2, plateY, 25 / 2 + 2]) rotate([90, 0, 0]) cylinder(h = 2 * RobotZ, r = 3, center = true);
            }

        }

    }

    difference() {
        translate([0, 0, 0]) {
            //Bottomo of the baseplate
            cube([RobotX, 2 * (RobotX + RobotZ / 4), 6], center = true);

        }

        translate([-plateY / 2, 0, 0]) {
            // "35/4" because of the distance of the hole in the bracket for the stepper NEMA

            for (i = [-plateX / 5 - 1.5: 2 * holeradius + 3: plateX / 5 + 1.5]) {
                translate([border, i, 0]) cylinder(h = 15, r = holeradius, center = true);
                translate([border + 2 * holeradius + 3, i, 0]) cylinder(h = 15, r = holeradius, center = true);

                translate([plateY - border, i, 0]) cylinder(h = 15, r = holeradius, center = true);
                translate([plateY - border - (2 * holeradius + 3), i, 0]) cylinder(h = 15, r = holeradius, center = true);

            }

        }

        SUB_nemaMountingPlateHoles();
        mirror([0, 1, 0]) SUB_nemaMountingPlateHoles();

        translate([0, 0, 0]) cylinder(h = 15, r = plateX / 10, center = true);

    }

}

module batteryPlate() {
    translate([0, 0, plateZ / 2])
    plate(plateX, 103 + 2 * plateZ, plateZ, plateZ + 5, "True", "True", "True", "");
    translate([-plateanchorY / 2, (103 + 2 * plateZ) / 2, 0])
    difference() {

        cube([plateanchorY, 1.5 * plateanchorX, plateZ], center = "True");
        translate([0, 1.5 * plateanchorX / 2, 0]) cylinder(h = plateZ, r = 2);
        translate([plateanchorY, 1.5 * plateanchorX / 2, 0]) cylinder(h = plateZ, r = 2);
    }
    mirror([0, 1, 0]) translate([-plateanchorY / 2, (103 + 2 * plateZ) / 2, 0])
    difference() {

        cube([plateanchorY, 1.5 * plateanchorX, plateZ], center = "True");
        translate([0, 1.5 * plateanchorX / 2, 0]) cylinder(h = plateZ, r = 2);
        translate([plateanchorY, 1.5 * plateanchorX / 2, 0]) cylinder(h = plateZ, r = 2);
    }

}

module stepperDriverSupport() {

    difference() {
        translate([RobotX / 2, (0 + BodyHoleSpace / 2), 0]) {

            cube([RobotX, 1.6 * BodyHoleSpace, RobotZ / 2], center = true);
            translate([0, 1.6 * BodyHoleSpace / 2, 30 / 2 - RobotZ / 2 / 2]) cube([RobotX, RobotZ / 2, 30], center = true);

        }

        for (i = [-8: BodyHoleSpace: BodyHoleSpace]) {
            translate([RobotX / 8, i, 0]) cylinder(r = 3, h = 10, center = true);
            translate([7 * RobotX / 8, i, 0]) cylinder(r = 3, h = 10, center = true);
        }
        translate([RobotX / 2, 1.4 * BodyHoleSpace, 20]) rotate([90, 0, 0]) cylinder(r = 3, h = 50, center = true);

        translate([RobotX / 2, 0, 0])
        hull() {
            //translate([0,-BodyHoleR,0])cylinder(r=BodyHoleR,h=RobotZ/2,center=true);
            translate([0, 5, 0]) cube([2 * BodyHoleR, 15, 20], center = true);
            translate([0, BodyHoleSpace - RobotZ / 2 - 8, 0]) cylinder(r = BodyHoleR, h = RobotZ / 2, center = true);
        }
        translate([RobotX / 2, -3 * RobotZ + 3, 0]) cylinder(r = 3, h = 10, center = true);
    }

}

base();
//stepperDriverSupport();
//translate([-plateY/2,-plateX/2,0])rotate([90,0,0])BodyExtension();

//Make passage for cables larger

RobotY=220;
RobotX=80;
RobotZ=5;
BodyHoleR=20;
BodyHoleSpace=55;

plateX=150;
plateZ=3;
plateY=RobotX;
plateanchorX=RobotZ;
plateanchorY=15;
holeradius=3;
holespace=3*holeradius;
borderZ=30;
border=8;
T=0.3;

stepperSupportHeight = 70;

border=holespace+((plateX)/holespace-floor((plateX)/holespace))/2;
include <TextGenerator.scad>;

module put_pilogo(mt) {
    fn="raspberrypi_logo.dxf";
    // calculate the scale and which offset to use

    linear_extrude(height=mt) import(file=fn, scale=scx);
}

module put_Alogo(mt) {
    fn="arduino.dxf";
    // calculate the scale and which offset to use

    linear_extrude(height=mt) import(file=fn, scale=scx);
}

module put_OAlogo(mt) {
    fn="ohw-logo.dxf";
    // calculate the scale and which offset to use
    linear_extrude(height=mt) import(file=fn, scale=scx);
}

module arduinoLogo(h,r) {

	scale([0.9,.7,1])union(){
		difference() {cylinder(h=h,r=r);cylinder(h=h,r=r-.25*r);}
		translate([1.8*r,0,0])difference() {cylinder(h=h,r=r);cylinder(h=h,r=r-.25*r);}

	}
translate([0,0,h/2])cube([0.6*r,0.2*r,h], center=true);
translate([2*r-0.4*r,0,h/2]){cube([0.6*r,0.2*r,h], center=true); rotate([0,0,90])cube([0.6*r,0.2*r,h], center=true);}
}

module plate(holes,baseF,baseB,text)
{
difference(){linear_extrude(plateZ, center = true, convexity = 0, twist = 0)

	difference(){

		union(){square ([plateX, plateY], center=true);
			translate([-plateX/2-plateanchorX,plateY-RobotX/8-(7*(RobotX/8)-plateanchorY),0]) square([plateanchorX,plateanchorY], center = "True");

			translate([-plateX/2-plateanchorX,plateanchorY+RobotX/8-(7*(RobotX/8)-plateanchorY),0]) square([plateanchorX,plateanchorY], center = "True");

			translate([+plateX/2,plateY-RobotX/8-(7*(RobotX/8)-plateanchorY),0]) square([plateanchorX,plateanchorY], center = "True");

			translate([+plateX/2,plateanchorY+RobotX/8-(7*(RobotX/8)-plateanchorY),0]) square([plateanchorX,plateanchorY], center = "True");

		}

//punchholes at the bottom of the plate
if (holes=="True")	{
for (j= [0 : holespace : plateY-1*border ]){
	for ( i = [0 : holespace : plateX-2*border ] ){
			translate([i+border-plateX/2+3,j+border-plateY/2, 0]) circle(holeradius);
	}
	}

}
	}

//Passage for cables
translate([-plateX/2+5,j+border-plateY/2, 0]) cube([5,0.5*plateY,plateZ], center=true);
translate([plateX/2-5,j+border-plateY/2, 0]) cube([5,0.5*plateY,plateZ], center=true);

}
if (baseF=="True")
translate([-plateX/2,plateY/2-plateZ,-plateZ/2]) cube([plateX,plateZ,borderZ]);
if (baseB=="True")
translate([-plateX/2,-plateY/2,-plateZ/2]) cube([plateX,plateZ,borderZ]);

translate([-plateX/2,-plateY/2,5])rotate(90,[1,0,0]) scale([2,2,1]) drawtext(text);

}

module SensorsPlate(){
	IRLedD=3;

	plate("True","True","false","");
	difference(){
		translate([0,-plateY/2+10,borderZ-plateZ/2])
		rotate([180,0,0]) difference(){
			scale( v=[1,0.30,1] ) difference() {
					cylinder( r = plateX/2, h=borderZ, center=false );
					cylinder( r = plateX/2-2*plateZ, h=borderZ, center=false );
					}

		 translate([-plateX/2,-plateY/2+10,0])cube([plateX,0.35*plateX/2,plateY/2]);
		}
		//hole for the IR sensor
	 	translate([-plateX/2+12,-plateY/2+2,borderZ/4])rotate([100,0,-30]) translate([6,-3.48,0])cube([6,6.95,10]);
		translate([-8,-plateY/2-10,borderZ/4])rotate([100,0,0]) translate([6,-3.48,0])cube([6,6.95,10]);
		translate([+plateX/2-12,-plateY/2+2,borderZ/4])rotate([100,0,30]) translate([-12,-3.48,0])cube([6,6.95,10]);

		//holes for sonars and slots for sensors
		translate([0+28,-plateY/2-8,borderZ/2])rotate([90,0,0]) cylinder(r=16.8/2,h=8);
		translate([0-28,-plateY/2-8,borderZ/2])rotate([90,0,0]) cylinder(r=16.8/2,h=8);
		translate([0,-plateY/2-8,borderZ/2])rotate([90,0,0]) cube([3,1,5]);
		translate([-plateX/2+12,-plateY/2+2,borderZ/2])rotate([90,0,-30]) cube([3,1,5]);
		translate([+plateX/2-12,-plateY/2+2,borderZ/2])rotate([90,0,30]) cube([3,1,5]);

	translate([-plateX/2+12,-plateY/2+2,borderZ/4]) rotate([100,0,-30])cylinder(r=1.5+IRLedD,h=10);
translate([-8,-plateY/2-10,borderZ/4]) rotate([100,0,0])cylinder(r=1.5+IRLedD,h=10);
translate([+plateX/2-12,-plateY/2+2,borderZ/4]) rotate([100,0,30])cylinder(r=1.5+IRLedD,h=10);
	}

//Tubes to focus the IR beams
	translate([-plateX/2,-plateY/2-30,0]) difference (){cylinder(r=1+IRLedD,h=15); cylinder(r=IRLedD,h=15);}
	translate([-plateX/2+15,-plateY/2-30,0]) difference (){cylinder(r=1+IRLedD,h=15); cylinder(r=IRLedD,h=15);}
	translate([-plateX/2+30,-plateY/2-30,0]) difference (){cylinder(r=1+IRLedD,h=15); cylinder(r=IRLedD,h=15);}
//	translate([-8,-plateY/2-10,borderZ/4]) rotate([100,0,0])difference (){cylinder(r=1.2*IRLedD,h=8); cylinder(r=IRLedD,h=10);}
//	translate([+plateX/2-12,-plateY/2+2,borderZ/4]) rotate([100,0,30])difference (){cylinder(r=1.2*IRLedD,h=10); cylinder(r=IRLedD,h=8);}
}

module PowerPlate(){

	difference(){
	plate("True","True","True","Power");
	//fix for batteries
	translate([plateX/2-15,plateY/2+5,borderZ/2])translate([0,0,3])rotate([90,0,0])cylinder(h=10,r=2);
	translate([-plateX/2+15,plateY/2+5,borderZ/2])translate([0,0,3])rotate([90,0,0])cylinder(h=10,r=2);
	translate([plateX/2-15,-plateY/2+5,borderZ/2])translate([0,0,3])rotate([90,0,0])cylinder(h=10,r=2);
	translate([-plateX/2+15,-plateY/2+5,borderZ/2])translate([0,0,3])rotate([90,0,0])cylinder(h=10,r=2);

	}

	translate([plateX/2-15,plateY/2+4,borderZ/2])
		difference(){
			sphere(2);rotate([0,90,0])translate([0.7,0.6,0])cylinder(h=10,r=1.1, center=true);}
	translate([-plateX/2+15,plateY/2+4,borderZ/2])
		difference(){
			sphere(2);rotate([0,90,0])translate([0.7,0.6,0])cylinder(h=10,r=1.1, center=true);}
	translate([plateX/2-15,-plateY/2-1,borderZ/2])rotate([0,0,180])
		difference(){
			sphere(2);rotate([0,90,0])translate([0.7,0.6,0])cylinder(h=10,r=1.1, center=true);}
	translate([-plateX/2+15,-plateY/2-1,borderZ/2])rotate([0,0,180])
		difference(){
			sphere(2);rotate([0,90,0])translate([0.7,0.6,0])cylinder(h=10,r=1.1, center=true);}

	//mid section
		difference(){
			translate([-plateX/2,0,0]) cube([plateX,plateZ,borderZ]);
			for ( i = [1 : plateX/4 : plateX] ){
				translate([i+(-plateX/2)+borderZ/2,10,borderZ/2]) rotate([90,0,0]) cylinder(20,r=0.8*borderZ/2);

			}

	}

}

module BrainPlate()
{
	plate("False","True","True","");
	translate([-plateX/2,-plateY/2,borderZ/2]){
	color("green")rotate([90,0,0])
		translate([120,-2,0])scale(0.3)arduinoLogo(5,30);
		translate([5,-12,0])scale(0.1)put_pilogo(1.5/0.1);
		translate([80,-2,0])scale(0.1)put_OAlogo(1.5/0.1);}
}

module MotorBody()
{difference(){
	linear_extrude(RobotZ, center = true, convexity = 0, twist = 0){
		difference() {
//eed to redefine the motorbody as a fixed lenght
union(){translate([0,RobotX/2,0]) square([RobotX,220-RobotX-15]);translate([RobotX/2,40,0]) circle(RobotX/2);}
			translate([RobotX/2,40,0]) circle(26/2);
			translate([RobotX/2,40,0]) circle(3);

			//Motor holes
			translate([RobotX/2, 40, 0]){
			for ( i = [0 : 4] )
				{
				    rotate( (i * 360 / 4)+45)
				    //datasheet provides distance between holes, we need the radius from the shaft
					 translate([21.92, 0, 0])
				    circle(3);
				}}
			//Modules
			for ( i = [112 :BodyHoleSpace: RobotY] ){
				translate([RobotX/2,i,0]) circle(BodyHoleR);
		//Slots for plates
				translate([RobotX/8,i-BodyHoleR-5,0]) square([1.15*plateanchorY,1.15*plateZ]);
translate([7*(RobotX/8)-plateanchorY,i-BodyHoleR-5,0]) square([plateanchorY,plateZ]);
				translate([RobotX/2,i-25-plateZ,0]) circle(3);
				translate([RobotX/8,i,0]) circle(3);
				translate([7*RobotX/8,i,0]) circle(3);
			}
		}

	}
		//Connection with body extension
			translate([0,220-RobotX+2,0]) cube([RobotX,25,RobotZ/2]);
			translate([15,3*BodyHoleSpace-25/2,-RobotZ/2])	cylinder(h=2*RobotZ,r=3);
			translate([RobotX-15,3*BodyHoleSpace-25/2,-RobotZ/2])	cylinder(h=2*RobotZ,r=3);
}
}

module BodyExtension()
{ difference() {
	linear_extrude(RobotZ, center = true, convexity = 0, twist = 0){
		difference() {
			square([RobotX,RobotY]);
			for ( i = [0 :BodyHoleSpace: RobotY] ){
				translate([RobotX/2,i,0]) circle(BodyHoleR);
				translate([RobotX/8,i-BodyHoleR-5,0]) square([1.15*plateanchorY,1.15*plateZ]);
				translate([7*(RobotX/8)-plateanchorY,i-BodyHoleR-5,0]) square([plateanchorY,plateZ]);
				translate([RobotX/2,i-25-plateZ,0]) circle(3);							translate([RobotX/8,i,0]) circle(3);
				translate([7*RobotX/8,i,0]) circle(3);

			}

translate([RobotX/8,0,0]) square([1.05*plateanchorY,1.05*plateZ]);
translate([7*(RobotX/8)-plateanchorY,0,0]) square([plateanchorY,plateZ]);
/*
translate([RobotX/8,RobotY-plateanchorY,0]) square([1.05*plateanchorY,1.05*plateZ]);
translate([7*(RobotX/8)-plateanchorY,0,0]) square([plateanchorY,plateZ]);

	*/	}

	}

//creates attachment for other vertical modules
			translate([0,RobotY-25,0]) cube([RobotX,25,RobotZ/2]);
			translate([15,RobotY-25/2,-RobotZ/2])	cylinder(h=2*RobotZ,r=3);
			translate([RobotX-15,RobotY-25/2,-RobotZ/2])	cylinder(h=2*RobotZ,r=3);

			translate([0,0,0]) cube([RobotX,25,RobotZ/2]);
			translate([15,25/2,-RobotZ/2])	cylinder(h=2*RobotZ,r=3);
			translate([RobotX-15,25/2,-RobotZ/2])	cylinder(h=2*RobotZ,r=3);
			}

}

$fs = 0.01;

module PCBSupport(PCBHoleR){
	difference (){
		cylinder(h=plateZ+5,r=holeradius-.2);
		cylinder(h=plateZ+2,r=holeradius/2);
		cube([10,1,8], center=true);
	}
		translate([0,0,plateZ+5])cylinder(h=6,r=PCBHoleR);

}

module PCBSupportHole(PCBHoleR, Height){
	difference (){
		cylinder(h=plateZ+Height,r=holeradius-T);
		cylinder(h=plateZ-5,r=holeradius/2);
	}
		translate([0,0,plateZ+Height])cylinder(h=6,r=PCBHoleR);

}

//Draw a prism based on a
//right angled triangle
//l - length of prism
//w - width of triangle
//h - height of triangle
module prism(l, w, h, he) {
	translate([0, l, 0]) rotate( a= [90, 0, 0])
	linear_extrude(height = he) polygon(points = [
		[0, 0],
		[w, 0],
		[0, h]
	], paths=[[0,1,2,0]]);
}

//creates attachment for other vertical modules
module base(){
	rotate([90,0,0]){
			translate([0,-(RobotY-25),-RobotX]){
				difference(){
					translate([0,RobotY-25,0]) cube([RobotX,25,RobotZ/2]);
					translate([15,RobotY-25/2,-RobotZ/2])	cylinder(h=2*RobotZ,r=3);
					translate([RobotX-15,RobotY-25/2,-RobotZ/2])	cylinder(h=2*RobotZ,r=3);
			}}
			translate([0,0,RobotX]){
				difference(){

				translate([0,-stepperSupportHeight+0,0]) cube([RobotX,25+stepperSupportHeight,5]);

				translate([15,25/2,-RobotZ/2])	cylinder(h=2*RobotZ,r=3);
				translate([RobotX-15,25/2,-RobotZ/2])	cylinder(h=2*RobotZ,r=3);}}}

difference()
{
    translate([0,-RobotX-RobotZ/2,-25/2+7]){

				cube([RobotX,2*(RobotX+RobotZ/4),6], center=false);
                translate([RobotX/2,0,-((5+60)/2)]){rotate([90,0,0])cylinder(h=10, r=38.01/2+T, center=true);

    translate([47.14/2,0,47.14/2])rotate([90,0,0])cylinder(h=10, r=2.5, center=true);

     translate([47.14/2,0,-47.14/2])rotate([90,0,0])cylinder(h=10, r=2.5, center=true);

     translate([-47.14/2,0,47.14/2])rotate([90,0,0])cylinder(h=10, r=2.5, center=true);

     translate([-47.14/2,0,-47.14/2])rotate([90,0,0])cylinder(h=10, r=2.5, center=true);
                }
			}

translate([RobotX/2-border,0,0]) {

for (i= [0 : 2*holeradius+3: plateY - 4*border]){

for (j= [0 : 2*holeradius+3: plateY-2*border ]){

			translate([i-border,j-plateY+border, -10]) cylinder(h=15,r = holeradius);
    translate([i-border,-j+plateY-border, -10]) cylinder(h=15,r = holeradius);
	}
}
    }

    translate([plateX/4,0, 0])cylinder(h=15,r = plateX/15, center=true);

}

}

base();
PCBSupportHole(0,8);
//permaproto drill holes 1.2mm

//MotorBody();
//BodyExtension();
//SensorsPlate();

	//rotate([0,0,90])plate("True","True","True", " Motors");

	//translate([RobotX/2,-RobotX,0])rotate([0,0,90]) prism(3,30,25,RobotZ);


Added springy bits

Added springy bits

for illustration purposes only :)

module Bumper_STL()
{
	printedPart("printedparts/Bumper.scad", "Bumper", "Bumper_STL()") {

	    //view(t=[0, -1, -1], r=[49, 0, 25], d=336);

		if (DebugCoordinateFrames) frame();
		if (DebugConnectors) connector(Wheel_Con_Default);

	    color(Level2PlasticColor) {
            if (UseSTL) {
                import(str(STLPath, "Bumper.stl"));
            } else {
				BumperModel();
            }
        }
	}
}

Bumper_Pin_Width = 3;
Bumper_Pin_Length = 18;

module BumperModel()
{
	thickness = 2;
	height = 15;
	offset = 5;				// distance from base to inside of bumper
	wrapAngle = 170;		// angle that bumper wraps around
	microSwitchAngle = 45;	// angle that microswitches are placed at

	outr = BaseDiameter/2 + offset + thickness; // outr is the outside radius or the bumper

	// Bumper arc
	linear_extrude(height)
	difference() {
		circle(r = outr);

		circle(r = outr - thickness);

		// Chop off below X-axis
		translate([-outr, -outr])
			square([outr*2, outr]);

		// Trim left side of arc
		rotate(a=wrapAngle/2, v=[0,0,1])
		translate([-outr, 0])
			square([outr, outr * 2]);

		// Trim right side of arc
		rotate(a=-wrapAngle/2, v=[0,0,1])
			square([outr, outr * 2]);
	}

	// Guide pins
	for(i=[0,1])
	mirror([i, 0, 0])
	rotate(a=microSwitchAngle, v=[0, 0, 1]) {
		for(i = [0,1])
		mirror([i, 0, 0,]) {
			translate([-1.5 - 8.6, BaseDiameter/2 - Bumper_Pin_Length, 0])
				cube([Bumper_Pin_Width, Bumper_Pin_Length + eta, 5]);
			translate([-1.5 - 8.6, BaseDiameter/2, 0])
				cube([Bumper_Pin_Width + 8.5, offset + eta, 5]);
		}
	}

	// Springy bits - to illustrate the idea
	// would also get rid of the need for the guide pins
	for(i=[0,1])
		mirror([i, 0, 0])
		translate([30, outr - 19, 0])
		rotate([0,0,90])
		linear_extrude(5)
		donutSector(12,11,180, center=true);

}

module Bumper_STL()
{
	printedPart("printedparts/Bumper.scad", "Bumper", "Bumper_STL()") {

	    //view(t=[0, -1, -1], r=[49, 0, 25], d=336);

		if (DebugCoordinateFrames) frame();
		if (DebugConnectors) connector(Wheel_Con_Default);

	    color(Level2PlasticColor) {
            if (UseSTL) {
                import(str(STLPath, "Bumper.stl"));
            } else {
				BumperModel();
            }
        }
	}
}

Bumper_Pin_Width = 3;
Bumper_Pin_Length = 18;

module BumperModel()
{
	thickness = 2;
	height = 15;
	offset = 5;				// distance from base to inside of bumper
	wrapAngle = 170;		// angle that bumper wraps around
	microSwitchAngle = 45;	// angle that microswitches are placed at

	outr = BaseDiameter/2 + offset + thickness; // outr is the outside radius or the bumper

	// Bumper arc
	linear_extrude(height)
	difference() {
		circle(r = outr);

		circle(r = outr - thickness);

		// Chop off below X-axis
		translate([-outr, -outr])
			square([outr*2, outr]);

		// Trim left side of arc
		rotate(a=wrapAngle/2, v=[0,0,1])
		translate([-outr, 0])
			square([outr, outr * 2]);

		// Trim right side of arc
		rotate(a=-wrapAngle/2, v=[0,0,1])
			square([outr, outr * 2]);
	}

	// Guide pins
	for(i=[0,1])
	mirror([i, 0, 0])
	rotate(a=microSwitchAngle, v=[0, 0, 1]) {
		for(i = [0,1])
		mirror([i, 0, 0,]) {
			translate([-1.5 - 8.6, BaseDiameter/2 - Bumper_Pin_Length, 0])
				cube([Bumper_Pin_Width, Bumper_Pin_Length + eta, 5]);
			translate([-1.5 - 8.6, BaseDiameter/2, 0])
				cube([Bumper_Pin_Width + 8.5, offset + eta, 5]);
		}
	}
}


Dirty hack for rotation of header material

FIXME: material needs to be rotated based on vector argument

/*
    Vitamin: ArduinoPro
    Model of an Arduino Pro Mini/Micro

    Derived from: https://github.com/sparkfun/Pro_Micro/
             and: https://github.com/sparkfun/Arduino_Pro_Mini_328/

    Authors:
        Jamie Osborne (@jmeosbn)

    Local Frame:
        Point of origin is the centre of the bottom left pin (9)

    Parameters:
        type: can be "mini", or "micro";
              otherwise returns a blank board with header pin holes

    Returns:
        Model of an Arduino Pro Mini/Micro with header holes
*/

// ArduinoPro Model Variants
ArduinoPro_Mini             = 1;            // default
ArduinoPro_Micro            = 2;

// ArduinoPro Without Programming Port
ArduinoPro_No_Port          = 0;

// Show Header Pins
ArduinoPro_Pins_Normal      = 1;
ArduinoPro_Pins_Opposite    = 2;

// ArduinoPro Without Header Pins
ArduinoPro_No_Pins          = 0;            // default

// ArduinoPro PCB Variables
ArduinoPro_PCB_Pitch    = 2.54;                         // spacing of the holes
ArduinoPro_PCB_Inset    = ArduinoPro_PCB_Pitch /2;      // inset from board edge
ArduinoPro_PCB_Type     = 0.047 * 25.4; // .047 .063    // standard PCB thickness
ArduinoPro_PCB_Layers   = 0.035 * 2;                    // total copper layer thickness
ArduinoPro_PCB_Height   = ArduinoPro_PCB_Type +
                          ArduinoPro_PCB_Layers;        // height of the PCB (along z)
ArduinoPro_PCB_Length   = 1.3 * 25.4;                   // length of the PCB (along y)
ArduinoPro_PCB_Width    = 0.7 * 25.4;                   //  width of the PCB (along x)
ArduinoPro_PCB_Colour   = [26/255, 90/255, 160/255];    // colour of solder mask

// Show board clearance area for components
ArduinoPro_PCB_Clearance      = 3;
ArduinoPro_PCB_Clearance_Show = true;

module ArduinoPro_MicroUSB() {
    include <MicroUSB.scad>
    // Subtracting `ArduinoPro_PCB_Inset` compansates for board origin
    //-: Not sure if board origin would be better set after creation
    move_x  = ArduinoPro_PCB_Width / 2 - ArduinoPro_PCB_Inset;
    move_y  = ArduinoPro_PCB_Length - ArduinoPro_PCB_Inset;
    move_z  = ArduinoPro_PCB_Height;

    // Add USB header and move to top of board (along x)
    translate([move_x, move_y, move_z])
        MicroUSB_Receptacle();
}

module ArduinoPro_PCB() {
    // Bare PCB, origin through location for bottom left hole
    translate([-ArduinoPro_PCB_Inset, -ArduinoPro_PCB_Inset, 0])
        square(size = [ArduinoPro_PCB_Width, ArduinoPro_PCB_Length]);
}

module ArduinoPro_Header_Hole() {
    // Standard PCB hole
    holediameter        = 1.25;         // diameter of PCB hole
    circle(d = holediameter);
}

module ArduinoPro_Header_Pin(rotation = 0) {
    // Standard PCB header pin
    pcbholepitch        = 2.54;         // spacing of PCB holes
    holediameter        = 1.25;         // diameter of PCB hole
    pinheight           =   11;         // length of PCB pins
    pinoffset           =    3;         // offset of PCB pins
    pinwidth            = 0.63;         // width/gauge of PCB pins
    spacerwidth         = 2.25;         // height of breakaway pin frame
    spacerheight        = 2.54;         // height of breakaway pin frame

    // Header Pins
    color("white")
    translate([0, 0, -pinoffset])
    linear_extrude(pinheight)
        square(pinwidth, center = true);

    // Pin Spacers
    color("black")
    linear_extrude(spacerheight)
        square(spacerwidth, center = true);

    // Break-Away Material
    color("black")
    // FIXME: material needs to be rotated based on vector argument
    rotate(rotation, 0, 0)
    translate([0, pcbholepitch/2, 0])
    linear_extrude(spacerheight)
        square([spacerwidth * 0.85, pcbholepitch - spacerwidth], center = true);
}

module ArduinoPro_Headers_Layout() {
    // distance between the two header rows
    // FIXME: improve this to be a multiple of 0.1 inch
    rowpitch  = ArduinoPro_PCB_Width - ArduinoPro_PCB_Inset*2;
    // length for holes, leaving room for end header and insets
    rowlength = ArduinoPro_PCB_Length - ArduinoPro_PCB_Pitch - ArduinoPro_PCB_Inset*2;

    // Add headers to either side (along y)
    for (x = [0, rowpitch], y = [0 : ArduinoPro_PCB_Pitch : rowlength]) {
        translate([x, y, 0]) children();
    }
}

module ArduinoPro_Serial_Header_Layout() {
    // y position for header
    header_y = ArduinoPro_PCB_Length - ArduinoPro_PCB_Inset*2;
    // width for holes, leaving room for insets
    rowwidth = ArduinoPro_PCB_Width - ArduinoPro_PCB_Inset*2;

    // Add serial header along top of board (along x)
    for (x = [ArduinoPro_PCB_Inset : ArduinoPro_PCB_Pitch : rowwidth]) {
        translate([x, header_y, 0]) children();
    }
}

module ArduinoPro(type = ArduinoPro_Mini, headerpins = 0, serialpins = 0) {
    color(ArduinoPro_PCB_Colour)
    linear_extrude(height=ArduinoPro_PCB_Height)
    difference() {
        // Base PCB
        ArduinoPro_PCB();

        // Common Headers for Pro Mini/Micro
        ArduinoPro_Headers_Layout()
            ArduinoPro_Header_Hole();

        // Pro Mini Serial Header
        if (type == ArduinoPro_Mini) {
            ArduinoPro_Serial_Header_Layout()
                ArduinoPro_Header_Hole();
        }
    }

    // Distance to middle from origin
    moveX = ArduinoPro_PCB_Width/2 - ArduinoPro_PCB_Inset;

    // Controller IC
    color(Grey20)
    translate([moveX, 0.5*25.4, ArduinoPro_PCB_Height])
    rotate([0,0,45])
    linear_extrude(height=1)
      square(2*sqrt(.4*25.4), center=true);

    // Reset switch (or crystal for Pro Micro)
    color("silver")
    translate([moveX, 0.15*25.4, ArduinoPro_PCB_Height])
    linear_extrude(height=1)
        square([5, 3.5], center=true);

    // Capacitors
    moveY = (type == ArduinoPro_Mini ? 0.9 : 0.8) * 25.4;
    color("silver")
    translate([moveX/2, moveY, ArduinoPro_PCB_Height])
    linear_extrude(height=2)
    union() {
        square([1.5, 3.5], center=true);
        translate([7.5, 0, 0])
          square([1.5, 3.5], center=true);
    }

    // Other components
    color("silver")
    translate([moveX, moveY, ArduinoPro_PCB_Height])
    linear_extrude(height=1)
    union() {
        square([1, 2.5], center=true);
        translate([0, 3, 0])
            square([2.5, 1.5], center=true);
    }

    // Pro Mini Serial Header Pins
    serialontop = (serialpins != ArduinoPro_Pins_Opposite);
    if (serialpins > 0 && type == ArduinoPro_Mini) {
        // Offset for board height if located on top
        translate([0, 0, serialontop ? ArduinoPro_PCB_Height : 0])
            mirror([0, 0, serialontop ? 0 : 1 ])
            ArduinoPro_Serial_Header_Layout()
                ArduinoPro_Header_Pin(rotation = 90);
    }

    // Common Header Pins
    headerontop = (headerpins == ArduinoPro_Pins_Opposite);
    if (headerpins > 0) {
        // Offset for board height located on top
        translate([0, 0, headerontop ? ArduinoPro_PCB_Height : 0])
            mirror([0, 0, headerontop ? 0 : 1 ])
            ArduinoPro_Headers_Layout()
                ArduinoPro_Header_Pin();
    }

    // Pro Micro USB port
    if (type == ArduinoPro_Micro) ArduinoPro_MicroUSB();

    // Indicate area for minimum board clearance
    if (ArduinoPro_PCB_Clearance_Show && !headerpins) {
        color(ArduinoPro_PCB_Colour, 0.1)
        translate([-ArduinoPro_PCB_Inset, -ArduinoPro_PCB_Inset, 0.5])
        linear_extrude(height=ArduinoPro_PCB_Clearance)
            square(size = [ArduinoPro_PCB_Width, ArduinoPro_PCB_Length]);
    }
}

// Example Usage
// ArduinoPro(ArduinoPro_Micro, ArduinoPro_Pins_Normal);
// ArduinoPro(ArduinoPro_Mini,  ArduinoPro_Pins_Normal, ArduinoPro_Pins_Normal);

/*
    Vitamin: ArduinoPro
    Model of an Arduino Pro Mini/Micro

    Derived from: https://github.com/sparkfun/Pro_Micro/
             and: https://github.com/sparkfun/Arduino_Pro_Mini_328/

    Authors:
        Jamie Osborne (@jmeosbn)

    Local Frame:
        Point of origin is the centre of the bottom left pin (9)

    Parameters:
        type: can be "mini", or "micro";
              otherwise returns a blank board with header pin holes

    Returns:
        Model of an Arduino Pro Mini/Micro with header holes
*/

// ArduinoPro Model Variants
ArduinoPro_Mini             = 1;            // default
ArduinoPro_Micro            = 2;

// ArduinoPro Without Programming Port
ArduinoPro_No_Port          = 0;

// Show Header Pins
ArduinoPro_Pins_Normal      = 1;
ArduinoPro_Pins_Opposite    = 2;

// ArduinoPro Without Header Pins
ArduinoPro_No_Pins          = 0;            // default

// ArduinoPro PCB Variables
ArduinoPro_PCB_Pitch    = 2.54;                         // spacing of the holes
ArduinoPro_PCB_Inset    = ArduinoPro_PCB_Pitch /2;      // inset from board edge
ArduinoPro_PCB_Type     = 0.047 * 25.4; // .047 .063    // standard PCB thickness
ArduinoPro_PCB_Layers   = 0.035 * 2;                    // total copper layer thickness
ArduinoPro_PCB_Height   = ArduinoPro_PCB_Type +
                          ArduinoPro_PCB_Layers;        // height of the PCB (along z)
ArduinoPro_PCB_Length   = 1.3 * 25.4;                   // length of the PCB (along y)
ArduinoPro_PCB_Width    = 0.7 * 25.4;                   //  width of the PCB (along x)
ArduinoPro_PCB_Colour   = [26/255, 90/255, 160/255];    // colour of solder mask

// Show board clearance area for components
ArduinoPro_PCB_Clearance      = 3;
ArduinoPro_PCB_Clearance_Show = true;

module ArduinoPro_MicroUSB() {
    include <MicroUSB.scad>
    // Subtracting `ArduinoPro_PCB_Inset` compansates for board origin
    //-: Not sure if board origin would be better set after creation
    move_x  = ArduinoPro_PCB_Width / 2 - ArduinoPro_PCB_Inset;
    move_y  = ArduinoPro_PCB_Length - ArduinoPro_PCB_Inset;
    move_z  = ArduinoPro_PCB_Height;

    // Add USB header and move to top of board (along x)
    translate([move_x, move_y, move_z])
        MicroUSB_Receptacle();
}

module ArduinoPro_PCB() {
    // Bare PCB, origin through location for bottom left hole
    translate([-ArduinoPro_PCB_Inset, -ArduinoPro_PCB_Inset, 0])
        square(size = [ArduinoPro_PCB_Width, ArduinoPro_PCB_Length]);
}

module ArduinoPro_Header_Hole() {
    // Standard PCB hole
    holediameter        = 1.25;         // diameter of PCB hole
    circle(d = holediameter);
}

module ArduinoPro_Header_Pin() {
    // Standard PCB header pin
    pcbholepitch        = 2.54;         // spacing of PCB holes
    holediameter        = 1.25;         // diameter of PCB hole
    pinheight           =   11;         // length of PCB pins
    pinoffset           =    3;         // offset of PCB pins
    pinwidth            = 0.63;         // width/gauge of PCB pins
    spacerwidth         = 2.25;         // height of breakaway pin frame
    spacerheight        = 2.54;         // height of breakaway pin frame

    // Header Pins
    color("white")
    translate([0, 0, -pinoffset])
    linear_extrude(pinheight)
        square(pinwidth, center = true);

    // Pin Spacers
    color("black")
    linear_extrude(spacerheight)
        square(spacerwidth, center = true);

    // Break-Away Material
    color("black")
    translate([0, pcbholepitch/2, 0])
    linear_extrude(spacerheight)
        square([spacerwidth * 0.85, pcbholepitch - spacerwidth], center = true);
}

module ArduinoPro_Headers_Layout() {
    // distance between the two header rows
    // FIXME: improve this to be a multiple of 0.1 inch
    rowpitch  = ArduinoPro_PCB_Width - ArduinoPro_PCB_Inset*2;
    // length for holes, leaving room for end header and insets
    rowlength = ArduinoPro_PCB_Length - ArduinoPro_PCB_Pitch - ArduinoPro_PCB_Inset*2;

    // Add headers to either side (along y)
    for (x = [0, rowpitch], y = [0 : ArduinoPro_PCB_Pitch : rowlength]) {
        translate([x, y, 0]) children();
    }
}

module ArduinoPro_Serial_Header_Layout() {
    // y position for header
    header_y = ArduinoPro_PCB_Length - ArduinoPro_PCB_Inset*2;
    // width for holes, leaving room for insets
    rowwidth = ArduinoPro_PCB_Width - ArduinoPro_PCB_Inset*2;

    // Add serial header along top of board (along x)
    for (x = [ArduinoPro_PCB_Inset : ArduinoPro_PCB_Pitch : rowwidth]) {
        translate([x, header_y, 0]) children();
    }
}

module ArduinoPro(type = ArduinoPro_Mini, headerpins = 0, serialpins = 0) {
    color(ArduinoPro_PCB_Colour)
    linear_extrude(height=ArduinoPro_PCB_Height)
    difference() {
        // Base PCB
        ArduinoPro_PCB();

        // Common Headers for Pro Mini/Micro
        ArduinoPro_Headers_Layout()
            ArduinoPro_Header_Hole();

        // Pro Mini Serial Header
        if (type == ArduinoPro_Mini) {
            ArduinoPro_Serial_Header_Layout()
                ArduinoPro_Header_Hole();
        }
    }

    // Distance to middle from origin
    moveX = ArduinoPro_PCB_Width/2 - ArduinoPro_PCB_Inset;

    // Controller IC
    color(Grey20)
    translate([moveX, 0.5*25.4, ArduinoPro_PCB_Height])
    rotate([0,0,45])
    linear_extrude(height=1)
      square(2*sqrt(.4*25.4), center=true);

    // Reset switch (or crystal for Pro Micro)
    color("silver")
    translate([moveX, 0.15*25.4, ArduinoPro_PCB_Height])
    linear_extrude(height=1)
        square([5, 3.5], center=true);

    // Capacitors
    moveY = (type == ArduinoPro_Mini ? 0.9 : 0.8) * 25.4;
    color("silver")
    translate([moveX/2, moveY, ArduinoPro_PCB_Height])
    linear_extrude(height=2)
    union() {
        square([1.5, 3.5], center=true);
        translate([7.5, 0, 0])
          square([1.5, 3.5], center=true);
    }

    // Other components
    color("silver")
    translate([moveX, moveY, ArduinoPro_PCB_Height])
    linear_extrude(height=1)
    union() {
        square([1, 2.5], center=true);
        translate([0, 3, 0])
            square([2.5, 1.5], center=true);
    }

    // Pro Mini Serial Header Pins
    serialontop = (serialpins != ArduinoPro_Pins_Opposite);
    if (serialpins > 0 && type == ArduinoPro_Mini) {
        // Offset for board height if located on top
        translate([0, 0, serialontop ? ArduinoPro_PCB_Height : 0])
            mirror([0, 0, serialontop ? 0 : 1 ])
            ArduinoPro_Serial_Header_Layout()
                ArduinoPro_Header_Pin();
    }

    // Common Header Pins
    headerontop = (headerpins == ArduinoPro_Pins_Opposite);
    if (headerpins > 0) {
        // Offset for board height located on top
        translate([0, 0, headerontop ? ArduinoPro_PCB_Height : 0])
            mirror([0, 0, headerontop ? 0 : 1 ])
            ArduinoPro_Headers_Layout()
                ArduinoPro_Header_Pin();
    }

    // Pro Micro USB port
    if (type == ArduinoPro_Micro) ArduinoPro_MicroUSB();

    // Indicate area for minimum board clearance
    if (ArduinoPro_PCB_Clearance_Show && !headerpins) {
        color(ArduinoPro_PCB_Colour, 0.1)
        translate([-ArduinoPro_PCB_Inset, -ArduinoPro_PCB_Inset, 0.5])
        linear_extrude(height=ArduinoPro_PCB_Clearance)
            square(size = [ArduinoPro_PCB_Width, ArduinoPro_PCB_Length]);
    }
}

// Example Usage
// ArduinoPro(ArduinoPro_Micro, ArduinoPro_Pins_Normal);
// ArduinoPro(ArduinoPro_Mini,  ArduinoPro_Pins_Normal, ArduinoPro_Pins_Normal);


Use centre line along y as datum for SMT components

/*
    Vitamin: ArduinoPro
    Model of an Arduino Pro Mini/Micro

    Derived from: https://github.com/sparkfun/Pro_Micro/
             and: https://github.com/sparkfun/Arduino_Pro_Mini_328/

    Authors:
        Jamie Osborne (@jmeosbn)

    Local Frame:
        Point of origin is the centre of the bottom left pin (9)

    Parameters:
        type: can be "mini", or "micro";
              otherwise returns a blank board with header pin holes

    Returns:
        Model of an Arduino Pro Mini/Micro with header holes
*/

// ArduinoPro Model Variants
ArduinoPro_Mini             = 1;            // default
ArduinoPro_Micro            = 2;

// ArduinoPro Without Programming Port
ArduinoPro_No_Port          = 0;

// Show Header Pins
ArduinoPro_Pins_Normal      = 1;
ArduinoPro_Pins_Opposite    = 2;

// ArduinoPro Without Header Pins
ArduinoPro_No_Pins          = 0;            // default

// ArduinoPro PCB Variables
ArduinoPro_PCB_Pitch    = 0.1 * 25.4;                   // spacing of the holes
ArduinoPro_PCB_Inset    = ArduinoPro_PCB_Pitch /2;      // inset from board edge
ArduinoPro_PCB_Type     = 0.047 * 25.4; // .047 .063    // standard PCB thickness
ArduinoPro_PCB_Layers   = 0.035 * 2;                    // total copper layer thickness
ArduinoPro_PCB_Height   = ArduinoPro_PCB_Type +
                          ArduinoPro_PCB_Layers;        // height of the PCB (along z)
ArduinoPro_PCB_Length   = 1.3 * 25.4;                   // length of the PCB (along y)
ArduinoPro_PCB_Width    = 0.7 * 25.4;                   //  width of the PCB (along x)
ArduinoPro_PCB_Colour   = [26/255, 90/255, 160/255];    // colour of solder mask

module ArduinoPro_MicroUSB()
{
    include <MicroUSB.scad>
    // Subtracting `ArduinoPro_PCB_Inset` compansates for board origin
    //-: Not sure if board origin would be better set after creation
    move_x  = ArduinoPro_PCB_Width / 2 - ArduinoPro_PCB_Inset;
    move_y  = ArduinoPro_PCB_Length - ArduinoPro_PCB_Inset;
    move_z  = ArduinoPro_PCB_Height;

    // Add USB header and move to top of board (along x)
    translate([move_x, move_y, move_z])
        MicroUSB_Receptacle();
}

module ArduinoPro_PCB()
{
    // Bare PCB, origin through location for bottom left hole
    translate([-ArduinoPro_PCB_Inset, -ArduinoPro_PCB_Inset, 0])
        square(size = [ArduinoPro_PCB_Width, ArduinoPro_PCB_Length]);
}

module ArduinoPro_Header_Hole()
{
    // Standard PCB hole
    holediameter        = 1.25;         // diameter of PCB hole
    circle(d = holediameter);
}

module ArduinoPro_Header_Pin(rotation = 0)
{
    // Standard PCB header pin
    pcbholepitch        = 2.54;         // spacing of PCB holes
    holediameter        = 1.25;         // diameter of PCB hole
    pinheight           =   11;         // length of PCB pins
    pinoffset           =    3;         // offset of PCB pins
    pinwidth            = 0.63;         // width/gauge of PCB pins
    spacerwidth         = 2.25;         // height of breakaway pin frame
    spacerheight        = 2.25;         // height of breakaway pin frame

    // Header Pins
    color("white")
    translate([0, 0, -pinoffset])
    linear_extrude(pinheight)
        square(pinwidth, center = true);

    // Pin Spacers
    color("black")
    linear_extrude(spacerheight)
        square(spacerwidth, center = true);

    // Break-Away Material
    color("black")
    // FIXME: material needs to be rotated based on vector argument
    rotate(rotation, 0, 0)
    translate([0, pcbholepitch/2, 0])
    linear_extrude(spacerheight)
        square([spacerwidth * 0.85, pcbholepitch - spacerwidth], center = true);
}

module ArduinoPro_Headers_Layout()
{
    // distance between the two header rows
    // FIXME: improve this to be a multiple of 0.1 inch
    rowpitch  = ArduinoPro_PCB_Width - ArduinoPro_PCB_Inset*2;
    // length for holes, leaving room for end header and insets
    rowlength = ArduinoPro_PCB_Length - ArduinoPro_PCB_Pitch - ArduinoPro_PCB_Inset*2;

    // Add headers to either side (along y)
    for (x = [0, rowpitch], y = [0 : ArduinoPro_PCB_Pitch : rowlength]) {
        translate([x, y, 0]) children();
    }
}

module ArduinoPro_Serial_Header_Layout()
{
    // y position for header
    header_y = ArduinoPro_PCB_Length - ArduinoPro_PCB_Inset*2;
    // width for holes, leaving room for insets
    rowwidth = ArduinoPro_PCB_Width - ArduinoPro_PCB_Inset*2;

    // Add serial header along top of board (along x)
    for (x = [ArduinoPro_PCB_Inset : ArduinoPro_PCB_Pitch : rowwidth]) {
        translate([x, header_y, 0]) children();
    }
}

module ArduinoPro_SMT_Components(type = ArduinoPro_Mini)
{
    // Distance from origin to middle along y
    datumX = ArduinoPro_PCB_Width/2 - ArduinoPro_PCB_Inset;
    datumZ = ArduinoPro_PCB_Height;

    // Controller IC
    color(Grey20)
    translate([datumX, 0.5 * 25.4, datumZ])
    rotate([0,0,45])
    linear_extrude(1)
      square(sqrt(pow(0.4 * 25.4, 2)/2), center=true);

    // Parts for Pro Mini
    if (type == ArduinoPro_Mini) {
        // Reset switch
        translate([datumX, 0.05 * 25.4, datumZ])
        {
            color("silver")
            linear_extrude(1.2)
                square([4.5, 4.5], center=true);
            color("sandybrown")
            translate([0, 0, 1.2])
            linear_extrude(0.5)
                circle(d=2.5);
        }

        // RX and TX LEDs
        color("white")
        translate([datumX, 0.05 * 25.4, datumZ])
        linear_extrude(1)
        {
            // Red - Power
            translate([0, 0.75 * 25.4, 0])
                square([1.2,0.7], center=true);
            // Green - Status
            translate([0.2 * 25.4, 0, 0])
                square([0.7,1.2], center=true);
        }

    }

    // Parts for Pro Micro
    if (type == ArduinoPro_Micro) {
        // Crystal
        color("silver")
        translate([datumX, 0.15 * 25.4, datumZ])
        linear_extrude(1)
            square([5, 3], center=true);

        // RX and TX LEDs
        color("white")
        translate([datumX, 0.2 * 25.4, datumZ])
        linear_extrude(1)
        {
            // RX - Yellow
            translate([-0.3 * 25.4/2, 0, 0])
                square([0.7,1.2], center=true);
            // Power - Red
            translate([-0.15 * 25.4, 0.75 * 25.4, 0])
                square([1.2,0.7], center=true);
            // TX - Green
            translate([0.3 * 25.4/2, 0, 0])
                square([0.7,1.2], center=true);
        }
    }

    // Capacitors
    moveY = (type == ArduinoPro_Mini ? 0.9 : 0.8) * 25.4;
    color("silver")
    translate([datumX, moveY, datumZ])
    linear_extrude(2)
    {
        translate([-7.5/2, 0, 0])
            square([1.5, 3.5], center=true);
        translate([7.5/2, 0, 0])
          square([1.5, 3.5], center=true);
    }

    // Other components
    color("silver")
    translate([datumX, moveY, datumZ])
    linear_extrude(1)
    {
        square([1, 2.5], center=true);
        translate([0, 3.25, 0])
            square([2.5, 1.5], center=true);
    }
}

module ArduinoPro(type = ArduinoPro_Mini, headerpins = 0, serialpins = 0)
{
    color(ArduinoPro_PCB_Colour)
    linear_extrude(ArduinoPro_PCB_Height)
    difference() {
        // Base PCB
        ArduinoPro_PCB();

        // Common Headers for Pro Mini/Micro
        ArduinoPro_Headers_Layout()
            ArduinoPro_Header_Hole();

        // Pro Mini Serial Header
        if (type == ArduinoPro_Mini) {
            ArduinoPro_Serial_Header_Layout()
                ArduinoPro_Header_Hole();
        }
    }

    // Pro Mini Serial Header Pins
    serialontop = (serialpins != ArduinoPro_Pins_Opposite);
    if (serialpins > 0 && type == ArduinoPro_Mini) {
        // Offset for board height if located on top
        translate([0, 0, serialontop ? ArduinoPro_PCB_Height : 0])
            mirror([0, 0, serialontop ? 0 : 1 ])
            ArduinoPro_Serial_Header_Layout()
                ArduinoPro_Header_Pin(rotation = 90);
    }

    // Common Header Pins
    headerontop = (headerpins == ArduinoPro_Pins_Opposite);
    if (headerpins > 0) {
        // Offset for board height located on top
        translate([0, 0, headerontop ? ArduinoPro_PCB_Height : 0])
            mirror([0, 0, headerontop ? 0 : 1 ])
            ArduinoPro_Headers_Layout()
                ArduinoPro_Header_Pin();
    }

    // Pro Micro USB port
    if (type == ArduinoPro_Micro) ArduinoPro_MicroUSB();

    // Surface mount components
    ArduinoPro_SMT_Components(type);
}

// Example Usage
// ArduinoPro(ArduinoPro_Micro, ArduinoPro_Pins_Normal);
// ArduinoPro(ArduinoPro_Mini,  ArduinoPro_Pins_Normal, ArduinoPro_Pins_Normal);

/*
    Vitamin: ArduinoPro
    Model of an Arduino Pro Mini/Micro

    Derived from: https://github.com/sparkfun/Pro_Micro/
             and: https://github.com/sparkfun/Arduino_Pro_Mini_328/

    Authors:
        Jamie Osborne (@jmeosbn)

    Local Frame:
        Point of origin is the centre of the bottom left pin (9)

    Parameters:
        type: can be "mini", or "micro";
              otherwise returns a blank board with header pin holes

    Returns:
        Model of an Arduino Pro Mini/Micro with header holes
*/

// ArduinoPro Model Variants
ArduinoPro_Mini             = 1;            // default
ArduinoPro_Micro            = 2;

// ArduinoPro Without Programming Port
ArduinoPro_No_Port          = 0;

// Show Header Pins
ArduinoPro_Pins_Normal      = 1;
ArduinoPro_Pins_Opposite    = 2;

// ArduinoPro Without Header Pins
ArduinoPro_No_Pins          = 0;            // default

// ArduinoPro PCB Variables
ArduinoPro_PCB_Pitch    = 2.54;                         // spacing of the holes
ArduinoPro_PCB_Inset    = ArduinoPro_PCB_Pitch /2;      // inset from board edge
ArduinoPro_PCB_Type     = 0.047 * 25.4; // .047 .063    // standard PCB thickness
ArduinoPro_PCB_Layers   = 0.035 * 2;                    // total copper layer thickness
ArduinoPro_PCB_Height   = ArduinoPro_PCB_Type +
                          ArduinoPro_PCB_Layers;        // height of the PCB (along z)
ArduinoPro_PCB_Length   = 1.3 * 25.4;                   // length of the PCB (along y)
ArduinoPro_PCB_Width    = 0.7 * 25.4;                   //  width of the PCB (along x)
ArduinoPro_PCB_Colour   = [26/255, 90/255, 160/255];    // colour of solder mask

module ArduinoPro_MicroUSB()
{
    include <MicroUSB.scad>
    // Subtracting `ArduinoPro_PCB_Inset` compansates for board origin
    //-: Not sure if board origin would be better set after creation
    move_x  = ArduinoPro_PCB_Width / 2 - ArduinoPro_PCB_Inset;
    move_y  = ArduinoPro_PCB_Length - ArduinoPro_PCB_Inset;
    move_z  = ArduinoPro_PCB_Height;

    // Add USB header and move to top of board (along x)
    translate([move_x, move_y, move_z])
        MicroUSB_Receptacle();
}

module ArduinoPro_PCB()
{
    // Bare PCB, origin through location for bottom left hole
    translate([-ArduinoPro_PCB_Inset, -ArduinoPro_PCB_Inset, 0])
        square(size = [ArduinoPro_PCB_Width, ArduinoPro_PCB_Length]);
}

module ArduinoPro_Header_Hole()
{
    // Standard PCB hole
    holediameter        = 1.25;         // diameter of PCB hole
    circle(d = holediameter);
}

module ArduinoPro_Header_Pin(rotation = 0)
{
    // Standard PCB header pin
    pcbholepitch        = 2.54;         // spacing of PCB holes
    holediameter        = 1.25;         // diameter of PCB hole
    pinheight           =   11;         // length of PCB pins
    pinoffset           =    3;         // offset of PCB pins
    pinwidth            = 0.63;         // width/gauge of PCB pins
    spacerwidth         = 2.25;         // height of breakaway pin frame
    spacerheight        = 2.25;         // height of breakaway pin frame

    // Header Pins
    color("white")
    translate([0, 0, -pinoffset])
    linear_extrude(pinheight)
        square(pinwidth, center = true);

    // Pin Spacers
    color("black")
    linear_extrude(spacerheight)
        square(spacerwidth, center = true);

    // Break-Away Material
    color("black")
    // FIXME: material needs to be rotated based on vector argument
    rotate(rotation, 0, 0)
    translate([0, pcbholepitch/2, 0])
    linear_extrude(spacerheight)
        square([spacerwidth * 0.85, pcbholepitch - spacerwidth], center = true);
}

module ArduinoPro_Headers_Layout()
{
    // distance between the two header rows
    // FIXME: improve this to be a multiple of 0.1 inch
    rowpitch  = ArduinoPro_PCB_Width - ArduinoPro_PCB_Inset*2;
    // length for holes, leaving room for end header and insets
    rowlength = ArduinoPro_PCB_Length - ArduinoPro_PCB_Pitch - ArduinoPro_PCB_Inset*2;

    // Add headers to either side (along y)
    for (x = [0, rowpitch], y = [0 : ArduinoPro_PCB_Pitch : rowlength]) {
        translate([x, y, 0]) children();
    }
}

module ArduinoPro_Serial_Header_Layout()
{
    // y position for header
    header_y = ArduinoPro_PCB_Length - ArduinoPro_PCB_Inset*2;
    // width for holes, leaving room for insets
    rowwidth = ArduinoPro_PCB_Width - ArduinoPro_PCB_Inset*2;

    // Add serial header along top of board (along x)
    for (x = [ArduinoPro_PCB_Inset : ArduinoPro_PCB_Pitch : rowwidth]) {
        translate([x, header_y, 0]) children();
    }
}

module ArduinoPro_SMT_Components(type = ArduinoPro_Mini)
{
    // Distance from origin to middle along y
    moveX = ArduinoPro_PCB_Width/2 - ArduinoPro_PCB_Inset;
    moveZ = ArduinoPro_PCB_Height;

    // Controller IC
    color(Grey20)
    translate([moveX, 0.5 * 25.4, moveZ])
    rotate([0,0,45])
    linear_extrude(height=1)
      square(sqrt(pow(0.4 * 25.4, 2)/2), center=true);

    // Parts for Pro Mini
    if (type == ArduinoPro_Mini) {
        // Reset switch
        translate([moveX, 0.05 * 25.4, moveZ])
        {
            color("silver")
            linear_extrude(height=1.2)
                square([4.5, 4.5], center=true);
            color("gold")
            translate([0, 0, 1.2])
            linear_extrude(height=0.5)
                circle(d=2.5);
        }

        // RX and TX LEDs
        color("white")
        translate([0.5 * 25.4, 0.05 * 25.4, moveZ])
        linear_extrude(height=1)
        {
            // Green - Status
            square([0.7,1.2], center=true);
            // Red - Power
            translate([-0.2 * 25.4, 0.75 * 25.4, 0])
                square([1.2,0.7], center=true);
        }
    }

    // Parts for Pro Micro
    if (type == ArduinoPro_Micro) {
        // Crystal
        color("silver")
        translate([moveX, 0.15 * 25.4, moveZ])
        linear_extrude(height=1)
            square([5, 3], center=true);

        // RX and TX LEDs
        color("white")
        translate([moveX/2, 0.2 * 25.4, moveZ])
        linear_extrude(height=1)
        {
            // RX - Yellow
            square([0.7,1.2], center=true);
            // Power - Red
            translate([0, 0.75 * 25.4, 0])
                square([1.2,0.7], center=true);
            // TX - Green
            translate([0.3 * 25.4, 0, 0])
                square([0.7,1.2], center=true);
        }
    }

    // Capacitors etc.
    moveY = (type == ArduinoPro_Mini ? 0.9 : 0.8) * 25.4;
    color("silver")
    translate([moveX/2, moveY, moveZ])
    linear_extrude(height=2)
    {
        square([1.5, 3.5], center=true);
        translate([7.5, 0, 0])
          square([1.5, 3.5], center=true);
    }

    // Other components
    color("silver")
    translate([moveX, moveY, moveZ])
    linear_extrude(height=1)
    {
        square([1, 2.5], center=true);
        translate([0, 3.25, 0])
            square([2.5, 1.5], center=true);
    }
}

module ArduinoPro(type = ArduinoPro_Mini, headerpins = 0, serialpins = 0)
{
    color(ArduinoPro_PCB_Colour)
    linear_extrude(height=ArduinoPro_PCB_Height)
    difference() {
        // Base PCB
        ArduinoPro_PCB();

        // Common Headers for Pro Mini/Micro
        ArduinoPro_Headers_Layout()
            ArduinoPro_Header_Hole();

        // Pro Mini Serial Header
        if (type == ArduinoPro_Mini) {
            ArduinoPro_Serial_Header_Layout()
                ArduinoPro_Header_Hole();
        }
    }

    // Pro Mini Serial Header Pins
    serialontop = (serialpins != ArduinoPro_Pins_Opposite);
    if (serialpins > 0 && type == ArduinoPro_Mini) {
        // Offset for board height if located on top
        translate([0, 0, serialontop ? ArduinoPro_PCB_Height : 0])
            mirror([0, 0, serialontop ? 0 : 1 ])
            ArduinoPro_Serial_Header_Layout()
                ArduinoPro_Header_Pin(rotation = 90);
    }

    // Common Header Pins
    headerontop = (headerpins == ArduinoPro_Pins_Opposite);
    if (headerpins > 0) {
        // Offset for board height located on top
        translate([0, 0, headerontop ? ArduinoPro_PCB_Height : 0])
            mirror([0, 0, headerontop ? 0 : 1 ])
            ArduinoPro_Headers_Layout()
                ArduinoPro_Header_Pin();
    }

    // Pro Micro USB port
    if (type == ArduinoPro_Micro) ArduinoPro_MicroUSB();

    // Surface mount components
    ArduinoPro_SMT_Components(type);
}

// Example Usage
// ArduinoPro(ArduinoPro_Micro, ArduinoPro_Pins_Normal);
// ArduinoPro(ArduinoPro_Mini,  ArduinoPro_Pins_Normal, ArduinoPro_Pins_Normal);


Adjusted bottom

Adjusted bottom

tol = 0.5;
pcb_x = 130;
pcb_y = 110;
pcb_z = 4;
bolt_d = 3.6;
shift_bolt = 5;

// box thickness
th = 3;

shift_x = th + 1;
shift_y = th + 1;

box_x = pcb_x + shift_x + th + 1;
box_y = pcb_y + 2*th + 1;

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;
start_socket_z = th + pcb_z + tol;
eps = 1e-1;

usb_type_b_w = 15.2;
//usb_type_b_h = 3;
start_type_b_y = shift_y + pcb_y - 30.1;
start_type_b_z = th + pcb_z + tol;

usb_type_a_w = 17.3;
//usb_type_a_h = 0.5;
start_type_a_y = shift_y + 44.7;
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 = 8;
fn = 10;
gaika_d = 6.25;
gaika_h = 2.5;

difference() {
  union() {
    difference() {
      cube([box_x,box_y,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
    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_up/2+th-eps]) {
          cube(size=[under_pcb,under_pcb,pcb_up], center=true);
        }
      }
    }
  }

  // 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_d/2, h=gaika_h);
      }
    }
  }

//    for (i = [0:1:socket_n-1]) {
//        translate([start_socket_x+i*socket_int-tol, box_y-th-eps, start_socket_z]) {
//            cube(size=[socket_w+2*tol, th+2*eps, box_z]);
//        }
//    }

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

//// 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;
pcb_x = 130;
pcb_y = 110;
pcb_z = 4;
bolt_d = 3.6;
shift_bolt = 5;

// box thickness
th = 1;

shift_x = th + 1;
shift_y = th + 1;

box_x = pcb_x + shift_x + th + 1;
box_y = pcb_y + 2*th + 1;

pcb_width = 2;
pcb_up = 9;

box_z = th + pcb_up + pcb_width;

//socket_h = 15;
socket_w = 10;
socket_n = 5;
socket_int = 20;
start_socket_x = 20 + shift_x;
start_socket_z = th + pcb_z + tol;
eps = 1e-1;

usb_type_b_w = 15.2;
//usb_type_b_h = 3;
start_type_b_y = shift_y + pcb_y - 30.1;
start_type_b_z = th + pcb_z + tol;

usb_type_a_w = 17.3;
//usb_type_a_h = 0.5;
start_type_a_y = shift_y + 44.7;
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 + 37.4;
contrast_start_y = shift_y + 26.7;
volume_start_x = shift_x + pcb_x - 39.2;
volume_start_y = contrast_start_y;
pot_d = 7;
under_pcb = 6;

difference() {
  union() {
    difference() {
      cube([box_x,box_y,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
    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_up/2+th-eps]) {
          cube(size=[under_pcb,under_pcb,pcb_up], center=true);
        }
      }
    }
  }

  // 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=20, r=bolt_d/2, h=th+pcb_up+2*eps);
      }
    }
  }

//    for (i = [0:1:socket_n-1]) {
//        translate([start_socket_x+i*socket_int-tol, box_y-th-eps, start_socket_z]) {
//            cube(size=[socket_w+2*tol, th+2*eps, box_z]);
//        }
//    }

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

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


change the nut trap drawing code

change the nut trap drawing code

tol = 0.5;
pcb_x = 130;
pcb_y = 110;
pcb_z = 4;
bolt_d = 3.6;
shift_bolt = 5;

// box thickness
th = 3;

shift_x = th + 1;
shift_y = th + 1;

box_x = pcb_x + shift_x + th + 1;
box_y = pcb_y + 2*th + 1;

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;
start_socket_z = th + pcb_z + tol;
eps = 1e-1;

usb_type_b_w = 15.2;
//usb_type_b_h = 3;
start_type_b_y = shift_y + pcb_y - 30.1;
start_type_b_z = th + pcb_z + tol;

usb_type_a_w = 17.3;
//usb_type_a_h = 0.5;
start_type_a_y = shift_y + 44.7;
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 = 12.5;
fn = 10;
gaika_h = 6;
gaika_w = 5.5;

difference() {
  union() {
    difference() {
      cube([box_x,box_y,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
    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_up/2+th-eps]) {
          cube(size=[under_pcb,under_pcb,pcb_up], center=true);
        }
      }
    }
  }

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

//    for (i = [0:1:socket_n-1]) {
//        translate([start_socket_x+i*socket_int-tol, box_y-th-eps, start_socket_z]) {
//            cube(size=[socket_w+2*tol, th+2*eps, box_z]);
//        }
//    }

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

//// 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;
pcb_x = 130;
pcb_y = 110;
pcb_z = 4;
bolt_d = 3.6;
shift_bolt = 5;

// box thickness
th = 3;

shift_x = th + 1;
shift_y = th + 1;

box_x = pcb_x + shift_x + th + 1;
box_y = pcb_y + 2*th + 1;

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;
start_socket_z = th + pcb_z + tol;
eps = 1e-1;

usb_type_b_w = 15.2;
//usb_type_b_h = 3;
start_type_b_y = shift_y + pcb_y - 30.1;
start_type_b_z = th + pcb_z + tol;

usb_type_a_w = 17.3;
//usb_type_a_h = 0.5;
start_type_a_y = shift_y + 44.7;
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 = 12.5;
fn = 10;
gaika_d = 6.25;
gaika_h = 6;

difference() {
  union() {
    difference() {
      cube([box_x,box_y,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
    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_up/2+th-eps]) {
          cube(size=[under_pcb,under_pcb,pcb_up], center=true);
        }
      }
    }
  }

  // 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_d/2, h=gaika_h);
      }
    }
  }

//    for (i = [0:1:socket_n-1]) {
//        translate([start_socket_x+i*socket_int-tol, box_y-th-eps, start_socket_z]) {
//            cube(size=[socket_w+2*tol, th+2*eps, box_z]);
//        }
//    }

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

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


TubeCollector

TubeCollector

//TubeCollector

//Parameters
$fn=50;
innerDiameter = 40;
outerDiameter = 45;
hoseDiameter = 10;

module bottom() {
    difference() {
        circle(d=outerDiameter+5);
        circle(d=hoseDiameter);
    }
}
module top() {
    difference() {
        circle(d=innerDiameter);
        circle(d=hoseDiameter);
    }
}
module extrude(h=5) {
    linear_extrude(height=h)children();
}
module assembly() {
    extrude()bottom();
    translate([0,0,5])extrude()top();
}
assembly();

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


Add demo for the starBox shape and some other shapes

/**
 * Samples using the camelSCAD library.
 *
 * A parametric christmas star.
 *
 * @author jsconan
 * @license CC0-1.0
 */

// As we need to use some shapes, use the right entry point of the library
use <../shapes.scad>

// We will render the object using the specifications of this mode
renderMode = "prod";

// Defines the dimensions of the star
radius = 40;
thickness = 3;
holeDiameter = 4;
ringThickness = 2;
ringDiameter = holeDiameter + ringThickness * 2;
coreRadius = (radius * 2) * (1 - 3 / 5);

// Sets the minimum facet angle and size using the defined render mode.
$fa = facetAngle(renderMode);
$fs = facetSize(renderMode);

// And draw the star
union() {
    // This is the frame of the star
    difference() {
        starBox(size=radius, h=thickness, edges=5, center=true);
        starBox(size=radius / 1.5, h=thickness + 1, edges=5, center=true);
    }
    // This is the core of the star
    rotateZ(180) {
        difference() {
            regularPolygonBox(size=coreRadius, n=5, h=thickness, center=true);
            cylinder(r=radius / 5, h=thickness + 1, center=true);
        }
    }
    // This the ring to hook the star
    translate([0, radius + ringThickness]) {
        pipe(d=ringDiameter, w=ringThickness, h=thickness, center=true);
    }
}

error: pathspec 'samples/christmas-star.scad' did not match any file(s) known to git


attach: fix warnings (using undefined global vars)

include <system.scad>
use <misc.scad>
use <transforms.scad>;
use <shapes.scad>

// From Obiscad,
// modified to take roll parameter as param in module instead of attachment points
//-------------------------------------------------------------------------
// ATTACH OPERATOR
// This operator applies the necessary transformations to the
// child (attachable part) so that it is attached to the main part
// Parameters
//  a: Connector of the main part
//  b: Connector of the attachable part
//  explode: extra translation between parts (child moved away from parent)
//  roll:
//  rollaxis:
//-------------------------------------------------------------------------
module attach(a, b, roll=0, rollaxis=N)
{
    /*if($debug)*/
    /*echo("attach():", a,b,roll,rollaxis);*/

    assert(is_list(a), a);
    assert(len(a)==2, a);
    assert_v3n(a[0], a);
    assert_v3n(a[1], a);
    /*assert(a[1]!=N, a);*/

    assert(is_list(b), b);
    assert(len(b)==2, b);
    assert_v3n(b[0], b);
    assert_v3n(b[1], b);
    /*assert(b[1]!=N, b);*/

    assert(is_num(roll));

    // Get the data from the connectors
    // Attachment point. Main part
    pos1 = a[0];
    // Attachment axis. Main part
    v    = a[1];

    // Attachment point. Attachable part
    pos2 = b[0];
    // Atachment axis. Attachable part
    vref = b[1];

    assert(is_list(pos1));
    assert(is_list(v));
    assert(is_list(pos2));
    assert(is_list(vref));

    // Calculations for the "orientate operator"
    // Calculate the rotation axis
    raxis = v_cross(vref,v);

    // Calculate the angle between the vectors
    // this can become nan if vref and v are N
    ang_ = v_anglev(vref,v);
    ang = is_num(ang_)?ang_:0;
    assert(is_num(ang));

    raxis_=ang==180&&raxis==N?X:raxis;

    /*if($debug)*/
    /*echo(pos1,v,pos2,vref, raxis, ang, raxis_);*/

    // Apply the transformations to the child

    // Place the attachable part on the main part attachment point
    t(pos1)
    // Orientate operator. Apply the orientation so that
    // both attachment axis are paralell. Also apply the roll angle
    r(a=roll, v=rollaxis)
    r(a=ang, v=raxis_)
    // Attachable part to the origin
    t(-pos2)
    t(is_undef($explode)?[0,0,0]:-$explode*vref)
    {
        children();

        if(is_undef($show_conn)?false:$show_conn)
        connector([b.x, -b.y]);
    }

    if(is_undef($show_conn)?false:$show_conn)
    connector(a);
}

if(false)
{
    s=[10,10,10];

    conn = [X*s.x/2,X];

    /*connector(conn);*/
    cubea(s);
    attach(conn, -conn, $explode=2)
    spherea(d=s.x);
}

include <system.scad>
use <misc.scad>
use <transforms.scad>;
use <shapes.scad>

// From Obiscad,
// modified to take roll parameter as param in module instead of attachment points
//-------------------------------------------------------------------------
// ATTACH OPERATOR
// This operator applies the necessary transformations to the
// child (attachable part) so that it is attached to the main part
// Parameters
//  a: Connector of the main part
//  b: Connector of the attachable part
//  explode: extra translation between parts (child moved away from parent)
//  roll:
//  rollaxis:
//-------------------------------------------------------------------------
module attach(a, b, roll=0, rollaxis=N)
{
    /*if($debug)*/
    /*echo("attach():", a,b,roll,rollaxis);*/

    assert(is_list(a), a);
    assert(len(a)==2, a);
    assert_v3n(a[0], a);
    assert_v3n(a[1], a);
    /*assert(a[1]!=N, a);*/

    assert(is_list(b), b);
    assert(len(b)==2, b);
    assert_v3n(b[0], b);
    assert_v3n(b[1], b);
    /*assert(b[1]!=N, b);*/

    assert(is_num(roll));

    // Get the data from the connectors
    // Attachment point. Main part
    pos1 = a[0];
    // Attachment axis. Main part
    v    = a[1];

    // Attachment point. Attachable part
    pos2 = b[0];
    // Atachment axis. Attachable part
    vref = b[1];

    assert(is_list(pos1));
    assert(is_list(v));
    assert(is_list(pos2));
    assert(is_list(vref));

    // Calculations for the "orientate operator"
    // Calculate the rotation axis
    raxis = v_cross(vref,v);

    // Calculate the angle between the vectors
    // this can become nan if vref and v are N
    ang_ = v_anglev(vref,v);
    ang = is_num(ang_)?ang_:0;
    assert(is_num(ang));

    raxis_=ang==180&&raxis==N?X:raxis;

    /*if($debug)*/
    /*echo(pos1,v,pos2,vref, raxis, ang, raxis_);*/

    // Apply the transformations to the child

    // Place the attachable part on the main part attachment point
    t(pos1)
    // Orientate operator. Apply the orientation so that
    // both attachment axis are paralell. Also apply the roll angle
    r(a=roll, v=rollaxis)
    r(a=ang, v=raxis_)
    // Attachable part to the origin
    t(-pos2)
    t(-$explode==U?[0,0,0]:$explode*vref)
    {
        children();

        if($show_conn)
        connector([b.x, -b.y]);
    }

    if($show_conn)
    connector(a);
}

if(false)
{
    s=[10,10,10];

    conn = [X*s.x/2,X];

    /*connector(conn);*/
    cubea(s);
    attach(conn, -conn, $explode=2)
    spherea(d=s.x);
}


base: rename position

base: rename position

include <constants.scad>;

DIAMETER_BASE = 6;
DIAMETER_OUTER_RING = 0.6;
THICKNESS = 0.3;

function radius(diameter) = diameter / 2;

module base()
{
    surface();
    border();
}

module surface()
{
    position_z = - HEIGHT_BODY - THICKNESS;
    position = [0, 0, position_z];

    diameter_total = DIAMETER_BASE - DIAMETER_OUTER_RING;

    color(GREY)
        translate(position)
            cylinder(h = THICKNESS, d = diameter_total, $fn = FINE);
}

module border()
{
    position_base_z = -HEIGHT_BODY;
    position_base = [0, 0, position_base_z];

    position_border_x = radius(DIAMETER_BASE) - radius(DIAMETER_OUTER_RING);

    position_border = [position_border_x, 0, 0];

    color(GREY)
        translate(position_base)
            rotate_extrude(convexity = CONVEXITY, $fn = FINE)
                translate(position_border)
                    circle(r = THICKNESS, $fn = FINE);
}

base();

include <constants.scad>;

DIAMETER_BASE = 6;
DIAMETER_OUTER_RING = 0.6;
THICKNESS = 0.3;

function radius(diameter) = diameter / 2;

module base()
{
    surface();
    border();
}

module surface()
{
    offset_z = - HEIGHT_BODY - THICKNESS;
    offset = [0, 0, offset_z];

    diameter_total = DIAMETER_BASE - DIAMETER_OUTER_RING;

    color(GREY)
        translate(offset)
            cylinder(h = THICKNESS, d = diameter_total, $fn = FINE);
}

module border()
{
    offset_z = -HEIGHT_BODY;
    offset_base = [0, 0, offset_z];

    offset_x = radius(DIAMETER_BASE) - radius(DIAMETER_OUTER_RING);
    offset_border = [offset_x, 0, 0];

    color(GREY)
        translate(offset_base)
            rotate_extrude(convexity = CONVEXITY, $fn = FINE)
                translate(offset_border)
                    circle(r = THICKNESS, $fn = FINE);
}

base();


[scad] first enclosure iteration in openscad

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


adjusted dimensions to match the real phone

// Holder for 4 phones - for the charging station
use <../common/extrusions.scad>
LARGE = 100;
EPSILON = 0.01;

iw = 16.5; // enough to fit phone thickness
thick = 3; // wall thickness
ow = iw + 2*thick;
ri = 5; // internal curvature - should work with phone curvature
ro = 0;
wall_height = 35; // wall height
length = 60; // front-to-back length - along phone should be at least half phone length
dome_r = 5;

module U() {
    O_channel(
    ow, wall_height,
    iw, LARGE,
    thick, thick,
    ro, ri, length
    );
}

module dome_U() {
    hi = 2*wall_height;
    translate([LARGE-EPSILON,0,0]) rotate([0,-90,0])translate([-thick, 0, 0])
    O_channel(
        length+2*thick, hi/2+2*thick,
        length, hi,
        thick, -hi/2, // offsets
        0, dome_r,
        LARGE
    );
}

module many_Us(n) {
    separation = ow - thick;
    for (i = [0 : n-1]) {
        translate([i*separation, 0, 0]) U();
    }
}

module holder() {
    difference() {
        many_Us(4);
        dome_U();
    }
}

holder();
//dome_U();
//translate ([50, 0, 0]) many_Us(4);

// Holder for 4 phones - for the charging station
use <../common/extrusions.scad>
LARGE = 100;
EPSILON = 0.01;
module marker_thing() {
    w = 4.5*25.4;
    thick = 3;
    d = 2*25.4;
    h = 2*25.4;
    ri =  3;
    ro = 1;

     O_channel(
    w+2*thick, h+thick,
    w, LARGE,
    thick, thick, ro, ri, d);
    //cube([w, d, h]);
}

iw = 10; // enough to fit phone thickness
thick = 3; // wall thickness
ow = iw + 2*thick;
ri = 3; // internal curvature - should work with phone curvature
ro = 0;
wall_height = 20; // wall height
length = 30; // front-to-back length - along phone should be at least half phone length
dome_r = 4;

module U() {
    O_channel(
    ow, wall_height,
    iw, LARGE,
    thick, thick,
    ro, ri, length
    );
}

module dome_U() {
    hi = 2*wall_height;
    translate([LARGE-EPSILON,0,0]) rotate([0,-90,0])translate([-thick, 0, 0])
    O_channel(
        length+2*thick, hi/2+2*thick,
        length, hi,
        thick, -hi/2, // offsets
        0, dome_r,
        LARGE
    );
}

module many_Us(n) {
    separation = ow - thick;
    for (i = [0 : n-1]) {
        translate([i*separation, 0, 0]) U();
    }
}

module holder() {
    difference() {
        many_Us(4);
        dome_U();
    }
}

holder();
//dome_U();
//translate ([50, 0, 0]) many_Us(4);


main model of toy elevator roller

main model of toy elevator roller

eps=0.01;
r_stick=2.8/2; // extr_width=0.4, d=2.5mm, thus 7*0.4=2.8 as a next best thing

module roller()
{
  difference()
  {
    cylinder(r=20/2, h=5, $fn=200);
    translate([0, 0, -eps])
      cylinder(r=r_stick, h=5+2*eps, $fn=200);
  }
  translate([20/2-5/2, 0, 5])
    cylinder(r=5/2, h=20, $fn=100);
}

module spool_body_()
{
  r_ext=(5+2*3)/2;
  r_int=r_stick+1;

  difference()
  {
    union()
    {
      cylinder(r1=r_ext, r2=r_int, h=5.5, $fn=150);
      translate([0, 0, 5.5+3])
        cylinder(r1=r_int, r2=r_ext, h=5.5, $fn=150);
      translate([0, 0, 5.5])
        cylinder(r=r_int, h=3, $fn=100);
    }
    translate([0, 0, -eps])
      cylinder(r=r_stick, h=2*5.5+3+2*eps, $fn=200);
  }
}

module hook_()
{
  r_int=1/2;
  r_ext=r_int+1;

  difference()
  {
    translate([-2, -1.5/2, 0])
      cube([2, 1.5, 3+2*3]);

    translate([-1, 0, (3+2*3)/2])
      translate([0, 1, 0])
        rotate([90, 0, 0])
          translate([0, 0, -eps])
            cylinder(r=1/2, h=2+2*eps, $fn=200);
  }
}

module spool()
{
  spool_body_();
  translate([-1.8, 0, 2.5])
    hook_();
}

roller();
translate([20, 0, 0])
  spool();

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