y/carriage/bearingmount: define part

y/carriage/bearingmount: define part

use <thing_libutils/bearing.scad>
include <thing_libutils/attach.scad>
include <config.scad>

yaxis_carriage_bearing_mount_bottom_thick = 3;
yaxis_carriage_bearing_mount_conn_bottom = [[0,0,0], [0,0,1]];
yaxis_carriage_bearing_mount_conn_bearing = [[0,0,yaxis_carriage_bearing_mount_bottom_thick+yaxis_bearing[1]/2], [0,0,1]];

module yaxis_carriage_bearing_mount(show_bearing=false)
{
    // x distance of holes
    screw_dx=28;
    // y distance of holes
    screw_dy=21;

    carriage_plate_thread=ThreadM4;
    carriage_plate_thread_d=lookup(ThreadSize, carriage_plate_thread);

    width = screw_dx+carriage_plate_thread_d*2;
    depth = max(yaxis_bearing[1], screw_dx+carriage_plate_thread_d*2);
    /*height = yaxis_bearing[1]/2+yaxis_carriage_bearing_mount_bottom_thick;*/
    height = 5+yaxis_carriage_bearing_mount_bottom_thick;

    difference()
    {
        union()
        {
            rcubea ([width, depth, height], align=[0,0,1]);
        }

        translate ([+screw_dx/2, +screw_dy/2, -1]) cylindera(d=carriage_plate_thread_d, h=height+2, align=[0,0,1]);
        translate ([+screw_dx/2, -screw_dy/2, -1]) cylindera(d=carriage_plate_thread_d, h=height+2, align=[0,0,1]);
        translate ([-screw_dx/2, +screw_dy/2, -1]) cylindera(d=carriage_plate_thread_d, h=height+2, align=[0,0,1]);
        translate ([-screw_dx/2, -screw_dy/2, -1]) cylindera(d=carriage_plate_thread_d, h=height+2, align=[0,0,1]);

        translate([0,0,yaxis_bearing[1]/2+yaxis_carriage_bearing_mount_bottom_thick])
        bearing_mount_holes(
            bearing_type=yaxis_bearing,
            ziptie_type=ziptie_type,
            ziptie_bearing_distance=ziptie_bearing_distance,
            orient=[0,1,0],
            ziptie_dist=4
            );
    }

    %if(show_bearing)
    {
        translate([0,0,yaxis_bearing[1]/2+yaxis_carriage_bearing_mount_bottom_thick])
        bearing(yaxis_bearing, orient=[0,1,0]);
    }
}

module part_y_carriage_bearing_mount()
{
    c1=[[0,0,0],[0,0,1]];
    attach(c1,yaxis_carriage_bearing_mount_conn_bottom)
    {
        yaxis_carriage_bearing_mount();
    }
}

use <thing_libutils/bearing.scad>
include <thing_libutils/attach.scad>
include <config.scad>

yaxis_carriage_bearing_mount_bottom_thick = 3;
yaxis_carriage_bearing_mount_conn_bottom = [[0,0,0], [0,0,1]];
yaxis_carriage_bearing_mount_conn_bearing = [[0,0,yaxis_carriage_bearing_mount_bottom_thick+yaxis_bearing[1]/2], [0,0,1]];

module yaxis_carriage_bearing_mount(show_bearing=false)
{
    // x distance of holes
    screw_dx=28;
    // y distance of holes
    screw_dy=21;

    carriage_plate_thread=ThreadM4;
    carriage_plate_thread_d=lookup(ThreadSize, carriage_plate_thread);

    width = screw_dx+carriage_plate_thread_d*2;
    depth = max(yaxis_bearing[1], screw_dx+carriage_plate_thread_d*2);
    /*height = yaxis_bearing[1]/2+yaxis_carriage_bearing_mount_bottom_thick;*/
    height = 5+yaxis_carriage_bearing_mount_bottom_thick;

    difference()
    {
        union()
        {
            rcubea ([width, depth, height], align=[0,0,1]);
        }

        translate ([+screw_dx/2, +screw_dy/2, -1]) cylindera(d=carriage_plate_thread_d, h=height+2, align=[0,0,1]);
        translate ([+screw_dx/2, -screw_dy/2, -1]) cylindera(d=carriage_plate_thread_d, h=height+2, align=[0,0,1]);
        translate ([-screw_dx/2, +screw_dy/2, -1]) cylindera(d=carriage_plate_thread_d, h=height+2, align=[0,0,1]);
        translate ([-screw_dx/2, -screw_dy/2, -1]) cylindera(d=carriage_plate_thread_d, h=height+2, align=[0,0,1]);

        translate([0,0,yaxis_bearing[1]/2+yaxis_carriage_bearing_mount_bottom_thick])
        bearing_mount_holes(
            bearing_type=yaxis_bearing,
            ziptie_type=ziptie_type,
            ziptie_bearing_distance=ziptie_bearing_distance,
            orient=[0,1,0],
            ziptie_dist=4
            );
    }

    %if(show_bearing)
    {
        translate([0,0,yaxis_bearing[1]/2+yaxis_carriage_bearing_mount_bottom_thick])
        bearing(yaxis_bearing, orient=[0,1,0]);
    }
}

if(false)
{
    c1=[[0,0,0],[0,0,1]];
    attach(c1,yaxis_carriage_bearing_mount_conn_bottom)
    {
        yaxis_carriage_bearing_mount();
    }
}


bearing: fix align bug when override_h used

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

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

        }
    }
}

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

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

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

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

        // bearing
        fncylindera(h=bearing_type[2], d=bearing_type[1], orient=[0,0,1]);

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

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

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

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

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

        }
    }
}

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

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

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

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

        // bearing
        fncylindera(h=bearing_type[2], d=bearing_type[1], orient=[0,0,1]);

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

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

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


Split top into two parts in DXF.

Split top into two parts in DXF.

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

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

// 0.100" Acrylic:
acrylic_thickness = 2.4;
    // 2.4mm = 0.094" (looks good based on cut test piece for acrylic slotting into itself)

