main/xends: fix motor 1mm offset

main/xends: fix motor 1mm offset

include <MCAD/motors.scad>
include <MCAD/stepper.scad>

include <config.scad>
include <thing_libutils/misc.scad>
include <thing_libutils/bearing.scad>
use <thing_libutils/metric-screw.scad>

motor_mount_wall_thick = xaxis_pulley[1]+0*mm-xaxis_pulley[0]/2;
xaxis_end_motorsize = lookup(NemaSideSize,xaxis_motor);
xaxis_end_motor_offset=[xaxis_end_motorsize/2+9*mm,motor_mount_wall_thick,0];
xaxis_end_wz = xaxis_rod_distance+xaxis_bearing[2]+5*mm;

module xaxis_end_body(with_motor, nut_top=false)
{
    x_side = with_motor?1:-1;
    nut_h = zaxis_nut[4];
    wx = zaxis_bearing[1]/2+zaxis_nut[1];
    wx_ = with_motor? xaxis_end_motorsize+xaxis_end_motor_offset[0] - xaxis_end_motorsize/2 : wx;
    wy = xaxis_bearing[1]*2+xaxis_zaxis_distance_y;

    /*%cuberounda([wx_, xaxis_rod_d*2, xaxis_end_wz], rounding_radius=3, align=[with_motor?1:-1,0,0]);*/

    if(with_motor)
    translate(xaxis_end_motor_offset)
    cuberounda([xaxis_end_motorsize, motor_mount_wall_thick, xaxis_end_motorsize], rounding_radius=3, align=[0,-1,0]);

    // nut mount
    mirror([0,0,nut_top?1:0])
    translate([x_side*zaxis_rod_screw_distance_x, -xaxis_zaxis_distance_y, -xaxis_end_wz/2])
    {
        union()
        {
            fncylindera(h=zaxis_nut[4], d=zaxis_nut[1], align=[0,0,1]);

            // lead screw
            // ensure some support for the leadscrew cutout all the way to the top
            fncylindera(h=xaxis_end_wz, d=zaxis_nut[2]*2, align=[0,0,1]);
        }
    }

    // x axis rod holders
    for(z=[-1,1])
    translate([0,0,z*(xaxis_rod_distance/2)])
        fncylindera(h=wx_,d=xaxis_rod_d*2, orient=[1,0,0], align=[x_side,0,0]);

    // support around z axis bearings
    translate([0, -xaxis_zaxis_distance_y, 0])
    {
        difference()
        {
            sizey= zaxis_bearing[1]*2;
            fncylindera(h=xaxis_end_wz,d=sizey, orient=[0,0,1], align=[0,0,0]);
            translate([0,0,.1])
            cubea([sizey/2+.1, sizey+.2, xaxis_end_wz+.4], orient=[0,0,1], align=[-x_side,0,0]);
        }
    }
}

module xaxis_end(with_motor=false, show_motor=false, nut_top=false, show_nut=false, show_rods=false)
{
    x_side = with_motor?1:-1;
    nut_h = zaxis_nut[4];
    wx = zaxis_bearing[1]/2+zaxis_nut[1];
    wx_ = with_motor? xaxis_end_motorsize+xaxis_end_motor_offset[0] - xaxis_end_motorsize/2 : wx;
    wy = xaxis_bearing[1]*2+xaxis_zaxis_distance_y;
    xaxis_end_wz = xaxis_rod_distance+xaxis_bearing[2]+5*mm;
    difference()
    {
        extrasize = with_motor?0*mm:0*mm;
        extrasize_align = with_motor?-1:1;

        hull()
        {
            xaxis_end_body(with_motor, nut_top);

            // projection against z, ensure easy print
            translate([0,0,-xaxis_end_wz/2])
                linear_extrude(1)
                projection(cut=false)
                xaxis_end_body(with_motor);
        }

        xaxis_end_beltpath();

        // z smooth bearing mounts
        for(z=[-1,1])
            translate([0,0,z*xaxis_rod_distance/2])
                translate([0, -xaxis_zaxis_distance_y, 0])
                bearing_mount_holes(
                        zaxis_bearing,
                        ziptie_type,
                        ziptie_bearing_distance,
                        orient=[0,0,1],
                        show_zips=false
                );

        // x smooth rods
        for(z=[-1,1])
            translate([0,0,z*(xaxis_rod_distance/2)])
                fncylindera(h=xaxis_rod_l,d=xaxis_rod_d, orient=[1,0,0]);

        if(with_motor)
        {
            screw_dist = lookup(NemaDistanceBetweenMountingHoles, xaxis_motor);

            // axle
            translate(xaxis_end_motor_offset)
            {
                translate([0, .1, 0])
                translate([0,1,0])
                fncylindera(d=1.1*lookup(NemaRoundExtrusionDiameter, xaxis_motor), h=motor_mount_wall_thick, orient=[0,1,0], align=[0,1,0]);

                // motor axle
                translate([0, .1, 0])
                fncylindera(d=1.1*lookup(NemaAxleDiameter, xaxis_motor), h=lookup(NemaFrontAxleLength, xaxis_motor), orient=[0,1,0], align=[0,1,0]);

                // bearing for offloading force on motor shaft
                translate([0, -xaxis_pulley[1]-0*mm+.1, 0])
                scale(1.03)
                bearing(bearing_MR105, orient=[0,1,0], align=[0,-1,0]);

                xaxis_motor_thread=ThreadM3;
                xaxis_motor_nut=MHexNutM3;
                for(x=[-1,1])
                for(z=[-1,1])
                translate([x*screw_dist/2, -motor_mount_wall_thick, z*screw_dist/2])
                {
                    screw_cut(xaxis_motor_nut, h=motor_mount_wall_thick, with_nut=false, orient=[0,1,0], align=[0,1,0]);
                }
            }

        }

        // nut mount
        mirror([0,0,nut_top?1:0])
        translate([x_side*zaxis_rod_screw_distance_x, -xaxis_zaxis_distance_y, -xaxis_end_wz/2])
        {
            union()
            {
                translate([0,0,-.1])
                {
                    // nut
                    fncylindera(h=nut_h+1, d=zaxis_nut[0]*1.05, align=[0,0,1]);

                    // lead screw
                    translate([0,0,-.1])
                    fncylindera(h=xaxis_end_wz+1, d=zaxis_nut[2]*1.5, align=[0,0,1]);

                    for(i=[-1,1])
                        translate([i*13.5, 0, 0])
                            fncylindera(h=5, r=1.6, align=[0,0,1]);
                }
            }
        }
    }

    if(with_motor && show_motor)
    {
        translate(xaxis_end_motor_offset)
        {
            /*translate([0,-motor_mount_wall_thick,0])*/
            /*translate([0,-5,0])*/
            /*translate([0,-xaxis_pulley[0]/2,0])*/
            pulley(xaxis_pulley, flip=false, orient=[0,1,0], align=[0,-1,0]);
            translate([0,-1,0])

                motor(xaxis_motor, NemaMedium, dualAxis=false, orientation=[-90,0,0]);
        }
    }

    %if(show_nut)
    {
        mirror([0,0,nut_top?1:0])
        translate([x_side*zaxis_rod_screw_distance_x, -xaxis_zaxis_distance_y, -xaxis_end_wz/2-zaxis_nut[3]])
        xaxis_end_znut();
    }

    %if(show_rods)
    {
        for(z=[-1,1])
            translate([0,0,z*xaxis_rod_distance/2])
            translate([0, -xaxis_zaxis_distance_y, 0])
            fncylindera(d=zaxis_rod_d, h=zaxis_rod_l, orient=[0,0,1]);
    }
}

xaxis_end_beltpath_height = xaxis_pulley_inner_d+5*mm;
xaxis_end_beltpath_width = max(belt_width+3*mm, xaxis_pulley[0]+3*mm);

module xaxis_end_beltpath(xaxis_end_beltpath_length=1000)
{
    diag = pythag_hyp(xaxis_end_beltpath_width,xaxis_end_beltpath_width)/2;

    hull()
    for(z=[-1,1])
    translate([0,0,z*xaxis_end_beltpath_height/2])
    translate([-diag/2,0,0])
    translate([diag/2,0,0])
    rotate([z*-45,0,0])
    cubea([xaxis_end_beltpath_length, diag, diag]);
}

module xaxis_end_idlerholder(xaxis_end_beltpath_length=10)
{
    diag = pythag_hyp(xaxis_end_beltpath_width,xaxis_end_beltpath_width)/2;

    difference()
    {
        union()
        {
            cubea([10*mm, xaxis_end_beltpath_width/sqrt(2), xaxis_rod_distance], align=[1,0,0]);

            translate([10*mm, 0,0])
                cubea([15*mm, xaxis_idler_pulley[0]+8*mm, xaxis_rod_distance+xaxis_rod_d*2], align=[1,0,0]);
        }

        // x smooth rods
        for(z=[-1,1])
            translate([0,0,z*(xaxis_rod_distance/2)])
                fncylindera(h=xaxis_rod_l,d=xaxis_rod_d, orient=[1,0,0]);

        translate([20,0,0])
            pulley(xaxis_idler_pulley, orient=[0,1,0]);

        translate([10*mm+15*mm/2,0,0])
        fncylindera(d=lookup(ThreadSize, ThreadM5), h=100, orient=[0,1,0]);

        xaxis_end_beltpath();
    }
}

module xaxis_end_znut()
{
    difference()
    {
        union()
        {
            fncylindera(d=zaxis_nut[1], h=zaxis_nut[3], orient=[0,0,1], align=[0,0,1]);
            fncylindera(d=zaxis_nut[0], h=zaxis_nut[4], orient=[0,0,1], align=[0,0,1]);
        }
        translate([0,0,-.1])
            fncylindera(d=zaxis_nut[2], h=zaxis_nut[4]+.2, orient=[0,0,1], align=[0,0,1]);
    }
}

/*debug=false;*/
/*[>debug=true;<]*/
/*if(debug)*/
/*{*/
    /*// x smooth rods*/
    /*for(z=[-1,1])*/
        /*translate([0,0,z*(xaxis_rod_distance/2)])*/
            /*%fncylindera(h=xaxis_rod_l,d=xaxis_rod_d, orient=[1,0,0]);*/

    /*xaxis_end(with_motor=true, show_motor=true, nut_top=false, show_nut=true, show_rods=true);*/

    /*translate([150,0,0])*/
    /*{*/
        /*xaxis_end(with_motor=false, show_motor=true, nut_top=false, show_nut=true, show_rods=true);*/
        /*xaxis_end_idlerholder();*/
    /*}*/
/*}*/

/*print=false;*/
/*if(print)*/
/*{*/
    /*translate([0,0,xaxis_end_wz/2])*/
    /*xaxis_end(with_motor=true, show_motor=false, show_nut=false);*/

    /*translate([100,0,xaxis_end_wz/2])*/
    /*xaxis_end(with_motor=false, show_motor=false, show_nut=false);*/

    /*translate([50,30,25])*/
        /*rotate([0,90,0])*/
        /*xaxis_end_idlerholder();*/
/*}*/

include <MCAD/motors.scad>
include <MCAD/stepper.scad>

include <config.scad>
include <thing_libutils/misc.scad>
include <thing_libutils/bearing.scad>
use <thing_libutils/metric-screw.scad>

motor_mount_wall_thick = xaxis_pulley[1]+1*mm-xaxis_pulley[0]/2;
xaxis_end_motorsize = lookup(NemaSideSize,xaxis_motor);
xaxis_end_motor_offset=[xaxis_end_motorsize/2+9*mm,motor_mount_wall_thick,0];

    xaxis_end_wz = xaxis_rod_distance+xaxis_bearing[2]+5*mm;
