tweaked spacings around F698 bearings a bit.

// try to draw Jansen linkage leg assembly as it might appear in steel

// these are for configuration "E" as referenced in other drawings
AC=17.5;
Ay =  3.318; Bx = 53.833;
BD = 48.020; BE = 46.977; BH = 40.359;
CD = 59.635; CH = 71.441; DE = 66.437;
EF = 47.467; FG = 75.792;
FH = 40.843; GH = 55.790;

DEleft = (DE*DE + BD*BD - BE*BE)/(2*DE);
FGleft = (FG*FG + FH*FH - GH*GH)/(2*FG);
DEperp = sqrt(BD*BD - DEleft*DEleft);
FGperp = sqrt(FH*FH - FGleft*FGleft);

echo(str("DEleft=",DEleft,"   DEperp=",DEperp));
echo(str("FGleft=",FGleft,"   FGperp=",FGperp));

//r38 = (3/8)*2.54/2;  // radius of 3/8" bolt

a=360*$t;
legAssembly(a,0);
mirror([1,0,0]) legAssembly(180-a,1.3);

//  -------------------------- crank-arm circle reference
%color([1,.5,.3,.4]) translate([0,Ay,-2]) difference() {
  cylinder(r=AC,h=1,$fn=48,center=true);
  cylinder(r=2,h=2,center=true);
}
color([0.3,.3,1,.7]) // axles
for(x=[-1,1]) translate([x*Bx,0,0]) difference() {
   cylinder(r=2.54/2,h=20,$fn=24,center=true);
   cylinder(r=2.54/2-.4,h=22,$fn=19,center=true);
}

%translate([0,-93,0]) cube([200,2,2],center=true); // ground

// -----------------------------------------------------------------

// plot a link shadow, a different way, to check kinematic correctness
module checkLink(xa,ya,xb,yb,ab) {
  *translate([(xa+xb)/2,(ya+yb)/2,-9])
    rotate([0,0,atan2(yb-ya,xb-xa)]) cube([ab,1,1],center=true);
}

function triK1(ax,ay,ca,bx,by,cb) = (cb*cb - ca*ca + ax*ax -bx*bx +ay*ay -by*by)/(2*(ax-bx));

// ===================================================================

module legAssembly(ang=0,linkOffset=0) {

// solve kinematics for given crank angle
xC = AC*cos(ang);
yC = AC*sin(ang)+Ay;
echo("C",xC,yC);

k1=(yC*yC - Bx*Bx + BD*BD - CD*CD + xC*xC)/(2*yC);
k2=(xC+Bx)/yC;
c=k1*k1-BD*BD+Bx*Bx;
b=2*(Bx-k1*k2);
a=k2*k2+1;
sgnD=(yC<0)?1:-1;
xD=(-b+sgnD*sqrt(b*b-4*a*c))/(2*a);
yD=sqrt(BD*BD - pow(xD+Bx,2));
echo("D",xD,yD,"CD err",sqrt(pow(xC-xD,2)+pow(yC-yD,2))-CD);

hipRot = atan2(yD,Bx+xD)-atan2(DEperp,DEleft);
echo("hipRot",hipRot);
xE = cos(hipRot) * (DEleft-DE) - sin(hipRot) * DEperp - Bx;
yE = sin(hipRot) * (DEleft-DE) + cos(hipRot) * DEperp;
/*
ke1=(yD*yD + xD*xD + DE*DE + BE*BE)/(2*yD);
ke2=(xD+Bx)/yD;
ae=2+ke2*ke2;
be=2*(Bx-ke1*ke2);
ce=ke1*ke1 - BE*BE +Bx*Bx;
echo("E abc:",ae,be,ce);
xE=(-be+sqrt(be*be-4*ae*ce))/(2*ae);
yE=sqrt(BE*BE - pow(xE+Bx,2));
*/
echo("E",xE,yE);

k1h=(xC*xC + yC*yC + BH*BH - CH*CH - Bx*Bx)/(2*yC);
k2h=-(xC+Bx)/yC;
ah=k2h*k2h+1;
bh=2*(k1h*k2h + Bx);
ch=k1h*k1h + Bx*Bx - BH*BH;
sgnH=(yC>0)?1:-1;
xH=(-bh+sgnH*sqrt(bh*bh-4*ah*ch))/(2*ah);
yH=-sqrt(BH*BH - pow(xH+Bx,2));
bhRot=atan2(yH,xH+Bx);
echo("H",xH,yH,"rot",bhRot,"CH err",sqrt(pow(xH-xC,2)+pow(yH-yC,2))-CH);

/*
k1f=(FH*FH - EF*EF - yE*yE - yH*yH + xE*xE - xH*xH) / (2*(yE-yH));
k2f=(xH-xE)/(yE-yH);
af=k2f*k2f+1;
bf=2*(k1f*k2f - xH - k2f*yH);
cf=xH*xH + yH*yH - 2*k1f*yH + k1f*k1f - FH*FH;
xF=(-bf-sqrt(bf*bf - 4*af*cf))/(2*af);
yF=k1f+k2f*xF;
*/
k2f = (yE-yH)/(xE-xH);
k1f = triK1(xE,yE,EF,xH,yH,FH);
af=k2f*k2f+1;
bf=2*(k2f*xE - k1f*k2f -yE);
cf=k1f*k1f - 2*k1f*xE + xE*xE + yE*yE - EF*EF;
yF=(-bf-sqrt(bf*bf - 4*af*cf))/(2*af);
xF=k1f-k2f*yF;
echo("F",xF,yF,"EF err",sqrt(pow(xF-xE,2)+pow(yF-yE,2))-EF);
echo("FH err",sqrt(pow(xF-xH,2)+pow(yF-yH,2))-FH);

// draw the hip so that the main "plane", the ED centerline plane, is at z=0
translate([-Bx,0,0]) rotate([0,0,hipRot])
    translate([DEleft-DE,DEperp,0]) hip();
//translate([-Bx,0,2.5]) rotate([0,0,12.5]) translate([-DEleft,DEperp,0]) hip();
//translate([ Bx,0,0]) rotate([0,0,-20]) translate([DE-DEleft,DEperp,0]) mirror([1,0,0])
//  hip();
checkLink(-Bx,0,xD,yD,BD);
checkLink(-Bx,0,xE,yE,BE);
checkLink(xD,yD,xE,yE,DE);

translate([-Bx,0,0]) rotate([0,0,bhRot])
   BHlinks();
checkLink(-Bx,0,xH,yH,BH);

//------------------------------------------------------- CrankLinks
translate([xC,yC,linkOffset-.6]) rotate([0,0,atan2(yD-yC,xD-xC)])
  mirror([0,0,(linkOffset>0)?1:0]) crankLink(CD);
checkLink(xC,yC,xD,yD,CD);

translate([xC,yC,linkOffset+2]) rotate([0,0,atan2(yH-yC,xH-xC)])
  mirror([0,0,(linkOffset>0)?1:0]) crankLink(CH);
checkLink(xC,yC,xH,yH,CH);

translate([xF,yF,0]) rotate([0,0,atan2(yE-yF,xE-xF)]) EFlink();
checkLink(xE,yE,xF,yF,EF);

footRot = atan2(yH-yF,xH-xF)-atan2(FGperp,FGleft);
translate([xF,yF,0]) rotate([0,0,footRot])
   foot();
checkLink(xF,yF,xH,yH,FH);

} // end module legAssembly()

// include includes whole text.
// use just imports modules
use <util.scad>

// -----------------------------------------------------------------

module foot() {
  hull() {  // FG
    translate([4,0,.2]) cube([4,2.5,2.5],center=true);
    translate([FG-1.3,0,.2]) cylinder(r=1.3,h=2.6,$fn=24,center=true);
  }

  // knee braces/fork
  for (z=[-1.3,7]) rotate([0,0,(z>0)?25*0:0]) difference() {
    hull() {
      // This was elongated as a brace for knee
      //translate([-5,2,1.5*z])scale([3,5,1])cylinder(r=1,h=.4,$fn=64,center=true);
      // wider knee shouldn't need brace
      translate([0,0,z]) cylinder(r=2.5,h=.4,$fn=24,center=true);
      translate([9,0,z])cylinder(r=1,h=.4,center=true);
    }
    cylinder(r=.4,h=22,$fn=17,center=true);
  }

  // hinge holders at H
  %color([0,0,.6,.4])
  translate([FGleft,FGperp,-1]) difference() {
    cylinder(r=2.54/2,h=7,$fn=36);

    cylinder(r=1.9/2,h=22,center=true,$fn=24);
    translate([0,0,3.6])cube([3,3,2.8],center=true);
  }
  translate([FGleft,FGperp,-.87]) {
    rotate([180,0,0]) F698();
    translate([0,0,5.0]) rotate([180,0,0]) F698();
    translate([0,0,1.95]) F698();
    translate([0,0,6.75]) F698();
  }

  // vertical brace extension at knee
  translate([3.5,0,4.1]) cube([2.6,2.6,5.3],center=true);
  hull() {  // gusset
    translate([ 5.5,-1,1]) cylinder(r=.2,h=5.8,$fn=8);
    translate([18, 1,0]) cylinder(r=.3,h=1  ,$fn=8);
  }

  // FH segment bracing
  for (z=[-.3,5.1]) hull() {
    translate([   3    ,   1    ,z]) barEnd1();
    translate([FGleft-1,FGperp-1,z]) barEnd1();
  }
  hull() {  // dig brace.  Could be gusset?
      translate([3,1,5.7]) barEnd1();
      translate([12,11,-.3]) barEnd1();
  }
  translate([FGleft-2,FGperp-2,.3]) cylinder(r=.8,h=5,$fn=11);
  hull() {
      translate([FGleft-7.2,FGperp-8,5.3]) barEnd1();
      translate([14,13.5,-.3]) barEnd1();
  }

  // GH braces
  hull() {
      translate([FG-8,0,-.3]) barEnd1();
      translate([FGleft+1,FGperp-1,-.3]) barEnd1();
  }
  hull() {
      translate([FG-10,0,0]) barEnd1();
      translate([FGleft+1,FGperp-1,5.2]) barEnd1();
  }