// 1/8" Hardboard:
hardboard_thickness = 3.2;
    // 2.8mm = 0.110"
    //   * looked good based on cut test piece for hardboard slotting into hardboard
    //   * 2015-03-06: Hanging supports didn't fit into cutouts (or did only with lots of force)
    // 3.1mm for some breathing room
    //   * 2016-02-26: Still tighter than is ideal for sliding parts together.
    // 3.2mm for just a smidge more...

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

// Interior box dimensions
// The variables are used below to control placement of **centerpoints** centerpoints of walls,
// so material thickness is added to account for that.
width = 290 + thickness;    // x = 29cm wall-to-wall
depth = 348 + thickness;    // y = 34.8cm to accomodate 34.8cm tank length
i_height = 180 + thickness; // z = 18cm to accomodate 16cm tank height plus cover
                            // (i_height because 'height' is used for height of entire box)

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

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

// tank base plate
base_height = overhang/2;

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

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

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

// x-position of mask piece inside box
mask_loc = tank_width + thickness;  // center-to-center
// dimensions for mask view opening
view_opening_left = 65;
view_opening_right = 78;
view_opening_width = depth-thickness - view_opening_left - view_opening_right;
view_opening_bottom = 24;
view_opening_height = 96;

// camera mounting measurements
camera_hole_diameter = 1.7;       // bolts are m2; 2mm nominal, 1.9mm actual, and a bit less for the beam width
camera_hole_horiz_offset = 21/2;  // 21mm between mounting holes, horizontally (so half that away from the camera center
camera_hole_vert_offset = 12.5;   // 12.5mm between mounting holes, vertically (one set on the camera center, one set up that much from center)

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

// for slight offsets/tweaks
epsilon = 1;

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

// vars to control projection for DXF export (see makefile)
if (DXF_TOP) {
    projection() top_cover(spacing=1);
} else if (DXF_BOTTOM) {
    projection() tank_base();
} else if (DXF_SIDE1) {
    projection() rotate(a=[90,0,0]) side(y=0);
} else if (DXF_SIDE2) {
    projection() rotate(a=[90,0,0]) side(y=depth);
} else if (DXF_END1) {
    projection() rotate(a=[0,90,0]) vert_face(x=0);
} else if (DXF_END2) {
    projection() rotate(a=[0,90,0]) vert_face(x=width);
} else if (DXF_MASK) {
    projection() rotate(a=[0,90,0]) mask(x=mask_loc);
} else if (DXF_TANK_SUPPORT) {
    projection() tank_support_layer1();
    projection() translate([tank_width+thickness,0,0]) tank_support_layer2();
    projection() translate([(tank_width+thickness)*2,0,0]) tank_support_layer3();
} else if (DXF_RPI_SUPPORT) {
    projection() rotate(a=[90,0,0]) rpi_support();
}
else {
    // 3D model
    // components to include (comment out unwanted)
    vert_face(x=0);      // "near face, transparent for monitor
    vert_face(x=width);  // "far" face, with camera, rpi, etc.
    mask(x=mask_loc);
    side(y=0);
    side(y=depth);
    tank_base();
    tank_support();
    rpi_support(x=width, y=rpi_ypos-10, z=height/2);
    mock_rpi(x=width, y=rpi_ypos, z=height/2);
    top_cover();
}

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

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

module vert_face(x=0) {
    difference() {
        if (x == 0) {
            vert_face_base(0, window_thickness);
        }
        else {
            vert_face_base(x);
        }
        camera_opening();
        // round=false so we get the full width of the piece in the cutout, not reduced because we hit the rounded corner
        rpi_support(x=width+thickness*2, y=rpi_ypos-10, z=height/2+support_drop, round=false);
        wire_opening();
        // CAUTION: OpenSCAD won't let me make a projection of vert_face(x=0)
        //   if tank_base is put after side(y=depth) here... bug.  :(
        tank_base();
        top_cover();
        side(y=0);
        side(y=depth);
        translate([x-thickness/2, -overhang, 0]) {
            translate([0, depth+overhang+thickness/2, 0])
                rounded_truncation(width=overhang-thickness/2, up=false);
            translate([0, 0, 0])
                rounded_truncation(width=overhang-thickness/2, up=false);
        }
    }
}

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

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

module camera_opening() {
    translate([width, depth/2, height/2])
    union() {
        cube([thickness*2,10,10], center=true);
        translate([0, camera_hole_horiz_offset, 0])
        rotate(a=[0, 90, 0])
            cylinder(d=camera_hole_diameter, h=100, center=true);
        translate([0, -camera_hole_horiz_offset, 0])
        rotate(a=[0, 90, 0])
            cylinder(d=camera_hole_diameter, h=100, center=true);
        translate([0, camera_hole_horiz_offset, camera_hole_vert_offset])
        rotate(a=[0, 90, 0])
            cylinder(d=camera_hole_diameter, h=100, center=true);
        translate([0, -camera_hole_horiz_offset, camera_hole_vert_offset])
        rotate(a=[0, 90, 0])
            cylinder(d=camera_hole_diameter, h=100, center=true);
    }
}

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

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

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

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

module top_cover(spacing=0) {
    // width1 = main cover ; width2 = tank section cover
    width1 = width - mask_loc - thickness/2;
    width2 = mask_loc - thickness/2;
    color("Grey", alpha=0.5)
    union() {
        // back piece (over empty space)
        // spacing added to make separate pieces for laser cutting
        translate([spacing,-outset,height-thickness])
        difference() {
            translate([mask_loc,0,0])
                cube([width1+thickness+outset,depth+outset*2,thickness]);
            cutouts(4,width1,outset,rot=0,trans=[width1/2+mask_loc,0,0]);
            cutouts(4,width1,outset,rot=180,trans=[width1/2+mask_loc,depth+outset*2,0]);
            cutouts(5,depth-thickness,outset,rot=90,trans=[width+outset,depth/2+outset,0]);
        }
        // front piece (over tank)
        translate([-outset-thickness/2,-overhang,height-thickness])
        difference() {
            cube([width2+thickness+outset,depth+overhang*2,thickness]);
            cutouts(5,depth-thickness,outset,rot=90,trans=[outset+thickness/2,depth/2+overhang,0]);
        }
    }
}

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

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

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

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

