new cage with LCD / ESC attachments

new cage with LCD / ESC attachments

//$fs = 0.1;
//$fa = 5;
$fs = 0.25;
$fa = 8;

use <hcsr04.scad>

module wheel() {
    color("black") rotate([90, 90, 0]) difference() {
        #cylinder(d=47, h=23, center=true);
        cylinder(d=30, h=26, center=true);
    }
}

module base() {

    // 4 wheels
    translate([77.5, 60, 47/2]) wheel();
    translate([-77.5, 60, 47/2]) wheel();
    translate([77.5, -60, 47/2]) wheel();
    translate([-77.5, -60, 47/2]) wheel();

    // front axe assemby - slightly longer
    translate([77.5-5, 0, 47/2]) color("gray") cube(size=[25, 103, 26], center=true);
    // rear axe assemby
    translate([-77.5, 0, 47/2]) color("gray") cube(size=[26, 97, 26], center=true);

    color("gray") translate ([0, 0, 12]) {

        // base plate
        linear_extrude(height = 2) base_plate();
        linear_extrude(height = 7) difference() {
            base_plate();
            offset(-2) base_plate();
        }

        // shaft
        translate ([0, 0, 23/2]) cube(size=[158, 12, 23], center=true);
        //shaft ribs
        translate ([14, 4, 23]) cube(size=[67, 2, 4], center=false);
        translate ([14, -6, 23]) cube(size=[67, 2, 4], center=false);
        translate ([0, 0, 23/2]) cube(size=[158, 12, 23], center=true);
        translate ([-81, 4, 23]) cube(size=[45, 2, 6], center=false);
        translate ([-81, -6, 23]) cube(size=[45, 2, 6], center=false);
        // servo
        linear_extrude(height = 15)  polygon([
            [29,0], [79,0],
            [79,-23], [70,-23],[49,-40],[29,-40]
        ]);

        // motor
        translate ([-79+30, -16, 23/2+2]) rotate([0, 90, 0]) cylinder(d=23, h=32, center=false);

        // gear
        translate ([-79+23, 0, 34/2]) rotate([0, 90, 0]) cylinder(d=34, h=6, center=false);

        // battery
        translate ([-5/2, 30/2+7, 16/2+2]) cube(size=[84, 30, 16], center=true);

        // battery holder
        translate ([-79+23, 20, 0]) cylinder(d=7, h=26, center=false);
        translate ([79-29, 20, 0]) cylinder(d=7, h=26, center=false);
        translate ([-5/2, 20, 22]) cube(size=[110, 13, 2], center=true);

        // front shocks
        translate ([162/2, 0, 0]) rotate([90, 0, 90]) linear_extrude(height = 16)
            polygon([[23,44],[18,48],[5,41],[-5,41],[-18,48],[-23,44], [-38,0],[38,0]]);

        // rear shocks
        translate ([-162/2-16, 0, 0]) rotate([90, 0, 90]) linear_extrude(height = 16)
            polygon([[25,48],[20,48],[5,38],[-5,38],[-20,48],[-25,48], [-38,0],[38,0]]);
    }
}

module base_plate() {
    polygon([
        [-79,25], [-70,25],[-54,40],[49,40],[70,23], [79,23],
        [79,-23], [70,-23],[49,-40],[-54,-40],[-70,-25], [-79,-25]
    ]);
}

// size is the XY plane size, height in Z
module hexagon(size, height) {
  boxWidth = size/1.75;
  for (r = [-60, 0, 60]) rotate([0,0,r]) cube([boxWidth, size, height], true);
}

module platform() {

    difference() {
    color("black") translate ([0, 0, 12+32+4]) difference() {
        union() {
            #linear_extrude(height = 3) intersection() {
                difference() {
                    offset(-10) offset(30) offset(-20)
                       polygon([
                         [-200,25], [-70,25],[-44,60],[34,60],[70,25], [200,25], // extra wide front
                         [200,-25], [70,-25],[34,-60],[-44,-60],[-70,-25], [-200,-25]
                       ]);

                    // central hole
                    translate ([-12.5, 0, 0])
                    offset(-5) offset(10) offset(-5) difference() {

                        polygon([
                         // left
                         [-45,-20], [-31,-37], // bevel [-45,-35],
                         [ 32,-37], [ 45,-27], // bevel [45,-35],

                         [48,-27], [48,27],

                         // right
                         [ 45, 27], [ 32, 37], // bevel [45,35],
                         [-31, 37], [-45, 20]  // bevel [-45,35]
                        ]);

                        //translate ([-45, -35, 0]) circle(r=7.5, center=true);
                        //translate ([-45,  35, 0]) circle(r=7.5, center=true);
                        //translate ([ 45, -35, 0]) circle(r=7.5, center=true);
                        //translate ([ 45,  35, 0]) circle(r=7.5, center=true);
                   }

                }
                square(size=[162,120], center=true); // cut off extra length
            }

            intersection() { translate ([0, 0, 100]) cube(size=[200,200,200], center=true); union() {
            // shock tower mount points
            // rear
            #translate ([-81, -25, 0]) {
                hull() {
                    cube(size=[4, 7, 12-3.5], center=false);
                    translate ([4/2, 3.5, 12-3.5]) rotate([90, 0, 90]) cylinder(d=7, h=4, center=true);
                }
                translate ([8/2, 3.5, 12-3.5-6]) rotate([90, 0, 90]) cylinder(d=6, h=8, center=true);
            }
            #translate ([-81, 25-7, 0]) {
                hull() {
                    cube(size=[4, 7, 12-3.5], center=false);
                    translate ([4/2, 7-3.5, 12-3.5]) rotate([90, 0, 90]) cylinder(d=7, h=4, center=true);
                }
                translate ([8/2, 7-3.5, 12-3.5-6]) rotate([90, 0, 90]) cylinder(d=6, h=8, center=true);
            }

            // front
            #translate ([81-6.5, -25, 0]) {
                cube(size=[6.5, 11, 4], center=false);
                translate ([6.5/2, 5.5, 4]) rotate([90, 0, 90]) cylinder(d=11, h=6.5, center=true);
            }
            #translate ([81-6.5, 25-11, 0]) {
                cube(size=[6.5, 11, 4], center=false);
                translate ([6.5/2, 5.5, 4]) rotate([90, 0, 90]) cylinder(d=11, h=6.5, center=true);
            }
            }}
        }

        // wire tie holes
        #translate ([-45, -45, 0]) cylinder(d=5, h=20, center=true);
        #translate ([-45,  45, 0]) cylinder(d=5, h=20, center=true);
        #translate ([-35, -45, 0]) cylinder(d=5, h=20, center=true);
        #translate ([-35,  45, 0]) cylinder(d=5, h=20, center=true);

        // esc power wires
        #hull() {
            translate ([48-12.5-5, 23, 0]) cylinder(d=6, h=20, center=true);
            translate ([54-12.5,   23, 0]) cylinder(d=6, h=20, center=true);
        }

        // esc motor wires
        #hull() {
            translate ([48-12.5-5, -23,   0]) cylinder(d=6, h=20, center=true);
            translate ([54-12.5,   -23+4, 0]) cylinder(d=6, h=20, center=true);
            translate ([54-12.5,   -23,   0]) cylinder(d=6, h=20, center=true);
            translate ([48-12.5,   -23+4, 0]) cylinder(d=6, h=20, center=true);
        }

        // space save
        #hull() {
            translate ([52, -10, 0]) cylinder(d=5, h=20, center=true);
            translate ([42, -10, 0]) cylinder(d=5, h=20, center=true);
            translate ([42,  10, 0]) cylinder(d=5, h=20, center=true);
            translate ([52,  10, 0]) cylinder(d=5, h=20, center=true);
        }

        // space save
        #hull() {
            translate ([-72, -10, 0]) cylinder(d=5, h=20, center=true);
            translate ([-67, -10, 0]) cylinder(d=5, h=20, center=true);
            translate ([-67,  10, 0]) cylinder(d=5, h=20, center=true);
            translate ([-72,  10, 0]) cylinder(d=5, h=20, center=true);
        }

        // board mount holes
        #translate ([-(45-2.5)-10,  (35-2.5), 2.5]) screw2x6bore();
        #translate ([-(45-2.5)-10, -(35-2.5), 2.5]) screw2x6bore();
        #translate ([ (45-2.5)-10,  (35-2.5), 2.5]) screw2x6bore();
        #translate ([ (45-2.5)-10, -(35-2.5), 2.5]) screw2x6bore();

        // mount holes
        // front
        // M3 hex nut in front H=2.4, Dmin = 5.4
        // left
        #translate ([81, 42.5/2-3/2, 8-2-3/2]) rotate([90, 0, 90]) cylinder(d=3, h=20, center=true);
        #translate ([81-4-5/2, 42.5/2-3/2, 8-2-3/2]) rotate([90, 90, 90]) hexagon(5.6, 6);
        // right
        #translate ([81,-42.5/2+3/2, 8-2-3/2]) rotate([90, 0, 90]) cylinder(d=3, h=20, center=true);
        #translate ([81-4-5/2,-42.5/2+3/2, 8-2-3/2]) rotate([90, 90, 90]) hexagon(5.6, 6);

        // rear
        // left
        #translate ([-81, 46.5/2-3/2, 12-2-3/2]) rotate([90, 0, 90]) cylinder(d=3, h=20, center=true);
        #translate ([-81,-46.5/2+3/2, 12-2-3/2-6]) rotate([90, 0, 90]) cylinder(d=3, h=12, center=true);
        // right
        #translate ([-81,-46.5/2+3/2, 12-2-3/2]) rotate([90, 0, 90]) cylinder(d=3, h=20, center=true);
        #translate ([-81, 46.5/2-3/2, 12-2-3/2-6]) rotate([90, 0, 90]) cylinder(d=3, h=12, center=true);
    }
    #arrangebottom(30)
    {
        hbaseholes(center=true, right=1, left=1);
        hbaseholes(center=true, right=0, left=1);
        hbaseholes(center=true, right=0, left=1);
        hbaseholes(center=true, right=1, left=0);
        hbaseholes(center=true, right=1, left=0);
    }
    // cage holes
    #cage(cut=true);

    //arrangebottom(45) hbaseholes();
    }
}

module board() {

    translate ([-12.5, 0, 47]) {
    // base
    color("yellow") cube(size=[90, 70, 1.2], center=true);

    // teensy
    color("green") translate ([-12, 0, 5]) cube(size=[63, 18, 10], center=true);

    // MPU-9250
    color("red") translate ([-24, 21, 5]) cube(size=[18.5, 19, 10], center=true);

    // servo conn
    color("black") translate ([27, -21, 1.5]) cube(size=[10, 7.5, 3], center=true);
    }
}

module esc() {
    color("green") cube(size=[36, 26, 2], center=true);
    color("black") translate ([36/2, 0, 0]) rotate([0, 90, 0]) cylinder(d=8, h=16, center=false);

    // esc support box ?
    // hcolor("black") translate ([0, 0, -11]) cube(size=[30, 20, 20], center=true);
}

module vsonar() {

    // vertical sonar
    translate ([0, -10, 45]) rotate([0, 90, 0]) hcsr04();

    // mount plate
    color("gray") translate ([1.5, -10, -6]) cube(size=[3, 20, 51], center=false);
    color("gray") translate ([-8.5, -10, -6]) cube(size=[10, 20, 5], center=false);

    // sonar ray
    //color("white") translate ([20+1000/2, 0, 22.5]) rotate([0, 90, 0]) cylinder(d1=40, d2=520,h=1000, center=true);
}

module hbaseholes(center = true, left = 2, right = 2)
{
    if (center) translate ([-5,    0, -15]) cylinder(d=3.2, h=15, center=false);

    if (left >= 1) translate ([-5,  9.5, -15]) cylinder(d=3.2, h=15, center=false);
    if (left >= 2) translate ([-5,  19, -15]) cylinder(d=3.2, h=15, center=false);

    if (right >= 1) translate ([-5, -9.5, -15]) cylinder(d=3.2, h=15, center=false);
    if (right >= 2) translate ([-5, -19, -15]) cylinder(d=3.2, h=15, center=false);
}

module hmount() {
    // mount plate
    color ("gray") {

        // front
        difference() {
            translate ([1.5, -48/2, -6]) #hull() {
                cube(size=[3, 48, 25], center=false);
                translate ([0, 48-3, 25]) rotate([90, 0, 90]) cylinder(r=3, h=3, center=false);
                translate ([0, 3, 25]) rotate([90, 0, 90]) cylinder(r=3, h=3, center=false);
            }

            translate ([0, -45/2, 0]) rotate([90, 0, 90]) {

                // sonar
                translate([45/2-(42-16)/2,18/2+1,1.3]) cylinder(d=17, h=15);
                translate([45/2+(42-16)/2,18/2+1,1.3]) cylinder(d=17, h=15);

                //xtal(s)
                hull () {
                    translate([45/2-3.25,20-3.5,1.3])
                    {
                        translate([0,0,0]) cylinder(d=6, h=5);
                        translate([6.5,0,0]) cylinder(d=6, h=5);
                    }
                    translate([45/2-3.25, 4,1.3]) hull()
                    {
                        //translate([0,0,0]) cylinder(d=6, h=5);
                        //translate([6.5,0,0]) cylinder(d=6, h=5);
                        translate([0,-2,0]) cylinder(d=6, h=5);
                        translate([6.5,-2,0]) cylinder(d=6, h=5);
                    }
                }

                // screws
                translate([   1.0,    1.0, 4.5-0.5]) screw2x6bore();
                translate([45-1.0, 20-1.5, 4.5-0.5]) screw2x6bore();
                translate([45-1.0,    1.0, 4.5-0.5]) screw2x6bore();
                translate([   1.0, 20-1.5, 4.5-0.5]) screw2x6bore();
            }

            translate ([3, 0, 10])
                cube(size=[5, 20, 11], center=true);
        }