module xaxis_end_body(with_motor, nut_top=false)
{
    x_side = with_motor?1:-1;
    nut_h = zaxis_nut[4];
    wx = zaxis_bearing[1]/2+zaxis_nut[1];
    wx_ = with_motor? xaxis_end_motorsize+xaxis_end_motor_offset[0] - xaxis_end_motorsize/2 : wx;
    wy = xaxis_bearing[1]*2+xaxis_zaxis_distance_y;

    /*%cuberounda([wx_, xaxis_rod_d*2, xaxis_end_wz], rounding_radius=3, align=[with_motor?1:-1,0,0]);*/

    if(with_motor)
    translate(xaxis_end_motor_offset)
    translate([0,1*mm,0])
    cuberounda([xaxis_end_motorsize, motor_mount_wall_thick, xaxis_end_motorsize], rounding_radius=3, align=[0,-1,0]);

    // nut mount
    mirror([0,0,nut_top?1:0])
    translate([x_side*zaxis_rod_screw_distance_x, -xaxis_zaxis_distance_y, -xaxis_end_wz/2])
    {
        union()
        {
            fncylindera(h=zaxis_nut[4], d=zaxis_nut[1], align=[0,0,1]);

            // lead screw
            // ensure some support for the leadscrew cutout all the way to the top
            fncylindera(h=xaxis_end_wz, d=zaxis_nut[2]*2, align=[0,0,1]);
        }
    }

    // x axis rod holders
    for(z=[-1,1])
    translate([0,0,z*(xaxis_rod_distance/2)])
        fncylindera(h=wx_,d=xaxis_rod_d*2, orient=[1,0,0], align=[x_side,0,0]);

    // support around z axis bearings
    translate([0, -xaxis_zaxis_distance_y, 0])
    {
        difference()
        {
            sizey= zaxis_bearing[1]*2;
            fncylindera(h=xaxis_end_wz,d=sizey, orient=[0,0,1], align=[0,0,0]);
            translate([0,0,.1])
            cubea([sizey/2+.1, sizey+.2, xaxis_end_wz+.4], orient=[0,0,1], align=[-x_side,0,0]);
        }
    }
}

module xaxis_end(with_motor=false, show_motor=false, nut_top=false, show_nut=false, show_rods=false)
{
    x_side = with_motor?1:-1;
    nut_h = zaxis_nut[4];
    wx = zaxis_bearing[1]/2+zaxis_nut[1];
    wx_ = with_motor? xaxis_end_motorsize+xaxis_end_motor_offset[0] - xaxis_end_motorsize/2 : wx;
    wy = xaxis_bearing[1]*2+xaxis_zaxis_distance_y;
    xaxis_end_wz = xaxis_rod_distance+xaxis_bearing[2]+5*mm;
    difference()
    {
        extrasize = with_motor?0*mm:0*mm;
        extrasize_align = with_motor?-1:1;

        hull()
        {
            xaxis_end_body(with_motor, nut_top);

            // projection against z, ensure easy print
            translate([0,0,-xaxis_end_wz/2])
                linear_extrude(1)
                projection(cut=false)
                xaxis_end_body(with_motor);
        }

        xaxis_end_beltpath();

        // z smooth bearing mounts
        for(z=[-1,1])
            translate([0,0,z*xaxis_rod_distance/2])
                translate([0, -xaxis_zaxis_distance_y, 0])
                bearing_mount_holes(
                        zaxis_bearing,
                        ziptie_type,
                        ziptie_bearing_distance,
                        orient=[0,0,1],
                        show_zips=false
                );

        // x smooth rods
        for(z=[-1,1])
            translate([0,0,z*(xaxis_rod_distance/2)])
                fncylindera(h=xaxis_rod_l,d=xaxis_rod_d, orient=[1,0,0]);

        if(with_motor)
        {
            screw_dist = lookup(NemaDistanceBetweenMountingHoles, xaxis_motor);

            // axle
            translate(xaxis_end_motor_offset)
            {
                translate([0, .1, 0])
                translate([0,1,0])
                fncylindera(d=1.1*lookup(NemaRoundExtrusionDiameter, xaxis_motor), h=motor_mount_wall_thick, orient=[0,1,0], align=[0,1,0]);

                // motor axle
                translate([0, .1, 0])
                fncylindera(d=1.1*lookup(NemaAxleDiameter, xaxis_motor), h=lookup(NemaFrontAxleLength, xaxis_motor), orient=[0,1,0], align=[0,1,0]);

                // bearing for offloading force on motor shaft
                translate([0, -xaxis_pulley[1]-1*mm+.1, 0])
                scale(1.03)
                bearing(bearing_MR105, orient=[0,1,0], align=[0,-1,0]);

                xaxis_motor_thread=ThreadM3;
                xaxis_motor_nut=MHexNutM3;
                for(x=[-1,1])
                for(z=[-1,1])
                translate([x*screw_dist/2, -motor_mount_wall_thick, z*screw_dist/2])
                {
                    screw_cut(xaxis_motor_nut, h=motor_mount_wall_thick, with_nut=false, orient=[0,1,0], align=[0,1,0]);
                }
            }

        }

        // nut mount
        mirror([0,0,nut_top?1:0])
        translate([x_side*zaxis_rod_screw_distance_x, -xaxis_zaxis_distance_y, -xaxis_end_wz/2])
        {
            union()
            {
                translate([0,0,-.1])
                {
                    // nut
                    fncylindera(h=nut_h+1, d=zaxis_nut[0]*1.05, align=[0,0,1]);

                    // lead screw
                    translate([0,0,-.1])
                    fncylindera(h=xaxis_end_wz+1, d=zaxis_nut[2]*1.5, align=[0,0,1]);

                    for(i=[-1,1])
                        translate([i*13.5, 0, 0])
                            fncylindera(h=5, r=1.6, align=[0,0,1]);
                }
            }
        }
    }

    if(with_motor && show_motor)
    {
        translate(xaxis_end_motor_offset)
        {
            /*translate([0,-motor_mount_wall_thick,0])*/
            /*translate([0,-5,0])*/
            translate([0,-1,0])
            /*translate([0,-xaxis_pulley[0]/2,0])*/
            pulley(xaxis_pulley, flip=false, orient=[0,1,0], align=[0,-1,0]);

            motor(xaxis_motor, NemaMedium, dualAxis=false, orientation=[-90,0,0]);
        }
    }

    %if(show_nut)
    {
        mirror([0,0,nut_top?1:0])
        translate([x_side*zaxis_rod_screw_distance_x, -xaxis_zaxis_distance_y, -xaxis_end_wz/2-zaxis_nut[3]])
        xaxis_end_znut();
    }

    %if(show_rods)
    {
        for(z=[-1,1])
            translate([0,0,z*xaxis_rod_distance/2])
            translate([0, -xaxis_zaxis_distance_y, 0])
            fncylindera(d=zaxis_rod_d, h=zaxis_rod_l, orient=[0,0,1]);
    }
}

xaxis_end_beltpath_height = xaxis_pulley_inner_d+5*mm;
xaxis_end_beltpath_width = max(belt_width+3*mm, xaxis_pulley[0]+3*mm);

module xaxis_end_beltpath(xaxis_end_beltpath_length=1000)
{
    diag = pythag_hyp(xaxis_end_beltpath_width,xaxis_end_beltpath_width)/2;

    hull()
    for(z=[-1,1])
    translate([0,0,z*xaxis_end_beltpath_height/2])
    translate([-diag/2,0,0])
    translate([diag/2,0,0])
    rotate([z*-45,0,0])
    cubea([xaxis_end_beltpath_length, diag, diag]);
}

module xaxis_end_idlerholder(xaxis_end_beltpath_length=10)
{
    diag = pythag_hyp(xaxis_end_beltpath_width,xaxis_end_beltpath_width)/2;

    difference()
    {
        union()
        {
            cubea([10*mm, xaxis_end_beltpath_width/sqrt(2), xaxis_rod_distance], align=[1,0,0]);

            translate([10*mm, 0,0])
                cubea([15*mm, xaxis_idler_pulley[0]+8*mm, xaxis_rod_distance+xaxis_rod_d*2], align=[1,0,0]);
        }

        // x smooth rods
        for(z=[-1,1])
            translate([0,0,z*(xaxis_rod_distance/2)])
                fncylindera(h=xaxis_rod_l,d=xaxis_rod_d, orient=[1,0,0]);

        translate([20,0,0])
            pulley(xaxis_idler_pulley, orient=[0,1,0]);

        translate([10*mm+15*mm/2,0,0])
        fncylindera(d=lookup(ThreadSize, ThreadM5), h=100, orient=[0,1,0]);

        xaxis_end_beltpath();
    }
}

module xaxis_end_znut()
{
    difference()
    {
        union()
        {
            fncylindera(d=zaxis_nut[1], h=zaxis_nut[3], orient=[0,0,1], align=[0,0,1]);
            fncylindera(d=zaxis_nut[0], h=zaxis_nut[4], orient=[0,0,1], align=[0,0,1]);
        }
        translate([0,0,-.1])
            fncylindera(d=zaxis_nut[2], h=zaxis_nut[4]+.2, orient=[0,0,1], align=[0,0,1]);
    }
}

/*debug=false;*/
/*[>debug=true;<]*/
/*if(debug)*/
/*{*/
    /*// x smooth rods*/
    /*for(z=[-1,1])*/
        /*translate([0,0,z*(xaxis_rod_distance/2)])*/
            /*%fncylindera(h=xaxis_rod_l,d=xaxis_rod_d, orient=[1,0,0]);*/

    /*xaxis_end(with_motor=true, show_motor=true, nut_top=false, show_nut=true, show_rods=true);*/

    /*translate([150,0,0])*/
    /*{*/
        /*xaxis_end(with_motor=false, show_motor=true, nut_top=false, show_nut=true, show_rods=true);*/
        /*xaxis_end_idlerholder();*/
    /*}*/
/*}*/

/*print=false;*/
/*if(print)*/
/*{*/
    /*translate([0,0,xaxis_end_wz/2])*/
    /*xaxis_end(with_motor=true, show_motor=false, show_nut=false);*/

    /*translate([100,0,xaxis_end_wz/2])*/
    /*xaxis_end(with_motor=false, show_motor=false, show_nut=false);*/

    /*translate([50,30,25])*/
        /*rotate([0,90,0])*/
        /*xaxis_end_idlerholder();*/
/*}*/


extruder wip

extruder wip

use <thing_libutils/shapes.scad>;
use <thing_libutils/misc.scad>;
use <thing_libutils/transforms.scad>;
use <thing_libutils/attach.scad>;
use <thing_libutils/triangles.scad>
use <thing_libutils/linear-extrusion.scad>;
use <thing_libutils/bearing.scad>
use <thing_libutils/metric-screw.scad>

include <config.scad>

xaxis_carriage_bearing_distance = 8;
xaxis_carriage_padding = 2;
xaxis_carriage_mount_distance = 23;
xaxis_carriage_mount_offset_z = 0;
xaxis_carriage_teeth_height=xaxis_belt_width*1.5;
xaxis_carriage_mount_screws = ThreadM4;

xaxis_carriage_conn = [[0, -xaxis_bearing[1]/2 - xaxis_carriage_bearing_offset_y,0], [0,0,0]];

xaxis_carriage_beltfasten_w = 20;