  hull() {    // perp brace
      translate([FGleft,FGperp-1,5.2]) barEnd1();
      translate([FGleft,0,0]) barEnd1();
  }
  hull() {    // perp brace
      translate([FGleft,FGperp-1,-.3]) barEnd1();
      translate([FGleft,0,-.3]) barEnd1();
  }

  // extra truss braces
  hull() {
      translate([46,15,3]) barEnd1();
      translate([35, 0,0]) barEnd1();
  }
  translate([FGleft+2,FGperp-2,.3]) cylinder(r=.6,h=5);
  translate([FGleft,FGperp-2,.3]) cylinder(r=.6,h=5);
}

$fn=12;
module hip() {
  translate([DE/2,0,-.2]) cube([DE-5,2.5,2.5],center=true); // top tube
  translate([DE-DEleft,-DEperp,-1.2]) difference() {
     cylinder(r=2.54*1.5/2,h=7.2,$fn=36); // axle
     cylinder(r=2.54*1.5/2-.3,h=22,$fn=18,center=true);
  }

  // top tube fork plates
  translate([DE,0,0]) mirror([1,0,0]) eFork();
                                      eFork();

  hull() {  // diag tubes
    translate([DE-DEleft,-DEperp,0]) barEnd1();
    translate([8,0,0]) barEnd1();
  }
  hull() {
    translate([DE-DEleft,-DEperp,0]) barEnd1();
    translate([DE-8,0,0]) barEnd1();
  }

  // extra bracing
  translate([DE/2,-20,0]) rotate([0,90,0]) cylinder(r=.8,h=20,center=true);
  translate([DE-DEleft,-DEperp,5]) rotate([-110,0,0]) cylinder(r=.8,h=14.4);
}

module eFork() for(z=[-1,1]) difference() {
  hull() {
    translate([0,0,1.4*z]) cylinder(r=2,h=.3,$fn=24,center=true);
    translate([6,0,1.4*z]) cube([1,2,.3],center=true);
  }
  cylinder(r=.4,h=11,$fn=17,center=true);
}

module crankLink(dx=CD) {
  %color([0,0,.6,.4]) difference() {
    cylinder(r=2.54/2,h=.9,$fn=36,center=true);
    cylinder(r=2.54/2-.17,h=2,$fn=24,center=true);
  }
  translate([0,0, .31]) F698(); //cylinder(r=1.4,h=.7,$fn=24,center=true);
  translate([0,0,-.31]) rotate([180,0,0]) F698();

  //translate([dx/2-1,0,0]) cube([dx-3,1.3,1.3],center=true);
  %color([0,.8,0,.6])
  translate([dx/2-1,0,0]) rotate([0,90,0])
     cylinder(r=.6,h=dx-3,$fn=11,center=true);

  translate([dx,0,0]) SA8();
}

module EFlink() {
  translate([EF,0,0]) SA8();
  translate([EF/2-.4,0,0]) rotate([0,90,0])
      cylinder(r=.8,h=EF-3,$fn=13,center=true);

    // ------ tube and knee bearings
    %color([0,0,.6,.4])
    translate([0,0,-.84]) difference() {
       cylinder(r=2.54/2,h=2.54*3-.25,$fn=36);
       cylinder(r=2.54/2-.3,h=22,$fn=36,center=true);
    }
    translate([0,0,6.41]) F698();
    translate([0,0,-.7]) rotate([180,0,0]) F698();

    hull() {  // gusset
      translate([1.3,0,2*2.54/2]) cylinder(r=.2,h=2.54*3,$fn=12,center=true);
      translate([9,0,   0    ]) cylinder(r=.2,h=1,$fn=12);
    }

  //translate([EF,0,0]) cylinder(r=r38,h=5,center=true);
    //                //cylinder(r=r38,h=55,center=true);
  //cylinder(r=1.2,h=22,$fn=36,center=true);
}

// this link drawn with B axle at origin, always.
module BHlinks() {
  difference() {  // main axle rings
    translate([0,0,2.4]) cylinder(r=2.54*1.5/2,h=13.5,$fn=36,center=true);
    translate([0,0,2.4]) cube([5,5,7.9],center=true);
    cylinder(r=2.54*1.5/2-.3,h=22,$fn=19,center=true);
  }

  for(z=[-2.4,7.2]) {  // main side rails
     hull() {
       translate([BH-6,0,z]) barEnd1();
       translate([   0,0,z]) barEnd1();
     }
  }

  // brace near axle
  translate([3,0,2.2]) cylinder(r=.8,h=10,$fn=19,center=true);

/* get rid of fork brace.  Comes close to hitting CH cranklink.
   let cross members hold forks apart
  //    fork brace
  translate([BH-7,0,2.43]) cube([2.5,2.5,7.6],center=true);

  hull() {
    translate([   4,.7,-1.6]) barEnd1();
    translate([BH-9,.7, 6.2]) barEnd1();
  }
  hull() {
    translate([   4,-.7, 6.2]) barEnd1();
    translate([BH-9,-.7,-1.6]) barEnd1();
  }
*/

  BHcrosses();

  // H forks
  for(z=[-1.7,6.2]) translate([BH,0,z]) difference() {
     hull() {
       cylinder(r=3,h=.33,$fn=36);
       translate([-8,0,0]) cylinder(r=1,h=.33);
     }
     cylinder(r=.7,h=2,center=true);
  }

  // to check dimensions
  //%translate([BH/2,0,2.4]) cube([BH,1,7.8],center=true);
}
module barEnd1() sphere(.8,$fn=12);
// diag braces.  Try to leave fork area open to allow clearance for CH link
module BHcrosses() {
h1=BH-4;  // node closest to H
h2=h1-19;
b2=h2-4;
b1=4;
spread=.7;
lo=-1.6;
hi=6.5;
rBar=.8;
  hull() {
    translate([h2, spread,lo]) barEnd1();
    translate([h1, spread,hi]) barEnd1();
  }
  hull() {
    translate([h2,-spread,hi]) barEnd1();
    translate([h1,-spread,lo]) barEnd1();
  }
  hull() {
    translate([b1,-spread,lo]) barEnd1();
    translate([b2,-spread,hi]) barEnd1();
  }
  hull() {
    translate([b2,spread,lo]) barEnd1();
    translate([b1,spread,hi]) barEnd1();
  }
}

// try to draw Jansen linkage leg assembly as it might appear in steel

// these are for configuration "E" as referenced in other drawings
AC=17.5;
Ay =  3.318; Bx = 53.833;
BD = 48.020; BE = 46.977; BH = 40.359;
CD = 59.635; CH = 71.441; DE = 66.437;
EF = 47.467; FG = 75.792;
FH = 40.843; GH = 55.790;

DEleft = (DE*DE + BD*BD - BE*BE)/(2*DE);
FGleft = (FG*FG + FH*FH - GH*GH)/(2*FG);
DEperp = sqrt(BD*BD - DEleft*DEleft);
FGperp = sqrt(FH*FH - FGleft*FGleft);

echo(str("DEleft=",DEleft,"   DEperp=",DEperp));
echo(str("FGleft=",FGleft,"   FGperp=",FGperp));

//r38 = (3/8)*2.54/2;  // radius of 3/8" bolt

a=360*$t;
legAssembly(a,0);
mirror([1,0,0]) legAssembly(180-a,1.4);

//  -------------------------- crank-arm circle reference
%color([1,.5,.3,.4]) translate([0,Ay,-2]) difference() {
  cylinder(r=AC,h=1,$fn=48,center=true);
  cylinder(r=2,h=2,center=true);
}
color([0.3,.3,1,.7]) // axles
for(x=[-1,1]) translate([x*Bx,0,0]) difference() {
   cylinder(r=2.54/2,h=20,$fn=24,center=true);
   cylinder(r=2.54/2-.4,h=22,$fn=19,center=true);
}

%translate([0,-93,0]) cube([200,2,2],center=true); // ground

// -----------------------------------------------------------------

// plot a link shadow, a different way, to check kinematic correctness
module checkLink(xa,ya,xb,yb,ab) {
  *translate([(xa+xb)/2,(ya+yb)/2,-9])
    rotate([0,0,atan2(yb-ya,xb-xa)]) cube([ab,1,1],center=true);
}

function triK1(ax,ay,ca,bx,by,cb) = (cb*cb - ca*ca + ax*ax -bx*bx +ay*ay -by*by)/(2*(ax-bx));

// ===================================================================

