Add a scale bar.

Add a scale bar.

Measurement need additional files (TextGenerator.scad and dimlines.scad)
which you can get via http://is.gd/f541Om

// Mockup of OmmatiDiag
/*
 * The mockup was done after the first crude drawing with
 * [Tinkrecad](https://tinkercad.com/things/3utMiKsZhx9) proved to be too
 * inflexible.
 * The basic unit of the detecotor will be the scintillator size, which we
 * chose to be 17" x 17" translating to 430 x 430 mm in SI units.
*/

// Basic length variables [mm]
unitlength = 430;
padding = 20;
height = 100;
semitransparent = 0.618;
nearlytransparent = 0.25;

// dimlines.scad is used to easily draw dimensional measurements
// http://www.cannymachines.com/entries/9/openscad_dimensioned_drawings
include <dimlines.scad>

DIM_LINE_WIDTH = .025 * unitlength;
DIM_SPACE = .1 * unitlength;

//~ translate([unitlength + 50 , padding/2, 0])
//~ rotate([0,0,90])
  //~ dimensions(unitlength, line_width=DIM_LINE_WIDTH, loc=0);

// Housing
module Housing()
  color ("gray", semitransparent) {
    // box bottom
    cube([unitlength + padding, unitlength + padding,1]);
    // box back walls
    cube([unitlength + padding, 1, height]);
    cube([1, unitlength + padding, height]);
    }
    // box front walls, can (and should be turned off for increased visibility)
    //~ color ("gray", 0.6) {
      //~ translate(v = [0, unitlength + padding, 0]) {
        //~ cube([unitlength + padding, 1, height]);
      //~ }
      //~ translate(v = [unitlength + padding, 0, 0]) {
        //~ cube([1, unitlength + padding, height]); //
      //~ }
    //~ }
Housing();

// Scintillator
module Scintillator()
  translate([padding/2, padding/2, 1]) {
    color ("green", 1) {
      cube([unitlength,unitlength,1]);
      }
    }
Scintillator();

// Ommatidium
module Ommatidium() {
  // FOV of one Ommatidium
  FOVSize = ([unitlength/4, unitlength/3]);
  module FOV()
    color("pink",0.5) cube([FOVSize[0], FOVSize[1], 1], center=true);

  // CMOS (Aptina AR0130)
  CMOSSize = ([1280, 960]);
  pixelsize = 3.75 / 1000; // [um]
  module CMOS()
    color ("blue", semitransparent)
    cube([CMOSSize[0] * pixelsize, CMOSSize[1] * pixelsize, 0.5], center=true);
  translate ([0,0,0]) CMOS();

  // FOV CMOS
  d_cmos_lens = 15;
  d_lens_scintillator = height - d_cmos_lens - 15;
  module CMOSCone()
      color("orange",nearlytransparent)
      cylinder(h = d_cmos_lens,
                r1 = CMOSSize[0] * pixelsize / 2 ,
                r2 = lensdiameter * 2, center=true);
  module CMOSCross() {
    color("red", 1) polyhedron(
      points=[ [0, 0, 0], //origin
        [-CMOSSize[0]*pixelsize/2, 0, d_cmos_lens],     // horizontal_1
        [CMOSSize[0]*pixelsize/2, 0,d_cmos_lens],       // horizontal_2
        [0, -CMOSSize[1] * pixelsize / 2,d_cmos_lens],  // vertical_1
        [0,  CMOSSize[1] * pixelsize / 2,d_cmos_lens]], // vertical_2
      triangles=[[0,1,2], [0,3,4]]);
    }

  mirror([0,0,1]) translate([0,0,-d_cmos_lens])CMOSCross();
  translate([0,0,d_cmos_lens/2])CMOSCone();

  // Lens
  lensdiameter = 4;
  module Lens()
    // the lens is a squashed sphere: http://is.gd/4H9sZf
      scale([2,2,0.5]) sphere(lensdiameter, $fn=50, center=true);
  translate([0, 0, d_cmos_lens]) Lens();

  // FOV Lens
  module LensCone()
    color("orange",nearlytransparent)
    scale([1, 4/3, 1])
    cylinder(h = d_lens_scintillator,
              r1 = lensdiameter * 2,
              r2 = FOVSize[1]/2 * 1.2);
  module LensCross() {
    color("red", 1) polyhedron(
      points=[ [0, 0, 0], //origin
        [-FOVSize[0]/2, 0, d_lens_scintillator],   // horizontal_1
        [FOVSize[0]/2, 0,d_lens_scintillator],     // horizontal_2
        [0, -FOVSize[1]/2 ,d_lens_scintillator],   // vertical_1
        [0,  FOVSize[1]/2 ,d_lens_scintillator]],  // vertical_2
      triangles=[[0,1,2], [0,3,4]]);
    }
  translate([0,0,d_cmos_lens]) LensCross();
  translate([0,0,d_cmos_lens]) LensCone();
  translate([0,0,d_cmos_lens + d_lens_scintillator]) FOV();
}

translate([unitlength/4/2 + padding/2, unitlength/3/2 + padding/2, height-14])
mirror([0,0,1])
for (xpos=[0:3], ypos = [0:2]) // iterate over x and y
  translate([xpos*unitlength/4, ypos*unitlength/3, 0]) Ommatidium();

// Mockup of OmmatiDiag
/*
 * The mockup was done after the first crude drawing with
 * [Tinkrecad](https://tinkercad.com/things/3utMiKsZhx9) proved to be too
 * inflexible.
 * The basic unit of the detecotor will be the scintillator size, which we
 * chose to be 17" x 17" translating to 430 x 430 mm in SI units.
*/

// Basic length variables [mm]
unitlength = 430;
padding = 20;
height = 100;
semitransparent = 0.618;
nearlytransparent = 0.25;

// Housing
module Housing()
  color ("gray", semitransparent) {
    // box bottom
    cube([unitlength + padding, unitlength + padding,1]);
    // box back walls
    cube([unitlength + padding, 1, height]);
    cube([1, unitlength + padding, height]);
    }
    // box front walls, can (and should be turned off for increased visibility)
    //~ color ("gray", 0.6) {
      //~ translate(v = [0, unitlength + padding, 0]) {
        //~ cube([unitlength + padding, 1, height]);
      //~ }
      //~ translate(v = [unitlength + padding, 0, 0]) {
        //~ cube([1, unitlength + padding, height]); //
      //~ }
    //~ }
Housing();

// Scintillator
module Scintillator()
  translate([padding/2, padding/2, 1]) {
    color ("green", 1) {
      cube([unitlength,unitlength,1]);
      }
    }
Scintillator();

// Ommatidium
module Ommatidium() {
  // FOV of one Ommatidium
  FOVSize = ([unitlength/4, unitlength/3]);
  module FOV()
    color("pink",0.5) cube([FOVSize[0], FOVSize[1], 1], center=true);

  // CMOS (Aptina AR0130)
  CMOSSize = ([1280, 960]);
  pixelsize = 3.75 / 1000; // [um]
  module CMOS()
    color ("blue", semitransparent)
    cube([CMOSSize[0] * pixelsize, CMOSSize[1] * pixelsize, 0.5], center=true);
  translate ([0,0,0]) CMOS();

  // FOV CMOS
  d_cmos_lens = 15;
  d_lens_scintillator = height - d_cmos_lens - 15;
  module CMOSCone()
      color("orange",nearlytransparent)
      cylinder(h = d_cmos_lens,
                r1 = CMOSSize[0] * pixelsize / 2 ,
                r2 = lensdiameter * 2, center=true);
  module CMOSCross() {
    color("red", 1) polyhedron(
      points=[ [0, 0, 0], //origin
        [-CMOSSize[0]*pixelsize/2, 0, d_cmos_lens],     // horizontal_1
        [CMOSSize[0]*pixelsize/2, 0,d_cmos_lens],       // horizontal_2
        [0, -CMOSSize[1] * pixelsize / 2,d_cmos_lens],  // vertical_1
        [0,  CMOSSize[1] * pixelsize / 2,d_cmos_lens]], // vertical_2
      triangles=[[0,1,2], [0,3,4]]);
    }

  mirror([0,0,1]) translate([0,0,-d_cmos_lens])CMOSCross();
  translate([0,0,d_cmos_lens/2])CMOSCone();

  // Lens
  lensdiameter = 4;
  module Lens()
    // the lens is a squashed sphere: http://is.gd/4H9sZf
      scale([2,2,0.5]) sphere(lensdiameter, $fn=50, center=true);
  translate([0, 0, d_cmos_lens]) Lens();

  // FOV Lens
  module LensCone()
    color("orange",nearlytransparent)
    scale([1, 4/3, 1])
    cylinder(h = d_lens_scintillator,
              r1 = lensdiameter * 2,
              r2 = FOVSize[1]/2 * 1.2);
  module LensCross() {
    color("red", 1) polyhedron(
      points=[ [0, 0, 0], //origin
        [-FOVSize[0]/2, 0, d_lens_scintillator],   // horizontal_1
        [FOVSize[0]/2, 0,d_lens_scintillator],     // horizontal_2
        [0, -FOVSize[1]/2 ,d_lens_scintillator],   // vertical_1
        [0,  FOVSize[1]/2 ,d_lens_scintillator]],  // vertical_2
      triangles=[[0,1,2], [0,3,4]]);
    }
  translate([0,0,d_cmos_lens]) LensCross();
  translate([0,0,d_cmos_lens]) LensCone();
  translate([0,0,d_cmos_lens + d_lens_scintillator]) FOV();
}

translate([unitlength/4/2 + padding/2, unitlength/3/2 + padding/2, height-14])
mirror([0,0,1])
for (xpos=[0:3], ypos = [0:2]) // iterate over x and y
  translate([xpos*unitlength/4, ypos*unitlength/3, 0]) Ommatidium();


Reduce space around potentiomètre Add a third layer

width = 15;
beam_size = 10;
beam_thickness = 5;
thickness = 3;
bridge_length = 32;
potentiometer_width = 16.1;
total_length = bridge_length+2*width+2*thickness;