        //base
        difference() {
            #hull() {
                translate ([-3.5, -48/2, -6]) cube(size=[5, 48, 5], center=false);
                translate ([-3.5, -48/2+5, -6]) cylinder(r=5, h=5, center=false);
                translate ([-3.5, 48/2-5, -6]) cylinder(r=5, h=5, center=false);
            }
            hbaseholes();
        }
    }
}

module screw2x6bore() {
    rotate([180, 0, 0]) {
        cylinder(d=2.2, h=6);
        translate ([0, 0, -1.3])
            cylinder(d1=2*3.6, d2=0, h=2*1.3);
    }
}

module hsonar() {

    // horizontal sonar
    translate ([0, -45/2, 0]) rotate([90, 0, 90]) hcsr04();

    hmount();

    // sonar ray
    //color("white") translate ([20+1000/2, 0, 10]) rotate([0, 90, 0]) cylinder(d1=40, d2=520,h=1000, center=true);
}

module barbox(p1, p2, s=1, r=1) {

    a = [p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2]];
    l = norm(a);
    b = [a[0]/l, a[1]/l, a[2]/l];

    c = cross([0,0,1], b);

    az = atan2(c[0], c[1]);
    ax = acos(b[2]);

    o = s/2-r;
    s1 = s-2*r;

    translate(p1)
        rotate([0, 0, -az])
           rotate([0, ax, 0])
               translate([0, 0, l/2]) {
                    cube(size=[s1, s, l], center=true);
                    cube(size=[s, s1, l], center=true);

                    for (x=[o, -o])
                        for (y=[o, -o]) {
                            translate([x,y,0]) cylinder(r=r, h=l, center=true);
                            for (z=[l/2, -l/2]) {
                                translate([x,y,z]) sphere(r=r, center=true);
                            }
                        }

                    for (z=[l/2, -l/2]) {
                        translate([0,0,z]) cube(size=[s1, s1, 2*r], center=true);

                        translate([ 0, o, z]) rotate([0,90,0]) cylinder(r=r, h=s1, center=true);
                        translate([ 0,-o, z]) rotate([0,90,0]) cylinder(r=r, h=s1, center=true);
                        translate([ o, 0, z]) rotate([90,0,0]) cylinder(r=r, h=s1, center=true);
                        translate([-o, 0, z]) rotate([90,0,0]) cylinder(r=r, h=s1, center=true);
                    }

               }
}

module bar(p1, p2, s=1) {

    a = [p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2]];
    l = norm(a);
    b = [a[0]/l, a[1]/l, a[2]/l];

    c = cross([0,0,1], b);

    az = atan2(c[0], c[1]);
    ax = acos(b[2]);

    translate(p1) sphere(d=s, center=true);
    translate(p2) sphere(d=s, center=true);

    translate(p1)
        rotate([0, 0, -az])
           rotate([0, ax, 0])
               cylinder(d=s, h=l, center=false);
}

module ball8(p1, s=1, r=1) {

    o = s/2-r;

    translate(p1)
        for (x=[o, -o])
            for (y=[o, -o])
                for (z=[o, -o])
                    translate([x,y,z])
                        sphere(r=r, center=true);
}

module skew(p1, p2) { // TODO - not working

    a = [p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2]];
    b = [a[0]/a[2], a[1]/a[2]];

    matrix = [
        [ 1, 0, b[1], 0 ],
        [ 0, 1, b[2], 0 ],
        [ 0, 0, 1, 0 ],
        [ 0, 0, 0, 1 ]
    ];

    translate(p1)
        multmatrix(matrix)
                children();
}

module cage_leg(p1, p2, d, db, r)
{
//    bar(p1, p2, d);

    hull() {
        ball8(p2, d, r);
        translate([0, 0, -d/2]) translate(p1) difference() {
            sphere(d=db, center=true);
            translate([0, 0, -db/2]) cube(size=[db, db, db], center=true);
        }
    }
}

module cage_pin(p1, p2, d, pd, ph, cut)
{
    if (cut)
    {
        bar(p1, p2, d+0.5);
    }
    else
    difference() {
        bar(p1, p2, d);

        translate ([0,0,-ph])
            translate (p1)
                rotate([90,0,0])
                    cylinder(d=pd, h=2*d, center=true);
    }
}

module lcd_mount(p1, x1, x2)
{
    translate(p1) difference() {
        #translate([(x1-x2)/2,0,-1]) cube(size=[x1+x2, 8, 2], center=true);
        #cylinder(d=2, h=6, center=true);
    }
}

module cage(cut = false)
{

    d = 4;
    r1 = 1;
    n = 4;
    db = 6;
    hb = d;
    pd = 1;
    ph = d/2 + 3 /*platform*/+ 1/*freespace*/;

    // measurements
    top = 82;

    top_side = 30;

    top_front = 20;
    top_rear = -40;

    top_esc = top_front-26/*esc size*/+d;
    top_lcd = top_rear+27/*lcd size*/+d+1;

    bottom = 51/*platform top*/+d/2;

    bottom_front = 27;
    bottom_rear = -50;

    bottom_front_side = 40;
    bottom_rear_side = 40;

    pin = 8;
    pin_base = bottom - pin;

    // points
    top_front_left = [top_front, top_side, top];
    top_front_right = [top_front, -top_side, top];

    top_esc_left = [top_esc, top_side, top];
    top_esc_right = [top_esc, -top_side, top];

    top_lcd_left = [top_lcd, top_side, top];
    top_lcd_right = [top_lcd, -top_side, top];

    top_rear_left = [top_rear, top_side, top];
    top_rear_right = [top_rear, -top_side, top];

    //mid_front_left = [(top_front+bottom_front)/2, (top_side+bottom_front_side)/2, (top+bottom)/2];
    //mid_front_right = [mid_front_left[0], -mid_front_left[1], mid_front_left[2]];

    bottom_front_left = [bottom_front, bottom_front_side, bottom];
    bottom_front_right = [bottom_front, -bottom_front_side, bottom];

    bottom_rear_left = [bottom_rear, bottom_rear_side, bottom];
    bottom_rear_right = [bottom_rear, -bottom_rear_side, bottom];

    pin_front_left = [bottom_front, bottom_front_side, pin_base];
    pin_front_right = [bottom_front, -bottom_front_side, pin_base];

    pin_rear_left = [bottom_rear, bottom_rear_side, pin_base];
    pin_rear_right = [bottom_rear, -bottom_rear_side, pin_base];

    // bars
    if (!cut)
    {
        barbox(top_front_left, top_front_right, d, r1);
        barbox(top_rear_left, top_rear_right, d, r1);
        barbox(top_front_left, top_rear_left, d, r1);
        barbox(top_front_right, top_rear_right, d, r1);

        barbox(top_esc_left, top_esc_right, d, r1);
        barbox(top_lcd_left, top_lcd_right, d, r1);

        lcd_mount([top_rear+d/2+2.5+23+0.5,  23/2, top+d/2], 4, 3);
        lcd_mount([top_rear+d/2+2.5+23+0.5, -23/2, top+d/2], 4, 3);
        lcd_mount([top_rear+d/2+2.5+0.5,     23/2, top+d/2], 3, 4);
        lcd_mount([top_rear+d/2+2.5+0.5,    -23/2, top+d/2], 3, 4);

        //bar(mid_front_left, mid_front_right, d);  // unprintable

        cage_leg(bottom_front_left, top_front_left, d, db, r1);
        cage_leg(bottom_front_right, top_front_right, d, db, r1);
        cage_leg(bottom_rear_left, top_rear_left, d, db, r1);
        cage_leg(bottom_rear_right, top_rear_right, d, db, r1);
    }

    cage_pin(bottom_front_left, pin_front_left, d, pd, ph, cut);
    cage_pin(bottom_front_right, pin_front_right, d, pd, ph, cut);
    cage_pin(bottom_rear_left, pin_rear_left, d, pd, ph, cut);
    cage_pin(bottom_rear_right, pin_rear_right, d, pd, ph, cut);
}

module car()
{
    base();
    platform();
    board();
    color("white") cage();

    translate ([9, -8, 79]) rotate([0, 0, 90]) esc();
}

module arrangebottom(a) {
    translate ([68, 0, 57]) if ($children == 1) children(); else children(0);

    translate ([45, 42, 57]) rotate([0, 0, a]) if ($children == 1) children(); else children(1);
    translate ([-5, 45, 57]) rotate([0, 0, 2*a]) if ($children == 1) children(); else children(2);

    translate ([45, -42, 57]) rotate([0, 0, -a]) if ($children == 1) children(); else children(3);
    translate ([-5, -45, 57]) rotate([0, 0, -2*a]) if ($children == 1) children(); else children(4);
}

module lcd1602() {
translate([-15,0,78]) difference() {
    union() {
        translate([0,0,5+8/2]) color("blue") cube(size=[27, 72, 8], center=true);
        translate([0,0,4+1/2]) color("green") cube(size=[36, 80, 1], center=true);
    }
    translate([ 31/2, 75/2,0]) cylinder(d=2.5, h=20, center=false);
    translate([-31/2, 75/2,0]) cylinder(d=2.5, h=20, center=false);
    translate([ 31/2,-75/2,0]) cylinder(d=2.5, h=20, center=false);
    translate([-31/2,-75/2,0]) cylinder(d=2.5, h=20, center=false);
}
}

module lcd() {
    color("blue") translate([-40+2+27.5/2+0.5,0,81]) cube(size=[27.5, 27.5, 2], center=true);
}

module fullb() {
    car();
    arrangebottom(30) hsonar();
    cage();
    lcd();
}

//car();

//cage();

//board();
//platform();

//fullb();

//barbox([0,0,0], [0,0,50], 10, 3);

//translate ([0, 0, 4.5]) rotate([0, 90, 0]) hmount();

/* // small front
intersection() {
    platform();
    translate ([80, -15, 0]) cube(size=[40, 35, 400], center=true);
}*/

/* // full front
intersection() {
    platform();
    #translate ([100+20, 0, 0]) cube(size=[200, 200, 400], center=true);
}*/

/* // rear
intersection() {
    platform();
    translate ([-80, 0, 0]) cube(size=[20, 200, 400], center=true);
}*/

//screw2x6bore();

//rotate([0,0,180]) projection(cut=true) translate ([0, 0, -49]) platform();
//projection() translate ([0, 0, 10]) hsonar();

translate([0,0,90]) rotate([180,0,0]) cage();

//$fs = 0.1;
//$fa = 5;
$fs = 0.25;
$fa = 8;

use <hcsr04.scad>

module wheel() {
    color("black") rotate([90, 90, 0]) difference() {
        #cylinder(d=47, h=23, center=true);
        cylinder(d=30, h=26, center=true);
    }
}

module base() {

    // 4 wheels
    translate([77.5, 60, 47/2]) wheel();
    translate([-77.5, 60, 47/2]) wheel();
    translate([77.5, -60, 47/2]) wheel();
    translate([-77.5, -60, 47/2]) wheel();

    // front axe assemby - slightly longer
    translate([77.5-5, 0, 47/2]) color("gray") cube(size=[25, 103, 26], center=true);
    // rear axe assemby
    translate([-77.5, 0, 47/2]) color("gray") cube(size=[26, 97, 26], center=true);

    color("gray") translate ([0, 0, 12]) {

        // base plate
        linear_extrude(height = 2) base_plate();
        linear_extrude(height = 7) difference() {
            base_plate();
            offset(-2) base_plate();
        }

        // shaft
        translate ([0, 0, 23/2]) cube(size=[158, 12, 23], center=true);
        //shaft ribs
        translate ([14, 4, 23]) cube(size=[67, 2, 4], center=false);
        translate ([14, -6, 23]) cube(size=[67, 2, 4], center=false);
        translate ([0, 0, 23/2]) cube(size=[158, 12, 23], center=true);
        translate ([-81, 4, 23]) cube(size=[45, 2, 6], center=false);
        translate ([-81, -6, 23]) cube(size=[45, 2, 6], center=false);
        // servo
        linear_extrude(height = 15)  polygon([
            [29,0], [79,0],
            [79,-23], [70,-23],[49,-40],[29,-40]
        ]);

        // motor
        translate ([-79+30, -16, 23/2+2]) rotate([0, 90, 0]) cylinder(d=23, h=32, center=false);

        // gear
        translate ([-79+23, 0, 34/2]) rotate([0, 90, 0]) cylinder(d=34, h=6, center=false);

        // battery
        translate ([-5/2, 30/2+7, 16/2+2]) cube(size=[84, 30, 16], center=true);

        // battery holder
        translate ([-79+23, 20, 0]) cylinder(d=7, h=26, center=false);
        translate ([79-29, 20, 0]) cylinder(d=7, h=26, center=false);
        translate ([-5/2, 20, 22]) cube(size=[110, 13, 2], center=true);

        // front shocks
        translate ([162/2, 0, 0]) rotate([90, 0, 90]) linear_extrude(height = 16)
            polygon([[23,44],[18,48],[5,41],[-5,41],[-18,48],[-23,44], [-38,0],[38,0]]);

        // rear shocks
        translate ([-162/2-16, 0, 0]) rotate([90, 0, 90]) linear_extrude(height = 16)
            polygon([[25,48],[20,48],[5,38],[-5,38],[-20,48],[-25,48], [-38,0],[38,0]]);
    }
}

module base_plate() {
    polygon([
        [-79,25], [-70,25],[-54,40],[49,40],[70,23], [79,23],
        [79,-23], [70,-23],[49,-40],[-54,-40],[-70,-25], [-79,-25]
    ]);
}

// size is the XY plane size, height in Z
module hexagon(size, height) {
  boxWidth = size/1.75;
  for (r = [-60, 0, 60]) rotate([0,0,r]) cube([boxWidth, size, height], true);
}