module legAssembly(ang=0,linkOffset=0) {

// solve kinematics for given crank angle
xC = AC*cos(ang);
yC = AC*sin(ang)+Ay;
echo("C",xC,yC);

k1=(yC*yC - Bx*Bx + BD*BD - CD*CD + xC*xC)/(2*yC);
k2=(xC+Bx)/yC;
c=k1*k1-BD*BD+Bx*Bx;
b=2*(Bx-k1*k2);
a=k2*k2+1;
sgnD=(yC<0)?1:-1;
xD=(-b+sgnD*sqrt(b*b-4*a*c))/(2*a);
yD=sqrt(BD*BD - pow(xD+Bx,2));
echo("D",xD,yD,"CD err",sqrt(pow(xC-xD,2)+pow(yC-yD,2))-CD);

hipRot = atan2(yD,Bx+xD)-atan2(DEperp,DEleft);
echo("hipRot",hipRot);
xE = cos(hipRot) * (DEleft-DE) - sin(hipRot) * DEperp - Bx;
yE = sin(hipRot) * (DEleft-DE) + cos(hipRot) * DEperp;
/*
ke1=(yD*yD + xD*xD + DE*DE + BE*BE)/(2*yD);
ke2=(xD+Bx)/yD;
ae=2+ke2*ke2;
be=2*(Bx-ke1*ke2);
ce=ke1*ke1 - BE*BE +Bx*Bx;
echo("E abc:",ae,be,ce);
xE=(-be+sqrt(be*be-4*ae*ce))/(2*ae);
yE=sqrt(BE*BE - pow(xE+Bx,2));
*/
echo("E",xE,yE);

k1h=(xC*xC + yC*yC + BH*BH - CH*CH - Bx*Bx)/(2*yC);
k2h=-(xC+Bx)/yC;
ah=k2h*k2h+1;
bh=2*(k1h*k2h + Bx);
ch=k1h*k1h + Bx*Bx - BH*BH;
sgnH=(yC>0)?1:-1;
xH=(-bh+sgnH*sqrt(bh*bh-4*ah*ch))/(2*ah);
yH=-sqrt(BH*BH - pow(xH+Bx,2));
bhRot=atan2(yH,xH+Bx);
echo("H",xH,yH,"rot",bhRot,"CH err",sqrt(pow(xH-xC,2)+pow(yH-yC,2))-CH);

/*
k1f=(FH*FH - EF*EF - yE*yE - yH*yH + xE*xE - xH*xH) / (2*(yE-yH));
k2f=(xH-xE)/(yE-yH);
af=k2f*k2f+1;
bf=2*(k1f*k2f - xH - k2f*yH);
cf=xH*xH + yH*yH - 2*k1f*yH + k1f*k1f - FH*FH;
xF=(-bf-sqrt(bf*bf - 4*af*cf))/(2*af);
yF=k1f+k2f*xF;
*/
k2f = (yE-yH)/(xE-xH);
k1f = triK1(xE,yE,EF,xH,yH,FH);
af=k2f*k2f+1;
bf=2*(k2f*xE - k1f*k2f -yE);
cf=k1f*k1f - 2*k1f*xE + xE*xE + yE*yE - EF*EF;
yF=(-bf-sqrt(bf*bf - 4*af*cf))/(2*af);
xF=k1f-k2f*yF;
echo("F",xF,yF,"EF err",sqrt(pow(xF-xE,2)+pow(yF-yE,2))-EF);
echo("FH err",sqrt(pow(xF-xH,2)+pow(yF-yH,2))-FH);

// draw the hip so that the main "plane", the ED centerline plane, is at z=0
translate([-Bx,0,0]) rotate([0,0,hipRot])
    translate([DEleft-DE,DEperp,0]) hip();
//translate([-Bx,0,2.5]) rotate([0,0,12.5]) translate([-DEleft,DEperp,0]) hip();
//translate([ Bx,0,0]) rotate([0,0,-20]) translate([DE-DEleft,DEperp,0]) mirror([1,0,0])
//  hip();
checkLink(-Bx,0,xD,yD,BD);
checkLink(-Bx,0,xE,yE,BE);
checkLink(xD,yD,xE,yE,DE);

translate([-Bx,0,0]) rotate([0,0,bhRot])
   BHlinks();
checkLink(-Bx,0,xH,yH,BH);

//------------------------------------------------------- CrankLinks
translate([xC,yC,linkOffset-.6]) rotate([0,0,atan2(yD-yC,xD-xC)])
  mirror([0,0,(linkOffset>0)?1:0]) crankLink(CD);
checkLink(xC,yC,xD,yD,CD);

translate([xC,yC,linkOffset+2.2]) rotate([0,0,atan2(yH-yC,xH-xC)])
  mirror([0,0,(linkOffset>0)?1:0]) crankLink(CH);
checkLink(xC,yC,xH,yH,CH);

translate([xF,yF,0]) rotate([0,0,atan2(yE-yF,xE-xF)]) EFlink();
checkLink(xE,yE,xF,yF,EF);

footRot = atan2(yH-yF,xH-xF)-atan2(FGperp,FGleft);
translate([xF,yF,0]) rotate([0,0,footRot])
   foot();
checkLink(xF,yF,xH,yH,FH);

} // end module legAssembly()

// include includes whole text.
// use just imports modules
use <util.scad>

// -----------------------------------------------------------------

module foot() {
  hull() {  // FG
    translate([4,0,.2]) cube([4,2.5,2.5],center=true);
    translate([FG-1.3,0,.2]) cylinder(r=1.3,h=2.6,$fn=24,center=true);
  }

  // knee braces/fork
  for (z=[-1.3,7]) rotate([0,0,(z>0)?25*0:0]) difference() {
    hull() {
      // This was elongated as a brace for knee
      //translate([-5,2,1.5*z])scale([3,5,1])cylinder(r=1,h=.4,$fn=64,center=true);
      // wider knee shouldn't need brace
      translate([0,0,z]) cylinder(r=2.5,h=.4,$fn=24,center=true);
      translate([9,0,z])cylinder(r=1,h=.4,center=true);
    }
    cylinder(r=.4,h=22,$fn=17,center=true);
  }

  // hinge holders at H
  %color([0,0,.6,.4])
  translate([FGleft,FGperp,-1]) difference() {
    cylinder(r=2.54/2,h=7,$fn=36);

    cylinder(r=1.9/2,h=22,center=true,$fn=24);
    translate([0,0,3.9])cube([3,3,2.8],center=true);
  }
  translate([FGleft,FGperp,-.87]) {
    rotate([180,0,0]) F698();
    translate([0,0,5.3]) rotate([180,0,0]) F698();
    translate([0,0,2.24]) F698();
    translate([0,0,6.74]) F698();
  }

  // vertical brace extension at knee
  translate([3.5,0,4.1]) cube([2.6,2.6,5.3],center=true);
  hull() {  // gusset
    translate([ 5.5,-1,1]) cylinder(r=.2,h=5.8,$fn=8);
    translate([18, 1,0]) cylinder(r=.3,h=1  ,$fn=8);
  }

  // FH segment bracing
  for (z=[-.3,5.1]) hull() {
    translate([   3    ,   1    ,z]) barEnd1();
    translate([FGleft-1,FGperp-1,z]) barEnd1();
  }
  hull() {  // dig brace.  Could be gusset?
      translate([3,1,5.7]) barEnd1();
      translate([12,11,-.3]) barEnd1();
  }
  translate([FGleft-2,FGperp-2,.3]) cylinder(r=.8,h=5,$fn=11);
  hull() {
      translate([FGleft-7.2,FGperp-8,5.3]) barEnd1();
      translate([14,13.5,-.3]) barEnd1();
  }

  // GH braces
  hull() {
      translate([FG-8,0,-.3]) barEnd1();
      translate([FGleft+1,FGperp-1,-.3]) barEnd1();
  }
  hull() {
      translate([FG-10,0,0]) barEnd1();
      translate([FGleft+1,FGperp-1,5.2]) barEnd1();
  }

  hull() {    // perp brace
      translate([FGleft,FGperp-1,5.2]) barEnd1();
      translate([FGleft,0,0]) barEnd1();
  }
  hull() {    // perp brace
      translate([FGleft,FGperp-1,-.3]) barEnd1();
      translate([FGleft,0,-.3]) barEnd1();
  }

  // extra truss braces
  hull() {
      translate([46,15,3]) barEnd1();
      translate([35, 0,0]) barEnd1();
  }
  translate([FGleft+2,FGperp-2,.3]) cylinder(r=.6,h=5);
  translate([FGleft,FGperp-2,.3]) cylinder(r=.6,h=5);
}

$fn=12;
module hip() {
  translate([DE/2,0,-.2]) cube([DE-5,2.5,2.5],center=true); // top tube
  translate([DE-DEleft,-DEperp,-1.2]) difference() {
     cylinder(r=2.54*1.5/2,h=7.2,$fn=36); // axle
     cylinder(r=2.54*1.5/2-.3,h=22,$fn=18,center=true);
  }

  // top tube fork plates
  translate([DE,0,0]) mirror([1,0,0]) eFork();
                                      eFork();

  hull() {  // diag tubes
    translate([DE-DEleft,-DEperp,0]) barEnd1();
    translate([8,0,0]) barEnd1();
  }
  hull() {
    translate([DE-DEleft,-DEperp,0]) barEnd1();
    translate([DE-8,0,0]) barEnd1();
  }

  // extra bracing
  translate([DE/2,-20,0]) rotate([0,90,0]) cylinder(r=.8,h=20,center=true);
  translate([DE-DEleft,-DEperp,5]) rotate([-110,0,0]) cylinder(r=.8,h=14.4);
}

module eFork() for(z=[-1,1]) difference() {
  hull() {
    translate([0,0,1.4*z]) cylinder(r=2,h=.3,$fn=24,center=true);
    translate([6,0,1.4*z]) cube([1,2,.3],center=true);
  }
  cylinder(r=.4,h=11,$fn=17,center=true);
}

module crankLink(dx=CD) {
  %color([0,0,.6,.4]) difference() {
    cylinder(r=2.54/2,h=1,$fn=36,center=true);
    cylinder(r=2.54/2-.17,h=2,$fn=24,center=true);
  }
  translate([0,0, .36]) F698(); //cylinder(r=1.4,h=.7,$fn=24,center=true);
  translate([0,0,-.36]) rotate([180,0,0]) F698();

  //translate([dx/2-1,0,0]) cube([dx-3,1.3,1.3],center=true);
  %color([0,.8,0,.6])
  translate([dx/2-1,0,0]) rotate([0,90,0])
     cylinder(r=.6,h=dx-3,$fn=11,center=true);

  translate([dx,0,0]) SA8();
}

module EFlink() {
  translate([EF,0,0]) SA8();
  translate([EF/2-.4,0,0]) rotate([0,90,0])
      cylinder(r=.8,h=EF-3,$fn=13,center=true);

    // ------ tube and knee bearings
    %color([0,0,.6,.4])
    translate([0,0,-.84]) difference() {
       cylinder(r=2.54/2,h=2.54*3-.25,$fn=36);
       cylinder(r=2.54/2-.3,h=22,$fn=36,center=true);
    }
    translate([0,0,6.41]) F698();
    translate([0,0,-.7]) rotate([180,0,0]) F698();

    hull() {  // gusset
      translate([1.3,0,2*2.54/2]) cylinder(r=.2,h=2.54*3,$fn=12,center=true);
      translate([9,0,   0    ]) cylinder(r=.2,h=1,$fn=12);
    }

  //translate([EF,0,0]) cylinder(r=r38,h=5,center=true);
    //                //cylinder(r=r38,h=55,center=true);
  //cylinder(r=1.2,h=22,$fn=36,center=true);
}