hobbed_gear_d_outer = 12.65;
hobbed_gear_d_inner = 11.5;
hobbed_gear_h = 11;

extruder_gear_small_d_inner = 5.75*mm;
extruder_gear_big_d_inner = 29.35*mm;
extruder_gear_big_d_outer = 30.85*mm;
extruder_gear_big_h = [3.85*mm, 5*mm];

// 13t metal gear and 60t metal gear
extruder_gears_distance=extruder_gear_big_d_inner/2+extruder_gear_small_d_inner/2;

extruder_motor = dict_replace_multiple(Nema17,
        [
        [NemaLengthMedium, 11.75*mm],
        [NemaFrontAxleLength, 5*mm],
        ]);

// shaft from big gear to hobbed gear
extruder_shaft_d = 5*mm;

// dist between gear and motor
extruder_gear_motor_dist = .5*mm;
extruder_motor_angle = -80;
extruder_motor_offset_x = cos(extruder_motor_angle) * extruder_gears_distance;
extruder_motor_offset_z = sin(extruder_motor_angle) * extruder_gears_distance;
extruder_motor_holedist = lookup(NemaDistanceBetweenMountingHoles, extruder_motor);

extruder_gear_big_offset=[-extruder_motor_offset_x,0,extruder_motor_offset_z];

extruder_offset = [0,0,10*mm];
extruder_offset_a = -extruder_gear_big_offset+[
    0,
    xaxis_bearing[1] + xaxis_carriage_bearing_offset_y + 1*mm,
    0];
extruder_filapath_offset = [hobbed_gear_d_inner/2, -15*mm, 0];

guidler_bearing = bearing_MR105;
extruder_hotmount_clamp_thread = ThreadM3;

module x_carriage_base(show_bearings=false)
{
    bottom_width = xaxis_bearing[2] + 2*xaxis_carriage_padding;
    top_width = xaxis_bearing[2]*2 + xaxis_carriage_bearing_distance + 2*xaxis_carriage_padding;
    thickness = xaxis_bearing[1]/2 + xaxis_carriage_bearing_offset_y;

    hull()
    {
        // top bearings
        translate([0,0,xaxis_rod_distance/2])
            rcubea([top_width, thickness, xaxis_bearing[1]+xaxis_carriage_padding+ziptie_bearing_distance*2], align=[0,1,0]);

        /*rcubea([top_width,thickness,xaxis_rod_distance/2], align=[0,1,0]);*/

        // bottom bearing
        translate([0,0,-xaxis_rod_distance/2])
            rcubea([bottom_width, thickness, xaxis_bearing[1]+xaxis_carriage_padding+ziptie_bearing_distance*2], align=[0,1,0]);

    }
    translate([0,xaxis_bearing[1]/2+xaxis_carriage_bearing_offset_y+xaxis_carriage_beltpath_offset+.1,0])
    {
        translate([0,-xaxis_beltpath_width/2,0])
        for(x=[-1,1])
        translate([x*(xaxis_carriage_beltfasten_w/2+5),-xaxis_beltpath_width/2,xaxis_pulley_inner_d/2])
        rcubea([xaxis_carriage_beltfasten_w,xaxis_beltpath_width,xaxis_beltpath_height/3], align=[0,0,-1]);
    }

    if(show_bearings)
    {
        for(x=[-1,1])
        translate([
                x*(xaxis_carriage_bearing_distance+xaxis_bearing[2])/2,
                xaxis_bearing[1]/2 + xaxis_carriage_bearing_offset_y,
                xaxis_rod_distance/2
        ])
        bearing(xaxis_bearing, orient=[1,0,0]);

        translate([
                0,
                xaxis_bearing[1]/2 + xaxis_carriage_bearing_offset_y,
                -xaxis_rod_distance/2
        ])
        bearing(xaxis_bearing, orient=[1,0,0]);

        /*translate([0,xaxis_carriage_beltpath_offset,0])*/
        /*for(i=[-1,1])*/
        /*translate([i*100,0,0])*/
        /*pulley(xaxis_idler_pulley, orient=[0,1,0]);*/
    }

}

module x_carriage_holes()
{
    for(i=[-1,1])
    translate([
            i*(xaxis_bearing[2]/2+xaxis_carriage_bearing_distance/2),
            xaxis_bearing[1]/2+xaxis_carriage_bearing_offset_y,
            xaxis_rod_distance/2
    ])
    {
        bearing_mount_holes(xaxis_bearing, orient=[1,0,0]);
        cubea([xaxis_bearing[2]*2,xaxis_bearing[1]/2+10,xaxis_bearing[1]+1*mm], align=[0,1,0]);
    }

    translate([
            0,
            xaxis_bearing[1]/2+xaxis_carriage_bearing_offset_y,
            -xaxis_rod_distance/2])
    {
        bearing_mount_holes(xaxis_bearing, orient=[1,0,0]);
        cubea([xaxis_bearing[2]*2,xaxis_bearing[1]/2+10,xaxis_bearing[1]+1*mm], align=[0,1,0]);
    }

    // Extruder mounting holes
    /*translate([0,0,xaxis_carriage_mount_offset_z])*/
    /*for(j=[-1,1])*/
    /*for(i=[-1,1])*/
    /*{*/
        /*translate([i*xaxis_carriage_mount_distance/2,0,j*xaxis_carriage_mount_distance/2])*/
        /*{*/
            /*screw_dia = lookup(ThreadSize, xaxis_carriage_mount_screws);*/
            /*cylindera(d=screw_dia, h=100, orient=[0,1,0]);*/
        /*}*/
    /*}*/

    translate([0,xaxis_carriage_beltpath_offset+.1,0])
    {
        // Cut clearing space for the belt
        /*translate([0,-xaxis_beltpath_width/2,-xaxis_beltpath_height/2])*/
            /*#rcubea([500,xaxis_beltpath_width+1,5], align=[0,1,0], extrasize=[0,0,4], extrasize_align=[0,0,1]);*/

        translate([0,-xaxis_beltpath_width/2,0])
        {
            difference()
            {
                rcubea([500,xaxis_beltpath_width*2,xaxis_beltpath_height], align=[0,1,0]);
                for(x=[-1,1])
                translate([x*(xaxis_carriage_beltfasten_w/2+5),-xaxis_beltpath_width/2,xaxis_pulley_inner_d/2])
                    rcubea([xaxis_carriage_beltfasten_w,xaxis_beltpath_width*2,xaxis_beltpath_height/3], align=[0,1,-1]);
            }
        }

        /*belt_thickness=1.5;*/
        /*for(i=[-1,1])*/
            /*translate([i*30,0,0])*/
                /*rcubea([15,xaxis_beltpath_width,15-belt_thickness], align=[0,0,0]);*/

        // Cut in the middle for belt
        /*rcubea([7,xaxis_beltpath_width,xaxis_beltpath_height], align=[0,0,0]);*/

        /*translate([0,-xaxis_beltpath_width/2,xaxis_pulley_inner_d/2])*/
        /*{*/
            /*// Belt slit*/
            /*rcubea([500,xaxis_beltpath_width,belt_thickness], align=[0,1,0]);*/

            /*[>// Teeth cuts<]*/
            /*[>teeth = 50;<]*/
            /*[>teeth_height = 2;<]*/
            /*[>translate([-belt_tooth_distance/2*teeth-.5,0,0])<]*/
            /*[>for(i=[0:teeth])<]*/
            /*[>{<]*/
                /*[>translate([i*belt_tooth_distance,0,0])<]*/
                    /*[>cubea([belt_tooth_distance*belt_tooth_ratio,xaxis_carriage_teeth_height,teeth_height], align=[0,0,-1]);<]*/
            /*[>}<]*/
        /*}*/
    }
}

module extruder_gear_small()
{
    difference()
    {
        union()
        {
            hull()
            {
                cylindera(d=extruder_gear_small_d_inner, h=7*mm, orient=[0,1,0], align=[0,1,0]);
                cylindera(d=10*mm, h= 3*mm, orient=[0,1,0], align=[0,1,0]);
            }
            cylindera(d=extruder_gear_small_d_inner, h=13*mm, orient=[0,1,0], align=[0,1,0]);
        }
        cylindera(d=5*mm, h=13*mm+.1, orient=[0,1,0], align=[0,1,0]);
    }
}

module extruder_gear_big(align=[0,0,0], orient=[0,0,1])
{
    total_h = extruder_gear_big_h[0]+extruder_gear_big_h[1];
    size_align([extruder_gear_big_d_inner, extruder_gear_big_d_inner, total_h], align=align, orient=orient)
    translate([0,0,-extruder_gear_big_h[0] + total_h/2])
    difference()
    {
        union()
        {
            cylindera(d=extruder_gear_big_d_inner, h=extruder_gear_big_h[0], orient=[0,0,1], align=[0,0,1]);
            cylindera(d=12*mm, h=extruder_gear_big_h[1], orient=[0,0,1], align=[0,0,-1]);
        }
        translate([0,0,-.5])
        cylindera(d=5*mm, h=total_h+.2, orient=[0,0,1], align=[0,0,0]);
    }
}

module motor_mount_cut(motor=Nema17, h=10*mm)
{
    screw_dist = lookup(NemaDistanceBetweenMountingHoles, motor);

    // round dia
    translate([0, .1, 0])
    cylindera(d=1.1*lookup(NemaRoundExtrusionDiameter, motor), h=h, orient=[0,1,0], align=[0,1,0]);

    // motor axle
    translate([0, .1, 0])
    cylindera(d=1.2*lookup(NemaAxleDiameter, motor), h=lookup(NemaFrontAxleLength, motor)+2*mm, orient=[0,1,0], align=[0,1,0]);

    // bearing for offloading force on motor shaft
    /*translate([0, -1*mm-xaxis_pulley[1]-.1, 0])*/
    scale(1.03)
    bearing(bearing_MR105, override_h=h, orient=[0,1,0], align=[0,-1,0]);

    motor_thread=ThreadM3;
    motor_nut=MHexNutM3;
    for(x=[-1,1])
    for(z=[-1,1])
    translate([x*screw_dist/2, -h, z*screw_dist/2])
    {
        if(x!=-1 || z!=-1)
        screw_cut(motor_nut, h=h, with_nut=false, orient=[0,1,0], align=[0,1,0]);
    }
}
extruder_a_h = 14*mm;

module extruder_a(show_vitamins=false)
{
    difference()
    {
        hull()
        /*union()*/
        {
            side = 15*mm;
            rcubea([extruder_motor_holedist+side/2,extruder_a_h,extruder_motor_holedist+side/2], align=[0,1,0]);
            /*hull()*/
            /*{*/
                /*for(x=[-1,1])*/
                /*for(z=[-1,1])*/
                /*translate([(extruder_motor_holedist/2)*x,0,(extruder_motor_holedist/2)*z])*/
                /*rotate([0,x*45,0])*/
                /*rcubea([side/2,extruder_a_h,side/2], align=[0,1,0]);*/
            /*}*/
            translate(extruder_gear_big_offset)
            cylindera(d=extruder_gear_big_d_outer+3*mm, h=extruder_a_h, orient=[0,1,0], align=[0,-1,0], round_radius=2);
        }

        translate([0,extruder_a_h,0])
        {
            translate(extruder_gear_big_offset)
            {
                /*scale([1.3,2.0,1.3])*/
                /*#extruder_gear_big(orient=[0,-1,0], align=[0,-1,0]);*/

                // big gear cutout
                translate([0,-bearing_MR105[2]+.1,0])
                cylindera(d=extruder_gear_big_d_outer+1*mm, h=extruder_a_h+.2, orient=[0,1,0], align=[0,1,0]);

                translate([0,.1,0])
                cylindera(d=extruder_shaft_d+.5*mm, h=extruder_a_h+.2, orient=[0,1,0], align=[0,1,0]);

                translate([0,.1,0])
                scale(1.03)
                bearing(bearing_MR105, override_h=6*mm, orient=[0,1,0], align=[0,-1,0]);
            }

            motor_mount_cut(extruder_motor, h=extruder_a_h+1);
        }

    }