module platform() {

    difference() {
    color("black") translate ([0, 0, 12+32+4]) difference() {
        union() {
            #linear_extrude(height = 3) intersection() {
                difference() {
                    offset(-10) offset(30) offset(-20)
                       polygon([
                         [-200,25], [-70,25],[-44,60],[34,60],[70,25], [200,25], // extra wide front
                         [200,-25], [70,-25],[34,-60],[-44,-60],[-70,-25], [-200,-25]
                       ]);

                    // central hole
                    translate ([-12.5, 0, 0])
                    offset(-5) offset(10) offset(-5) difference() {

                        polygon([
                         // left
                         [-45,-20], [-31,-37], // bevel [-45,-35],
                         [ 32,-37], [ 45,-27], // bevel [45,-35],

                         [48,-27], [48,27],

                         // right
                         [ 45, 27], [ 32, 37], // bevel [45,35],
                         [-31, 37], [-45, 20]  // bevel [-45,35]
                        ]);

                        //translate ([-45, -35, 0]) circle(r=7.5, center=true);
                        //translate ([-45,  35, 0]) circle(r=7.5, center=true);
                        //translate ([ 45, -35, 0]) circle(r=7.5, center=true);
                        //translate ([ 45,  35, 0]) circle(r=7.5, center=true);
                   }

                }
                square(size=[162,120], center=true); // cut off extra length
            }

            intersection() { translate ([0, 0, 100]) cube(size=[200,200,200], center=true); union() {
            // shock tower mount points
            // rear
            #translate ([-81, -25, 0]) {
                hull() {
                    cube(size=[4, 7, 12-3.5], center=false);
                    translate ([4/2, 3.5, 12-3.5]) rotate([90, 0, 90]) cylinder(d=7, h=4, center=true);
                }
                translate ([8/2, 3.5, 12-3.5-6]) rotate([90, 0, 90]) cylinder(d=6, h=8, center=true);
            }
            #translate ([-81, 25-7, 0]) {
                hull() {
                    cube(size=[4, 7, 12-3.5], center=false);
                    translate ([4/2, 7-3.5, 12-3.5]) rotate([90, 0, 90]) cylinder(d=7, h=4, center=true);
                }
                translate ([8/2, 7-3.5, 12-3.5-6]) rotate([90, 0, 90]) cylinder(d=6, h=8, center=true);
            }

            // front
            #translate ([81-6.5, -25, 0]) {
                cube(size=[6.5, 11, 4], center=false);
                translate ([6.5/2, 5.5, 4]) rotate([90, 0, 90]) cylinder(d=11, h=6.5, center=true);
            }
            #translate ([81-6.5, 25-11, 0]) {
                cube(size=[6.5, 11, 4], center=false);
                translate ([6.5/2, 5.5, 4]) rotate([90, 0, 90]) cylinder(d=11, h=6.5, center=true);
            }
            }}
        }

        // wire tie holes
        #translate ([-45, -45, 0]) cylinder(d=5, h=20, center=true);
        #translate ([-45,  45, 0]) cylinder(d=5, h=20, center=true);
        #translate ([-35, -45, 0]) cylinder(d=5, h=20, center=true);
        #translate ([-35,  45, 0]) cylinder(d=5, h=20, center=true);

        // esc power wires
        #hull() {
            translate ([48-12.5-5, 23, 0]) cylinder(d=6, h=20, center=true);
            translate ([54-12.5,   23, 0]) cylinder(d=6, h=20, center=true);
        }

        // esc motor wires
        #hull() {
            translate ([48-12.5-5, -23,   0]) cylinder(d=6, h=20, center=true);
            translate ([54-12.5,   -23+4, 0]) cylinder(d=6, h=20, center=true);
            translate ([54-12.5,   -23,   0]) cylinder(d=6, h=20, center=true);
            translate ([48-12.5,   -23+4, 0]) cylinder(d=6, h=20, center=true);
        }

        // space save
        #hull() {
            translate ([52, -10, 0]) cylinder(d=5, h=20, center=true);
            translate ([42, -10, 0]) cylinder(d=5, h=20, center=true);
            translate ([42,  10, 0]) cylinder(d=5, h=20, center=true);
            translate ([52,  10, 0]) cylinder(d=5, h=20, center=true);
        }

        // space save
        #hull() {
            translate ([-72, -10, 0]) cylinder(d=5, h=20, center=true);
            translate ([-67, -10, 0]) cylinder(d=5, h=20, center=true);
            translate ([-67,  10, 0]) cylinder(d=5, h=20, center=true);
            translate ([-72,  10, 0]) cylinder(d=5, h=20, center=true);
        }

        // board mount holes
        translate ([-(45-2.5)-10,  (35-2.5), 2.5]) screw2x6bore();
        translate ([-(45-2.5)-10, -(35-2.5), 2.5]) screw2x6bore();
        translate ([ (45-2.5)-10,  (35-2.5), 2.5]) screw2x6bore();
        translate ([ (45-2.5)-10, -(35-2.5), 2.5]) screw2x6bore();

        // mount holes
        // front
        // M3 hex nut in front H=2.4, Dmin = 5.4
        // left
        #translate ([81, 42.5/2-3/2, 8-2-3/2]) rotate([90, 0, 90]) cylinder(d=3, h=20, center=true);
        #translate ([81-4-5/2, 42.5/2-3/2, 8-2-3/2]) rotate([90, 90, 90]) hexagon(5.6, 6);
        // right
        #translate ([81,-42.5/2+3/2, 8-2-3/2]) rotate([90, 0, 90]) cylinder(d=3, h=20, center=true);
        #translate ([81-4-5/2,-42.5/2+3/2, 8-2-3/2]) rotate([90, 90, 90]) hexagon(5.6, 6);

        // rear
        // left
        #translate ([-81, 46.5/2-3/2, 12-2-3/2]) rotate([90, 0, 90]) cylinder(d=3, h=20, center=true);
        #translate ([-81,-46.5/2+3/2, 12-2-3/2-6]) rotate([90, 0, 90]) cylinder(d=3, h=12, center=true);
        // right
        #translate ([-81,-46.5/2+3/2, 12-2-3/2]) rotate([90, 0, 90]) cylinder(d=3, h=20, center=true);
        #translate ([-81, 46.5/2-3/2, 12-2-3/2-6]) rotate([90, 0, 90]) cylinder(d=3, h=12, center=true);
    }
    arrangebottom(30)
    {
        hbaseholes(center=true, right=1, left=1);
        hbaseholes(center=true, right=0, left=1);
        hbaseholes(center=true, right=0, left=1);
        hbaseholes(center=true, right=1, left=0);
        hbaseholes(center=true, right=1, left=0);
    }
    //arrangebottom(45) hbaseholes();
    }
}

module board() {

    translate ([-12.5, 0, 47]) {
    // base
    color("yellow") cube(size=[90, 70, 1.2], center=true);

    // teensy
    color("green") translate ([-12, 0, 5]) cube(size=[63, 18, 10], center=true);

    // MPU-9250
    color("red") translate ([-24, 21, 5]) cube(size=[18.5, 19, 10], center=true);

    // servo conn
    color("black") translate ([27, -21, 1.5]) cube(size=[10, 7.5, 3], center=true);
    }
}

module esc() {
    color("green") cube(size=[36, 26, 2], center=true);
    color("black") translate ([36/2, 0, 0]) rotate([0, 90, 0]) cylinder(d=8, h=16, center=false);

    // esc support box ?
    // hcolor("black") translate ([0, 0, -11]) cube(size=[30, 20, 20], center=true);
}

module vsonar() {

    // vertical sonar
    translate ([0, -10, 45]) rotate([0, 90, 0]) hcsr04();

    // mount plate
    color("gray") translate ([1.5, -10, -6]) cube(size=[3, 20, 51], center=false);
    color("gray") translate ([-8.5, -10, -6]) cube(size=[10, 20, 5], center=false);

    // sonar ray
    //color("white") translate ([20+1000/2, 0, 22.5]) rotate([0, 90, 0]) cylinder(d1=40, d2=520,h=1000, center=true);
}

module hbaseholes(center = true, left = 2, right = 2)
{
    if (center) translate ([-5,    0, -15]) cylinder(d=3.2, h=15, center=false);

    if (left >= 1) translate ([-5,  9.5, -15]) cylinder(d=3.2, h=15, center=false);
    if (left >= 2) translate ([-5,  19, -15]) cylinder(d=3.2, h=15, center=false);

    if (right >= 1) translate ([-5, -9.5, -15]) cylinder(d=3.2, h=15, center=false);
    if (right >= 2) translate ([-5, -19, -15]) cylinder(d=3.2, h=15, center=false);
}

module hmount() {
    // mount plate
    color ("gray") {

        // front
        difference() {
            translate ([1.5, -48/2, -6]) #hull() {
                cube(size=[3, 48, 25], center=false);
                translate ([0, 48-3, 25]) rotate([90, 0, 90]) cylinder(r=3, h=3, center=false);
                translate ([0, 3, 25]) rotate([90, 0, 90]) cylinder(r=3, h=3, center=false);
            }

            translate ([0, -45/2, 0]) rotate([90, 0, 90]) {

                // sonar
                translate([45/2-(42-16)/2,18/2+1,1.3]) cylinder(d=17, h=15);
                translate([45/2+(42-16)/2,18/2+1,1.3]) cylinder(d=17, h=15);

                //xtal(s)
                hull () {
                    translate([45/2-3.25,20-3.5,1.3])
                    {
                        translate([0,0,0]) cylinder(d=6, h=5);
                        translate([6.5,0,0]) cylinder(d=6, h=5);
                    }
                    translate([45/2-3.25, 4,1.3]) hull()
                    {
                        //translate([0,0,0]) cylinder(d=6, h=5);
                        //translate([6.5,0,0]) cylinder(d=6, h=5);
                        translate([0,-2,0]) cylinder(d=6, h=5);
                        translate([6.5,-2,0]) cylinder(d=6, h=5);
                    }
                }

                // screws
                translate([   1.0,    1.0, 4.5-0.5]) screw2x6bore();
                translate([45-1.0, 20-1.5, 4.5-0.5]) screw2x6bore();
                translate([45-1.0,    1.0, 4.5-0.5]) screw2x6bore();
                translate([   1.0, 20-1.5, 4.5-0.5]) screw2x6bore();
            }

            translate ([3, 0, 10])
                cube(size=[5, 20, 11], center=true);
        }

        //base
        difference() {
            #hull() {
                translate ([-3.5, -48/2, -6]) cube(size=[5, 48, 5], center=false);
                translate ([-3.5, -48/2+5, -6]) cylinder(r=5, h=5, center=false);
                translate ([-3.5, 48/2-5, -6]) cylinder(r=5, h=5, center=false);
            }
            hbaseholes();
        }
    }
}

module screw2x6bore() {
    rotate([180, 0, 0]) {
        cylinder(d=2.2, h=6);
        translate ([0, 0, -1.3])
            cylinder(d1=2*3.6, d2=0, h=2*1.3);
    }
}

module hsonar() {

    // horizontal sonar
    translate ([0, -45/2, 0]) rotate([90, 0, 90]) hcsr04();

    hmount();

    // sonar ray
    //color("white") translate ([20+1000/2, 0, 10]) rotate([0, 90, 0]) cylinder(d1=40, d2=520,h=1000, center=true);
}

/*skew takes an array of six koef:
 *x along y
 *x along z
 *y along x
 *y along z
 *z along x
 *z along y
 */

module skew(dims) {
    matrix = [
	    [ 1, dims[0], dims[1], 0 ],
	    [ dims[2], 1, dims[4], 0 ],
	    [ dims[5], dims[3], 1, 0 ],
	    [ 0, 0, 0, 1 ]
    ];

    multmatrix(matrix) children();
}

module cagetop()
{
            for (x = [-20, 0, 20, 40]) translate([x-10, 0, 81]) cube(size=[2, 60, 2], center=true);
            for (y = [-30, 0, 30])    translate([0, y, 81])  cube(size=[60, 2, 2], center=true);

            translate([43, 0, 67]) skew([0, -0.9, 0, 0, 0, 0]) cube(size=[2, 2, 30], center=true);

            // front sides
            translate([33, -33, 67]) skew([0, -0.2, 0, 0, 0.2, 0]) cube(size=[2, 2, 30], center=true);
            translate([33,  33, 67]) skew([0, -0.2, 0, 0, -0.2, 0]) cube(size=[2, 2, 30], center=true);

            // rear
            translate([-42, -34.5, 67]) skew([0, 0.8, 0, 0, 0.3, 0]) cube(size=[2, 2, 30], center=true);
            translate([-42,  34.5, 67]) skew([0, 0.8, 0, 0, -0.3, 0]) cube(size=[2, 2, 30], center=true);
}

module cage(round=false)
{
    if (round) minkowski() {
        cagetop();
        sphere(r=1);
    } else
        cagetop();

    #translate([ 36,  36, 45]) cylinder(d=3, h=7, center=false);
    #translate([ 36, -36, 45]) cylinder(d=3, h=7, center=false);

    #translate([-54, -39, 45]) cylinder(d=3, h=7, center=false);
    #translate([-54,  39, 45]) cylinder(d=3, h=7, center=false);
}

module car()
{
    base();
    platform();
    board();
    color("white") cage();

    translate ([30, -5, 60]) rotate([90, 0, 90]) esc();
}

module arrangebottom(a) {
    translate ([68, 0, 57]) if ($children == 1) children(); else children(0);

    translate ([45, 42, 57]) rotate([0, 0, a]) if ($children == 1) children(); else children(1);
    translate ([-5, 45, 57]) rotate([0, 0, 2*a]) if ($children == 1) children(); else children(2);

    translate ([45, -42, 57]) rotate([0, 0, -a]) if ($children == 1) children(); else children(3);
    translate ([-5, -45, 57]) rotate([0, 0, -2*a]) if ($children == 1) children(); else children(4);
}

