result

result

// collection of parts for the new picker idea

airflow = 57;
sleeveout = airflow+1;

// [fullOD, shaftD, thickness, turning_hubD]
hubbearing = [22,8,7,13];
travelbearing = [6,3,2.5,5];
travelwheel = 60;
travelpeg = travelwheel - travelbearing[1];

fat     = 0.3;  // add-on to make walls cut out enough space
hb      = 12.7 + fat; // height of bar cross-section
wthk    = 1.5 + fat;  // thickness of walls
flrthk  = 1.6 + fat;  // thickness of floor (that walls extend from)
inside  = 6.9 - fat;  // between walls, across floor (subtracting 2*.5*fat)
c_bar = [[0,0], [0,hb], [wthk, hb], [wthk, flrthk], [wthk+inside, flrthk], [wthk+inside, hb], [wthk+inside+wthk, hb], [wthk+inside+wthk, 0]];

//#shaft(travelbearing);
//#cbar(barH=100);
//#can_sleeve();
//translate([50,50,0])
//    for (i=[0:3:360]){
//        nutbolt(nut_position=20*i/360, channel_ang=i);
//    }
//bigwheel_part();
// bartest();

// ** the can traveler by itself ***
//rotate([0,0,180]) translate([0, -56, +25.9])
    //upndown();

//motorcut();
//cbar();

rackpush();

// ** the main picker body **
//cbracket();

// ** the valve parts **
//louvers();

//plate_air_parts();

// for cutting out shaft and hub-turning space
module shaft(bearing, xtraH=0, hubclearance=0.5){
    height=bearing[2] + xtraH;
    translate([0,0,-height/2-hubclearance/2])
        cylinder(r=bearing[3]/2, h=hubclearance, center=true, $fn=28);
    translate([0,0,0])
        cylinder(r=bearing[1]/2, h=height, center=true, $fn=24);
    translate([0,0,height/2+hubclearance/2])
        cylinder(r=bearing[3]/2, h=hubclearance, center=true, $fn=28);
    echo("shaft of bearing = ", bearing, "is top-to-bottom = ", hubclearance*2 + height);
}

// alluminum c-channel, positive or negative
module cbar(outline=c_bar, barH=50){
    midbar = outline[7][0] / 2;
    echo("midbar read as: ",midbar);
    translate([-midbar,0,0])
    linear_extrude(center=true, height=barH, convexity=10, slices=2)
        polygon(points=outline);
}

// intended as positive model, could add scale or thickness
module can_sleeve (emptyness=airflow, thickness=sleeveout-airflow-0.2, sleeveH=25){
    translate([0,0,-sleeveH/2])
        rotate_extrude($fn=196)
            translate([(emptyness+thickness) / 2, 0, 0])
                polygon(points=[[0,0], [0,sleeveH], [thickness,sleeveH], [thickness,0]]);
}

// negative model with channel for captured nut insertion
module nutbolt(hexhead=6.65,
                shaftD=3.1,
                shaftlen=20,
                nut_position=17,
                nut_thick=2.33,
                channel_len=30,
                channel_ang=0,){
    color( .5, .9, .9 )
    translate([0,0,-shaftlen/2]){  //center it by shaftlen
        //shaft
        cylinder(r=shaftD/2, h=shaftlen, center=false, $fn=18);
        //head
        #translate([0,0,shaftlen-hexhead/2])
        cylinder(r=hexhead/2, h=hexhead/2, center=false, $fn=6);
        //nut + channel
        translate([0,0,shaftlen-nut_position])
        hull(){
        rotate([0,0,channel_ang])
            cylinder(r=hexhead/2+.1, h=nut_thick+.1, center=false, $fn=6);
        translate([cos(channel_ang)*channel_len,
                    sin(channel_ang)*channel_len, 0])
            rotate([0,0,channel_ang])
                cylinder(r=hexhead/2+.2, h=nut_thick+.1, center=false, $fn=6);
        }
    }
}

module motorhub(flat_to_flat=4.76, diameter=7.4, height=5.57, baseD=9, baseH=1.0){
    cutrad = (diameter - flat_to_flat)/2;
    cutcenter = flat_to_flat/2 + cutrad;
    cylinder(r=baseD/2, h=baseH+0.1, center=false, $fn=36);
    cylinder(r=0.8, h=baseH+5*height+.1, center=true, $fn=6);
    translate([0,0,baseH])
        difference(){
            cylinder(r=diameter/2, h=height+baseH, center=false, $fn=24);
            for (i=[cutcenter+0.05, -cutcenter-0.05]){
                translate([0,i,(height+baseH)/2])
                    cube([diameter+0.1, cutrad+0.1, height+.1], center=true);
            }

        }
}

module bigwheel_part(od=travelwheel, thk=4, hub=12, hubthk=4, holes=6, lever=5){
    overall_thk = thk+hubthk;
    echo("overall bigwheel thickness is : ", overall_thk);
    difference(){
        union(){
            cylinder(r=od/2, h=thk, $fn=196);
            translate([0,0,4])
            cylinder(r=hub/2, h=hubthk, $fn=64);
        }
        translate([0,0,overall_thk+0.05]) rotate([180,0,0])
            motorhub();
        for (i=[0 : 360/holes : 360-(360/holes)*.5]){
            translate([od/3.14*cos(i), od/3.14*sin(i), hubthk/2])
                cylinder(r=od*.5/(holes-1), h=hubthk+.1, center=true, $fn=42);
        }
        translate([0,od/2-lever,-9]) rotate([0,0,0])
            nutbolt();
        translate([0,-od/2+lever,-9]) rotate([0,0,0])
            nutbolt();
    }
}

module ring(ID, OD, ht){
    difference(){
        cylinder(r=OD/2, h=ht, center=true, $fn=96);
        cylinder(r=ID/2, h=ht+.1, center=true, $fn=96);
    }
}

// for LMB8MM
module bearingcut(D=15.1/2, dring=14.41/2, drod=8.9/2, dziptie=[19,3.3],){
    rotate_extrude(center=true, convexity=10, $fn=36){
        polygon(points=[[0,-2], [D,0],
                        [D,3.3], [dring,3.3],
                        [dring,4.55], [D,4.55],
                        [D,19.35], [dring,19.35],
                        [dring,20.8], [D,20.8],
                        [D, 24.01], [0,26.01]]);
    }
    // zip tie rings
    for (i=[(3.3+4.55)/2, (19.35+20.8)/2]){
        translate([0,0,i])
            ring(dziptie[0], dziptie[0]+dziptie[1], 5);
    }
    // rod upon which it travels
    translate([0,0,12])
        cylinder(r=drod, h=90, $fn=18, center=true);
}

module bigwheel_cutout(od=travelwheel+3, thk=10){
    cylinder(r=od/2, h=thk, $fn=128);
}

module bartest(ht=10){
    difference(){
    minkowski(){
        cube([20,20,10], center=true);
        cylinder(r=4, h=.1, center=true, $fn=24);
    }
    translate([-7,-9,0])
        #cbar(barH=30);
    translate([17,0,0]) rotate([0,0,90])
        #cbar(barH=30);
    translate([0,10.5,0]) rotate([90,0,0])
        #shaft(hubbearing);
    }
}

module upndown(ht=travelwheel){
    difference(){
    cube([travelwheel, travelwheel/2, ht], center=true);
    // lift rail
    translate([0, travelwheel/2-hb, 0])
        cube([travelwheel+.1, hb+.1, c_bar[6][0]+.1], center=true);
    // side rails
    translate([-travelwheel/2+.5 ,3.25, 0]) rotate([0,0,-0])
        cube([hb+.5, c_bar[6][0]+1, travelwheel+.1], center=true);
    translate([travelwheel/2-.5 ,3.25, 0]) rotate([0,0,0])
        cube([hb+.5, c_bar[6][0]+1, travelwheel+.1], center=true);

    // cylinder space
    translate([0, -travelwheel/2, 0])
        cylinder(r = (sleeveout+.5)/2, h=ht+.1, $fn=196, center=true);
    // nuts
    translate([0,0,ht/4]) rotate([90,0,0])
        #nutbolt(channel_ang=90);
    translate([0,0,-ht/4]) rotate([90,0,0])
        #nutbolt(channel_ang=-90);
    }
    // underside printing supports for lift rail
    for (i=[0:5:travelwheel-1]){
        translate([i - travelwheel/2+2.5, travelwheel/2-hb*1.333, 0])
            cube([.5, hb*.37, c_bar[6][0]+.1], center=true);
    }
}

module upndown_cutout(ht=travelwheel){
    translate([0,-4.5,0])
    cube([travelwheel+1, travelwheel/2+9.5, ht+2], center=true);
    // lift rail
    //translate([0, travelwheel/2+hb, 0])
    //    cube([travelwheel+.1, hb+.1, c_bar[6][0]+.1], center=true);
    // side rails
    translate([-travelwheel/2+hb/2+.2,-5, 0]) rotate([0,0,90])
        cbar(barH=70);
    translate([travelwheel/2-hb/2-.2,-5, 0]) rotate([0,0,-90])
        cbar(barH=70);
    // cylinder of suckage
    translate([0, -travelwheel/2 -9.5, 0])
        cylinder(r = (sleeveout+2)/2, h=ht+2, $fn=196, center=true);

}

module motorcut(x=23,y=22,z=37,tab=[6,4,5],tabpos=7,curverad=5, shaftpos=[0,11,16], canheight=28){
    tiptop = canheight + z + tab[2] - curverad;
    // top-motorhousing
    translate([0,y/2, tiptop - canheight])
        cylinder(r=x/2, h=canheight, center=false, $fn=36);
    // gearbox housing
    translate([-(x-curverad*2)/2, 0, curverad+tab[2]])
        minkowski(){
            cube([x-curverad*2,y,z-curverad*2], center=false);
            rotate([90,0,0])
                cylinder(r=curverad, h=.1, center=false, $fn=64);
        }
    // tab thingy for motor attachment
    translate([0,tabpos+tab[1]/2, tab[2]/2]){
        cube(tab, center=true);
        // cuts hole for bolting tab
        rotate([90,0,0])
            cylinder(r=3.26/2, h=50, center=true, $fn=12);
    }
    // driven hub stub and slide-in track
    translate(shaftpos)
        rotate([90,0,0])
            hull(){
            cylinder(r=9.14/2, h=y+4, center=true, $fn=18);
            translate([0,z-shaftpos[0], 0])
                cylinder(r=9.14/2, h=y+4, center=true, $fn=18);
            }
    // cuts shaft for holes that penetrate housing
    for (i=[1,-1]){
    translate([17.75/2 * i, 0, 36])
        rotate([90,0,0])
            cylinder(r=3.26/2, h=50, center=true, $fn=12);
    }
    // add on the driven wheel
    translate(shaftpos)
        rotate([90, 0,0]) translate([0,0,-y]){
            bigwheel_cutout();
            // and its connection hub
            translate([0,0,+3])
            hull(){
                cylinder(r=8, h=15, $fn=16, center=false);
                translate([0,z-shaftpos[0], 0])
                cylinder(r=8, h=15, $fn=16, center=false);
            }
        }
    // make a cut-out for the traveling part
    rotate([0,0,180]) translate(shaftpos) translate([0,-59,0])
    upndown_cutout();
}

// carve the big thing out of a block
module cbracket(z=travelwheel/2, bs=1.5){
    difference(){
        translate([-travelwheel/2, 0, -4])
        minkowski(){
            cube([travelwheel, travelwheel*1.2, travelwheel-17], center=false);
            cylinder(r=8, h=1, $fn=16);
        }
    motorcut();
    translate([-travelwheel/2-bs, -bs, 4])
    bearingcut();
    translate([travelwheel/2+bs,-bs, 4])
    bearingcut();
    translate([z+2.5,z*2.5+.5,z*1.3]) rotate([0,0,0])
        #nutbolt(channel_ang=45);
    translate([-z-2.5,z*2.5+.5,z*1.3]) rotate([0,0,0])
        #nutbolt(channel_ang=135);
    translate([-z*.8, z*.5,z*1.23]) rotate([0,0,0])
        #nutbolt(channel_ang=180);
    translate([z*.8, z*.5,z*1.23]) rotate([0,0,0])
        #nutbolt(channel_ang=0);
    }
}
////-----------------------------////
//// *** air valve section  **** ////
//// ____________________________////

flapquant=4;
openingside=airflow/flapquant;
flapthick = 5;
buttonht = 4;
gap = 1.8; // between walls

flap = [[0,0], [flapthick,openingside], [flapthick,0], [0,-openingside]];

module pie(arc=90, center=90, rad=11, height=3){
    rotate([0,0,center-arc/2])
     difference(){
        children();
        translate([0,-rad, 0])
            cube([rad*2,rad*2,rad*2], center=true);
        rotate([0,0,arc])
        translate([0,rad, 0])
            cube([rad*2,rad*2,rad*2], center=true);
    }
}

module degreed(sect=90, mks=60, size=15){
    for (i=[0:sect/mks:sect-1]){
        translate([cos(i)*size, sin(i)*size, 3])
            color([.9, i/sect*2+.5,0,1])
                cylinder(r=sect/mks/4, h=6, $fn=12, center=true);
    }
}

module one_love(scaler=1){
    // one flap with key holes
    difference(){
        translate([-flapthick/2, 0, 0])
            linear_extrude(height=airflow){
                polygon(points=flap);
            }
    translate([0,0, airflow/2]) rotate([0,0,-10.1])
        scale([scaler,scaler,1]){
            cube([flapthick/2.8, openingside/1.5, airflow+.1], center=true);
        cylinder(r=1.65, h=airflow+.1, $fn=16, center=true);
        }
    }
}