    if(show_vitamins)
    translate([0,extruder_a_h,0])
    {
        translate([0,-extruder_gear_motor_dist,0])
        {
            extruder_gear_small();

            // big gear
            translate(extruder_gear_big_offset)
            {
                translate([0,1,0])
                translate([0,-bearing_MR105[2]+.1,0])
                extruder_gear_big(orient=[0,-1,0], align=[0,-1,0]);

                translate([0,1,0])
                bearing(bearing_MR105, orient=[0,1,0], align=[0,-1,0]);

                translate([0,bearing_MR105[2],0])
                {
                    cylindera(h=60*mm, d=extruder_shaft_d, orient=[0,1,0], align=[0,1,0]);
                }
            }
        }
        motor(extruder_motor, NemaMedium, dualAxis=false, orientation=[-90,0,0]);
    }
}

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

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

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

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

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

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

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

        }

        // clamp mount screw holes
        for(i=[-1,1])
        {
            translate([.1, i*hotmount_clamp_screws_dist, 0])
                rotate([0,90,0])
                cylindera(d=lookup(ThreadSize, extruder_hotmount_clamp_thread), h=hotmount_clamp_thickness+.2, align=[0,0,-hotmount_clamp_side], extra_h=2);
        }
    }
}

extruder_b_bearing = bearing_MR105;
extruder_b_w = hobbed_gear_d_outer+10*mm;

guidler_arm_len = 15*mm;

extruder_offset_guidler = extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0]+[guidler_bearing[1],0,0];

guidler_mount_off_d=-guidler_bearing[1]/1.7;
guidler_mount_off_h=-guidler_bearing[1]/1.7;
extruder_guidler_mount_off = [hobbed_gear_d_inner/2+10,0,guidler_mount_off_h];

module extruder_b(show_vitamins=false)
{
    difference()
    {
        /*hull()*/
        union()
        {
            // main house
            extruder_b_size=[10,extruder_filapath_offset,10];
            rcubea(extruder_b_size);

            // gear support
            translate([0,-hobbed_gear_h/2,0])
            {
                // hobbed gear support
                cylindera(d=hobbed_gear_d_outer+5*mm, h=abs(extruder_filapath_offset[1])+hobbed_gear_h/2, align=[0,-1,0], orient=[0,1,0]);

                // bearing support
                cylindera(d=extruder_b_bearing[1]+5*mm, h=extruder_b_bearing[2]+4*mm, align=[0,1,0], orient=[0,1,0]);

            }

            // guidler mount
            translate(extruder_guidler_mount_off)
            {
                cylindera(d=guidler_mount_d, h=guidler_mount_w, orient=[0,1,0]);
            }

            // hotmount support
            translate([hobbed_gear_d_inner/2,0,-hobbed_gear_d_outer/2 + hotmount_offset_h])
            cubea([extruder_b_w, hotmount_outer_size_xy, hotmount_outer_size_h], align=[0,0,-1]);

            // clamp mount screw holes
            translate([hobbed_gear_d_inner/2,0,-hobbed_gear_d_outer/2 + hotmount_offset_h])
            for(i=[-1,1])
            {
                translate([0, i*hotmount_clamp_screws_dist, -hotmount_d_h[0][1]-hotmount_d_h[1][1]/2])
                cylindera(d=lookup(ThreadSize, extruder_hotmount_clamp_thread)+6*mm, h=extruder_b_w, orient=[1,0,0]);
            }
        }

        // guidler mount screw
        translate(extruder_guidler_mount_off)
        {
            cylindera(d=lookup(ThreadSize, guidler_screws_thread), h=guidler_mount_w+.1, orient=[0,1,0]);
        }

        // hobbed gear (inner)
        cylindera(h=hobbed_gear_h, d=hobbed_gear_d_outer+2*mm, orient=[0,1,0], align=[0,0,0]);

        // hotmount clamp screws
        translate([hobbed_gear_d_inner/2,0,-hobbed_gear_d_outer/2 + hotmount_offset_h])
            for(i=[-1,1])
            {
                translate([0, i*hotmount_clamp_screws_dist, -hotmount_d_h[0][1]-hotmount_d_h[1][1]/2])
                    rotate([0,90,0])
                    cylindera(d=lookup(ThreadSize, extruder_hotmount_clamp_thread), h=extruder_b_w+10);
            }

        // filament path
        translate([hobbed_gear_d_outer/2,0,0])
            cylindera(h=1000, d=4*mm, orient=[0,0,1], align=[0,0,0]);

        // gear cutout
        translate([0,-hobbed_gear_h/2-.5*mm,0])
            cylindera(d=extruder_b_bearing[1]+.3*mm, h=extruder_b_bearing[2]+.5*mm, align=[0,1,0], orient=[0,1,0]);

        for(x=[1])
        translate([x*hobbed_gear_d_inner/2,0,0])
        scale([1.03,1,1.03])
        {
            cubea([guidler_bearing[1]+1*mm,guidler_w+1*mm,guidler_bearing[1]*2], align=[x,0,1]);
            cylindera(d=guidler_bearing[1]+1*mm, h=guidler_w+1*mm, orient=[0,1,0], align=[x,0,0]);
        }

        translate([hobbed_gear_d_inner/2,0,-hobbed_gear_d_outer/2 + hotmount_offset_h+.01])
        {
            hotmount_cutout(extend_cut=true);

            // clamp mount screw holes
            for(i=[-1,1])
            {
                translate([0, i*hotmount_clamp_screws_dist, -hotmount_d_h[0][1]-hotmount_d_h[1][1]/2])
                cylindera(d=lookup(ThreadSize, extruder_hotmount_clamp_thread), h=extruder_b_w+1, orient=[1,0,0]);
            }

            // hotmount clamp cutout
            translate([extruder_b_w/2 * (hotmount_clamp_side), 0, -hotmount_d_h[0][1]-hotmount_d_h[1][1]/2])
            {
                rcubea([hotmount_clamp_thickness+0.2, hotmount_clamp_y+0.2, hotmount_clamp_height+0.2], align=[-hotmount_clamp_side,0,0], extrasize=[1,0,0], extrasize_align=[hotmount_clamp_side,0,0]);
            }
        }
    }

    if(show_vitamins)
    {
        translate([hobbed_gear_d_inner/2,0,-hobbed_gear_d_outer/2 + hotmount_offset_h+.01])
            translate([extruder_b_w/2 * (hotmount_clamp_side), 0, -hotmount_d_h[0][1]-hotmount_d_h[1][1]/2])
            hotmount_clamp();

        translate([0,-hobbed_gear_h/2-extruder_b_bearing[2]-.5*mm,0])
        {
            cylindera(h=extruder_a_h+extruder_offset_a[1]-extruder_filapath_offset[1], d=extruder_shaft_d, orient=[0,1,0], align=[0,-1,0]);

            bearing(extruder_b_bearing, orient=[0,1,0], align=[0,1,0]);
        }

        // hobbed gear
        cylindera(h=hobbed_gear_h, d=hobbed_gear_d_inner, orient=[0,1,0], align=[0,0,0]);
        for(y=[-1,1])
            translate([0,y*hobbed_gear_h/2,0])
            {
                cylindera(h=hobbed_gear_h/3, d=hobbed_gear_d_outer, orient=[0,1,0], align=[0,y,0]);
            }
    }
}

// Final part
module x_carriage(show_bearings=true)
{
    difference()
    {
        /*hull()*/
        union()
        {
            x_carriage_base(show_bearings=show_bearings);
            translate(extruder_offset)
            translate(extruder_offset_a)
            {
                for(x=[-1,1])
                for(z=[-1,1])
                translate([x*extruder_motor_holedist/2,0,z*extruder_motor_holedist/2])
                cylindera(d=10*mm, h=extruder_offset_a[1], orient=[0,1,0], align=[0,1,0], round_radius=2);
            }
        }
        translate(extruder_offset)
        translate(extruder_offset_a)
        {
            for(x=[-1,1])
            for(z=[-1,1])
            translate([x*extruder_motor_holedist/2,0,z*extruder_motor_holedist/2])
            translate([0,.1,0])
            cylindera(d=3*mm, h=extruder_offset_a[1]+.2, orient=[0,1,0], align=[0,1,0]);
        }
        x_carriage_holes();
    }
}

/*translate([0,-42,38])*/
/*rotate([0,0,90])*/
/*translate([0,-1,-42])*/
/*translate([-83,25,-42])*/
/*rotate([90,0,0])*/
/*import("stl/i3R_Compact_E3Dv6_Extruder_1.75_01.STL");*/

module x_extruder_hotend()
{
    hotend_conn =[[0,0,27.8-hotmount_offset_h],[0,0,1]];
    translate(extruder_offset)
    translate(extruder_filapath_offset)
    attach(extruder_conn_hotend, hotend_conn)
        rotate([90,0,270])
        %import("stl/E3D_V6_1.75mm_Universal_HotEnd_Mockup.stl");

}

house_w = 20;
house_h = 30;

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

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

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

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

guidler_srew_distance = 10;

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

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

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

                // guidler bearing bolt holder
                cylindera(d=guidler_bearing[0]*1.5,h=guidler_w, orient=[1,0,0]);
            }

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

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

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

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

            }
        }

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

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

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

        // mount bolt hole
        translate([0,guidler_mount_off_d, guidler_mount_off_h])
        cylindera(d=lookup(ThreadSize, guidler_screws_thread),h=100, orient=[1,0,0]);

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

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

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

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

extruder_offset_b = extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0];

/*if(false)*/
{
    %x_carriage(show_bearings=false);

    translate(extruder_offset)
    {
        translate(extruder_offset_a)
        extruder_a(show_vitamins=true);

        translate(extruder_offset_b)
        {
            extruder_b(show_vitamins=true);
        }

        translate(extruder_offset_guidler)
        rotate([0,0,90])
        {
            extruder_guidler(show_extras=true);
        }
    }
    //filament path
    %translate(extruder_filapath_offset)
        cylindera(h=1000, d=1.75*mm, orient=[0,0,1], align=[0,0,0]);
}

use <thing_libutils/shapes.scad>;
use <thing_libutils/misc.scad>;
use <thing_libutils/transforms.scad>;
use <thing_libutils/attach.scad>;
use <thing_libutils/triangles.scad>
use <thing_libutils/linear-extrusion.scad>;
use <thing_libutils/bearing.scad>
use <thing_libutils/metric-screw.scad>

include <config.scad>

xaxis_carriage_bearing_distance = 8;
xaxis_carriage_padding = 2;
xaxis_carriage_mount_distance = 23;
xaxis_carriage_mount_offset_z = 0;
xaxis_carriage_teeth_height=xaxis_belt_width*1.5;
xaxis_carriage_mount_screws = ThreadM4;

xaxis_carriage_conn = [[0, -xaxis_bearing[1]/2 - xaxis_carriage_bearing_offset_y,0], [0,0,0]];

xaxis_carriage_beltfasten_w = 20;

hobbed_gear_d_outer = 12.65;
hobbed_gear_d_inner = 11.5;
hobbed_gear_h = 11;

