x/ends: fix motor mount screw overlap pulley mount

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

include <config.scad>
include <thing_libutils/misc.scad>
include <thing_libutils/bearing.scad>
use <thing_libutils/screws.scad>
use <thing_libutils/timing-belts.scad>

motor_mount_wall_thick = xaxis_pulley[1] - xaxis_pulley[0]/2 + 4*mm;
xaxis_end_pulley_offset = 41*mm;
xaxis_end_motorsize = lookup(NemaSideSize,xaxis_motor);
xaxis_end_motor_offset=[xaxis_end_motorsize/2+zaxis_bearing[1]/2+1*mm,motor_mount_wall_thick-2*mm,0];
xaxis_end_wz = xaxis_rod_distance+zaxis_bearing[2]+2*mm;

xaxis_endstop_size_switch = [10.3*mm, 20*mm, 6.3*mm];
xaxis_endstop_screw_offset_switch = [-2.45*mm, 0*mm, 0*mm];

xaxis_endstop_size_SN04 = [34.15*mm, 18.15*mm, 17.8*mm];
xaxis_endstop_screw_offset_SN04 = [-27.5*mm, 0*mm, 0*mm];
xaxis_endstop_offset_SN04 = [-3*mm, 0*mm, 0*mm];

function xaxis_end_width(with_motor) = with_motor? xaxis_end_motorsize+xaxis_end_motor_offset[0] - xaxis_end_motorsize/2 : zaxis_bearing[1]/2+zaxis_nut[1];

module xaxis_end_body(part, with_motor, beltpath_index=0, nut_top=false, with_xrod_adjustment=false)
{
    nut_h = zaxis_nut[4];
    bearing_sizey = zaxis_bearing[1] + 5*mm;

    xaxis_end_xrod_offset_z = xaxis_rod_l/2 - (main_width/2 + zmotor_mount_rod_offset_x);
    xaxis_rod_d_support = xaxis_rod_d+5*mm;
    xaxis_rod_l_support = xaxis_end_xrod_offset_z + 8*mm + (with_xrod_adjustment?8*mm:0);

    if(part==undef)
    {
        difference()
        {
            xaxis_end_body(part="pos", with_motor=with_motor, beltpath_index=beltpath_index, nut_top=nut_top, with_xrod_adjustment=with_xrod_adjustment);
            xaxis_end_body(part="neg", with_motor=with_motor, beltpath_index=beltpath_index, nut_top=nut_top, with_xrod_adjustment=with_xrod_adjustment);
        }
        %xaxis_end_body(part="vit", with_motor=with_motor, beltpath_index=beltpath_index, nut_top=nut_top, with_xrod_adjustment=with_xrod_adjustment);
    }
    else if(part=="pos")
    {
        if(with_motor)
        {
            screw_dist = lookup(NemaDistanceBetweenMountingHoles, xaxis_motor);
            for(x=[-1,1])
            for(z=[-1,1])
            translate([0,0,xaxis_beltpath_z_offsets[beltpath_index]])
            translate(xaxis_end_motor_offset)
            {
                translate([x*screw_dist/2, 0, z*screw_dist/2])
                cylindera(d=lookup(ThreadSize,xaxis_motor_thread)+4*mm, h=motor_mount_wall_thick, orient=[0,1,0], align=[0,-1,0], rounding_radius=2);
            }
        }

        // nut mount
        mirror([0,0,nut_top?1:0])
        translate([zaxis_rod_screw_distance_x, -xaxis_zaxis_distance_y, -xaxis_end_wz/2])
        {
            // main nut support
            cylindera(h=zaxis_nut[4], d=zaxis_nut[0]+5*mm, align=[0,0,1], round_radius=2);

            // nut screw holes support
            for(x=[-1,1])
            translate([x*zaxis_nut[5], 0, 0])
            cylindera(h=zaxis_nut[4], d=lookup(ThreadSize, zaxis_nut[6])+5*mm, align=[0,0,1], round_radius=2);

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

        // x axis rod holders
        for(z=[-1,1])
        translate([0,0,z*(xaxis_rod_distance/2)])
        cylindera(h=xaxis_rod_l_support, d=xaxis_rod_d_support, orient=[1,0,0], align=[-1,0,0], round_radius=2);

        /*if(xaxis_endstop_type == "SWITCH")*/
        {
            translate([xaxis_end_width(with_motor),0,(xaxis_rod_distance/2)+xaxis_rod_d])
            {
                rcubea(xaxis_endstop_size_switch, align=[-1,0,-1]);
            }
        }
        /*else if(xaxis_endstop_type == "SN04")*/
        {
            translate([xaxis_end_width(with_motor),0,(xaxis_rod_distance/2)+xaxis_rod_d])
            {
                translate(xaxis_endstop_offset_SN04)
                rcubea(xaxis_endstop_size_SN04, align=[-1,0,-1]);
            }
        }

        // support around z axis bearings
        translate([0, -xaxis_zaxis_distance_y, 0])
        cylindera(h=xaxis_end_wz,d=bearing_sizey, orient=[0,0,1], align=[0,0,0], round_radius=2);

        // belt idler screw cut support
        for(z=[-1,1])
        for(y=[-1,1])
        translate([xaxis_end_pulley_offset,0,-xaxis_beltpath_z_offsets[max(0,beltpath_index)]])
        {
            translate([0,y*-xaxis_beltpath_width/2,0])
            cylindera(orient=YAXIS, d=15*mm, h=7*mm, align=-y*YAXIS);
        }
    }
    else if(part=="neg")
    {
        // cut support around z axis bearings
        translate([0, -xaxis_zaxis_distance_y, 0])
        translate([0,0,.1])
        cubea([bearing_sizey+.1, bearing_sizey+.2, xaxis_end_wz+.4], orient=[0,0,1], align=[0,-1,0]);

        // x smooth rods
        for(z=[-1,1])
        translate([0,0*mm,z*(xaxis_rod_distance/2)])
        {
            xoff = - xaxis_end_xrod_offset_z -(with_xrod_adjustment?6:0)*mm;
            translate([xoff,0,0])
            cylindera(h=abs(xoff)+xaxis_end_width(with_motor)+1,d=xaxis_rod_d+.5*mm, orient=[1,0,0], align=[1,0,0]);

            if(with_xrod_adjustment)
            {
                translate([-xaxis_rod_l_support+5*mm,0,0])
                nut_trap_cut(nut=NutHexM4, trap_axis=YAXIS, orient=-XAXIS, align=XAXIS);

                translate([-xaxis_rod_l_support-7*mm,0,0])
                cylindera(d=10, h=10, orient=XAXIS);
            }
        }
    }
    else if(part=="vit")
    {
    }
}

module xaxis_end(part, with_motor=false, stop_x_rods=true, beltpath_index=0, show_motor=false, nut_top=false, show_nut=false, show_rods=false, show_bearings=false, with_xrod_adjustment=false)
{
    nut_h = zaxis_nut[4];
    extrasize = with_motor?0*mm:0*mm;
    extrasize_align = 1;