module carabas(wheelrad=openingside/2, leverscale=1){
    // its the place for louvers
    wheel = max(wheelrad, 3);
    translate([0,0,-gap/2- buttonht/2])
        cylinder(r=wheel+.1, h= gap/2, $fn=24, center=false);
    difference(){
        cylinder(r1=wheel, r2=wheel-3, h=buttonht, $fn=196, center=true);
        scale([1.07,1.07,1])
            one_love(scaler=0.85);
        cylinder(r=1.7, h=4.1, $fn=16, center=true);
    }
    translate([-wheel+(openingside/2+1.5)/4, 0, -buttonht/2 - gap/2])
        lever(lvrad= openingside/2 +1.5, lvthk=gap/2, lvscale=leverscale);
}

module lever(lvrad=openingside/2 + 1.5, lvthk=gap/2, lvscale=1){
    difference(){
        union(){
            hull(){
                cylinder(r=(lvrad + 1.5)/4, h=lvthk, center=false, $fn=16);
                translate([0,9/lvscale,0])
                    cylinder(r=(lvrad + 1.5)/4, h=lvthk, center=false, $fn=16);
            }
            translate([0,9/lvscale,0])
                cylinder(r=2, h=lvthk*2 + 0.25, center=false, $fn=16);
        }
        if (lvscale < 1.001){
            translate([0,9/lvscale,-0.05])
                cylinder(r=1.65, h=lvthk*2 + 0.25 + 0.1, center=false, $fn=6);
        }
    }
}

module louvers(){
    // the flaps- working well standing up
    for (i=[0:flapquant-2]){
        translate([i*openingside, 0, 0]) rotate([0,0,75])
        one_love();
        translate([i*(openingside+.5)+5,-openingside*2.8 ,buttonht/2+gap/2]){
            carabas();
            //translate([0, 0, -buttonht/2 - gap/2])
            //    lever();
           mirror([0,1,0]) //{
            translate([-openingside*0.4, -openingside*1.8, 0])
                carabas();
           // translate([0, openingside*1.2, - buttonht/2- gap/2])
           //     lever();}
        }
    }
    //translate([airflow/2-openingside,openingside,airflow/2]) rotate([90,0,0])
     //   #circle(r=30, $fn=128, center=true);
}

module side_plate(sidethick=2, insider=1, scalecut=1.07){
    // laying on its... side
    difference(){
    translate([airflow - openingside*(flapquant-1), 0, buttonht/4])
        union(){
        cube([airflow, openingside*2 + 1, buttonht/2], center=true);
            for (i=[1,-1]){
                translate([i * (airflow/2+sidethick/2), 0,0]) rotate([0,-i*90,0])
                notcher();
            }
        }

        if (insider==1){
            echo("flapquant =",flapquant);
            for (i=[0:flapquant-2]){
                echo("i*openingside = ",i*openingside);
                translate([i*openingside*1.06, 0, buttonht/2+0.05]){
                    scale([scalecut,scalecut,scalecut])
                       rotate([0,0,-81])
                       carabas(leverscale=scalecut);
                    translate([0,0,-buttonht/2])
                    pie(arc=109, center=95, rad=13.6, height=4){
                       rotate_extrude(convexity=10, $fn=36){
                       translate([11/scalecut, 0, 0])
                          square([4.2,2.5], center=true);
                       }
                    }
                }
            }
        }
    }
}

module notcher(cd=2.2, cz=6, clong=1){
    difference(){
        cube([cd, openingside*2, cz], center=true);
        translate([0,0,-clong/2-0.05])
            cube([cd+0.05, openingside*2-((cz-clong)*2), cz-clong], center=true);
    }
}

module end_plate(sidethick=2.2, ridge=1, cc=buttonht/2+0.2){
    xlen = airflow+sidethick*4+gap*4+ridge*2;
    translate([0,0,(sidethick+ridge)/2])
    difference(){
        cube([xlen, openingside*2 + 1, sidethick+ridge], center=true);
        translate([0,openingside/3, sidethick/2])
            cube([airflow+sidethick*4+gap*2, openingside/2-1, ridge+0.1], center=true);
        translate([0,-openingside/3, sidethick/2])
            cube([airflow+sidethick*4+gap*2, openingside/2-1, ridge+0.1], center=true);
        for (i=[1,-1], j=[cc, cc*3.5]){
        translate([i*(xlen/2-j),0, 0])
            scale([1.05,1.05,1.05])
                notcher(cd=cc, cz=6.75, clong=ridge);
        }
    }
}

module rackpush(camsize=openingside*2, travelspace=openingside+2.5, curv=2){
    difference(){
        union(){
		cube([100,10,10], center=true);
        translate([airflow / 2, (camsize - gap * 3.1) / 2,0])
            minkowski(){
                cube([camsize + airflow - travelspace - curv, openingside * 2 - gap*2-curv*2, gap-.1], center=true);
                cylinder(r=curv, $fn=20, center=true);
            }
            for (i=[0:flapquant-2]){
                translate([i*openingside*1.06+camsize+gap, openingside*2 - gap*4, -3.5/2])
                    cylinder(r=2, h = 3.5, $fn=20, center=true);
            }
        }
        for (i=[0:flapquant-2]){
            translate([i*openingside*1.06+camsize+gap, openingside*2-gap*4, (gap-.1)/2])
                cylinder(r=0.8, h = 10, $fn=14, center=true);
        }
		translate([openingside/2, openingside-curv,0])
			cylinder(r=openingside*1.5/2, h=15, center=true, $fn=80);
    }
}

module plate_air_parts(){
    // for printing the parts
    translate([33,52,0]) rotate([0,0,0])
        end_plate();
    mirror([ 1, 0, 0 ]) {
    translate([33,22,0]) rotate([0,0,0])
         end_plate(); }

    translate([23.5,21,2]) rotate([180,0,0])   side_plate();
    mirror([ 1, 0, 0 ]) {
    translate([23.5,52,2]) rotate([180,0,0])   side_plate(); }
    translate([-56,-12,0]) rotate([0,0,0]){
        side_plate(insider=0);
        mirror([ 1, 0, 0 ]) {
        translate([-113,-29,0]) rotate([0,0,90])
            side_plate(insider=0); }
    }
}

// collection of parts for the new picker idea

airflow = 57;
sleeveout = airflow+1;

// [fullOD, shaftD, thickness, turning_hubD]
hubbearing = [22,8,7,13];
travelbearing = [6,3,2.5,5];
travelwheel = 60;
travelpeg = travelwheel - travelbearing[1];

fat     = 0.3;  // add-on to make walls cut out enough space
hb      = 12.7 + fat; // height of bar cross-section
wthk    = 1.5 + fat;  // thickness of walls
flrthk  = 1.6 + fat;  // thickness of floor (that walls extend from)
inside  = 6.9 - fat;  // between walls, across floor (subtracting 2*.5*fat)
c_bar = [[0,0], [0,hb], [wthk, hb], [wthk, flrthk], [wthk+inside, flrthk], [wthk+inside, hb], [wthk+inside+wthk, hb], [wthk+inside+wthk, 0]];

//#shaft(travelbearing);
//#cbar(barH=100);
//#can_sleeve();
//translate([50,50,0])
//    for (i=[0:3:360]){
//        nutbolt(nut_position=20*i/360, channel_ang=i);
//    }
//bigwheel_part();
// bartest();

// ** the can traveler by itself ***
//rotate([0,0,180]) translate([0, -56, +25.9])
    //upndown();

//motorcut();
//cbar();

rackpush();

// ** the main picker body **
//cbracket();

// ** the valve parts **
//louvers();

//plate_air_parts();

// for cutting out shaft and hub-turning space
module shaft(bearing, xtraH=0, hubclearance=0.5){
    height=bearing[2] + xtraH;
    translate([0,0,-height/2-hubclearance/2])
        cylinder(r=bearing[3]/2, h=hubclearance, center=true, $fn=28);
    translate([0,0,0])
        cylinder(r=bearing[1]/2, h=height, center=true, $fn=24);
    translate([0,0,height/2+hubclearance/2])
        cylinder(r=bearing[3]/2, h=hubclearance, center=true, $fn=28);
    echo("shaft of bearing = ", bearing, "is top-to-bottom = ", hubclearance*2 + height);
}

// alluminum c-channel, positive or negative
module cbar(outline=c_bar, barH=50){
    midbar = outline[7][0] / 2;
    echo("midbar read as: ",midbar);
    translate([-midbar,0,0])
    linear_extrude(center=true, height=barH, convexity=10, slices=2)
        polygon(points=outline);
}

// intended as positive model, could add scale or thickness
module can_sleeve (emptyness=airflow, thickness=sleeveout-airflow-0.2, sleeveH=25){
    translate([0,0,-sleeveH/2])
        rotate_extrude($fn=196)
            translate([(emptyness+thickness) / 2, 0, 0])
                polygon(points=[[0,0], [0,sleeveH], [thickness,sleeveH], [thickness,0]]);
}

// negative model with channel for captured nut insertion
module nutbolt(hexhead=6.65,
                shaftD=3.1,
                shaftlen=20,
                nut_position=17,
                nut_thick=2.33,
                channel_len=30,
                channel_ang=0,){
    color( .5, .9, .9 )
    translate([0,0,-shaftlen/2]){  //center it by shaftlen
        //shaft
        cylinder(r=shaftD/2, h=shaftlen, center=false, $fn=18);
        //head
        #translate([0,0,shaftlen-hexhead/2])
        cylinder(r=hexhead/2, h=hexhead/2, center=false, $fn=6);
        //nut + channel
        translate([0,0,shaftlen-nut_position])
        hull(){
        rotate([0,0,channel_ang])
            cylinder(r=hexhead/2+.1, h=nut_thick+.1, center=false, $fn=6);
        translate([cos(channel_ang)*channel_len,
                    sin(channel_ang)*channel_len, 0])
            rotate([0,0,channel_ang])
                cylinder(r=hexhead/2+.2, h=nut_thick+.1, center=false, $fn=6);
        }
    }
}

module motorhub(flat_to_flat=4.76, diameter=7.4, height=5.57, baseD=9, baseH=1.0){
    cutrad = (diameter - flat_to_flat)/2;
    cutcenter = flat_to_flat/2 + cutrad;
    cylinder(r=baseD/2, h=baseH+0.1, center=false, $fn=36);
    cylinder(r=0.8, h=baseH+5*height+.1, center=true, $fn=6);
    translate([0,0,baseH])
        difference(){
            cylinder(r=diameter/2, h=height+baseH, center=false, $fn=24);
            for (i=[cutcenter+0.05, -cutcenter-0.05]){
                translate([0,i,(height+baseH)/2])
                    cube([diameter+0.1, cutrad+0.1, height+.1], center=true);
            }

        }
}

module bigwheel_part(od=travelwheel, thk=4, hub=12, hubthk=4, holes=6, lever=5){
    overall_thk = thk+hubthk;
    echo("overall bigwheel thickness is : ", overall_thk);
    difference(){
        union(){
            cylinder(r=od/2, h=thk, $fn=196);
            translate([0,0,4])
            cylinder(r=hub/2, h=hubthk, $fn=64);
        }
        translate([0,0,overall_thk+0.05]) rotate([180,0,0])
            motorhub();
        for (i=[0 : 360/holes : 360-(360/holes)*.5]){
            translate([od/3.14*cos(i), od/3.14*sin(i), hubthk/2])
                cylinder(r=od*.5/(holes-1), h=hubthk+.1, center=true, $fn=42);
        }
        translate([0,od/2-lever,-9]) rotate([0,0,0])
            nutbolt();
        translate([0,-od/2+lever,-9]) rotate([0,0,0])
            nutbolt();
    }
}

module ring(ID, OD, ht){
    difference(){
        cylinder(r=OD/2, h=ht, center=true, $fn=96);
        cylinder(r=ID/2, h=ht+.1, center=true, $fn=96);
    }
}

// for LMB8MM
module bearingcut(D=15.1/2, dring=14.41/2, drod=8.9/2, dziptie=[19,3.3],){
    rotate_extrude(center=true, convexity=10, $fn=36){
        polygon(points=[[0,-2], [D,0],
                        [D,3.3], [dring,3.3],
                        [dring,4.55], [D,4.55],
                        [D,19.35], [dring,19.35],
                        [dring,20.8], [D,20.8],
                        [D, 24.01], [0,26.01]]);
    }
    // zip tie rings
    for (i=[(3.3+4.55)/2, (19.35+20.8)/2]){
        translate([0,0,i])
            ring(dziptie[0], dziptie[0]+dziptie[1], 5);
    }
    // rod upon which it travels
    translate([0,0,12])
        cylinder(r=drod, h=90, $fn=18, center=true);
}

module bigwheel_cutout(od=travelwheel+3, thk=10){
    cylinder(r=od/2, h=thk, $fn=128);
}

module bartest(ht=10){
    difference(){
    minkowski(){
        cube([20,20,10], center=true);
        cylinder(r=4, h=.1, center=true, $fn=24);
    }
    translate([-7,-9,0])
        #cbar(barH=30);
    translate([17,0,0]) rotate([0,0,90])
        #cbar(barH=30);
    translate([0,10.5,0]) rotate([90,0,0])
        #shaft(hubbearing);
    }
}

module upndown(ht=travelwheel){
    difference(){
    cube([travelwheel, travelwheel/2, ht], center=true);
    // lift rail
    translate([0, travelwheel/2-hb, 0])
        cube([travelwheel+.1, hb+.1, c_bar[6][0]+.1], center=true);
    // side rails
    translate([-travelwheel/2+.5 ,3.25, 0]) rotate([0,0,-0])
        cube([hb+.5, c_bar[6][0]+1, travelwheel+.1], center=true);
    translate([travelwheel/2-.5 ,3.25, 0]) rotate([0,0,0])
        cube([hb+.5, c_bar[6][0]+1, travelwheel+.1], center=true);

    // cylinder space
    translate([0, -travelwheel/2, 0])
        cylinder(r = (sleeveout+.5)/2, h=ht+.1, $fn=196, center=true);
    // nuts
    translate([0,0,ht/4]) rotate([90,0,0])
        #nutbolt(channel_ang=90);
    translate([0,0,-ht/4]) rotate([90,0,0])
        #nutbolt(channel_ang=-90);
    }
    // underside printing supports for lift rail
    for (i=[0:5:travelwheel-1]){
        translate([i - travelwheel/2+2.5, travelwheel/2-hb*1.333, 0])
            cube([.5, hb*.37, c_bar[6][0]+.1], center=true);
    }
}