// this link drawn with B axle at origin, always.
module BHlinks() {
  difference() {  // main axle rings
    translate([0,0,2.4]) cylinder(r=2.54*1.5/2,h=13.5,$fn=36,center=true);
    translate([0,0,2.4]) cube([5,5,7.9],center=true);
    cylinder(r=2.54*1.5/2-.3,h=22,$fn=19,center=true);
  }

  for(z=[-2.4,7.2]) {  // main side rails
     hull() {
       translate([BH-6,0,z]) barEnd1();
       translate([   0,0,z]) barEnd1();
     }
  }

  // brace near axle
  translate([3,0,2.2]) cylinder(r=.8,h=10,$fn=19,center=true);

/* get rid of fork brace.  Comes close to hitting CH cranklink.
   let cross members hold forks apart
  //    fork brace
  translate([BH-7,0,2.43]) cube([2.5,2.5,7.6],center=true);

  hull() {
    translate([   4,.7,-1.6]) barEnd1();
    translate([BH-9,.7, 6.2]) barEnd1();
  }
  hull() {
    translate([   4,-.7, 6.2]) barEnd1();
    translate([BH-9,-.7,-1.6]) barEnd1();
  }
*/

  BHcrosses();

  // H forks
  for(z=[-1.7,6.2]) translate([BH,0,z]) difference() {
     hull() {
       cylinder(r=3,h=.33,$fn=36);
       translate([-8,0,0]) cylinder(r=1,h=.33);
     }
     cylinder(r=.7,h=2,center=true);
  }

  // to check dimensions
  //%translate([BH/2,0,2.4]) cube([BH,1,7.8],center=true);
}
module barEnd1() sphere(.8,$fn=12);
// diag braces.  Try to leave fork area open to allow clearance for CH link
module BHcrosses() {
h1=BH-4;  // node closest to H
h2=h1-19;
b2=h2-4;
b1=4;
spread=.7;
lo=-1.6;
hi=6.5;
rBar=.8;
  hull() {
    translate([h2, spread,lo]) barEnd1();
    translate([h1, spread,hi]) barEnd1();
  }
  hull() {
    translate([h2,-spread,hi]) barEnd1();
    translate([h1,-spread,lo]) barEnd1();
  }
  hull() {
    translate([b1,-spread,lo]) barEnd1();
    translate([b2,-spread,hi]) barEnd1();
  }
  hull() {
    translate([b2,spread,lo]) barEnd1();
    translate([b1,spread,hi]) barEnd1();
  }
}


[3d] Extend USB pillar reinforcements top to bottom and make ends 1mm wider

// preview[view:northeast, tilt:topdiagonal]

/* [Options] */
// Pit probe type
Control_Probe = "Thermocouple"; // [Thermocouple,Thermistor]
// Raspberry Pi Model
Pi_Model = "3B/2B/1B+"; // [3B/2B/1B+,1A+,Zero]
// Which case halves
Pieces = "Both"; // [Both,Top,Bottom]
// Corner ear height
MouseEarHeight = 0.0;

/* [Hidden] */
function inch(x) = x*25.4;

w = inch(3.75)+0.5; // overall interior case width
d = inch(3.75)-0.5; // overall interior case depth
h_b = 32; // overall interior case height

probe_centerline = 9.0; // case is split along probe centerline

pic_ex = 2;
lcd_mount_t = 7;

wall = 2.0*1.41; // thickness of side walls (*1.41 so rounded corners are this width)
wall_t = 2; // thickness of top and bottom walls
e = 0.01;

echo("WALL is ", wall);
hm43_split();

module cube_fillet_chamfer(size,f,c,$fn=32) {
  hull() {
    translate([f,f,c]) linear_extrude(height=size[2]-2*c) minkowski() {
      square([size[0]-2*f, size[1]-2*f]);
      circle(r=f, $fn=$fn);
    }
    translate([f+c,f+c,0]) linear_extrude(height=size[2]) minkowski() {
      square([size[0]-2*(f+c), size[1]-2*(f+c)]);
      circle(r=f, $fn=$fn);
    }
  }
}

module jhole(d, h) {
  translate([0,0,h/2]) cube([2*(wall+pic_ex),d,h], center=true);
}

module phole() {
  dia=4.5;
  // Hole for thermistor probe jack
  rotate([0,90,0]) cylinder(2*wall, d=dia, $fn=16);
  // because 3d print tends to curl up slightly between the probe holes,
  // do not go right to the edge on the final layer (stop 0.25mm short on each side)
  translate([0,-(dia+0.5)/2, -0.3]) cube([2*wall, dia+0.5, 0.6]);
}

module screwhole() {
  // Screw hole for bottom of case (including nut)
  //translate([0,0,-e]) cylinder(h_b+wall_t, d=3.4, $fn=18);
  translate([0,0,-e]) {
    cylinder(0.4, d1=7.4, d2=6.6, $fn=6);
    translate([0,0,0.4]) cylinder(3, d=6.6, $fn=6);
  }
  translate([0,0,3+0.2]) cylinder(h_b+2*wall_t, d=3.4, $fn=18);
  translate([0,0,h_b+wall_t]) cylinder(3, d=5.5, $fn=18);
}

module screwhole2() {
  translate([0,0,-e]) cylinder(3, d=6, $fn=18);
  translate([0,0,3+0.4]) cylinder(h_b-3-0.4, d=3.4, $fn=18);
}

module pic_ex_cube() {
  translate([0,33.75,2])
    cube_fillet([pic_ex+e, 59.5, 20.8],
      vertical=[0, pic_ex, pic_ex, 0],
      top=[0,pic_ex,0,0],
      bottom=[0,pic_ex,0,0]);
}

module screw_pimount() {
  // 2mm height is good for screw holes
  difference() {
    cylinder(h=2.25, d=6.4, $fn=18);
    //cylinder(h=2+e, d=2.5, $fn=16);
  }
}

module btn_rnd(dia=10) {
  cylinder(wall_t+2*e, d1=dia, d2=dia+1.5*wall_t, $fn=24);
  translate([-6.5,-6.5,0]) cube([13,13,0.75+e]);
}

module btn_square(sq=13) {
  translate([-sq/2,-sq/2,0]) cube([sq,sq,wall_t+2*e]);
}

module tc_plusminus() {
  T=0.75+e;
  H=2;
  W=6;
  // Minus
  translate([0,2,0])
    cube_fillet([T, W, H], top=[0,0,0,T]);
  translate([0,-(2+W),0]) {
    cube_fillet([T, W, H], top=[0,0,0,T]);
    translate([0,(W-H)/2,(H-W)/2])
      cube_fillet([T, H, W], top=[0,0,0,T]);
  }
}

module led_hole() {
  cylinder(wall_t+2*e, d=3.4, $fn=16);
}

module nuttrap() {
  ww_w=3;
  ww_d=2.7;
  nut_h=2.8;
  nut_ingress = 5.8; //nut_d * sin(60);
  nut_d = nut_ingress / sin(60);
  oa_h=wall_t+0.4+nut_h+wall_t+6.7;

  // bottom half for M3 socket cap screw (flush)
  difference() {
    translate([-5.5/2-ww_w, -nut_ingress/2-e, 0])
      cube_fillet([5.5+2*ww_w, nut_ingress+ww_d*0.8+e, 6], vertical=[3.4,3.4], $fn=20);
    // socket cap
    translate([0,0,-e]) cylinder(3.5, d=6, $fn=18);
    // screw shaft
    translate([0,0,3.5+0.3]) cylinder(oa_h-3, d=3.4, $fn=18);
  }

  // top half M3 nut trap
  translate([0,0,h_b+wall_t-oa_h])
  difference() {
    translate([-(nut_d/2+ww_w), -nut_ingress/2-e, 0])
      cube_fillet([nut_d+2*ww_w, nut_ingress+ww_d+e, oa_h],
        vertical=[3.4,3.4], $fn=20);
    // M3 screw
    translate([0,0,-e]) cylinder(wall_t, d1=4, d2=3.4, $fn=16);
    // nut hole / M3 extra
    translate([0,0,wall_t+0.3]) {
      translate([-0.4,0,0]) // nut offset slightly deeper for easier alignment
        cylinder(nut_h*1.5+e, d=nut_d, $fn=6);  // nut
      cylinder(oa_h-wall_t-0.3, d=4, $fn=16);  // M3 with plenty of clearance
    }
    // nut ingress
    translate([0,-nut_ingress/2,wall_t+0.3])
      cube([nut_d/2+ww_w+e,nut_ingress,nut_h+e]);
  }
}

module locklip_p(l, l_offset=1,
  lip_insert_depth=2.0, // how deep V to insert
  lip_v_off=0.2, // extra height before starting insert
  lip_h_off=0.4, // back connector away from mating area
  lip_w=1.5  // thickness of attachment beam
  ) {
  translate([l_offset,0,0]) rotate([90,0,0]) rotate([0,90,0])
    linear_extrude(height=l-2*l_offset) polygon(points=[
      [0, -lip_w-lip_insert_depth-lip_h_off],
      [0, 0],
      [-lip_insert_depth-lip_h_off, 0],
      [-lip_insert_depth-lip_h_off, lip_v_off],
      [-lip_h_off, lip_v_off+lip_insert_depth],
      [-lip_insert_depth-lip_h_off, lip_v_off+2*lip_insert_depth,],
      [-lip_w-lip_insert_depth-lip_h_off, lip_v_off+2*lip_insert_depth],
      [-lip_w-lip_insert_depth-lip_h_off, 0]
    ]);
}

module locklip_n(l, l_offset=1,
  lip_insert_depth=2.2, // how deep V to insert
  lip_tip_clip=0.3, // how much to shave off the top tip
  ) {
  translate([l-l_offset,0,0]) rotate([90,0,0]) rotate([0,-90,0])
    linear_extrude(height=l-2*l_offset) polygon(points=[
      [0.1, -3*lip_insert_depth],  // 0.1 to add depth to keep extrusion manifold
      [0.1, -lip_tip_clip],
      [-lip_insert_depth+lip_tip_clip, -lip_tip_clip],
      [-e, -lip_insert_depth],
      [-lip_insert_depth, -2*lip_insert_depth]
    ]);
}