    if(part==undef)
    {
        difference()
        {
            xaxis_end(part="pos", with_motor=with_motor, stop_x_rods=stop_x_rods, beltpath_index=beltpath_index, show_motor=show_motor, nut_top=nut_top, show_nut=show_nut, show_rods=show_rods, show_bearings=show_bearings, with_xrod_adjustment=with_xrod_adjustment);
            xaxis_end(part="neg", with_motor=with_motor, stop_x_rods=stop_x_rods, beltpath_index=beltpath_index, show_motor=show_motor, nut_top=nut_top, show_nut=show_nut, show_rods=show_rods, show_bearings=show_bearings, with_xrod_adjustment=with_xrod_adjustment);
        }
        %xaxis_end(part="vit", with_motor=with_motor, stop_x_rods=stop_x_rods, beltpath_index=beltpath_index, show_motor=show_motor, nut_top=nut_top, show_nut=show_nut, show_rods=show_rods, show_bearings=show_bearings, with_xrod_adjustment=with_xrod_adjustment);
    }
    else if(part=="pos")
    {
        hull()
        {
            xaxis_end_body(part=part, with_motor=with_motor, beltpath_index=beltpath_index, nut_top=nut_top, with_xrod_adjustment=with_xrod_adjustment);

            // projection against z, ensure easy print
            translate([0,0,-xaxis_end_wz/2])
                linear_extrude(1)
                projection(cut=false)
                xaxis_end_body(part=part, with_motor=with_motor, beltpath_index=beltpath_index, nut_top=nut_top, with_xrod_adjustment=with_xrod_adjustment);
        }
    }
    else if(part=="neg")
    {
        xaxis_end_body(part=part, with_motor=with_motor, beltpath_index=beltpath_index, nut_top=nut_top, with_xrod_adjustment=with_xrod_adjustment);

        // belt idler screw cut
        for(z=[-1,1])
        translate([xaxis_end_pulley_offset,0,-xaxis_beltpath_z_offsets[max(0,beltpath_index)]])
        {
            translate([0, -xaxis_beltpath_width/2 - 7*mm, 0])
            {
                screw_cut(nut=NutHexM5, h=xaxis_beltpath_width+13*mm, with_nut=true, orient=[0,1,0], align=[0,1,0]);
            }
        }

        //endstop mount screw cuts
        /*if(xaxis_endstop_type == "SWITCH")*/
        {
            translate([xaxis_end_width(with_motor),0,(xaxis_rod_distance/2)+xaxis_rod_d])
            translate(xaxis_endstop_screw_offset_switch)
            for(y=[-1,1])
            translate([-5*mm,y*9.5*mm/2,xaxis_endstop_size_switch[2]])
            {
                screw_cut(nut=NutHexM2_5, h=10*mm, embed_head=false, with_head=true, with_nut=false, orient=[0,0,-1], align=[0,0,-1]);
            }
        }
        /*else if(xaxis_endstop_type == "SN04")*/
        {
            translate([xaxis_end_width(with_motor),0,(xaxis_rod_distance/2)+xaxis_rod_d])
            translate(xaxis_endstop_screw_offset_SN04)
            for(y=[-1,1])
            translate([-0*mm,y*10.5*mm/2,xaxis_endstop_size_SN04[2]])
            {
                translate(xaxis_endstop_offset_SN04)
                screw_cut(nut=NutHexM3, h=20*mm, embed_head=false, with_head=true, with_nut=false, orient=[0,0,-1], align=[0,0,-1]);
            }
        }

        xaxis_end_beltpath(height=xaxis_beltpath_height_body, width=xaxis_beltpath_width);

        // 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(
                        bearing_type=zaxis_bearing,
                        ziptie_type=ziptie_type,
                        ziptie_bearing_distance=ziptie_bearing_distance,
                        orient=[0,0,1],
                        with_zips=true
                        );
                /*hull()*/
                /*{*/
                    /*cylindera(d=zaxis_bearing[1],h=xaxis_end_wz);*/