extruder_gear_small_d_inner = 5.75*mm;
extruder_gear_big_d_inner = 29.35*mm;
extruder_gear_big_d_outer = 30.85*mm;
extruder_gear_big_h = [3.85*mm, 5*mm];

// 13t metal gear and 60t metal gear
extruder_gears_distance=extruder_gear_big_d_inner/2+extruder_gear_small_d_inner/2;

extruder_motor = dict_replace_multiple(Nema17,
        [
        [NemaLengthMedium, 11.75*mm],
        [NemaFrontAxleLength, 5*mm],
        ]);

// shaft from big gear to hobbed gear
extruder_shaft_d = 5*mm;

// dist between gear and motor
extruder_gear_motor_dist = .5*mm;
extruder_motor_angle = -80;
extruder_motor_offset_x = cos(extruder_motor_angle) * extruder_gears_distance;
extruder_motor_offset_z = sin(extruder_motor_angle) * extruder_gears_distance;
extruder_motor_holedist = lookup(NemaDistanceBetweenMountingHoles, extruder_motor);

extruder_gear_big_offset=[-extruder_motor_offset_x,0,extruder_motor_offset_z];

extruder_offset = [0,0,10*mm];
extruder_offset_a = -extruder_gear_big_offset+[
    0,
    xaxis_bearing[1] + xaxis_carriage_bearing_offset_y + 1*mm,
    0];
extruder_filapath_offset = [hobbed_gear_d_inner/2, -15*mm, 0];

extruder_guilder_bearing = bearing_625;
extruder_hotmount_clamp_thread = ThreadM3;

module x_carriage_base(show_bearings=false)
{
    bottom_width = xaxis_bearing[2] + 2*xaxis_carriage_padding;
    top_width = xaxis_bearing[2]*2 + xaxis_carriage_bearing_distance + 2*xaxis_carriage_padding;
    thickness = xaxis_bearing[1]/2 + xaxis_carriage_bearing_offset_y;

    hull()
    {
        // top bearings
        translate([0,0,xaxis_rod_distance/2])
            rcubea([top_width, thickness, xaxis_bearing[1]+xaxis_carriage_padding+ziptie_bearing_distance*2], align=[0,1,0]);

        /*rcubea([top_width,thickness,xaxis_rod_distance/2], align=[0,1,0]);*/

        // bottom bearing
        translate([0,0,-xaxis_rod_distance/2])
            rcubea([bottom_width, thickness, xaxis_bearing[1]+xaxis_carriage_padding+ziptie_bearing_distance*2], align=[0,1,0]);

    }
    translate([0,xaxis_bearing[1]/2+xaxis_carriage_bearing_offset_y+xaxis_carriage_beltpath_offset+.1,0])
    {
        translate([0,-xaxis_beltpath_width/2,0])
        for(x=[-1,1])
        translate([x*(xaxis_carriage_beltfasten_w/2+5),-xaxis_beltpath_width/2,xaxis_pulley_inner_d/2])
        rcubea([xaxis_carriage_beltfasten_w,xaxis_beltpath_width,xaxis_beltpath_height/3], align=[0,0,-1]);
    }

    if(show_bearings)
    {
        for(x=[-1,1])
        translate([
                x*(xaxis_carriage_bearing_distance+xaxis_bearing[2])/2,
                xaxis_bearing[1]/2 + xaxis_carriage_bearing_offset_y,
                xaxis_rod_distance/2
        ])
        bearing(xaxis_bearing, orient=[1,0,0]);

        translate([
                0,
                xaxis_bearing[1]/2 + xaxis_carriage_bearing_offset_y,
                -xaxis_rod_distance/2
        ])
        bearing(xaxis_bearing, orient=[1,0,0]);

        /*translate([0,xaxis_carriage_beltpath_offset,0])*/
        /*for(i=[-1,1])*/
        /*translate([i*100,0,0])*/
        /*pulley(xaxis_idler_pulley, orient=[0,1,0]);*/
    }

}

module x_carriage_holes()
{
    for(i=[-1,1])
    translate([
            i*(xaxis_bearing[2]/2+xaxis_carriage_bearing_distance/2),
            xaxis_bearing[1]/2+xaxis_carriage_bearing_offset_y,
            xaxis_rod_distance/2
    ])
    {
        bearing_mount_holes(xaxis_bearing, orient=[1,0,0]);
        cubea([xaxis_bearing[2]*2,xaxis_bearing[1]/2+10,xaxis_bearing[1]+1*mm], align=[0,1,0]);
    }

    translate([
            0,
            xaxis_bearing[1]/2+xaxis_carriage_bearing_offset_y,
            -xaxis_rod_distance/2])
    {
        bearing_mount_holes(xaxis_bearing, orient=[1,0,0]);
        cubea([xaxis_bearing[2]*2,xaxis_bearing[1]/2+10,xaxis_bearing[1]+1*mm], align=[0,1,0]);
    }

    // Extruder mounting holes
    /*translate([0,0,xaxis_carriage_mount_offset_z])*/
    /*for(j=[-1,1])*/
    /*for(i=[-1,1])*/
    /*{*/
        /*translate([i*xaxis_carriage_mount_distance/2,0,j*xaxis_carriage_mount_distance/2])*/
        /*{*/
            /*screw_dia = lookup(ThreadSize, xaxis_carriage_mount_screws);*/
            /*cylindera(d=screw_dia, h=100, orient=[0,1,0]);*/
        /*}*/
    /*}*/

    translate([0,xaxis_carriage_beltpath_offset+.1,0])
    {
        // Cut clearing space for the belt
        /*translate([0,-xaxis_beltpath_width/2,-xaxis_beltpath_height/2])*/
            /*#rcubea([500,xaxis_beltpath_width+1,5], align=[0,1,0], extrasize=[0,0,4], extrasize_align=[0,0,1]);*/

        translate([0,-xaxis_beltpath_width/2,0])
        {
            difference()
            {
                rcubea([500,xaxis_beltpath_width*2,xaxis_beltpath_height], align=[0,1,0]);
                for(x=[-1,1])
                translate([x*(xaxis_carriage_beltfasten_w/2+5),-xaxis_beltpath_width/2,xaxis_pulley_inner_d/2])
                    rcubea([xaxis_carriage_beltfasten_w,xaxis_beltpath_width*2,xaxis_beltpath_height/3], align=[0,1,-1]);
            }
        }

        /*belt_thickness=1.5;*/
        /*for(i=[-1,1])*/
            /*translate([i*30,0,0])*/
                /*rcubea([15,xaxis_beltpath_width,15-belt_thickness], align=[0,0,0]);*/

        // Cut in the middle for belt
        /*rcubea([7,xaxis_beltpath_width,xaxis_beltpath_height], align=[0,0,0]);*/

        /*translate([0,-xaxis_beltpath_width/2,xaxis_pulley_inner_d/2])*/
        /*{*/
            /*// Belt slit*/
            /*rcubea([500,xaxis_beltpath_width,belt_thickness], align=[0,1,0]);*/

            /*[>// Teeth cuts<]*/
            /*[>teeth = 50;<]*/
            /*[>teeth_height = 2;<]*/
            /*[>translate([-belt_tooth_distance/2*teeth-.5,0,0])<]*/
            /*[>for(i=[0:teeth])<]*/
            /*[>{<]*/
                /*[>translate([i*belt_tooth_distance,0,0])<]*/
                    /*[>cubea([belt_tooth_distance*belt_tooth_ratio,xaxis_carriage_teeth_height,teeth_height], align=[0,0,-1]);<]*/
            /*[>}<]*/
        /*}*/
    }
}

module extruder_gear_small()
{
    difference()
    {
        union()
        {
            hull()
            {
                cylindera(d=extruder_gear_small_d_inner, h=7*mm, orient=[0,1,0], align=[0,1,0]);
                cylindera(d=10*mm, h= 3*mm, orient=[0,1,0], align=[0,1,0]);
            }
            cylindera(d=extruder_gear_small_d_inner, h=13*mm, orient=[0,1,0], align=[0,1,0]);
        }
        cylindera(d=5*mm, h=13*mm+.1, orient=[0,1,0], align=[0,1,0]);
    }
}

module extruder_gear_big(align=[0,0,0], orient=[0,0,1])
{
    total_h = extruder_gear_big_h[0]+extruder_gear_big_h[1];
    size_align([extruder_gear_big_d_inner, extruder_gear_big_d_inner, total_h], align=align, orient=orient)
    translate([0,0,-extruder_gear_big_h[0] + total_h/2])
    difference()
    {
        union()
        {
            cylindera(d=extruder_gear_big_d_inner, h=extruder_gear_big_h[0], orient=[0,0,1], align=[0,0,1]);
            cylindera(d=12*mm, h=extruder_gear_big_h[1], orient=[0,0,1], align=[0,0,-1]);
        }
        translate([0,0,-.5])
        cylindera(d=5*mm, h=total_h+.2, orient=[0,0,1], align=[0,0,0]);
    }
}

module motor_mount_cut(motor=Nema17, h=10*mm)
{
    screw_dist = lookup(NemaDistanceBetweenMountingHoles, motor);

    // round dia
    translate([0, .1, 0])
    cylindera(d=1.1*lookup(NemaRoundExtrusionDiameter, motor), h=h, orient=[0,1,0], align=[0,1,0]);

    // motor axle
    translate([0, .1, 0])
    cylindera(d=1.2*lookup(NemaAxleDiameter, motor), h=lookup(NemaFrontAxleLength, motor)+2*mm, orient=[0,1,0], align=[0,1,0]);

    // bearing for offloading force on motor shaft
    /*translate([0, -1*mm-xaxis_pulley[1]-.1, 0])*/
    scale(1.03)
    bearing(bearing_MR105, override_h=h, orient=[0,1,0], align=[0,-1,0]);

    motor_thread=ThreadM3;
    motor_nut=MHexNutM3;
    for(x=[-1,1])
    for(z=[-1,1])
    translate([x*screw_dist/2, -h, z*screw_dist/2])
    {
        if(x!=-1 || z!=-1)
        screw_cut(motor_nut, h=h, with_nut=false, orient=[0,1,0], align=[0,1,0]);
    }
}
extruder_a_h = 14*mm;

module extruder_a(show_vitamins=false)
{
    difference()
    {
        hull()
        /*union()*/
        {
            side = 15*mm;
            rcubea([extruder_motor_holedist+side/2,extruder_a_h,extruder_motor_holedist+side/2], align=[0,1,0]);
            /*hull()*/
            /*{*/
                /*for(x=[-1,1])*/
                /*for(z=[-1,1])*/
                /*translate([(extruder_motor_holedist/2)*x,0,(extruder_motor_holedist/2)*z])*/
                /*rotate([0,x*45,0])*/
                /*rcubea([side/2,extruder_a_h,side/2], align=[0,1,0]);*/
            /*}*/
            translate(extruder_gear_big_offset)
            cylindera(d=extruder_gear_big_d_outer+3*mm, h=extruder_a_h, orient=[0,1,0], align=[0,-1,0], round_radius=2);
        }

        translate([0,extruder_a_h,0])
        {
            translate(extruder_gear_big_offset)
            {
                /*scale([1.3,2.0,1.3])*/
                /*#extruder_gear_big(orient=[0,-1,0], align=[0,-1,0]);*/

                // big gear cutout
                translate([0,-bearing_MR105[2]+.1,0])
                cylindera(d=extruder_gear_big_d_outer+1*mm, h=extruder_a_h+.2, orient=[0,1,0], align=[0,1,0]);

                translate([0,.1,0])
                cylindera(d=extruder_shaft_d+.5*mm, h=extruder_a_h+.2, orient=[0,1,0], align=[0,1,0]);

                translate([0,.1,0])
                scale(1.03)
                bearing(bearing_MR105, override_h=6*mm, orient=[0,1,0], align=[0,-1,0]);
            }

            motor_mount_cut(extruder_motor, h=extruder_a_h+1);
        }

    }