module lcd_screw() {
  rotate([180]) difference() {
    //cylinder(lcd_mount_t, d=2.5+3.2, $fn=16);
    cylinder(lcd_mount_t+e, d=2.5, $fn=16);
  }
}

module lcd_mount() {
  // Assuming starting at bottom left screw hole
  lcd_screw();
  //translate([75,0,0]) lcd_screw(); // bottom right hole obscured by PCB
  translate([0,31,0]) lcd_screw();
  translate([75,31,0]) lcd_screw();
}

module lcd_neg() {
  // Assuming starting at bottom left screw hole
  translate([1.0, 2.1, 0])
    cube([73.0, 26.3, lcd_mount_t+wall_t-0.8]); // black bezel inset
  translate([5.5, 7.8, 0])
    cube([64.0, 15.4, lcd_mount_t+wall_t+2*e]); // LCD active area
  translate([4.23, -2.5, 0])
    cube([16*2.54, 5, lcd_mount_t+wall_t-0.8]); // pins cutout
}

module mouseears() {
  me_h = MouseEarHeight;
  me_d = 15;
  me_outset_bottom = (me_d/4) - wall/2;
  me_outset_top = (me_d/4) - wall;

  // Bottom corners
  translate([-me_outset_bottom, -me_outset_bottom, 0])
    cylinder(me_h, d1=me_d, d2=me_d-2*me_h, $fn=24);
  translate([w+2*wall+me_outset_bottom, -me_outset_bottom, 0])
    cylinder(me_h, d1=me_d, d2=me_d-2*me_h, $fn=24);
  translate([w+2*wall+me_outset_bottom, d+2*wall+me_outset_bottom, 0])
    cylinder(me_h, d1=me_d, d2=me_d-2*me_h, $fn=24);
  translate([-me_outset_bottom, d+2*wall+me_outset_bottom, 0])
    cylinder(me_h, d1=me_d, d2=me_d-2*me_h, $fn=24);

  // top corners
  translate([0,0,h_b+2*wall_t-me_h]) {
    translate([-me_outset_top, -me_outset_top, 0])
      cylinder(me_h, d2=me_d, d1=me_d-2*me_h, $fn=24);
    translate([w+2*wall+me_outset_top, -me_outset_top, 0])
      cylinder(me_h, d2=me_d, d1=me_d-2*me_h, $fn=24);
    translate([w+2*wall+me_outset_top, d+2*wall+me_outset_top, 0])
      cylinder(me_h, d2=me_d, d1=me_d-2*me_h, $fn=24);
    translate([-me_outset_top, d+2*wall+me_outset_top, 0])
      cylinder(me_h, d2=me_d, d1=me_d-2*me_h, $fn=24);
  }
}

module hm43() {
difference() {
  union() {
    cube_bchamfer([w+2*wall, d+2*wall, h_b+2*wall_t],
      r=wall, top=wall/2, bottom=wall/2, $fn=36);
    // extra thick by Pi connectors
    if (Pi_Model != "Zero")
      translate([-pic_ex,wall,wall_t])
        pic_ex_cube();
    // TC +/-
    if (Control_Probe == "Thermocouple")
      translate([w+wall*2-e,wall+10,wall_t+18]) tc_plusminus();
    if (MouseEarHeight > 0.0)
      mouseears();
  }
  translate([wall, wall, wall_t]) cube([w, d, h_b+e]);
  if (Pi_Model != "Zero")
    translate([wall-pic_ex+e,wall,wall_t]) pic_ex_cube();

  // Probe jack side
  translate([w+wall*0.5,wall,wall_t]) {
    // Probe jacks
    translate([0,24.25,probe_centerline]) {
      if (Control_Probe == "Thermocouple")
        // TC jack
        translate([0,inch(-0.55)-16.5/2,-1.4]) cube([2*wall, 16.5, 6.5]);
      else
        translate([0,-17.25,0]) phole();
      translate([0,inch(0.37)*0,0]) phole();
      translate([0,inch(0.37)*1,0]) phole();
      translate([0,inch(0.37)*2,0]) phole();
    }
  }
  // Pi connector side
  translate([wall*-0.5,wall,wall_t]) {
    // Pi connectors
    translate([0,0,5]) {
      if (Pi_Model == "3B/2B/1B+") {
        // ethernet
        translate([0,81.5,-0.5]) jhole(15,13);
        translate([0,81.5,-1.5]) jhole(5,5);
        // USB 0+1
        translate([0,62.75,0]) jhole(13,14.8);
        translate([0,44.75,0]) jhole(13,14.8);
      }
      if (Pi_Model == "1A+")
        translate([0,44.75,0]) jhole(13,7.4);
    }
    // HeaterMeter connectors
    translate([0,0,0]) {
      // Blower/Servo output
      translate([0,25.25,1.1]) jhole(16.7,13);
      // HM power jack
      translate([0,5.25,3.4]) jhole(9.4,11);
    }
  }

  // lcd hole
  translate([wall+10.7, wall+52, h_b+wall_t-lcd_mount_t-e]) lcd_neg();

  // button holes
  translate([wall+48.7, wall+29.4, h_b+wall_t-e]) {
    translate([-inch(1.1)/2,0,0]) btn_rnd(7.2);  // left
    translate([inch(1.1)/2,0,0]) btn_rnd(7.2);   // right
    translate([0,inch(0.9)/2,0]) btn_rnd(7.2);   // up
    translate([0,-inch(0.9)/2,0]) btn_rnd(7.2);  // down
    // LED holes
    translate([inch(1.3), inch(-0.05), 0]) {
      led_hole();  //red
      translate([0, inch(0.35), 0]) led_hole(); //yellow
      translate([0, inch(0.70), 0]) led_hole(); //green
    }
  }
  // close screw holes
  translate([wall+inch(0.8)+1.3,wall+2.9,0]) {
    screwhole2();
    translate([inch(2.0),0,0]) screwhole2();
  }
}  // END OF DIFFERENCE

  // Pi mounting screws
  translate([wall+24,wall+d-7,wall_t]) {
    //screw_pimount();
    translate([58,0,0]) screw_pimount();
    translate([58,-49,0]) screw_pimount();
    translate([0,-49,0]) screw_pimount();
    translate([0,0,0]) screw_pimount();
  }
  // Pi right edge stop
  translate([wall+w-10, wall+d-60, wall_t]) {
    difference() {
      cube_fillet([10,60,4], vertical=[0,0,10/2], $fn=24);
      // Pi B+ microsd gap
      translate([-e,22.5,-e]) cube_fillet([6,14,4+2*e], vertical=[2,0,0,2], $fn=20);
    }
  }

  // close nut traps
  translate([wall+inch(0.8)+1.3,wall+2.9,0]) {
    nuttrap();
    translate([inch(2.0),0,0]) nuttrap();
  }

  // Top locklip (negative)
  translate([wall, d+wall, probe_centerline+wall_t+e])
    rotate([180]) {
      locklip_n(28);
      translate([w-34,0,0]) locklip_n(34);
    }

  // LCD mount
  difference() {
    union() {
      // Filled block above LCD hole
      translate([wall, wall+d-16, h_b+wall_t-lcd_mount_t]) cube([w,16,lcd_mount_t+e]);
      // LCD grab notch
      translate([wall+10.7, wall+52, h_b+wall_t-lcd_mount_t])
        translate([(77.5-20)/2,33.5-wall_t,-(1.8+wall_t)])
          // 1.8=thickness of LCD pcb
          cube_fillet([20,1.8+wall_t+wall,1.8+wall_t+e], top=[0,0,1.8+wall_t+e],
            vertical=[wall/2,wall/2]);
    }
    translate([wall+10.7, wall+52, h_b+wall_t-lcd_mount_t-e]) lcd_neg();
    translate([wall+10.7, wall+52, h_b+wall_t-e]) lcd_mount();
  }

  if (Pi_Model == "3B/2B/1B+")
    translate([wall-pic_ex, wall, wall_t]) {
      // USB pillar reinforcements
      translate([0, (44.75+62.75)/2-1, 0]) cube([pic_ex+1, 2, h_b]);
      translate([0, 81.5-15/2-3, 0]) cube([pic_ex+1, 2.5, h_b]);
      // Near pic_ex fill
      translate([0, 33.75, 0]) cube([pic_ex+1, 3, h_b]);
      // Far pic_ex fill (near ethernet)
      translate([0, (33.75+59.5)-3, 0]) cube([pic_ex+1, 3, h_b]);
    }
}

module lip_guide(l) {
  guide_offset = 0.2; // how much to recess the edge guides
  guide_h = 1.2; // how tall above the edge to extend
  linear_extrude(height=l) polygon([
    [0,-e], [wall+guide_offset,-e], [0, wall+guide_offset],
    [-guide_h, wall+guide_offset], [-guide_h, guide_offset],
    [0, guide_offset]
  ]);
}

module hm43_bottom_lips() {
  translate([wall, wall, probe_centerline+wall_t]) {
    // bottom locklip (postive)
    translate([0,d,0]) {
      locklip_p(28);
      translate([w-34,0,0]) locklip_p(34);
    }

    // front guide lip
    translate([w/2-9, 0, 0])
      rotate([0,90]) lip_guide(30);
    // right guide lip
    translate([w, d-45, 0])
      rotate([-90]) rotate(90) lip_guide(40);
    // left guide lip assortment
    translate([0, 5.25+9.4/2, 0])
      rotate([-90]) rotate(90) mirror([0,1,0]) lip_guide(25.25-5.25-9.4/2-16.7/2);
    *translate([-pic_ex, 52, 0])
      rotate([-90]) rotate(90) mirror([0,1,0]) lip_guide(3.5);
    *translate([-pic_ex, 70, 0])
      rotate([-90]) rotate(90) mirror([0,1,0]) lip_guide(3.5);
  }
}

module hm43_split() {
  half=wall_t+probe_centerline;