module side(y=0) {
    difference() {
        side_base(y);
        translate([0,0,height/2])
        scale([1,1,0.5])
            vert_face_base(x=mask_loc);
        translate([0,0,height/2])
        scale([1,1,0.5])
            vert_face_base(0, window_thickness);
        translate([0,0,height/2])
        scale([1,1,0.5])
            vert_face_base(width);
        top_cover();
    }
}

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

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

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

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

// 0.100" Acrylic:
acrylic_thickness = 2.4;
    // 2.4mm = 0.094" (looks good based on cut test piece for acrylic slotting into itself)

// 1/8" Hardboard:
hardboard_thickness = 3.2;
    // 2.8mm = 0.110"
    //   * looked good based on cut test piece for hardboard slotting into hardboard
    //   * 2015-03-06: Hanging supports didn't fit into cutouts (or did only with lots of force)
    // 3.1mm for some breathing room
    //   * 2016-02-26: Still tighter than is ideal for sliding parts together.
    // 3.2mm for just a smidge more...

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

// Interior box dimensions
// The variables are used below to control placement of **centerpoints** centerpoints of walls,
// so material thickness is added to account for that.
width = 290 + thickness;    // x = 29cm wall-to-wall
depth = 348 + thickness;    // y = 34.8cm to accomodate 34.8cm tank length
i_height = 180 + thickness; // z = 18cm to accomodate 16cm tank height plus cover
                            // (i_height because 'height' is used for height of entire box)

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

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

// tank base plate
base_height = overhang/2;

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

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

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

// x-position of mask piece inside box
mask_loc = tank_width + thickness;  // center-to-center
// dimensions for mask view opening
view_opening_left = 65;
view_opening_right = 78;
view_opening_width = depth-thickness - view_opening_left - view_opening_right;
view_opening_bottom = 24;
view_opening_height = 96;

// camera mounting measurements
camera_hole_diameter = 1.7;       // bolts are m2; 2mm nominal, 1.9mm actual, and a bit less for the beam width
camera_hole_horiz_offset = 21/2;  // 21mm between mounting holes, horizontally (so half that away from the camera center
camera_hole_vert_offset = 12.5;   // 12.5mm between mounting holes, vertically (one set on the camera center, one set up that much from center)

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

// for slight offsets/tweaks
epsilon = 1;

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

// vars to control projection for DXF export (see makefile)
if (DXF_TOP) {
    projection() top_cover();
} else if (DXF_BOTTOM) {
    projection() tank_base();
} else if (DXF_SIDE1) {
    projection() rotate(a=[90,0,0]) side(y=0);
} else if (DXF_SIDE2) {
    projection() rotate(a=[90,0,0]) side(y=depth);
} else if (DXF_END1) {
    projection() rotate(a=[0,90,0]) vert_face(x=0);
} else if (DXF_END2) {
    projection() rotate(a=[0,90,0]) vert_face(x=width);
} else if (DXF_MASK) {
    projection() rotate(a=[0,90,0]) mask(x=mask_loc);
} else if (DXF_TANK_SUPPORT) {
    projection() tank_support_layer1();
    projection() translate([tank_width+thickness,0,0]) tank_support_layer2();
    projection() translate([(tank_width+thickness)*2,0,0]) tank_support_layer3();
} else if (DXF_RPI_SUPPORT) {
    projection() rotate(a=[90,0,0]) rpi_support();
}
else {
    // 3D model
    // components to include (comment out unwanted)
    vert_face(x=0);      // "near face, transparent for monitor
    vert_face(x=width);  // "far" face, with camera, rpi, etc.
    mask(x=mask_loc);
    side(y=0);
    side(y=depth);
    tank_base();
    tank_support();
    rpi_support(x=width, y=rpi_ypos-10, z=height/2);
    mock_rpi(x=width, y=rpi_ypos, z=height/2);
    top_cover();
}

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

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

module vert_face(x=0) {
    difference() {
        if (x == 0) {
            vert_face_base(0, window_thickness);
        }
        else {
            vert_face_base(x);
        }
        camera_opening();
        // round=false so we get the full width of the piece in the cutout, not reduced because we hit the rounded corner
        rpi_support(x=width+thickness*2, y=rpi_ypos-10, z=height/2+support_drop, round=false);
        wire_opening();
        // CAUTION: OpenSCAD won't let me make a projection of vert_face(x=0)
        //   if tank_base is put after side(y=depth) here... bug.  :(
        tank_base();
        top_cover();
        side(y=0);
        side(y=depth);
        translate([x-thickness/2, -overhang, 0]) {
            translate([0, depth+overhang+thickness/2, 0])
                rounded_truncation(width=overhang-thickness/2, up=false);
            translate([0, 0, 0])
                rounded_truncation(width=overhang-thickness/2, up=false);
        }
    }
}

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

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

module camera_opening() {
    translate([width, depth/2, height/2])
    union() {
        cube([thickness*2,10,10], center=true);
        translate([0, camera_hole_horiz_offset, 0])
        rotate(a=[0, 90, 0])
            cylinder(d=camera_hole_diameter, h=100, center=true);
        translate([0, -camera_hole_horiz_offset, 0])
        rotate(a=[0, 90, 0])
            cylinder(d=camera_hole_diameter, h=100, center=true);
        translate([0, camera_hole_horiz_offset, camera_hole_vert_offset])
        rotate(a=[0, 90, 0])
            cylinder(d=camera_hole_diameter, h=100, center=true);
        translate([0, -camera_hole_horiz_offset, camera_hole_vert_offset])
        rotate(a=[0, 90, 0])
            cylinder(d=camera_hole_diameter, h=100, center=true);
    }
}

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

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

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

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