    if(show_vitamins)
    translate([0,extruder_a_h,0])
    {
        translate([0,-extruder_gear_motor_dist,0])
        {
            extruder_gear_small();

            // big gear
            translate(extruder_gear_big_offset)
            {
                translate([0,1,0])
                translate([0,-bearing_MR105[2]+.1,0])
                extruder_gear_big(orient=[0,-1,0], align=[0,-1,0]);

                translate([0,1,0])
                bearing(bearing_MR105, orient=[0,1,0], align=[0,-1,0]);

                translate([0,bearing_MR105[2],0])
                {
                    cylindera(h=60*mm, d=extruder_shaft_d, orient=[0,1,0], align=[0,1,0]);
                }
            }
        }
        motor(extruder_motor, NemaMedium, dualAxis=false, orientation=[-90,0,0]);
    }
}

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

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

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

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

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

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

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

        }

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

extruder_b_bearing = bearing_MR105;
extruder_b_w = hobbed_gear_d_outer+10*mm;

module extruder_b(show_vitamins=false)
{
    translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])
    {
        // guidler mount
        guidler_arm_len = 15*mm;
        translate([hobbed_gear_d_inner/2,0,guidler_arm_len])
        {
            difference()
            {
                cylindera(d=2*lookup(ThreadSize, ThreadM3), h=10*mm, orient=[0,1,0]);
                cylindera(d=2*lookup(ThreadSize, ThreadM3), h=10*mm, orient=[0,1,0]);
            }
        }

        difference()
        {
            /*hull()*/
            union()
            {
                // main house
                extruder_b_size=[10,extruder_filapath_offset,10];
                #rcubea(extruder_b_size);

                // gear support
                translate([0,-hobbed_gear_h/2,0])
                {
                    // hobbed gear support
                    cylindera(d=hobbed_gear_d_outer+5*mm, h=abs(extruder_filapath_offset[1])+hobbed_gear_h/2, align=[0,-1,0], orient=[0,1,0]);

                    // bearing support
                    cylindera(d=extruder_b_bearing[1]+5*mm, h=extruder_b_bearing[2]+4*mm, align=[0,1,0], orient=[0,1,0]);

                }
                // hotmount support
                translate([hobbed_gear_d_inner/2,0,-hobbed_gear_d_outer/2 + hotmount_offset_h])
                cubea([extruder_b_w, hotmount_outer_size_xy, hotmount_outer_size_h], align=[0,0,-1]);

                // clamp mount screw holes
                translate([hobbed_gear_d_inner/2,0,-hobbed_gear_d_outer/2 + hotmount_offset_h])
                for(i=[-1,1])
                {
                    translate([0, i*hotmount_clamp_screws_dist, -hotmount_d_h[0][1]-hotmount_d_h[1][1]/2])
                        rotate([0,90,0])
                        cylindera(r=lookup(ThreadSize, extruder_hotmount_clamp_thread)+3*mm, h=extruder_b_w);
                }
            }

            // hobbed gear
            cylindera(h=hobbed_gear_h, d=hobbed_gear_d_outer+2*mm, orient=[0,1,0], align=[0,0,0]);

            translate([hobbed_gear_d_inner/2,0,-hobbed_gear_d_outer/2 + hotmount_offset_h])
            for(i=[-1,1])
            {
                translate([0, i*hotmount_clamp_screws_dist, -hotmount_d_h[0][1]-hotmount_d_h[1][1]/2])
                    rotate([0,90,0])
                    cylindera(d=lookup(ThreadSize, extruder_hotmount_clamp_thread), h=extruder_b_w+10);
            }

            // filament path
            translate([hobbed_gear_d_outer/2,0,0])
            cylindera(h=1000, d=4*mm, orient=[0,0,1], align=[0,0,0]);

            // gear cutout
            translate([0,-hobbed_gear_h/2-.5*mm,0])
                cylindera(d=extruder_b_bearing[1]+.3*mm, h=extruder_b_bearing[2]+.5*mm, align=[0,1,0], orient=[0,1,0]);

            for(x=[-1,1])
            translate([x*hobbed_gear_d_inner/2,0,0])
            scale([1.03,1,1.03])
            {
                cubea([extruder_guilder_bearing[1]+1*mm,extruder_guilder_bearing[2]+1*mm,extruder_guilder_bearing[1]*2], align=[x,0,1]);
                cylindera(d=extruder_guilder_bearing[1]+1*mm, h=extruder_guilder_bearing[2]+1*mm, orient=[0,1,0], align=[x,0,0]);
            }

            translate([hobbed_gear_d_inner/2,0,-hobbed_gear_d_outer/2 + hotmount_offset_h+.01])
            {
                hotmount_cutout(extend_cut=true);

                // clamp mount screw holes
                for(i=[-1,1])
                {
                    translate([0, i*hotmount_clamp_screws_dist, -hotmount_d_h[0][1]-hotmount_d_h[1][1]/2])
                        rotate([0,90,0])
                        cylindera(d=lookup(ThreadSize, extruder_hotmount_clamp_thread), h=extruder_b_w+1);
                }

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

        if(show_vitamins)
        {
            translate([hobbed_gear_d_inner/2,0,-hobbed_gear_d_outer/2 + hotmount_offset_h+.01])
            translate([extruder_b_w/2 * (hotmount_clamp_side), 0, -hotmount_d_h[0][1]-hotmount_d_h[1][1]/2])
            hotmount_clamp();

            translate([0,-hobbed_gear_h/2-extruder_b_bearing[2]-.5*mm,0])
            {
                cylindera(h=extruder_a_h+extruder_offset_a[1]-extruder_filapath_offset[1], d=extruder_shaft_d, orient=[0,1,0], align=[0,-1,0]);

                bearing(extruder_b_bearing, orient=[0,1,0], align=[0,1,0]);
            }

            // hobbed gear
            cylindera(h=hobbed_gear_h, d=hobbed_gear_d_inner, orient=[0,1,0], align=[0,0,0]);
            for(y=[-1,1])
            translate([0,y*hobbed_gear_h/2,0])
            {
                cylindera(h=hobbed_gear_h/3, d=hobbed_gear_d_outer, orient=[0,1,0], align=[0,y,0]);
            }
        }
    }
}

// Final part
module x_carriage(show_bearings=true)
{
    difference()
    {
        /*hull()*/
        union()
        {
            x_carriage_base(show_bearings=show_bearings);
            translate(extruder_offset)
            translate(extruder_offset_a)
            {
                for(x=[-1,1])
                for(z=[-1,1])
                translate([x*extruder_motor_holedist/2,0,z*extruder_motor_holedist/2])
                cylindera(d=10*mm, h=extruder_offset_a[1], orient=[0,1,0], align=[0,1,0], round_radius=2);
            }
        }
        translate(extruder_offset)
        translate(extruder_offset_a)
        {
            for(x=[-1,1])
            for(z=[-1,1])
            translate([x*extruder_motor_holedist/2,0,z*extruder_motor_holedist/2])
            translate([0,.1,0])
            cylindera(d=3*mm, h=extruder_offset_a[1]+.2, orient=[0,1,0], align=[0,1,0]);
        }
        x_carriage_holes();
    }
}

module x_extruder_a()
{
    translate(extruder_offset)
    translate(extruder_offset_a)
    extruder_a(show_vitamins=true);
}

module x_extruder_b()
{
    translate(extruder_offset)
    {
        extruder_b(show_vitamins=true);
    }
}

/*translate([0,-42,38])*/
/*rotate([0,0,90])*/
/*translate([0,-1,-42])*/
/*translate([-83,25,-42])*/
/*rotate([90,0,0])*/
/*import("stl/i3R_Compact_E3Dv6_Extruder_1.75_01.STL");*/

module x_extruder_hotend()
{
    hotend_conn =[[0,0,27.8-hotmount_offset_h],[0,0,1]];
    translate(extruder_offset)
    translate(extruder_filapath_offset)
    attach(extruder_conn_hotend, hotend_conn)
        rotate([90,0,270])
        %import("stl/E3D_V6_1.75mm_Universal_HotEnd_Mockup.stl");

}

/*if(false)*/
{
    /*extruder_a(show_vitamins=true);*/
    %x_carriage(show_bearings=false);

    /*if(false)*/
    %x_extruder_a();

    /*if(false)*/
    x_extruder_b();

    //filament path
    %translate(extruder_filapath_offset)
        cylindera(h=1000, d=1.75*mm, orient=[0,0,1], align=[0,0,0]);
}


Fix mask panel tabs to be symmetric (won't matter which way bottom is installed).

// fishbox.scad
//  - Enclosure design for zebrafish Skinner box
//
//  Author: Mark Liffiton
//  Date: Oct, 2014 - Nov, 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:
acrylic_thickness = 2.4;
    // 2.4mm = 0.094" (looks good based on cut test piece for acrylic slotting into itself)

// 1/8" Hardboard:
hardboard_thickness = 3.1;
    // 2.8mm = 0.110"
    //   * looked good based on cut test piece for hardboard slotting into hardboard
    //   * 2015-03-06: Hanging supports didn't fit into cutouts (or did only with lots of force)
    // 3.1mm for some breathing room

// Assign materials: window/back wall and everything else
//window_thickness = acrylic_thickness;
window_thickness = hardboard_thickness;
thickness = hardboard_thickness;

// Interior box dimensions
// The variables are used below to control placement of **centerpoints** centerpoints of walls,
// so material thickness is added to account for that.
width = 290 + thickness;    // x = 29cm wall-to-wall
depth = 348 + thickness;    // y = 34.8cm to accomodate 34.8cm tank length
i_height = 190 + thickness; // z = 19cm to accomodate 16cm tank height 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_height = overhang/2;

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

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

// useful tank measurements
tank_width = 70;
tank_foot_offset_left = 105;
tank_foot_offset_right = 101;

// x-position of mask piece inside box
mask_loc = tank_width + thickness;  // center-to-center
// dimensions for mask view opening
view_opening_left = 75;
view_opening_right = 85;
view_opening_width = depth-thickness - view_opening_left - view_opening_right;
view_opening_bottom = 29;
view_opening_height = 90;

// position of rpi and related parts
rpi_ypos = depth/2 + 60;

// for slight offsets/tweaks
epsilon = 1;

// set precision of all arcs/spheres/cylinders/etc.
$fn = 50;

// 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_MASK) {
    projection() rotate(a=[0,90,0]) mask(x=mask_loc);
} else if (DXF_TANK_SUPPORT) {
    projection() tank_support_layer1();
    projection() translate([tank_width+thickness,0,0]) tank_support_layer2();
    projection() translate([(tank_width+thickness)*2,0,0]) tank_support_layer3();
} else if (DXF_CAMERA_SUPPORT) {
    projection() rotate(a=[90,0,0]) camera_support(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.
    mask(x=mask_loc);
    side(y=0);
    side(y=depth);
    tank_base();
    tank_support();
    camera_support(x=width, y=depth/2, z=height/2);
    rpi_support(x=width, y=rpi_ypos-10, z=height/2);
    mock_rpi(x=width, y=rpi_ypos, z=height/2);
    top_cover();
}

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

module mask(x) {
    difference() {
        vert_face_base(x, top_offset=thickness, bottom_offset=base_height-thickness);
        side(y=0);
        side(y=depth);
        translate([x-thickness/2, -overhang, 0]) {
            translate([0, 0, 0])
                rounded_truncation(width=overhang-thickness/2, up=false);
            translate([0, depth+overhang+thickness/2, 0])
                rounded_truncation(width=overhang-thickness/2, up=false);
        }
        // opening for tank view
        translate([0,view_opening_left+thickness/2, view_opening_bottom+base_height+thickness/2])
            cube([width, view_opening_width, view_opening_height]);
        // opening for wires
        translate([0, depth-thickness/2, base_height+thickness])
        rotate(a=[0,90,0])
            cylinder(r=10, h=width);
        // tabs for rigidity w/ bottom panel
        cutouts(4,depth-thickness,outset*2,rot=[-90,0,90],trans=[x+thickness/2,depth/2,base_height+thickness/2]);
    }
}

module vert_face(x=0) {
    difference() {
        if (x == 0) {
            vert_face_base(0, window_thickness);
        }
        else {
            vert_face_base(x);
        }
        camera_opening();
        // round=false so we get the full width of the piece in the cutout, not reduced because we hit the rounded corner
        camera_support(x=width+thickness*2, y=depth/2, z=height/2+support_drop, round=false);
        rpi_support(x=width+thickness*2, y=rpi_ypos-10, z=height/2+support_drop, round=false);
        wire_opening();
        // 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);
        translate([x-thickness/2, -overhang, 0]) {
            translate([0, depth+overhang+thickness/2, 3/4*height])
                rounded_truncation(width=overhang-thickness/2, up=true);
            translate([0, 0, 3/4*height])
                rounded_truncation(width=overhang-thickness/2, up=true);
        }
    }
}

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

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

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

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

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

module hanging_support(x, y, z, out, up, round=true) {
    inner_w = out+thickness;
    inner_h = up;
    color("Red", alpha=0.5)
    translate([x,y,z])
    // push inner opening up against vert face
    translate([out/2,0,0])
    difference() {
        if (round) {
            rounded_rect(inner_w+support_w*2, thickness, inner_h+support_w*2, center=true, radius=support_w);
        }
        else {
            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([-out/2,0,-(inner_h/2+support_w-support_drop/2)])
            cube([thickness, thickness*2, support_drop], center=true);
    }
}

// rounded corners in x,z directions
module rounded_rect(x,y,z, center, radius) {
    difference() {
        cube([x,y,z], center);

        translate([x/2-radius, 50, z/2-radius])
        rotate(a=[90,0,0])
        difference() {
            cube([radius,radius,100]);
            cylinder(r=radius, h=100);
        }
        translate([-x/2+radius, 50, z/2-radius])
        rotate(a=[90,-90,0])
        difference() {
            cube([radius,radius,100]);
            cylinder(r=radius, h=100);
        }
        translate([x/2-radius, 50, -z/2+radius])
        rotate(a=[90,90,0])
        difference() {
            cube([radius,radius,100]);
            cylinder(r=radius, h=100);
        }
        translate([-x/2+radius, 50, -z/2+radius])
        rotate(a=[90,180,0])
        difference() {
            cube([radius,radius,100]);
            cylinder(r=radius, h=100);
        }
    }
}

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() {
    difference() {
        translate([-outset,thickness/2,base_height])
            difference() {
                cube([width+outset*2, depth-thickness, thickness]);
                cutouts(5,depth,outset,rot=-90,trans=[0,(depth-thickness)/2,0]);
                cutouts(5,depth,outset,rot=90,trans=[width+outset*2,(depth-thickness)/2,0]);
            }
        mask(x=mask_loc);
    }
}

module tank_support() {
    translate([thickness/2, thickness/2, base_height+thickness])
    union() {
        tank_support_layer1();
        color("Grey", alpha=0.5)
            tank_support_layer2();
        color("Grey", alpha=0.5)
            tank_support_layer3();
    }
}
// Two strips of hardboard on either side of LED strip
module tank_support_layer1() {
    // front bottom strip, w/ space for wires
    translate([0, 0, 0])
        cube([tank_width/3, depth-thickness, thickness]);
    // back bottom strip, full-depth
    translate([2*tank_width/3, 0, 0])
        cube([tank_width/3, depth-thickness-20, thickness]);
}
// Clear acrylic over LED strip
module tank_support_layer2() {
    translate([0, 0, thickness])
        cube([tank_width, depth-thickness, thickness]);
}
// Clear acrylic end blocks to prevent tank shifting / seat it in correct location
module tank_support_layer3() {
    translate([0, 0, thickness*2])
        cube([tank_width, tank_foot_offset_right, thickness]);
    translate([0, depth-thickness-tank_foot_offset_left, thickness*2])
        cube([tank_width, tank_foot_offset_left, thickness]);
}

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, -thickness/2])
            cube([w, outset+thickness, thickness*2]);
    }
}