module lcd1602() {
translate([-15,0,78]) difference() {
    union() {
        translate([0,0,5+8/2]) color("blue") cube(size=[27, 72, 8], center=true);
        #translate([0,0,4+1/2]) color("green") cube(size=[36, 80, 1], center=true);
    }
    #translate([ 31/2, 75/2,0]) cylinder(d=2.5, h=20, center=false);
    #translate([-31/2, 75/2,0]) cylinder(d=2.5, h=20, center=false);
    #translate([ 31/2,-75/2,0]) cylinder(d=2.5, h=20, center=false);
    #translate([-31/2,-75/2,0]) cylinder(d=2.5, h=20, center=false);
}
}

module fullb() {
    car();
    arrangebottom(30) hsonar();
}

//car();

//cage();

//board();
//platform();

fullb();

//translate ([0, 0, 4.5]) rotate([0, 90, 0]) hmount();

/* // small front
intersection() {
    platform();
    translate ([80, -15, 0]) cube(size=[40, 35, 400], center=true);
}*/

/* // full front
intersection() {
    platform();
    #translate ([100+20, 0, 0]) cube(size=[200, 200, 400], center=true);
}*/

/* // rear
intersection() {
    platform();
    translate ([-80, 0, 0]) cube(size=[20, 200, 400], center=true);
}*/

//screw2x6bore();

//rotate([0,0,180]) projection(cut=true) translate ([0, 0, -49]) platform();
//projection() translate ([0, 0, 10]) hsonar();

//translate([0,0,80]) rotate([180,0,0]) cage(true);


removed unused parameter

removed unused parameter

w=119;
s=21;
h=2.5;

module wedge(width, span, height)
{
  polyhedron(
    points=[
             [0, 0, 0],
             [span, 0, 0],
             [span, width, 0],
             [0, width, 0],
             [0, width, height],
             [span, width, height],
           ],
    faces=[
            // bottom
            [0,1,2],
            [2,3,0],
            // sides
            [5,2,1],
            [0,3,4],
            // back
            [3,2,4],
            [5,4,2],
            // top
            [0,4,5],
            [5,1,0],
          ]
   );
};

module fence(width, height)
{
  cube([width, 119, height-h]);
  translate([0,0,1])
    wedge(width=w, span=1, height=h);
}

module support()
{
  translate([1,0,0])
  {
    difference()
    {
      union()
      {
        wedge(width=w, span=s, height=h);

        // rounded ending
        translate([s/2, w, 0])
          difference()
          {
            cylinder(r=s/2, h=h);
            translate([-s/2, -s/2*2, 0])
              cube([s, s, h]);
          }
      }

      // screw hole
      translate([s/2, w-8/2, 0])
        cylinder(r=8/2, h=h);
    }
  }

  // side walls
  for(i=[0, s+1])
    translate(i*[1,0,0])
      fence(width=1, height=h+2);
}

support();

w=119;
s=21;
h=2.5;

module wedge(width, span, height)
{
  polyhedron(
    points=[
             [0, 0, 0],
             [span, 0, 0],
             [span, width, 0],
             [0, width, 0],
             [0, width, height],
             [span, width, height],
           ],
    faces=[
            // bottom
            [0,1,2],
            [2,3,0],
            // sides
            [5,2,1],
            [0,3,4],
            // back
            [3,2,4],
            [5,4,2],
            // top
            [0,4,5],
            [5,1,0],
          ]
   );
};

module fence(width, height)
{
  cube([width, 119, height-h]);
  translate([0,0,1])
    wedge(width=w, span=1, height=h);
}

module support()
{
  translate([1,0,0])
  {
    difference()
    {
      union()
      {
        wedge(width=w, span=s, height=h);

        // rounded ending
        translate([s/2, w, 0])
          difference()
          {
            cylinder(r=s/2, h=h);
            translate([-s/2, -s/2*2, 0])
              cube([s, s, h]);
          }
      }

      // screw hole
      translate([s/2, w-8/2, 0])
        cylinder(r=8/2, h=h);
    }
  }

  // side walls
  for(i=[0, s+1])
    translate(i*[1,0,0])
      fence(width=1, height=h+2);
}

support(2.5);


updating 'dingy' with proper dimensions

updating 'dingy' with proper dimensions

// licensed under CC0
//
// still a work in progress.
// the dimensions need to be confirmed.
// the 'dingy' especially needs to be confirmed.
//

module saw_end_linkage( base_length,
                  width,
                  saw_h,
                  circle_d_mid) {
  difference() {
    union() {
      square([base_length, width], center=true);
      polygon([[-base_length/2.0,width/2],
               [-base_length/2.0 - saw_h, 0],
               [-base_length/2.0,-width/2]]);
      polygon([[ base_length/2.0,width/2],
               [ base_length/2.0 + saw_h, 0],
               [ base_length/2.0,-width/2]]);
    }

    translate([0,0]) circle(d=circle_d_mid);
  }
}

// center_hole_p from circle end of base edge
//
module circle_saw_end_linkage( base_length,
                  width,
                  saw_h,
                  center_hole_p,
                  circle_d_left,
                  circle_d_mid) {
  difference() {
    union() {
      square([base_length, width], center=true);
      translate([-base_length/2,0]) circle(d=width);
      polygon([[base_length/2.0,width/2],
               [base_length/2.0 + saw_h, 0],
               [base_length/2.0,-width/2]]);
    }
    translate([-base_length/2,0]) circle(d=circle_d_left);
    translate([-(base_length/2.0) + center_hole_p ,0]) circle(d=circle_d_mid);
  }
}

module circle_end_linkage( base_length,
                  width,
                  circle_d_left,
                  circle_d_mid,
                  circle_d_right) {

  difference() {
    union() {
      square([base_length, width], center=true);
      translate([-base_length/2,0]) circle(d=width);
      translate([ base_length/2,0]) circle(d=width);
    }

    translate([-base_length/2,0]) circle(d=circle_d_left);
    translate([0,0]) circle(d=circle_d_mid);
    translate([ base_length/2,0]) circle(d=circle_d_right);
  }

}

module dingy(base_length,
             width,
             circle_d,
             hole_l_a,
             hole_w_a,
             hole_l_b,
             hole_w_b) {
  difference() {
    union() {
      square([base_length,width], center=true);
      translate([base_length/2,0]) circle(d=width);
    }
    translate([base_length/2,0]) circle(d=circle_d);
    translate([-base_length/2.0 + 4.35 + hole_l_a/2, 0])
      square([hole_l_a, hole_w_a], center=true);
    translate([-base_length/2.0 + 4.35 + hole_l_a + hole_l_b/2,0, 0])
      square([hole_l_b, hole_w_b], center=true);
    translate([-base_length/2.0 + 4.35 + hole_l_a + hole_l_b, 0])
      circle(d=hole_w_b);
  }
}

module linkage_cross(base_length,
                     width,
                     tab_length,
                     tab_width,
                     square_hole_length,
                     square_hole_width) {
  difference() {
    union() {
      square([base_length, width], center=true);
      translate([base_length/2 + tab_length/2, 0])
        square([tab_length, tab_width], center=true);
      translate([-(base_length/2 + tab_length/2), 0])
        square([tab_length, tab_width], center=true);
    }
    square([square_hole_length, square_hole_width], center=true);
  }
}

// a2, f2
w=18.75;
l=247-w;
translate([0, 0*w]) circle_end_linkage(l, w, 6.5, 6.5, 9.15);
translate([0, 2*w]) circle_end_linkage(l, w, 6.5, 6.5, 9.15);

// b1, b3
translate([0, 4*w]) circle_end_linkage(l, w, 6.5, 6.5, 6.5);
translate([0, 6*w]) circle_end_linkage(l, w, 6.5, 6.5, 6.5);

// d1, d3, c2
translate([0, -2*w]) circle_end_linkage(l, w, 6.5, 0, 9.15);
translate([0, -4*w]) circle_end_linkage(l, w, 6.5, 0, 9.15);
translate([0, -6*w]) circle_end_linkage(l, w, 6.5, 0, 9.15);

// a1, a3, f1, f3
saw_h = 5.75;
ll=223 - saw_h - (w/2);
center_hole_p = l/2;
translate([l + 3*w, 0*w]) circle_saw_end_linkage(ll, w, saw_h, center_hole_p,9.15, 6.5);
translate([l+3*w, -2*w]) circle_saw_end_linkage(ll, w, saw_h, center_hole_p, 9.15, 6.5);
translate([l+3*w, -4*w]) circle_saw_end_linkage(ll, w, saw_h, center_hole_p, 9.15, 6.5);
translate([l+3*w, -6*w]) circle_saw_end_linkage(ll, w, saw_h, center_hole_p, 9.15, 6.5);

// e1, e2, e3
translate([l+3*w, 2*w]) circle_saw_end_linkage(ll, w, saw_h, center_hole_p, 6.5, 6.5);
translate([l+3*w, 4*w]) circle_saw_end_linkage(ll, w, saw_h, center_hole_p, 6.5, 6.5);
translate([l+3*w, 6*w]) circle_saw_end_linkage(ll, w, saw_h, center_hole_p, 6.5, 6.5);

// b2
lll=182;
translate([0, -8*w]) saw_end_linkage(lll, w, saw_h, 6.5);

// g2, g2
cross_tab_width = 9.2;
translate([0, -10*w])
  linkage_cross(18.75, w, 6, cross_tab_width, 8.75, 6.5);
translate([3*w, -10*w])
  linkage_cross(18.75, w, 6, cross_tab_width, 8.75, 6.5);

// c1 c3, d2

translate([6*w,-10*w])
  difference() { circle(d=18.75); circle(d=9.7); }

translate([9*w,-10*w])
  difference() { circle(d=18.75); circle(d=9.7); }
translate([12*w,-10*w])
  difference() { circle(d=18.75); circle(d=9.7); }

// g1, g1, g3, g3
dingy_l = 60.5 - w/2;
fudge = 0.5;
translate([0, -12*w])
  dingy(dingy_l, w, 6.5, 6, cross_tab_width + fudge,, 9, 7.45);
translate([4*w, -12*w])
  dingy(dingy_l, w, 6.5, 6, cross_tab_width + fudge, 9, 7.45);
translate([0, -14*w])
  dingy(dingy_l, w, 6.5, 6, cross_tab_width + fudge, 9, 7.45);
translate([4*w, -14*w])
  dingy(dingy_l, w, 6.5, 6, cross_tab_width + fudge, 9, 7.45);

// licensed under CC0
//
// still a work in progress.
// the dimensions need to be confirmed.
// the 'dingy' especially needs to be confirmed.
//

module saw_end_linkage( base_length,
                  width,
                  saw_h,
                  circle_d_mid) {
  difference() {
    union() {
      square([base_length, width], center=true);
      polygon([[-base_length/2.0,width/2],
               [-base_length/2.0 - saw_h, 0],
               [-base_length/2.0,-width/2]]);
      polygon([[ base_length/2.0,width/2],
               [ base_length/2.0 + saw_h, 0],
               [ base_length/2.0,-width/2]]);
    }

    translate([0,0]) circle(d=circle_d_mid);
  }
}

// center_hole_p from circle end of base edge
//
module circle_saw_end_linkage( base_length,
                  width,
                  saw_h,
                  center_hole_p,
                  circle_d_left,
                  circle_d_mid) {
  difference() {
    union() {
      square([base_length, width], center=true);
      translate([-base_length/2,0]) circle(d=width);
      polygon([[base_length/2.0,width/2],
               [base_length/2.0 + saw_h, 0],
               [base_length/2.0,-width/2]]);
    }
    translate([-base_length/2,0]) circle(d=circle_d_left);
    translate([-(base_length/2.0) + center_hole_p ,0]) circle(d=circle_d_mid);
  }
}

module circle_end_linkage( base_length,
                  width,
                  circle_d_left,
                  circle_d_mid,
                  circle_d_right) {

  difference() {
    union() {
      square([base_length, width], center=true);
      translate([-base_length/2,0]) circle(d=width);
      translate([ base_length/2,0]) circle(d=width);
    }

    translate([-base_length/2,0]) circle(d=circle_d_left);
    translate([0,0]) circle(d=circle_d_mid);
    translate([ base_length/2,0]) circle(d=circle_d_right);
  }

}

module dingy(base_length,
             width,
             circle_d,
             hole_l_a,
             hole_w_a,
             hole_l_b,
             hole_w_b) {
  difference() {
    union() {
      square([base_length,width], center=true);
      translate([base_length/2,0]) circle(d=width);
    }
    translate([base_length/2,0]) circle(d=circle_d);
    translate([-base_length/2.0 + 4.35 + hole_l_a/2, 0])
      square([hole_l_a, hole_w_a], center=true);
    translate([-base_length/2.0 + 4.35 + hole_l_a + hole_l_b/2,0])
      square([hole_l_b, hole_w_b], center=true);
  }
}

module linkage_cross(base_length,
                     width,
                     tab_length,
                     tab_width,
                     square_hole_length,
                     square_hole_width) {
  difference() {
    union() {
      square([base_length, width], center=true);
      translate([base_length/2 + tab_length/2, 0])
        square([tab_length, tab_width], center=true);
      translate([-(base_length/2 + tab_length/2), 0])
        square([tab_length, tab_width], center=true);
    }
    square([square_hole_length, square_hole_width], center=true);
  }
}

// a2, f2
w=18.75;
l=247-w;
translate([0, 0*w]) circle_end_linkage(l, w, 6.5, 6.5, 9.15);
translate([0, 2*w]) circle_end_linkage(l, w, 6.5, 6.5, 9.15);

// b1, b3
translate([0, 4*w]) circle_end_linkage(l, w, 6.5, 6.5, 6.5);
translate([0, 6*w]) circle_end_linkage(l, w, 6.5, 6.5, 6.5);

