x/ends: reduce top/bottom thickness

x/ends: reduce top/bottom thickness

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>
use <thing_libutils/timing-belts.scad>

motor_mount_wall_thick = xaxis_pulley[1] - xaxis_pulley[0]/2 + 4*mm;
xaxis_end_pulley_offset = 39*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 = [10.3*mm, 20*mm, 6.3*mm];
xaxis_endstop_screw_offset = [-1.8*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);

        translate([xaxis_end_width(with_motor),0,(xaxis_rod_distance/2)+xaxis_rod_d])
        {
            rcubea(xaxis_endstop_size, 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=MHexNutM4, 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=MHexNutM5, h=xaxis_beltpath_width+13*mm, with_nut=true, orient=[0,1,0], align=[0,1,0]);
            }
        }

        //endstop mount screw cuts
        translate([xaxis_end_width(with_motor),0,(xaxis_rod_distance/2)+xaxis_rod_d])
        translate(xaxis_endstop_screw_offset)
        for(y=[-1,1])
        translate([-5*mm,y*9.5*mm/2,xaxis_endstop_size[2]])
        {
            screw_cut(nut=MHexNutM2_5, screw_l=6*mm, screw_l_extra=0*mm, embed_head=false, with_head=true, with_nut=false, orient=[0,0,-1], align=[0,0,-1]);
            /*nut_trap_cut(nut=MHexNutM2_5, screw_l=6*mm, screw_l_extra=0*mm, trap_axis=[-1,0,0], 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);

                // 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+4*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)
        {
            translate([xaxis_end_width(with_motor),0,(xaxis_rod_distance/2)+xaxis_rod_d])
            {
                difference()
                {
                    rcubea(xaxis_endstop_size, align=[-1,0,1]);

                    translate(xaxis_endstop_screw_offset)
                    for(y=[-1,1])
                    translate([-5*mm,y*9.5*mm/2,xaxis_endstop_size[2]])
                    screw(nut=MHexNutM2_5, h=6*mm, orient=[0,0,-1], align=[0,0,-1]);
                }
            }
        }

        // 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=MHexNutM5, 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,0,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/metric-screw.scad>
use <thing_libutils/timing-belts.scad>

motor_mount_wall_thick = xaxis_pulley[1] - xaxis_pulley[0]/2 + 4*mm;
xaxis_end_pulley_offset = 39*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]+5*mm;

xaxis_endstop_size = [10.3*mm, 20*mm, 6.3*mm];
xaxis_endstop_screw_offset = [-1.8*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);

        translate([xaxis_end_width(with_motor),0,(xaxis_rod_distance/2)+xaxis_rod_d])
        {
            rcubea(xaxis_endstop_size, 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=MHexNutM4, 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=MHexNutM5, h=xaxis_beltpath_width+13*mm, with_nut=true, orient=[0,1,0], align=[0,1,0]);
            }
        }

        //endstop mount screw cuts
        translate([xaxis_end_width(with_motor),0,(xaxis_rod_distance/2)+xaxis_rod_d])
        translate(xaxis_endstop_screw_offset)
        for(y=[-1,1])
        translate([-5*mm,y*9.5*mm/2,xaxis_endstop_size[2]])
        {
            screw_cut(nut=MHexNutM2_5, screw_l=6*mm, screw_l_extra=0*mm, embed_head=false, with_head=true, with_nut=false, orient=[0,0,-1], align=[0,0,-1]);
            /*nut_trap_cut(nut=MHexNutM2_5, screw_l=6*mm, screw_l_extra=0*mm, trap_axis=[-1,0,0], 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);

                // 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+4*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)
        {
            translate([xaxis_end_width(with_motor),0,(xaxis_rod_distance/2)+xaxis_rod_d])
            {
                difference()
                {
                    rcubea(xaxis_endstop_size, align=[-1,0,1]);

                    translate(xaxis_endstop_screw_offset)
                    for(y=[-1,1])
                    translate([-5*mm,y*9.5*mm/2,xaxis_endstop_size[2]])
                    screw(nut=MHexNutM2_5, h=6*mm, orient=[0,0,-1], align=[0,0,-1]);
                }
            }
        }

        // 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=MHexNutM5, 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,0,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);
}


=First version

=First version

/*
 * Backup Lampe
 *
 * Klein, praktisch, ausfallsicher
 */
$fn=150;

/*
// Materialliste
Alurohr Aussendurchmesser = 30, Innendurchmesser = 27, länge = XX?
Cree XP-G2 R5, weiß, 521lm
26650er LiFePo4 e.g. 3.3Ah

*/

aussenRohr(15, 14, 150);

akkuBlock(26.5,68); //26650er

translate ([0,0, 140]){
  ledCreeXpG2 (true);
}

module ledCreeXpG2 (withStar){

  color("LightSteelBlue"){
    difference (){
     sphere (1.53);
      translate ([-5,-5,-3.53]){
       cube ([10,10,3.53]);
      }
    }
    translate ([-3.45/2,-3.45/2,-.83]){
      cube ([3.45,3.45,.83]);
    }
  }

  if (withStar){
    color("DarkGreen"){
      translate ([0,0,-1.5]){
        difference (){
          octagon(20,1.5);
          rotate ([0,0, 22.5]){
            translate ([0,0,-5]){
              LEDSternBohrungen(9,1.6,8,10);
            }
          }
        }
      }
    }
  }
}

module aussenRohr (aussenRadius, innenRadius, hoehe){

 %ring (aussenRadius, innenRadius, hoehe);
}

module akkuBlock (durchmesser, hoehe){
  liFePO4 (durchmesser,hoehe);
  translate ([0,0, hoehe + 2]){
    liFePO4 (durchmesser,hoehe);
  }
}

module liFePO4 (durchmesser, hoehe) {
  color ("Blue"){
    cylinder (r = durchmesser /2, h = hoehe);
  }
  color ("Silver"){
    translate ([0,0,-.1]){
      cylinder (r = durchmesser /2 -2, h = hoehe +.2);
    }
  }
}

// Ein einfacher Ring
module ring(aussenRadius, innenRadius, hoehe) {
    difference() {
        cylinder(r = aussenRadius, h = hoehe);
        translate([ 0, 0, -1 ]) cylinder(r = innenRadius, h = hoehe+2);
    }
}

// size is the XY plane size, height in Z
module octagon(size, height) {
  intersection() {
    cube([size, size, height], true);
    rotate([0,0,45]) cube([size, size, height], true);
  }
}

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

module LEDSternBohrungen (radius, lochRadius, anzahl, tiefe){
  for ( i = [0 : anzahl] ) {
      rotate( i * 360 / anzahl + 1, [0, 0, 1]){
        translate ([radius ,0 , -0.1]){
          cylinder (h = tiefe + 0.1, r = lochRadius);
        }
        translate ([radius ,lochRadius * -1, -0.1]){
          cube ([lochRadius*2,lochRadius*2,tiefe]) ;
        }
      }
    }
}

// Zeichnet eine Reihe von Zylindern auf einem festgelegtem Radius.
// Gut geeignet um auf einem Ring Bohrungen anzubringen.
module bohrungenAufRadius (radius, lochRadius, anzahl, tiefe){
  for ( i = [0 : anzahl] ) {
      rotate( i * 360 / anzahl + 1, [0, 0, 1]){
        translate ([radius ,0 , -0.1]){
          cylinder (h = tiefe + 0.1, r = lochRadius);
        }
      }
    }
}

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


finished lid

finished lid

$fn = 64;

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

// latch buttons
latchButtonDiameter = 13;
latchButtonHeight = 30;
module latch_button(color="green") {
    color(color)
        cylinder(h = latchButtonHeight, d = latchButtonDiameter, center = false);
}

// led momentary buttons
ledButtonDiameter = 25;
ledButtonHeight = 33;
module momentary_button(color="white") {
    color(color)
        cylinder(h = ledButtonHeight, d = ledButtonDiameter, center = false);
}

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

// string
stringWallThickness = 1;
stringRecess = 5;
stringLength = 60;
photoresistorWidth = 5.5 + iFitAdjust_d;
photoresistorLength = photoresistorWidth;
photoresistorWireSep = 3.5;
ledLaserDiameter = 6.5 + iFitAdjust_d;
ledLaserLength = 10;
wireCasingDepth = 3;
stringWidth = ledLaserDiameter;
module photoresistor_holder() {
    difference() {
        cylinder(h = stringRecess + stringWallThickness * 2, d = 2 * stringWallThickness + photoresistorWidth + iFitAdjust_d, center = false);
        translate([0,0,-.1])
            cylinder(h = stringRecess + stringWallThickness * 2 + 1, d = photoresistorWidth + iFitAdjust_d, center = false);
        /*
        for (i = [-1,1])
            translate([i * photoresistorWireSep / 2, 0, -1])
                cylinder(h = 20, d = 1, center = false);
        */
    }
    rotate([0, 0, 180])
        translate([-(ledLaserDiameter + iFitAdjust_d + 2 * stringWallThickness)/2, -(ledLaserDiameter )/2 - 1, -(wireCasingDepth + stringWallThickness * 2)])
        difference() {
            cube([ledLaserDiameter + iFitAdjust_d + 2 * stringWallThickness, ledLaserDiameter + ledLaserDiameter / 2 + 1, wireCasingDepth + stringWallThickness * 2], center=false);
            translate([stringWallThickness, stringWallThickness * 2 + 1, stringWallThickness])
                cube([ledLaserDiameter + iFitAdjust_d , ledLaserDiameter + ledLaserDiameter / 2 - stringWallThickness, wireCasingDepth], center=false);
            translate([ledLaserDiameter / 2 + stringWallThickness, ledLaserDiameter / 2 + stringWallThickness, stringWallThickness])
                cylinder(h=wireCasingDepth + 2 * stringWallThickness, d = ledLaserDiameter + iFitAdjust, center=false);
        }
}
module led_holder() {
    difference() {
        cylinder(h = ledLaserLength + stringWallThickness * 2, d = 2 * stringWallThickness + ledLaserDiameter + iFitAdjust_d, center = false);
        translate([0,0,-.1])
            cylinder(h = ledLaserLength + stringWallThickness * 2 + 1, d = ledLaserDiameter + iFitAdjust_d, center = false);
        /*
        for (i = [-1,1])
            translate([i * photoresistorWireSep / 2, 0, -1])
                cylinder(h = 20, d = 1, center = false);
        */
    }
    translate([-(ledLaserDiameter + iFitAdjust_d + 2 * stringWallThickness)/2, -(ledLaserDiameter )/2 - 1, -(wireCasingDepth + stringWallThickness * 2)])
        difference() {
            cube([ledLaserDiameter + iFitAdjust_d + 2 * stringWallThickness, ledLaserDiameter + ledLaserDiameter / 2 + 1, wireCasingDepth + stringWallThickness * 2], center=false);
            translate([stringWallThickness, stringWallThickness * 2 + 1, stringWallThickness])
                cube([ledLaserDiameter + iFitAdjust_d , ledLaserDiameter + ledLaserDiameter / 2 - stringWallThickness, wireCasingDepth], center=false);
            translate([ledLaserDiameter / 2 + stringWallThickness, ledLaserDiameter / 2 + stringWallThickness, stringWallThickness])
                cylinder(h=wireCasingDepth + 2 * stringWallThickness, d = ledLaserDiameter + iFitAdjust, center=false);
        }
}
module string() {
 rotate([0, 0, 90])
  translate([0, -(wireCasingDepth + stringWallThickness * 2), ledLaserDiameter]) rotate([90, 0, 0])
   union() {
    photoresistor_holder();
    translate([0, 0, stringLength])
        rotate([180, 0, 0])
            led_holder();
    difference() {
        translate([-(ledLaserDiameter + 2 * stringWallThickness + iFitAdjust_d)/2, - ledLaserDiameter, 0])
            cube([ledLaserDiameter + iFitAdjust_d + 2 * stringWallThickness, ledLaserDiameter / 2, stringLength ], center = false);
        cylinder(h=100, d = ledLaserDiameter + iFitAdjust, center=false);
    }
   }
}

// display
OLEDWidth = 27.3;
OLEDDisplayHeight = 19;
OLEDScrewWidth = 20.7;
OLEDScrewHeight = 23.2;
OLEDScrewDiameter = 3;
OLEDDepth = 1;
OLEDDisplayDepth = 1;
module display() {
    difference() {
        union() {
            cube([OLEDWidth, OLEDWidth, OLEDDepth]);
            translate([0, (OLEDWidth - OLEDDisplayHeight) / 2, 1])
                cube([OLEDWidth, OLEDDisplayHeight, OLEDDisplayDepth]);
        }
        for (i = [0: 1])
            for (j = [0: 1])
                translate([(OLEDWidth - OLEDScrewWidth) / 2 + i * OLEDScrewWidth, (OLEDWidth - OLEDScrewHeight) / 2 + j * OLEDScrewHeight, -.1])
                    cylinder(h=boxThickness + 1, d=OLEDScrewDiameter);
    }
}

lidWidth = 100;
lidThickness = 2.5;
rowWidth = ledButtonDiameter + 10;
lidLength = rowWidth * 2 + ledButtonDiameter / 2;
controlOffset = 10;
lidScrewDiameter = 3.5;
lidScrewBoundaryOffset = 10;
module spoke_lid() {
    union() {
        difference () {
            cube([lidWidth, lidLength, lidThickness]);
            for (i = [0:1]) {
                translate([0, ledButtonDiameter + i * rowWidth, -lidThickness * 2]) {
            // led buttons
                    translate([ledButtonDiameter / 2 + controlOffset, 0, 0])
                        momentary_button();
            // encoders
                    translate([ledButtonDiameter / 2 + controlOffset + 2 * controlOffset + latchButtonDiameter / 2 + encoderLength / 4, 0, 0])
                    rotate([0, 0, 270])
                        encoder();
            // latch buttons
                    translate([ledButtonDiameter / 2 + controlOffset + 2 * controlOffset + latchButtonDiameter / 2 + encoderLength + 5, 0, 0])
                        latch_button();

                }
            }
            translate([lidScrewBoundaryOffset/2, lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            translate([lidWidth - lidScrewBoundaryOffset/2, lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            translate([lidScrewBoundaryOffset/2, lidLength - lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            translate([lidWidth - lidScrewBoundaryOffset/2, lidLength - lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
        }
    }
}

module string_lid() {
    union() {
        difference () {
            union() {
                cube([lidWidth, lidLength, lidThickness]);
            }
            translate([lidScrewBoundaryOffset/2, lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            translate([lidWidth - lidScrewBoundaryOffset/2, lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            translate([lidScrewBoundaryOffset/2, lidLength - lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            translate([lidWidth - lidScrewBoundaryOffset/2, lidLength - lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            for (i = [0:7])
                translate([15 + stringWidth * i * 1.5, 5, -.01])
                    rotate([0, 0, 90])
                        hull() string();
        }
        for (i = [0:7])
            translate([15 + stringWidth * i * 1.5, 5, 0])
                rotate([0, 0, 90])
                    string();
   }
}

boxHeight = 45;
screwTabDim = 10;
boxThickness = lidThickness;
boxWidth = lidWidth;
boxLength = lidLength;
boxScrewDiameter = lidScrewDiameter;
module spoke_box() {
    difference() {
        union() {
             difference () {
                union() {
                    cube([lidWidth, lidLength, lidThickness]);
                    for (i = [0,1])
                        for (j = [0,1]) {
                            translate([i * lidWidth - i * screwTabDim, j * lidLength - j * screwTabDim, 0])
                                cube([screwTabDim, screwTabDim, boxHeight]);
                    }
                    cube([boxWidth, boxThickness, boxHeight]);
                    translate([0, boxLength - boxThickness, 0])
                        cube([boxWidth, boxThickness, boxHeight]);
                    cube([boxThickness, boxLength, boxHeight]);
                    translate([boxWidth - screwTabDim, 0, 0])
                        cube([screwTabDim, boxLength, screwTabDim]);
                }
                for (i = [0,1])
                    for (j = [0,1]) {
                        translate([i * boxWidth - i * screwTabDim + screwTabDim / 2, j * boxLength - j * screwTabDim + screwTabDim / 2, boxHeight - 9])
                            cylinder(h=20, d = lidScrewDiameter);
                    }
                for (i = [1, 2])
                    translate([boxWidth - screwTabDim / 2, i * boxLength / 3, boxThickness])
                        cylinder(h=screwTabDim + .1 - boxThickness, d=boxScrewDiameter);
                translate([boxWidth - screwTabDim / 2, screwTabDim + .1, (boxHeight / 3) * 2])
                    rotate([90, 0, 0])
                        cylinder(h=screwTabDim + .1 - boxThickness, d=boxScrewDiameter);
                translate([boxWidth - screwTabDim / 2, boxLength - boxThickness, (boxHeight / 3) * 2])
                    rotate([90, 0, 0])
                        cylinder(h=screwTabDim + .1 - boxThickness, d=boxScrewDiameter);
            }
        }
    }
}

pentagonRadius = boxLength / (2.0 * sin(180. / 5.));
pentagonR = (1/10) * sqrt(25 + 10 * sqrt(5)) * boxLength;
module pentagon_core() {
    difference() {
        union() {
            cylinder(h=boxThickness, r=pentagonRadius, $fn=5);
            translate([-pentagonR, 0, 0])
                    translate([0, -boxLength / 2, 0])
                        cube([screwTabDim, boxLength, screwTabDim]);
            rotate([0, 0,  36])
                translate([pentagonR - screwTabDim, 0, 0])
                    translate([0, -boxLength / 2, 0])
                        cube([screwTabDim, boxLength, screwTabDim]);
            rotate([0, 0,  2 * 36])
                translate([-pentagonR, 0, 0])
                    translate([0, -boxLength / 2, 0])
                        cube([screwTabDim, boxLength, screwTabDim]);
            rotate([0, 0,  3 * 36])
                translate([pentagonR - screwTabDim, 0, 0])
                    translate([0, -boxLength / 2, 0])
                        cube([screwTabDim, boxLength, screwTabDim]);
            rotate([0, 0,  4 * 36])
                translate([-pentagonR, 0, 0])
                    translate([0, -boxLength / 2, 0])
                        cube([screwTabDim, boxLength, screwTabDim]);
            for (i = [0:4])
                rotate([0, 0, i * 72])
                    for (j = [-1, 1])
                        translate([-pentagonR + screwTabDim / 2, j * boxLength / 2 - j * screwTabDim / 2, 0])
                            translate([0, 0, boxHeight/2])
                                cube([screwTabDim, screwTabDim, boxHeight], center=true);
        }
        for (i = [0:4])
            rotate([0, 0, i * 72])
                translate([-pentagonR + screwTabDim / 2, 0, 0]) {
                    translate([0, -boxLength / 3 / 2, boxThickness])
                        cylinder(h=screwTabDim + .1 - boxThickness, d=boxScrewDiameter);
                    translate([0, boxLength / 3 / 2, boxThickness])
                        cylinder(h=screwTabDim + .1 - boxThickness, d=boxScrewDiameter);
                }
        for (i = [0:4])
            rotate([0, 0, i * 72])
                for (j = [-1, 1])
                    translate([-pentagonR + screwTabDim / 2, j * boxLength / 2 - (j == -1 ? -1 * screwTabDim : screwTabDim / 4), 0])
                        translate([0, 0, (boxHeight / 3) * 2])
                            rotate([90, 0, 0])
                                #cylinder(h=screwTabDim + .1 - boxThickness, d=boxScrewDiameter);
         for (i = [0:4])
            rotate([0, 0, i * 72])
                translate([pentagonRadius - (screwTabDim / 3) * 2, 0, boxHeight - 9.9])
                    cylinder(h=10, d=boxScrewDiameter);
   }
}

module pentagon_lid() {
    difference() {
        union() {
            cylinder(h=boxThickness, r=pentagonRadius, $fn=5);
        }
        for (i = [0:4])
            rotate([0, 0, i * 72])
                translate([pentagonRadius - (screwTabDim / 3) * 2, 0, -.1])
                    cylinder(h=10, d=boxScrewDiameter);
        translate([-OLEDWidth / 2, 0, 0]) rotate([0, 0, -18]) {
            translate([0, (OLEDWidth - OLEDDisplayHeight) / 2, -.1])
                cube([OLEDWidth, OLEDDisplayHeight, boxThickness + .2]);
            for (i = [0: 1])
                for (j = [0: 1])
                    translate([(OLEDWidth - OLEDScrewWidth) / 2 + i * OLEDScrewWidth, (OLEDWidth - OLEDScrewHeight) / 2 + j * OLEDScrewHeight, -.1])
                        cylinder(h=boxThickness + 1, d=OLEDScrewDiameter);
        }
        for (i = [3:4])
            rotate([0, 0, i * 72])
                translate([pentagonRadius - ledButtonDiameter * 1.5, 0, -.1])
                    momentary_button(color="red");
        for (i = [3:4])
            rotate([0, 0, 180 + i * 72])
                translate([pentagonRadius - latchButtonDiameter * 2.2, 0, -.1])
                    latch_button((i == 3 ? "red" : "green"));
        for (i = [0,2])
            rotate([0, 0, (i == 0 ? - 1 : 1) * 12 + i * 72])
                translate([pentagonRadius - latchButtonDiameter * 2.2, 0, -10])
                    encoder();
    }
//    display();
}

module screw_tab() {
    difference() {
        cube([screwTabDim, 2 * screwTabDim, boxThickness]);
        for (i = [0,1])
            translate([screwTabDim / 2, screwTabDim / 2 + i * screwTabDim, -.1])
                cylinder(h=10, d=boxScrewDiameter);
    }
}

module case() {
    //translate([0, 0, boxHeight + boxThickness]) spoke_lid();
    //string_lid();
    //spoke_box();
    //screw_tab();
    //pentagon_core();
    //translate([0, 0, boxHeight + boxThickness])
        pentagon_lid();
    //display();
}

case();

$fn = 64;

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

// latch buttons
latchButtonDiameter = 13;
latchButtonHeight = 30;
module latch_button(color="green") {
    color(color)
        cylinder(h = latchButtonHeight, d = latchButtonDiameter, center = false);
}

// led momentary buttons
ledButtonDiameter = 25;
ledButtonHeight = 33;
module momentary_button(color="white") {
    color(color)
        cylinder(h = ledButtonHeight, d = ledButtonDiameter, center = false);
}

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

// string
stringWallThickness = 1;
stringRecess = 5;
stringLength = 60;
photoresistorWidth = 5.5 + iFitAdjust_d;
photoresistorLength = photoresistorWidth;
photoresistorWireSep = 3.5;
ledLaserDiameter = 6.5 + iFitAdjust_d;
ledLaserLength = 10;
wireCasingDepth = 3;
stringWidth = ledLaserDiameter;
module photoresistor_holder() {
    difference() {
        cylinder(h = stringRecess + stringWallThickness * 2, d = 2 * stringWallThickness + photoresistorWidth + iFitAdjust_d, center = false);
        translate([0,0,-.1])
            cylinder(h = stringRecess + stringWallThickness * 2 + 1, d = photoresistorWidth + iFitAdjust_d, center = false);
        /*
        for (i = [-1,1])
            translate([i * photoresistorWireSep / 2, 0, -1])
                cylinder(h = 20, d = 1, center = false);
        */
    }
    rotate([0, 0, 180])
        translate([-(ledLaserDiameter + iFitAdjust_d + 2 * stringWallThickness)/2, -(ledLaserDiameter )/2 - 1, -(wireCasingDepth + stringWallThickness * 2)])
        difference() {
            cube([ledLaserDiameter + iFitAdjust_d + 2 * stringWallThickness, ledLaserDiameter + ledLaserDiameter / 2 + 1, wireCasingDepth + stringWallThickness * 2], center=false);
            translate([stringWallThickness, stringWallThickness * 2 + 1, stringWallThickness])
                cube([ledLaserDiameter + iFitAdjust_d , ledLaserDiameter + ledLaserDiameter / 2 - stringWallThickness, wireCasingDepth], center=false);
            translate([ledLaserDiameter / 2 + stringWallThickness, ledLaserDiameter / 2 + stringWallThickness, stringWallThickness])
                cylinder(h=wireCasingDepth + 2 * stringWallThickness, d = ledLaserDiameter + iFitAdjust, center=false);
        }
}
module led_holder() {
    difference() {
        cylinder(h = ledLaserLength + stringWallThickness * 2, d = 2 * stringWallThickness + ledLaserDiameter + iFitAdjust_d, center = false);
        translate([0,0,-.1])
            cylinder(h = ledLaserLength + stringWallThickness * 2 + 1, d = ledLaserDiameter + iFitAdjust_d, center = false);
        /*
        for (i = [-1,1])
            translate([i * photoresistorWireSep / 2, 0, -1])
                cylinder(h = 20, d = 1, center = false);
        */
    }
    translate([-(ledLaserDiameter + iFitAdjust_d + 2 * stringWallThickness)/2, -(ledLaserDiameter )/2 - 1, -(wireCasingDepth + stringWallThickness * 2)])
        difference() {
            cube([ledLaserDiameter + iFitAdjust_d + 2 * stringWallThickness, ledLaserDiameter + ledLaserDiameter / 2 + 1, wireCasingDepth + stringWallThickness * 2], center=false);
            translate([stringWallThickness, stringWallThickness * 2 + 1, stringWallThickness])
                cube([ledLaserDiameter + iFitAdjust_d , ledLaserDiameter + ledLaserDiameter / 2 - stringWallThickness, wireCasingDepth], center=false);
            translate([ledLaserDiameter / 2 + stringWallThickness, ledLaserDiameter / 2 + stringWallThickness, stringWallThickness])
                cylinder(h=wireCasingDepth + 2 * stringWallThickness, d = ledLaserDiameter + iFitAdjust, center=false);
        }
}
module string() {
 rotate([0, 0, 90])
  translate([0, -(wireCasingDepth + stringWallThickness * 2), ledLaserDiameter]) rotate([90, 0, 0])
   union() {
    photoresistor_holder();
    translate([0, 0, stringLength])
        rotate([180, 0, 0])
            led_holder();
    difference() {
        translate([-(ledLaserDiameter + 2 * stringWallThickness + iFitAdjust_d)/2, - ledLaserDiameter, 0])
            cube([ledLaserDiameter + iFitAdjust_d + 2 * stringWallThickness, ledLaserDiameter / 2, stringLength ], center = false);
        cylinder(h=100, d = ledLaserDiameter + iFitAdjust, center=false);
    }
   }
}

// display
OLEDWidth = 27.3;
OLEDDisplayHeight = 19;
OLEDScrewWidth = 20.7;
OLEDScrewHeight = 23.2;
OLEDScrewDiameter = 3;
OLEDDepth = 1;
OLEDDisplayDepth = 1;
module display() {
    difference() {
        union() {
            cube([OLEDWidth, OLEDWidth, OLEDDepth]);
            translate([0, (OLEDWidth - OLEDDisplayHeight) / 2, 1])
                cube([OLEDWidth, OLEDDisplayHeight, OLEDDisplayDepth]);
        }
        for (i = [0: 1])
            for (j = [0: 1])
                translate([(OLEDWidth - OLEDScrewWidth) / 2 + i * OLEDScrewWidth, (OLEDWidth - OLEDScrewHeight) / 2 + j * OLEDScrewHeight, -.1])
                    cylinder(h=boxThickness + 1, d=OLEDScrewDiameter);
    }
}

lidWidth = 100;
lidThickness = 2.5;
rowWidth = ledButtonDiameter + 10;
lidLength = rowWidth * 2 + ledButtonDiameter / 2;
controlOffset = 10;
lidScrewDiameter = 3.5;
lidScrewBoundaryOffset = 10;
module spoke_lid() {
    union() {
        difference () {
            cube([lidWidth, lidLength, lidThickness]);
            for (i = [0:1]) {
                translate([0, ledButtonDiameter + i * rowWidth, -lidThickness * 2]) {
            // led buttons
                    translate([ledButtonDiameter / 2 + controlOffset, 0, 0])
                        momentary_button();
            // encoders
                    translate([ledButtonDiameter / 2 + controlOffset + 2 * controlOffset + latchButtonDiameter / 2 + encoderLength / 4, 0, 0])
                    rotate([0, 0, 270])
                        encoder();
            // latch buttons
                    translate([ledButtonDiameter / 2 + controlOffset + 2 * controlOffset + latchButtonDiameter / 2 + encoderLength + 5, 0, 0])
                        latch_button();

                }
            }
            translate([lidScrewBoundaryOffset/2, lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            translate([lidWidth - lidScrewBoundaryOffset/2, lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            translate([lidScrewBoundaryOffset/2, lidLength - lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            translate([lidWidth - lidScrewBoundaryOffset/2, lidLength - lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
        }
    }
}

module string_lid() {
    union() {
        difference () {
            union() {
                cube([lidWidth, lidLength, lidThickness]);
            }
            translate([lidScrewBoundaryOffset/2, lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            translate([lidWidth - lidScrewBoundaryOffset/2, lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            translate([lidScrewBoundaryOffset/2, lidLength - lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            translate([lidWidth - lidScrewBoundaryOffset/2, lidLength - lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            for (i = [0:7])
                translate([15 + stringWidth * i * 1.5, 5, -.01])
                    rotate([0, 0, 90])
                        hull() string();
        }
        for (i = [0:7])
            translate([15 + stringWidth * i * 1.5, 5, 0])
                rotate([0, 0, 90])
                    string();
   }
}

boxHeight = 45;
screwTabDim = 10;
boxThickness = lidThickness;
boxWidth = lidWidth;
boxLength = lidLength;
boxScrewDiameter = lidScrewDiameter;
module spoke_box() {
    difference() {
        union() {
             difference () {
                union() {
                    cube([lidWidth, lidLength, lidThickness]);
                    for (i = [0,1])
                        for (j = [0,1]) {
                            translate([i * lidWidth - i * screwTabDim, j * lidLength - j * screwTabDim, 0])
                                cube([screwTabDim, screwTabDim, boxHeight]);
                    }
                    cube([boxWidth, boxThickness, boxHeight]);
                    translate([0, boxLength - boxThickness, 0])
                        cube([boxWidth, boxThickness, boxHeight]);
                    cube([boxThickness, boxLength, boxHeight]);
                    translate([boxWidth - screwTabDim, 0, 0])
                        cube([screwTabDim, boxLength, screwTabDim]);
                }
                for (i = [0,1])
                    for (j = [0,1]) {
                        translate([i * boxWidth - i * screwTabDim + screwTabDim / 2, j * boxLength - j * screwTabDim + screwTabDim / 2, boxHeight - 9])
                            cylinder(h=20, d = lidScrewDiameter);
                    }
                for (i = [1, 2])
                    translate([boxWidth - screwTabDim / 2, i * boxLength / 3, boxThickness])
                        cylinder(h=screwTabDim + .1 - boxThickness, d=boxScrewDiameter);
                translate([boxWidth - screwTabDim / 2, screwTabDim + .1, (boxHeight / 3) * 2])
                    rotate([90, 0, 0])
                        cylinder(h=screwTabDim + .1 - boxThickness, d=boxScrewDiameter);
                translate([boxWidth - screwTabDim / 2, boxLength - boxThickness, (boxHeight / 3) * 2])
                    rotate([90, 0, 0])
                        cylinder(h=screwTabDim + .1 - boxThickness, d=boxScrewDiameter);
            }
        }
    }
}

pentagonRadius = boxLength / (2.0 * sin(180. / 5.));
pentagonR = (1/10) * sqrt(25 + 10 * sqrt(5)) * boxLength;
module pentagon_core() {
    difference() {
        union() {
            cylinder(h=boxThickness, r=pentagonRadius, $fn=5);
            translate([-pentagonR, 0, 0])
                    translate([0, -boxLength / 2, 0])
                        cube([screwTabDim, boxLength, screwTabDim]);
            rotate([0, 0,  36])
                translate([pentagonR - screwTabDim, 0, 0])
                    translate([0, -boxLength / 2, 0])
                        cube([screwTabDim, boxLength, screwTabDim]);
            rotate([0, 0,  2 * 36])
                translate([-pentagonR, 0, 0])
                    translate([0, -boxLength / 2, 0])
                        cube([screwTabDim, boxLength, screwTabDim]);
            rotate([0, 0,  3 * 36])
                translate([pentagonR - screwTabDim, 0, 0])
                    translate([0, -boxLength / 2, 0])
                        cube([screwTabDim, boxLength, screwTabDim]);
            rotate([0, 0,  4 * 36])
                translate([-pentagonR, 0, 0])
                    translate([0, -boxLength / 2, 0])
                        cube([screwTabDim, boxLength, screwTabDim]);
            for (i = [0:4])
                rotate([0, 0, i * 72])
                    for (j = [-1, 1])
                        translate([-pentagonR + screwTabDim / 2, j * boxLength / 2 - j * screwTabDim / 2, 0])
                            translate([0, 0, boxHeight/2])
                                cube([screwTabDim, screwTabDim, boxHeight], center=true);
        }
        for (i = [0:4])
            rotate([0, 0, i * 72])
                translate([-pentagonR + screwTabDim / 2, 0, 0]) {
                    translate([0, -boxLength / 3 / 2, boxThickness])
                        cylinder(h=screwTabDim + .1 - boxThickness, d=boxScrewDiameter);
                    translate([0, boxLength / 3 / 2, boxThickness])
                        cylinder(h=screwTabDim + .1 - boxThickness, d=boxScrewDiameter);
                }
        for (i = [0:4])
            rotate([0, 0, i * 72])
                for (j = [-1, 1])
                    translate([-pentagonR + screwTabDim / 2, j * boxLength / 2 - (j == -1 ? -1 * screwTabDim : screwTabDim / 4), 0])
                        translate([0, 0, (boxHeight / 3) * 2])
                            rotate([90, 0, 0])
                                #cylinder(h=screwTabDim + .1 - boxThickness, d=boxScrewDiameter);
         for (i = [0:4])
            rotate([0, 0, i * 72])
                translate([pentagonRadius - (screwTabDim / 3) * 2, 0, boxHeight - 9.9])
                    cylinder(h=10, d=boxScrewDiameter);
   }
}

module pentagon_lid() {
    difference() {
        union() {
            cylinder(h=boxThickness, r=pentagonRadius, $fn=5);
        }
        for (i = [0:4])
            rotate([0, 0, i * 72])
                translate([pentagonRadius - (screwTabDim / 3) * 2, 0, -.1])
                    cylinder(h=10, d=boxScrewDiameter);
        translate([-OLEDWidth / 2, 0, 0]) rotate([0, 0, -18]) {
            translate([0, (OLEDWidth - OLEDDisplayHeight) / 2, -.1])
                cube([OLEDWidth, OLEDDisplayHeight, boxThickness + .2]);
                for (i = [0: 1])
                    for (j = [0: 1])
                        translate([(OLEDWidth - OLEDScrewWidth) / 2 + i * OLEDScrewWidth, (OLEDWidth - OLEDScrewHeight) / 2 + j * OLEDScrewHeight, -.1])
                            cylinder(h=boxThickness + 1, d=OLEDScrewDiameter);
        }
        for (i = [3:4])
            rotate([0, 0, i * 72])
                translate([pentagonRadius - (screwTabDim / 3) * 2, 0, -.1])
                    #cylinder(h=10, d=boxScrewDiameter);
    }
//    display();
}

module screw_tab() {
    difference() {
        cube([screwTabDim, 2 * screwTabDim, boxThickness]);
        for (i = [0,1])
            translate([screwTabDim / 2, screwTabDim / 2 + i * screwTabDim, -.1])
                cylinder(h=10, d=boxScrewDiameter);
    }
}

module case() {
    //translate([0, 0, boxHeight + boxThickness]) spoke_lid();
    //string_lid();
    //spoke_box();
    //screw_tab();
    //pentagon_core();
    //translate([0, 0, boxHeight + boxThickness])
        pentagon_lid();
    //display();
}

case();