  // bottom
  if (Pieces != "Top") {
    intersection() {
      hm43();
      translate([-w,-d,0]) cube([w*3, d*3, half]);
    }
    hm43_bottom_lips();
  } // if include bottom

  // top
  if (Pieces != "Bottom") {
    translate([0,-2,h_b+2*wall_t]) rotate([180]) intersection() {
      hm43();
      translate([-w,-d,half]) cube([w*3, d*3, h_b]);
    }
  }  // if include top
}

/**********************                               **********************/
/********************** END OF CASE / LIBRARY FOLLOWS **********************/
/**********************                               **********************/

module cube_bchamfer(dim, r, top=0, bottom=0, $fn=$fn) {
  // bottom beaded area
  if (bottom != 0) hull(){
    translate([r,r,0]) cylinder(bottom, r1=r-bottom, r2=r, $fn=$fn);
    translate([dim[0]-r,r,0]) cylinder(bottom, r1=r-bottom, r2=r, $fn=$fn);
    translate([r,dim[1]-r,0]) cylinder(bottom, r1=r-bottom, r2=r, $fn=$fn);
    translate([dim[0]-r,dim[1]-r,0]) cylinder(bottom, r1=r-bottom, r2=r, $fn=$fn);
  }
  // center
  translate([0,0,bottom]) hull(){
    translate([r,r,0]) cylinder(dim[2]-top-bottom, r=r, $fn=$fn);
    translate([dim[0]-r,r,0]) cylinder(dim[2]-top-bottom, r=r, $fn=$fn);
    translate([r,dim[1]-r,0]) cylinder(dim[2]-top-bottom, r=r, $fn=$fn);
    translate([dim[0]-r,dim[1]-r,0]) cylinder(dim[2]-top-bottom, r=r, $fn=$fn);
  }
  // top beaded area
  if (top != 0) translate([0,0,dim[2]-top]) hull(){
    translate([r,r,0]) cylinder(top, r2=r-top, r1=r, $fn=$fn);
    translate([dim[0]-r,r,0]) cylinder(top, r2=r-top, r1=r, $fn=$fn);
    translate([r,dim[1]-r,0]) cylinder(top, r2=r-top, r1=r, $fn=$fn);
    translate([dim[0]-r,dim[1]-r,0]) cylinder(top, r2=r-top, r1=r, $fn=$fn);
  }
}

module fillet(radius, height=100, $fn=$fn) {
  if (radius > 0) {
    //this creates acutal fillet
    translate([-radius, -radius, -height / 2 - 0.02]) difference() {
        cube([radius * 2, radius * 2, height + 0.04]);
        if ($fn == 0 && (radius == 2 || radius == 3 || radius == 4)) {
            cylinder(r=radius, h=height + 0.04, $fn=4 * radius);
        } else {
            cylinder(r=radius, h=height + 0.04, $fn=$fn);
        }

    }
  }
}

module cube_fillet(size, radius=-1, vertical=[0,0,0,0], top=[0,0,0,0], bottom=[0,0,0,0], center=false, $fn=4){
    if (center) {
        cube_fillet_inside(size, radius, vertical, top, bottom, $fn);
    } else {
        translate([size[0]/2, size[1]/2, size[2]/2])
            cube_fillet_inside(size, radius, vertical, top, bottom, $fn);
    }
}

module cube_negative_fillet(size, radius=-1, vertical=[3,3,3,3], top=[0,0,0,0], bottom=[0,0,0,0], $fn=$fn){
    j=[1,0,1,0];

    for (i=[0:3]) {
        if (radius > -1) {
            rotate([0, 0, 90*i]) translate([size[1-j[i]]/2, size[j[i]]/2, 0]) fillet(radius, size[2], $fn);
        } else {
            rotate([0, 0, 90*i]) translate([size[1-j[i]]/2, size[j[i]]/2, 0]) fillet(vertical[i], size[2], $fn);
        }
        rotate([90*i, -90, 0]) translate([size[2]/2, size[j[i]]/2, 0 ]) fillet(top[i], size[1-j[i]], $fn);
        rotate([90*(4-i), 90, 0]) translate([size[2]/2, size[j[i]]/2, 0]) fillet(bottom[i], size[1-j[i]], $fn);

    }
}

module cube_fillet_inside(size, radius=-1, vertical=[3,3,3,3], top=[0,0,0,0], bottom=[0,0,0,0], $fn=$fn){
    //makes CENTERED cube with round corners
    // if you give it radius, it will fillet vertical corners.
    //othervise use vertical, top, bottom arrays
    //when viewed from top, it starts in upper right corner (+x,+y quadrant) , goes counterclockwise
    //top/bottom fillet starts in direction of Y axis and goes CCW too

    if (radius == 0) {
        cube(size, center=true);
    } else {
        difference() {
            cube(size, center=true);
            cube_negative_fillet(size, radius, vertical, top, bottom, $fn);
        }
    }
}

//cube_fillet([10,10,10]);

// preview[view:northeast, tilt:topdiagonal]

/* [Options] */
// Pit probe type
Control_Probe = "Thermocouple"; // [Thermocouple,Thermistor]
// Raspberry Pi Model
Pi_Model = "3B/2B/1B+"; // [3B/2B/1B+,1A+,Zero]
// Which case halves
Pieces = "Both"; // [Both,Top,Bottom]
// Corner ear height
MouseEarHeight = 0.0;

/* [Hidden] */
function inch(x) = x*25.4;

w = inch(3.75)+0.5; // overall interior case width
d = inch(3.75)-0.5; // overall interior case depth
h_b = 32; // overall interior case height

probe_centerline = 9.0; // case is split along probe centerline

pic_ex = 2;
lcd_mount_t = 7;

wall = 2.0*1.41; // thickness of side walls (*1.41 so rounded corners are this width)
wall_t = 2; // thickness of top and bottom walls
e = 0.01;

echo("WALL is ", wall);
hm43_split();

module cube_fillet_chamfer(size,f,c,$fn=32) {
  hull() {
    translate([f,f,c]) linear_extrude(height=size[2]-2*c) minkowski() {
      square([size[0]-2*f, size[1]-2*f]);
      circle(r=f, $fn=$fn);
    }
    translate([f+c,f+c,0]) linear_extrude(height=size[2]) minkowski() {
      square([size[0]-2*(f+c), size[1]-2*(f+c)]);
      circle(r=f, $fn=$fn);
    }
  }
}

module jhole(d, h) {
  translate([0,0,h/2]) cube([2*(wall+pic_ex),d,h], center=true);
}

module phole() {
  dia=4.5;
  // Hole for thermistor probe jack
  rotate([0,90,0]) cylinder(2*wall, d=dia, $fn=16);
  // because 3d print tends to curl up slightly between the probe holes,
  // do not go right to the edge on the final layer (stop 0.25mm short on each side)
  translate([0,-(dia+0.5)/2, -0.3]) cube([2*wall, dia+0.5, 0.6]);
}

module screwhole() {
  // Screw hole for bottom of case (including nut)
  //translate([0,0,-e]) cylinder(h_b+wall_t, d=3.4, $fn=18);
  translate([0,0,-e]) {
    cylinder(0.4, d1=7.4, d2=6.6, $fn=6);
    translate([0,0,0.4]) cylinder(3, d=6.6, $fn=6);
  }
  translate([0,0,3+0.2]) cylinder(h_b+2*wall_t, d=3.4, $fn=18);
  translate([0,0,h_b+wall_t]) cylinder(3, d=5.5, $fn=18);
}

module screwhole2() {
  translate([0,0,-e]) cylinder(3, d=6, $fn=18);
  translate([0,0,3+0.4]) cylinder(h_b-3-0.4, d=3.4, $fn=18);
}

module pic_ex_cube() {
  translate([0,33.75,2])
    cube_fillet([pic_ex+e, 59.5, 20.8],
      vertical=[0, pic_ex, pic_ex, 0],
      top=[0,pic_ex,0,0],
      bottom=[0,pic_ex,0,0]);
}

module screw_pimount() {
  // 2mm height is good for screw holes
  difference() {
    cylinder(h=2.25, d=6.4, $fn=18);
    //cylinder(h=2+e, d=2.5, $fn=16);
  }
}

module btn_rnd(dia=10) {
  cylinder(wall_t+2*e, d1=dia, d2=dia+1.5*wall_t, $fn=24);
  translate([-6.5,-6.5,0]) cube([13,13,0.75+e]);
}

module btn_square(sq=13) {
  translate([-sq/2,-sq/2,0]) cube([sq,sq,wall_t+2*e]);
}

module tc_plusminus() {
  T=0.75+e;
  H=2;
  W=6;
  // Minus
  translate([0,2,0])
    cube_fillet([T, W, H], top=[0,0,0,T]);
  translate([0,-(2+W),0]) {
    cube_fillet([T, W, H], top=[0,0,0,T]);
    translate([0,(W-H)/2,(H-W)/2])
      cube_fillet([T, H, W], top=[0,0,0,T]);
  }
}

module led_hole() {
  cylinder(wall_t+2*e, d=3.4, $fn=16);
}

module nuttrap() {
  ww_w=3;
  ww_d=2.7;
  nut_h=2.8;
  nut_ingress = 5.8; //nut_d * sin(60);
  nut_d = nut_ingress / sin(60);
  oa_h=wall_t+0.4+nut_h+wall_t+6.7;

  // bottom half for M3 socket cap screw (flush)
  difference() {
    translate([-5.5/2-ww_w, -nut_ingress/2-e, 0])
      cube_fillet([5.5+2*ww_w, nut_ingress+ww_d*0.8+e, 6], vertical=[3.4,3.4], $fn=20);
    // socket cap
    translate([0,0,-e]) cylinder(3.5, d=6, $fn=18);
    // screw shaft
    translate([0,0,3.5+0.3]) cylinder(oa_h-3, d=3.4, $fn=18);
  }