module top_cover() {
    // width1 = main cover ; width2 = tank section cover
    width1 = width - mask_loc - thickness/2;
    width2 = mask_loc - thickness/2;
    color("Grey", alpha=0.5)
    union() {
        // back piece (over empty space)
        translate([0,-outset,height-thickness])
        difference() {
            translate([mask_loc,0,0])
                cube([width1+thickness+outset,depth+outset*2,thickness]);
            cutouts(4,width1,outset,rot=0,trans=[width1/2+mask_loc,0,0]);
            cutouts(4,width1,outset,rot=180,trans=[width1/2+mask_loc,depth+outset*2,0]);
            cutouts(5,depth-thickness,outset,rot=90,trans=[width+outset,depth/2+outset,0]);
        }
        // front piece (over tank)
        translate([-outset-thickness/2,-overhang,height-thickness])
        difference() {
            cube([width2+thickness+outset,depth+overhang*2,thickness]);
            cutouts(5,depth-thickness,outset,rot=90,trans=[outset+thickness/2,depth/2+overhang,0]);
        }
    }
}

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

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

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

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

module side(y=0) {
    difference() {
        side_base(y);
        translate([0,0,height/2])
        scale([1,1,0.5])
            vert_face_base(x=mask_loc);
        translate([0,0,height/2])
        scale([1,1,0.5])
            vert_face_base(0, window_thickness);
        translate([0,0,height/2])
        scale([1,1,0.5])
            vert_face_base(width);
        top_cover();
    }
}

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

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


WIP of the troley mount

WIP of the troley mount

r_mount=(28.8+2*2.1)/2;
h=20;
eps=0.01;

module mount_rod_space()
{
  translate([0, 0, -eps])
    cylinder(r=r_mount, h=h+2*eps, $fn=180);
}

module body_core()
{
  // holes rod
  rotate([0, 0, 180-30])
    hull()
      for(dx=[0, 90])
        translate([dx, 0, 0])
          cylinder(r=30/2, h=h);
  // rod_slot
  cylinder(r=30/2, h=h);
  translate([-35, -40, 0])
    cube([50, 40, h]);
  // stubbing hole, between two elements
  translate([-35, 0, 0])
    cube([20, 10, h]);
}

module buggy_troley_mount()
{
  difference()
  {
    body_core();
    translate([-20/2, -20, 0])
      mount_rod_space();
  }
}

buggy_troley_mount();

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


more relative distances

more relative distances


cable guide hole element

cable guide hole element

module cableGuide()
{
  hull()
  {
    // upper baund
    translate([0, 20, 0])
      cube([75, 1, 6+7]);
    // lower baund
    translate([(75-40)/2, 0, 0])
      cube([40, 1, 6+7]);
  }
}

cableGuide();

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


config: yaxis also sf1 bushing

config: yaxis also sf1 bushing

include <MCAD/stepper.scad>
include <screws.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;
}

// 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 + 15*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_igus_rj4jp_01_12;*/
zaxis_bearing=bearing_sf1_1212;

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

include <MCAD/stepper.scad>
include <screws.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;
}

// 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 + 15*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_igus_rj4jp_01_12;*/
zaxis_bearing=bearing_sf1_1212;

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


config: increase preview res a bit

config: increase preview res a bit

include <thing_libutils/units.scad>
include <thing_libutils/system.scad>
include <thing_libutils/bearing_data.scad>
include <thing_libutils/pulley.scad>
include <thing_libutils/bearing-linear-data.scad>
/*include <thing_libutils/thread-data.scad>*/
include <thing_libutils/nut-data.scad>
include <thing_libutils/timing-belts-data.scad>

include <MCAD/stepper.scad>

use <thing_libutils/misc.scad>

e=0.01*mm;

// high quality etc
is_build = false;

// 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 = is_build ? 0.5 : 1;

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

$show_vit = is_build ? false : true;

// enable preview model (faster openscad)
$preview_mode = is_build ? false : true;

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;
Mat_filament = Mat_PlasticBlack;

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

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

extrusion_mount_thread = ThreadM4;

// for tapped ends
extrusion_end_nut = NutHexM6;

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

gantry_connector_thickness = 5;

rod_fit_tolerance=1.01;

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

xaxis_rod_distance = 65*mm;
xaxis_rod_d = 9.975*mm;
xaxis_rod_l = 500*mm;
// relative to entire machine
xaxis_rod_offset_x = 0*mm;
xaxis_bearings_top=2;
xaxis_bearings_bottom=1;
xaxis_bearing_top = LinearBearingLM10;
xaxis_bearing_bottom = xaxis_bearing_top;

xaxis_pulley = pulley_2GT_20T;
xaxis_pulley_inner_d = xaxis_pulley[2];
xaxis_pulley_outer_d = xaxis_pulley[3];
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 = TimingBelt_GT2_2;
xaxis_belt_width = 6*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 = [-3*mm-xaxis_beltpath_z_offset_pulley, 3*mm+xaxis_beltpath_z_offset_pulley];
xaxis_beltpath_height_body = xaxis_pulley_outer_d/2+3*mm+v_sum(v_abs(xaxis_beltpath_z_offsets))+5*mm;
xaxis_beltpath_height_holders = max(xaxis_pulley_outer_d+2*mm, xaxis_pulley_inner_d+xaxis_beltpath_z_offsets[0]+3*mm);

xaxis_carriage_bearing_offset_y = ziptie_thickness+3*mm;
xaxis_carriage_beltpath_offset_y = xaxis_carriage_bearing_offset_y+get(LinearBearingOuterDiameter, xaxis_bearing_top)/2;

xaxis_motor = dict_replace(Nema17, NemaFrontAxleLength, 22*mm);
xaxis_motor_thread=ThreadM3;
xaxis_motor_nut=NutHexM3;

xaxis_endstop_type = "SWITCH";
/*xaxis_endstop_type = "SN04";*/

yaxis_rod_distance = 170*mm;
yaxis_rod_d = 11.975*mm;
yaxis_rod_l = 500*mm;
yaxis_bearing = LinearBearingKH1228;
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 = TimingBelt_GT2_2;
yaxis_belt_width = 6*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];
printbed_size = [213*mm,213*mm,3*mm];
Mat_PrintCarriage = Mat_Aluminium;
Mat_PrintBed = [.6,.5,.5];