module upndown_cutout(ht=travelwheel){
    translate([0,-4.5,0])
    cube([travelwheel+1, travelwheel/2+9.5, ht+2], center=true);
    // lift rail
    //translate([0, travelwheel/2+hb, 0])
    //    cube([travelwheel+.1, hb+.1, c_bar[6][0]+.1], center=true);
    // side rails
    translate([-travelwheel/2+hb/2+.2,-5, 0]) rotate([0,0,90])
        cbar(barH=70);
    translate([travelwheel/2-hb/2-.2,-5, 0]) rotate([0,0,-90])
        cbar(barH=70);
    // cylinder of suckage
    translate([0, -travelwheel/2 -9.5, 0])
        cylinder(r = (sleeveout+2)/2, h=ht+2, $fn=196, center=true);

}

module motorcut(x=23,y=22,z=37,tab=[6,4,5],tabpos=7,curverad=5, shaftpos=[0,11,16], canheight=28){
    tiptop = canheight + z + tab[2] - curverad;
    // top-motorhousing
    translate([0,y/2, tiptop - canheight])
        cylinder(r=x/2, h=canheight, center=false, $fn=36);
    // gearbox housing
    translate([-(x-curverad*2)/2, 0, curverad+tab[2]])
        minkowski(){
            cube([x-curverad*2,y,z-curverad*2], center=false);
            rotate([90,0,0])
                cylinder(r=curverad, h=.1, center=false, $fn=64);
        }
    // tab thingy for motor attachment
    translate([0,tabpos+tab[1]/2, tab[2]/2]){
        cube(tab, center=true);
        // cuts hole for bolting tab
        rotate([90,0,0])
            cylinder(r=3.26/2, h=50, center=true, $fn=12);
    }
    // driven hub stub and slide-in track
    translate(shaftpos)
        rotate([90,0,0])
            hull(){
            cylinder(r=9.14/2, h=y+4, center=true, $fn=18);
            translate([0,z-shaftpos[0], 0])
                cylinder(r=9.14/2, h=y+4, center=true, $fn=18);
            }
    // cuts shaft for holes that penetrate housing
    for (i=[1,-1]){
    translate([17.75/2 * i, 0, 36])
        rotate([90,0,0])
            cylinder(r=3.26/2, h=50, center=true, $fn=12);
    }
    // add on the driven wheel
    translate(shaftpos)
        rotate([90, 0,0]) translate([0,0,-y]){
            bigwheel_cutout();
            // and its connection hub
            translate([0,0,+3])
            hull(){
                cylinder(r=8, h=15, $fn=16, center=false);
                translate([0,z-shaftpos[0], 0])
                cylinder(r=8, h=15, $fn=16, center=false);
            }
        }
    // make a cut-out for the traveling part
    rotate([0,0,180]) translate(shaftpos) translate([0,-59,0])
    upndown_cutout();
}

// carve the big thing out of a block
module cbracket(z=travelwheel/2, bs=1.5){
    difference(){
        translate([-travelwheel/2, 0, -4])
        minkowski(){
            cube([travelwheel, travelwheel*1.2, travelwheel-17], center=false);
            cylinder(r=8, h=1, $fn=16);
        }
    motorcut();
    translate([-travelwheel/2-bs, -bs, 4])
    bearingcut();
    translate([travelwheel/2+bs,-bs, 4])
    bearingcut();
    translate([z+2.5,z*2.5+.5,z*1.3]) rotate([0,0,0])
        #nutbolt(channel_ang=45);
    translate([-z-2.5,z*2.5+.5,z*1.3]) rotate([0,0,0])
        #nutbolt(channel_ang=135);
    translate([-z*.8, z*.5,z*1.23]) rotate([0,0,0])
        #nutbolt(channel_ang=180);
    translate([z*.8, z*.5,z*1.23]) rotate([0,0,0])
        #nutbolt(channel_ang=0);
    }
}
////-----------------------------////
//// *** air valve section  **** ////
//// ____________________________////

flapquant=4;
openingside=airflow/flapquant;
flapthick = 5;
buttonht = 4;
gap = 1.8; // between walls

flap = [[0,0], [flapthick,openingside], [flapthick,0], [0,-openingside]];

module pie(arc=90, center=90, rad=11, height=3){
    rotate([0,0,center-arc/2])
     difference(){
        children();
        translate([0,-rad, 0])
            cube([rad*2,rad*2,rad*2], center=true);
        rotate([0,0,arc])
        translate([0,rad, 0])
            cube([rad*2,rad*2,rad*2], center=true);
    }
}

module degreed(sect=90, mks=60, size=15){
    for (i=[0:sect/mks:sect-1]){
        translate([cos(i)*size, sin(i)*size, 3])
            color([.9, i/sect*2+.5,0,1])
                cylinder(r=sect/mks/4, h=6, $fn=12, center=true);
    }
}

module one_love(scaler=1){
    // one flap with key holes
    difference(){
        translate([-flapthick/2, 0, 0])
            linear_extrude(height=airflow){
                polygon(points=flap);
            }
    translate([0,0, airflow/2]) rotate([0,0,-10.1])
        scale([scaler,scaler,1]){
            cube([flapthick/2.8, openingside/1.5, airflow+.1], center=true);
        cylinder(r=1.65, h=airflow+.1, $fn=16, center=true);
        }
    }
}

module carabas(wheelrad=openingside/2, leverscale=1){
    // its the place for louvers
    wheel = max(wheelrad, 3);
    translate([0,0,-gap/2- buttonht/2])
        cylinder(r=wheel+.1, h= gap/2, $fn=24, center=false);
    difference(){
        cylinder(r1=wheel, r2=wheel-3, h=buttonht, $fn=196, center=true);
        scale([1.07,1.07,1])
            one_love(scaler=0.85);
        cylinder(r=1.7, h=4.1, $fn=16, center=true);
    }
    translate([-wheel+(openingside/2+1.5)/4, 0, -buttonht/2 - gap/2])
        lever(lvrad= openingside/2 +1.5, lvthk=gap/2, lvscale=leverscale);
}

module lever(lvrad=openingside/2 + 1.5, lvthk=gap/2, lvscale=1){
    difference(){
        union(){
            hull(){
                cylinder(r=(lvrad + 1.5)/4, h=lvthk, center=false, $fn=16);
                translate([0,9/lvscale,0])
                    cylinder(r=(lvrad + 1.5)/4, h=lvthk, center=false, $fn=16);
            }
            translate([0,9/lvscale,0])
                cylinder(r=2, h=lvthk*2 + 0.25, center=false, $fn=16);
        }
        if (lvscale < 1.001){
            translate([0,9/lvscale,-0.05])
                cylinder(r=1.65, h=lvthk*2 + 0.25 + 0.1, center=false, $fn=6);
        }
    }
}

module louvers(){
    // the flaps- working well standing up
    for (i=[0:flapquant-2]){
        translate([i*openingside, 0, 0]) rotate([0,0,75])
        one_love();
        translate([i*(openingside+.5)+5,-openingside*2.8 ,buttonht/2+gap/2]){
            carabas();
            //translate([0, 0, -buttonht/2 - gap/2])
            //    lever();
           mirror([0,1,0]) //{
            translate([-openingside*0.4, -openingside*1.8, 0])
                carabas();
           // translate([0, openingside*1.2, - buttonht/2- gap/2])
           //     lever();}
        }
    }
    //translate([airflow/2-openingside,openingside,airflow/2]) rotate([90,0,0])
     //   #circle(r=30, $fn=128, center=true);
}

module side_plate(sidethick=2, insider=1, scalecut=1.07){
    // laying on its... side
    difference(){
    translate([airflow - openingside*(flapquant-1), 0, buttonht/4])
        union(){
        cube([airflow, openingside*2 + 1, buttonht/2], center=true);
            for (i=[1,-1]){
                translate([i * (airflow/2+sidethick/2), 0,0]) rotate([0,-i*90,0])
                notcher();
            }
        }

        if (insider==1){
            echo("flapquant =",flapquant);
            for (i=[0:flapquant-2]){
                echo("i*openingside = ",i*openingside);
                translate([i*openingside*1.06, 0, buttonht/2+0.05]){
                    scale([scalecut,scalecut,scalecut])
                       rotate([0,0,-81])
                       carabas(leverscale=scalecut);
                    translate([0,0,-buttonht/2])
                    pie(arc=109, center=95, rad=13.6, height=4){
                       rotate_extrude(convexity=10, $fn=36){
                       translate([11/scalecut, 0, 0])
                          square([4.2,2.5], center=true);
                       }
                    }
                }
            }
        }
    }
}

module notcher(cd=2.2, cz=6, clong=1){
    difference(){
        cube([cd, openingside*2, cz], center=true);
        translate([0,0,-clong/2-0.05])
            cube([cd+0.05, openingside*2-((cz-clong)*2), cz-clong], center=true);
    }
}

module end_plate(sidethick=2.2, ridge=1, cc=buttonht/2+0.2){
    xlen = airflow+sidethick*4+gap*4+ridge*2;
    translate([0,0,(sidethick+ridge)/2])
    difference(){
        cube([xlen, openingside*2 + 1, sidethick+ridge], center=true);
        translate([0,openingside/3, sidethick/2])
            cube([airflow+sidethick*4+gap*2, openingside/2-1, ridge+0.1], center=true);
        translate([0,-openingside/3, sidethick/2])
            cube([airflow+sidethick*4+gap*2, openingside/2-1, ridge+0.1], center=true);
        for (i=[1,-1], j=[cc, cc*3.5]){
        translate([i*(xlen/2-j),0, 0])
            scale([1.05,1.05,1.05])
                notcher(cd=cc, cz=6.75, clong=ridge);
        }
    }
}

module rackpush(camsize=openingside*2, travelspace=openingside+2.5, curv=2){
    difference(){
        union(){
        translate([airflow/2, (openingside*2-gap*3.1)/2,0])
            minkowski(){

                cube([camsize + airflow - travelspace-curv, openingside*2-gap*2-curv*2, gap-.1], center=true);
                cylinder(r=curv, $fn=20, center=true);
            }
            for (i=[0:flapquant-2]){
                translate([i*openingside*1.06+camsize+gap, openingside*2-gap*3, -3.5/2])
                    cylinder(r=2, h = 3.5, $fn=14, center=true);
            }
        }
        for (i=[0:flapquant-2]){
            translate([i*openingside*1.06+camsize+gap, openingside*2-gap*4, (gap-.1)/2])
                cylinder(r=0.8, h = 3.5, $fn=14, center=true);
        }
    }
}

module plate_air_parts(){
    // for printing the parts
    translate([33,52,0]) rotate([0,0,0])
        end_plate();
    mirror([ 1, 0, 0 ]) {
    translate([33,22,0]) rotate([0,0,0])
         end_plate(); }

    translate([23.5,21,2]) rotate([180,0,0])   side_plate();
    mirror([ 1, 0, 0 ]) {
    translate([23.5,52,2]) rotate([180,0,0])   side_plate(); }
    translate([-56,-12,0]) rotate([0,0,0]){
        side_plate(insider=0);
        mirror([ 1, 0, 0 ]) {
        translate([-113,-29,0]) rotate([0,0,90])
            side_plate(insider=0); }
    }
}


[3d] MeterMonitor increase lid corner tolerence

// LCD type
lt = 0; // [0: 0.56inch, 1: 0.36inch]

wall = 1.3; // interior walls
wall_o = 1.9; // outer walls
wall_t = 1.45; // base thickness

/* Hidden */
lid_h = wall_t;

lcd_w = [67, 45.50][lt];
lcd_d = [28, 23.00][lt];
lcd_s_w = [60, 40.35][lt]; // width between screws
lcd_s_d = [22, 17.76][lt];
lcd_s_h = [8.5, 7.0][lt];
lcd_s_dia = [3.1, 3.1][lt];
lcd_a_w = [50, 30][lt]; // width of actual 7-segment area
lcd_a_d = [17.5, 14][lt];
lcd_ex_w = [0, 2][lt];
lcd_ex_d = [2, 4][lt];
lcd_window_offset = [2, (5.43-10.07)/2][lt];
w_extra = [2, 6][lt];
d_extra = [0, 0][lt];

oa_w = 2*lcd_w + 2*lcd_ex_w + w_extra;
oa_d = 3*lcd_d + 3*lcd_ex_d + d_extra;
oa_h = 15;
pad_right = max(2*lcd_window_offset, 0); // padding is asymetrical so not included in oa_w

main();
translate([-oa_w/2, oa_d/2+wall_o+5, 0]) lid();
//lid_stand();

module main() {
  difference() {
    union() {
      translate([-oa_w/2-wall_o, -oa_d/2-wall_o, 0])
        cube_bchamfer([oa_w+pad_right+2*wall_o, oa_d+2*wall_o, oa_h+wall_t+lid_h+wall_t/2], r=5, bottom=1);
    } // union

    // main cutout
    translate([-oa_w/2, -oa_d/2, wall_t])
      cube_bchamfer([oa_w+pad_right, oa_d, oa_h+e], r=5-wall, bottom=1, top=lid_h);
    // lid cutout
    translate([-oa_w/2,-oa_d/2-wall_o-e,wall_t+oa_h])
      cube_fillet([oa_w+pad_right, oa_d+wall_o+e, lid_h+wall_t+e],
        vertical=[2,2,0,0], top=[lid_h,lid_h,0,lid_h], $fn=4);

    // LCD holes
    lcd_places() lcd_mount_n();

    // USB power hole
    wemos_place() translate([-5.9, -35.2/2-1.2-wall_o-e, 2.3+2-0.5])
      cube_fillet([13, 10, 6+1.5], top=[0,1,0,1]);

    //branding();
  } // diff