// d1, d3, c2
translate([0, -2*w]) circle_end_linkage(l, w, 6.5, 0, 9.15);
translate([0, -4*w]) circle_end_linkage(l, w, 6.5, 0, 9.15);
translate([0, -6*w]) circle_end_linkage(l, w, 6.5, 0, 9.15);

// a1, a3, f1, f3
saw_h = 5.75;
ll=223 - saw_h - (w/2);
center_hole_p = l/2;
translate([l + 3*w, 0*w]) circle_saw_end_linkage(ll, w, saw_h, center_hole_p,9.15, 6.5);
translate([l+3*w, -2*w]) circle_saw_end_linkage(ll, w, saw_h, center_hole_p, 9.15, 6.5);
translate([l+3*w, -4*w]) circle_saw_end_linkage(ll, w, saw_h, center_hole_p, 9.15, 6.5);
translate([l+3*w, -6*w]) circle_saw_end_linkage(ll, w, saw_h, center_hole_p, 9.15, 6.5);

// e1, e2, e3
translate([l+3*w, 2*w]) circle_saw_end_linkage(ll, w, saw_h, center_hole_p, 6.5, 6.5);
translate([l+3*w, 4*w]) circle_saw_end_linkage(ll, w, saw_h, center_hole_p, 6.5, 6.5);
translate([l+3*w, 6*w]) circle_saw_end_linkage(ll, w, saw_h, center_hole_p, 6.5, 6.5);

// b2
lll=182;
translate([0, -8*w]) saw_end_linkage(lll, w, saw_h, 6.5);

// g2, g2
translate([0, -10*w])
  linkage_cross(18.75, w, 6, 9, 8.75, 6.5);
translate([3*w, -10*w])
  linkage_cross(18.75, w, 6, 9, 8.75, 6.5);

// c1 c3, d2

translate([6*w,-10*w])
  difference() { circle(d=18.75); circle(d=9.7); }

translate([9*w,-10*w])
  difference() { circle(d=18.75); circle(d=9.7); }
translate([12*w,-10*w])
  difference() { circle(d=18.75); circle(d=9.7); }

// g1, g1, g3, g3
translate([0, -12*w])
  dingy(52, w, 6.5, 6, 9.75, 9.4,7.45);
translate([4*w, -12*w])
  dingy(52, w, 6.5, 6, 9.75, 9.4,7.45);
translate([0, -14*w])
  dingy(52, w, 6.5, 6, 9.75, 9.4,7.45);
translate([4*w, -14*w])
  dingy(52, w, 6.5, 6, 9.75, 9.4,7.45);


The start of a fan mount.  Hilariously, the main thing missing is the actual fan mount. Plan is to use offsets to push this back from the fan mounting lugs, and have two long screws going through fan->mount->lugs, and two shorter screws securing the fan to the bottom of the mount. Offset should be about 10mm.

hot_rad = 30/2/cos(30);
hotend_x=25;
fan_x = 15;

hotend_y=-5;

thickness = 10;
wall=2.5;

fan_hole = 38/2;
fan_z = fan_hole+wall;

fan_mount();

%cylinder(r=hot_rad, h=20, center=true);

module fan_mount(){
    difference(){
        union(){
            //core
            cylinder(r1=hot_rad+thickness+wall, r2=hot_rad+thickness*2+wall, h=thickness+wall, $fn=6);

            hull(){
                intersection(){
                    cylinder(r1=hot_rad+thickness+wall, r2=hot_rad+thickness*2+wall, h=thickness+wall, $fn=6);
                    translate([50+hot_rad,0,50]) cube([100,100,100], center=true);
                }
                translate([hotend_x+fan_x,hotend_y,fan_z]) rotate([0,90,0]) cylinder(r=fan_hole+wall, h=.1);
            }
        }

        //center cutout
        translate([0,0,-.5]) cylinder(r=hot_rad+wall, h=thickness+wall+1, $fn=6);

        //front cutout
        translate([-(hot_rad+thickness*2+wall),0,0]) cylinder(r=hot_rad+thickness*2+wall, h=thickness+wall*10, center=true, $fn=6);

        //air path
        translate([0,0,-.1]) difference(){
            union(){
                cylinder(r1=hot_rad+thickness, r2=hot_rad+thickness*2, h=thickness, $fn=6);
                hull(){
                    intersection(){
                        cylinder(r1=hot_rad+thickness, r2=hot_rad+thickness*2, h=thickness, $fn=6);
                        translate([50+hot_rad+wall,0,50+wall]) cube([100,100,100], center=true);
                    }
                    translate([hotend_x+fan_x,hotend_y,fan_z]) rotate([0,90,0]) cylinder(r=fan_hole, h=.3, center=true);
                }
            }
            cylinder(r=hot_rad+wall+wall, h=thickness+wall, $fn=6);
            translate([-(hot_rad+thickness*2),0,0]) cylinder(r=hot_rad+thickness*2+wall, h=thickness+wall*10, center=true, $fn=6);
        }
    }
}

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


=> rules coding и параметр

=> rules coding и параметр

//Каркас для модели участка ДНК
$fn=190;
x=9;
y=90;
z=90;
dz=0;
cylinder(x,y,z);
translate([0,0,dz]) cylinder(x*5,y/10,z/10);

//Каркас для модели участка ДНК
$fn=190;
x=9;
y=90;
z=90;
dz=-45;
cylinder(x,y,z);
translate([0,0,dz]) cylinder(x*5,y/10,z/10);


Adjusting motor shaft model further

Adjusting motor shaft model further

wall_thickness=2;
// Piece that will be rotated
damper_arm_diameter=9;
damper_arm_cut_width=5.1;
damper_arm_depth=12;
// stepper mount
stepper_shaft_diameter=5.8;
stepper_shaft_cut_width=3.5;
stepper_shaft_depth=7;
// Marker for closed position
marker_size=2;
marker_distance=9;
marker_height=5;
// Connecting the two
mount_length=1.2*(damper_arm_depth+stepper_shaft_depth);
mount_diameter=max(damper_arm_diameter,stepper_shaft_diameter)+wall_thickness*2;
// Pin offset degrees to achieve fully closed vent on button press
pin_degrees_offset=0;

/*
 * motor-to-damper adaptor
**/
translate([0,0,-mount_length]) motor_to_damper_adaptor();

module motor_to_damper_adaptor() {
    rotate([0,0,pin_degrees_offset]) button_pin();
    difference() {
        // main body
        cylinder(mount_length, mount_diameter/2, mount_diameter/2);
        // Stepper cutout
        translate([0,0,stepper_shaft_depth/2]) mount_cutout(stepper_shaft_diameter/2, stepper_shaft_cut_width, stepper_shaft_depth);
        // Damper cutout
        translate([0,0,mount_length-damper_arm_depth/2]) mount_cutout(damper_arm_diameter/2, damper_arm_cut_width, damper_arm_depth);
    }

}

module button_pin() {
    translate([mount_diameter/2,0,mount_length-marker_distance]) scale([2*marker_size/marker_height, 0.6, 1]) sphere(d=marker_height, $fn=50);
    translate([-mount_diameter/2,0,mount_length-marker_distance]) scale([2*marker_size/marker_height, 0.6, 1]) sphere(d=marker_height, $fn=50);
}

// Motor mount
vent_diameter = 6*25.4; // 6"
shaft_offset=8;
motor_ears_distance=35;
motot_ears_hole_diameter=3.8;
motor_ears_screw_length=15;
vent_mount_distance=55;
vent_mount_hole_diameter=6;
motor_to_vent_distance=mount_length+4-wall_thickness*1.5; // 4mm distance between connector and motor body
vent_ears_total_length=vent_mount_distance+vent_mount_hole_diameter+wall_thickness*2;
vent_ears_total_width=mount_diameter+wall_thickness*4;
motor_screw_cube_side=motot_ears_hole_diameter+wall_thickness*2;
/*
 * mount bracket itself
**/
//motor_to_vent_mount();

// endstop sensor
endstop_screw_diameter=1.8;
endstop_screw1_distance=16;
endstop_screw1_offset=-1.5;
endstop_screw2_distance=5;
endstop_screw2_offset=20;

module motor_to_vent_mount() {
    union() {
        // Vent ears
        vent_mount_plate();
        // motor mount
        translate([motor_ears_distance/2,shaft_offset,-motor_to_vent_distance]) motor_screw_connector();
        translate([-motor_ears_distance/2,shaft_offset,-motor_to_vent_distance]) motor_screw_connector();
    }
}

module damper_mount_cutout() {
    intersection() {
        cylinder(damper_arm_depth, damper_arm_diameter, damper_arm_diameter, center=true, $fn=40);
        cube([damper_arm_diameter*2, damper_arm_cut_width, damper_arm_depth], center=true);
    }
}

module mount_cutout(radius, width, depth) {
    intersection() {
        cylinder(depth, radius, radius, center=true, $fn=40);
        cube([radius*2, width, depth], center=true);
    }
}

module vent(length) {
    cylinder(length, vent_diameter/2, vent_diameter/2, $fn=100);
}

module vent_mount_plate() {
    endstop_sensor_space=max(endstop_screw1_distance,endstop_screw2_distance)+endstop_screw_diameter/2+wall_thickness-(vent_ears_total_width/2-mount_diameter/2);
    //                   ^ distance to furthest hole                          ^ mounting holes w/ walls                ^ distance from original edge to shaft
    plate_total_width=vent_ears_total_width+motor_screw_cube_side/2+shaft_offset-vent_ears_total_width/2+(endstop_sensor_space) ;
    //                 ^ base width         ^ extend for motor mount                                     ^ accommodate endstop sensor
    translate([-vent_ears_total_length/2,0,0]) rotate([0,90,0]) translate([-wall_thickness*1.5,0,0]) intersection() {
        translate([-wall_thickness*1.5, -vent_ears_total_width/2-endstop_sensor_space, 0]) cube([wall_thickness*3, plate_total_width, vent_ears_total_length]);
        difference() {
            translate([-vent_diameter/2, 0, 0]) cylinder(vent_ears_total_length, d=vent_diameter+wall_thickness*8);
            translate([-vent_diameter/2, 0, 0]) vent(vent_ears_total_length);
            // Mount holes cutout
            translate([-wall_thickness*1.5,0,vent_mount_hole_diameter/2+wall_thickness]) rotate([0,90,0]) cylinder(wall_thickness*3, vent_mount_hole_diameter/2, vent_mount_hole_diameter/2, $fn=20);
            translate([-wall_thickness*1.5,0,vent_ears_total_length-vent_mount_hole_diameter/2-wall_thickness]) rotate([0,90,0]) cylinder(wall_thickness*3, vent_mount_hole_diameter/2, vent_mount_hole_diameter/2, $fn=20);
            // shaft cutout
            translate([-wall_thickness*1.5,0,vent_ears_total_length/2]) rotate([0,90,0]) cylinder(wall_thickness*4, mount_diameter/2+wall_thickness, mount_diameter/2+wall_thickness);
            // endstop sensor mount
            #translate([-5,-endstop_screw1_distance-mount_diameter/2,vent_ears_total_length/2+endstop_screw1_offset]) rotate([0,90,0]) cylinder(10, d=endstop_screw_diameter, $fn=20);
            #translate([-5,-endstop_screw2_distance-mount_diameter/2,vent_ears_total_length/2+endstop_screw2_offset]) rotate([0,90,0]) cylinder(10, d=endstop_screw_diameter, $fn=20);
        }
    }
}

module motor_screw_connector() {
    difference() {
        translate([-motor_screw_cube_side/2, -motor_screw_cube_side/2, 0]) cube([motor_screw_cube_side, motor_screw_cube_side, motor_to_vent_distance]);
        cylinder(motor_ears_screw_length, motot_ears_hole_diameter/2, motot_ears_hole_diameter/2, $fn=20);
    }

}

wall_thickness=2;
// Piece that will be rotated
damper_arm_diameter=8.5;
damper_arm_cut_width=6;
damper_arm_depth=12;
// stepper mount
stepper_shaft_diameter=5.8;
stepper_shaft_cut_width=3.5;
stepper_shaft_depth=7;
// Marker for closed position
marker_size=2;
marker_distance=9;
marker_height=5;
// Connecting the two
mount_length=1.2*(damper_arm_depth+stepper_shaft_depth);
mount_diameter=max(damper_arm_diameter,stepper_shaft_diameter)+wall_thickness*2;

/*
 * motor-to-damper adaptor
**/
translate([0,0,-mount_length]) motor_to_damper_adaptor();

module motor_to_damper_adaptor() {
    difference() {
        // main body
        cylinder(mount_length, mount_diameter/2, mount_diameter/2);
        // Stepper cutout
        translate([0,0,stepper_shaft_depth/2]) mount_cutout(stepper_shaft_diameter/2, stepper_shaft_cut_width, stepper_shaft_depth);
        // Damper cutout
        translate([0,0,mount_length-damper_arm_depth/2]) mount_cutout(damper_arm_diameter/2, damper_arm_cut_width, damper_arm_depth);
    }
    translate([mount_diameter/2,0,mount_length-marker_distance]) scale([2*marker_size/marker_height, 0.6, 1]) sphere(d=marker_height, $fn=50);
}

// Motor mount
vent_diameter = 6*25.4; // 6"
shaft_offset=8;
motor_ears_distance=35;
motot_ears_hole_diameter=3.8;
motor_ears_screw_length=15;
vent_mount_distance=55;
vent_mount_hole_diameter=6;
motor_to_vent_distance=mount_length+4-wall_thickness*1.5; // 4mm distance between connector and motor body
vent_ears_total_length=vent_mount_distance+vent_mount_hole_diameter+wall_thickness*2;
vent_ears_total_width=mount_diameter+wall_thickness*4;
motor_screw_cube_side=motot_ears_hole_diameter+wall_thickness*2;
/*
 * mount bracket itself
**/
//motor_to_vent_mount();