module bottom_beam(){
difference(){
union(){
		difference(){
		union(){
			cube(size = [total_length, beam_size, beam_thickness], center=true);

			translate([total_length/2 - thickness/2,0,0]) cube(size = [thickness, beam_size+2*thickness, beam_thickness], center=true);
			translate([-total_length/2 + thickness/2,0,0]) cube(size = [thickness, beam_size+2*thickness, beam_thickness], center=true);

			translate([total_length/2 - thickness/2-thickness-width,0,0]) cube(size = [thickness, beam_size+2*thickness, beam_thickness], center=true);
			translate([-total_length/2 + thickness/2+thickness+width,0,0]) cube(size = [thickness, beam_size+2*thickness, beam_thickness], center=true);
		}

	//Remove space to save weight?
		translate([bridge_length/2+width/2,0,0]) cube(size = [width, beam_size-2*thickness, 2*beam_thickness], center=true);
		translate([-bridge_length/2-width/2,0,0]) cube(size = [width, beam_size-2*thickness, 2*beam_thickness], center=true);
	}
		minkowski(){
			cube(size = [potentiometer_width, potentiometer_width, beam_thickness/2], center=true);
			cylinder(r= thickness, h=beam_thickness/2,center=true);
}
	}
	cube(size = [potentiometer_width, potentiometer_width, beam_thickness*2], center=true);
}

}
module top_beam(){
difference(){
	union(){
			difference(){
		union(){
			cube(size = [total_length, beam_size, beam_thickness], center=true);

			translate([total_length/2 - thickness/2,0,0]) cube(size = [thickness, beam_size+2*thickness, beam_thickness], center=true);
			translate([-total_length/2 + thickness/2,0,0]) cube(size = [thickness, beam_size+2*thickness, beam_thickness], center=true);

			translate([total_length/2 - thickness/2-thickness-width,0,0]) cube(size = [thickness, beam_size+2*thickness, beam_thickness], center=true);
			translate([-total_length/2 + thickness/2+thickness+width,0,0]) cube(size = [thickness, beam_size+2*thickness, beam_thickness], center=true);
		}
	}
		cylinder(r= 5+thickness, h= beam_thickness, center=true);
	}
	cylinder(r= 5, h= 2* beam_thickness, center=true);
}
}

projection() difference(){
	bottom_beam();
	translate([0 , potentiometer_width/2],0) cube(size = [potentiometer_width, potentiometer_width, beam_thickness*2], center=true);
}
projection() translate([0, 23, beam_thickness+1]) bottom_beam();

projection()  translate([0, 44, 2*beam_thickness+2])top_beam();

translate([0, 0, 2* beam_thickness+2]) difference(){
 	cylinder(r=3+thickness,h=beam_thickness, center=true);
	cylinder(r=3, h=2*beam_thickness, center=true);
}

width = 15;
beam_size = 10;
beam_thickness = 5;
thickness = 3;
bridge_length = 32;
potentiometer_width = 17;
total_length = bridge_length+2*width+2*thickness;

module bottom_beam(){
difference(){
union(){
		difference(){
		union(){
			cube(size = [total_length, beam_size, beam_thickness], center=true);

			translate([total_length/2 - thickness/2,0,0]) cube(size = [thickness, beam_size+2*thickness, beam_thickness], center=true);
			translate([-total_length/2 + thickness/2,0,0]) cube(size = [thickness, beam_size+2*thickness, beam_thickness], center=true);

			translate([total_length/2 - thickness/2-thickness-width,0,0]) cube(size = [thickness, beam_size+2*thickness, beam_thickness], center=true);
			translate([-total_length/2 + thickness/2+thickness+width,0,0]) cube(size = [thickness, beam_size+2*thickness, beam_thickness], center=true);
		}

	//Remove space to save weight?
		translate([bridge_length/2+width/2,0,0]) cube(size = [width, beam_size-2*thickness, 2*beam_thickness], center=true);
		translate([-bridge_length/2-width/2,0,0]) cube(size = [width, beam_size-2*thickness, 2*beam_thickness], center=true);
	}
		minkowski(){
			cube(size = [potentiometer_width, potentiometer_width, beam_thickness/2], center=true);
			cylinder(r= thickness, h=beam_thickness/2,center=true);
}
	}
	cube(size = [potentiometer_width, potentiometer_width, beam_thickness*2], center=true);
	translate([0 , potentiometer_width/2],0) cube(size = [potentiometer_width, potentiometer_width, beam_thickness*2], center=true);
}

}
module top_beam(){
difference(){
	union(){
			difference(){
		union(){
			cube(size = [bridge_length+2*thickness, beam_size, beam_thickness], center=true);

			translate([total_length/2 - thickness/2-thickness-width,0,0]) cube(size = [thickness, beam_size+2*thickness, beam_thickness], center=true);
			translate([-total_length/2 + thickness/2+thickness+width,0,0]) cube(size = [thickness, beam_size+2*thickness, beam_thickness], center=true);
		}

	//Remove space to save weight?
		translate([bridge_length/2+width/2,0,0]) cube(size = [width, beam_size-2*thickness, 2*beam_thickness], center=true);
		translate([-bridge_length/2-width/2,0,0]) cube(size = [width, beam_size-2*thickness, 2*beam_thickness], center=true);
	}
		cylinder(r= 5+thickness, h= beam_thickness, center=true);
	}
	cylinder(r= 5, h= 2* beam_thickness, center=true);
}
}

projection()  translate([0, 12, beam_thickness+1]) rotate([0,0, 90]) top_beam();
projection() bottom_beam();

translate([0, 0, 2* beam_thickness+2]) difference(){
 	cylinder(r=3+thickness,h=beam_thickness, center=true);
	cylinder(r=3, h=2*beam_thickness, center=true);
}


main/yaxis: add y axis motor mount

main/yaxis: add y axis motor mount

include <thing_libutils/metric-thread.scad>;
include <thing_libutils/metric-hexnut.scad>;
use <thing_libutils/shapes.scad>;
use <thing_libutils/misc.scad>;
use <thing_libutils/attach.scad>;
use <thing_libutils/triangles.scad>
use <thing_libutils/linear-extrusion.scad>;
include <thing_libutils/timing-belts.scad>;

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

include <config.scad>
include <misc.scad>
include <extruder-direct.scad>
include <x-carriage.scad>
include <y-axis.scad>
include <z-axis.scad>
include <psu.scad>
include <rod-clamps.scad>

use <scad-utils/trajectory.scad>
use <scad-utils/trajectory_path.scad>
use <scad-utils/transformations.scad>
use <scad-utils/shapes.scad>
use <list-comprehension-demos/skin.scad>

axis_pos_x = 0*mm;
axis_range_z=[85,380];
axis_pos_z = axis_range_z[1]*mm/2;

module main()
{
    color(extrusion_color)
    gantry_lower();

    color(extrusion_color)
    translate([0,0,-main_lower_dist_z])
    gantry_lower();

    color(extrusion_color)
    for(i=[-1,1])
    translate([0,i*(main_upper_dist_y/2),0])
    gantry_upper();

    // x axis
    translate([0,0,axis_pos_z])
    {
        if(!preview_mode)
        {
            translate([0, xaxis_zaxis_distance_y, 0])
                belt_path(500, 6, xaxis_pulley_d, orient=[1,0,0]);
        }

        translate([axis_pos_x,0,0])
        {
            // x carriage
            attach(xaxis_carriage_conn, [[0,-xaxis_zaxis_distance_y,0],[0,0,0]])
            {
                x_carriage(show_bearings=true);
            }

            if(!preview_mode)
            {
                attach([[12, -30, -30], [1,0,0]], extruder_conn_xcarriage)
                {
                    extruder();
                }
            }
        }

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

        translate([16,16,-8])
            translate([(main_width/2 + lookup(NemaSideSize,zaxis_motor)/2), 0, 0])
            /*translate([(xaxis_bearing_distance+xaxis_bearing[2])/2, xaxis_zaxis_distance_y, 0])*/
            idler_x_end();

        translate([-21,16,-8])
            translate([-(main_width/2 + lookup(NemaSideSize,zaxis_motor)/2), 0, 0])
            motor_x_end();
    }

    // y axis
    attach([[0,main_depth/2,0], [0,-1,0]], yaxis_motor_mount_conn)
    {
        yaxis_motor_mount();

        attach([[0,0,0],[0,0,0]], yaxis_motor_mount_conn_motor)
        {
            motor(yaxis_motor, NemaMedium, dualAxis=false, orientation=[0,180,0]);

            translate([0,0,5*mm])
            fncylindera(d=yaxis_pulley_d, h=10*mm, orient=[0,0,1]);
        }
    }

    translate([0,0,yaxis_bearing[0]/2])
    {
        for(i=[-1,1])
        for(j=[-1,1])
        {
            attach([[i*(yaxis_rod_distance/2),j*(main_depth/2+extrusion_size/2),0],[0,0,1]],mount_rod_clamp_conn_rod)
            {
                mount_rod_clamp_full(rod_d=zaxis_rod_d, thick=4, width=extrusion_size, thread=zmotor_mount_clamp_thread, orient=[0,1,0]);
            }
        }

        for(i=[-1,1])
        translate([i*(yaxis_rod_distance/2), 0, 0])
        {
            fncylindera(h=yaxis_rod_l,d=yaxis_rod_d, orient=[0,1,0]);

            for(j=[-1,1])
            {
                attach([[0,j*(yaxis_rod_distance/2),0],[0,0,-1]], ycarriage_bearing_mount_conn_bearing)
                {
                    ycarriage_bearing_mount(show_bearing=true, show_zips=true);
                }
            }
        }

        attach([[0,0,0],[0,0,-1]], ycarriage_bearing_mount_conn_bearing)
        {
            // y axis plate
            cubea(ycarriage_size, align=[0,0,-1]);

            translate([0,0,-10*mm])
                cubea(ycarriage_size, align=[0,0,-1]);
        }
    }