  // top half M3 nut trap
  translate([0,0,h_b+wall_t-oa_h])
  difference() {
    translate([-(nut_d/2+ww_w), -nut_ingress/2-e, 0])
      cube_fillet([nut_d+2*ww_w, nut_ingress+ww_d+e, oa_h],
        vertical=[3.4,3.4], $fn=20);
    // M3 screw
    translate([0,0,-e]) cylinder(wall_t, d1=4, d2=3.4, $fn=16);
    // nut hole / M3 extra
    translate([0,0,wall_t+0.3]) {
      translate([-0.4,0,0]) // nut offset slightly deeper for easier alignment
        cylinder(nut_h*1.5+e, d=nut_d, $fn=6);  // nut
      cylinder(oa_h-wall_t-0.3, d=4, $fn=16);  // M3 with plenty of clearance
    }
    // nut ingress
    translate([0,-nut_ingress/2,wall_t+0.3])
      cube([nut_d/2+ww_w+e,nut_ingress,nut_h+e]);
  }
}

module locklip_p(l, l_offset=1,
  lip_insert_depth=2.0, // how deep V to insert
  lip_v_off=0.2, // extra height before starting insert
  lip_h_off=0.4, // back connector away from mating area
  lip_w=1.5  // thickness of attachment beam
  ) {
  translate([l_offset,0,0]) rotate([90,0,0]) rotate([0,90,0])
    linear_extrude(height=l-2*l_offset) polygon(points=[
      [0, -lip_w-lip_insert_depth-lip_h_off],
      [0, 0],
      [-lip_insert_depth-lip_h_off, 0],
      [-lip_insert_depth-lip_h_off, lip_v_off],
      [-lip_h_off, lip_v_off+lip_insert_depth],
      [-lip_insert_depth-lip_h_off, lip_v_off+2*lip_insert_depth,],
      [-lip_w-lip_insert_depth-lip_h_off, lip_v_off+2*lip_insert_depth],
      [-lip_w-lip_insert_depth-lip_h_off, 0]
    ]);
}

module locklip_n(l, l_offset=1,
  lip_insert_depth=2.2, // how deep V to insert
  lip_tip_clip=0.3, // how much to shave off the top tip
  ) {
  translate([l-l_offset,0,0]) rotate([90,0,0]) rotate([0,-90,0])
    linear_extrude(height=l-2*l_offset) polygon(points=[
      [0.1, -3*lip_insert_depth],  // 0.1 to add depth to keep extrusion manifold
      [0.1, -lip_tip_clip],
      [-lip_insert_depth+lip_tip_clip, -lip_tip_clip],
      [-e, -lip_insert_depth],
      [-lip_insert_depth, -2*lip_insert_depth]
    ]);
}

module lcd_screw() {
  rotate([180]) difference() {
    //cylinder(lcd_mount_t, d=2.5+3.2, $fn=16);
    cylinder(lcd_mount_t+e, d=2.5, $fn=16);
  }
}

module lcd_mount() {
  // Assuming starting at bottom left screw hole
  lcd_screw();
  //translate([75,0,0]) lcd_screw(); // bottom right hole obscured by PCB
  translate([0,31,0]) lcd_screw();
  translate([75,31,0]) lcd_screw();
}

module lcd_neg() {
  // Assuming starting at bottom left screw hole
  translate([1.0, 2.1, 0])
    cube([73.0, 26.3, lcd_mount_t+wall_t-0.8]); // black bezel inset
  translate([5.5, 7.8, 0])
    cube([64.0, 15.4, lcd_mount_t+wall_t+2*e]); // LCD active area
  translate([4.23, -2.5, 0])
    cube([16*2.54, 5, lcd_mount_t+wall_t-0.8]); // pins cutout
}

module mouseears() {
  me_h = MouseEarHeight;
  me_d = 15;
  me_outset_bottom = (me_d/4) - wall/2;
  me_outset_top = (me_d/4) - wall;

  // Bottom corners
  translate([-me_outset_bottom, -me_outset_bottom, 0])
    cylinder(me_h, d1=me_d, d2=me_d-2*me_h, $fn=24);
  translate([w+2*wall+me_outset_bottom, -me_outset_bottom, 0])
    cylinder(me_h, d1=me_d, d2=me_d-2*me_h, $fn=24);
  translate([w+2*wall+me_outset_bottom, d+2*wall+me_outset_bottom, 0])
    cylinder(me_h, d1=me_d, d2=me_d-2*me_h, $fn=24);
  translate([-me_outset_bottom, d+2*wall+me_outset_bottom, 0])
    cylinder(me_h, d1=me_d, d2=me_d-2*me_h, $fn=24);

  // top corners
  translate([0,0,h_b+2*wall_t-me_h]) {
    translate([-me_outset_top, -me_outset_top, 0])
      cylinder(me_h, d2=me_d, d1=me_d-2*me_h, $fn=24);
    translate([w+2*wall+me_outset_top, -me_outset_top, 0])
      cylinder(me_h, d2=me_d, d1=me_d-2*me_h, $fn=24);
    translate([w+2*wall+me_outset_top, d+2*wall+me_outset_top, 0])
      cylinder(me_h, d2=me_d, d1=me_d-2*me_h, $fn=24);
    translate([-me_outset_top, d+2*wall+me_outset_top, 0])
      cylinder(me_h, d2=me_d, d1=me_d-2*me_h, $fn=24);
  }
}

module hm43() {
difference() {
  union() {
    cube_bchamfer([w+2*wall, d+2*wall, h_b+2*wall_t],
      r=wall, top=wall/2, bottom=wall/2, $fn=36);
    // extra thick by Pi connectors
    if (Pi_Model != "Zero")
      translate([-pic_ex,wall,wall_t])
        pic_ex_cube();
    // TC +/-
    if (Control_Probe == "Thermocouple")
      translate([w+wall*2-e,wall+10,wall_t+18]) tc_plusminus();
    if (MouseEarHeight > 0.0)
      mouseears();
  }
  translate([wall, wall, wall_t]) cube([w, d, h_b+e]);
  if (Pi_Model != "Zero")
    translate([wall-pic_ex+e,wall,wall_t]) pic_ex_cube();

  // Probe jack side
  translate([w+wall*0.5,wall,wall_t]) {
    // Probe jacks
    translate([0,24.25,probe_centerline]) {
      if (Control_Probe == "Thermocouple")
        // TC jack
        translate([0,inch(-0.55)-16.5/2,-1.4]) cube([2*wall, 16.5, 6.5]);
      else
        translate([0,-17.25,0]) phole();
      translate([0,inch(0.37)*0,0]) phole();
      translate([0,inch(0.37)*1,0]) phole();
      translate([0,inch(0.37)*2,0]) phole();
    }
  }
  // Pi connector side
  translate([wall*-0.5,wall,wall_t]) {
    // Pi connectors
    translate([0,0,5]) {
      if (Pi_Model == "3B/2B/1B+") {
        // ethernet
        translate([0,81.5,-0.5]) jhole(15,13);
        translate([0,81.5,-1.5]) jhole(5,5);
        // USB 0+1
        translate([0,62.75,0]) jhole(13,14.8);
        translate([0,44.75,0]) jhole(13,14.8);
      }
      if (Pi_Model == "1A+")
        translate([0,44.75,0]) jhole(13,7.4);
    }
    // HeaterMeter connectors
    translate([0,0,0]) {
      // Blower/Servo output
      translate([0,25.25,1.1]) jhole(16.7,13);
      // HM power jack
      translate([0,5.25,3.4]) jhole(9.4,11);
    }
  }

  // lcd hole
  translate([wall+10.7, wall+52, h_b+wall_t-lcd_mount_t-e]) lcd_neg();

  // button holes
  translate([wall+48.7, wall+29.4, h_b+wall_t-e]) {
    translate([-inch(1.1)/2,0,0]) btn_rnd(7.2);  // left
    translate([inch(1.1)/2,0,0]) btn_rnd(7.2);   // right
    translate([0,inch(0.9)/2,0]) btn_rnd(7.2);   // up
    translate([0,-inch(0.9)/2,0]) btn_rnd(7.2);  // down
    // LED holes
    translate([inch(1.3), inch(-0.05), 0]) {
      led_hole();  //red
      translate([0, inch(0.35), 0]) led_hole(); //yellow
      translate([0, inch(0.70), 0]) led_hole(); //green
    }
  }
  // close screw holes
  translate([wall+inch(0.8)+1.3,wall+2.9,0]) {
    screwhole2();
    translate([inch(2.0),0,0]) screwhole2();
  }
}  // END OF DIFFERENCE

  // Pi mounting screws
  translate([wall+24,wall+d-7,wall_t]) {
    //screw_pimount();
    translate([58,0,0]) screw_pimount();
    translate([58,-49,0]) screw_pimount();
    translate([0,-49,0]) screw_pimount();
    translate([0,0,0]) screw_pimount();
  }
  // Pi right edge stop
  translate([wall+w-10, wall+d-60, wall_t]) {
    difference() {
      cube_fillet([10,60,4], vertical=[0,0,10/2], $fn=24);
      // Pi B+ microsd gap
      translate([-e,22.5,-e]) cube_fillet([6,14,4+2*e], vertical=[2,0,0,2], $fn=20);
    }
  }

  // close nut traps
  translate([wall+inch(0.8)+1.3,wall+2.9,0]) {
    nuttrap();
    translate([inch(2.0),0,0]) nuttrap();
  }

  // Top locklip (negative)
  translate([wall, d+wall, probe_centerline+wall_t+e])
    rotate([180]) {
      locklip_n(28);
      translate([w-34,0,0]) locklip_n(34);
    }

  // LCD mount
  difference() {
    union() {
      // Filled block above LCD hole
      translate([wall, wall+d-16, h_b+wall_t-lcd_mount_t]) cube([w,16,lcd_mount_t+e]);
      // LCD grab notch
      translate([wall+10.7, wall+52, h_b+wall_t-lcd_mount_t])
        translate([(77.5-20)/2,33.5-wall_t,-(1.8+wall_t)])
          // 1.8=thickness of LCD pcb
          cube_fillet([20,1.8+wall_t+wall,1.8+wall_t+e], top=[0,0,1.8+wall_t+e],
            vertical=[wall/2,wall/2]);
    }
    translate([wall+10.7, wall+52, h_b+wall_t-lcd_mount_t-e]) lcd_neg();
    translate([wall+10.7, wall+52, h_b+wall_t-e]) lcd_mount();
  }