module wire_opening() {
    translate([width, rpi_ypos+20, overhang+20])
    scale([1,2,1])
    rotate(a=[0,90,0])
        cylinder(d=12, h=thickness+epsilon, center=true);
}

module side(y=0) {
    difference() {
        side_base(y);
        translate([0,0,height/2])
        scale([1,1,0.5])
            vert_face_base(x=mask_loc);
        scale([1,1,0.5])
            vert_face_base(0, window_thickness);
        scale([1,1,0.5])
            vert_face_base(width);
        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(width=overhang-thickness/2, up=false, rot=[0,0,-90]);
        translate([0, 0, 0])
            rounded_truncation(width=overhang-window_thickness/2, up=false, rot=[0,0,-90]);
    }
}

module mock_rpi(x, y, z) {
    color("Blue", alpha=0.5)
    translate([x+thickness/2, y, z])
        rotate(a=[0,-90,180])
            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 - Nov, 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:
acrylic_thickness = 2.4;
    // 2.4mm = 0.094" (looks good based on cut test piece for acrylic slotting into itself)

// 1/8" Hardboard:
hardboard_thickness = 3.1;
    // 2.8mm = 0.110"
    //   * looked good based on cut test piece for hardboard slotting into hardboard
    //   * 2015-03-06: Hanging supports didn't fit into cutouts (or did only with lots of force)
    // 3.1mm for some breathing room

// Assign materials: window/back wall and everything else
//window_thickness = acrylic_thickness;
window_thickness = hardboard_thickness;
thickness = hardboard_thickness;

// Interior box dimensions
// The variables are used below to control placement of **centerpoints** centerpoints of walls,
// so material thickness is added to account for that.
width = 290 + thickness;    // x = 29cm wall-to-wall
depth = 348 + thickness;    // y = 34.8cm to accomodate 34.8cm tank length
i_height = 190 + thickness; // z = 19cm to accomodate 16cm tank height 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_height = overhang/2;

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

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

// useful tank measurements
tank_width = 70;
tank_foot_offset_left = 105;
tank_foot_offset_right = 101;

// x-position of mask piece inside box
mask_loc = tank_width + thickness;  // center-to-center
// dimensions for mask view opening
view_opening_left = 75;
view_opening_right = 85;
view_opening_width = depth-thickness - view_opening_left - view_opening_right;
view_opening_bottom = 29;
view_opening_height = 90;

// position of rpi and related parts
rpi_ypos = depth/2 + 60;

// for slight offsets/tweaks
epsilon = 1;

// set precision of all arcs/spheres/cylinders/etc.
$fn = 50;

// 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_MASK) {
    projection() rotate(a=[0,90,0]) mask(x=mask_loc);
} else if (DXF_TANK_SUPPORT) {
    projection() tank_support_layer1();
    projection() translate([tank_width+thickness,0,0]) tank_support_layer2();
    projection() translate([(tank_width+thickness)*2,0,0]) tank_support_layer3();
} else if (DXF_CAMERA_SUPPORT) {
    projection() rotate(a=[90,0,0]) camera_support(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.
    mask(x=mask_loc);
    side(y=0);
    side(y=depth);
    tank_base();
    tank_support();
    camera_support(x=width, y=depth/2, z=height/2);
    rpi_support(x=width, y=rpi_ypos-10, z=height/2);
    mock_rpi(x=width, y=rpi_ypos, z=height/2);
    top_cover();
}

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

module mask(x) {
    difference() {
        vert_face_base(x, top_offset=thickness, bottom_offset=base_height-thickness);
        side(y=0);
        side(y=depth);
        translate([x-thickness/2, -overhang, 0]) {
            translate([0, 0, 0])
                rounded_truncation(width=overhang-thickness/2, up=false);
            translate([0, depth+overhang+thickness/2, 0])
                rounded_truncation(width=overhang-thickness/2, up=false);
        }
        // opening for tank view
        translate([0,view_opening_left+thickness/2, view_opening_bottom+base_height+thickness/2])
            cube([width, view_opening_width, view_opening_height]);
        // opening for wires
        translate([0, depth-thickness/2, base_height+thickness])
        rotate(a=[0,90,0])
            cylinder(r=10, h=width);
        // tabs for rigidity w/ bottom panel
        cutouts(4,depth-thickness,outset*2,rot=[-90,0,90],trans=[x+thickness/2,(depth-thickness)/2,base_height+thickness/2]);
    }
}

module vert_face(x=0) {
    difference() {
        if (x == 0) {
            vert_face_base(0, window_thickness);
        }
        else {
            vert_face_base(x);
        }
        camera_opening();
        // round=false so we get the full width of the piece in the cutout, not reduced because we hit the rounded corner
        camera_support(x=width+thickness*2, y=depth/2, z=height/2+support_drop, round=false);
        rpi_support(x=width+thickness*2, y=rpi_ypos-10, z=height/2+support_drop, round=false);
        wire_opening();
        // 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);
        translate([x-thickness/2, -overhang, 0]) {
            translate([0, depth+overhang+thickness/2, 3/4*height])
                rounded_truncation(width=overhang-thickness/2, up=true);
            translate([0, 0, 3/4*height])
                rounded_truncation(width=overhang-thickness/2, up=true);
        }
    }
}

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

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

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

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

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

module hanging_support(x, y, z, out, up, round=true) {
    inner_w = out+thickness;
    inner_h = up;
    color("Red", alpha=0.5)
    translate([x,y,z])
    // push inner opening up against vert face
    translate([out/2,0,0])
    difference() {
        if (round) {
            rounded_rect(inner_w+support_w*2, thickness, inner_h+support_w*2, center=true, radius=support_w);
        }
        else {
            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([-out/2,0,-(inner_h/2+support_w-support_drop/2)])
            cube([thickness, thickness*2, support_drop], center=true);
    }
}

// rounded corners in x,z directions
module rounded_rect(x,y,z, center, radius) {
    difference() {
        cube([x,y,z], center);

        translate([x/2-radius, 50, z/2-radius])
        rotate(a=[90,0,0])
        difference() {
            cube([radius,radius,100]);
            cylinder(r=radius, h=100);
        }
        translate([-x/2+radius, 50, z/2-radius])
        rotate(a=[90,-90,0])
        difference() {
            cube([radius,radius,100]);
            cylinder(r=radius, h=100);
        }
        translate([x/2-radius, 50, -z/2+radius])
        rotate(a=[90,90,0])
        difference() {
            cube([radius,radius,100]);
            cylinder(r=radius, h=100);
        }
        translate([-x/2+radius, 50, -z/2+radius])
        rotate(a=[90,180,0])
        difference() {
            cube([radius,radius,100]);
            cylinder(r=radius, h=100);
        }
    }
}

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() {
    difference() {
        translate([-outset,thickness/2,base_height])
            difference() {
                cube([width+outset*2, depth-thickness, thickness]);
                cutouts(5,depth,outset,rot=-90,trans=[0,(depth-thickness)/2,0]);
                cutouts(5,depth,outset,rot=90,trans=[width+outset*2,(depth-thickness)/2,0]);
            }
        mask(x=mask_loc);
    }
}

module tank_support() {
    translate([thickness/2, thickness/2, base_height+thickness])
    union() {
        tank_support_layer1();
        color("Grey", alpha=0.5)
            tank_support_layer2();
        color("Grey", alpha=0.5)
            tank_support_layer3();
    }
}
// Two strips of hardboard on either side of LED strip
module tank_support_layer1() {
    // front bottom strip, w/ space for wires
    translate([0, 0, 0])
        cube([tank_width/3, depth-thickness, thickness]);
    // back bottom strip, full-depth
    translate([2*tank_width/3, 0, 0])
        cube([tank_width/3, depth-thickness-20, thickness]);
}
// Clear acrylic over LED strip
module tank_support_layer2() {
    translate([0, 0, thickness])
        cube([tank_width, depth-thickness, thickness]);
}
// Clear acrylic end blocks to prevent tank shifting / seat it in correct location
module tank_support_layer3() {
    translate([0, 0, thickness*2])
        cube([tank_width, tank_foot_offset_right, thickness]);
    translate([0, depth-thickness-tank_foot_offset_left, thickness*2])
        cube([tank_width, tank_foot_offset_left, thickness]);
}

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, -thickness/2])
            cube([w, outset+thickness, thickness*2]);
    }
}