    // z axis
    for(i=[-1,1])
    {
        translate([i*(main_width/2),0,main_height])
        {
            mirror([i==-1?1:0,0,0])
            {
                upper_gantry_zrod_connector();

                translate([zmotor_mount_rod_offset_x, 0, extrusion_size/2])
                    mount_rod_clamp_half(
                            rod_d=zaxis_rod_d,
                            screw_dist=zmotor_mount_clamp_dist,
                            thick=5,
                            base_thick=5,
                            width=zmotor_mount_thickness_h,
                            thread=zmotor_mount_clamp_thread);
            }
        }

        translate([i*(main_width/2), 0, 0])
        {
            translate([0,0,zaxis_motor_offset_z])
                mirror([i==-1?1:0,0,0])
                {
                    zaxis_motor_mount();
                    translate([zmotor_mount_rod_offset_x, 0, zmotor_mount_thickness_h/2])
                    {
                        mount_rod_clamp_half(
                                rod_d=zaxis_rod_d,
                                screw_dist=zmotor_mount_clamp_dist,
                                thick=5,
                                base_thick=5,
                                width=zmotor_mount_thickness_h,
                                thread=zmotor_mount_clamp_thread);
                    }

                    translate([(lookup(NemaSideSize,zaxis_motor)/2), 0, 0])
                    attach([[0,0,0],[0,0,0]],zmotor_mount_conn_motor)
                    {
                        // z motor/leadscrews
                        motor(zaxis_motor, NemaMedium, dualAxis=false, orientation=[0,180,0]);
                    }
                }

            // z smooth rods
            translate([i*(lookup(NemaSideSize,zaxis_motor)/2), 0, 0])
            translate([i*(zaxis_rod_screw_distance_x+zmotor_mount_motor_offset),0,0])
            {
                // z rods
                translate([0,0,zaxis_motor_offset_z-50])
                    fncylindera(h=zaxis_rod_l,d=zaxis_rod_d, align=[0,0,1]);

                for(j=[-1,1])
                    translate([0,0,axis_pos_z-j*xaxis_rod_distance/2])
                        bearing(zaxis_bearing);

            }

            translate([i*zmotor_mount_rod_offset_x, 0, axis_pos_z])
                #fncylindera(h=100, d=zaxis_nut[1], align=[0,0,0]);

            translate([i*zaxis_leadscrew_offset_x, 0, axis_pos_z-xaxis_rod_distance/2-10])
            {
                difference()
                {
                    #fncylindera(h=10, d=zaxis_nut[1], align=[0,0,0]);
                    union()
                    {
                        fncylindera(h=10+1, d=zaxis_nut[0], center= false);
                        translate([0, 13.5, -1]) fncylindera(h=5, r=1.6);
                        translate([0, -13.5, -1]) fncylindera(h=5, r=1.6);
                    }
                }
            }
        }
    }

    for(x=[-1,1])
    translate([x*(main_width/2-extrusion_size),main_depth/2,-main_lower_dist_z-extrusion_size])
    {
        translate([-x*psu_w/2, -psu_d/2, psu_h/2])
        {
            psu();

            mirror([x==-1?1:0,0,0])
            translate([0, -psu_screw_dist_y/2, 0])
                psu_extrusion_bracket_side();

            translate([0, psu_screw_dist_y/2, 0])
                psu_extrusion_bracket_back();
        }
    }
}

module upper_gantry_zrod_connector()
{
    upper_width_extra = main_upper_width-main_width;
    difference()
    {
        union()
        {
            hull()
            {
                // attach to z rod
                translate([lookup(NemaSideSize,zaxis_motor)/2, 0, 0])
                translate([(zaxis_rod_screw_distance_x+zmotor_mount_motor_offset),0,0])
                {
                    cubea([gantry_connector_thickness, zmotor_mount_clamp_width, extrusion_size+gantry_connector_thickness], align=[-1,0,1]);
                }

                // connect upper gantry
                translate([upper_width_extra/2, 0, 0])
                    translate([0,0,extrusion_size/2])
                    cubea([gantry_connector_thickness,main_upper_dist_y+extrusion_size,extrusion_size], align=[1,0,0], extrasize=[0,0,gantry_connector_thickness], extrasize_align=[0,0,1]);
            }

            translate([upper_width_extra/2, 0, 0])
                translate([0,0,extrusion_size])
                cubea([extrusion_size*1.5,main_upper_dist_y+extrusion_size,gantry_connector_thickness], align=[-1,0,1]);

        }

        // cut out z rod mounting clamp nut traps and screw holes
        translate([0,0,extrusion_size/2])
        translate([upper_width_extra/2, 0, 0])
        for(i=[-1,1])
        {
            translate([-1, i*zmotor_mount_clamp_dist/2, 0])
            {
                fncylindera(fn=6, d=zmotor_mount_clamp_nut_dia, h=zmotor_mount_clamp_nut_thick, orient=[1,0,0], align=[1,0,0]);

                fncylindera(d=zmotor_mount_clamp_thread_dia, h=100, orient=[1,0,0], align=[1,0,0]);
            }
        }

        // cutout for z rod
        translate([lookup(NemaSideSize,zaxis_motor)/2, 0, 0])
        translate([(zaxis_rod_screw_distance_x+zmotor_mount_motor_offset),0,extrusion_size])
        fncylindera(d=zaxis_rod_d*1.01, h=extrusion_size*3, align=[0,0,0], orient=[0,0,1]);
    }
}

module gantry_upper()
{
    for(i=[-1,1])
    translate([i*(main_width/2), 0, 0])
    {
        if(preview_mode)
        {
            cubea(size=[extrusion_size, extrusion_size, main_height], align=[-i,0,1]);
        }
        else
        {
            linear_extrusion(h=main_height, align=[-i,0,1], orient=[0,0,1]);
        }
    }

    translate([0, 0, main_height])
    {
        if(preview_mode)
        {
            cubea(size=[main_upper_width, extrusion_size, extrusion_size], align=[0,0,1]);
        }
        else
        {
            linear_extrusion(h=main_upper_width, align=[0,0,1], orient=[1,0,0]);
        }
    }
}

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

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

module enclosure()
{
    w=60*cm;
    h=60*cm;
    d=60*cm;
    wallthick=2*cm;
    backthick=0.5*cm;

    translate([0, 0, h/2])
    {
        // left/right walls
        for(i=[-1,1])
            translate([i*w/2,0,0])
                cubea([wallthick,d,h], align=[-i, 0, 0]);

        // back plate
        translate([0,d/2,0])
            cubea([w,backthick,h], align=[0,-1, 0]);

        // top/bottom plate
        for(i=[-1,1])
        translate([0,0,i*h/2])
            cubea([w-wallthick*2,d,wallthick], align=[0,0, -i]);
    }
}

translate([0, 0, main_lower_dist_z+extrusion_size*2])
main();

/*psu();*/

/*%enclosure();*/

include <thing_libutils/metric-thread.scad>;
include <thing_libutils/metric-hexnut.scad>;
use <thing_libutils/shapes.scad>;
use <thing_libutils/misc.scad>;
use <thing_libutils/attach.scad>;
use <thing_libutils/triangles.scad>
use <thing_libutils/linear-extrusion.scad>;
include <thing_libutils/timing-belts.scad>;

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

include <config.scad>
include <misc.scad>
include <extruder-direct.scad>
include <x-carriage.scad>
include <y-axis.scad>
include <z-axis.scad>
include <psu.scad>
include <rod-clamps.scad>

use <scad-utils/trajectory.scad>
use <scad-utils/trajectory_path.scad>
use <scad-utils/transformations.scad>
use <scad-utils/shapes.scad>
use <list-comprehension-demos/skin.scad>

axis_pos_x = 0*mm;
axis_range_z=[85,380];
axis_pos_z = axis_range_z[1]*mm/2;

module main()
{
    color(extrusion_color)
    gantry_lower();

    color(extrusion_color)
    translate([0,0,-main_lower_dist_z])
    gantry_lower();

    color(extrusion_color)
    for(i=[-1,1])
    translate([0,i*(main_upper_dist_y/2),0])
    gantry_upper();

    // x axis
    translate([0,0,axis_pos_z])
    {
        if(!preview_mode)
        {
            translate([0, xaxis_zaxis_distance_y, 0])
                belt_path(500, 6, xaxis_pulley_d, orient=[1,0,0]);
        }

        translate([axis_pos_x,0,0])
        {
            // x carriage
            attach(xaxis_carriage_conn, [[0,-xaxis_zaxis_distance_y,0],[0,0,0]])
            {
                x_carriage(show_bearings=true);
            }

            if(!preview_mode)
            {
                attach([[12, -30, -30], [1,0,0]], extruder_conn_xcarriage)
                {
                    extruder();
                }
            }
        }

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

        translate([16,16,-8])
            translate([(main_width/2 + lookup(NemaSideSize,zaxis_motor)/2), 0, 0])
            /*translate([(xaxis_bearing_distance+xaxis_bearing[2])/2, xaxis_zaxis_distance_y, 0])*/
            idler_x_end();

        translate([-21,16,-8])
            translate([-(main_width/2 + lookup(NemaSideSize,zaxis_motor)/2), 0, 0])
            motor_x_end();
    }

    // y smooth rods
    translate([0,0,yaxis_bearing[0]/2])
    {
        for(i=[-1,1])
        for(j=[-1,1])
        {
            attach([[i*(yaxis_rod_distance/2),j*(main_depth/2+extrusion_size/2),0],[0,0,1]],mount_rod_clamp_conn_rod)
            {
                mount_rod_clamp_full(rod_d=zaxis_rod_d, thick=4, width=extrusion_size, thread=zmotor_mount_clamp_thread, orient=[0,1,0]);
            }
        }

        for(i=[-1,1])
        translate([i*(yaxis_rod_distance/2), 0, 0])
        {
            fncylindera(h=yaxis_rod_l,d=yaxis_rod_d, orient=[0,1,0]);

            for(j=[-1,1])
            {
                attach([[0,j*(yaxis_rod_distance/2),0],[0,0,-1]], ycarriage_bearing_mount_conn_bearing)
                {
                    ycarriage_bearing_mount(show_bearing=true, show_zips=true);
                }
            }
        }

        attach([[0,0,0],[0,0,-1]], ycarriage_bearing_mount_conn_bearing)
        {
            // y axis plate
            cubea(ycarriage_size, align=[0,0,-1]);

            translate([0,0,-10*mm])
                cubea(ycarriage_size, align=[0,0,-1]);
        }
    }