  if (Pi_Model == "3B/2B/1B+")
    translate([wall-pic_ex, wall, wall_t+2]) {
      // USB pillar reinforcements
      translate([0, (44.75+62.75)/2-1, 0]) cube([pic_ex, 2, 20.8]);
      translate([0, 81.5-15/2-3, 0]) cube([pic_ex, 2.5, 20.8]);
      // Near pic_ex fill
      translate([0, 33.75, 0]) cube([pic_ex, 3, 20.8]);
      // Far pic_ex fill (near ethernet)
      translate([0, (33.75+59.5)-3, 0]) cube([pic_ex, 3, 20.8]);
    }
}

module lip_guide(l) {
  guide_offset = 0.2; // how much to recess the edge guides
  guide_h = 1.2; // how tall above the edge to extend
  linear_extrude(height=l) polygon([
    [0,-e], [wall+guide_offset,-e], [0, wall+guide_offset],
    [-guide_h, wall+guide_offset], [-guide_h, guide_offset],
    [0, guide_offset]
  ]);
}

module hm43_bottom_lips() {
  translate([wall, wall, probe_centerline+wall_t]) {
    // bottom locklip (postive)
    translate([0,d,0]) {
      locklip_p(28);
      translate([w-34,0,0]) locklip_p(34);
    }

    // front guide lip
    translate([w/2-9, 0, 0])
      rotate([0,90]) lip_guide(30);
    // right guide lip
    translate([w, d-45, 0])
      rotate([-90]) rotate(90) lip_guide(40);
    // left guide lip assortment
    translate([0, 5.25+9.4/2, 0])
      rotate([-90]) rotate(90) mirror([0,1,0]) lip_guide(25.25-5.25-9.4/2-16.7/2);
    *translate([-pic_ex, 52, 0])
      rotate([-90]) rotate(90) mirror([0,1,0]) lip_guide(3.5);
    *translate([-pic_ex, 70, 0])
      rotate([-90]) rotate(90) mirror([0,1,0]) lip_guide(3.5);
  }
}

module hm43_split() {
  half=wall_t+probe_centerline;

  // bottom
  if (Pieces != "Top") {
    intersection() {
      hm43();
      translate([-w,-d,0]) cube([w*3, d*3, half]);
    }
    hm43_bottom_lips();
  } // if include bottom

  // top
  if (Pieces != "Bottom") {
    translate([0,-2,h_b+2*wall_t]) rotate([180]) intersection() {
      hm43();
      translate([-w,-d,half]) cube([w*3, d*3, h_b]);
    }
  }  // if include top
}

/**********************                               **********************/
/********************** END OF CASE / LIBRARY FOLLOWS **********************/
/**********************                               **********************/

module cube_bchamfer(dim, r, top=0, bottom=0, $fn=$fn) {
  // bottom beaded area
  if (bottom != 0) hull(){
    translate([r,r,0]) cylinder(bottom, r1=r-bottom, r2=r, $fn=$fn);
    translate([dim[0]-r,r,0]) cylinder(bottom, r1=r-bottom, r2=r, $fn=$fn);
    translate([r,dim[1]-r,0]) cylinder(bottom, r1=r-bottom, r2=r, $fn=$fn);
    translate([dim[0]-r,dim[1]-r,0]) cylinder(bottom, r1=r-bottom, r2=r, $fn=$fn);
  }
  // center
  translate([0,0,bottom]) hull(){
    translate([r,r,0]) cylinder(dim[2]-top-bottom, r=r, $fn=$fn);
    translate([dim[0]-r,r,0]) cylinder(dim[2]-top-bottom, r=r, $fn=$fn);
    translate([r,dim[1]-r,0]) cylinder(dim[2]-top-bottom, r=r, $fn=$fn);
    translate([dim[0]-r,dim[1]-r,0]) cylinder(dim[2]-top-bottom, r=r, $fn=$fn);
  }
  // top beaded area
  if (top != 0) translate([0,0,dim[2]-top]) hull(){
    translate([r,r,0]) cylinder(top, r2=r-top, r1=r, $fn=$fn);
    translate([dim[0]-r,r,0]) cylinder(top, r2=r-top, r1=r, $fn=$fn);
    translate([r,dim[1]-r,0]) cylinder(top, r2=r-top, r1=r, $fn=$fn);
    translate([dim[0]-r,dim[1]-r,0]) cylinder(top, r2=r-top, r1=r, $fn=$fn);
  }
}

module fillet(radius, height=100, $fn=$fn) {
  if (radius > 0) {
    //this creates acutal fillet
    translate([-radius, -radius, -height / 2 - 0.02]) difference() {
        cube([radius * 2, radius * 2, height + 0.04]);
        if ($fn == 0 && (radius == 2 || radius == 3 || radius == 4)) {
            cylinder(r=radius, h=height + 0.04, $fn=4 * radius);
        } else {
            cylinder(r=radius, h=height + 0.04, $fn=$fn);
        }

    }
  }
}

module cube_fillet(size, radius=-1, vertical=[0,0,0,0], top=[0,0,0,0], bottom=[0,0,0,0], center=false, $fn=4){
    if (center) {
        cube_fillet_inside(size, radius, vertical, top, bottom, $fn);
    } else {
        translate([size[0]/2, size[1]/2, size[2]/2])
            cube_fillet_inside(size, radius, vertical, top, bottom, $fn);
    }
}

module cube_negative_fillet(size, radius=-1, vertical=[3,3,3,3], top=[0,0,0,0], bottom=[0,0,0,0], $fn=$fn){
    j=[1,0,1,0];

    for (i=[0:3]) {
        if (radius > -1) {
            rotate([0, 0, 90*i]) translate([size[1-j[i]]/2, size[j[i]]/2, 0]) fillet(radius, size[2], $fn);
        } else {
            rotate([0, 0, 90*i]) translate([size[1-j[i]]/2, size[j[i]]/2, 0]) fillet(vertical[i], size[2], $fn);
        }
        rotate([90*i, -90, 0]) translate([size[2]/2, size[j[i]]/2, 0 ]) fillet(top[i], size[1-j[i]], $fn);
        rotate([90*(4-i), 90, 0]) translate([size[2]/2, size[j[i]]/2, 0]) fillet(bottom[i], size[1-j[i]], $fn);

    }
}

module cube_fillet_inside(size, radius=-1, vertical=[3,3,3,3], top=[0,0,0,0], bottom=[0,0,0,0], $fn=$fn){
    //makes CENTERED cube with round corners
    // if you give it radius, it will fillet vertical corners.
    //othervise use vertical, top, bottom arrays
    //when viewed from top, it starts in upper right corner (+x,+y quadrant) , goes counterclockwise
    //top/bottom fillet starts in direction of Y axis and goes CCW too

    if (radius == 0) {
        cube(size, center=true);
    } else {
        difference() {
            cube(size, center=true);
            cube_negative_fillet(size, radius, vertical, top, bottom, $fn);
        }
    }
}

//cube_fillet([10,10,10]);


Baseplate is now compatible with any motor bracket

//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([-(3/5)*plateY/2, plateY / 2, 0]) {
            hull(){
            translate([0, 0, 0]) cylinder(h = 15, r = holeradius, center = true);
            translate([(1/5)*plateY, 0, 0]) cylinder(h = 15, r = holeradius, center = true);
            }

            hull(){
            translate([(3/5)*plateY, 0, 0]) cylinder(h = 15, r = holeradius, center = true);
            translate([(3/5)*plateY-(1/5)*plateY, 0, 0]) cylinder(h = 15, r = holeradius, center = true);
            }
            hull(){
            translate([0, 25, 0]) cylinder(h = 15, r = holeradius, center = true);
            translate([(1/5)*plateY, 25, 0]) cylinder(h = 15, r = holeradius, center = true);
            }
            hull(){
            translate([(3/5)*plateY, 25, 0]) cylinder(h = 15, r = holeradius, center = true);
            translate([(3/5)*plateY-(1/5)*plateY, 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;
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();


Create StepperMount.scad

Create StepperMount.scad

/*
Stepper steel mount
*/
module StepperMount (){
color( "Black", 1 ) {
union (){
difference (){

     cube ([50,52,53.5]) ;

     // difference starts here
   translate ([-1,3,3])
     cube ([52,52,53.5]) ;
    hull() {
        translate ([8,3,13]) rotate ([90,0,0])
        cylinder(d=4.2,h=10, center = true);
            translate ([8,3,42]) rotate ([90,0,0])
        cylinder(d=4.2,h=10, center = true);
       }
    hull() {
        translate ([42,3,13]) rotate ([90,0,0])
        cylinder(d=4.2,h=10, center = true);
        translate ([42,3,42]) rotate ([90,0,0])
        cylinder(d=4.2,h=10, center = true);
    }
        translate ([25,31,-1])
        cylinder(d=22,h=10, center = true);
        translate ([10,46,-1])
        cylinder(d=3.5,h=10, center = true);
        translate ([10,15,-1])
        cylinder(d=3.5,h=10, center = true);
        translate ([41,15,-1])
        cylinder(d=3.5,h=10, center = true);
        translate ([41,46,-1])
        cylinder(d=3.5,h=10, center = true);

}
difference (){
        translate ([0,3,3])
        cube ([3,20,15]) ;
        translate ([4,3,18]) rotate ([127,0,180])
        cube ([5,20,30]) ;
}
difference (){
        translate ([47,3,3])
        cube ([3,20,15]) ;
        translate ([51,3,18]) rotate ([127,0,180])
        cube ([5,20,30]) ;
}
}
}
}
// Place the stepper mounts
translate ([13,320 ,56]) rotate ([0,180,180])
StepperMount ();

translate ([377,320 ,56]) rotate ([0,180,180])
StepperMount ();

//  the CoreXY drive shafts
color( "Silver", 1 ) {
translate ([38,289 ,66]) rotate ([0,0,180])
cylinder(d=8,h=270, center = false);
translate ([402,289 ,66]) rotate ([0,0,180])
cylinder(d=8,h=270, center = false);
}

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