zaxis_rod_d = 11.975*mm;
zaxis_rod_l = 500*mm;
// relative to entire machine
zaxis_rod_offset = [0,-20*mm,0];
zaxis_bearing = LinearBearingLMH12L;
zaxis_bearing_ID=get(LinearBearingInnerDiameter,zaxis_bearing);
zaxis_bearing_OD=get(LinearBearingOuterDiameter,zaxis_bearing);
zaxis_bearing_L=get(LinearBearingLength,zaxis_bearing);

// 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, screw_dist, screw_thread
zaxis_nut = [20*mm, 36*mm, 8*mm, 5*mm, 23*mm, 13.5*mm, ThreadM3];
zaxis_nut_mat = Mat_PlasticBlack;

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 = extrusion_mount_thread;
zmotor_mount_clamp_nut = NutHexM4;
zmotor_mount_clamp_thread_dia = lookup(ThreadSize, zmotor_mount_clamp_thread);
zmotor_mount_clamp_nut_dia = lookup(NutWidthMin, zmotor_mount_clamp_nut);
zmotor_mount_clamp_nut_thick = lookup(NutThickness, 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_OD/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 screw offset from lower extrusion (outer)
zmotor_mount_screw_offset_x = zmotor_w/2 + zmotor_mount_motor_offset;

// z rod offset from lower extrusion (outer)
zmotor_mount_rod_offset_x = zmotor_mount_screw_offset_x + zaxis_rod_screw_distance_x;

include <thing_libutils/units.scad>
include <thing_libutils/system.scad>
include <thing_libutils/bearing_data.scad>
include <thing_libutils/pulley.scad>
include <thing_libutils/bearing-linear-data.scad>
/*include <thing_libutils/thread-data.scad>*/
include <thing_libutils/nut-data.scad>
include <thing_libutils/timing-belts-data.scad>

include <MCAD/stepper.scad>

use <thing_libutils/misc.scad>

e=0.01*mm;

// high quality etc
is_build = false;

// 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 = is_build ? 0.5 : 1.4;

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

$show_vit = is_build ? false : true;

// enable preview model (faster openscad)
$preview_mode = is_build ? false : true;

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;
Mat_filament = Mat_PlasticBlack;

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

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

extrusion_mount_thread = ThreadM4;

// for tapped ends
extrusion_end_nut = NutHexM6;

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

gantry_connector_thickness = 5;

rod_fit_tolerance=1.01;

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

xaxis_rod_distance = 65*mm;
xaxis_rod_d = 9.975*mm;
xaxis_rod_l = 500*mm;
// relative to entire machine
xaxis_rod_offset_x = 0*mm;
xaxis_bearings_top=2;
xaxis_bearings_bottom=1;
xaxis_bearing_top = LinearBearingLM10;
xaxis_bearing_bottom = xaxis_bearing_top;

xaxis_pulley = pulley_2GT_20T;
xaxis_pulley_inner_d = xaxis_pulley[2];
xaxis_pulley_outer_d = xaxis_pulley[3];
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 = TimingBelt_GT2_2;
xaxis_belt_width = 6*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 = [-3*mm-xaxis_beltpath_z_offset_pulley, 3*mm+xaxis_beltpath_z_offset_pulley];
xaxis_beltpath_height_body = xaxis_pulley_outer_d/2+3*mm+v_sum(v_abs(xaxis_beltpath_z_offsets))+5*mm;
xaxis_beltpath_height_holders = max(xaxis_pulley_outer_d+2*mm, xaxis_pulley_inner_d+xaxis_beltpath_z_offsets[0]+3*mm);

xaxis_carriage_bearing_offset_y = ziptie_thickness+3*mm;
xaxis_carriage_beltpath_offset_y = xaxis_carriage_bearing_offset_y+get(LinearBearingOuterDiameter, xaxis_bearing_top)/2;

xaxis_motor = dict_replace(Nema17, NemaFrontAxleLength, 22*mm);
xaxis_motor_thread=ThreadM3;
xaxis_motor_nut=NutHexM3;

xaxis_endstop_type = "SWITCH";
/*xaxis_endstop_type = "SN04";*/

yaxis_rod_distance = 170*mm;
yaxis_rod_d = 11.975*mm;
yaxis_rod_l = 500*mm;
yaxis_bearing = LinearBearingKH1228;
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 = TimingBelt_GT2_2;
yaxis_belt_width = 6*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];
printbed_size = [213*mm,213*mm,3*mm];
Mat_PrintCarriage = Mat_Aluminium;
Mat_PrintBed = [.6,.5,.5];

zaxis_rod_d = 11.975*mm;
zaxis_rod_l = 500*mm;
// relative to entire machine
zaxis_rod_offset = [0,-20*mm,0];
zaxis_bearing = LinearBearingLMH12L;
zaxis_bearing_ID=get(LinearBearingInnerDiameter,zaxis_bearing);
zaxis_bearing_OD=get(LinearBearingOuterDiameter,zaxis_bearing);
zaxis_bearing_L=get(LinearBearingLength,zaxis_bearing);

// 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, screw_dist, screw_thread
zaxis_nut = [20*mm, 36*mm, 8*mm, 5*mm, 23*mm, 13.5*mm, ThreadM3];
zaxis_nut_mat = Mat_PlasticBlack;

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 = extrusion_mount_thread;
zmotor_mount_clamp_nut = NutHexM4;
zmotor_mount_clamp_thread_dia = lookup(ThreadSize, zmotor_mount_clamp_thread);
zmotor_mount_clamp_nut_dia = lookup(NutWidthMin, zmotor_mount_clamp_nut);
zmotor_mount_clamp_nut_thick = lookup(NutThickness, 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_OD/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 screw offset from lower extrusion (outer)
zmotor_mount_screw_offset_x = zmotor_w/2 + zmotor_mount_motor_offset;

// z rod offset from lower extrusion (outer)
zmotor_mount_rod_offset_x = zmotor_mount_screw_offset_x + zaxis_rod_screw_distance_x;


config: fix xaxis_zaxis_distance_y

config: fix xaxis_zaxis_distance_y

include <MCAD/stepper.scad>
include <screws.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;
}