// endstop sensor
endstop_screw_diameter=1.8;
endstop_screw1_distance=16;
endstop_screw1_offset=-1.5;
endstop_screw2_distance=5;
endstop_screw2_offset=20;

module motor_to_vent_mount() {
    union() {
        // Vent ears
        vent_mount_plate();
        // motor mount
        translate([motor_ears_distance/2,shaft_offset,-motor_to_vent_distance]) motor_screw_connector();
        translate([-motor_ears_distance/2,shaft_offset,-motor_to_vent_distance]) motor_screw_connector();
    }
}

module damper_mount_cutout() {
    intersection() {
        cylinder(damper_arm_depth, damper_arm_diameter, damper_arm_diameter, center=true, $fn=40);
        cube([damper_arm_diameter*2, damper_arm_cut_width, damper_arm_depth], center=true);
    }
}

module mount_cutout(radius, width, depth) {
    intersection() {
        cylinder(depth, radius, radius, center=true, $fn=40);
        cube([radius*2, width, depth], center=true);
    }
}

module vent(length) {
    cylinder(length, vent_diameter/2, vent_diameter/2, $fn=100);
}

module vent_mount_plate() {
    endstop_sensor_space=max(endstop_screw1_distance,endstop_screw2_distance)+endstop_screw_diameter/2+wall_thickness-(vent_ears_total_width/2-mount_diameter/2);
    //                   ^ distance to furthest hole                          ^ mounting holes w/ walls                ^ distance from original edge to shaft
    plate_total_width=vent_ears_total_width+motor_screw_cube_side/2+shaft_offset-vent_ears_total_width/2+(endstop_sensor_space) ;
    //                 ^ base width         ^ extend for motor mount                                     ^ accommodate endstop sensor
    translate([-vent_ears_total_length/2,0,0]) rotate([0,90,0]) translate([-wall_thickness*1.5,0,0]) intersection() {
        translate([-wall_thickness*1.5, -vent_ears_total_width/2-endstop_sensor_space, 0]) cube([wall_thickness*3, plate_total_width, vent_ears_total_length]);
        difference() {
            translate([-vent_diameter/2, 0, 0]) cylinder(vent_ears_total_length, d=vent_diameter+wall_thickness*8);
            translate([-vent_diameter/2, 0, 0]) vent(vent_ears_total_length);
            // Mount holes cutout
            translate([-wall_thickness*1.5,0,vent_mount_hole_diameter/2+wall_thickness]) rotate([0,90,0]) cylinder(wall_thickness*3, vent_mount_hole_diameter/2, vent_mount_hole_diameter/2, $fn=20);
            translate([-wall_thickness*1.5,0,vent_ears_total_length-vent_mount_hole_diameter/2-wall_thickness]) rotate([0,90,0]) cylinder(wall_thickness*3, vent_mount_hole_diameter/2, vent_mount_hole_diameter/2, $fn=20);
            // shaft cutout
            translate([-wall_thickness*1.5,0,vent_ears_total_length/2]) rotate([0,90,0]) cylinder(wall_thickness*4, mount_diameter/2+wall_thickness, mount_diameter/2+wall_thickness);
            // endstop sensor mount
            #translate([-5,-endstop_screw1_distance-mount_diameter/2,vent_ears_total_length/2+endstop_screw1_offset]) rotate([0,90,0]) cylinder(10, d=endstop_screw_diameter, $fn=20);
            #translate([-5,-endstop_screw2_distance-mount_diameter/2,vent_ears_total_length/2+endstop_screw2_offset]) rotate([0,90,0]) cylinder(10, d=endstop_screw_diameter, $fn=20);
        }
    }
}

module motor_screw_connector() {
    difference() {
        translate([-motor_screw_cube_side/2, -motor_screw_cube_side/2, 0]) cube([motor_screw_cube_side, motor_screw_cube_side, motor_to_vent_distance]);
        cylinder(motor_ears_screw_length, motot_ears_hole_diameter/2, motot_ears_hole_diameter/2, $fn=20);
    }

}


bearing: bearing mount rod cutout (use 1mm tolerance, not 1.3 factor)

use <transforms.scad>;
use <shapes.scad>
include <bearing_data.scad>
include <units.scad>

module bearing(bearing_type, extra_h=0, override_h=undef, orient=[0,0,1], align=[0,0,0])
{
    h = (override_h==undef ? bearing_type[2] : override_h) + extra_h;
    size_align(size=[bearing_type[1],bearing_type[1],h], align=align ,orient=orient)
    difference()
    {
        // outer
        cylindera(h=h, d=bearing_type[1], align=[0,0,0]);
        // inner
        cylindera(h=h+.1, d=bearing_type[0], align=[0,0,0]);
        // clips
        if(len(bearing_type) > 3)
        {
            clip_depth=.5;
            for(z=[-1,1])
            translate([0,0,z*bearing_type[3]/2])
            difference()
            {
                cylindera(h=1*mm, d=bearing_type[2]+1, align=[0,0,-z]);
                cylindera(h=1*mm+.1, d=bearing_type[4]-clip_depth, align=[0,0,-z]);
            }

        }
    }
}

module bearing_mount_holes(bearing_type, ziptie_type=[2*mm, 3*mm], ziptie_bearing_distance=3*mm, tolerance=1.01, orient=[1,0,0], ziptie_dist=undef, show_zips=false)
{
    ziptie_thickness = ziptie_type[0];
    ziptie_width = ziptie_type[1]+0.6*mm;

    ziptie_dist_ = (ziptie_dist==undef?bearing_type[3]/2:ziptie_dist);

    orient(orient)
    {
        // Main bearing cut
        cylindera(h=bearing_type[2]*tolerance, d=bearing_type[1]*tolerance, orient=[0,0,1]);

        for(z=[-1,1])
        translate([0,0,z*ziptie_dist_ - z*1/2])
        hollow_cylinder(
                d=bearing_type[1]+ziptie_bearing_distance+ziptie_thickness,
                thickness = ziptie_thickness*2,
                h = ziptie_width,
                taper=true,
                orient=[0,0,1],
                align=[0,0,0]
                );

        // for linear rod
        cylindera(d=bearing_type[0]+1*mm, h=100, orient=[0,0,1]);

        if(show_zips)
        {
            for(z=[-1,1])
            translate([0,0,z*ziptie_dist_])
            {
                %hollow_cylinder(
                        d=bearing_type[1]+ziptie_bearing_distance+ziptie_thickness,
                        thickness = ziptie_thickness,
                        h = ziptie_width,
                        orient=[0,0,1],
                        align=[0,0,-z]
                        );
            }
        }
    }
}

if(false)
{
    b=bearing_igus_rj4jp_01_12;
    bearing_mount_holes(b, orient=[0,0,1]);
    translate([30,0,0])
    bearing(b, orient=[0,0,1]);
}

use <transforms.scad>;
use <shapes.scad>
include <bearing_data.scad>
include <units.scad>

module bearing(bearing_type, extra_h=0, override_h=undef, orient=[0,0,1], align=[0,0,0])
{
    h = (override_h==undef ? bearing_type[2] : override_h) + extra_h;
    size_align(size=[bearing_type[1],bearing_type[1],h], align=align ,orient=orient)
    difference()
    {
        // outer
        cylindera(h=h, d=bearing_type[1], align=[0,0,0]);
        // inner
        cylindera(h=h+.1, d=bearing_type[0], align=[0,0,0]);
        // clips
        if(len(bearing_type) > 3)
        {
            clip_depth=.5;
            for(z=[-1,1])
            translate([0,0,z*bearing_type[3]/2])
            difference()
            {
                cylindera(h=1*mm, d=bearing_type[2]+1, align=[0,0,-z]);
                cylindera(h=1*mm+.1, d=bearing_type[4]-clip_depth, align=[0,0,-z]);
            }

        }
    }
}

module bearing_mount_holes(bearing_type, ziptie_type=[2*mm, 3*mm], ziptie_bearing_distance=3*mm, tolerance=1.01, orient=[1,0,0], ziptie_dist=undef, show_zips=false)
{
    ziptie_thickness = ziptie_type[0];
    ziptie_width = ziptie_type[1]+0.6*mm;

    ziptie_dist_ = (ziptie_dist==undef?bearing_type[3]/2:ziptie_dist);

    orient(orient)
    {
        // Main bearing cut
        cylindera(h=bearing_type[2]*tolerance, d=bearing_type[1]*tolerance, orient=[0,0,1]);

        for(z=[-1,1])
        translate([0,0,z*ziptie_dist_ - z*1/2])
        hollow_cylinder(
                d=bearing_type[1]+ziptie_bearing_distance+ziptie_thickness,
                thickness = ziptie_thickness*2,
                h = ziptie_width,
                taper=true,
                orient=[0,0,1],
                align=[0,0,0]
                );

        // for linear rod
        cylindera(d=bearing_type[0]*1.3, h=100, orient=[0,0,1]);

        if(show_zips)
        {
            for(z=[-1,1])
            translate([0,0,z*ziptie_dist_])
            {
                %hollow_cylinder(
                        d=bearing_type[1]+ziptie_bearing_distance+ziptie_thickness,
                        thickness = ziptie_thickness,
                        h = ziptie_width,
                        orient=[0,0,1],
                        align=[0,0,-z]
                        );
            }
        }
    }
}

if(false)
{
    b=bearing_igus_rj4jp_01_12;
    bearing_mount_holes(b, orient=[0,0,1]);
    translate([30,0,0])
    bearing(b, orient=[0,0,1]);
}


bearings: add MR105

bearings: add MR105

use <thing_libutils/shapes.scad>;

// radial bearings
// inner_d, outer_d, length/width (thickness)
bearing_608 = [8,22,7];
bearing_626 = [8,19,6];
bearing_625 = [5,16,5];
bearing_608 = [8,22,7];
bearing_MR128 = [8,12,3.5];
bearing_MR115 = [5,11,4];
bearing_MR105 = [5,10,4];

// linear bearings
// inner_d, outer_d, length, clips_len, clips_d

// http://www.igus.eu/wpck/12157/Motek14_N14_6_3_Vollkunststofflager?L=en
bearing_igus_rj4jp_01_08 = [8,15,24,17.5,14.3];
bearing_igus_rj4jp_01_10 = [10,19,29,22.5,18];
bearing_igus_rj4jp_01_12 = [12,21,30,23.5,20];
bearing_igus_rj4jp_01_16 = [16,28,37,26.5,26.6];
bearing_igus_rj4jp_01_20 = [20,32,42,30.5,30.3];

module bearing(bearing_type, orient=[0,0,1])
{
    orient(orient)
    difference()
    {
        // outer
        fncylindera(h=bearing_type[2], d=bearing_type[1], align=[0,0,0]);
        // inner
        fncylindera(h=bearing_type[2]+1, d=bearing_type[0], align=[0,0,0]);
        // clips
        if(len(bearing_type) > 3)
        {
            clip_depth=.5;
            for(j=[-1,1])
            translate([0,0,j*bearing_type[3]/2])
            difference()
            {
                fncylindera(h=1, d=bearing_type[2]+1, align=[0,0,0]);
                fncylindera(h=2, d=bearing_type[4]-clip_depth, align=[0,0,0]);
            }

        }
    }
}

module bearing_mount_holes(bearing_type, orient=[1,0,0], ziptie_dist=undef, show_zips=false)
{
    ziptie_dist_ = ziptie_dist==undef?bearing_type[3]/2:ziptie_dist;
    orient(orient)
    {
        // Main bearing cut
        difference()
        {
            fncylindera(h=bearing_type[2], d=bearing_type[1]*rod_fit_tolerance, orient=[0,0,1]);
        }

        difference()
        {
            union()
            {
                for(i=[-1,1])
                translate([0,0,i*ziptie_dist_])
                fncylindera(h=ziptie_width, d=bearing_type[1]+ziptie_bearing_distance+ziptie_thickness, orient=[0,0,1]);
            }
            fncylindera(h=bearing_type[2], d=bearing_type[1]+ziptie_bearing_distance, orient=[0,0,1]);
        }

        // for linear rod
        fncylindera(d=bearing_type[0]*1.5, h=100, orient=[0,0,1]);

        %if(show_zips)
        {
            for(i=[-1,1])
            translate([0,0,i*ziptie_dist_])
            fncylindera(h=ziptie_width, d=bearing_type[1]+ziptie_thickness, orient=[0,0,1]);
        }
    }
}

use <thing_libutils/shapes.scad>;

// radial bearings
// inner_d, outer_d, length/width (thickness)
bearing_608 = [8,22,7];
bearing_626 = [8,19,6];
bearing_625 = [5,16,5];
bearing_608 = [8,22,7];
bearing_MR128 = [8,12,3.5];
bearing_MR115 = [5,11,4];

// linear bearings
// inner_d, outer_d, length, clips_len, clips_d

// http://www.igus.eu/wpck/12157/Motek14_N14_6_3_Vollkunststofflager?L=en
bearing_igus_rj4jp_01_08 = [8,15,24,17.5,14.3];
bearing_igus_rj4jp_01_10 = [10,19,29,22.5,18];
bearing_igus_rj4jp_01_12 = [12,21,30,23.5,20];
bearing_igus_rj4jp_01_16 = [16,28,37,26.5,26.6];
bearing_igus_rj4jp_01_20 = [20,32,42,30.5,30.3];

module bearing(bearing_type, orient=[0,0,1])
{
    orient(orient)
    difference()
    {
        // outer
        fncylindera(h=bearing_type[2], d=bearing_type[1], align=[0,0,0]);
        // inner
        fncylindera(h=bearing_type[2]+1, d=bearing_type[0], align=[0,0,0]);
        // clips
        if(len(bearing_type) > 3)
        {
            clip_depth=.5;
            for(j=[-1,1])
            translate([0,0,j*bearing_type[3]/2])
            difference()
            {
                fncylindera(h=1, d=bearing_type[2]+1, align=[0,0,0]);
                fncylindera(h=2, d=bearing_type[4]-clip_depth, align=[0,0,0]);
            }

        }
    }
}