  lcd_places() lcd_mount_p();
  wemos_place() wemos_mount(2);
}

module lid() {
  ww = oa_w+pad_right+0.2;
  dd = oa_d+wall_o-0.2;
  difference() {
    cube_fillet([ww, dd, lid_h], bottom=[0.5, 0.5, 0, 0.5], vertical=[4, 4 ,1.5, 1.5]);
    // vent holes
    //translate([15, dd/2, 0])
    //  for (X=[0:3])
    //    translate([X*(ww-30)/3, 0, -e]) rotate(90) cylcyl(d*0.7, 2, lid_h+2*e, $fn=12);
  }
  // lock bump
  //translate([wall_o+wall_t+0.5, dd/2-4*wall, lid_h-e]) cube_fillet([2*wall, 8*wall, 0.6], top=[0.6,0,0.6,0]);
  translate([ww/4, wall_o+wall_t+0.5, lid_h-e])
    cube_fillet([ww/2, 2*wall, 0.6], top=[0, 0.6, 0, 0.6]);
}

module lcd_places() {
  // center two
  translate([lcd_w/2+lcd_ex_w,0,0])
    children();
  translate([-lcd_w/2-lcd_ex_w,0,0])
    children();
  // top/bottom
  mirror2([0,1,0]) translate([-lcd_w/2-lcd_ex_w,lcd_d+lcd_ex_d,0])
    children();
}

module lcd_mount_p() {
  mirror2([1,0,0]) mirror2([0,1,0]) translate([lcd_s_w/2, lcd_s_d/2, wall_t]) {
    difference() {
      cylinder(lcd_s_h, d=lcd_s_dia+2*wall, $fn=16);
      translate([0,0,-e]) cylinder(lcd_s_h+2*e, d=lcd_s_dia, $fn=16);
    }
  }
}

module lcd_mount_n() {
  translate([-lcd_a_w/2+lcd_window_offset-wall_t, -lcd_a_d/2-wall_t, -e])
    cube_bchamfer([lcd_a_w+2*wall_t, lcd_a_d+2*wall_t, wall_t+2*e], r=3, top=wall_t, $fn=12);
}

module wemos_place() {
  translate([oa_w/2+pad_right+wall-20, -lcd_d-lcd_ex_d, wall_t]) rotate(90) children();
}

module wemos_mount(extra_h) {
  we_w=25.9;
  we_d=35.2;
  we_h=6;
  we_rad=2.4;
  we_wall=1.2;

  difference() {
    translate([-we_w/2-we_wall, -we_d/2-we_wall, 0])
      cube_fillet([we_w+2*we_wall, we_d+2*we_wall, we_h+extra_h],
        vertical=[we_rad+we_wall*0.5855, we_rad+we_wall*0.5855, 0, 0]);

    translate([0,0,extra_h]) {
      // Big hole
      translate([-we_w/2, -we_d/2, 3])
        cube_fillet([we_w, we_d, we_h+2*e], vertical=[we_rad, we_rad, 0, 0]);
      // USB jack
      translate([-5.9, -we_d/2-we_wall-e, 2.3])
        cube([13, 10, we_h]);
      // Reset button
      translate([we_w/2-e, -we_d/2+1.8, 3.5])
        cube([we_wall+2*e, 5, we_h]);
      // Bottom small hole
      translate([-21/2, -31/2, -e])
        cube([21, 31, we_h+2*e]);
      // wifi antenna
      translate([-18/2, we_d/2-(we_d-31)/2-e, 3-1.3])
        cube([18, (we_d-31)/2+e, 1.3+e]);
    }
  } // diff

  // Grab notches
  translate([0,0,extra_h]) {
    translate([we_w/2,5/2,we_h-0.8/2]) rotate([90]) cylinder(5, d=0.8, $fn=4);
    translate([-we_w/2,5/2,we_h-0.8/2]) rotate([90]) cylinder(5, d=0.8, $fn=4);
  }
}

module lid_stand()
{
  ls_weight_dia = 19.1;
  ls_weight_h = 12;

  ls_w = 75;
  ls_d = ls_weight_dia + 2 * wall;
  ls_h = ls_weight_h + 5;

  ls_mag_w = 7;
  ls_mag_d = 12.7;
  ls_mag_h = 2.3;

  difference() {
    translate([-ls_w/2, -ls_d/2, 0])
      cube_fillet([ls_w, ls_d, ls_h], top=[5, ls_h/2,0, ls_h/2]);

    // weight hole
    translate([0, 0, -e])
      cylinder(ls_weight_h, d=ls_weight_dia, $fn=24);
    // magnet holes
    translate([-ls_w/2+wall, -ls_mag_d/2, -e]) cube([ls_mag_w, ls_mag_d, ls_mag_h]);
    translate([-ls_weight_dia/2-ls_mag_w-wall, -ls_mag_d/2, -e]) cube([ls_mag_w, ls_mag_d, ls_mag_h]);
    translate([ls_w/2-ls_mag_w-wall, -ls_mag_d/2, -e]) cube([ls_mag_w, ls_mag_d, ls_mag_h]);
    translate([ls_weight_dia/2+wall, -ls_mag_d/2, -e]) cube([ls_mag_w, ls_mag_d, ls_mag_h]);
  }  // diff
}

module branding() {
  translate([lcd_w/2-3,lcd_d+lcd_ex_d,-e]) mirror([1,0,0]) linear_extrude(0.24+e)
    text("HeaterMeter", halign="center", valign="center", font="Impact",
      spacing=1.3, size=7);
}

/********************************** LIBRARY CODE BELOW HERE **********************/

e = 0.01;

module cube_bchamfer(dim, r, top=0, bottom=0, $fn=$fn) {
  // bottom beaded area
  if (bottom != 0) hull(){
    translate([r,r,0]) cylinder(bottom+e, r1=max(0, r-bottom), r2=r, $fn=$fn);
    translate([dim[0]-r,r,0]) cylinder(bottom+e, r1=max(0, r-bottom), r2=r, $fn=$fn);
    translate([r,dim[1]-r,0]) cylinder(bottom+e, r1=max(0, r-bottom), r2=r, $fn=$fn);
    translate([dim[0]-r,dim[1]-r,0]) cylinder(bottom+e, r1=max(0, 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-e]) hull(){
    translate([r,r,0]) cylinder(top+e, r2=max(0, r-top), r1=r, $fn=$fn);
    translate([dim[0]-r,r,0]) cylinder(top+e, r2=max(0, r-top), r1=r, $fn=$fn);
    translate([r,dim[1]-r,0]) cylinder(top+e, r2=max(0, r-top), r1=r, $fn=$fn);
    translate([dim[0]-r,dim[1]-r,0]) cylinder(top+e, r2=max(0, r-top), r1=r, $fn=$fn);
  }
}

module mirror2(dim) {
  // Create both item and mirror of item
  children();
  mirror(dim) children();
}

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];

    fn_V = $fn[0] == undef ? $fn : $fn[0];
    fn_T = $fn[1] == undef ? $fn : $fn[1];
    fn_B = $fn[2] == undef ? $fn : $fn[2];

    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_V);
        } else {
            rotate([0, 0, 90*i]) translate([size[1-j[i]]/2, size[j[i]]/2, 0]) fillet(vertical[i], size[2], fn_V);
        }
        rotate([90*i, -90, 0]) translate([size[2]/2, size[j[i]]/2, 0 ]) fillet(top[i], size[1-j[i]], fn_T);
        rotate([90*(4-i), 90, 0]) translate([size[2]/2, size[j[i]]/2, 0]) fillet(bottom[i], size[1-j[i]], fn_B);

    }
}

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]);

// LCD type
lt = 0; // [0: 0.56inch, 1: 0.36inch]

wall = 1.3; // interior walls
wall_o = 1.9; // outer walls
wall_t = 1.45; // base thickness

/* Hidden */
lid_h = wall_t;

lcd_w = [67, 45.50][lt];
lcd_d = [28, 23.00][lt];
lcd_s_w = [60, 40.35][lt]; // width between screws
lcd_s_d = [22, 17.76][lt];
lcd_s_h = [8.5, 7.0][lt];
lcd_s_dia = [3.1, 3.1][lt];
lcd_a_w = [50, 30][lt]; // width of actual 7-segment area
lcd_a_d = [17.5, 14][lt];
lcd_ex_w = [0, 2][lt];
lcd_ex_d = [2, 4][lt];
lcd_window_offset = [2, (5.43-10.07)/2][lt];
w_extra = [2, 6][lt];
d_extra = [0, 0][lt];

oa_w = 2*lcd_w + 2*lcd_ex_w + w_extra;
oa_d = 3*lcd_d + 3*lcd_ex_d + d_extra;
oa_h = 15;
pad_right = max(2*lcd_window_offset, 0); // padding is asymetrical so not included in oa_w

main();
//translate([-oa_w/2, oa_d/2+wall_o+5, 0]) lid();

module main() {
  difference() {
    union() {
      translate([-oa_w/2-wall_o, -oa_d/2-wall_o, 0])
        cube_bchamfer([oa_w+pad_right+2*wall_o, oa_d+2*wall_o, oa_h+wall_t+lid_h+wall_t/2], r=5, bottom=1);
    } // union

    // main cutout
    translate([-oa_w/2, -oa_d/2, wall_t])
      cube_bchamfer([oa_w+pad_right, oa_d, oa_h+e], r=5-wall, bottom=1, top=lid_h);
    // lid cutout
    translate([-oa_w/2,-oa_d/2-wall_o-e,wall_t+oa_h])
      cube_fillet([oa_w+pad_right, oa_d+wall_o+e, lid_h+wall_t+e],
        vertical=[2,2], top=[lid_h,lid_h,0,lid_h], $fn=4);

    // LCD holes
    lcd_places() lcd_mount_n();

    // USB power hole
    wemos_place() translate([-5.9, -35.2/2-1.2-wall_o-e, 2.3+2-0.5])
      cube_fillet([13, 10, 6+1.5], top=[0,1,0,1]);

    //branding();
  } // diff

  lcd_places() lcd_mount_p();
  wemos_place() wemos_mount(2);
}

module lid() {
  ww = oa_w+pad_right+0.2;
  dd = oa_d+wall_o-0.2;
  difference() {
    cube_fillet([ww, dd, lid_h], bottom=[0.5, 0.5, 0, 0.5], vertical=[1.5, 1.5 ,1.5, 1.5]);
    // vent holes
    //translate([15, dd/2, 0])
    //  for (X=[0:3])
    //    translate([X*(ww-30)/3, 0, -e]) rotate(90) cylcyl(d*0.7, 2, lid_h+2*e, $fn=12);
  }
  // lock bump
  //translate([wall_o+wall_t+0.5, dd/2-4*wall, lid_h-e]) cube_fillet([2*wall, 8*wall, 0.6], top=[0.6,0,0.6,0]);
  translate([ww/4, wall_o+wall_t+0.5, lid_h-e]) cube_fillet([ww/2, 2*wall, 0.6], top=[0,0.6,0,0.6]);
}

module lcd_places() {
  // center two
  translate([lcd_w/2+lcd_ex_w,0,0])
    children();
  translate([-lcd_w/2-lcd_ex_w,0,0])
    children();
  // top/bottom
  mirror2([0,1,0]) translate([-lcd_w/2-lcd_ex_w,lcd_d+lcd_ex_d,0])
    children();
}

module lcd_mount_p() {
  mirror2([1,0,0]) mirror2([0,1,0]) translate([lcd_s_w/2, lcd_s_d/2, wall_t]) {
    difference() {
      cylinder(lcd_s_h, d=lcd_s_dia+2*wall, $fn=16);
      translate([0,0,-e]) cylinder(lcd_s_h+2*e, d=lcd_s_dia, $fn=16);
    }
  }
}

module lcd_mount_n() {
  translate([-lcd_a_w/2+lcd_window_offset-wall_t, -lcd_a_d/2-wall_t, -e])
    cube_bchamfer([lcd_a_w+2*wall_t, lcd_a_d+2*wall_t, wall_t+2*e], r=3, top=wall_t, $fn=12);
}

module wemos_place() {
  translate([oa_w/2+pad_right+wall-20, -lcd_d-lcd_ex_d, wall_t]) rotate(90) children();
}

module wemos_mount(extra_h) {
  we_w=25.9;
  we_d=35.2;
  we_h=6;
  we_rad=2.4;
  we_wall=1.2;

  difference() {
    translate([-we_w/2-we_wall, -we_d/2-we_wall, 0])
      cube_fillet([we_w+2*we_wall, we_d+2*we_wall, we_h+extra_h],
        vertical=[we_rad+we_wall*0.5855,we_rad+we_wall*0.5855]);

    translate([0,0,extra_h]) {
      // Big hole
      translate([-we_w/2, -we_d/2, 3])
        cube_fillet([we_w, we_d, we_h+2*e], vertical=[we_rad,we_rad]);
      // USB jack
      translate([-5.9, -we_d/2-we_wall-e, 2.3])
        cube([13, 10, we_h]);
      // Reset button
      translate([we_w/2-e, -we_d/2+1.8, 3.5])
        cube([we_wall+2*e, 5, we_h]);
      // Bottom small hole
      translate([-21/2, -31/2, -e])
        cube([21, 31, we_h+2*e]);
      // wifi antenna
      translate([-18/2, we_d/2-(we_d-31)/2-e, 3-1.3])
        cube([18, (we_d-31)/2+e, 1.3+e]);
    }
  } // diff

  // Grab notches
  translate([0,0,extra_h]) {
    translate([we_w/2,5/2,we_h-0.8/2]) rotate([90]) cylinder(5, d=0.8, $fn=4);
    translate([-we_w/2,5/2,we_h-0.8/2]) rotate([90]) cylinder(5, d=0.8, $fn=4);
  }
}