// 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 = 20*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 + 15*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_igus_rj4jp_01_12;
/*zaxis_bearing=bearing_sf1_1212;*/

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

include <MCAD/stepper.scad>
include <screws.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;
}

// 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 = 20*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 + 15*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_igus_rj4jp_01_12;
/*zaxis_bearing=bearing_sf1_1212;*/

// 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 = 1*mm + xaxis_rod_d/2 + zaxis_bearing[1]/2;

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;


Correct hole diameter in button box

Correct hole diameter in button box

// This box is the housing for the scoring buttons that get mounted
// under the pingpong table. The buttons I used are these:
// https://www.sparkfun.com/products/11275
// In hindsight, these buttons are rather large. You could use smaller
// buttons and adjust some of these values accordingly.

// The overall radius of the button. The datasheet reports 100mm, but
// mine both measure 98.
button_radius = 49;

// The radius of the hole the button back needs.
hole_radius = 11.5;

// There's a bar on the front of my table that is 40mm high
table_padding = 40;

// I want 30mm around the button's hole
bottom_padding = 30;
extra_padding = 2;

// The thickness of the box walls
wall_thickness = 3;

// Dimensions for the overall box
mount_height = table_padding + extra_padding + button_radius + hole_radius + bottom_padding;
mount_depth = 50;
mount_width = (hole_radius * 2) + (bottom_padding * 2);

$fn=100;
font = "monaco.dxf";

// Comment or uncomment the body or cover, depending on which you need to render

// Body
union() {
    difference() {
        bottom();
        // You don't have to put my name in your box ;)
        name();
    }

    difference() {
        sides();
        cover_screws();
        mount_screws();
    }
}

// Cover
/*
difference() {
    translate([0, 0, mount_depth-wall_thickness])
    cover();
    cover_screws();
    // Remove this line if you don't want the project's name on the cover
    project();
}
*/

// You shouldn't have to configure anything below this, except maybe text
// attributes at the bottom if you're putting your own text in it.

module screw_mount() {
    difference() {
        cube([10, wall_thickness, 10]);

        rotate([90, 0, 0])
        translate([5, 5, -wall_thickness-1])
        cylinder(r=2, h=wall_thickness+2);
    }
}

module bottom() {
    difference() {
    hull() {
        // lower left
        translate([wall_thickness*2, wall_thickness*2, 0])
        cylinder(r=wall_thickness*2, h=wall_thickness);

        // lower right
        translate([mount_width-(wall_thickness*2), wall_thickness*2, 0])
        cylinder(r=wall_thickness*2, h=wall_thickness);

        // upper right
        translate([mount_width-(wall_thickness*2), mount_height-(wall_thickness*2), 0])
        cube(size=[wall_thickness*2, wall_thickness*2, wall_thickness]);

        // upper left
        translate([0, mount_height-(wall_thickness*2), 0])
        cube(size=[wall_thickness*2, wall_thickness*2, wall_thickness]);
    }

    union() {
        translate([mount_width/2, wall_thickness+7.5, -1])
        cylinder(r=3, h=wall_thickness+2);

        translate([mount_width/2-4.5, wall_thickness+7.5-2.5, wall_thickness-.8])
        cube(size=[9, 5, 1]);
    }
    }
}

module sides() {
    difference() {
        hull() {
            // lower left
            translate([wall_thickness*2, wall_thickness*2, 0])
            cylinder(r=wall_thickness*2, h=mount_depth);

            // lower right
            translate([mount_width-(wall_thickness*2), wall_thickness*2, 0])
            cylinder(r=wall_thickness*2, h=mount_depth);

            // upper right
            translate([mount_width-(wall_thickness*2), mount_height-(wall_thickness*2), 0])
            cube(size=[wall_thickness*2, wall_thickness*2, mount_depth]);

            // upper left
            translate([0, mount_height-(wall_thickness*2), 0])
            cube(size=[wall_thickness*2, wall_thickness*2, mount_depth]);
        }

        hull() {
            // lower left
            translate([wall_thickness*2, wall_thickness*2, 0])
            cylinder(r=wall_thickness, h=mount_depth+1);

            // lower right
            translate([mount_width-(wall_thickness*2), wall_thickness*2, 0])
            cylinder(r=wall_thickness, h=mount_depth+1);

            // upper right
            translate([mount_width-(wall_thickness*2), mount_height-(wall_thickness*2), 0])
            cube(size=[wall_thickness, wall_thickness, mount_depth+1]);

            // upper left
            translate([wall_thickness, mount_height-(wall_thickness*2), 0])
            cube(size=[wall_thickness, wall_thickness, mount_depth+1]);
        }
    }

    intersection() {
        translate([wall_thickness, wall_thickness, 0])
        cube([mount_width-(wall_thickness*2), mount_height-(wall_thickness*2), mount_depth]);

        union() {
            translate([wall_thickness, wall_thickness, mount_depth-6-wall_thickness])
            cylinder(r=9, h=6);
            translate([wall_thickness, wall_thickness, mount_depth-10-wall_thickness])
            cylinder(r1=3, r2=9, h=4);

            translate([mount_width-wall_thickness, wall_thickness, mount_depth-6-wall_thickness])
            cylinder(r=9, h=6);
            translate([mount_width-wall_thickness, wall_thickness, mount_depth-10-wall_thickness])
            cylinder(r1=3, r2=9, h=4);

            translate([mount_width-wall_thickness, mount_height-wall_thickness, mount_depth-6-wall_thickness])
            cylinder(r=9, h=6);
            translate([mount_width-wall_thickness, mount_height-wall_thickness, mount_depth-10-wall_thickness])
            cylinder(r1=3, r2=9, h=4);

            translate([wall_thickness, mount_height-wall_thickness, mount_depth-6-wall_thickness])
            cylinder(r=9, h=6);
            translate([wall_thickness, mount_height-wall_thickness, mount_depth-10-wall_thickness])
            cylinder(r1=3, r2=9, h=4);
        }
    }
}