module wire_opening() {
    translate([width, rpi_ypos+20, overhang+20])
    scale([1,2,1])
    rotate(a=[0,90,0])
        cylinder(d=12, h=thickness+epsilon, center=true);
}

module side(y=0) {
    difference() {
        side_base(y);
        translate([0,0,height/2])
        scale([1,1,0.5])
            vert_face_base(x=mask_loc);
        scale([1,1,0.5])
            vert_face_base(0, window_thickness);
        scale([1,1,0.5])
            vert_face_base(width);
        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(width=overhang-thickness/2, up=false, rot=[0,0,-90]);
        translate([0, 0, 0])
            rounded_truncation(width=overhang-window_thickness/2, up=false, rot=[0,0,-90]);
    }
}

module mock_rpi(x, y, z) {
    color("Blue", alpha=0.5)
    translate([x+thickness, y, z])
        rotate(a=[0,-90,180])
            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]);
                }
}


main block is now ready

main block is now ready

use <m3d/screw_head_hex.scad>

eps = 0.01;

// standard ball bearing: 8x22x7mm
module bearing()
{
  difference()
  {
    cylinder(d=22, h=7, $fn=100);
    translate(eps*[0,0,-1])
      cylinder(d=8, h=7+2*eps, $fn=40);
  }
}

module screw_head()          { screw_head_hex_m8(); }
module screw_head_slot(dh=0) { screw_head_hex_m8(0.5, 2*0.2+dh); }

module washer(dh=0)
{
  difference()
  {
    cylinder(d=15.5, h=1.4+dh);
    translate(eps*[0,0,-1])
      cylinder(d=8.5, h=1.4+dh+2*eps);
  }
}

// slot for ball bearing + 2 washers
module bearing_slot()
{
  d_spacing = 0.5;
  h_spacing = 0.2;
  cylinder(d=22+d_spacing, h=7+h_spacing, $fn=150);

  for(dh=[-1.4, 7+h_spacing])
    translate([0,0,dh])
      washer();
}

module side_block()
{
  module fin()
  {
    translate(-0.5*[1, 2, 0])
    hull()
    {
      cube([1, 2, 5]);
      for(dx=[-1,+1])
        translate(dx*(120/2-1/2)*[1,0,0])
          cube([1, 2, 2]);
    }
  }

  dx_offset = 80/2;
  module core_body()
  {
    cylinder(d=120, h=5, $fn=360);
    cylinder(d=30, h=5+25, $fn=100);
    // spherical slot around screw head
    translate([dx_offset, 0, 5])
      intersection()
      {
        scale([1,1,0.5])
          sphere(d=30, $fn=100);
        translate([-20, -20, 0])
          cube([40, 40, 6]);
      }
    // fins
    translate([0,0,5])
      for(r=[0:20:180])
        rotate([0, 0, r])
          fin();
  }

  difference()
  {
    core_body();
    // screw slot
    translate([dx_offset, 0, -eps])
    {
      translate([0,0,5])
      {
        screw_head_slot(0.5);
        %screw_head();
      }
      // rod
      cylinder(d=8+0.55, h=100, $fn=50);
    }
    // screw holes in the center block part
    {
      offset = 7;
      h = 10;
      // top
      translate([0, offset, -eps])
      {
        cylinder(d1=10, d2=7, h=h);
        cylinder(d=3+0.7, h=50, $fn=50);
      }
      // bottom
      translate([0, -offset, -eps])
      {
        screw_head_hex_m3(0.5, h);
        cylinder(d=3+0.7, h=50, $fn=50);
      }

    }

    // asymetric cut, to connect 2 parts with friction
    translate([-20, 0, 5+25-10+eps])
      cube([40, 40, 10]);
  }
}

side_block();

use <m3d/screw_head_hex.scad>

eps = 0.01;

// standard ball bearing: 8x22x7mm
module bearing()
{
  difference()
  {
    cylinder(d=22, h=7, $fn=100);
    translate(eps*[0,0,-1])
      cylinder(d=8, h=7+2*eps, $fn=40);
  }
}

module screw_head_slot(dh=0)
{
  screw_head_hex_m8(0.5, 2*0.2+dh);
}

module washer(dh=0)
{
  difference()
  {
    cylinder(d=15.5, h=1.4+dh);
    translate(eps*[0,0,-1])
      cylinder(d=8.5, h=1.4+dh+2*eps);
  }
}

// slot for ball bearing + 2 washers
module bearing_slot()
{
  d_spacing = 0.5;
  h_spacing = 0.2;
  cylinder(d=22+d_spacing, h=7+h_spacing, $fn=150);

  for(dh=[-1.4, 7+h_spacing])
    translate([0,0,dh])
      washer();
}

module side_block()
{
  difference()
  {
    // main element
    cylinder(d1=120, d2=30, h=20, $fn=360);
    // screw slot
    translate([60/2, 0, -eps])
    {
      screw_head_slot(0.5);
      // rod
      cylinder(d=8+0.55, h=100, $fn=50);
      translate([0, 0, 12])
        washer(dh=100);
    }
  }
}

side_block();


basic encoder model

basic encoder model

$fn = 64;

// interference fit adjustment for 3D printer
iFitAdjust = .4;
iFitAdjust_d = .25;

// waveshare 5" knock off
displayScreenWidth = 118;
displayScreenHeight = 70;
displayScreenThickness = 3;
displayBoardWidth = 122;
displayBoardHeight = 78.5;
displayBoardThickness = 7;
displayDepth = 22;
displayScrewDiameter = 3;
module display() {
    // screen
    %translate([-displayScreenWidth / 2, -displayScreenHeight / 2, 0])
        cube([displayScreenWidth, displayScreenHeight, displayScreenThickness], center=false);
    // board
    %translate([-displayBoardWidth / 2, -displayBoardHeight / 2, -displayBoardThickness])
        cube([displayBoardWidth, displayBoardHeight, displayBoardThickness], center=false);
    // corner tabs
    for (i = [-1,1])
        for (j = [-1,1]) {
            translate([i * displayBoardWidth/2, j * displayBoardHeight/2, -displayBoardThickness])
                difference() {
                    cube([20, 20, 3], center=true);
                    translate([i *2, j * 2, -displayBoardThickness / 2])
                        cylinder(h=displayBoardThickness + 2, r = displayScrewDiameter + iFitAdjust_d);
                }
        }
}

// encoders
encoderShaftDiameter = 7;
encoderShaftHeight = 18;
encoderWidth = 18;
encoderLength = 31;
encoderDepth = 8.2;
module encoder() {
    // encoder shaft
    cylinder(h = encoderShaftHeight, d = encoderShaftDiameter, center=false);
    // encoder base
    translate([-encoderWidth/2, -encoderLength/2, -encoderDepth/2])
        cube([encoderWidth, encoderLength, encoderDepth]);
}

// lid with screen and encoders
module lid() {
    // face plate
    // screen cutout
    // encoder cutout
    // screw holes
}

// box with pi mounts and holes
module box() {
    // bottom
    // pi mount holes
    // sides
    // pi usb / ethernet
    // hifi audio out
}

//display();
encoder();

$fn = 64;

// interference fit adjustment for 3D printer
iFitAdjust = .4;
iFitAdjust_d = .25;

// waveshare 5" knock off
displayScreenWidth = 118;
displayScreenHeight = 70;
displayScreenThickness = 3;
displayBoardWidth = 122;
displayBoardHeight = 78.5;
displayBoardThickness = 7;
displayDepth = 22;
displayScrewDiameter = 3;
module display() {
    // screen
    %translate([-displayScreenWidth / 2, -displayScreenHeight / 2, 0])
        cube([displayScreenWidth, displayScreenHeight, displayScreenThickness], center=false);
    // board
    %translate([-displayBoardWidth / 2, -displayBoardHeight / 2, -displayBoardThickness])
        cube([displayBoardWidth, displayBoardHeight, displayBoardThickness], center=false);
    // screen mounts
    // corner tabs
    for (i = [-1,1])
        for (j = [-1,1]) {
            translate([i * displayBoardWidth/2, j * displayBoardHeight/2, -displayBoardThickness])
                difference() {
                    cube([20, 20, 3], center=true);
                    translate([i *2, j * 2, -displayBoardThickness / 2])
                        cylinder(h=displayBoardThickness + 2, r = displayScrewDiameter + iFitAdjust_d);
                }
        }
}

// encoders
encoderShaftDiameter = 7;
encoderWidth = 18;
encoderLength = 31;
encoderDepth = 8.2;
module encoder() {
    // encoder shaft
    // encoder base
}

// lid with screen and encoders
module lid() {
    // face plate
    // screen cutout
    // encoder cutout
    // screw holes
}

// box with pi mounts and holes
module box() {
    // bottom
    // pi mount holes
    // sides
    // pi usb / ethernet
    // hifi audio out
}

display();


elements rotate to better fit printer's dimentions

use <support.scad>
use <wallMount.scad>

module bothElements()
{
  translate([0, 55, 0])
    support();
  wallMount();
}

module closedPosition()
{
  wallMount();
  translate([150, 0, 14.5])
    rotate([0, 180, 0])
      support();
}

module openPosition()
{
  wallMount();
  translate([150, -4, 4])
    rotate([-90, 180, 0])
      support();
}

//%closedPosition();
//%openPosition();

rotate([0, 0, 90])
  bothElements();

use <support.scad>
use <wallMount.scad>

module bothElements()
{
  translate([0, 55, 0])
    support();
  wallMount();
}

module closedPosition()
{
  wallMount();
  translate([150, 0, 14.5])
    rotate([0, 180, 0])
      support();
}

module openPosition()
{
  wallMount();
  translate([150, -4, 4])
    rotate([-90, 180, 0])
      support();
}

//%closedPosition();
//%openPosition();

bothElements();