    // z axis
    for(i=[-1,1])
    {
        translate([i*(main_width/2),0,main_height])
        {
            mirror([i==-1?1:0,0,0])
            {
                upper_gantry_zrod_connector();

                translate([zmotor_mount_rod_offset_x, 0, extrusion_size/2])
                    mount_rod_clamp_half(
                            rod_d=zaxis_rod_d,
                            screw_dist=zmotor_mount_clamp_dist,
                            thick=5,
                            base_thick=5,
                            width=zmotor_mount_thickness_h,
                            thread=zmotor_mount_clamp_thread);
            }
        }

        translate([i*(main_width/2), 0, 0])
        {
            translate([0,0,zaxis_motor_offset_z])
                mirror([i==-1?1:0,0,0])
                {
                    zaxis_motor_mount();
                    translate([zmotor_mount_rod_offset_x, 0, zmotor_mount_thickness_h/2])
                    {
                        mount_rod_clamp_half(
                                rod_d=zaxis_rod_d,
                                screw_dist=zmotor_mount_clamp_dist,
                                thick=5,
                                base_thick=5,
                                width=zmotor_mount_thickness_h,
                                thread=zmotor_mount_clamp_thread);
                    }

                    translate([(lookup(NemaSideSize,zaxis_motor)/2), 0, 0])
                    attach([[0,0,0],[0,0,0]],zmotor_mount_conn_motor)
                    {
                        // z motor/leadscrews
                        motor(zaxis_motor, NemaMedium, dualAxis=false, orientation=[0,180,0]);
                    }
                }

            // z smooth rods
            translate([i*(lookup(NemaSideSize,zaxis_motor)/2), 0, 0])
            translate([i*(zaxis_rod_screw_distance_x+zmotor_mount_motor_offset),0,0])
            {
                // z rods
                translate([0,0,zaxis_motor_offset_z-50])
                    fncylindera(h=zaxis_rod_l,d=zaxis_rod_d, align=[0,0,1]);

                for(j=[-1,1])
                    translate([0,0,axis_pos_z-j*xaxis_rod_distance/2])
                        bearing(zaxis_bearing);

            }

            translate([i*zmotor_mount_rod_offset_x, 0, axis_pos_z])
                #fncylindera(h=100, d=zaxis_nut[1], align=[0,0,0]);

            translate([i*zaxis_leadscrew_offset_x, 0, axis_pos_z-xaxis_rod_distance/2-10])
            {
                difference()
                {
                    #fncylindera(h=10, d=zaxis_nut[1], align=[0,0,0]);
                    union()
                    {
                        fncylindera(h=10+1, d=zaxis_nut[0], center= false);
                        translate([0, 13.5, -1]) fncylindera(h=5, r=1.6);
                        translate([0, -13.5, -1]) fncylindera(h=5, r=1.6);
                    }
                }
            }
        }
    }

    for(x=[-1,1])
    translate([x*(main_width/2-extrusion_size),main_depth/2,-main_lower_dist_z-extrusion_size])
    {
        translate([-x*psu_w/2, -psu_d/2, psu_h/2])
        {
            psu();

            mirror([x==-1?1:0,0,0])
            translate([0, -psu_screw_dist_y/2, 0])
                psu_extrusion_bracket_side();

            translate([0, psu_screw_dist_y/2, 0])
                psu_extrusion_bracket_back();
        }
    }
}

module upper_gantry_zrod_connector()
{
    upper_width_extra = main_upper_width-main_width;
    difference()
    {
        union()
        {
            hull()
            {
                // attach to z rod
                translate([lookup(NemaSideSize,zaxis_motor)/2, 0, 0])
                translate([(zaxis_rod_screw_distance_x+zmotor_mount_motor_offset),0,0])
                {
                    cubea([gantry_connector_thickness, zmotor_mount_clamp_width, extrusion_size+gantry_connector_thickness], align=[-1,0,1]);
                }

                // connect upper gantry
                translate([upper_width_extra/2, 0, 0])
                    translate([0,0,extrusion_size/2])
                    cubea([gantry_connector_thickness,main_upper_dist_y+extrusion_size,extrusion_size], align=[1,0,0], extrasize=[0,0,gantry_connector_thickness], extrasize_align=[0,0,1]);
            }

            translate([upper_width_extra/2, 0, 0])
                translate([0,0,extrusion_size])
                cubea([extrusion_size*1.5,main_upper_dist_y+extrusion_size,gantry_connector_thickness], align=[-1,0,1]);

        }

        // cut out z rod mounting clamp nut traps and screw holes
        translate([0,0,extrusion_size/2])
        translate([upper_width_extra/2, 0, 0])
        for(i=[-1,1])
        {
            translate([-1, i*zmotor_mount_clamp_dist/2, 0])
            {
                fncylindera(fn=6, d=zmotor_mount_clamp_nut_dia, h=zmotor_mount_clamp_nut_thick, orient=[1,0,0], align=[1,0,0]);

                fncylindera(d=zmotor_mount_clamp_thread_dia, h=100, orient=[1,0,0], align=[1,0,0]);
            }
        }

        // cutout for z rod
        translate([lookup(NemaSideSize,zaxis_motor)/2, 0, 0])
        translate([(zaxis_rod_screw_distance_x+zmotor_mount_motor_offset),0,extrusion_size])
        fncylindera(d=zaxis_rod_d*1.01, h=extrusion_size*3, align=[0,0,0], orient=[0,0,1]);
    }
}

module gantry_upper()
{
    for(i=[-1,1])
    translate([i*(main_width/2), 0, 0])
    {
        if(preview_mode)
        {
            cubea(size=[extrusion_size, extrusion_size, main_height], align=[-i,0,1]);
        }
        else
        {
            linear_extrusion(h=main_height, align=[-i,0,1], orient=[0,0,1]);
        }
    }

    translate([0, 0, main_height])
    {
        if(preview_mode)
        {
            cubea(size=[main_upper_width, extrusion_size, extrusion_size], align=[0,0,1]);
        }
        else
        {
            linear_extrusion(h=main_upper_width, align=[0,0,1], orient=[1,0,0]);
        }
    }
}

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

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

module enclosure()
{
    w=60*cm;
    h=60*cm;
    d=60*cm;
    wallthick=2*cm;
    backthick=0.5*cm;

    translate([0, 0, h/2])
    {
        // left/right walls
        for(i=[-1,1])
            translate([i*w/2,0,0])
                cubea([wallthick,d,h], align=[-i, 0, 0]);

        // back plate
        translate([0,d/2,0])
            cubea([w,backthick,h], align=[0,-1, 0]);

        // top/bottom plate
        for(i=[-1,1])
        translate([0,0,i*h/2])
            cubea([w-wallthick*2,d,wallthick], align=[0,0, -i]);
    }
}

translate([0, 0, main_lower_dist_z+extrusion_size*2])
main();

/*psu();*/

/*%enclosure();*/


Do not put the battery and arduino on this part anymore, put on one of the two arm (to be done)

RF_module_length  = 30;
9V_battery_length = 50;
length_for_arduino_nano = 30;
total_length = RF_module_length +9V_battery_length+0*length_for_arduino_nano;
width = 15; // Based on arduino nano length between "legs"
thickness = 5;

projection() embedded_support();

module embedded_support(){
	difference(){
		union(){
			translate([total_length/2+10,0,0]) cylinder(r=15, h=thickness, center=true);
			// Main support
			cube(size = [total_length +20, width, thickness], center = true);
			//translate([30,0,0]) cube(size = [length_for_arduino_nano, length_for_arduino_nano, thickness], center = true);

			// Right plate to attach strap
			translate([total_length/2+20/2-30/2,0,0]) cube(size = [30, width+20, thickness], center = true);

			// Left plate to attach strap
			translate([-total_length/2-20/2+30/2,0,0]) cube(size = [30, width+20, thickness], center = true);
		}
				// Right holes to attach strap
			translate([total_length/2+20/2-30/2,7.5,0]) cube(size = [20, 5, 2*thickness], center = true);
			translate([total_length/2+20/2-30/2,-7.5,0]) cube(size = [20, 5, 2*thickness], center = true);

			// Left holes to attach strap
			translate([-total_length/2-20/2+30/2,7.5,0]) cube(size = [20, 5, 2*thickness], center = true);
			translate([-total_length/2-20/2+30/2,-7.5,0]) cube(size = [20, 5, 2*thickness], center = true);
			translate([total_length/2+10,0,0]) cylinder(r=2.5, h=thickness, center=true);

	}
}

RF_module_length  = 30;
9V_battery_length = 50;
length_for_arduino_nano = 30;
total_length = RF_module_length +9V_battery_length+length_for_arduino_nano;
width = 15; // Based on arduino nano length between "legs"
thickness = 5;

projection() embedded_support();

module embedded_support(){
	difference(){
		union(){
			translate([total_length/2+10,0,0]) cylinder(r=15, h=thickness, center=true);
			// Main support
			cube(size = [total_length +20, width, thickness], center = true);
			translate([30,0,0]) cube(size = [length_for_arduino_nano, length_for_arduino_nano, thickness], center = true);

			// Right plate to attach strap
			translate([total_length/2+20/2-30/2,0,0]) cube(size = [30, width+20, thickness], center = true);

			// Left plate to attach strap
			translate([-total_length/2-20/2+30/2,0,0]) cube(size = [30, width+20, thickness], center = true);
		}
				// Right holes to attach strap
			translate([total_length/2+20/2-30/2,7.5,0]) cube(size = [20, 5, 2*thickness], center = true);
			translate([total_length/2+20/2-30/2,-7.5,0]) cube(size = [20, 5, 2*thickness], center = true);

			// Left holes to attach strap
			translate([-total_length/2-20/2+30/2,7.5,0]) cube(size = [20, 5, 2*thickness], center = true);
			translate([-total_length/2-20/2+30/2,-7.5,0]) cube(size = [20, 5, 2*thickness], center = true);
			translate([total_length/2+10,0,0]) cylinder(r=2.5, h=thickness, center=true);

	}
}


[scad] reduce wall thickness to 1mm

[scad] reduce wall thickness to 1mm

/*
	kube.scad - OpenSCAD code generating the Fluksokube enclosure

	Copyright (C) 2014 Bart Van Der Meerssche <bart@flukso.net>

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/*$fn = 100; /* number of facets per circle */