module bearing_mount_holes(bearing_type, orient=[1,0,0], ziptie_dist=undef, show_zips=false)
{
    ziptie_dist_ = ziptie_dist==undef?bearing_type[3]/2:ziptie_dist;
    orient(orient)
    {
        // Main bearing cut
        difference()
        {
            fncylindera(h=bearing_type[2], d=bearing_type[1]*rod_fit_tolerance, orient=[0,0,1]);
        }

        difference()
        {
            union()
            {
                for(i=[-1,1])
                translate([0,0,i*ziptie_dist_])
                fncylindera(h=ziptie_width, d=bearing_type[1]+ziptie_bearing_distance+ziptie_thickness, orient=[0,0,1]);
            }
            fncylindera(h=bearing_type[2], d=bearing_type[1]+ziptie_bearing_distance, orient=[0,0,1]);
        }

        // for linear rod
        fncylindera(d=bearing_type[0]*1.5, h=100, orient=[0,0,1]);

        %if(show_zips)
        {
            for(i=[-1,1])
            translate([0,0,i*ziptie_dist_])
            fncylindera(h=ziptie_width, d=bearing_type[1]+ziptie_thickness, orient=[0,0,1]);
        }
    }
}


Altered measurements for hardboard, tweaked height and lightbar position, rounded/truncated overhangs on vertical faces.

// fishbox.scad
//  - Enclosure design for zebrafish Skinner box
//
//  Author: Mark Liffiton
//  Date: Oct, 2014 - Jan, 2015
//
//  Units are mm

// Set thickness to account for thickness of material
// PLUS needed clearance for cuts into which material should fit.

// 0.100" Acrylic:
//thickness = 2.4;  // 2.4mm = 0.094" (looks good based on cut test piece)

// 1/8" Hardboard:
thickness = 3.1;  // 3.1mm = 0.122" (best guess for hardboard for now)

// Interior box dimensions (NOTE: from centerpoints of walls, so actual dimension is minus material thickness)
width = 290;    // x = 29cm wall-to-wall
depth = 350;    // y = 35cm to accomodate 34.5cm tank length
i_height = 190; // z = 19cm to accomodate 16cm tank height plus light holder, plus cover
                // (i_height because 'height' is used for height of entire box)

// amount faces extend past each other at corners
overhang = 15;

// amount horizontal support tabs extend past side supports (technically, it will go this distance minus thickness/2)
outset = thickness+2;

// tank base plate
base_depth = depth-thickness*2;
base_height = overhang/2;

// create height var to account for raised base
height = i_height + base_height;

// light bar
light_bar_width = 30;
light_pos_x = 50;
light_height = height-thickness*2-8;

// hanging support thickness and drop (distance it "sits down" after in place)
support_w = 10;
support_drop = support_w/2;

// for slight offsets/tweaks
epsilon = 1;

// vars to control projection for DXF export (see makefile)
if (DXF_TOP) {
    projection() top_cover();
} else if (DXF_BOTTOM) {
    projection() tank_base();
} else if (DXF_SIDE1) {
    projection() rotate(a=[90,0,0]) side(y=0);
} else if (DXF_SIDE2) {
    projection() rotate(a=[90,0,0]) side(y=depth);
} else if (DXF_END1) {
    projection() rotate(a=[0,90,0]) vert_face(x=0);
} else if (DXF_END2) {
    projection() rotate(a=[0,90,0]) vert_face(x=width);
} else if (DXF_LIGHT_BAR) {
    projection() light_bar();
} else if (DXF_CAMERA_SUPPORT) {
    projection() rotate(a=[90,0,0]) camera_supports(justone=true);
} else if (DXF_RPI_SUPPORT) {
    projection() rotate(a=[90,0,0]) rpi_support();
}
else {
    // 3D model
    // components to include (comment out unwanted)
    vert_face(x=0);      // "near face, transparent for monitor
    vert_face(x=width);  // "far" face, with camera, rpi, etc.
    side(y=0);
    side(y=depth);
    tank_base();
    light_bar();
    camera_supports(x=width, y=depth/2, z=height/2);
    rpi_support(x=width, y=depth/2-50, z=height/2);
    mock_rpi(x=width, y=depth/2-60, z=height/2);
    top_cover();
}

//////////////////////////////////////////////////////////////////
// Module definitions
//

module vert_face(x=0) {
    difference() {
        vert_face_base(x);
        camera_opening();
        camera_supports(x=width+thickness*2, y=depth/2, z=height/2+support_drop);
        rpi_support(x=width+thickness*2, y=depth/2-50, z=height/2+support_drop);
        // CAUTION: OpenSCAD won't let me make a projection of vert_face(x=0)
        //   if tank_base is put after side(y=depth) here... bug.  :(
        tank_base();
        top_cover();
        side(y=0);
        side(y=depth);
    }
}

module vert_face_base(x) {
    translate([x-thickness/2,-overhang, 0])
    difference() {
        cube([thickness,depth+overhang*2,height]);
        translate([0, depth+overhang+thickness/2, 3/4*height])
            rounded_truncation(up=true, rot=false);
        translate([0, 0, 3/4*height])
            rounded_truncation(up=true, rot=false);
    }
}

module rounded_truncation(up, rot=[0,0,0]) {
    real_overhang=overhang-thickness/2;
    truncation_height=height/4;
    rotate(a=rot)
    difference() {
        translate([-50,0,0])
            cube([100, real_overhang, truncation_height]);
        if (up) {
            translate([-50, real_overhang/2, 0])
            rotate(a=[0, 90, 0])
                cylinder(d=real_overhang, h=100);
        }
        else {
            translate([-50, real_overhang/2, truncation_height])
            rotate(a=[0, 90, 0])
                cylinder(d=real_overhang, h=100);
        }
    }
}

module camera_opening() {
    translate([width, depth/2, height/2])
        cube([thickness*2,10,10], center=true);
}

module camera_supports(x, y, z, justone=false) {
    spacing = 20;
    out = 10;
    up = 36;
    hanging_support(x, y + spacing/2, z, out, up);
    if (!justone) {
        hanging_support(x, y - spacing/2, z, out, up);
    }
}

module rpi_support(x, y, z) {
    hanging_support(x, y, z, out=3.2, up=85);
}

module hanging_support(x, y, z, out, up) {
    inner_w = out+thickness;
    inner_h = up;
    color("Red", alpha=0.5)
    translate([x,y,z])
    // push inner opening up against vert face
    translate([inner_w/2,0,0])
    difference() {
        cube([inner_w+support_w*2, thickness, inner_h+support_w*2], center=true);
        // cutout for object
        cube([inner_w, thickness*2, inner_h], center=true);
        // cutout for passing through vertface
        translate([-(inner_w/2+support_w/2),0,-support_drop/2])
            cube([support_w+2*epsilon, thickness*2, inner_h-support_drop], center=true);
        // bottom cutout
        translate([-inner_w/2,0,-(inner_h/2+support_w-support_drop/2)])
            cube([thickness, thickness*2, support_drop], center=true);
    }
}

module top_cover() {
    color("Grey", alpha=0.5)
    translate([-outset,-outset,height-thickness])
    difference() {
        cube([width+outset*2,depth+outset*2,thickness]);
        cutouts(5,width-thickness,outset,rot=0,trans=[width/2+outset,0,0]);
        cutouts(5,width-thickness,outset,rot=180,trans=[width/2+outset,depth+outset*2,0]);
        cutouts(5,depth-thickness,outset,rot=-90,trans=[0,depth/2+outset,0]);
        cutouts(5,depth-thickness,outset,rot=90,trans=[width+outset*2,depth/2+outset,0]);
    }
}

module tank_base() {
    translate([-outset,thickness,base_height])
    difference() {
        cube([width+outset*2, base_depth, thickness]);
        cutouts(5,depth,outset,rot=-90,trans=[0,base_depth/2,0]);
        cutouts(5,depth,outset,rot=90,trans=[width+outset*2,base_depth/2,0]);
    }
}

module light_bar_opening() {
    // A wider opening, so the bar can slide out of the way of placing or removing the fish tank
    translate([light_pos_x-light_bar_width/4, -outset, light_height])
        cube([light_bar_width*2, depth+outset*2, thickness]);
}

module light_bar() {
    translate([light_pos_x-light_bar_width/2, -outset, light_height])
    difference() {
        cube([light_bar_width, depth+outset*2, thickness]);
        cutouts(2,light_bar_width,outset,rot=0,trans=[light_bar_width/2,0,0]);
        cutouts(2,light_bar_width,outset,rot=180,trans=[light_bar_width/2,depth+outset*2,0]);
    }
}

module cutouts(num, width, outset, rot, trans) {
    w = width / ((num-1) * 2);
    translate(trans)
    rotate([0,0,1], a=rot)
    for (i = [0 : num-1]) {
        translate([-width/2 - w/2 + i*2*w, -thickness/2, -epsilon])
            cube([w, outset+thickness, thickness+epsilon*2]);
    }
}

module light_wire_opening() {
    translate([light_pos_x, 0, light_height-10])
    scale([2,1,1])
    rotate(v=[1,0,0], a=90)
        cylinder(d=10, h=thickness+epsilon, center=true);
}

module side(y=0) {
    difference() {
        side_base(y);
        scale([1,1,0.5])
            vert_face_base(x=0);
        scale([1,1,0.5])
            vert_face_base(x=width);
        light_bar_opening();
        light_wire_opening();
        top_cover();
    }
}

module side_base(y) {
    translate([-overhang,y-thickness/2,overhang/2])
    difference() {
        cube([width+overhang*2, thickness, height-overhang/2]);
        translate([width+overhang+thickness/2, 0, 0])
            rounded_truncation(up=false, rot=[0,0,-90]);
        translate([0, 0, 0])
            rounded_truncation(up=false, rot=[0,0,-90]);
    }
}

module mock_rpi(x, y, z) {
    color("Blue", alpha=0.5)
    translate([x+thickness, y, z])
        rotate(v=[0,1,0], a=90)
            translate([-85/2, -56/2, 0])
                union() {
                    cube([85, 56, 2]);
                    // USB1
                    translate([67, 41, 2])
                        cube([20, 12, 12]);
                    // USB2
                    translate([67, 23, 2])
                        cube([20, 12, 12]);
                }
}

// fishbox.scad
//  - Enclosure design for zebrafish Skinner box
//
//  Author: Mark Liffiton
//  Date: Oct, 2014 - Jan, 2015
//
//  Units are mm

// Set thickness to account for thickness of material
// PLUS needed clearance for cuts into which material should fit.
thickness = 2.4;  // 2.4mm = 0.094" (looks good based on cut test piece)

// Interior box dimensions (from centerpoints of walls, so actual dimension is minus material thickness)
width = 290;    // x = 29cm wall-to-wall
depth = 350;    // y = 35cm to accomodate 34.5cm tank length
i_height = 180+thickness;
                // z = 18cm to accomodate 16cm tank height plus light holder, plus cover
                // (i_height because 'height' is used for height of entire box)

// amount faces extend past each other at corners
overhang = 20;

// amount horizontal support bars extend past side supports
outset = overhang/2;

// tank base plate
base_depth = depth-thickness*2;
base_height = overhang;

// create height var to account for raised base
height = i_height + base_height;

// light bar
light_bar_width = 30;
light_pos_x = 50;
light_height = height-thickness*2-10;

// hanging support thickness and drop (distance it "sits down" after in place)
support_w = 8;
support_drop = 4;

// for slight offsets/tweaks
epsilon = 1;

// vars to control projection for DXF export (see makefile)
if (DXF_TOP) {
    projection() top_cover();
} else if (DXF_BOTTOM) {
    projection() tank_base();
} else if (DXF_SIDE1) {
    projection() rotate(a=[90,0,0]) side(y=0);
} else if (DXF_SIDE2) {
    projection() rotate(a=[90,0,0]) side(y=depth);
} else if (DXF_END1) {
    projection() rotate(a=[0,90,0]) vert_face(x=0);
} else if (DXF_END2) {
    projection() rotate(a=[0,90,0]) vert_face(x=width);
} else if (DXF_LIGHT_BAR) {
    projection() light_bar();
} else if (DXF_CAMERA_SUPPORT) {
    projection() rotate(a=[90,0,0]) camera_supports(justone=true);
} else if (DXF_RPI_SUPPORT) {
    projection() rotate(a=[90,0,0]) rpi_support();
}
else {
    // 3D model
    // components to include (comment out unwanted)
    vert_face(x=0);      // "near face, transparent for monitor
    vert_face(x=width);  // "far" face, with camera, rpi, etc.
    side(y=0);
    side(y=depth);
    tank_base();
    light_bar();
    camera_supports(x=width, y=depth/2, z=height/2);
    rpi_support(x=width, y=depth/3, z=height/2);
    mock_rpi(x=width, y=depth/3-10, z=height/2);
    top_cover();
}

//////////////////////////////////////////////////////////////////
// Module definitions
//

module vert_face(x=0) {
    difference() {
        vert_face_base(x);
        camera_opening();
        camera_supports(x=width+thickness*2, y=depth/2, z=height/2+support_drop);
        rpi_support(x=width+thickness*2, y=depth/3, z=height/2+support_drop);
        // CAUTION: OpenSCAD won't let me make a projection of vert_face(x=0)
        //   if tank_base is put after side(y=depth) here... bug.  :(
        tank_base();
        top_cover();
        side(y=0);
        side(y=depth);
    }
}