module branding() {
  translate([lcd_w/2-3,lcd_d+lcd_ex_d,-e]) mirror([1,0,0]) linear_extrude(0.24+e)
    text("HeaterMeter", halign="center", valign="center", font="Impact",
      spacing=1.3, size=7);
}

/********************************** LIBRARY CODE BELOW HERE **********************/

e = 0.01;

module cube_bchamfer(dim, r, top=0, bottom=0, $fn=$fn) {
  // bottom beaded area
  if (bottom != 0) hull(){
    translate([r,r,0]) cylinder(bottom+e, r1=max(0, r-bottom), r2=r, $fn=$fn);
    translate([dim[0]-r,r,0]) cylinder(bottom+e, r1=max(0, r-bottom), r2=r, $fn=$fn);
    translate([r,dim[1]-r,0]) cylinder(bottom+e, r1=max(0, r-bottom), r2=r, $fn=$fn);
    translate([dim[0]-r,dim[1]-r,0]) cylinder(bottom+e, r1=max(0, 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-e]) hull(){
    translate([r,r,0]) cylinder(top+e, r2=max(0, r-top), r1=r, $fn=$fn);
    translate([dim[0]-r,r,0]) cylinder(top+e, r2=max(0, r-top), r1=r, $fn=$fn);
    translate([r,dim[1]-r,0]) cylinder(top+e, r2=max(0, r-top), r1=r, $fn=$fn);
    translate([dim[0]-r,dim[1]-r,0]) cylinder(top+e, r2=max(0, r-top), r1=r, $fn=$fn);
  }
}

module mirror2(dim) {
  // Create both item and mirror of item
  children();
  mirror(dim) children();
}

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];

    fn_V = $fn[0] == undef ? $fn : $fn[0];
    fn_T = $fn[1] == undef ? $fn : $fn[1];
    fn_B = $fn[2] == undef ? $fn : $fn[2];

    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_V);
        } else {
            rotate([0, 0, 90*i]) translate([size[1-j[i]]/2, size[j[i]]/2, 0]) fillet(vertical[i], size[2], fn_V);
        }
        rotate([90*i, -90, 0]) translate([size[2]/2, size[j[i]]/2, 0 ]) fillet(top[i], size[1-j[i]], fn_T);
        rotate([90*(4-i), 90, 0]) translate([size[2]/2, size[j[i]]/2, 0]) fillet(bottom[i], size[1-j[i]], fn_B);

    }
}

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]);


shapes: add pie_slice_shape and pie_slice

module size_align(size=[10,10,10], align=[0,0,0])
{
    t=[align[0]*size[0]/2,align[1]*size[1]/2,align[2]*size[2]/2];
    /*echo(t);*/
    translate(t)
    {
        children();
    }
}

module cubea(size=[10,10,10], align=[0,0,0], extrasize=[0,0,0], extrasize_align=[0,0,0])
{
    size_align(extrasize,extrasize_align)
    {
        size_align(size,align)
        {
            cube(size+extrasize, center=true);
        }
    }
}

module cylindera(h=10, r=undef, r1=undef, r2=undef, d=undef, d1=undef, d2=undef, align=[0,0,0], extra_h=0,extra_r=undef,extra_d=undef,extra_align=[0,0,0])
{
    extra_r_=(extra_r==undef?0:extra_r);
    extra_d_=(extra_d==undef?0:extra_d);
    extra_sizexy=extra_r_*2 + extra_d_;
    size_align([extra_sizexy,extra_sizexy,extra_h],extra_align)
    {
        r_=(r==undef?0:r);
        d_=(d==undef?0:d);
        sizexy=r_*2 + d_;
        size_align([sizexy,sizexy,h],align)
        {
            cylinder(h=h+extra_h, r=r+extra_r_, r1=r1, r2=r2, d=d+extra_d_, d1=d1, d2=d2, center=true);
        }
    }
}

module fncylinder(r, r2, d, d2, h, fn, center=false, enlarge=0, fnr=0.4){
    translate(center==false?[0,0,-enlarge]:[0,0,-h/2-enlarge]) {
        if (fn==undef) {
            if (r2==undef && d2==undef) {
                cylinder(r=r?r:d?d/2:1,h=h+enlarge*2,$fn=floor(2*(r?r:d?d/2:1)*PI/fnr));
            } else {
                cylinder(r=r?r:d?d/2:1,r2=r2?r2:d2?d2/2:1,h=h+enlarge*2,$fn=floor(2*(r?r:d?d/2:1)*PI/fnr));
            }
        } else {
            if (r2==undef && d2==undef) {
                cylinder(r=r?r:d?d/2:1,h=h+enlarge*2,$fn=fn);
            } else {
                cylinder(r=r?r:d?d/2:1,r2=r2?r2:d2?d2/2:1,h=h+enlarge*2,$fn=fn);
            }
        }
    }
}

// specify segment length with fnr, $fn not needed but if desired use fn instead but if desired use fn instead
module fncylindera(
        h=10,
        r=undef,
        r1=undef,
        r2=undef,
        d=undef,
        d1=undef,
        d2=undef,
        align=[0,0,0],
        extra_h=0,
        extra_r=undef,
        extra_d=undef,
        extra_align=[0,0,0],
        fn,
        fnr=0.4,
        debug=false
        )
{
    pi=3.1415926536;

    useDia = r == undef && (r1 == undef && r2 == undef);

    r_= useDia?d/2:(r==undef?0:r);
    r1_ = useDia?((d1==undef?undef:d1)/2):r1;
    r2_ = useDia?((d2==undef?undef:d2)/2):r2;
    extra_r_ = useDia?((extra_d==undef?0:extra_d)/2):((extra_r==undef)?0:extra_d/2);

    extra_sizexy=extra_r_*2;

    size_align([extra_sizexy,extra_sizexy,extra_h],extra_align)
    {

        fn_=fn==undef?(floor(2*(r_+extra_r_)*pi/fnr)):fn;

        if(debug)
            echo(useDia, h, r_, r1_, r2_, extra_r_, align, fn_);

        sizexy=r_*2;
        size_align([sizexy,sizexy,h],align)
        {
            cylinder(h=h+extra_h, r=r_+extra_r_, r1=r1_, r2=r2_, center=true, $fn=fn_);
        }
    }
}

module pie_slice_shape(r, start_angle, end_angle) {
    R = r * sqrt(2) + 1;
    a0 = (4 * start_angle + 0 * end_angle) / 4;
    a1 = (3 * start_angle + 1 * end_angle) / 4;
    a2 = (2 * start_angle + 2 * end_angle) / 4;
    a3 = (1 * start_angle + 3 * end_angle) / 4;
    a4 = (0 * start_angle + 4 * end_angle) / 4;
    if(end_angle > start_angle)
    {
        intersection() {
            circle(r);
            polygon([
                    [0,0],
                    [R * cos(a0), R * sin(a0)],
                    [R * cos(a1), R * sin(a1)],
                    [R * cos(a2), R * sin(a2)],
                    [R * cos(a3), R * sin(a3)],
                    [R * cos(a4), R * sin(a4)],
                    [0,0]
            ]);
        }
    }
}

module pie_slice(r, start_angle, end_angle, h)
{
    linear_extrude(h)
    {
        pie_slice_shape(r, start_angle, end_angle);
    }
}

/*%pie_slice(r=10, start_angle=-30, end_angle=270, h=10);*/

/*cubea([10,10,10],[1,0,0]);*/
/*%cubea([10,10,10],[1,0,0],[5,5,5],[1,1,1]);*/

/*%cubea([10,10,10],[-1,0,1]);*/
/*%cubea([10,10,10],[-1,0,1],[1,1,1],[-1,0,1]);*/
/*%cylindera(h=10, r=10/2, align=[-1,1,1], extra_r=5/2, extra_h=2, extra_align=[-1,1,1], $fn=100);*/

/*%cylindera(h=10, d=10, align=[-1,1,1], extra_d=5, extra_h=2, extra_align=[-1,1,1], $fn=100);*/
/*%cylindera(h=10, d=10, align=[1,1,1], extra_d=15, extra_h=2, extra_align=[1,1,1], $fn=100);*/

/*%cylindera(h=10, d=10, align=[1,-1,1], extra_d=5, extra_h=2, extra_align=[-1,-1,1], $fn=100);*/
/*%cylindera(h=10, d=10, align=[1,1,1], extra_d=5, extra_h=2, extra_align=[1,1,1], $fn=100);*/

%cylindera(h=10, d=10, align=[1,0,0], extra_d=10);
%cylindera(h=10, r=5, align=[-1,0,0], extra_r=5);

module size_align(size=[10,10,10], align=[0,0,0])
{
    t=[align[0]*size[0]/2,align[1]*size[1]/2,align[2]*size[2]/2];
    /*echo(t);*/
    translate(t)
    {
        children();
    }
}

module cubea(size=[10,10,10], align=[0,0,0], extrasize=[0,0,0], extrasize_align=[0,0,0])
{
    size_align(extrasize,extrasize_align)
    {
        size_align(size,align)
        {
            cube(size+extrasize, center=true);
        }
    }
}

module cylindera(h=10, r=undef, r1=undef, r2=undef, d=undef, d1=undef, d2=undef, align=[0,0,0], extra_h=0,extra_r=undef,extra_d=undef,extra_align=[0,0,0])
{
    extra_r_=(extra_r==undef?0:extra_r);
    extra_d_=(extra_d==undef?0:extra_d);
    extra_sizexy=extra_r_*2 + extra_d_;
    size_align([extra_sizexy,extra_sizexy,extra_h],extra_align)
    {
        r_=(r==undef?0:r);
        d_=(d==undef?0:d);
        sizexy=r_*2 + d_;
        size_align([sizexy,sizexy,h],align)
        {
            cylinder(h=h+extra_h, r=r+extra_r_, r1=r1, r2=r2, d=d+extra_d_, d1=d1, d2=d2, center=true);
        }
    }
}

module fncylinder(r, r2, d, d2, h, fn, center=false, enlarge=0, fnr=0.4){
    translate(center==false?[0,0,-enlarge]:[0,0,-h/2-enlarge]) {
        if (fn==undef) {
            if (r2==undef && d2==undef) {
                cylinder(r=r?r:d?d/2:1,h=h+enlarge*2,$fn=floor(2*(r?r:d?d/2:1)*PI/fnr));
            } else {
                cylinder(r=r?r:d?d/2:1,r2=r2?r2:d2?d2/2:1,h=h+enlarge*2,$fn=floor(2*(r?r:d?d/2:1)*PI/fnr));
            }
        } else {
            if (r2==undef && d2==undef) {
                cylinder(r=r?r:d?d/2:1,h=h+enlarge*2,$fn=fn);
            } else {
                cylinder(r=r?r:d?d/2:1,r2=r2?r2:d2?d2/2:1,h=h+enlarge*2,$fn=fn);
            }
        }
    }
}

// specify segment length with fnr, $fn not needed but if desired use fn instead but if desired use fn instead
module fncylindera(
        h=10,
        r=undef,
        r1=undef,
        r2=undef,
        d=undef,
        d1=undef,
        d2=undef,
        align=[0,0,0],
        extra_h=0,
        extra_r=undef,
        extra_d=undef,
        extra_align=[0,0,0],
        fn,
        fnr=0.4,
        debug=false
        )
{
    pi=3.1415926536;

    useDia = r == undef && (r1 == undef && r2 == undef);

    r_= useDia?d/2:(r==undef?0:r);
    r1_ = useDia?((d1==undef?undef:d1)/2):r1;
    r2_ = useDia?((d2==undef?undef:d2)/2):r2;
    extra_r_ = useDia?((extra_d==undef?0:extra_d)/2):((extra_r==undef)?0:extra_d/2);

    extra_sizexy=extra_r_*2;

    size_align([extra_sizexy,extra_sizexy,extra_h],extra_align)
    {

        fn_=fn==undef?(floor(2*(r_+extra_r_)*pi/fnr)):fn;

        if(debug)
            echo(useDia, h, r_, r1_, r2_, extra_r_, align, fn_);

        sizexy=r_*2;
        size_align([sizexy,sizexy,h],align)
        {
            cylinder(h=h+extra_h, r=r_+extra_r_, r1=r1_, r2=r2_, center=true, $fn=fn_);
        }
    }
}
/*cubea([10,10,10],[1,0,0]);*/
/*%cubea([10,10,10],[1,0,0],[5,5,5],[1,1,1]);*/

/*%cubea([10,10,10],[-1,0,1]);*/
/*%cubea([10,10,10],[-1,0,1],[1,1,1],[-1,0,1]);*/
/*%cylindera(h=10, r=10/2, align=[-1,1,1], extra_r=5/2, extra_h=2, extra_align=[-1,1,1], $fn=100);*/

/*%cylindera(h=10, d=10, align=[-1,1,1], extra_d=5, extra_h=2, extra_align=[-1,1,1], $fn=100);*/
/*%cylindera(h=10, d=10, align=[1,1,1], extra_d=15, extra_h=2, extra_align=[1,1,1], $fn=100);*/

/*%cylindera(h=10, d=10, align=[1,-1,1], extra_d=5, extra_h=2, extra_align=[-1,-1,1], $fn=100);*/
/*%cylindera(h=10, d=10, align=[1,1,1], extra_d=5, extra_h=2, extra_align=[1,1,1], $fn=100);*/

%cylindera(h=10, d=10, align=[1,0,0], extra_d=10);
%cylindera(h=10, r=5, align=[-1,0,0], extra_r=5);


top is now fully covered (no need for passing any cables atm)


Created object is no longer centered

Created object is no longer centered


extruder/old: remove

extruder/old: remove

include <thing_libutils/metric-thread-data.scad>;
include <thing_libutils/metric-hexnut-data.scad>;
use <thing_libutils/shapes.scad>;
use <thing_libutils/misc.scad>;
use <thing_libutils/attach.scad>;
include <MCAD/stepper.scad>
include <MCAD/motors.scad>