/*
	_h = height
	_w = width
	_r = radius
	_t = tolerance
	_s = scaling factor (printer specific)
*/

dim_s = 1;
dim_s = 1.015; /* makerbot */
kube_s = [dim_s, dim_s, dim_s];

magnet_h = 5;
magnet_t = 0.2;
magnet_r = 8 - magnet_t; /* inner diameter now! */

flk_h = 23.5;
flk_t = 0.2;
flk_w = 30.5 + 2*flk_t;

wall_w = 1;
outer_w = flk_w + 2*wall_w;

support_h = outer_w - wall_w - flk_h;
support_r = magnet_r;

ring_h = support_h - magnet_h;
ring_t = 0.2;
ring_inner_r = support_r + ring_t;
ring_outer_r = ring_inner_r + 2;

echo("*** kube dimensions ***");
echo("scaling vector", "=", kube_s);
echo("magnet diameter", "=", magnet_r*2);
echo("flk width", "=", flk_w);
echo("kube width", "=", outer_w);
echo("support diameter", "=", support_r*2);
echo("support height", "=", support_h);
echo("ring height", "=", ring_h);
echo("ring inner diameter", "=", ring_inner_r*2);
echo("ring outer diameter", "=", ring_outer_r*2);
echo("***********************");

module kube()
{
	difference() {
		cube(outer_w);
		translate([wall_w, wall_w, wall_w]) {
			cube([flk_w, flk_w, outer_w - wall_w]);
		}
	}

	translate([outer_w/2, outer_w/2, wall_w]) {
		cylinder(r=support_r, h=support_h);
	}
}

module ring()
{
	difference() {
		cylinder(r=ring_outer_r, h=ring_h);
		cylinder(r=ring_inner_r, h=ring_h);
	}
}

scale(kube_s) {
	kube();
	translate([1.5*outer_w, outer_w/2, 0]) ring();
}

/*
	kube.scad - OpenSCAD code generating the Fluksokube enclosure

	Copyright (C) 2014 Bart Van Der Meerssche <bart@flukso.net>

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/*$fn = 100; /* number of facets per circle */

/*
	_h = height
	_w = width
	_r = radius
	_t = tolerance
	_s = scaling factor (printer specific)
*/

dim_s = 1;
dim_s = 1.015; /* makerbot */
kube_s = [dim_s, dim_s, dim_s];

magnet_h = 5;
magnet_t = 0.2;
magnet_r = 8 - magnet_t; /* inner diameter now! */

flk_h = 23.5;
flk_t = 0.2;
flk_w = 30.5 + 2*flk_t;

wall_w = 2;
outer_w = flk_w + 2*wall_w;

support_h = outer_w - wall_w - flk_h;
support_r = magnet_r;

ring_h = support_h - magnet_h;
ring_t = 0.2;
ring_inner_r = support_r + ring_t;
ring_outer_r = ring_inner_r + 2;

echo("*** kube dimensions ***");
echo("scaling vector", "=", kube_s);
echo("magnet diameter", "=", magnet_r*2);
echo("flk width", "=", flk_w);
echo("kube width", "=", outer_w);
echo("support diameter", "=", support_r*2);
echo("support height", "=", support_h);
echo("ring height", "=", ring_h);
echo("ring inner diameter", "=", ring_inner_r*2);
echo("ring outer diameter", "=", ring_outer_r*2);
echo("***********************");

module kube()
{
	difference() {
		cube(outer_w);
		translate([wall_w, wall_w, wall_w]) {
			cube([flk_w, flk_w, outer_w - wall_w]);
		}
	}

	translate([outer_w/2, outer_w/2, wall_w]) {
		cylinder(r=support_r, h=support_h);
	}
}

module ring()
{
	difference() {
		cylinder(r=ring_outer_r, h=ring_h);
		cylinder(r=ring_inner_r, h=ring_h);
	}
}

scale(kube_s) {
	kube();
	translate([1.5*outer_w, outer_w/2, 0]) ring();
}


nor cchnage.# Your branch is ahead of 'origin/master' by 2 commits.

// OpenSCAD for a "mezzanine" extension for a Turtlebot3 burger
//           It includes supports for a breadboard and
//           rivet holes for a battery. The breadboard is
//           centered on the origin. y is positive toward the RPi.
thickness = 4;

wide_x  = 110;    // 1/2 width of the "wings"
start_cutout_x  = 40;   // 1/2 width of cutout around the helper board
end_cutout_x    = 65;   // 1/2 width of cutout around the helper board
narrow_x= 45;    // 1/2 width of the battery holder

min_y = 18;      // beginning of "wing
cutout_y = 0;    // close edge of the cutout
wide_y  = -26;    // The near edge the wide rectangular portion
fillet_side= 16;  // End of flare to narrow
full_y  = -86;    // Greatest extent of the plate

breadboard_width = 164;     //
breadboard_height = 26;     // Chopped
breadboard_thickness = 10;
breadboard_z = 10;          // Base to bottom of breadboard

pillar_x     = 24;    // Center-line to center of pillar
pillar_y     = -20;   // Baseline to center of pillar
rim          = 3;     // Width of rim

battery_rivet_x     = 28;  // On centerline
battery_rivet_y     = 16;  // On centerline, 16mm from rim.
rivet2_x     = 60;
rivet_y      = 8;
rivet_radius = 2.5;   // Hole radius for rivet attachment
round_radius = 2;     // Radius of the corner arcs

// Make 4 holders for the breadboard corners plus 1 at midpoint on battery edge
module tub(z,rwidth) {
    //linear_extrude(height=z,center=false,convexity=10) {
     //   difference() {
      //      square([breadboard_x+2*rwidth,breadboard_y+2*rwidth],true);
      //      square([breadboard_x,breadboard_y],true);
       // }
    //}
}
// Subtract this from the base platform
// These are the posts
module post_holes(z) {
    for(i=[[pillar_x,pillar_y],[-pillar_x,pillar_y]]) {
        translate(i)
        rotate(22.5,0,0)
        cylinder(r=4,h=z,$fn=6);
    }
}