module vert_face_base(x) {
    translate([x-thickness/2,-overhang, 0])
        cube([thickness,depth+overhang*2,height]);
}

module camera_opening() {
    translate([width, depth/2, height/2])
        cube([thickness*2,10,10], center=true);
}

module camera_supports(x, y, z, justone=false) {
    spacing = 20;
    out = 10;
    up = 36;
    hanging_support(x, y + spacing/2, z, out, up);
    if (!justone) {
        hanging_support(x, y - spacing/2, z, out, up);
    }
}

module rpi_support(x, y, z) {
    hanging_support(x, y, z, out=3, up=85);
}

module hanging_support(x, y, z, out, up) {
    inner_w = out+thickness;
    inner_h = up;
    color("Red", alpha=0.5)
    translate([x,y,z])
    // push inner opening up against vert face
    translate([inner_w/2,0,0])
    difference() {
        cube([inner_w+support_w*2, thickness, inner_h+support_w*2], center=true);
        // cutout for object
        cube([inner_w, thickness*2, inner_h], center=true);
        // cutout for passing through vertface
        translate([-(inner_w/2+support_w/2),0,-support_drop/2])
            cube([support_w+2*epsilon, thickness*2, inner_h-support_drop], center=true);
        // bottom cutout
        translate([-inner_w/2,0,-(inner_h/2+support_w-support_drop/2)])
            cube([thickness, thickness*2, support_drop], center=true);
    }
}

module top_cover() {
    color("Grey", alpha=0.5)
    translate([-outset,-outset,height-thickness])
    difference() {
        cube([width+outset*2,depth+outset*2,thickness]);
        cutouts(5,width-thickness,outset,rot=0,trans=[width/2+outset,0,0]);
        cutouts(5,width-thickness,outset,rot=180,trans=[width/2+outset,depth+outset*2,0]);
        cutouts(5,depth-thickness,outset,rot=-90,trans=[0,depth/2+outset,0]);
        cutouts(5,depth-thickness,outset,rot=90,trans=[width+outset*2,depth/2+outset,0]);
    }
}

module tank_base() {
    translate([-outset,thickness,base_height])
    difference() {
        cube([width+outset*2, base_depth, thickness]);
        cutouts(5,depth,outset,rot=-90,trans=[0,base_depth/2,0]);
        cutouts(5,depth,outset,rot=90,trans=[width+outset*2,base_depth/2,0]);
    }
}

module light_bar_opening() {
    // A wider opening, so the bar can slide out of the way of placing or removing the fish tank
    translate([light_pos_x-light_bar_width/4, -outset, light_height])
        cube([light_bar_width*2, depth+outset*2, thickness]);
}

module light_bar() {
    translate([light_pos_x-light_bar_width/2, -outset, light_height])
    difference() {
        cube([light_bar_width, depth+outset*2, thickness]);
        cutouts(2,light_bar_width,outset,rot=0,trans=[light_bar_width/2,0,0]);
        cutouts(2,light_bar_width,outset,rot=180,trans=[light_bar_width/2,depth+outset*2,0]);
    }
}

module cutouts(num, width, outset, rot, trans) {
    w = width / ((num-1) * 2);
    translate(trans)
    rotate([0,0,1], a=rot)
    for (i = [0 : num-1]) {
        translate([-width/2 - w/2 + i*2*w, -thickness/2, -epsilon])
            cube([w, outset+thickness, thickness+epsilon*2]);
    }
}

module light_wire_opening() {
    translate([light_pos_x, 0, light_height-10])
    scale([2,1,1])
    rotate(v=[1,0,0], a=90)
        cylinder(d=10, h=thickness+epsilon, center=true);
}

module side(y=0) {
    difference() {
        side_base(y);
        scale([1,1,0.5])
            vert_face_base(x=0);
        scale([1,1,0.5])
            vert_face_base(x=width);
        light_bar_opening();
        light_wire_opening();
        top_cover();
    }
}

module side_base(y) {
    translate([-overhang,y-thickness/2,overhang/2])
        cube([width+overhang*2, thickness, height-overhang/2]);
}

module mock_rpi(x, y, z) {
    color("Blue", alpha=0.5)
    translate([x+thickness, y, z])
        rotate(v=[0,1,0], a=90)
            translate([-85/2, -56/2, 0])
                union() {
                    cube([85, 56, 2]);
                    // USB1
                    translate([67, 41, 2])
                        cube([20, 12, 12]);
                    // USB2
                    translate([67, 23, 2])
                        cube([20, 12, 12]);
                }
}


lcd2004: add mount for lcd2004

lcd2004: add mount for lcd2004

use <thing_libutils/linear-extrusion.scad>
use <thing_libutils/metric-screw.scad>
include <config.scad>

// wall thickness
lcd2004_wall_thick=4;
lcd2004_width=151+2*lcd2004_wall_thick;
lcd2004_depth=63.5+2*lcd2004_wall_thick;
mount_lcd2004_mount_angle=45;

module mount_lcd2004_parts(
    eps=[0.1,0.1,0], // gap for cavities
    part=undef,
    height=16*mm,
    align, orient, roll, extra_roll, extra_roll_orient
    )
{

    size_align(size=[lcd2004_width,lcd2004_depth,height], align=align, orient=orient, orient_ref=[0,0,1], roll=roll, extra_roll=extra_roll, extra_roll_orient=extra_roll_orient)
    if(part==undef)
    {
        difference()
        {
            mount_lcd2004_parts(lcd2004_wall_thick=lcd2004_wall_thick, eps=eps, part="pos", height=height);
            mount_lcd2004_parts(lcd2004_wall_thick=lcd2004_wall_thick, eps=eps, part="neg", height=height);
        }
    }
    else if(part=="pos")
    {
        translate([-lcd2004_width/2,-lcd2004_depth/2,-height/2])
        rcubea(size=[lcd2004_width,lcd2004_depth,height], rounding_radius=3, align=[1,1,1]);
    }
    else if(part=="neg")
    mirror([0,1,0])
    translate([-lcd2004_width/2,-lcd2004_depth/2,-height/2])
    translate([lcd2004_wall_thick,lcd2004_wall_thick,0])
    {
        // LCD cutout
        translate([14.5,10,-2])
        cubea([97,40,19], align=[1,1,1]);

        // LCD PCB
        translate([14,-0.25,4])
        cubea([98.5,60.5,9+10], align=[1,1,1]);

        // Main PCB
        translate([0,7.75,8])
        cubea([151,56,5+22], align=[1,1,1]);

        // Switch axis
        translate([137,35,-2])
        cylindera(r=8/2, h=19, align=[0,0,1]);

        // buzzer
        translate([130+13.5/2,8+39+12.5/2,-2])
        cylindera(r=12.5/2, h=19, align=[0,0,1]);

        // reset switch
        translate([137,16,-2])
        cylindera(r=2, h=19, align=[0,0,1]);

        // buzzer/switch/reset
        translate([116,8,2])
        cubea([29,55.5,10], align=[1,1,1]);

        // buzzer/switch/reset
        translate([118,18,2])
        cubea([33,35.5,10], align=[1,1,1]);

        // buzzer/switch/reset
        translate([0,18,2])
        cubea([11,35.5,10], align=[1,1,1]);

        // SD slot
        translate([-lcd2004_wall_thick-1,17,9])
        cubea([lcd2004_wall_thick+2,27,10], align=[1,1,1]);

        // Screw hole for PCB
        translate([0+2.9,8+2.5,3])
        cylindera(r=2.5/2, h=6, align=[0,0,1]);

        // Screw hole for PCB
        translate([151-2.7,8+2.5,3])
        cylindera(r=2.5/2, h=6, align=[0,0,1]);

        // Screw hole for PCB
        translate([0+2.9,8+55.5-2.5,3])
        cylindera(r=2.5/2, h=6, align=[0,0,1]);

        // Screw hole for PCB
        translate([151-2.7,8+55.5-2.5,3])
        cylindera(r=2.5/2, h=6, align=[0,0,1]);

        // LCD pin header
        translate([14.5+8,60-5,2])
        cubea([42,8.5,9], align=[1,1,1]);

        // Anti-Warping
        translate([50,-lcd2004_wall_thick/2,2])
        cubea([2,55.5+8+lcd2004_wall_thick,11], align=[1,1,1]);

        // Anti-Warping
        translate([90,-lcd2004_wall_thick/2,2])
        cubea([2,55.5+8+lcd2004_wall_thick,11], align=[1,1,1]);
    }
}

module gantry_lower()
{
    color(color_extrusion)
    for(z=[-1,1])
    {
        translate([0,0,z*-main_lower_dist_z/2])
        {
            for(y=[-1,1])
            translate([0, y*(main_depth/2), 0])
            {
                if(preview_mode)
                {
                    cubea([main_width, extrusion_size, extrusion_size], align=[0,y,-1]);
                }
                else
                {
                    linear_extrusion(h=main_width, align=[0,y,-1], orient=[1,0,0]);
                }
            }

            for(x=[-1,1])
            translate([x*(main_width/2), 0, 0])
            {
                if(preview_mode)
                {
                    cubea([extrusion_size, main_depth, extrusion_size], align=[-x,0,-1]);
                }
                else
                {
                    linear_extrusion(h=main_depth, align=[-x,0,-1], orient=[0,1,0]);
                }
            }
        }
    }
}

lcd2004_mount_thickness = 5*mm;
module lcd2004_extrusion_conn(part, orient=[0,0,1], align=[0,0,0])
{
    s = [extrusion_size, extrusion_size, lcd2004_mount_thickness];
    size_align(size=s, orient=orient, orient_ref=[0,0,1], align=align)
    if(part==undef)
    {
        difference()
        {
            lcd2004_extrusion_conn(part="pos");
            lcd2004_extrusion_conn(part="neg");
        }
    }
    else if(part=="pos")
    {
        rcubea(size=s);
    }
    else if(part=="neg")
    {
        translate([0,0,-lcd2004_mount_thickness/2])
        screw_cut(nut=extrusion_nut, with_nut=true, nut_cut_h=30, with_head=true, head_cut_h=30, length=12*mm, align=[0,0,1], orient=[0,0,1]);
    }
}

lcd2004_offset = [0, -35*mm,-5*mm];

module mount_lcd2004(part, show_gantry=false)
{
    if(part==undef)
    {
        difference()
        {
            mount_lcd2004(part="pos", show_gantry=show_gantry);
            mount_lcd2004(part="neg", show_gantry=show_gantry);
        }
    }
    else if(part == "pos")
    {
        hull()
        {
            for(x=[-1,1])
            translate([x*(lcd2004_width/2+extrusion_size),0,0])
            {
                translate([0,0,main_lower_dist_z/2-extrusion_size])
                lcd2004_extrusion_conn(part=part, orient=[0,0,1], align=[-x,0,-1]);
            }

            for(x=[-1,1])
            translate([x*(lcd2004_width/2+extrusion_size),0,0])
            {
                translate([0,0,-main_lower_dist_z/2])
                lcd2004_extrusion_conn(part=part, orient=[0,0,-1], align=[-x,0,1]);
            }

            translate(lcd2004_offset)
            rotate([-mount_lcd2004_mount_angle,0,0])
            mount_lcd2004_parts(part=part, orient=[0,1,0], align=[0,1,0]);

        }
        if(show_gantry)
        {
            translate([0,main_depth/2,0])
            translate([0,extrusion_size/2,0])
            gantry_lower();
        }

    }
    else if(part == "neg")
    {
        for(x=[-1,1])
        translate([x*(lcd2004_width/2+extrusion_size),0,0])
        {
            translate([0,0,main_lower_dist_z/2-extrusion_size])
            lcd2004_extrusion_conn(part=part, orient=[0,0,1], align=[-x,0,-1]);

            translate([0,0,-main_lower_dist_z/2])
            {
                lcd2004_extrusion_conn(part=part, orient=[0,0,-1], align=[-x,0,1]);

            }
        }

        translate([0,10*mm,-extrusion_size/2])
        /*#rcubea([lcd2004_width+30*mm, extrusion_size+.2, main_lower_dist_z-extrusion_size-lcd2004_mount_thickness*2]);*/
        rcubea([1000, extrusion_size+.2, main_lower_dist_z-extrusion_size-lcd2004_mount_thickness*2]);

        /*translate([0,0,-extrusion_size/2])*/
        /*rcubea([lcd2004_width, extrusion_size+.2, main_lower_dist_z-extrusion_size-lcd2004_mount_thickness*1]);*/

        translate(lcd2004_offset)
        rotate([-mount_lcd2004_mount_angle,0,0])
        {
            mount_lcd2004_parts(part=part, orient=[0,1,0], align=[0,1,0]);

            translate([0,1000+5,0])
            rotate([90,0,0])
            linear_extrude(height=1000)
            projection(cut=false)
            rotate([-90,0,0])
            mount_lcd2004_parts(part=part, orient=[0,1,0], align=[0,1,0]);
        }

        translate(lcd2004_offset)
        translate([0,27,-13])
        translate([0,1000,0])
        rotate([90,0,0])
        linear_extrude(height=1000)
        projection(cut=false)
        rotate([-90,0,0])
        mount_lcd2004_parts(part=part, orient=[0,1,0], align=[0,1,0]);

        translate([0,main_depth/2,0])
        translate([0,extrusion_size/2,0])
        gantry_lower();
    }

}

/*$show_vit=true;*/

/*if(false)*/
{
    rotate([90+mount_lcd2004_mount_angle,0,0])
    translate(-lcd2004_offset)
    mount_lcd2004();
}

if(false)
{
    mount_lcd2004(show_gantry=true);
}

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


остаток фосфорной кислоты

остаток фосфорной кислоты

//Остаток фосфорной кислоты

$fn=270;
sphere(60);
translate([0,3,4]) cylinder(150,10,10);

error: pathspec '3D-models/SCAD/Phosphor.scad' did not match any file(s) known to git