include <config.scad>

module capmount(show_sensor=false,lower_height=12,mount_lower=12,height=10,thickness=5,screws_spacing=21,screw_offset=[1,0],screws_diameter=4,sensor_spacing=3,sensor_height=[15,40,5],sensor_diameter=12)
{
    mount_start = 1.7+sensor_spacing+screws_spacing+screws_diameter+2*screw_offset[0];
    if(show_sensor)
    {
        translate([-8+sensor_diameter/2+thickness,-.5+mount_start+thickness+sensor_diameter/2,-39])
        {
            translate([0,0,sensor_height[1]+sensor_height[2]])
                cylindera(d=sensor_diameter-0.5,h=sensor_height[0]);
            translate([0,0,sensor_height[2]])
                %cylindera(d=sensor_diameter-0.5,h=sensor_height[1]);
            cylindera(d=sensor_diameter-0.5,h=sensor_height[2]);
        }
    }

    //  Mount
    $fn=50;
    difference() {
        translate([0,0,-lower_height])
            cube([thickness+1, mount_start, height+lower_height]);

        //Screws 1
        translate([2*e, 4+screw_offset[0], height/2+screw_offset[1]])
        {
            rotate([0,90,0])
            {
                cylindera(d=screws_diameter, h=thickness+1);
                translate([0,0,2.5])
                    cylindera(h = 4, d=8.2, $fn=6);
            }
            //Screws 2
            translate([0,screws_spacing,0])
                rotate([0,90,0])
                {
                    cylindera(d=screws_diameter, h=thickness+1);
                    translate([0,0,2.5])
                        cylindera(h = 4, d=8.2, $fn=6);
                }
        }

    }
    //Sensor mount
    $fn=200;
    translate([-8,-.3,0])
        difference() {
            union() {
                translate([sensor_diameter/2+thickness,mount_start+thickness+sensor_diameter/2, -lower_height])
                    cylindera(d=sensor_diameter+2*thickness, h=height+lower_height-mount_lower);

            }
            translate([sensor_diameter/2+thickness,mount_start+thickness+sensor_diameter/2, -height/2])
                cylindera(d=sensor_diameter+0,5, h=2*height, center=true);

            cutoff=[1,2];
            translate([0,mount_start, -lower_height-e])
                cubea([cutoff[0],sensor_diameter+thickness*2,height+lower_height-mount_lower+2*e],[1,1,1]);

            translate([sensor_diameter+thickness*2,mount_start, -lower_height-e])
                cubea([cutoff[1],sensor_diameter+thickness*2,height+lower_height-mount_lower+2*e],[-1,1,1]);
        }
}

house_bearing=bearing_MR128;
guidler_bearing=bearing_625;

house_padding_wd=11*mm;
house_padding_h=4*mm;

filapath_width=10*mm;

// 4mm ptfe tube
filament_path_d = 4*mm;

// offset from the center of the bolt to the filament path
bolt_center_offset = 4.2*mm;

hotend_mount_h=10.5*mm;

// from E3D V6 heatsink drawing
// http://wiki.e3d-online.com/wiki/File:DRAWING-V6-175-SINK.png
// each entry == dia + h
hotmount_d_h=[[16*mm,3.7*mm],[12*mm,6*mm],[16*mm,3*mm]];
hotmount_outer_size=max(vec_i(hotmount_d_h,0))+10*mm;
hotmount_h_offset=-2*mm;
// which side does hotend slide in (x-axis, i.e. -1 is left, 1 is right)
hotmount_clamp_side=1*mm;

hotmount_tolerance=1.05*mm;

// hotmount clamp screws distance from center
hotmount_clamp_thread = ThreadM3;
hotmount_clamp_nut = MHexNutM3;

hotmount_clamp_screw_dia = lookup(ThreadSize, hotmount_clamp_thread);
hotmount_clamp_screws_dist = hotmount_d_h[1][1] + 2*hotmount_clamp_screw_dia;
hotmount_clamp_pad = 2.5*mm;
hotmount_clamp_thickness = 5*mm;
hotmount_clamp_y = 2*(hotmount_clamp_screws_dist + hotmount_clamp_screw_dia + hotmount_clamp_pad);
hotmount_clamp_height = hotmount_d_h[1][1];

// length of the guidler bearing bolt/screw
guidler_bolt_h=10*mm;

guidler_mount_w=guidler_bearing[2];
guidler_mount_d=9*mm;

guidler_w=max(guidler_mount_w+7, guidler_bearing[2]*2.8);
guidler_d=5;
guidler_h=12;
guidler_extra_h_up=guidler_bearing[1]/2+hotmount_clamp_screw_dia/2;

guidler_mount_off_d=-guidler_bearing[1]/1.7;
guidler_mount_off_h=-guidler_bearing[1]/1.7;

extruder_guidler_mount_off_y = guidler_mount_off_d - guidler_bearing[1]/2;

house_inner_w=max(guidler_w+3, filament_d*2 + 4*2);

guidler_screws_thread = ThreadM3;
guidler_screws_thread_dia= lookup(ThreadSize, guidler_screws_thread);
guidler_screws_distance=6*mm;
guidler_screws_mount_d = 10*mm;
guidler_screws_mount_d_offset = 0*mm;

xcarriage_mount_hole_distance = 23*mm;
xcarriage_mount_w = xcarriage_mount_hole_distance + 6*mm;
xcarriage_mount_d = 6*mm;
xcarriage_mount_h = xcarriage_mount_w;

// 80t + 20t w/228-2GT-6 belt
gears_distance=38.8*mm;
motor_offset_y = 20*mm;
motor_offset_z = pythag_leg(motor_offset_y,gears_distance);

extruder_motor_type = NemaShort;
extruder_motor = dict_replace_multiple(Nema17,
        [
        [NemaShort, 33*mm],
        [NemaFrontAxleLength, 22*mm]
        ]);

extruder_motor_mount_thickness = 5*mm;
extruder_motor_side = motorWidth(extruder_motor);
extruder_motor_length = motorLength(extruder_motor);

house_w = max(house_inner_w+2*house_bearing[2], hotmount_outer_size, xcarriage_mount_w);
house_d=house_bearing[1]/2+house_padding_wd;
house_h=house_bearing[1]+house_padding_h;

house_guidler_screw_h = guidler_screws_thread_dia+8*mm;
house_guidler_screw_h_offset = house_h/2 + guidler_screws_thread_dia + 4*mm;

alpha = 0.7;
/*alpha = 1;*/
color_xcarriage = [0.3,0.8,0.3, alpha];
color_hotend = [0.8,0.4,0.4, alpha];
color_extruder = [0.2,0.6,0.9, alpha];
color_guidler = [0.4,0.5,0.8, alpha];

extruder_guidler_roll = 45;

house_offset_xcarriage_y = house_d+19*mm;
house_offset_xcarriage_z = -25;

// extruder connection point for guidler
extruder_conn_guidler = [ [0, extruder_guidler_mount_off_y, guidler_mount_off_h],  [1,0,0]];
extruder_conn_hotend = [[0,0,-house_h/2+hotmount_h_offset-0.1],[0,0,1]];
extruder_conn_xcarriage=[[0, house_offset_xcarriage_y, house_offset_xcarriage_z],[0,1,0]];
/*extruder_conn_xcarriage=[[house_w/2+10, 15,-36],[-1,0,0]];*/

extruder_conn_hotmount_clamp=[[house_w/2*(hotmount_clamp_side), 0,-house_h/2+hotmount_h_offset -hotmount_d_h[0][1]-hotmount_d_h[1][1]/2], [0,0,0]];
hotmount_clamp_conn = [[0,0,0],[0,0,0]];

module extruder_guidler_mount(){

    translate([0,guidler_mount_off_d-guidler_bearing[1]/2, guidler_mount_off_h])
    {
        cubea([guidler_mount_w,guidler_mount_d,guidler_mount_d],align=[0,0,-1], extrasize=[0,5,0], extrasize_align=[0,1,0]);
        rotate([0,90,0])
        {
            cylindera(d=guidler_mount_d, h=guidler_mount_w);
        }

        translate([0,0,-guidler_mount_d/2-1])
            cubea([house_w,guidler_mount_d,guidler_mount_d/2+1],align=[0,0,-1], extrasize=[0,5,0], extrasize_align=[0,1,0]);
    }
}

module extruder_own(show_filament=true)
{
    color(color_extruder)
    difference()
    {
        union(){

            house_w_extended = max(house_w, extruder_motor_mount_thickness*2+extruder_motor_length);
            hull()
            {
                // main house
                translate([0,bolt_center_offset,0])
                {
                    /*rotate([0,90,0])*/
                    /*cylindera(h=house_w, d=house_d);*/
                    cubea(size=[house_w,house_d,house_h], align=[0,0,0]);
                }

                // hotend mount housing
                translate([0,0,-house_h/2 + hotmount_h_offset])
                {
                    /*cubea([house_w/2, hotmount_outer_size, hotend_mount_h], align=[-1,0,-1], extrasize=[guidler_mount_w/2,0,-hotmount_h_offset], extrasize_align=[1,-1,1]);*/
                    cubea([house_w, hotmount_outer_size, hotend_mount_h], align=[0,0,-1]);
                }

            }

            hull()
            {
                // main house
                translate([0,bolt_center_offset,0])
                {
                    /*rotate([0,90,0])*/
                    /*cylindera(h=house_w, d=house_d);*/
                    cubea(size=[house_w, house_d, house_h], align=[0,0,0]);
                }

                // guidler screws mount
                translate([0, guidler_screws_mount_d_offset, house_guidler_screw_h_offset])
                {
                    cubea([house_w, guidler_screws_mount_d, house_guidler_screw_h], align=[0,0,0]);

                    for(i=[-1,1])
                    translate([i*(guidler_screws_distance), 0, 0])
                    rotate([0,90,90])
                    cylindera(d=house_guidler_screw_h, h=guidler_screws_mount_d);
                }

                // mount onto xcarriage
                translate([0,0,0])
                    translate([0, house_offset_xcarriage_y, house_offset_xcarriage_z])
                    cubea([xcarriage_mount_w,xcarriage_mount_d,xcarriage_mount_h],[0,-1,0]);

                /*translate([0, house_offset_xcarriage_y, house_offset_xcarriage_z])*/
                /*cubea([xcarriage_mount_w,house_offset_xcarriage_y,xcarriage_mount_h],[0,-1,0]);*/
            }

            translate([0,bolt_center_offset,0])
            translate([0,motor_offset_y,motor_offset_z])
            {
                difference()
                {
                    slide_dist=4;
                    union()
                    {
                        // front mount plate for motor
                        translate([-house_w/2,0,0])
                        {
                            cubea([extruder_motor_mount_thickness, extruder_motor_side+slide_dist, extruder_motor_side],[1,0,0]);

                            // back mount plate for motor
                            translate([extruder_motor_length,0,0])
                                cubea([extruder_motor_mount_thickness, extruder_motor_side+slide_dist, extruder_motor_side],[1,0,0]);
                        }
                    }

                    translate([-extruder_motor_mount_thickness-1,0,0])
                        rotate([90,90,90])
                        linear_extrude(extruder_motor_mount_thickness+2)
                        stepper_motor_mount(17, slide_distance=4, mochup=false);
                }
            }

            // guidler mount
            extruder_guidler_mount();
        }

        translate([0,bolt_center_offset,0])
        translate([0,motor_offset_y,motor_offset_z])
        {
            slide_dist=4;
            cubea([extruder_motor_length, extruder_motor_side+slide_dist, extruder_motor_side],[1,0,0]);

            translate([-extruder_motor_mount_thickness-1,0,0])
                rotate([90,90,90])
                linear_extrude(extruder_motor_mount_thickness+2)
                stepper_motor_mount(17, slide_distance=4, mochup=false);
        }

        // guidler screws cutouts
        for(i=[-1,1])
        translate([i*(guidler_screws_distance), guidler_screws_mount_d_offset, house_guidler_screw_h_offset])
        {
            r= guidler_screws_thread_dia/2 * 1.1;
            cubea([r*2, guidler_screws_mount_d+1, r]);
            for(v=[-1,1])
            translate([0,0, v*r/2])
            {
                rotate([0,90,90])
                    cylindera(r=r,h=guidler_screws_mount_d+1);
            }

            // guidler screw nuts drop-in slots
            translate([0,0, -r*2])
            cubea([nut_m3[1]*1.1,nut_m3[2]*1.25,house_guidler_screw_h], align=[0,0,1], extrasize=[0,0,1], extrasize_align=[0,0,1]);
        }

        // filament path ptfe line cutout
        cylindera(d=filament_path_d, h=50, align=[0,0,0]);

        translate([0,0,-house_h/2+hotmount_h_offset])
        {
            hotmount_cutout(extend_cut=true);

            // clamp mount screw holes
            for(i=[-1,1])
            {
                translate([0, i*hotmount_clamp_screws_dist, -hotmount_d_h[0][1]-hotmount_d_h[1][1]/2])
                    rotate([0,90,0])
                    cylindera(r=screw_m3[0], h=house_w+1);
            }

            translate([house_w/2 * (hotmount_clamp_side), 0, -hotmount_d_h[0][1]-hotmount_d_h[1][1]/2])
            {
                cubea([hotmount_clamp_thickness+0.2, hotmount_clamp_y+0.2, hotmount_clamp_height+0.2], align=[-hotmount_clamp_side,0,0], extrasize=[1,0,0], extrasize_align=[hotmount_clamp_side,0,0]);
            }
        }

        // cutout pivot to make sure guidler can rotate out
        guidler_pivot_r=pythag_hyp(abs(guidler_mount_off_d),abs(guidler_mount_off_h))+(guidler_bearing[1])/2;
        difference()
        {
            union()
            {
                /*translate([-house_inner_w/2,0,0])*/
                    /*translate([0,extruder_guidler_mount_off_y, guidler_mount_off_h])*/
                    /*rotate([0,90,0])*/
                    /*pie_slice(guidler_pivot_r*1.05, 120, 180, house_inner_w, $fn=50);*/

                translate([-house_inner_w/2,0,0])
                    translate([0,extruder_guidler_mount_off_y, guidler_mount_off_h])
                    rotate([0,90,0])
                    pie_slice(guidler_mount_d/2*1.25, 0, 180, house_inner_w/2 - guidler_mount_w/2, $fn=50);

                translate([guidler_mount_w/2,0,0])
                    translate([0,extruder_guidler_mount_off_y, guidler_mount_off_h])
                    rotate([0,90,0])
                    pie_slice(guidler_mount_d/2*1.25, 0, 180, house_inner_w/2 - guidler_mount_w/2, $fn=50);
            }

            extruder_guidler_mount();
        }

        // cutout inside main house for guidler
        guidler_pivot_r=pythag_hyp(guidler_mount_off_d,guidler_mount_off_h);
        translate([-house_inner_w/2,-guidler_bearing[1]/2, 0])
        {
            rotate([0,90,0])
            {
                pie_slice(r=guidler_bearing[1]/2*1.02, start_angle=0, end_angle=360, h=house_inner_w);
            }
        }

        /*translate([0,-guidler_bearing[1]/2,0])*/
        /*rotate([0,90,0])*/
        /*cylindera(d=guidler_bearing[1]*1.05, h=house_inner_w);*/

        translate([0,bolt_center_offset,0])
        {
            // left bearing
            translate([-house_w/2-2*e,0,0])
                rotate([90,0,90])
                cylindera(d=house_bearing[1]*1.02, h=house_bearing[2], align=[0,0,1]);

            // right bearing
            translate([house_w/2+2*e,0,0])
                rotate([90,0,90])
                cylindera(d=house_bearing[1]*1.02, h=house_bearing[2], align=[0,0,-1]);

            // hobbed bolt
            rotate([90,0,90])
                cylindera(d=8.5, h=house_w+1);
        }

        // guidler mount bolt hole
        translate([0,guidler_mount_off_d-guidler_bearing[1]/2, guidler_mount_off_h])
            rotate([0,90,0])
            cylindera(r=screw_m3[0],h=guidler_w+1);
    }