module cover() {
    hole_center = mount_height - table_padding - button_radius;

    difference() {
        hull() {
            // lower left
            translate([wall_thickness*2, wall_thickness*2, 0])
            cylinder(r=wall_thickness, h=wall_thickness);

            // lower right
            translate([mount_width-(wall_thickness*2), wall_thickness*2, 0])
            cylinder(r=wall_thickness, h=wall_thickness);

            // upper right
            translate([mount_width-(wall_thickness*2), mount_height-(wall_thickness*2), 0])
            cube(size=[wall_thickness, wall_thickness, wall_thickness]);

            // upper left
            translate([wall_thickness, mount_height-(wall_thickness*2), 0])
            cube(size=[wall_thickness, wall_thickness, wall_thickness]);
        }

        translate([mount_width/2, hole_center, -1])
        cylinder(r=hole_radius, h=wall_thickness*2);
    }

    // Fake button
    // translate([mount_width/2, hole_center, 5])
    // cylinder(r=button_radius, h=20);
}

module cover_screws() {
    translate([wall_thickness+3.5, wall_thickness+3.5, mount_depth/2])
    cylinder(r=1.5, h=30);

    translate([mount_width-wall_thickness-3.5, wall_thickness+3.5, mount_depth/2])
    cylinder(r=1.5, h=30);

    translate([mount_width-wall_thickness-3.5, mount_height-wall_thickness-3.5, mount_depth/2])
    cylinder(r=1.5, h=30);

    translate([wall_thickness+3.5, mount_height-wall_thickness-3.5, mount_depth/2])
    cylinder(r=1.5, h=30);
}

module mount_screws() {
    spacing = 15;

    translate([spacing, mount_height, spacing])
    rotate([90, 0, 0])
    cylinder(r=2, h=wall_thickness+2);

    translate([spacing, mount_height, mount_depth-spacing])
    rotate([90, 0, 0])
    cylinder(r=2, h=wall_thickness+2);

    translate([mount_width-spacing, mount_height, mount_depth-spacing])
    rotate([90, 0, 0])
    cylinder(r=2, h=wall_thickness+2);

    translate([mount_width-spacing, mount_height, spacing])
    rotate([90, 0, 0])
    cylinder(r=2, h=wall_thickness+2);
}

// Text
module letter(l, h=100, i=0) {
    union() {
        linear_extrude(height=h) import(font, layer=l[i]);
        translate([dxf_dim(file=font, name="advx", layer=l[i]), dxf_dim(file=font, name="advy", layer=l[i]), 0])
        child();
    }
}

module word(wrd, h=100, i=0) {
    if (i < len(wrd)) {
        letter(wrd, h, i) word(wrd, h, i+1);
    } else {
        child();
    }
}

module name() {
    translate([18.5, mount_height - 20, wall_thickness-1.5])
    scale(0.002)
    word("Scott", 1000);

    translate([46.5, mount_height - 20, wall_thickness-1.5])
    scale(0.002)
    word("Barron", 1000);

    translate([34.5, mount_height - 35, wall_thickness-1.5])
    scale(0.002)
    word("2014", 1000);
}

module project() {
    translate([22, mount_height-20, mount_depth-1.5])
    scale(0.002)
     word("Pingduino", 1000);
}

// This box is the housing for the scoring buttons that get mounted
// under the pingpong table. The buttons I used are these:
// https://www.sparkfun.com/products/11275
// In hindsight, these buttons are rather large. You could use smaller
// buttons and adjust some of these values accordingly.

// The overall radius of the button. The datasheet reports 100mm, but
// mine both measure 98.
button_radius = 49;

// The radius of the hole the button back needs.
hole_radius = 14.5;

// There's a bar on the front of my table that is 40mm high
table_padding = 40;

// I want 30mm around the button's hole
bottom_padding = 30;
extra_padding = 2;

// The thickness of the box walls
wall_thickness = 3;

// Dimensions for the overall box
mount_height = table_padding + extra_padding + button_radius + hole_radius + bottom_padding;
mount_depth = 50;
mount_width = (hole_radius * 2) + (bottom_padding * 2);

$fn=100;
font = "monaco.dxf";

// Comment or uncomment the body or cover, depending on which you need to render

// Body
union() {
    difference() {
        bottom();
        // You don't have to put my name in your box ;)
        name();
    }

    difference() {
        sides();
        cover_screws();
        mount_screws();
    }
}

// Cover
/*
difference() {
    translate([0, 0, mount_depth-wall_thickness])
    cover();
    cover_screws();
    // Remove this line if you don't want the project's name on the cover
    project();
}
*/

// You shouldn't have to configure anything below this, except maybe text
// attributes at the bottom if you're putting your own text in it.

module screw_mount() {
    difference() {
        cube([10, wall_thickness, 10]);

        rotate([90, 0, 0])
        translate([5, 5, -wall_thickness-1])
        cylinder(r=2, h=wall_thickness+2);
    }
}

module bottom() {
    difference() {
    hull() {
        // lower left
        translate([wall_thickness*2, wall_thickness*2, 0])
        cylinder(r=wall_thickness*2, h=wall_thickness);

        // lower right
        translate([mount_width-(wall_thickness*2), wall_thickness*2, 0])
        cylinder(r=wall_thickness*2, h=wall_thickness);

        // upper right
        translate([mount_width-(wall_thickness*2), mount_height-(wall_thickness*2), 0])
        cube(size=[wall_thickness*2, wall_thickness*2, wall_thickness]);

        // upper left
        translate([0, mount_height-(wall_thickness*2), 0])
        cube(size=[wall_thickness*2, wall_thickness*2, wall_thickness]);
    }

    union() {
        translate([mount_width/2, wall_thickness+7.5, -1])
        cylinder(r=3, h=wall_thickness+2);

        translate([mount_width/2-4.5, wall_thickness+7.5-2.5, wall_thickness-.8])
        cube(size=[9, 5, 1]);
    }
    }
}