                    /*translate([-5*cm,0,0])*/
                    /*cylindera(d=zaxis_bearing[1],h=xaxis_end_wz);*/
                /*}*/
            }
        }

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

            // axle
            translate([0,0,xaxis_beltpath_z_offsets[beltpath_index]])
            translate(xaxis_end_motor_offset)
            {
                round_d=1.1*lookup(NemaRoundExtrusionDiameter, xaxis_motor);
                translate([0, .1, 0])
                translate([0,1,0])
                teardrop(d=round_d,h=motor_mount_wall_thick, tear_orient=[0,0,1], orient=[0,1,0], align=[0,-1,0], roll=90, truncate=0.9);

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

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

                for(x=[-1,1])
                for(z=[-1,1])
                translate([0,-xaxis_end_motor_offset[1],0])
                translate([x*screw_dist/2, -(xaxis_beltpath_width/2+3*mm), z*screw_dist/2])
                {
                    if(!(x==1 && z == (beltpath_index==0?1:-1)))
                    screw_cut(xaxis_motor_nut, h=25, with_nut=false, orient=[0,1,0], align=[0,1,0]);
                }
            }

        }

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

                    // lead screw
                    translate([0,0,-.1])
                    cylindera(h=lookup(NemaFrontAxleLength,zaxis_motor), d=zaxis_nut[2]*1.5, align=[0,0,1]);

                    for(i=[-1,1])
                    translate([i*zaxis_nut[5], 0, -zaxis_nut[3]])
                    screw_cut(thread=zaxis_nut[6], h=20*mm, with_nut=false, orient=ZAXIS, align=ZAXIS);
                }
            }
        }
    }
    else if(part=="vit")
    {
        xaxis_end_body(part=part, with_motor=with_motor, beltpath_index=beltpath_index, nut_top=nut_top, with_xrod_adjustment=with_xrod_adjustment);

        if(with_motor)
        {
            translate([0,0,xaxis_beltpath_z_offsets[beltpath_index]])
            translate(xaxis_end_motor_offset)
            {
                // 1mm due to motor offset
                translate([0,-1*mm,0])
                {
                    // 1mm between pulley and motor
                    translate([0,-1*mm,0])
                    pulley(xaxis_pulley, flip=false, orient=[0,1,0], align=[0,-1,0]);

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

        //endstop
        if($show_vit)
        {
            /*if(xaxis_endstop_type == "SWITCH")*/
            {
                translate([xaxis_end_width(with_motor),0,(xaxis_rod_distance/2)+xaxis_rod_d])
                {
                    difference()
                    {
                        rcubea(xaxis_endstop_size_switch, align=[-1,0,1]);

                        translate(xaxis_endstop_screw_offset_switch)
                        for(y=[-1,1])
                        translate([-5*mm,y*9.5*mm/2,xaxis_endstop_size_switch[2]])
                        screw(nut=NutHexM2_5, h=6*mm, orient=[0,0,-1], align=[0,0,-1]);
                    }
                }
            }
            /*else if(xaxis_endstop_type == "SN04")*/
            {
                translate([xaxis_end_width(with_motor),0,(xaxis_rod_distance/2)+xaxis_rod_d])
                {
                    translate(xaxis_endstop_offset_SN04)
                    translate([-36,-9,0])
                    rotate(ZAXIS*-90)
                    import("stl/SN04-N_Inductive_Proximity_Sensor_3528_0.stl");
                }
            }
        }

        // belt idler pulley screw
        for(z=[-1,1])
        translate([xaxis_end_pulley_offset,0,-xaxis_beltpath_z_offsets[max(0,beltpath_index)]])
        {
            translate([0, -xaxis_beltpath_width/2 - 7*mm, 0])
            {
                screw(nut=NutHexM5, h=25*mm, with_nut=true, orient=[0,1,0], align=[0,1,0]);
            }
        }

        for(z=[-1,1])
        translate([xaxis_end_pulley_offset,0,-xaxis_beltpath_z_offsets[max(0,beltpath_index)]])
        {
            pulley(xaxis_idler_pulley, orient=[0,1,0]);
        }

        if(show_nut)
        {
            mirror([0,0,nut_top?1:0])
            translate([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])
                cylindera(d=zaxis_rod_d, h=zaxis_rod_l, orient=[0,0,1]);
        }

        if(show_bearings)
        {
            for(z=[-1,1])
            translate([0,0,z*xaxis_rod_distance/2])
            translate([0, -xaxis_zaxis_distance_y, 0])
            bearing(zaxis_bearing);
        }
    }
}

module xaxis_end_beltpath(height, width, length = 1000, align=[0,0,0], orient=[1,0,0])
{
    hull()
    for(z=[-1,1])
    translate([0,0,z*height/2])
    teardrop(h=length, d=width, orient=orient, align=align, roll=-180*min(0,z), truncate=1);
}

module xaxis_end_znut()
{
    difference()
    {
        union()
        {
            cylindera(d=zaxis_nut[1], h=zaxis_nut[3], orient=[0,0,1], align=[0,0,1]);
            cylindera(d=zaxis_nut[0], h=zaxis_nut[4], orient=[0,0,1], align=[0,0,1]);
        }

        translate([0,0,-.1])
        cylindera(d=zaxis_nut[2], h=zaxis_nut[4]+.2, orient=[0,0,1], align=[0,0,1]);
    }
}

if(false)
{
    // x axis
    /*translate([0,0,axis_pos_z])*/
    {
        /*if(!$preview_mode)*/
        {
            zrod_offset = zmotor_mount_rod_offset_x;
            for(x=[-1,1])
            {
                z=xaxis_beltpath_z_offsets[x<0?0:x];
                xo = x>0?xaxis_end_pulley_offset:xaxis_end_motor_offset[0];
                xw = x<0?xaxis_end_pulley_offset:xaxis_end_motor_offset[0];
                translate([-main_width/2-xo/2, xaxis_zaxis_distance_y, z])
                rotate([90,0,0])
                color("black")
                belt_path(main_width+xw, 6, xaxis_pulley_inner_d, orient=[1,0,0], align=[1,0,0]);
            }
        }

        /*translate([axis_pos_x,0,0])*/
        /*{*/
            // x carriage
            /*attach(xaxis_carriage_conn, [[0,-xaxis_zaxis_distance_y,0],[0,0,0]])*/
            /*{*/
                /*x_carriage_full();*/
            /*}*/
        /*}*/

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

        for(x=[-1,1])
        translate([x*(main_width/2), 0, 0])
        translate([x*(zmotor_mount_rod_offset_x),0,0])
        cylindera(h=zaxis_rod_l,d=zaxis_rod_d, orient=ZAXIS, align=[0,0,0]);

        for(x=[-1,1])
        {
            translate([x*(main_width/2), 0, 0])
            {
                translate([0, xaxis_zaxis_distance_y, 0])
                translate([x*zmotor_mount_rod_offset_x, 0, 0])
                mirror([max(0,x),0,0])
                {
                    xaxis_end(with_motor=true, beltpath_index=max(0,x), show_nut=true, show_motor=true, show_nut=true);
                }
            }
        }
    }

}

if(false)
{
    for(x=[-1,1])
    translate([x*55,x*55,xaxis_end_wz/2])
    mirror([max(0,x),0,0])
    {
        xaxis_end(with_motor=true, beltpath_index=max(0,x), show_motor=false, show_nut=false, show_bearings=false, with_xrod_adjustment=true);
    }
}

module part_x_end_right()
{
    x=1;
    translate([0,0,xaxis_end_wz/2])
    mirror([max(0,x),0,0])
    xaxis_end(with_motor=true, beltpath_index=max(0,x), with_xrod_adjustment=true);
}

module part_x_end_left()
{
    x=-1;
    translate([0,0,xaxis_end_wz/2])
    mirror([max(0,x),0,0])
    xaxis_end(with_motor=true, beltpath_index=max(0,x), with_xrod_adjustment=true);
}

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

include <config.scad>
include <thing_libutils/misc.scad>
include <thing_libutils/bearing.scad>
use <thing_libutils/screws.scad>
use <thing_libutils/timing-belts.scad>

motor_mount_wall_thick = xaxis_pulley[1] - xaxis_pulley[0]/2 + 4*mm;
xaxis_end_pulley_offset = 41*mm;
xaxis_end_motorsize = lookup(NemaSideSize,xaxis_motor);
xaxis_end_motor_offset=[xaxis_end_motorsize/2+zaxis_bearing[1]/2+1*mm,motor_mount_wall_thick-2*mm,0];
xaxis_end_wz = xaxis_rod_distance+zaxis_bearing[2]+2*mm;

xaxis_endstop_size_switch = [10.3*mm, 20*mm, 6.3*mm];
xaxis_endstop_screw_offset_switch = [-2.45*mm, 0*mm, 0*mm];

xaxis_endstop_size_SN04 = [34.15*mm, 18.15*mm, 17.8*mm];
xaxis_endstop_screw_offset_SN04 = [-27.5*mm, 0*mm, 0*mm];
xaxis_endstop_offset_SN04 = [-3*mm, 0*mm, 0*mm];

function xaxis_end_width(with_motor) = with_motor? xaxis_end_motorsize+xaxis_end_motor_offset[0] - xaxis_end_motorsize/2 : zaxis_bearing[1]/2+zaxis_nut[1];

module xaxis_end_body(part, with_motor, beltpath_index=0, nut_top=false, with_xrod_adjustment=false)
{
    nut_h = zaxis_nut[4];
    bearing_sizey = zaxis_bearing[1] + 5*mm;

    xaxis_end_xrod_offset_z = xaxis_rod_l/2 - (main_width/2 + zmotor_mount_rod_offset_x);
    xaxis_rod_d_support = xaxis_rod_d+5*mm;
    xaxis_rod_l_support = xaxis_end_xrod_offset_z + 8*mm + (with_xrod_adjustment?8*mm:0);

    if(part==undef)
    {
        difference()
        {
            xaxis_end_body(part="pos", with_motor=with_motor, beltpath_index=beltpath_index, nut_top=nut_top, with_xrod_adjustment=with_xrod_adjustment);
            xaxis_end_body(part="neg", with_motor=with_motor, beltpath_index=beltpath_index, nut_top=nut_top, with_xrod_adjustment=with_xrod_adjustment);
        }
        %xaxis_end_body(part="vit", with_motor=with_motor, beltpath_index=beltpath_index, nut_top=nut_top, with_xrod_adjustment=with_xrod_adjustment);
    }
    else if(part=="pos")
    {
        if(with_motor)
        {
            screw_dist = lookup(NemaDistanceBetweenMountingHoles, xaxis_motor);
            for(x=[-1,1])
            for(z=[-1,1])
            translate([0,0,xaxis_beltpath_z_offsets[beltpath_index]])
            translate(xaxis_end_motor_offset)
            {
                translate([x*screw_dist/2, 0, z*screw_dist/2])
                cylindera(d=lookup(ThreadSize,xaxis_motor_thread)+4*mm, h=motor_mount_wall_thick, orient=[0,1,0], align=[0,-1,0], rounding_radius=2);
            }
        }

        // nut mount
        mirror([0,0,nut_top?1:0])
        translate([zaxis_rod_screw_distance_x, -xaxis_zaxis_distance_y, -xaxis_end_wz/2])
        {
            // main nut support
            cylindera(h=zaxis_nut[4], d=zaxis_nut[0]+5*mm, align=[0,0,1], round_radius=2);

            // nut screw holes support
            for(x=[-1,1])
            translate([x*zaxis_nut[5], 0, 0])
            cylindera(h=zaxis_nut[4], d=lookup(ThreadSize, zaxis_nut[6])+5*mm, align=[0,0,1], round_radius=2);

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

        // x axis rod holders
        for(z=[-1,1])
        translate([0,0,z*(xaxis_rod_distance/2)])
        cylindera(h=xaxis_rod_l_support, d=xaxis_rod_d_support, orient=[1,0,0], align=[-1,0,0], round_radius=2);

        /*if(xaxis_endstop_type == "SWITCH")*/
        {
            translate([xaxis_end_width(with_motor),0,(xaxis_rod_distance/2)+xaxis_rod_d])
            {
                rcubea(xaxis_endstop_size_switch, align=[-1,0,-1]);
            }
        }
        /*else if(xaxis_endstop_type == "SN04")*/
        {
            translate([xaxis_end_width(with_motor),0,(xaxis_rod_distance/2)+xaxis_rod_d])
            {
                translate(xaxis_endstop_offset_SN04)
                rcubea(xaxis_endstop_size_SN04, align=[-1,0,-1]);
            }
        }

        // support around z axis bearings
        translate([0, -xaxis_zaxis_distance_y, 0])
        cylindera(h=xaxis_end_wz,d=bearing_sizey, orient=[0,0,1], align=[0,0,0], round_radius=2);

        // belt idler screw cut support
        for(z=[-1,1])
        for(y=[-1,1])
        translate([xaxis_end_pulley_offset,0,-xaxis_beltpath_z_offsets[max(0,beltpath_index)]])
        {
            translate([0,y*-xaxis_beltpath_width/2,0])
            cylindera(orient=YAXIS, d=15*mm, h=7*mm, align=-y*YAXIS);
        }
    }
    else if(part=="neg")
    {
        // cut support around z axis bearings
        translate([0, -xaxis_zaxis_distance_y, 0])
        translate([0,0,.1])
        cubea([bearing_sizey+.1, bearing_sizey+.2, xaxis_end_wz+.4], orient=[0,0,1], align=[0,-1,0]);

        // x smooth rods
        for(z=[-1,1])
        translate([0,0*mm,z*(xaxis_rod_distance/2)])
        {
            xoff = - xaxis_end_xrod_offset_z -(with_xrod_adjustment?6:0)*mm;
            translate([xoff,0,0])
            cylindera(h=abs(xoff)+xaxis_end_width(with_motor)+1,d=xaxis_rod_d+.5*mm, orient=[1,0,0], align=[1,0,0]);

            if(with_xrod_adjustment)
            {
                translate([-xaxis_rod_l_support+5*mm,0,0])
                nut_trap_cut(nut=NutHexM4, trap_axis=YAXIS, orient=-XAXIS, align=XAXIS);

                translate([-xaxis_rod_l_support-7*mm,0,0])
                cylindera(d=10, h=10, orient=XAXIS);
            }
        }
    }
    else if(part=="vit")
    {
    }
}

module xaxis_end(part, with_motor=false, stop_x_rods=true, beltpath_index=0, show_motor=false, nut_top=false, show_nut=false, show_rods=false, show_bearings=false, with_xrod_adjustment=false)
{
    nut_h = zaxis_nut[4];
    extrasize = with_motor?0*mm:0*mm;
    extrasize_align = 1;

    if(part==undef)
    {
        difference()
        {
            xaxis_end(part="pos", with_motor=with_motor, stop_x_rods=stop_x_rods, beltpath_index=beltpath_index, show_motor=show_motor, nut_top=nut_top, show_nut=show_nut, show_rods=show_rods, show_bearings=show_bearings, with_xrod_adjustment=with_xrod_adjustment);
            xaxis_end(part="neg", with_motor=with_motor, stop_x_rods=stop_x_rods, beltpath_index=beltpath_index, show_motor=show_motor, nut_top=nut_top, show_nut=show_nut, show_rods=show_rods, show_bearings=show_bearings, with_xrod_adjustment=with_xrod_adjustment);
        }
        %xaxis_end(part="vit", with_motor=with_motor, stop_x_rods=stop_x_rods, beltpath_index=beltpath_index, show_motor=show_motor, nut_top=nut_top, show_nut=show_nut, show_rods=show_rods, show_bearings=show_bearings, with_xrod_adjustment=with_xrod_adjustment);
    }
    else if(part=="pos")
    {
        hull()
        {
            xaxis_end_body(part=part, with_motor=with_motor, beltpath_index=beltpath_index, nut_top=nut_top, with_xrod_adjustment=with_xrod_adjustment);

            // projection against z, ensure easy print
            translate([0,0,-xaxis_end_wz/2])
                linear_extrude(1)
                projection(cut=false)
                xaxis_end_body(part=part, with_motor=with_motor, beltpath_index=beltpath_index, nut_top=nut_top, with_xrod_adjustment=with_xrod_adjustment);
        }
    }
    else if(part=="neg")
    {
        xaxis_end_body(part=part, with_motor=with_motor, beltpath_index=beltpath_index, nut_top=nut_top, with_xrod_adjustment=with_xrod_adjustment);

        // belt idler screw cut
        for(z=[-1,1])
        translate([xaxis_end_pulley_offset,0,-xaxis_beltpath_z_offsets[max(0,beltpath_index)]])
        {
            translate([0, -xaxis_beltpath_width/2 - 7*mm, 0])
            {
                screw_cut(nut=NutHexM5, h=xaxis_beltpath_width+13*mm, with_nut=true, orient=[0,1,0], align=[0,1,0]);
            }
        }

        //endstop mount screw cuts
        /*if(xaxis_endstop_type == "SWITCH")*/
        {
            translate([xaxis_end_width(with_motor),0,(xaxis_rod_distance/2)+xaxis_rod_d])
            translate(xaxis_endstop_screw_offset_switch)
            for(y=[-1,1])
            translate([-5*mm,y*9.5*mm/2,xaxis_endstop_size_switch[2]])
            {
                screw_cut(nut=NutHexM2_5, h=10*mm, embed_head=false, with_head=true, with_nut=false, orient=[0,0,-1], align=[0,0,-1]);
            }
        }
        /*else if(xaxis_endstop_type == "SN04")*/
        {
            translate([xaxis_end_width(with_motor),0,(xaxis_rod_distance/2)+xaxis_rod_d])
            translate(xaxis_endstop_screw_offset_SN04)
            for(y=[-1,1])
            translate([-0*mm,y*10.5*mm/2,xaxis_endstop_size_SN04[2]])
            {
                translate(xaxis_endstop_offset_SN04)
                screw_cut(nut=NutHexM3, h=20*mm, embed_head=false, with_head=true, with_nut=false, orient=[0,0,-1], align=[0,0,-1]);
            }
        }

        xaxis_end_beltpath(height=xaxis_beltpath_height_body, width=xaxis_beltpath_width);

        // 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(
                        bearing_type=zaxis_bearing,
                        ziptie_type=ziptie_type,
                        ziptie_bearing_distance=ziptie_bearing_distance,
                        orient=[0,0,1],
                        with_zips=true
                        );
                /*hull()*/
                /*{*/
                    /*cylindera(d=zaxis_bearing[1],h=xaxis_end_wz);*/

                    /*translate([-5*cm,0,0])*/
                    /*cylindera(d=zaxis_bearing[1],h=xaxis_end_wz);*/
                /*}*/
            }
        }

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

            // axle
            translate([0,0,xaxis_beltpath_z_offsets[beltpath_index]])
            translate(xaxis_end_motor_offset)
            {
                round_d=1.1*lookup(NemaRoundExtrusionDiameter, xaxis_motor);
                translate([0, .1, 0])
                translate([0,1,0])
                teardrop(d=round_d,h=motor_mount_wall_thick, tear_orient=[0,0,1], orient=[0,1,0], align=[0,-1,0], roll=90, truncate=0.9);

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

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

                for(x=[-1,1])
                for(z=[-1,1])
                translate([0,-xaxis_end_motor_offset[1],0])
                translate([x*screw_dist/2, -(xaxis_beltpath_width/2+3*mm), z*screw_dist/2])
                {
                    screw_cut(xaxis_motor_nut, h=25, with_nut=false, orient=[0,1,0], align=[0,1,0]);
                }
            }

        }

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

                    // lead screw
                    translate([0,0,-.1])
                    cylindera(h=lookup(NemaFrontAxleLength,zaxis_motor), d=zaxis_nut[2]*1.5, align=[0,0,1]);

                    for(i=[-1,1])
                    translate([i*zaxis_nut[5], 0, -zaxis_nut[3]])
                    screw_cut(thread=zaxis_nut[6], h=20*mm, with_nut=false, orient=ZAXIS, align=ZAXIS);
                }
            }
        }
    }
    else if(part=="vit")
    {
        xaxis_end_body(part=part, with_motor=with_motor, beltpath_index=beltpath_index, nut_top=nut_top, with_xrod_adjustment=with_xrod_adjustment);

        if(with_motor)
        {
            translate([0,0,xaxis_beltpath_z_offsets[beltpath_index]])
            translate(xaxis_end_motor_offset)
            {
                // 1mm due to motor offset
                translate([0,-1*mm,0])
                {
                    // 1mm between pulley and motor
                    translate([0,-1*mm,0])
                    pulley(xaxis_pulley, flip=false, orient=[0,1,0], align=[0,-1,0]);

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

        //endstop
        if($show_vit)
        {
            /*if(xaxis_endstop_type == "SWITCH")*/
            {
                translate([xaxis_end_width(with_motor),0,(xaxis_rod_distance/2)+xaxis_rod_d])
                {
                    difference()
                    {
                        rcubea(xaxis_endstop_size_switch, align=[-1,0,1]);

                        translate(xaxis_endstop_screw_offset_switch)
                        for(y=[-1,1])
                        translate([-5*mm,y*9.5*mm/2,xaxis_endstop_size_switch[2]])
                        screw(nut=NutHexM2_5, h=6*mm, orient=[0,0,-1], align=[0,0,-1]);
                    }
                }
            }
            /*else if(xaxis_endstop_type == "SN04")*/
            {
                translate([xaxis_end_width(with_motor),0,(xaxis_rod_distance/2)+xaxis_rod_d])
                {
                    translate(xaxis_endstop_offset_SN04)
                    translate([-36,-9,0])
                    rotate(ZAXIS*-90)
                    import("stl/SN04-N_Inductive_Proximity_Sensor_3528_0.stl");
                }
            }
        }

        // belt idler pulley screw
        for(z=[-1,1])
        translate([xaxis_end_pulley_offset,0,-xaxis_beltpath_z_offsets[max(0,beltpath_index)]])
        {
            translate([0, -xaxis_beltpath_width/2 - 7*mm, 0])
            {
                screw(nut=NutHexM5, h=25*mm, with_nut=true, orient=[0,1,0], align=[0,1,0]);
            }
        }

        for(z=[-1,1])
        translate([xaxis_end_pulley_offset,0,-xaxis_beltpath_z_offsets[max(0,beltpath_index)]])
        {
            pulley(xaxis_idler_pulley, orient=[0,1,0]);
        }

        if(show_nut)
        {
            mirror([0,0,nut_top?1:0])
            translate([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])
                cylindera(d=zaxis_rod_d, h=zaxis_rod_l, orient=[0,0,1]);
        }

        if(show_bearings)
        {
            for(z=[-1,1])
            translate([0,0,z*xaxis_rod_distance/2])
            translate([0, -xaxis_zaxis_distance_y, 0])
            bearing(zaxis_bearing);
        }
    }
}

module xaxis_end_beltpath(height, width, length = 1000, align=[0,0,0], orient=[1,0,0])
{
    hull()
    for(z=[-1,1])
    translate([0,0,z*height/2])
    teardrop(h=length, d=width, orient=orient, align=align, roll=-180*min(0,z), truncate=1);
}

module xaxis_end_znut()
{
    difference()
    {
        union()
        {
            cylindera(d=zaxis_nut[1], h=zaxis_nut[3], orient=[0,0,1], align=[0,0,1]);
            cylindera(d=zaxis_nut[0], h=zaxis_nut[4], orient=[0,0,1], align=[0,0,1]);
        }

        translate([0,0,-.1])
        cylindera(d=zaxis_nut[2], h=zaxis_nut[4]+.2, orient=[0,0,1], align=[0,0,1]);
    }
}

if(false)
{
    // x axis
    /*translate([0,0,axis_pos_z])*/
    {
        /*if(!$preview_mode)*/
        {
            zrod_offset = zmotor_mount_rod_offset_x;
            for(x=[-1,1])
            {
                z=xaxis_beltpath_z_offsets[x<0?0:x];
                xo = x>0?xaxis_end_pulley_offset:xaxis_end_motor_offset[0];
                xw = x<0?xaxis_end_pulley_offset:xaxis_end_motor_offset[0];
                translate([-main_width/2-xo/2, xaxis_zaxis_distance_y, z])
                rotate([90,0,0])
                color("black")
                belt_path(main_width+xw, 6, xaxis_pulley_inner_d, orient=[1,0,0], align=[1,0,0]);
            }
        }

        /*translate([axis_pos_x,0,0])*/
        /*{*/
            // x carriage
            /*attach(xaxis_carriage_conn, [[0,-xaxis_zaxis_distance_y,0],[0,0,0]])*/
            /*{*/
                /*x_carriage_full();*/
            /*}*/
        /*}*/

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

        for(x=[-1,1])
        translate([x*(main_width/2), 0, 0])
        translate([x*(zmotor_mount_rod_offset_x),0,0])
        cylindera(h=zaxis_rod_l,d=zaxis_rod_d, orient=ZAXIS, align=[0,0,0]);

        for(x=[-1,1])
        {
            translate([x*(main_width/2), 0, 0])
            {
                translate([0, xaxis_zaxis_distance_y, 0])
                translate([x*zmotor_mount_rod_offset_x, 0, 0])
                mirror([max(0,x),0,0])
                {
                    xaxis_end(with_motor=true, beltpath_index=max(0,x), show_nut=true, show_motor=true, show_nut=true);
                }
            }
        }
    }

}

if(false)
{
    for(x=[-1,1])
    translate([x*55,x*55,xaxis_end_wz/2])
    mirror([max(0,x),0,0])
    {
        xaxis_end(with_motor=true, beltpath_index=max(0,x), show_motor=false, show_nut=false, show_bearings=false, with_xrod_adjustment=true);
    }
}

module part_x_end_right()
{
    x=1;
    translate([0,0,xaxis_end_wz/2])
    mirror([max(0,x),0,0])
    xaxis_end(with_motor=true, beltpath_index=max(0,x), with_xrod_adjustment=true);
}

module part_x_end_left()
{
    x=-1;
    translate([0,0,xaxis_end_wz/2])
    mirror([max(0,x),0,0])
    xaxis_end(with_motor=true, beltpath_index=max(0,x), with_xrod_adjustment=true);
}


config: remove belt stuff, now have this in libutils

include <MCAD/stepper.scad>
include <pulley.scad>
include <thing_libutils/bearing_data.scad>
include <thing_libutils/metric-thread-data.scad>
include <thing_libutils/metric-hexnut-data.scad>
include <thing_libutils/misc.scad>

e=0.01;

// minimum size of a fragment
// resolution of any round object (segment length)
// Because of this variable very small circles have a smaller number of fragments than specified using $fa.
// The default value is 2.
$fs = 2;

// minimum angle for a fragment.
// The default value is 12 (i.e. 30 fragments for a full circle)
$fa = 12;

//hq
if(false)
{
    $fs= 0.5;
    $fa = 4;
}

/*$show_vit=true;*/

// enable preview model (faster openscad)
preview_mode=false;

extrusion_height            = 0.4*mm;

// width of a single wall, should match your slicer settings
extrusion_width             = 0.4*mm;

// how many lines should a normal wall have (i.e. 0.6(extrusion_width)*6(normal_wall_factor)= 3.6mm wall width)
normal_wall_factor          = 3;

thick_wall_factor           = 4;

// diameter of your filament.
filament_d                  = 1.75*mm;
filament_r                  = filament_d/2;

main_width = 340*mm;
main_depth = 420*mm;
main_height = 400*mm;
main_upper_width = 420*mm;

extrusion_size = 20*mm;
extrusion_thread = ThreadM5;
extrusion_thread_dia = lookup(ThreadSize, extrusion_thread);
extrusion_nut = MHexNutM5;
extrusion_nut_dia = lookup(MHexNutWidthMax, extrusion_nut);

// for tapped ends
extrusion_end_nut = MHexNutM6;

main_lower_dist_z = 80*mm;
main_upper_dist_y = 160*mm;

gantry_connector_thickness = 5;

rod_fit_tolerance=1.01;

ziptie_type = [1.2*mm, 2.8*mm];
ziptie_thickness = ziptie_type[0];
ziptie_width = ziptie_type[1]+0.6*mm;
ziptie_bearing_distance=3*mm;

xaxis_rod_distance = 60*mm;
xaxis_rod_d = 9.975*mm;
xaxis_rod_l = 500*mm;
xaxis_rod_offset_x = 0*mm;
xaxis_bearing=bearing_sf1_1010;
/*xaxis_bearing=bearing_igus_rj4jp_01_10;*/

xaxis_pulley = pulley_2GT_20T;
xaxis_pulley_inner_d = xaxis_pulley[2];
xaxis_idler_pulley = pulley_2GT_20T_idler;
xaxis_idler_pulley_inner_d = xaxis_idler_pulley[2];
xaxis_idler_pulley_outer_d = xaxis_idler_pulley[3];

xaxis_belt_width = 6*mm;
xaxis_beltpath_height = xaxis_pulley_inner_d+5*mm;
xaxis_beltpath_width = max(xaxis_belt_width+3*mm, xaxis_pulley[0]+2*mm);
xaxis_beltpath_z_offset_pulley = xaxis_pulley_inner_d/2;
/*xaxis_beltpath_z_offsets = [xaxis_beltpath_z_offset_pulley];*/
xaxis_beltpath_z_offsets = [-2*mm-xaxis_beltpath_z_offset_pulley, 2*mm+xaxis_beltpath_z_offset_pulley];

xaxis_carriage_bearing_offset_y = ziptie_thickness+3*mm;
xaxis_carriage_beltpath_offset_y = xaxis_carriage_bearing_offset_y+xaxis_bearing[1]/2;

xaxis_motor = dict_replace(Nema17, NemaFrontAxleLength, 22*mm);

yaxis_rod_distance = 170*mm;
yaxis_rod_d = 11.975*mm;
yaxis_rod_l = 500*mm;
/*yaxis_bearing=bearing_igus_rj4jp_01_12;*/
yaxis_bearing=bearing_sf1_1212;
yaxis_bearing_distance_y = 7*cm;

yaxis_motor = dict_replace(Nema17, NemaFrontAxleLength, 22*mm);

yaxis_pulley = pulley_2GT_20T;
yaxis_pulley_inner_d = yaxis_pulley[2];
ymotor_mount_thickness = 5;
ymotor_mount_thickness_h = 5;
yaxis_motor_offset_x = lookup(NemaSideSize,yaxis_motor)/2+ymotor_mount_thickness;
yaxis_motor_offset_z = -5*mm;
yaxis_belt_path_offset_x = -yaxis_pulley_inner_d/2;
yaxis_belt_path_offset_z = yaxis_motor_offset_z + 10*mm;

yaxis_idler_pulley = pulley_2GT_20T_idler;
yaxis_idler_pulley_inner_d = yaxis_idler_pulley[2];
yaxis_idler_pulley_outer_d = yaxis_idler_pulley[3];
yaxis_idler_pulley_h = yaxis_idler_pulley[0];
yaxis_idler_mount_thickness = 5;
yaxis_idler_pulley_tight_len = 20*mm;
yaxis_idler_pulley_offset_y = yaxis_idler_mount_thickness + yaxis_pulley_inner_d/2 + yaxis_idler_pulley_tight_len;
yaxis_idler_offset_x = lookup(NemaSideSize,yaxis_motor)/2+ymotor_mount_thickness;
yaxis_idler_offset_z = 10*mm;

yaxis_carriage_size=[220*mm,220*mm,5*mm];

zaxis_rod_d = 11.975*mm;
zaxis_rod_l = 500*mm;
zaxis_bearing=bearing_bronze_12_18_18;

// Nema17 motor w/340mm long 8*mm leadscrew
zaxis_motor = dict_replace_multiple(Nema17,
        [
        [NemaAxleDiameter, 8*mm],
        [NemaFrontAxleLength, 340*mm],
        ]);

zmotor_w = lookup(NemaSideSize,zaxis_motor);
zmotor_h = lookup(NemaLengthLong,zaxis_motor);

// inner_d, outer_d, thread, outer_h, full_h
zaxis_nut = [20*mm, 36*mm, 8*mm, 5*mm, 23*mm];

zaxis_motor_offset_z = 10*mm;
zmotor_mount_thickness = 5;
zmotor_mount_thickness_h = 10;
zmotor_mount_motor_offset=5;

zmotor_w = lookup(NemaSideSize,zaxis_motor);
zmotor_h = lookup(NemaLengthLong,zaxis_motor);
zmotor_mount_thread_dia = lookup(ThreadSize, extrusion_thread);
zmotor_mount_width = zmotor_w+zmotor_mount_thickness*2 + zmotor_mount_thread_dia*8;
zmotor_mount_h = main_lower_dist_z+extrusion_size+zaxis_motor_offset_z;

zmotor_mount_clamp_dist = zaxis_rod_d*2.5;
zmotor_mount_clamp_thread = ThreadM4;
zmotor_mount_clamp_nut = MHexNutM4;
zmotor_mount_clamp_thread_dia = lookup(ThreadSize, zmotor_mount_clamp_thread);
zmotor_mount_clamp_nut_dia = lookup(MHexNutWidthMin, zmotor_mount_clamp_nut);
zmotor_mount_clamp_nut_thick = lookup(MHexNutThickness, zmotor_mount_clamp_nut);
zmotor_mount_clamp_width = zmotor_mount_clamp_dist+zmotor_mount_clamp_thread_dia*3;

xaxis_zaxis_distance_y_ = max(xaxis_rod_d/2 + zaxis_bearing[1]/2, zaxis_nut[1]/2 - xaxis_rod_d/2);
xaxis_zaxis_distance_y = xaxis_zaxis_distance_y_ + ziptie_type[0]+.5*mm + 1*mm;

zaxis_nut_mount_outer = zaxis_nut[1]/2 + zaxis_rod_d/2 + 1*mm;

// offset between Z motor screw and z rod
// place z rod as close as possible (depends on z nut and also motor etc)
zaxis_rod_screw_distance_x = max(zaxis_nut_mount_outer, zaxis_rod_d/2 + zmotor_w/2 + 1*mm);

// z rod offset from lower extrusion (outer)
zmotor_mount_rod_offset_x = zmotor_w/2+zaxis_rod_screw_distance_x+zmotor_mount_motor_offset;

// z screw offset from lower extrusion (outer)
zmotor_mount_screw_offset_x = zmotor_mount_rod_offset_x - zaxis_rod_screw_distance_x ;

color_extrusion = "DimGray";
color_rods = "CornflowerBlue";
color_part = "DarkRed";
color_gantry_connectors = "OliveDrab";

// GT2
// there is bunch of GT2 belts with different tooth-to-tooth distance
// this one is most common in reprap world
// adjust to your needs.
belt_width = 6.5;
belt_tooth_distance = 2;
belt_tooth_ratio = 0.5;
belt_thickness = 0.8;

//T2.5
//belt_tooth_distance = 2.5;
//belt_tooth_ratio = 0.5;

//T5 (strongly discouraged)
//belt_tooth_distance = 5;
//belt_tooth_ratio = 0.75;

//HTD3
//belt_tooth_distance = 3;
//belt_tooth_ratio = 0.75;

//MXL
//belt_tooth_distance = 2.032;
//belt_tooth_ratio = 0.64;


Add an OpenSCAD file.

Add an OpenSCAD file.

// VoR-12 - 2D foot

// Copyright (c) 2015 Jérémie DECOCK (www.jdhp.org)

// Base unit: mm

module 2d_foot() {
    inner_square_size = 33;
    outer_square_size = 105;
    screw_hole_diameter = 3;

    difference() {
        union() {
            square(outer_square_size, center=true);
            rotate(45) 2d_toe();
            rotate(135) 2d_toe();
            rotate(-45) 2d_toe();
            rotate(-135) 2d_toe();
        }

        union() {
            square(inner_square_size, center=true);
            translate([-31.5,    0]) circle(d=screw_hole_diameter);
            translate([ 31.5,    0]) circle(d=screw_hole_diameter);
            translate([    0, 38.5]) circle(d=screw_hole_diameter);
        }
    }
}

module 2d_toe() {
    $fn=50;

    toe_depth = 25;
    toe_length = 80;

    hull() {
        square(toe_depth, center=true);
        translate([toe_length, 0]) circle(d=toe_depth);
    }
}

// Uncomment the following line to test this module
2d_foot();

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


timingbelt: Fixes and rewrites

timingbelt: Fixes and rewrites

/*Parametric belting section generator
 * types GT2 2mm T2.5 T5 T10 MXL
 *
 * (c) ALJ_rprp
 *
 * Derived from http://www.thingiverse.com/
 * thing:19758 By The DoomMeister
 * thing:16627 by Droftarts
 *
 * licence GPL 2.1 or later
 *
 * deal properly with ends
 * allow circular segments
 * length is given in mm not nb of teeth
 * belt is centered at z=0 and extend along x
 *
 * TODO : add ofset for cosmetic teeth liaisons between segments
 *
 * usage :
 * belt_angle(prf = tT2_5, rad=25, bwdth = 6, angle=90)
 * belt_len  (prf = tT2_5, belt_width = 6, len = 10)
 */

include <shapes.scad>
include <transforms.scad>

// profiles
tGT2_2=0;
tT2_5=1;
tT5=2;
tT10=3;
tMXL=4;

/*test_belt();*/

module test_belt()
{
    $fs= 0.5;
    $fa = 4;

    translate([-00.5,0,5.5]) cube([1,40,1]);

    stack(dist=20, axis=[0,0,-1])
    {
        belt_len(profile = tT10, belt_width = 10, len = 100);
        color("red") belt_len(profile = tT5, belt_width = 10, len = 100);
        color("green") belt_len(profile = tT2_5, belt_width = 10, len = 80);
        color("blue") belt_len(profile = tGT2_2, belt_width = 10, len = 100);
        color("orange") belt_len(profile = tMXL, belt_width = 10, len = 100);

        belt_angle(tT10,20,10,180);
        belt_angle(tT5,15,10,90);
        belt_angle(tT2_5,25,10,120);
        belt_angle(tGT2_2,30,10,40);
        belt_angle(tMXL,30,10,40);

        color("aquamarine") {
            belt_len(tT2_5,10, 50);
            translate([50,30,0]) rotate([0,0,180]) belt_len(tT2_5,10,50);
            translate([ 0,30,0]) rotate([0,0,180]) belt_angle(tT2_5,15,10,180);
            translate([50,0,0]) rotate([0,0,0]) belt_angle(tT2_5,15,10,180);
        }
    }
}

module belt_angle(prf = tT2_5, rad=25, bwdth = 6, angle=90)
{
    av=360/2/rad/3.14159*tpitch[prf];
    bk=bk_thick[prf];

    nn=ceil(angle/av);
    ang=av*nn;

    intersection()
    {
        translate([0,-bk-.5,0])
        pie_slice(r=rad+bk+.5,start_angle=-90,end_angle=angle-90,h=bwdth, align=[0,1,0]);

        union ()
        {
            for(i=[0:nn])
            {
                translate ([0,rad,-bwdth/2])
                rotate ([0,0,av*i])
                translate ([0,-rad,0])
                draw_tooth(prf,0,bwdth);
            }

            translate ([0,rad,-bwdth/2])
            rotate([0,0,-90])
            rotate_extrude(angle = angle)
                polygon([[rad,0],[rad+bk,0],[rad+bk,bwdth],[rad,bwdth]]);
        }
    }
}

//Outer Module
module belt_len(profile = tT2_5, belt_width = 6, len = 10){
    if ( profile == tT2_5 ) { _belt_len(prf=profile,len = len,bwdth = belt_width);}
    if ( profile == tT5 )   { _belt_len(prf=profile,len = len,bwdth = belt_width);}
    if ( profile == tT10 )  { _belt_len(prf=profile,len = len,bwdth = belt_width);}
    if ( profile == tMXL )	{ _belt_len(prf=profile,len = len,bwdth = belt_width);}
    if ( profile == tGT2_2 ){ _belt_len(prf=profile,len = len,bwdth = belt_width);}
}

//inner module
module _belt_len(prf = -1, len = 10, bwdth = 5) {

    n=ceil(len/tpitch[prf]);

    translate ([0,0,-bwdth/2]) intersection() {
        union(){
            for( i = [0:n]) {
                draw_tooth(prf,i,bwdth);
            }
            translate([-1,-bk_thick[prf],0])cube([len+1,bk_thick[prf],bwdth]);
        }
        translate([0,-bk_thick[prf],0])cube([len,max_h[prf]+bk_thick[prf],bwdth]);
    }
}

module draw_tooth(prf,i,bwdth) {
    if ( prf == tT2_5 ) { translate([tpitch[prf]*i,0,0])
        linear_extrude(height=bwdth) polygon(pf_T2_5);}
    if ( prf == tT5 ) { translate([tpitch[prf]*i,0,0])
        linear_extrude(height=bwdth) polygon(pf_T5);}
    if ( prf == tT10 ) { translate([tpitch[prf]*i,0,0])
        linear_extrude(height=bwdth) polygon(pf_T10);}
    if ( prf == tMXL ) { translate([tpitch[prf]*i,0,0])
        linear_extrude(height=bwdth) polygon(pf_MXL);}
    if ( prf == tGT2_2 ) { translate([tpitch[prf]*i,0,0])
        linear_extrude(height=bwdth) polygon(pf_GT2_2);}
}

/************************************
 *				DATA TABLES					*
 ************************************/
    tpitch = [2,2.5,5,10,2.032];
    bk_thick=[0.6,0.6,1,2,0.64];
    max_h=[0.76447, 0.699911, 1.189895, 2.499784, 0.508035];

    pf_GT2_2=  [[ 0.747183,-0.5     ],[ 0.747183, 0       ],[ 0.647876, 0.037218],
    [ 0.598311, 0.130528],[ 0.578556, 0.238423],[ 0.547158, 0.343077],
    [ 0.504649, 0.443762],[ 0.451556, 0.53975 ],[ 0.358229, 0.636924],
    [ 0.2484  , 0.707276],[ 0.127259, 0.750044],[ 0       , 0.76447 ],
    [-0.127259, 0.750044],[-0.2484  , 0.707276],[-0.358229, 0.636924],
    [-0.451556, 0.53975 ],[-0.504797, 0.443762],[-0.547291, 0.343077],
    [-0.578605, 0.238423],[-0.598311, 0.130528],[-0.648009, 0.037218],
    [-0.747183, 0       ],[-0.747183,-0.5]];
pf_T2_5=   [[-0.839258,-0.5     ],[-0.839258, 0       ],[-0.770246, 0.021652],
    [-0.726369, 0.079022],[-0.529167, 0.620889],[-0.485025, 0.67826 ],
    [-0.416278, 0.699911],[ 0.416278, 0.699911],[ 0.484849, 0.67826 ],
    [ 0.528814, 0.620889],[ 0.726369, 0.079022],[ 0.770114, 0.021652],
    [ 0.839258, 0       ],[ 0.839258,-0.5]];
pf_T5= 	  [[-1.632126,-0.5     ],[-1.632126, 0       ],[-1.568549, 0.004939],
    [-1.507539, 0.019367],[-1.450023, 0.042686],[-1.396912, 0.074224],
    [-1.349125, 0.113379],[-1.307581, 0.159508],[-1.273186, 0.211991],
    [-1.246868, 0.270192],[-1.009802, 0.920362],[-0.983414, 0.978433],
    [-0.949018, 1.030788],[-0.907524, 1.076798],[-0.859829, 1.115847],
    [-0.80682 , 1.147314],[-0.749402, 1.170562],[-0.688471, 1.184956],
    [-0.624921, 1.189895],[ 0.624971, 1.189895],[ 0.688622, 1.184956],
    [ 0.749607, 1.170562],[ 0.807043, 1.147314],[ 0.860055, 1.115847],
    [ 0.907754, 1.076798],[ 0.949269, 1.030788],[ 0.9837  , 0.978433],
    [ 1.010193, 0.920362],[ 1.246907, 0.270192],[ 1.273295, 0.211991],
    [ 1.307726, 0.159508],[ 1.349276, 0.113379],[ 1.397039, 0.074224],
    [ 1.450111, 0.042686],[ 1.507589, 0.019367],[ 1.568563, 0.004939],
    [ 1.632126, 0       ],[ 1.632126,-0.5]];
pf_T10=    [[-3.06511 ,-1       ],[-3.06511 , 0       ],[-2.971998, 0.007239],
    [-2.882718, 0.028344],[-2.79859 , 0.062396],[-2.720931, 0.108479],
    [-2.651061, 0.165675],[-2.590298, 0.233065],[-2.539962, 0.309732],
    [-2.501371, 0.394759],[-1.879071, 2.105025],[-1.840363, 2.190052],
    [-1.789939, 2.266719],[-1.729114, 2.334109],[-1.659202, 2.391304],
    [-1.581518, 2.437387],[-1.497376, 2.47144 ],[-1.408092, 2.492545],
    [-1.314979, 2.499784],[ 1.314979, 2.499784],[ 1.408091, 2.492545],
    [ 1.497371, 2.47144 ],[ 1.581499, 2.437387],[ 1.659158, 2.391304],
    [ 1.729028, 2.334109],[ 1.789791, 2.266719],[ 1.840127, 2.190052],
    [ 1.878718, 2.105025],[ 2.501018, 0.394759],[ 2.539726, 0.309732],
    [ 2.59015 , 0.233065],[ 2.650975, 0.165675],[ 2.720887, 0.108479],
    [ 2.798571, 0.062396],[ 2.882713, 0.028344],[ 2.971997, 0.007239],
    [ 3.06511 , 0       ],[ 3.06511 ,-1]];
pf_MXL=    [[-0.660421,-0.5     ],[-0.660421, 0       ],[-0.621898, 0.006033],
    [-0.587714, 0.023037],[-0.560056, 0.049424],[-0.541182, 0.083609],
    [-0.417357, 0.424392],[-0.398413, 0.458752],[-0.370649, 0.48514 ],
    [-0.336324, 0.502074],[-0.297744, 0.508035],[ 0.297744, 0.508035],
    [ 0.336268, 0.502074],[ 0.370452, 0.48514 ],[ 0.39811 , 0.458752],
    [ 0.416983, 0.424392],[ 0.540808, 0.083609],[ 0.559752, 0.049424],
    [ 0.587516, 0.023037],[ 0.621841, 0.006033],[ 0.660421, 0       ],
    [ 0.660421,-0.5]];

/*Parametric belting section generator
 * types GT2 2mm T2.5 T5 T10 MXL
 *
 * (c) ALJ_rprp
 *
 * Derived from http://www.thingiverse.com/
 * thing:19758 By The DoomMeister
 * thing:16627 by Droftarts
 *
 * licence GPL 2.1 or later
 *
 * deal properly with ends
 * allow circular segments
 * length is given in mm not nb of teeth
 * belt is centered at z=0 and extend along x
 *
 * TODO : add ofset for cosmetic teeth liaisons between segments
 *
 * usage :
 * belt_angle(prf = tT2_5, rad=25, bwdth = 6, angle=90,fn=128)
 * belt_len  (prf = tT2_5, belt_width = 6, len = 10)
 */

// profiles
tGT2_2=0;
tT2_5=1;
tT5=2;
tT10=3;
tMXL=4;

/*test_belt();*/

module test_belt() {
    translate([-00.5,0,5.5])cube([1,40,1]);

    belt_len(profile = tT10, belt_width = 10, len = 100);
    translate([0,0,-20])color("red")belt_len(profile = tT5, belt_width = 10, len = 100);
    translate([0,0,-40])color("green")belt_len(profile = tT2_5, belt_width = 10, len = 80);
    translate([0,0,-60])color("blue")belt_len(profile = tGT2_2, belt_width = 10, len = 100);
    translate([0,0,-80])color("orange")belt_len(profile = tMXL, belt_width = 10, len = 100);

    translate([0,0,-0])  belt_angle(tT10,20,10,180);
    translate([0,0,-20]) belt_angle(tT5,15,10,90);
    translate([0,0,-40]) belt_angle(tT2_5,25,10,120);
    translate([0,0,-60]) belt_angle(tGT2_2,30,10,40);
    translate([0,0,-80]) belt_angle(tMXL,30,10,40);

    translate([0,0,-100])color("aquamarine") {
        belt_len(tT2_5,10, 50);
        translate([50,30,0]) rotate([0,0,180]) belt_len(tT2_5,10,50);
        translate([ 0,30,0]) rotate([0,0,180]) belt_angle(tT2_5,15,10,180);
        translate([50,0,0]) rotate([0,0,0]) belt_angle(tT2_5,15,10,180);
    }
}

/* there is no partial rotate extrude in scad, hence the workaround
 * note that the pie slice will silently drop angles > 360 */
module p_slice(radius, angle,height,back_t=0.6) {
    pt_slc = [[0,radius],
           [0 ,-back_t],
           [radius,-back_t],
               [radius+back_t,radius],
                   [radius+back_t,radius*2],
                       [0,radius*2+back_t],
                           [-radius-back_t,radius*2+back_t],
                               [-radius-back_t,radius],
                                   [-radius-back_t,-back_t],
                                       [(radius+back_t)*sin(angle),(radius+back_t)*(1-cos(angle))-back_t]];

    if (angle<=90) {
        linear_extrude(height = height+0.2, center=true)
            polygon( points = pt_slc,
                    paths=[[0,1,2,9]]);
    }else if (angle<=180){
        linear_extrude(height = height+0.2, center=true)
            polygon( points = pt_slc,
                    paths=[[0,1,2,3,4,9]]);
    }else if (angle<=270){
        linear_extrude(height = height+0.2, center=true)
            polygon( points = pt_slc,
                    paths=[[0,1,2,3,4,5,6,9]]);
    }else if (angle<360) {
        linear_extrude(height = height+0.2, center=true)
            polygon( points = pt_slc,
                    paths=[[0,1,2,3,4,5,6,7,8,9]]);
    }
}

dp=5;

module belt_angle(prf = tT2_5, rad=25, bwdth = 6, angle=90,fn=128) {
    av=360/2/rad/3.14159*tpitch[prf];
    bk=bk_thick[prf];

    nn=ceil(angle/av);
    ang=av*nn;
    intersection(){
        p_slice(rad,angle,bwdth,bk_thick[prf]);
        union () {
            for( i = [0:nn]){
                translate ([0,rad,-bwdth/2])rotate ([0,0,av*i])translate ([0,-rad,0])
                    draw_tooth(prf,0,bwdth);
            }
            translate ([0,rad,-bwdth/2]) rotate_extrude(angle = 90, $fn=fn)
                polygon([[rad,0],[rad+bk,0],[rad+bk,bwdth],[rad,bwdth]]);
        }
    }
}

//Outer Module
module belt_len(profile = tT2_5, belt_width = 6, len = 10){
    if ( profile == tT2_5 ) { _belt_len(prf=profile,len = len,bwdth = belt_width);}
    if ( profile == tT5 )   { _belt_len(prf=profile,len = len,bwdth = belt_width);}
    if ( profile == tT10 )  { _belt_len(prf=profile,len = len,bwdth = belt_width);}
    if ( profile == tMXL )	{ _belt_len(prf=profile,len = len,bwdth = belt_width);}
    if ( profile == tGT2_2 ){ _belt_len(prf=profile,len = len,bwdth = belt_width);}
}

//inner module
module _belt_len(prf = -1, len = 10, bwdth = 5) {

    n=ceil(len/tpitch[prf]);

    translate ([0,0,-bwdth/2]) intersection() {
        union(){
            for( i = [0:n]) {
                draw_tooth(prf,i,bwdth);
            }
            translate([-1,-bk_thick[prf],0])cube([len+1,bk_thick[prf],bwdth]);
        }
        translate([0,-bk_thick[prf],0])cube([len,max_h[prf]+bk_thick[prf],bwdth]);
    }
}

module draw_tooth(prf,i,bwdth) {
    if ( prf == tT2_5 ) { translate([tpitch[prf]*i,0,0])
        linear_extrude(height=bwdth) polygon(pf_T2_5);}
    if ( prf == tT5 ) { translate([tpitch[prf]*i,0,0])
        linear_extrude(height=bwdth) polygon(pf_T5);}
    if ( prf == tT10 ) { translate([tpitch[prf]*i,0,0])
        linear_extrude(height=bwdth) polygon(pf_T10);}
    if ( prf == tMXL ) { translate([tpitch[prf]*i,0,0])
        linear_extrude(height=bwdth) polygon(pf_MXL);}
    if ( prf == tGT2_2 ) { translate([tpitch[prf]*i,0,0])
        linear_extrude(height=bwdth) polygon(pf_GT2_2);}
}

/************************************
 *				DATA TABLES					*
 ************************************/
    tpitch = [2,2.5,5,10,2.032];
    bk_thick=[0.6,0.6,1,2,0.64];
    max_h=[0.76447, 0.699911, 1.189895, 2.499784, 0.508035];

    pf_GT2_2=  [[ 0.747183,-0.5     ],[ 0.747183, 0       ],[ 0.647876, 0.037218],
    [ 0.598311, 0.130528],[ 0.578556, 0.238423],[ 0.547158, 0.343077],
    [ 0.504649, 0.443762],[ 0.451556, 0.53975 ],[ 0.358229, 0.636924],
    [ 0.2484  , 0.707276],[ 0.127259, 0.750044],[ 0       , 0.76447 ],
    [-0.127259, 0.750044],[-0.2484  , 0.707276],[-0.358229, 0.636924],
    [-0.451556, 0.53975 ],[-0.504797, 0.443762],[-0.547291, 0.343077],
    [-0.578605, 0.238423],[-0.598311, 0.130528],[-0.648009, 0.037218],
    [-0.747183, 0       ],[-0.747183,-0.5]];
pf_T2_5=   [[-0.839258,-0.5     ],[-0.839258, 0       ],[-0.770246, 0.021652],
    [-0.726369, 0.079022],[-0.529167, 0.620889],[-0.485025, 0.67826 ],
    [-0.416278, 0.699911],[ 0.416278, 0.699911],[ 0.484849, 0.67826 ],
    [ 0.528814, 0.620889],[ 0.726369, 0.079022],[ 0.770114, 0.021652],
    [ 0.839258, 0       ],[ 0.839258,-0.5]];
pf_T5= 	  [[-1.632126,-0.5     ],[-1.632126, 0       ],[-1.568549, 0.004939],
    [-1.507539, 0.019367],[-1.450023, 0.042686],[-1.396912, 0.074224],
    [-1.349125, 0.113379],[-1.307581, 0.159508],[-1.273186, 0.211991],
    [-1.246868, 0.270192],[-1.009802, 0.920362],[-0.983414, 0.978433],
    [-0.949018, 1.030788],[-0.907524, 1.076798],[-0.859829, 1.115847],
    [-0.80682 , 1.147314],[-0.749402, 1.170562],[-0.688471, 1.184956],
    [-0.624921, 1.189895],[ 0.624971, 1.189895],[ 0.688622, 1.184956],
    [ 0.749607, 1.170562],[ 0.807043, 1.147314],[ 0.860055, 1.115847],
    [ 0.907754, 1.076798],[ 0.949269, 1.030788],[ 0.9837  , 0.978433],
    [ 1.010193, 0.920362],[ 1.246907, 0.270192],[ 1.273295, 0.211991],
    [ 1.307726, 0.159508],[ 1.349276, 0.113379],[ 1.397039, 0.074224],
    [ 1.450111, 0.042686],[ 1.507589, 0.019367],[ 1.568563, 0.004939],
    [ 1.632126, 0       ],[ 1.632126,-0.5]];
pf_T10=    [[-3.06511 ,-1       ],[-3.06511 , 0       ],[-2.971998, 0.007239],
    [-2.882718, 0.028344],[-2.79859 , 0.062396],[-2.720931, 0.108479],
    [-2.651061, 0.165675],[-2.590298, 0.233065],[-2.539962, 0.309732],
    [-2.501371, 0.394759],[-1.879071, 2.105025],[-1.840363, 2.190052],
    [-1.789939, 2.266719],[-1.729114, 2.334109],[-1.659202, 2.391304],
    [-1.581518, 2.437387],[-1.497376, 2.47144 ],[-1.408092, 2.492545],
    [-1.314979, 2.499784],[ 1.314979, 2.499784],[ 1.408091, 2.492545],
    [ 1.497371, 2.47144 ],[ 1.581499, 2.437387],[ 1.659158, 2.391304],
    [ 1.729028, 2.334109],[ 1.789791, 2.266719],[ 1.840127, 2.190052],
    [ 1.878718, 2.105025],[ 2.501018, 0.394759],[ 2.539726, 0.309732],
    [ 2.59015 , 0.233065],[ 2.650975, 0.165675],[ 2.720887, 0.108479],
    [ 2.798571, 0.062396],[ 2.882713, 0.028344],[ 2.971997, 0.007239],
    [ 3.06511 , 0       ],[ 3.06511 ,-1]];
pf_MXL=    [[-0.660421,-0.5     ],[-0.660421, 0       ],[-0.621898, 0.006033],
    [-0.587714, 0.023037],[-0.560056, 0.049424],[-0.541182, 0.083609],
    [-0.417357, 0.424392],[-0.398413, 0.458752],[-0.370649, 0.48514 ],
    [-0.336324, 0.502074],[-0.297744, 0.508035],[ 0.297744, 0.508035],
    [ 0.336268, 0.502074],[ 0.370452, 0.48514 ],[ 0.39811 , 0.458752],
    [ 0.416983, 0.424392],[ 0.540808, 0.083609],[ 0.559752, 0.049424],
    [ 0.587516, 0.023037],[ 0.621841, 0.006033],[ 0.660421, 0       ],
    [ 0.660421,-0.5]];