    if(show_filament)
    {
        // filament
        cylindera(d=filament_d, h=50);
    }

    /*translate([0,0,-house_h/2])*/
}

module hotmount_cutout(extend_cut=false)
{
    // cutout of j-head/e3d heatsink mount
    heights=vec_i(hotmount_d_h,1);
    for(e=v_itrlen(hotmount_d_h))
    {
        hs=v_sum(heights,e);
        translate([0,0,-hs])
        {
            d=hotmount_d_h[e][0]*hotmount_tolerance;
            h=hotmount_d_h[e][1]*hotmount_tolerance;
            cylindera(d=d,h=h,align=[0,0,1]);
            if(extend_cut)
            {
                cubea([house_w/2+1,d,h],align=[hotmount_clamp_side,0,1]);
            }
        }
    }
}

module hotmount_clamp()
{
    difference()
    {
        union()
        {
            translate([house_w/2 * hotmount_clamp_side, 0, 0]);
            {
                cubea([hotmount_clamp_thickness, hotmount_clamp_y, hotmount_clamp_height], align=[-hotmount_clamp_side,0,0]);
            }

            difference()
            {
                translate([house_w/2 * hotmount_clamp_side, 0, 0]);
                {
                    cubea([house_w/2, hotmount_d_h[1][0], hotmount_clamp_height], align=[-hotmount_clamp_side,0,0]);
                }

                translate([(-house_w/2 * hotmount_clamp_side) + (-0.5*hotmount_clamp_side), 0, hotmount_d_h[0][1]+hotmount_d_h[1][1]/2])
                {
                    hotmount_cutout(extend_cut = false);
                }
            }

        }

        // clamp mount screw holes
        for(i=[-1,1])
        {
            translate([0, i*hotmount_clamp_screws_dist, 0])
                rotate([0,90,0])
                cylindera(r=screw_m3[0], h=hotmount_clamp_thickness, align=[0,0,-hotmount_clamp_side], extra_h=1);
        }
    }
}

// guidler connection point
guidler_conn = [ [0, guidler_mount_off_d, guidler_mount_off_h],  [1,0,0]];

module guidler()
{
    // everything inside this module is relative to the center of the
    // bearing (that clamps the filament)
    color(color_guidler)
    difference()
    {
        union()
        {

            hull()
            {
                // guidler main block
                translate([0,guidler_mount_off_d-guidler_mount_d/2, 0])
                    cubea([guidler_w, guidler_d, guidler_h], align=[0,1,0]);

                // guidler bearing bolt holder
                rotate([0,90,0])
                    cylindera(d=guidler_bearing[0]*1.5,h=guidler_w);
            }
            hull()
            {
                // guidler main block
                translate([0,guidler_mount_off_d-guidler_mount_d/2, 0])
                    cubea([guidler_w, guidler_d, guidler_h], align=[0,1,0], extrasize=[0,0,guidler_extra_h_up], extrasize_align=[0,0,1]);

                // guidler mount point
                translate([0,guidler_mount_off_d, guidler_mount_off_h])
                    rotate([0,90,0])
                    cylindera(d=guidler_mount_d,h=guidler_w);
            }

            hull()
            {
                // guidler main block
                translate([0,guidler_mount_off_d-guidler_mount_d/2, guidler_h])
                    cubea([guidler_w, guidler_d, 1], align=[0,1,0]);

                // guidler screws mount
                for(i=[-1,1])
                translate([i*(guidler_screws_distance),guidler_mount_off_d-guidler_mount_d/2, house_guidler_screw_h_offset])
                rotate([0,90,90])
                cylindera(r=guidler_screws_thread_dia/2*3,h=guidler_d, align=[0,0,1]);

            }
        }

        // cutouts for clamping screws
        for(i=[-1,1])
        translate([i*(guidler_screws_distance),guidler_mount_off_d-guidler_mount_d/2, house_guidler_screw_h_offset])
        {
            r= guidler_screws_thread_dia/2*1.1;
            cubea([r*2,house_w+1,r]);
            for(v=[-1,1])
                translate([0,0, v*r/2])
                {
                    rotate([0,90,90])
                        cylindera(r=r,h=house_w+1);
                }
        }

        // port hole to see bearing
        translate([0,-guidler_bearing[1]/2,0])
            cubea([guidler_bearing[0]*1.1, 100, guidler_bearing[1]/2], align=[0,0,1]);

        // cutout middle mount point pivot
        translate([0,guidler_mount_off_d, guidler_mount_off_h])
            rotate([0,90,0])
            {
                cylindera(d=guidler_mount_d*1.25,h=guidler_mount_w*1.1);
            }

        // mount bolt hole
        translate([0,guidler_mount_off_d, guidler_mount_off_h])
            rotate([0,90,0])
            cylindera(r=screw_m3[0],h=100);

        // guidler bearing bolt holder cutout
        union() {
            cubea([guidler_bolt_h*1.05+2*e,guidler_bearing[0]*1.05,guidler_bearing[0]*1.05],align=[0,1,0]);

            rotate([0,90,0])
                cylindera(d=guidler_bearing[0]*1.05, h=guidler_bolt_h*1.05);
        }

        // guidler bearing cutout
        rotate([0,90,0])
            cylindera(d=guidler_bearing[1]*1.1, h=guidler_bearing[2]*1.1);
    }

    %if(show_extras)
    {
        rotate([0,90,0])
        {
            cylindera(d=guidler_bearing[1], h=guidler_bearing[2]);
            cylindera(d=guidler_bearing[0], h=guidler_bolt_h);
        }
    }
}

module extras()
{
    hob_offset_x = -5*mm;

    // hobbed bolt
    // measurements from
    // http://wiki.e3d-online.com/wiki/E3D_HobbGoblin_Drawings
    hob_l = 64.5*mm;

    // center of the hob (from left side)
    hob_center = 37*mm;

    hob_conn_extruder=[[-hob_l/2+hob_center,0,0], [0,0,0]];

    attach([[0,bolt_center_offset,0],[0,0,0]], hob_conn_extruder)
    {
        /*connector(hob_conn_extruder);*/

        // hob-goblin hobbed bolt
        union()
        {
            thread_left = 20.5;
            thread_right = 14;
            hob_width = 4.2;
            color([0.1,0.2,0.3])
                translate([-hob_l/2,0,0])
                rotate([0,90,0])
                cylindera(h=thread_left, d=8, align=[0,0,1]);

            color([0.6,0.6,0.6])
            difference()
            {
                translate([-hob_l/2+thread_left,0,0])
                    rotate([0,90,0])
                    cylindera(h=hob_l-thread_left-thread_right, d=8, align=[0,0,1]);

                translate([-hob_l/2+hob_center,0,0])
                    rotate([0,90,0])
                    cylindera(h=hob_width, d=8.1);
            }
            color([0.6,0.2,0.3])
                translate([-hob_l/2+hob_center,0,0])
                rotate([0,90,0])
                cylindera(h=hob_width, d=7);

            color([0.1,0.2,0.3])
            translate([hob_l/2-thread_right,0,0])
                rotate([0,90,0])
                cylindera(h=thread_right, d=8, align=[0,0,1]);

            /*rotate([0,90,0])*/
                /*cylindera(h=hob_l, d=8);*/

            /*translate([-hob_l/2+hob_center,0,0])*/
                /*rotate([0,90,0])*/
                /*cylindera(h=hob_width, d=8.1);*/

        }

        hob_conn_cog = [[-hob_l/2 + 13*mm,0,0], [-1,0,0]];

        /*connector(hob_conn_cog);*/
        // gear/cog
        // attach onto hobbed bolt
        cog_conn = [[11*mm,0,0],[1,0,0]];
        attach(hob_conn_cog, cog_conn, 019)
        {
            rotate([270,0,90])
                import("stl/gt2_extruder_cog_80tooth.stl");
        }
    }

    // motor/belt
    translate([-1,bolt_center_offset,0])
    translate([-house_w/2+extruder_motor_mount_thickness,motor_offset_y,motor_offset_z])
    {
        // main motor body
        motor(extruder_motor, extruder_motor_type, dualAxis=false, orientation=[0,90,0]);

        translate([-1,0,0])
            rotate([0,0,180])
            import("stl/GT2_20tooth.stl");
    }

    // hotend
    hotend_conn =[[0,0,21.35*mm],[0,0,1]];
    attach(extruder_conn_hotend, hotend_conn)
        color(color_hotend)
        rotate([90,0,270])
        import("stl/E3D_V6_1.75mm_Universal_HotEnd_Mockup.stl");

    // x carriage
    xcarriage_conn =[[-0.4,-8.5,-1],[0,-1,0]];
    attach(extruder_conn_xcarriage, xcarriage_conn)
    {
        /*connector(xcarriage_conn);*/
        color(color_xcarriage)
            translate([282*mm,-170,14])
            rotate([90,180,180])
            import("../wilson/x-carriage.stl");
    }
}

module extruder()
{
    extruder_own();

    attach(extruder_conn_guidler, guidler_conn, extruder_guidler_roll)
    {
        guidler(show_extras=true);
    }

    attach(extruder_conn_hotmount_clamp, hotmount_clamp_conn)
    {
        /*connector(hotmount_clamp_conn);*/
        hotmount_clamp(); }

    if(true) { extras(); } }

module print()
{
    extruder_conn_layflat = [[-house_w/2,0,0],[-1,0,0]];
    attach([[0,0,0],[0,0,-1]], extruder_conn_layflat)
    {
        /*connector(extruder_conn_layflat);*/
        extruder_own(false,false);
    }

    guidler_conn_layflat = [ [0, guidler_mount_off_d-guidler_mount_d/2, guidler_mount_off_h],  [0,-1,0]]; attach([[34*mm,10*mm,0],[0,0,-1]], guidler_conn_layflat)
    {
        /*connector(guidler_conn_layflat);*/
        guidler(false);
    }

    hotmount_clamp_conn_layflat=[[0,0,0],[-1,0,0]];
    attach([[54*mm,0,0],[0,0,1]], hotmount_clamp_conn_layflat)
    {
        /*connector(hotmount_clamp_conn);*/
        hotmount_clamp();
    }
}

/*extruder();*/
/*print();*/


convert to actual angle beams for floor frame

// config e
Ay=3.318;
AC=17.5;
Bx=53.83;

loY=-60;  // location of lower brace beams
loX= 10;

zBar=90;

$fn=8;

for (a=[-1,1]) {
  %translate([0,0,(zBar-10)*a]) legProxy();
  %translate([0,0,(zBar+10)*a]) legProxy();
  translate( [0,0, zBar    *a]) color([.2,.2,.8,1]) mainBar();
  #translate([0,0,a*(zBar+20)]) rotate([0,90*(a+1),0]) outerCap();
}
basket();