module sides() {
    difference() {
        hull() {
            // lower left
            translate([wall_thickness*2, wall_thickness*2, 0])
            cylinder(r=wall_thickness*2, h=mount_depth);

            // lower right
            translate([mount_width-(wall_thickness*2), wall_thickness*2, 0])
            cylinder(r=wall_thickness*2, h=mount_depth);

            // upper right
            translate([mount_width-(wall_thickness*2), mount_height-(wall_thickness*2), 0])
            cube(size=[wall_thickness*2, wall_thickness*2, mount_depth]);

            // upper left
            translate([0, mount_height-(wall_thickness*2), 0])
            cube(size=[wall_thickness*2, wall_thickness*2, mount_depth]);
        }

        hull() {
            // lower left
            translate([wall_thickness*2, wall_thickness*2, 0])
            cylinder(r=wall_thickness, h=mount_depth+1);

            // lower right
            translate([mount_width-(wall_thickness*2), wall_thickness*2, 0])
            cylinder(r=wall_thickness, h=mount_depth+1);

            // upper right
            translate([mount_width-(wall_thickness*2), mount_height-(wall_thickness*2), 0])
            cube(size=[wall_thickness, wall_thickness, mount_depth+1]);

            // upper left
            translate([wall_thickness, mount_height-(wall_thickness*2), 0])
            cube(size=[wall_thickness, wall_thickness, mount_depth+1]);
        }
    }

    intersection() {
        translate([wall_thickness, wall_thickness, 0])
        cube([mount_width-(wall_thickness*2), mount_height-(wall_thickness*2), mount_depth]);

        union() {
            translate([wall_thickness, wall_thickness, mount_depth-6-wall_thickness])
            cylinder(r=9, h=6);
            translate([wall_thickness, wall_thickness, mount_depth-10-wall_thickness])
            cylinder(r1=3, r2=9, h=4);

            translate([mount_width-wall_thickness, wall_thickness, mount_depth-6-wall_thickness])
            cylinder(r=9, h=6);
            translate([mount_width-wall_thickness, wall_thickness, mount_depth-10-wall_thickness])
            cylinder(r1=3, r2=9, h=4);

            translate([mount_width-wall_thickness, mount_height-wall_thickness, mount_depth-6-wall_thickness])
            cylinder(r=9, h=6);
            translate([mount_width-wall_thickness, mount_height-wall_thickness, mount_depth-10-wall_thickness])
            cylinder(r1=3, r2=9, h=4);

            translate([wall_thickness, mount_height-wall_thickness, mount_depth-6-wall_thickness])
            cylinder(r=9, h=6);
            translate([wall_thickness, mount_height-wall_thickness, mount_depth-10-wall_thickness])
            cylinder(r1=3, r2=9, h=4);
        }
    }
}

module cover() {
    hole_center = mount_height - table_padding - button_radius;

    difference() {
        hull() {
            // lower left
            translate([wall_thickness*2, wall_thickness*2, 0])
            cylinder(r=wall_thickness, h=wall_thickness);

            // lower right
            translate([mount_width-(wall_thickness*2), wall_thickness*2, 0])
            cylinder(r=wall_thickness, h=wall_thickness);

            // upper right
            translate([mount_width-(wall_thickness*2), mount_height-(wall_thickness*2), 0])
            cube(size=[wall_thickness, wall_thickness, wall_thickness]);

            // upper left
            translate([wall_thickness, mount_height-(wall_thickness*2), 0])
            cube(size=[wall_thickness, wall_thickness, wall_thickness]);
        }

        translate([mount_width/2, hole_center, -1])
        cylinder(r=hole_radius, h=wall_thickness*2);
    }

    // Fake button
    // translate([mount_width/2, hole_center, 5])
    // cylinder(r=button_radius, h=20);
}

module cover_screws() {
    translate([wall_thickness+3.5, wall_thickness+3.5, mount_depth/2])
    cylinder(r=1.5, h=30);

    translate([mount_width-wall_thickness-3.5, wall_thickness+3.5, mount_depth/2])
    cylinder(r=1.5, h=30);

    translate([mount_width-wall_thickness-3.5, mount_height-wall_thickness-3.5, mount_depth/2])
    cylinder(r=1.5, h=30);

    translate([wall_thickness+3.5, mount_height-wall_thickness-3.5, mount_depth/2])
    cylinder(r=1.5, h=30);
}

module mount_screws() {
    spacing = 15;

    translate([spacing, mount_height, spacing])
    rotate([90, 0, 0])
    cylinder(r=2, h=wall_thickness+2);

    translate([spacing, mount_height, mount_depth-spacing])
    rotate([90, 0, 0])
    cylinder(r=2, h=wall_thickness+2);

    translate([mount_width-spacing, mount_height, mount_depth-spacing])
    rotate([90, 0, 0])
    cylinder(r=2, h=wall_thickness+2);

    translate([mount_width-spacing, mount_height, spacing])
    rotate([90, 0, 0])
    cylinder(r=2, h=wall_thickness+2);
}

// Text
module letter(l, h=100, i=0) {
    union() {
        linear_extrude(height=h) import(font, layer=l[i]);
        translate([dxf_dim(file=font, name="advx", layer=l[i]), dxf_dim(file=font, name="advy", layer=l[i]), 0])
        child();
    }
}

module word(wrd, h=100, i=0) {
    if (i < len(wrd)) {
        letter(wrd, h, i) word(wrd, h, i+1);
    } else {
        child();
    }
}

module name() {
    translate([18.5, mount_height - 20, wall_thickness-1.5])
    scale(0.002)
    word("Scott", 1000);

    translate([46.5, mount_height - 20, wall_thickness-1.5])
    scale(0.002)
    word("Barron", 1000);

    translate([34.5, mount_height - 35, wall_thickness-1.5])
    scale(0.002)
    word("2014", 1000);
}

module project() {
    translate([22, mount_height-20, mount_depth-1.5])
    scale(0.002)
     word("Pingduino", 1000);
}