// These are the various holes for battery rivets.
// z - thickness
module rivet_holes(z) {
    for(i=[[rivet1_x,-rivet_y],[rivet2_x,-rivet_y],
           [-rivet1_x,-rivet_y],[-rivet2_x,-rivet_y]]) {
        translate(i)
        cylinder(r=rivet_radius,h=z);
    }
}
// 0,0 is upper left corner
module fillet(radius,angle) {
    rotate(angle,[0,0,1])
    difference() {
        square(radius,false);
        translate([radius,radius,0])
        circle(r=radius);
    }

}
// This is the basic plate. The baseline is y=0 along the edge of the helper
// board next to the RPi GPIO header. This object cannot be translated once created.
// y is positive towards the RPi. Couldn't make a single hull work.
module base(z) {
    $fn=100;
    linear_extrude(height=z,center=false,convexity=10) {
        // place circles in the corners, account for the rounding radius
        union() {
         // Breadboard rectangular area.
        hull() {
            translate([-wide_x+round_radius/2, wide_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([wide_x-round_radius/2, wide_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([wide_x-round_radius/2, cutout_y-round_radius/2, 0])
            circle(r=round_radius);

            translate([-wide_x+round_radius/2, cutout_y-round_radius/2, 0])
            circle(r=round_radius);
            }
        };
        // Battery area
        hull() {
            translate([narrow_x-round_radius/2, wide_y-round_radius/2, 0])
            circle(r=round_radius);

            translate([narrow_x-round_radius/2, full_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([-narrow_x+round_radius/2, full_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([-narrow_x+round_radius/2, wide_y-round_radius/2, 0])
            circle(r=round_radius);
        }
        // Wingtip left
        hull() {
            translate([-wide_x+round_radius/2, cutout_y-round_radius/2, 0])
            circle(r=round_radius);

            translate([-wide_x+round_radius/2, min_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([-end_cutout_x+round_radius/2, min_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([-start_cutout_x+round_radius/2, cutout_y+round_radius/2, 0])
            circle(r=round_radius);
        }
        // Wingtip right
        hull() {
            translate([wide_x-round_radius/2, cutout_y-round_radius/2, 0])
            circle(r=round_radius);

            translate([wide_x-round_radius/2, min_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([end_cutout_x-round_radius/2, min_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([start_cutout_x-round_radius/2, cutout_y+round_radius/2, 0])
            circle(r=round_radius);
        }
        translate([narrow_x,wide_y,0])
        fillet(fillet_side,270);
        translate([-narrow_x,wide_y,0])
        fillet(fillet_side,180);
    }
}

// This is the basic plate less a rim width all around. This is meant to
// be subtracted from the standard plate. There should be no rim where hulls join.
module base_cutout(z,rwidth) {
    $fn=100;
    linear_extrude(height=z,center=false,convexity=10) {
        // place circles in the corners, account for the rounding radius and rim
        // There is no rim on joint.
        union() {
            // Breadboard rectangular area.
            hull() {
            translate([-wide_x+round_radius/2+rwidth, wide_y+round_radius/2+rwidth, 0])
            circle(r=round_radius);

            translate([wide_x-round_radius/2-rwidth, wide_y+round_radius/2+rwidth, 0])
            circle(r=round_radius);

            translate([wide_x-round_radius/2-rwidth, cutout_y-round_radius/2, 0])
            circle(r=round_radius);

            translate([-wide_x+round_radius/2+rwidth, cutout_y-round_radius/2, 0])
            circle(r=round_radius);
            }
        };
        // Battery area
        hull() {
            translate([narrow_x-round_radius/2-rwidth, wide_y+round_radius, 0])
            circle(r=round_radius);

            translate([narrow_x-round_radius/2-rwidth, full_y+round_radius/2+rwidth, 0])
            circle(r=round_radius);

            translate([-narrow_x+round_radius/2+rwidth, full_y+round_radius/2+rwidth, 0])
            circle(r=round_radius);

            translate([-narrow_x+round_radius/2+rwidth, wide_y+round_radius, 0])
            circle(r=round_radius);
        }
        // Wingtip left
        hull() {
            translate([-wide_x+round_radius/2+rwidth, cutout_y-round_radius/2, 0])
            circle(r=round_radius);

            translate([-wide_x+round_radius/2+rwidth, min_y+round_radius/2-rwidth, 0])
            circle(r=round_radius);

            translate([-end_cutout_x+round_radius/2-rwidth, min_y+round_radius/2-rwidth, 0])
            circle(r=round_radius);

            translate([-start_cutout_x+round_radius/2, cutout_y-round_radius/2-rwidth, 0])
            circle(r=round_radius);
        }
        // Wingtip right
        hull() {
            translate([wide_x-round_radius/2-rwidth, cutout_y-round_radius/2, 0])
            circle(r=round_radius);

            translate([wide_x-round_radius/2-rwidth, min_y+round_radius/2-rwidth, 0])
            circle(r=round_radius);

            translate([end_cutout_x-round_radius/2+rwidth, min_y+round_radius/2-rwidth, 0])
            circle(r=round_radius);

            translate([start_cutout_x-round_radius/2, cutout_y-round_radius/2-rwidth, 0])
            circle(r=round_radius);
        }
        translate([narrow_x-rwidth,-wide_y+rwidth,0])
        fillet(fillet_side,270);
        translate([-narrow_x+rwidth,-wide_y+rwidth,0])
        fillet(fillet_side,180);
    }
}

// --------------------- Final Assembly ----------------------
// Baseplate
translate([0,0,-thickness/2])
difference() {
    base(thickness);
    rivet_holes(thickness);
    post_holes(thickness);
}
translate([0,0,thickness/2])
difference() {
     color("red")
     base(thickness);
     base_cutout(thickness,rim);
}
 //translate([0,-breadboard_y/2,thickness/2])
 //tub(thickness,rim);

// OpenSCAD for a "mezzanine" extension for a Turtlebot3 burger
//           It includes supports for a breadboard and
//           rivet holes for a battery. The breadboard is
//           centered on the origin. y is positive toward the RPi.
thickness = 4;

wide_x  = 110;    // 1/2 width of the "wings"
start_cutout_x  = 40;   // 1/2 width of cutout around the helper board
end_cutout_x    = 65;   // 1/2 width of cutout around the helper board
narrow_x= 45;    // 1/2 width of the battery holder

min_y = 18;      // beginning of "wing
cutout_y = 0;    // close edge of the cutout
wide_y  = -26;    // The near edge the wide rectangular portion
fillet_side= 16;  // End of flare to narrow
full_y  = -86;    // Greatest extent of the plate

breadboard_width = 164;     //
breadboard_height = 26;     // Chopped
breadboard_thickness = 10;
breadboard_z = 10;          // Base to bottom of breadboard

pillar_x     = 24;    // Center-line to center of pillar
pillar_y     = 20;    // Baseline to center of pillar
rim          = 3;     // Width of rim

rivet1_x     = 54;
rivet2_x     = 60;
rivet_y      = 8;
rivet_radius = 2.5;   // Hole radius for rivet attachment
round_radius = 2;     // Radius of the corner arcs

// Make 4 holders for the breadboard corners plus 1 at midpoint on battery edge
module tub(z,rwidth) {
    //linear_extrude(height=z,center=false,convexity=10) {
     //   difference() {
      //      square([breadboard_x+2*rwidth,breadboard_y+2*rwidth],true);
      //      square([breadboard_x,breadboard_y],true);
       // }
    //}
}
// Subtract this from the base platform
// These are the posts
module post_holes(z) {
    for(i=[[pillar_x,-pillar_y],[-pillar_x,-pillar_y]]) {
        translate(i)
        rotate(22.5,0,0)
        cylinder(r=4,h=z,$fn=6);
    }
}

// These are the various holes for rivets
// z - thickness
module rivet_holes(z) {
    for(i=[[rivet1_x,-rivet_y],[rivet2_x,-rivet_y],
           [-rivet1_x,-rivet_y],[-rivet2_x,-rivet_y]]) {
        translate(i)
        cylinder(r=rivet_radius,h=z);
    }
}
// 0,0 is upper left corner
module fillet(radius,angle) {
    rotate(angle,[0,0,1])
    difference() {
        square(radius,false);
        translate([radius,radius,0])
        circle(r=radius);
    }

}
// This is the basic plate. The baseline is y=0 along the edge of the helper
// board next to the RPi GPIO header. This object cannot be translated once created.
// y is positive towards the RPi. Couldn't make a single hull work.
module base(z) {
    $fn=100;
    linear_extrude(height=z,center=false,convexity=10) {
        // place circles in the corners, account for the rounding radius
        union() {
         // Breadboard rectangular area.
        hull() {
            translate([-wide_x+round_radius/2, wide_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([wide_x-round_radius/2, wide_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([wide_x-round_radius/2, cutout_y-round_radius/2, 0])
            circle(r=round_radius);

            translate([-wide_x+round_radius/2, cutout_y-round_radius/2, 0])
            circle(r=round_radius);
            }
        };
        // Battery area
        hull() {
            translate([narrow_x-round_radius/2, wide_y-round_radius/2, 0])
            circle(r=round_radius);

            translate([narrow_x-round_radius/2, full_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([-narrow_x+round_radius/2, full_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([-narrow_x+round_radius/2, wide_y-round_radius/2, 0])
            circle(r=round_radius);
        }
        // Wingtip left
        hull() {
            translate([-wide_x+round_radius/2, cutout_y-round_radius/2, 0])
            circle(r=round_radius);

            translate([-wide_x+round_radius/2, min_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([-end_cutout_x+round_radius/2, min_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([-start_cutout_x+round_radius/2, cutout_y+round_radius/2, 0])
            circle(r=round_radius);
        }
        // Wingtip right
        hull() {
            translate([wide_x-round_radius/2, cutout_y-round_radius/2, 0])
            circle(r=round_radius);

            translate([wide_x-round_radius/2, min_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([end_cutout_x-round_radius/2, min_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([start_cutout_x-round_radius/2, cutout_y+round_radius/2, 0])
            circle(r=round_radius);
        }
        translate([narrow_x,wide_y,0])
        fillet(fillet_side,270);
        translate([-narrow_x,wide_y,0])
        fillet(fillet_side,180);
    }
}

// This is the basic plate less a rim width all around. This is meant to
// be subtracted from the standard plate. There should be no rim where hulls join.
module base_cutout(z,rwidth) {
    $fn=100;
    linear_extrude(height=z,center=false,convexity=10) {
        // place circles in the corners, account for the rounding radius and rim
        // There is no rim on joint.
        union() {
            // Breadboard rectangular area.
            hull() {
            translate([-wide_x+round_radius/2+rwidth, wide_y+round_radius/2+rwidth, 0])
            circle(r=round_radius);

            translate([wide_x-round_radius/2-rwidth, wide_y+round_radius/2+rwidth, 0])
            circle(r=round_radius);

            translate([wide_x-round_radius/2-rwidth, cutout_y-round_radius/2, 0])
            circle(r=round_radius);

            translate([-wide_x+round_radius/2+rwidth, cutout_y-round_radius/2, 0])
            circle(r=round_radius);
            }
        };
        // Battery area
        hull() {
            translate([narrow_x-round_radius/2-rwidth, wide_y+round_radius, 0])
            circle(r=round_radius);

            translate([narrow_x-round_radius/2-rwidth, full_y+round_radius/2+rwidth, 0])
            circle(r=round_radius);

            translate([-narrow_x+round_radius/2+rwidth, full_y+round_radius/2+rwidth, 0])
            circle(r=round_radius);

            translate([-narrow_x+round_radius/2+rwidth, wide_y+round_radius, 0])
            circle(r=round_radius);
        }
        // Wingtip left
        hull() {
            translate([-wide_x+round_radius/2+rwidth, cutout_y-round_radius/2, 0])
            circle(r=round_radius);

            translate([-wide_x+round_radius/2+rwidth, min_y+round_radius/2-rwidth, 0])
            circle(r=round_radius);

            translate([-end_cutout_x+round_radius/2-rwidth, min_y+round_radius/2-rwidth, 0])
            circle(r=round_radius);

            translate([-start_cutout_x+round_radius/2, cutout_y-round_radius/2-rwidth, 0])
            circle(r=round_radius);
        }
        // Wingtip right
        hull() {
            translate([wide_x-round_radius/2-rwidth, cutout_y-round_radius/2, 0])
            circle(r=round_radius);

            translate([wide_x-round_radius/2-rwidth, min_y+round_radius/2-rwidth, 0])
            circle(r=round_radius);

            translate([end_cutout_x-round_radius/2+rwidth, min_y+round_radius/2-rwidth, 0])
            circle(r=round_radius);

            translate([start_cutout_x-round_radius/2, cutout_y-round_radius/2-rwidth, 0])
            circle(r=round_radius);
        }
        translate([narrow_x-rwidth,-wide_y+rwidth,0])
        fillet(fillet_side,270);
        translate([-narrow_x+rwidth,-wide_y+rwidth,0])
        fillet(fillet_side,180);
    }
}

// --------------------- Final Assembly ----------------------
// Baseplate
translate([0,0,-thickness/2])
difference() {
    base(thickness);
    rivet_holes(thickness);
    post_holes(thickness);
}
translate([0,0,thickness/2])
difference() {
     color("red")
     base(thickness);
     base_cutout(thickness,rim);
}
 //translate([0,-breadboard_y/2,thickness/2])
 //tub(thickness,rim);


change material thickness

change material thickness

include <../util/slots.scad>
include <../util/rounded_square.scad>
$fn=20;
power_supply_length=215;
power_supply_width=115;
power_supply_height=50;

overall_length=300;
overall_height=70;
stepper_power_width=30;

part_separation=5;
material_thickness=3.04;
corner_radius=10;
hole_size=3.2;

base_plate_length=150 + 70;
base_plate_width=power_supply_width + 2*corner_radius+material_thickness;
module m4_holes(){
  hole_radius = 4.2/2;
  x_offset = 150/2;
  y_offset = 50/2;
  translate([x_offset, y_offset]){
    circle(hole_radius);
  }
  translate([-x_offset, y_offset]){
    circle(hole_radius);
  }
  translate([x_offset, -y_offset]){
    circle(hole_radius);
  }
  translate([-x_offset, -y_offset]){
    circle(hole_radius);
  }

}
module power_supply(){
  difference(){
    %square([215, 115], center=true);
    m4_holes();
  }
}
module power_supply_side_holes(){
  hole_diameter = 4.2;
  x_offset = 150/2;
  y_offset = 13;
  translate([x_offset, y_offset]){
    circle(d=hole_diameter);
  }
  translate([-x_offset, y_offset]){
    circle(d=hole_diameter);
  }
}
module power_supply_side(){
  difference(){
    %square([215, 50], center=true);
    power_supply_side_holes();
  }
}

module nema(){
  square([27, 42.3], center=true);
}

module vent_legs(count=3, radius=10){
  for(x=[1:count]){
    translate([x*overall_length/(count + 1), 0]){
      hull(){
          translate([-1.5*radius, 0])circle(radius);
          translate([1.5*radius, 0]) circle(radius);
      }
    }
  }
}

module power_switch(){
  circle(12);
  %square([30, 37], center=true);
}

module stepper_power(){
  square([stepper_power_width, 110]);
}

module stepper_power_side_dc(){
  %square([stepper_power_width, 48]);
  translate([stepper_power_width/2, 9]) circle(d=10);
}

module stepper_power_side_ac(){
  %square([stepper_power_width, 48]);
  translate([stepper_power_width/2, 15.5]) square([15,20], center=true);
}

module ac_side(){
  difference(){
    side();
    translate([material_thickness, material_thickness]) stepper_power_side_ac();
    translate([material_thickness + stepper_power_width + 25, power_supply_height/2 + 10]) rotate(90) nema();
    translate([material_thickness + stepper_power_width + 10, 9]) circle(d=7.5);
  }
}

module dc_side(){
  difference(){
    side();
    translate([material_thickness, material_thickness]) stepper_power_side_dc();
    translate([material_thickness + stepper_power_width + 25, 2*power_supply_height/3]) circle(d=19.7);
    translate([material_thickness + stepper_power_width + 5, 17]) circle(d=7.5);
  }
}

module screw_terminal(n=2){
  terminal_height=18.6;
  divider_height=21.8;

  hole_locations = [[ 2, 28.7], [3, 38.2], [4, 47.7], [5, 57.2], [6, 66.7], [7, 76.2], [8, 85.7]];
  lengths =        [[2, 36.2], [3, 45.7], [4, 55.2], [5, 64.7], [6, 74.2], [7, 83.7], [8, 93.2]];
  hole_distance = lookup(n, hole_locations);
  length =        lookup(n, lengths);
  // translate([length/2, divider_height/2]){
      %square([length, divider_height], center=true);
      translate([-hole_distance/2, 4]) circle(d=4);
      translate([-hole_distance/2, -4]) circle(d=4);
      translate([hole_distance/2, 4]) circle(d=4);
      translate([hole_distance/2, -4]) circle(d=4);
  // }
}

module side(){
  leg_holes = floor(overall_length/5);
  difference(){
    square([overall_length, overall_height]);
    make_slots(overall_length - power_supply_length, 5, material_thickness, true);
    translate([0, overall_height]) vent_legs();
    translate([material_thickness, 0]) rotate(90) make_slots(overall_height, 5, material_thickness, true);
    translate([material_thickness, power_supply_height + 1.5]) make_slots(overall_length - power_supply_length - material_thickness, 5, material_thickness, true);
    translate([overall_length - power_supply_length, 0]){
      translate([power_supply_length/2, power_supply_height/2]) rotate(180) power_supply_side();
    }
  }
}

module front(){
  translate([0, material_thickness]) square([power_supply_width, overall_height - material_thickness]);
  translate([power_supply_width + material_thickness, 0]) rotate(90) make_slots(overall_height, 5, material_thickness, true);
  translate([0, 0]) rotate(90) make_slots(overall_height, 5, material_thickness, true);
  make_slots(power_supply_width, 5, material_thickness, true);
}

module top(){
  difference(){
    union(){
      square([overall_length - power_supply_length, power_supply_width]);
      translate([0, power_supply_width]) make_slots(overall_length - power_supply_length, 5, material_thickness, true);
      translate([0, -material_thickness]) make_slots(overall_length - power_supply_length, 5, material_thickness, true);
    }
    translate([material_thickness, 0]) rotate(90) make_slots(power_supply_width, 5, material_thickness, true);
    translate([(overall_length - power_supply_length + 13)/2, 2.4*power_supply_width/5]) power_switch();
    translate([(overall_length - power_supply_length + 30)/2, 4*power_supply_width/5]) screw_terminal(2);
    % translate([material_thickness, 0]) stepper_power();
  }
}

module bottom(){
  bottom_length = overall_length - power_supply_length - material_thickness;
  square([bottom_length, power_supply_width]);
  translate([0, power_supply_width]) make_slots(bottom_length, 5, material_thickness, true);
  translate([0, -material_thickness]) make_slots(bottom_length, 5, material_thickness, true);
}

ac_side();
translate([0, -part_separation]) mirror([0,1,0]) dc_side();
translate([0, -(overall_height + power_supply_width + 2* part_separation)]) top();
translate([-power_supply_width - part_separation, 0]) front();
translate([material_thickness, overall_height + part_separation]) bottom();

include <../util/slots.scad>
include <../util/rounded_square.scad>
$fn=20;
power_supply_length=215;
power_supply_width=115;
power_supply_height=50;

overall_length=300;
overall_height=70;
stepper_power_width=30;

part_separation=5;
material_thickness=3.1;
corner_radius=10;
hole_size=3.2;

base_plate_length=150 + 70;
base_plate_width=power_supply_width + 2*corner_radius+material_thickness;
module m4_holes(){
  hole_radius = 4.2/2;
  x_offset = 150/2;
  y_offset = 50/2;
  translate([x_offset, y_offset]){
    circle(hole_radius);
  }
  translate([-x_offset, y_offset]){
    circle(hole_radius);
  }
  translate([x_offset, -y_offset]){
    circle(hole_radius);
  }
  translate([-x_offset, -y_offset]){
    circle(hole_radius);
  }

}
module power_supply(){
  difference(){
    %square([215, 115], center=true);
    m4_holes();
  }
}
module power_supply_side_holes(){
  hole_diameter = 4.2;
  x_offset = 150/2;
  y_offset = 13;
  translate([x_offset, y_offset]){
    circle(d=hole_diameter);
  }
  translate([-x_offset, y_offset]){
    circle(d=hole_diameter);
  }
}
module power_supply_side(){
  difference(){
    %square([215, 50], center=true);
    power_supply_side_holes();
  }
}

module nema(){
  square([27, 42.3], center=true);
}

module vent_legs(count=3, radius=10){
  for(x=[1:count]){
    translate([x*overall_length/(count + 1), 0]){
      hull(){
          translate([-1.5*radius, 0])circle(radius);
          translate([1.5*radius, 0]) circle(radius);
      }
    }
  }
}

module power_switch(){
  circle(12);
  %square([30, 37], center=true);
}

module stepper_power(){
  square([stepper_power_width, 110]);
}

module stepper_power_side_dc(){
  %square([stepper_power_width, 48]);
  translate([stepper_power_width/2, 9]) circle(d=10);
}

module stepper_power_side_ac(){
  %square([stepper_power_width, 48]);
  translate([stepper_power_width/2, 15.5]) square([15,20], center=true);
}

module ac_side(){
  difference(){
    side();
    translate([material_thickness, material_thickness]) stepper_power_side_ac();
    translate([material_thickness + stepper_power_width + 25, power_supply_height/2 + 10]) rotate(90) nema();
    translate([material_thickness + stepper_power_width + 10, 9]) circle(d=7.5);
  }
}

module dc_side(){
  difference(){
    side();
    translate([material_thickness, material_thickness]) stepper_power_side_dc();
    translate([material_thickness + stepper_power_width + 25, 2*power_supply_height/3]) circle(d=19.7);
    translate([material_thickness + stepper_power_width + 5, 17]) circle(d=7.5);
  }
}

module screw_terminal(n=2){
  terminal_height=18.6;
  divider_height=21.8;

  hole_locations = [[ 2, 28.7], [3, 38.2], [4, 47.7], [5, 57.2], [6, 66.7], [7, 76.2], [8, 85.7]];
  lengths =        [[2, 36.2], [3, 45.7], [4, 55.2], [5, 64.7], [6, 74.2], [7, 83.7], [8, 93.2]];
  hole_distance = lookup(n, hole_locations);
  length =        lookup(n, lengths);
  // translate([length/2, divider_height/2]){
      %square([length, divider_height], center=true);
      translate([-hole_distance/2, 4]) circle(d=4);
      translate([-hole_distance/2, -4]) circle(d=4);
      translate([hole_distance/2, 4]) circle(d=4);
      translate([hole_distance/2, -4]) circle(d=4);
  // }
}

module side(){
  leg_holes = floor(overall_length/5);
  difference(){
    square([overall_length, overall_height]);
    make_slots(overall_length - power_supply_length, 5, material_thickness, true);
    translate([0, overall_height]) vent_legs();
    translate([material_thickness, 0]) rotate(90) make_slots(overall_height, 5, material_thickness, true);
    translate([material_thickness, power_supply_height + 1.5]) make_slots(overall_length - power_supply_length - material_thickness, 5, material_thickness, true);
    translate([overall_length - power_supply_length, 0]){
      translate([power_supply_length/2, power_supply_height/2]) rotate(180) power_supply_side();
    }
  }
}

module front(){
  translate([0, material_thickness]) square([power_supply_width, overall_height - material_thickness]);
  translate([power_supply_width + material_thickness, 0]) rotate(90) make_slots(overall_height, 5, material_thickness, true);
  translate([0, 0]) rotate(90) make_slots(overall_height, 5, material_thickness, true);
  make_slots(power_supply_width, 5, material_thickness, true);
}

module top(){
  difference(){
    union(){
      square([overall_length - power_supply_length, power_supply_width]);
      translate([0, power_supply_width]) make_slots(overall_length - power_supply_length, 5, material_thickness, true);
      translate([0, -material_thickness]) make_slots(overall_length - power_supply_length, 5, material_thickness, true);
    }
    translate([material_thickness, 0]) rotate(90) make_slots(power_supply_width, 5, material_thickness, true);
    translate([(overall_length - power_supply_length + 13)/2, 2.4*power_supply_width/5]) power_switch();
    translate([(overall_length - power_supply_length + 30)/2, 4*power_supply_width/5]) screw_terminal(2);
    % translate([material_thickness, 0]) stepper_power();
  }
}

module bottom(){
  bottom_length = overall_length - power_supply_length - material_thickness;
  square([bottom_length, power_supply_width]);
  translate([0, power_supply_width]) make_slots(bottom_length, 5, material_thickness, true);
  translate([0, -material_thickness]) make_slots(bottom_length, 5, material_thickness, true);
}

ac_side();
translate([0, -part_separation]) mirror([0,1,0]) dc_side();
translate([0, -(overall_height + power_supply_width + 2* part_separation)]) top();
translate([-power_supply_width - part_separation, 0]) front();
translate([material_thickness, overall_height + part_separation]) bottom();


Bugfixes.

Bugfixes.

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

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

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

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

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

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

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

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

// for slight offsets/tweaks
epsilon = 1;

// vars to control projection for DXF export (see makefile)
if (DXF_TOP) {
    projection() top_cover();
} else if (DXF_BOTTOM) {
    projection() tank_base();
} else if (DXF_SIDE1) {
    projection() rotate(a=[90,0,0]) side(y=0);
} else if (DXF_SIDE2) {
    projection() rotate(a=[90,0,0]) side(y=depth);
} else if (DXF_END1) {
    projection() rotate(a=[0,90,0]) vert_face(x=0);
} else if (DXF_END2) {
    projection() rotate(a=[0,90,0]) vert_face(x=width);
} else if (DXF_LIGHT_BAR) {
    projection() light_bar();
}
else {
    // 3D model
    // components to include (comment out unwanted)
    vert_face(x=0);
    vert_face(x=width);
    side(y=0);
    side(y=depth);
    tank_base();
    light_bar();
    // camera supports
    hanging_supports(x=width, y=depth/2, z=height/2, out=20, up=30, spacing=20);
    // rpi support
    hanging_support(x=width, y=depth/4+9, z=height/2, out=3, up=85);
    mock_rpi(x=width, y=depth/4, z=height/2);
    top_cover();
}

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

module vert_face(x=0) {
    difference() {
        vert_face_base(x);
        camera_opening();
        // camera supports
        hanging_supports(x=width+thickness, y=depth/2, z=height/2+10, out=20, up=30, spacing=20);
        // rpi supports
        hanging_support(x=width+thickness, y=depth/4+9, z=height/2+10, out=3, up=85);
        side(y=0);
        side(y=depth);
        tank_base();
    }
}

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

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

module hanging_supports(x, y, z, out, up, spacing) {
    hanging_support(x, y + spacing/2, z, out, up);
    hanging_support(x, y - spacing/2, z, out, up);
}

module hanging_support(x, y, z, out, up) {
    inner_w = out+thickness;
    inner_h = up;
    inner_offset = 5;
    translate([x,y,z])
    // shift down to center on camera opening
    translate([0,0,-inner_offset])
    // push inner opening up against vert face
    translate([inner_w/2,0,0])
    difference() {
        cube([inner_w+20, thickness, inner_h+30], center=true);
        // cutout for camera
        translate([0,0,inner_offset])
            cube([inner_w, thickness*2, inner_h], center=true);
        // cutout for passing through vertface
        translate([-10-epsilon,0,0])
            cube([inner_w, thickness*2, inner_h-10], center=true);
        // bottom cutout
        translate([-inner_w/2,0,-25])
            cube([thickness, thickness*2, 10], center=true);
    }
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// for slight offsets/tweaks
epsilon = 1;

// vars to control projection for DXF export (see makefile)
if (DXF_TOP) {
    projection() top_cover();
} else if (DXF_BOTTOM) {
    projection() tank_base();
} else if (DXF_SIDE1) {
    projection() rotate(a=[90,0,0]) side(y=0);
} else if (DXF_SIDE2) {
    projection() rotate(a=[90,0,0]) side(y=depth);
} else if (DXF_END1) {
    projection() rotate(a=[0,90,0]) vert_face(x=0);
} else if (DXF_END2) {
    projection() rotate(a=[0,90,0]) vert_face(x=width);
} else if (DXF_LIGHT_BAR) {
    projection() light_bar();
}
else {
    // 3D model
    // components to include (comment out unwanted)
    vert_face(x=0);
    vert_face(x=width);
    side(y=0);
    side(y=depth);
    tank_base();
    light_bar();
    // camera supports
    hanging_supports(x=width, y=depth/2, z=height/2, out=20, up=30, spacing=20);
    // rpi support
    hanging_support(x=width, y=depth/4+9, z=height/2, out=3, up=85);
    mock_rpi(x=width, y=depth/4, z=height/2);
    top_cover();
}

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

module vert_face(x=0) {
    difference() {
        vert_face_base(x);
        camera_opening();
        // camera supports
        hanging_supports(x=width+thickness, y=depth/2, z=height/2+10, out=20, up=30, spacing=20);
        // rpi supports
        hanging_support(x=width+thickness, y=depth/4+9, z=height/2+10, out=3, up=85);
        side(y=0);
        side(y=depth);
        tank_base();
    }
}

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

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

module hanging_supports(x, y, z, out, up, spacing) {
    hanging_support(x, y + spacing/2, z, out, up);
    hanging_support(x, y - spacing/2, z, out, up);
}

module hanging_support(x, y, z, out, up) {
    inner_w = out+thickness;
    inner_h = up;
    inner_offset = 5;
    translate([x,y,z])
    // shift down to center on camera opening
    translate([0,0,-inner_offset])
    // push inner opening up against vert face
    translate([inner_w/2,0,0])
    difference() {
        cube([inner_w+20, thickness, inner_h+30], center=true);
        // cutout for camera
        translate([0,0,inner_offset])
            cube([inner_w, thickness*2, inner_h], center=true);
        // cutout for passing through vertface
        translate([-10-epsilon,0,0])
            cube([inner_w, thickness*2, inner_h-10], center=true);
        // bottom cutout
        translate([-inner_w/2,0,-25])
            cube([thickness, thickness*2, 10], center=true);
    }
}

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

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

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

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

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

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

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

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

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


bottom_surface

include <constants.scad>;
HEIGHT_BODY = 44.5;
DIAMETER_BODY = 10.4;
BORDER_RADIUS_BODY = 0.2;
HEIGHT_NIPPLE = 0.8;
HEIGHT_COVER = 2 * BORDER_RADIUS_BODY;

function top_position_z () = -(HEIGHT_NIPPLE + BORDER_RADIUS_BODY);
function main_position_z() = -(HEIGHT_BODY - BORDER_RADIUS_BODY);

module top_surface()
{
    position = [0,0,top_position_z()];
    diameter_base = DIAMETER_BODY - HEIGHT_COVER;

    translate(position)
    cylinder(
        h = BORDER_RADIUS_BODY,
        d = diameter_base,
        $fn = FINE);
}

module shoulder(position_z)
{
    position_ring = [0,0,position_z];

    position_circle_x = radius(DIAMETER_BODY)-BORDER_RADIUS_BODY;
    posision_circle = [position_circle_x, 0, 0];

    translate(position_ring)
        rotate_extrude(convexity = CONVEXITY, $fn = FINE)
            translate(posision_circle)
                circle(r = BORDER_RADIUS_BODY, $fn = FINE);
}

module main_cylinder()
{
    position = [0,0,main_position_z()];

    heigh_main = HEIGHT_BODY - (HEIGHT_NIPPLE + HEIGHT_COVER);

    translate(position)
        cylinder(
            h = heigh_main,
            d = DIAMETER_BODY,
            $fn = FINE);
}

module bottom_surface()
{
    position = [0,0,-HEIGHT_BODY];
    diameter = DIAMETER_BODY - HEIGHT_COVER;

    translate(position)
        cylinder(
            h = BORDER_RADIUS_BODY,
            d = diameter,
            $fn = FINE);
}

module body()
{
    top_surface();
    shoulder(top_position_z());

    main_cylinder();

    shoulder(main_position_z());
    bottom_surface();
}

body();

include <constants.scad>;
HEIGHT_BODY = 44.5;
DIAMETER_BODY = 10.4;
BORDER_RADIUS_BODY = 0.2;
HEIGHT_NIPPLE = 0.8;

HEIGHT_TOP = 2 * BORDER_RADIUS_BODY;

function top_position_z () = -(HEIGHT_NIPPLE + BORDER_RADIUS_BODY);
function main_position_z() = -(HEIGHT_BODY - BORDER_RADIUS_BODY);

module top_surface()
{
    position = [0,0,top_position_z()];

    diameter_base = DIAMETER_BODY - HEIGHT_TOP;

    translate(position)
    cylinder(
        h = BORDER_RADIUS_BODY,
        d = diameter_base,
        $fn = FINE);
}

module shoulder(position_z)
{
    position_ring = [0,0,position_z];

    position_circle_x = radius(DIAMETER_BODY)-BORDER_RADIUS_BODY;
    posision_circle = [position_circle_x, 0, 0];

    translate(position_ring)
        rotate_extrude(convexity = CONVEXITY, $fn = FINE)
            translate(posision_circle)
                circle(r = BORDER_RADIUS_BODY, $fn = FINE);
}

module main_cylinder()
{
    position = [0,0,main_position_z()];

    heigh_main = HEIGHT_BODY - (HEIGHT_NIPPLE + HEIGHT_TOP);

    translate(position)
        cylinder(
            h = heigh_main,
            d = DIAMETER_BODY,
            $fn = FINE);
}

module body()
{
    top_surface();
    shoulder(top_position_z());

    main_cylinder();
    shoulder(main_position_z());

//Bottom face of body
translate([0,0,-(HEIGHT_BODY)])
    cylinder(
        h = BORDER_RADIUS_BODY,
        d = (DIAMETER_BODY - (2 * BORDER_RADIUS_BODY)),
        $fn = FINE);
}

body();