module basket() {
  for(a=[-1,1]) {
    %translate([Bx*a,0,0]) cylinder(r=1,h=120,$fn=16,center=true); // main axle
    for (b=[-1,1]) translate([Bx*b,0,zBar*a]) {
       color([0,0,1,.6]) translate([0,0,-6*a])
       cylinder(r=1.9,h=60,$fn=16,center=true); // axle

       // axle brace sleves
       translate([0,0,-26*a]) cylinder(r=2.5,h=18,$fn=16,center=true);
    }

    //color([.6,.8,0,1])
    translate([loX*a,loY,0]) difference() {
       cube([2.5,2.5,230],center=true); // lower rails

       // remove center section for wide platform version
       cube([3,3,66],center=true);
    }

    hull() for (b=[-1,1]) translate([ Bx*b, 0 ,71*a]) sphere(1); // arm guard bar
    //hull() for (b=[-1,1]) translate([loX*b,loY,71*a]) sphere(1); // outer foot bar
    for (b=[-1,1]) {
      hull() { // outer diagonal
        translate([ Bx*b, 0 ,70*a]) sphere(1);
        translate([20*b,loY+2,70*a]) sphere(1);
      }
    }

    for(x=[-1,1]) {
       hull() { // inner back trap
         translate([x*35,loY+4,22*a]) sphere(1);
         translate([x*Bx,  0  , 5*a]) sphere(1);
       }
       hull() { // outer back
         translate([x*35,loY+2,31*a]) sphere(1);
         translate([x*Bx,  0  ,60*a]) sphere(1);
       }
    }

    // may do something more complicated for payload bay,
    // but for now, just stich sides together
    translate([a*(Bx+2),2,0]) cube([3.8,3.8,140],center=true);

    translate([34*a,loY+2.7,0]) difference() {
       cube([2.5,2.5,138],center=true);
       translate([-.4*a,.4,0]) cube([2.5,2.5,139],center=true);
    }
    translate([0,loY+3,67*a]) rotate([0,90*(a+1),0]) difference() {
       cube([70,3.8,3.8],center=true);
       translate([0,.4,.4]) cube([72,3.8 ,3.8],center=true);
    }
    hull() {  // central floor cross
      translate([ 34*a,loY+1, 32]) sphere(1);
      translate([-34*a,loY+1,-32]) sphere(1);
    }
  }

  //for(z=[-1,0,1])
  for(z=[-1,1])
  translate([0,loY+.4,34*z]) rotate([0,(z==1)?180:0,0]) difference() {
     cube([70,2.5,2.5],center=true);
     translate([0,-.4,-.4]) cube([71,2.5,2.5],center=true);
  }
  translate([0,loY+2,0]) rotate([90,0,0]) cylinder(r=4,h=.4,$fn=32);
  color([0,.2,.8,.2]) // expanded mesh floor
     translate([0,loY+2,0]) cube([68,.5,134],center=true);
     //translate([0,loY+2,0]) cube([2*loX,1,130],center=true);
}

module mainBar() {
  cube([110,5,5],center=true);
  translate([0,Ay,0]) {
    cylinder(r=1.5,h=4,$fn=16,center=true);
    #cylinder(r=AC,h=2,$fn=36,center=true);
    //cylinder(r=AC+2,h=.4,$fn=36,center=true);
  }

  // lower support
  for(x=[-1,1]) {
     // lower rail tubes
     translate([x*loX,loY,0]) cube([3.8,3.8,10],center=true);

     hull() {     // diagonals
       translate([x*(loX+2),loY,0]) sphere(1);
       translate([x*(Bx-8),0,0]) sphere(1);
     }
  }
  translate([0,loY,0]) cube([2*loX,3.8,3.8],center=true);
}

module outerCap() {
  for (b=[-1,1]) translate([Bx*b,0,-1]) {
     // axle brace sleves... shorter on outside
     cylinder(r=2.5,h=6 ,$fn=16,center=true);
  }
  translate([0,loY,0]) cube([2*loX,3.8,3.8],center=true);
  for(x=[-1,1]) translate([x*loX,loY,1])
         cube([3.8,3.8,8],center=true); // lower rail sleves

  for (b=[-1,1]) hull() { // outside diagonal brace
    translate([loX*b,loY,0]) sphere(1);
    translate([ Bx*b, 0 ,0]) sphere(1);
  }
  hull() for(b=[-1,1]) translate([Bx*b,0,0]) sphere(1);
}

module legProxy() scale([1,1,12]) {
  legProxy1();
  mirror([1,0,0]) legProxy1();
}

// measurements from drawing, center pixel 600,300, 4 pixels/cm
module legProxy1() {

  hull() {
    translate([0,3.32,0]) cylinder(r=17.5+2,h=1,$fn=36,center=true);
    translate([-250/4, 290/4,0]) node();
    translate([-200/4, 290/4,0]) node();
    translate([-360/4, 120/4,0]) node();
    translate([-500/4,-110/4,0]) node();
    translate([-430/4,-230/4,0]) node();
  }
  hull() {
    translate([-400/4,-220/4  ,0]) node();
    translate([-340/4,-370/4+2,0]) node();
    translate([ -90/4,-370/4+2,0]) node();
    translate([-140/4,-120/4  ,0]) node();
  }
}

module node() cylinder(r=2,h=1,$fn=9,center=true);

// config e
Ay=3.318;
AC=17.5;
Bx=53.83;

loY=-60;  // location of lower brace beams
loX= 10;

zBar=90;

$fn=8;

for (a=[-1,1]) {
  %translate([0,0,(zBar-10)*a]) legProxy();
  %translate([0,0,(zBar+10)*a]) legProxy();
  translate( [0,0, zBar    *a]) color([.2,.2,.8,1]) mainBar();
  #translate([0,0,a*(zBar+20)]) rotate([0,90*(a+1),0]) outerCap();
}
basket();

module basket() {
  for(a=[-1,1]) {
    %translate([Bx*a,0,0]) cylinder(r=1,h=120,$fn=16,center=true); // main axle
    for (b=[-1,1]) translate([Bx*b,0,zBar*a]) {
       color([0,0,1,.6]) translate([0,0,-6*a])
       cylinder(r=1.9,h=60,$fn=16,center=true); // axle

       // axle brace sleves
       translate([0,0,-26*a]) cylinder(r=2.5,h=18,$fn=16,center=true);
    }

    //color([.6,.8,0,1])
    translate([loX*a,loY,0]) difference() {
       cube([2.5,2.5,230],center=true); // lower rails

       // remove center section for wide platform version
       cube([3,3,66],center=true);
    }

    hull() for (b=[-1,1]) translate([ Bx*b, 0 ,71*a]) sphere(1); // arm guard bar
    //hull() for (b=[-1,1]) translate([loX*b,loY,71*a]) sphere(1); // outer foot bar
    for (b=[-1,1]) {
      hull() { // outer diagonal
        translate([ Bx*b, 0 ,70*a]) sphere(1);
        translate([20*b,loY+2,70*a]) sphere(1);
      }
    }

    for(x=[-1,1]) {
       hull() { // inner back trap
         translate([x*35,loY+4,22*a]) sphere(1);
         translate([x*Bx,  0  , 5*a]) sphere(1);
       }
       hull() { // outer back
         translate([x*35,loY+2,31*a]) sphere(1);
         translate([x*Bx,  0  ,60*a]) sphere(1);
       }
    }

    *hull() { // center foot low diag
      translate([ loX,loY, 5*a]) sphere(1);
      translate([-loX,loY,30*a]) sphere(1);
    }
    *hull() {
      translate([-loX,loY,40*a]) sphere(1);
      translate([ loX,loY,70*a]) sphere(1);
    }
    *for (b=[-1,1]) hull() {  // outer low X
      translate([-loX*b,loY,130*a]) sphere(1);
      translate([ loX*b,loY, 70*a]) sphere(1);
    }

    // may do something more complicated for payload bay,
    // but for now, just stich sides together
    translate([a*(Bx+2),2,0]) cube([3.8,3.8,140],center=true);

    translate([34*a,loY+6,0]) cube([2.5,2.5,138],center=true);
    translate([0,loY+3,67*a]) cube([70,3.8 ,3.8],center=true);
  }

  for(z=[-1,0,1]) translate([0,loY+3,34*z])
     cube([70,2.5,2.5],center=true);
  color([0,.2,.8,.2]) // expanded mesh floor
     translate([0,loY+5,0]) cube([68,.5,130],center=true);
     //translate([0,loY+2,0]) cube([2*loX,1,130],center=true);
}

module mainBar() {
  cube([110,5,5],center=true);
  translate([0,Ay,0]) {
    cylinder(r=1.5,h=4,$fn=16,center=true);
    #cylinder(r=AC,h=2,$fn=36,center=true);
    //cylinder(r=AC+2,h=.4,$fn=36,center=true);
  }

  // lower support
  for(x=[-1,1]) {
     // lower rail tubes
     translate([x*loX,loY,0]) cube([3.8,3.8,10],center=true);

     hull() {     // diagonals
       translate([x*(loX+2),loY,0]) sphere(1);
       translate([x*(Bx-8),0,0]) sphere(1);
     }
  }
  translate([0,loY,0]) cube([2*loX,3.8,3.8],center=true);
}

module outerCap() {
  for (b=[-1,1]) translate([Bx*b,0,-1]) {
     // axle brace sleves... shorter on outside
     cylinder(r=2.5,h=6 ,$fn=16,center=true);
  }
  translate([0,loY,0]) cube([2*loX,3.8,3.8],center=true);
  for(x=[-1,1]) translate([x*loX,loY,1])
         cube([3.8,3.8,8],center=true); // lower rail sleves

  for (b=[-1,1]) hull() { // outside diagonal brace
    translate([loX*b,loY,0]) sphere(1);
    translate([ Bx*b, 0 ,0]) sphere(1);
  }
  hull() for(b=[-1,1]) translate([Bx*b,0,0]) sphere(1);
}

module legProxy() scale([1,1,12]) {
  legProxy1();
  mirror([1,0,0]) legProxy1();
}

// measurements from drawing, center pixel 600,300, 4 pixels/cm
module legProxy1() {

  hull() {
    translate([0,3.32,0]) cylinder(r=17.5+2,h=1,$fn=36,center=true);
    translate([-250/4, 290/4,0]) node();
    translate([-200/4, 290/4,0]) node();
    translate([-360/4, 120/4,0]) node();
    translate([-500/4,-110/4,0]) node();
    translate([-430/4,-230/4,0]) node();
  }
  hull() {
    translate([-400/4,-220/4  ,0]) node();
    translate([-340/4,-370/4+2,0]) node();
    translate([ -90/4,-370/4+2,0]) node();
    translate([-140/4,-120/4  ,0]) node();
  }
}

module node() cylinder(r=2,h=1,$fn=9,center=true);


thicken frame

thicken frame

// Copyright (c) 2015
// Author: Jeff Weisberg <jaw @ tcp4me.com>
// Created: 2015-Oct-04 22:32 (EDT)
// Function: frame for mini-copter

show_env   = 0;

pcb_x      = 25.0;
pcb_y      = 25.0;
pcb_z      =  1.6;

peg_pos    = 1.25;	// in from corner
prop_x     = 56.0;	// prop diam plus margin
mot_z      = 10.0; 	// ht of center of motor
motor_phi  = 5.0;	// slight dihedral
motor_diam = 7;

//################################################################

mot_pos = (prop_x - pcb_x) / 2;
mot_armang = atan( (mot_z + 2) / (mot_pos + peg_pos) / sqrt(2) );

$fn = 0;
$fa = .5;
$fs = 0.05;

//################################################################

module vcyl(x,y,z,diam1, diam2, len){
    translate([x,y,z])
        cylinder(r1=diam1/2, r2=diam2/2, h=len);
}

module hcyl(x,y,z,diam1, diam2, len){
    translate([x,y,z])
        rotate([0,90,0])
            cylinder(r1=diam1/2, r2=diam2/2, h=len);
}

module box(x,y,z, dx,dy,dz){
    translate([x, y, z]) cube([dx, dy, dz]);
}

module proparm(){

    // board support+attach
    translate([ (pcb_x/2-peg_pos)*sqrt(2), 0, 0]) rotate([0,0,45]){
        vcyl(0,0,-3, 3, 3,3);
        // slightly tapered pins
        vcyl(0,0,-.1, 1.0, 0.7, 2.1);
        box(-3.5,-.5,-1.5, 4,1,1.5);
        box( -.5,-.5,-1.5, 1,4,1.5);

    }

    // legs
    translate([ (pcb_x/2-peg_pos)*sqrt(2), 0, -3.0]) rotate([0,30,0]){
        intersection(){
            box(0,-1,0, 15,2,1.5);
            hcyl(0,0,1, 2, 1, 15);
        }
        translate([15,0,.5]) sphere(1.0);
    }

    difference(){
        union(){
            // motor arms
            intersection(){
                translate([ (pcb_x/2-peg_pos)*sqrt(2), 0, -2.0]) rotate([0,-mot_armang,0]) {
                    box(0, -1.4, 0, (mot_pos+peg_pos)*sqrt(2) / cos(mot_armang), 2.8,1 );
                    box(0,-.5,  -1.5, (mot_pos+peg_pos)*sqrt(2) / cos(mot_armang), 1,2.5 );
                }
                // clean up the bottom
                box(-5,-5,-3, 60,60,60);
            }
            // motor mounts
            translate([prop_x/2 * sqrt(2),0, mot_z]) rotate([0,-motor_phi,0]){
                vcyl(0,0,-3.25, motor_diam+2, motor_diam+2, 6.5 );

                // prop
                if( show_env ) color([.75,0,.75,1]) vcyl(0,0,5, 45, 45, 5);
            }

        }
        union(){
            // hole for motor
            translate([prop_x/2 * sqrt(2),0, mot_z]) rotate([0,-motor_phi,0]){
                vcyl(0,0,-5, motor_diam-.5, motor_diam-.5, 9 );
                rotate([0,0,90]) box(motor_diam/2-2, -.5,-5, 5,1,9);
            }
        }
    }
}

module cage(){
    // outer box
    box(-28/2-1.5, 28/2+.5, -1.25, 28+3, 1.0,2.5);
    box(-28/2-1.5, 28/2-.5, -.5,  28+3, 2.0,1.0);

    // rubber band attachment pegs
    hcyl(28/2+.5, -6, 0,  2,2,3);
    hcyl(28/2+.5,  6, 0,  2,2,3);
    hcyl(28/2+.5, -2, 0,  2,2,3);
    hcyl(28/2+.5,  2, 0,  2,2,3);
}

// ################################################################

if( show_env ) color([.75,0,.75, 1]) box(-pcb_x/2, -pcb_y/2, 0, pcb_x, pcb_y, pcb_z);

for( angle = [ 0 : 90 : 270 ] ){
    rotate([0,0,45+angle]) proparm();

    // outer cage
    rotate([0,0,angle]) translate([0,0,.60]) cage();

}