config: refactor lq/hq modes

config: refactor lq/hq modes

include <MCAD/stepper.scad>
include <thing_libutils/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>
include <thing_libutils/timing-belts-data.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 : 2;

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

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

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 = 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 = [2*mm, 3*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;
// relative to entire machine
xaxis_rod_offset_x = 0*mm;
xaxis_bearings_top=2;
xaxis_bearings_bottom=1;
xaxis_bearing=bearing_bronze_10_16_12;
xaxis_bearing_bottom=bearing_bronze_10_16_18;
/*xaxis_bearing=bearing_igus_rj4jp_01_10;*/

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+1*mm;
xaxis_carriage_beltpath_offset_y = xaxis_carriage_bearing_offset_y+xaxis_bearing[1]/2;

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

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_bronze_12_18_18;
yaxis_bearing_distance_y = 7*cm;

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

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

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

yaxis_carriage_size = [220*mm,220*mm,5*mm];
printbed_size = [213*mm,213*mm,3*mm];

zaxis_rod_d = 11.975*mm;
zaxis_rod_l = 500*mm;
// relative to entire machine
zaxis_rod_offset = [0,-20*mm,0];
zaxis_bearing=bearing_bronze_12_18_18;

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

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

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

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

include <MCAD/stepper.scad>
include <thing_libutils/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>
include <thing_libutils/timing-belts-data.scad>

e=0.01;

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

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

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

/*$show_vit=true;*/

// enable preview model (faster openscad)
$preview_mode=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;

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 = 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 = [2*mm, 3*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;
// relative to entire machine
xaxis_rod_offset_x = 0*mm;
xaxis_bearings_top=2;
xaxis_bearings_bottom=1;
xaxis_bearing=bearing_bronze_10_16_12;
xaxis_bearing_bottom=bearing_bronze_10_16_18;
/*xaxis_bearing=bearing_igus_rj4jp_01_10;*/

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+1*mm;
xaxis_carriage_beltpath_offset_y = xaxis_carriage_bearing_offset_y+xaxis_bearing[1]/2;

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

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_bronze_12_18_18;
yaxis_bearing_distance_y = 7*cm;

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

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

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

yaxis_carriage_size = [220*mm,220*mm,5*mm];
printbed_size = [213*mm,213*mm,3*mm];

zaxis_rod_d = 11.975*mm;
zaxis_rod_l = 500*mm;
// relative to entire machine
zaxis_rod_offset = [0,-20*mm,0];
zaxis_bearing=bearing_bronze_12_18_18;

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

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

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

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


feat: add an operator to animate a scaling

/**
 * @license
 * MIT License
 *
 * Copyright (c) 2022 Jean-Sebastien CONAN
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

/**
 * Part of the camelSCAD library.
 *
 * Operators that animate child modules with respect to particular rules.
 *
 * @package operator/animate
 * @author jsconan
 */

/**
 * Scales the child modules, interpolating the scale ratios with respect to the `$t` variable.
 *
 * @param Vector [from] - The scale ratios from where starts the interpolation.
 * @param Vector [to] - The scale ratios to where ends the interpolation.
 * @param Number [start] - The start threshold under what the from-scale ratios will persist and above what it will be interpolated.
 * @param Number [end] - The end threshold above what the to-scale ratios will persist and under what it will be interpolated.
 * @param Number [domain] - The percentage domain used to compute the thresholds (default: 100).
 * @param Vector [values] - A list of scale ratios composing the range to interpolate.
 * @param Vector [range] - A pre-built interpolation range. If missing, it will be built from the parameters `from`, `to`, `start`, `end`, `domain`.
 * @returns Number
 */
module scaleAnimate(from, to, start, end, domain, values, range) {
    scale(interpolateStep3D(step=$t, low=from, high=to, start=start, end=end, domain=domain, values=values, range=range)) {
        children();
    }
}

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


initial model

initial model

$fs=0.01;

module supportCore()
{
  // top cylinder
  translate([0, 0, 30-5])
    rotate([-90, 0, 0])
      cylinder(r=5, h=40);
  // main support
  translate([-5, 0, 0])
    cube([10, 40, 30-5]);
}

module support()
{
  difference()
  {
    supportCore();
    for(offset = [-5, +5])
      translate([offset, 0, 0])
        scale([1, 1, (30-5)/(2*2)])
          translate([0, -1, 2])
           rotate([-90, 0, 0])
             cylinder(r=2, h=42);
  }
}

module mountingPad()
{
  translate([-30/2, -10, 0])
    cube([30, 60, 2]);
}

mountingPad();
translate([0, 0, 2])
  support();


Create motor2.scad

Create motor2.scad

module logo_motor(motor_rotation_x, motor_rotation_y, motor_rotation_z){
motor_shaft_r=5;
motor_shaft_h=8;
motor_flange_h = 1;
motor_flange_r = 9.20;
Motor_body_r = 28.00;
Motor_body_h = 19.30;

	///rotate object around to Y access
	rotate([motor_rotation_x, motor_rotation_y, motor_rotation_z]){

// shaft

			difference() {
		color("grey");
		cylinder(r=motor_shaft_r, h=motor_shaft_h, center=true);
			///add some flats

				translate([-5,2,-4])
				cube([10,5,6]);

				mirror([0,1,0]){

				translate([-5,2,-4])
				cube([10,5,6]);
				}
					}

					//flange
					translate([0,0,motor_shaft_h/2])
						color("yellow")
						cylinder(r=motor_flange_r, h=motor_flange_h, center=true);
						// Main Body
							translate([0,-15,14])
								color("silver")
						cylinder(r=Motor_body_r, h=Motor_body_h, center=true);
							//Flanges
								translate([35,-15,4.5]){
									difference() {
										cylinder(r=7, h=1);
											cylinder(r=4, h=1);
										}
										translate([-14,-7,0]){
											cube([14.5,14,1]);
										}
										//color("white")
										//cylinder(r=4, h=1);

								}
								translate([-35,-15,4.5]){
								difference() {
									cylinder(r=7, h=1);
									cylinder(r=4, h=1);
									}
									translate([0,-7,0]){
											cube([14.5,14,1]);
										}

										//color("white")
										//cylinder(r=4, h=1);

										}
							  //bottom
							color("blue")
							 translate([0-7,-46,4])
								  cube([14.5,5.5,Motor_body_h]);

			}
}
logo_motor(90,0,0);

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


made L298N module mounts a little closer to walls. raise top platform a bit to clear L298N heatsink

// $URL: svn+ssh://mrwhat@ssh.boim.com/home/mrwhat/svn/Walker/trunk/driveElectronicsMount.scad $
// $Id: driveElectronicsMount.scad 437 2015-03-02 15:24:02Z mrwhat $

// Mount to attach to axles and hold motor drive module

Bhole=2.38+.2;  // for brass tube
PCBhole = (25.4*3/32)/2;//1;  // found that 3/32" drill made good pilot for #4 self-piloting screw
include <JansenDefs.scad>;  // Bx
layer1bias = 0.4;
platformHeight = 45; // from bar to top platform
mountHeight=15; // from bar to electronics platform
PCBwidth=43;
HoleInset=3;

thick=5;
t2=thick/2;

sf = 16;  // sphere faces

module braceBar(axisSep,axisRad) { difference() { union() {
   for (a=[-1,1]) translate([a*axisSep,0,0]) {
       //cylinder(h=thick,r1=axisRad+3,r2=axisRad+2,$fn=24);
     hull() {
       intersection() {
          translate([0,0,2]) scale([axisRad+3,axisRad+3,thick*.8]) sphere(r=1,$fn=24);
          translate([0,0,thick/2]) cube([22,22,thick],center=true);
       }
       translate([-a*16,-2,t2]) sphere(t2,$fn=24);
     }
   }

   // main bar
   //%hull() for (a=[-1,1]) translate([a*axisSep,-axisRad+1,0])
   //    cylinder(h=thick,r1=4,r2=3,$fn=6);
   hull() for (a=[-1,1]) translate([a*axisSep,-axisRad+.5,0])
      intersection() {
         translate([0,0,2.5]) scale([4,3.5,3.5]) sphere(1,$fn=24);
         translate([0,0,t2]) cube([22,22,thick],center=true);
      }

   }

   // holes for main axle bars
   for (a=[-1,1]) translate([axisSep*a,0,-.1])
       cylinder(h=thick*2,r=axisRad,$fn=96);

   // u-groove in main bar
   hull() for (a=[-1,1]) translate([a*axisSep*.8,-axisRad*.8,4.1])
       scale([6,2,2.5]) sphere(r=1,$fn=18);
}}

module braceCutOut1(pw,mh,dh) {
    translate([-pw+dh,mh,0]) hull() {
       translate([0,0,11]) sphere(r=2.2,$fn=22);
       translate([0,0,4]) scale([3.5,3,2]) sphere(r=1,$fn=22);
    }

    for(b=[-1,1]) hull() {
      translate([-pw+dh-4*b,mh,13]) sphere(r=2.2,$fn=22);
      translate([-pw+dh-7.5*b,mh,5]) sphere(r=3,$fn=22);
    }
}

module braceCutOut(pw,mh,dh) {
    translate([-pw+dh,mh,0]) hull() {
       translate([0,0,11-1]) sphere(r=2.2,$fn=22);
       translate([0,0,5]) scale([2.5,4,2]) sphere(r=1,$fn=22);
    }

    for(b=[-1,1]) hull() {
      translate([-pw+dh-4*b,mh,13-2]) sphere(r=2.2,$fn=22);
      translate([-pw+dh-6.5*b,mh,5]) sphere(r=2.8,$fn=22);
    }
}

thinWall=0.41;  // width of thinnest wall which will not get culled by slicer

module mountBrace(pw,mh,dh) {
mountInset = 16;  // dist above z axis for PCB mount hole
mountSphereRad=6;
  union() {
    difference() {
      hull() {
        translate([-pw-10,mh, 2]) sphere(r=2,$fn=sf);
        translate([-4    ,mh, 2]) sphere(r=2,$fn=sf);
        //translate([-pw+dh,mh,16]) rotate([90,0,0])
        //  cylinder(h=4,r=5,$fn=26,center=true);
        translate([-pw+dh,mh,mountInset+HoleInset-mountSphereRad]) intersection() {
           scale([1,.6,1]) sphere(r=mountSphereRad,$fn=24);
           cube([15,4,15],center=true);
        }
      }

      braceCutOut(pw,mh,dh);
    }

    // put a (hopefully) single-layer wall across middle of brace.
    // makes it more stable, easier to print, and can be remioved
    // if desired.
    #hull() {
      translate([-pw+dh,mh,16]) cube([8,thinWall,2],center=true);
      translate([-pw/2-7,mh,2]) cube([pw+10,thinWall,1],center=true);
    }
  }
}
module mountBrace1(pw,mh,dh) {
  hull() { translate([-pw+2 ,mh,19]) sphere(r=2,$fn=sf);
           translate([-pw-10,mh, 2]) sphere(r=2,$fn=sf); }
  hull() { translate([-pw+2 ,mh,19]) sphere(r=2,$fn=sf);
           translate([-4    ,mh, 2]) sphere(r=2,$fn=sf); }
  translate([-pw+dh,mh,16]) rotate([90,0,0]) cylinder(h=4,r=6,$fn=6,center=true);
}

module motorDriverStand(axisSep,axisRad,platHeight,platWidth,dHole,rHole)
{
difference() { union() {
   braceBar(axisSep,axisRad);

if(0) {
   hull() { translate([-axisSep+thick, -2,t2]) sphere(r=t2-1,$fn=sf);
            translate([ axisSep-18,-2,22]) sphere(r=t2-1,$fn=sf); } hull() {
            translate([ axisSep-thick, -2,t2]) sphere(r=t2-1,$fn=sf);
            translate([-axisSep+18,-2,22]) sphere(r=t2-1,$fn=sf); } hull() {
            translate([-axisSep+thick, -2,t2]) sphere(r=t2,$fn=sf);
            translate([-axisSep+18,-2,22]) sphere(r=t2,$fn=sf); }
hull() {
            translate([ axisSep-thick, -2,t2]) sphere(r=t2,$fn=sf);
            translate([ axisSep-18,-2,22]) sphere(r=t2,$fn=sf); }
hull() {
            translate([-axisSep+18,-2,22]) sphere(r=t2,$fn=sf);
            translate([ axisSep-18,-2,22]) sphere(r=t2,$fn=sf); }
}

   mirror([1,0,0]) mountBrace(platWidth/2,mountHeight,dHole);
                   mountBrace(platWidth/2,mountHeight,dHole);

   hull() for(a=[-1,1]) translate([a*(platWidth/2+15),mountHeight,2])
      sphere(r=2.4,$fn=sf);

   for (a=[-1,1]) hull() {  // side diag rails
      translate([a*platWidth*.3,platHeight-.5,2]) sphere(r=2.4,$fn=sf);
      translate([a*(axisSep-5) ,    1        ,2]) sphere(r=2.4,$fn=sf); }

   translate([-platWidth*.35,platHeight-2,0]) cube([platWidth*.7,4,8]);
   }

   for (a=[-1,1]) translate([a*(platWidth/2-dHole),mountHeight,14.5])
      rotate([90,0,0]) cylinder(h=10,r=rHole,$fn=80,center=true);
}}

module footpad(r) { // pad to help a part stick to plate for 3D printer
   cylinder(h=layer1bias,r1=r,r2=r-.3,$fn=11); }

if (WITH_BRIM) {
union() { color("Cyan") hull() {
translate([-Bx,0,0]) footpad(12);
translate([ Bx,0,0]) footpad(12);
translate([-PCBwidth/2, platformHeight-2,0]) footpad(12);
translate([ PCBwidth/2, platformHeight-2,0]) footpad(12);
}
translate([0,0,layer1bias/2])
   motorDriverStand(Bx,Bhole,platformHeight,PCBwidth,HoleInset,PCBhole);
}} else {
  difference() {
    motorDriverStand(Bx,Bhole,platformHeight,PCBwidth,HoleInset,PCBhole);
    translate([0,0,-4]) cube([200,200,8],center=true); }
}

// $URL: svn+ssh://mrwhat@ssh.boim.com/home/mrwhat/svn/Walker/trunk/driveElectronicsMount.scad $
// $Id: driveElectronicsMount.scad 437 2015-03-02 15:24:02Z mrwhat $

// Mount to attach to axles and hold motor drive module

Bhole=2.38+.2;  // for brass tube
PCBhole = 1;
include <JansenDefs.scad>;  // Bx
layer1bias = 0.4;
platformHeight = 40;
mountHeight=15;
PCBwidth=43;
HoleInset=3;

thick=5;
t2=thick/2;

sf = 16;  // sphere faces

module braceBar(axisSep,axisRad) { difference() { union() {
   for (a=[-1,1]) translate([a*axisSep,0,0]) {
       //cylinder(h=thick,r1=axisRad+3,r2=axisRad+2,$fn=24);
     hull() {
       intersection() {
          translate([0,0,2]) scale([axisRad+3,axisRad+3,thick*.8]) sphere(r=1,$fn=24);
          translate([0,0,thick/2]) cube([22,22,thick],center=true);
       }
       translate([-a*16,-2,t2]) sphere(t2,$fn=24);
     }
   }

   // main bar
   //%hull() for (a=[-1,1]) translate([a*axisSep,-axisRad+1,0])
   //    cylinder(h=thick,r1=4,r2=3,$fn=6);
   hull() for (a=[-1,1]) translate([a*axisSep,-axisRad+.5,0])
      intersection() {
         #translate([0,0,2.5]) scale([4,3.5,3.5]) sphere(1,$fn=24);
         translate([0,0,t2]) cube([22,22,thick],center=true);
      }

   }

   // holes for main axle bars
   for (a=[-1,1]) translate([axisSep*a,0,-.1])
       cylinder(h=thick*2,r=axisRad,$fn=96);

   // u-groove in main bar
   hull() for (a=[-1,1]) translate([a*axisSep*.8,-axisRad*.8,4.1])
       scale([6,2,2.5]) sphere(r=1,$fn=18);
}}

module braceCutOut1(pw,mh,dh) {
    translate([-pw+dh,mh,0]) hull() {
       translate([0,0,11]) sphere(r=2.2,$fn=22);
       translate([0,0,4]) scale([3.5,3,2]) sphere(r=1,$fn=22);
    }

    for(b=[-1,1]) hull() {
      translate([-pw+dh-4*b,mh,13]) sphere(r=2.2,$fn=22);
      translate([-pw+dh-7.5*b,mh,5]) sphere(r=3,$fn=22);
    }
}

module braceCutOut(pw,mh,dh) {
    translate([-pw+dh,mh,0]) hull() {
       translate([0,0,11]) sphere(r=2.2,$fn=22);
       translate([0,0,4]) scale([3.5,3,2]) sphere(r=1,$fn=22);
    }

    for(b=[-1,1]) hull() {
      translate([-pw+dh-4*b,mh,13]) sphere(r=2.2,$fn=22);
      translate([-pw+dh-7.5*b,mh,5]) sphere(r=3,$fn=22);
    }
}

module mountBrace(pw,mh,dh) {
  union() {
    difference() {
      hull() {
        translate([-pw-10,mh, 2]) sphere(r=2,$fn=sf);
        translate([-4    ,mh, 2]) sphere(r=2,$fn=sf);
        //translate([-pw+dh,mh,16]) rotate([90,0,0])
        //  cylinder(h=4,r=5,$fn=26,center=true);
        translate([-pw+dh,mh,16]) intersection() {
           scale([6,4,6]) sphere(r=1,$fn=24);
           cube([15,4,15],center=true);
        }
      }

      braceCutOut(pw,mh,dh);
    }

    // put a (hopefully) single-layer wall across middle of brace.
    // makes it more stable, easier to print, and can be remioved
    // if desired.
    #hull() {
      translate([-pw+dh,mh,16]) cube([9,.35,2],center=true);
      translate([-pw/2-7,mh,2]) cube([pw+10,.35,1],center=true);
    }
  }
}
module mountBrace1(pw,mh,dh) {
  hull() { translate([-pw+2 ,mh,19]) sphere(r=2,$fn=sf);
           translate([-pw-10,mh, 2]) sphere(r=2,$fn=sf); }
  hull() { translate([-pw+2 ,mh,19]) sphere(r=2,$fn=sf);
           translate([-4    ,mh, 2]) sphere(r=2,$fn=sf); }
  translate([-pw+dh,mh,16]) rotate([90,0,0]) cylinder(h=4,r=6,$fn=6,center=true);
}

module motorDriverStand(axisSep,axisRad,platHeight,platWidth,dHole,rHole)
{
difference() { union() {
   braceBar(axisSep,axisRad);

if(0) {
   hull() { translate([-axisSep+thick, -2,t2]) sphere(r=t2-1,$fn=sf);
            translate([ axisSep-18,-2,22]) sphere(r=t2-1,$fn=sf); } hull() {
            translate([ axisSep-thick, -2,t2]) sphere(r=t2-1,$fn=sf);
            translate([-axisSep+18,-2,22]) sphere(r=t2-1,$fn=sf); } hull() {
            translate([-axisSep+thick, -2,t2]) sphere(r=t2,$fn=sf);
            translate([-axisSep+18,-2,22]) sphere(r=t2,$fn=sf); }
hull() {
            translate([ axisSep-thick, -2,t2]) sphere(r=t2,$fn=sf);
            translate([ axisSep-18,-2,22]) sphere(r=t2,$fn=sf); }
hull() {
            translate([-axisSep+18,-2,22]) sphere(r=t2,$fn=sf);
            translate([ axisSep-18,-2,22]) sphere(r=t2,$fn=sf); }
}

   mirror([1,0,0]) mountBrace(platWidth/2,mountHeight,dHole);
                   mountBrace(platWidth/2,mountHeight,dHole);

   hull() for(a=[-1,1]) translate([a*(platWidth/2+13),mountHeight,2])
      sphere(r=2.4,$fn=sf);

   for (a=[-1,1]) hull() {  // side diag rails
      translate([a*platWidth*.3,platHeight-.5,2]) sphere(r=2.4,$fn=sf);
      translate([a*(axisSep-5) ,    1        ,2]) sphere(r=2.4,$fn=sf); }

   translate([-platWidth*.35,platHeight-2,0]) cube([platWidth*.7,4,8]);
   }

   for (a=[-1,1]) translate([a*(platWidth/2-dHole),mountHeight,16])
      rotate([90,0,0]) cylinder(h=10,r=rHole,$fn=80,center=true);
}}

module footpad(r) { // pad to help a part stick to plate for 3D printer
   cylinder(h=layer1bias,r1=r,r2=r-.3,$fn=11); }

if (WITH_BRIM) {
union() { color("Cyan") hull() {
translate([-Bx,0,0]) footpad(12);
translate([ Bx,0,0]) footpad(12);
translate([-PCBwidth/2, platformHeight-2,0]) footpad(12);
translate([ PCBwidth/2, platformHeight-2,0]) footpad(12);
}
translate([0,0,layer1bias/2])
   motorDriverStand(Bx,Bhole,platformHeight,PCBwidth,HoleInset,PCBhole);
}} else {
  difference() {
    motorDriverStand(Bx,Bhole,platformHeight,PCBwidth,HoleInset,PCBhole);
    translate([0,0,-4]) cube([200,200,8],center=true); }
}


final touches on the model

final touches on the model

module rounded_surface_(size, r)
{
  assert(len(size)==2);
  hull()
    for(dx=[r, size[0]-r])
      for(dy=[r, size[1]-r])
        translate([dx, dy, r])
          sphere(r=r, $fn=r*20);
}

module rounded_half_surface_(size, r)
{
  assert(len(size)==2);
  translate([0, 0, -r])
    difference()
    {
      rounded_surface_(size, r);
      cube([size[0], size[1], r]);
    }
}

// element for holding a single brush
module holder()
{
  translate([-4/2, 0, 0])
    cube([4, 7, 17]);
  translate([0, 0, 17-2])
  {
    rotate([-90, 0, 0])
      cylinder(r=(8-1.5)/2, h=7+2+7, $fn=50);
    translate([0, 7, 0])
      rotate([-90,0,0])
        cylinder(r=(3-1)/2, h=14+2, $fn=30);
  }
}

module whole_holder(names)
{
  assert( len(names) > 0 );
  r=5;
  spacing=20;
  total_len=2*(r+3) + spacing*(len(names)-1) + 4;

  // plate
  translate([0, r+2, -r])
    rotate([90, 0, 0])
      difference()
      {
        rounded_surface_([total_len, 35], r/2+1);
        cube([total_len, r, r*2]);
      }
  // back wall
  rounded_half_surface_([total_len, 50], r);
  // holders
  for(i=[0:len(names)-1])
    translate([r+3+4/2, 25, r-1] + i*[spacing, 0, 0])
      holder();
}

whole_holder(["John", "Jane", "Jackob"]);

module rounded_surface_(size, r)
{
  assert(len(size)==2);
  hull()
    for(dx=[r, size[0]-r])
      for(dy=[r, size[1]-r])
        translate([dx, dy, r])
          sphere(r=r, $fn=r*3); // TODO: r*10!
}

module rounded_half_surface_(size, r)
{
  assert(len(size)==2);
  translate([0, 0, -r])
    difference()
    {
      rounded_surface_(size, r);
      cube([size[0], size[1], r]);
    }
}

// element for holding a single brush
module holder()
{
  translate([-3/2, 0, 0])
    cube([3, 7, 17]);
  translate([0, 0, 17-2])
  {
    rotate([-90, 0, 0])
      cylinder(r=(8-1.5)/2, h=7+2+7, $fn=50);
    translate([0, 7, 0])
      rotate([-90,0,0])
        cylinder(r=(3-1)/2, h=14+2, $fn=30);
  }
}

module whole_holder(names)
{
  // plate
  translate([0, 5+1, -5])
    rotate([90, 0, 0])
      difference()
      {
        rounded_surface_([36, 35], 3);
        cube([36, 5, 3*2]);
      }
  // back wall
  rounded_half_surface_([36, 50], 5);
  // holders
  for(i=[0:len(names)-1])
    translate([7+i*20, 25, 4])
      holder();
}

whole_holder(["John", "Jane", "Jackob"]);


Adding Apex details and ESC

Adding Apex details and ESC

use <hcsr04.scad>

module wheel() {
    color("black") rotate([90, 90, 0]) difference() {
        #cylinder(d=47, h=23, center=true);
        cylinder(d=30, h=26, center=true);
    }
}

module base() {

    // 4 wheels
    translate([77.5, 60, 47/2]) wheel();
    translate([-77.5, 60, 47/2]) wheel();
    translate([77.5, -60, 47/2]) wheel();
    translate([-77.5, -60, 47/2]) wheel();

    // front axe assemby - slightly longer
    translate([77.5-5, 0, 47/2]) color("gray") cube(size=[25, 103, 26], center=true);
    // rear axe assemby
    translate([-77.5, 0, 47/2]) color("gray") cube(size=[26, 97, 26], center=true);

    color("gray") translate ([0, 0, 12]) {

        // base plate
        linear_extrude(height = 2) base_plate();
        linear_extrude(height = 7) difference() {
            base_plate();
            offset(-2) base_plate();
        }

        // shaft
        translate ([0, 0, 23/2]) cube(size=[158, 12, 23], center=true);
        //shaft ribs
        translate ([14, 4, 23]) cube(size=[65, 2, 4], center=false);
        translate ([14, -6, 23]) cube(size=[65, 2, 4], center=false);
        translate ([0, 0, 23/2]) cube(size=[158, 12, 23], center=true);
        translate ([-79, 4, 23]) cube(size=[43, 2, 6], center=false);
        translate ([-79, -6, 23]) cube(size=[43, 2, 6], center=false);
        // servo
        linear_extrude(height = 15)  polygon([
            [29,0], [79,0],
            [79,-23], [70,-23],[49,-40],[29,-40]
        ]);

        // motor
        translate ([-79+30, -16, 23/2+2]) rotate([0, 90, 0]) cylinder(d=23, h=32, center=false);

        // gear
        translate ([-79+23, 0, 34/2]) rotate([0, 90, 0]) cylinder(d=34, h=6, center=false);

        // battery
        translate ([-5/2, 30/2+7, 16/2+2]) cube(size=[84, 30, 16], center=true);

        // battery holder
        translate ([-79+23, 20, 0]) cylinder(d=7, h=26, center=false);
        translate ([79-29, 20, 0]) cylinder(d=7, h=26, center=false);
        translate ([-5/2, 20, 22]) cube(size=[110, 13, 2], center=true);

        // front shocks
        translate ([79, 0, 0]) rotate([90, 0, 90]) linear_extrude(height = 16)
            polygon([[23,41], [-23,41],[-38,0],[38,0]]);

        // rear shocks
        translate ([-79-16, 0, 0]) rotate([90, 0, 90]) linear_extrude(height = 16)
            polygon([[25,45], [-25,45],[-38,0],[38,0]]);
    }
}

module base_plate() {
    polygon([
        [-79,25], [-70,25],[-54,40],[49,40],[70,23], [79,23],
        [79,-23], [70,-23],[49,-40],[-54,-40],[-70,-25], [-79,-25]
    ]);
}

module platform() {

    color("black") translate ([0, 0, 46]) difference() {
        union() {
            #linear_extrude(height = 3)
                difference() {
                    offset(20) offset(-20) base_plate();

                    offset(5) offset(-10) polygon([
                        [-54,40],[29,40],[29,-40],[-54,-40]
                    ]);
                }

            // shock tower mount points
            translate ([-79, -25, 0]) cube(size=[5, 50, 11], center=false);
            translate ([79-5, -23, 0]) cube(size=[5, 46, 7], center=false);

            // joint mount plates to body
            translate ([-79, -25, 0]) cube(size=[15, 50, 3], center=false);
            translate ([79-15, -23, 0]) cube(size=[15, 46, 3], center=false);
        }

        // board mount holes
        #translate ([-54, 31, 0])  cylinder(d=3.2, h=10, center=true);
        #translate ([-54, -31, 0]) cylinder(d=3.2, h=10, center=true);
        #translate ([29, 31, 0])   cylinder(d=3.2, h=10, center=true);
        #translate ([29, -31, 0])  cylinder(d=3.2, h=10, center=true);
    }
}

module board() {

    // base
    color("yellow") translate ([-12.5, 0, 45]) cube(size=[90, 70, 1], center=true);

    // teensy
    color("green") translate ([-25, 0, 45+5]) cube(size=[20, 63, 10], center=true);

    // MPU-9250
    color("red") translate ([0, 15, 45+5]) cube(size=[20, 20, 10], center=true);
}

module vsonar() {

    // vertical sonar
    translate ([0, -10, 45]) rotate([0, 90, 0]) hcsr04();

    // mount plate
    color("gray") translate ([1.5, -10, -6]) cube(size=[3, 20, 51], center=false);
    color("gray") translate ([-8.5, -10, -6]) cube(size=[10, 20, 5], center=false);

    // sonar ray
    //color("white") translate ([20+1000/2, 0, 22.5]) rotate([0, 90, 0]) cylinder(d1=40, d2=520,h=1000, center=true);
}

module esc() {
    color("green") cube(size=[36, 26, 2], center=true);
    color("black") translate ([36/2, 0, 0]) rotate([0, 90, 0]) cylinder(d=8, h=16, center=false);

    // esc support box ?
    // hcolor("black") translate ([0, 0, -11]) cube(size=[30, 20, 20], center=true);
}

module hsonar() {

    // horizontal sonar
    translate ([0, -45/2, 0]) rotate([90, 0, 90]) hcsr04();

    // mount plate
    color("gray") translate ([1.5, -45/2, -6]) cube(size=[3, 45, 26], center=false);
    color("gray") translate ([-8.5, -45/2, -6]) cube(size=[10, 45, 5], center=false);

    // sonar ray
    //color("white") translate ([20+1000/2, 0, 10]) rotate([0, 90, 0]) cylinder(d1=40, d2=520,h=1000, center=true);
}

module car()
{
    base();
    platform();
    board();

    //translate ([10, -23, 35]) esc();
    translate ([-10, 0, 40]) rotate([0, 0, 180]) esc();
}

// full model - vertical sonars
module fullv() {
    car();

    translate ([68, 0, 55]) vsonar();
    translate ([60, 25, 55]) rotate([0, 0, 30]) vsonar();
    translate ([60, -25, 55]) rotate([0, 0, -30]) vsonar();
    translate ([35, 35, 55]) rotate([0, 0, 60]) vsonar();
    translate ([35, -35, 55]) rotate([0, 0, -60]) vsonar();
}

// full model - horizontal sonars
module fullh() {
    car();

    translate ([68, 0, 55]) hsonar();
    translate ([40, 35, 55]) rotate([0, 0, 30]) hsonar();
    translate ([40, -35, 55]) rotate([0, 0, -30]) hsonar();
    translate ([-10, 35, 55]) rotate([0, 0, 60]) hsonar();
    translate ([-10, -35, 55]) rotate([0, 0, -60]) hsonar();
}

fullv();

use <hcsr04.scad>

module wheel() {
    color("black") rotate([90, 90, 0]) difference() {
        #cylinder(d=47, h=23, center=true);
        cylinder(d=30, h=26, center=true);
    }
}

module base() {

    // 4 wheels
    translate([77.5, 60, 47/2]) wheel();
    translate([-77.5, 60, 47/2]) wheel();
    translate([77.5, -60, 47/2]) wheel();
    translate([-77.5, -60, 47/2]) wheel();

    // front axe assemby - slightly longer
    translate([77.5-5, 0, 47/2]) color("gray") cube(size=[25, 103, 26], center=true);
    // rear axe assemby
    translate([-77.5, 0, 47/2]) color("gray") cube(size=[26, 97, 26], center=true);

    // base plate
    color("gray") translate ([0, 0, 12])
         linear_extrude(height = 20) base_plate();

    // front shocks
    color("gray") translate ([79, 0, 12]) rotate([90, 0, 90]) linear_extrude(height = 16)
        polygon([[23,41], [-23,41],[-38,0],[38,0]]);

    // rear shocks
    color("gray") translate ([-79-16, 0, 12]) rotate([90, 0, 90]) linear_extrude(height = 16)
        polygon([[25,45], [-25,45],[-38,0],[38,0]]);
}

module base_plate() {
    polygon([
        [-79,25], [-70,25],[-54,40],[49,40],[70,23], [79,23],
        [79,-23], [70,-23],[49,-40],[-54,-40],[-70,-25], [-79,-25]
    ]);
}

module platform() {

    color("black") translate ([0, 0, 46]) difference() {
        union() {
            #linear_extrude(height = 3)
                difference() {
                    offset(20) offset(-20) base_plate();

                    offset(5) offset(-10) polygon([
                        [-54,40],[29,40],[29,-40],[-54,-40]
                    ]);
                }

            // shock tower mount points
            translate ([-79, -25, 0]) cube(size=[5, 50, 11], center=false);
            translate ([79-5, -23, 0]) cube(size=[5, 46, 7], center=false);

            // joint mount plates to body
            translate ([-79, -25, 0]) cube(size=[15, 50, 3], center=false);
            translate ([79-15, -23, 0]) cube(size=[15, 46, 3], center=false);
        }

        // board mount holes
        #translate ([-54, 27, 0])  cylinder(d=3.2, h=10, center=true);
        #translate ([-54, -27, 0]) cylinder(d=3.2, h=10, center=true);
        #translate ([29, 20, 0])   cylinder(d=3.2, h=10, center=true);
        #translate ([29, -20, 0])  cylinder(d=3.2, h=10, center=true);
    }

    // board
    color("yellow") translate ([-12.5, 0, 45]) cube(size=[90, 70, 1], center=true);

    // teensy
    color("green") translate ([-25, 0, 45+5]) cube(size=[20, 63, 10], center=true);

    // MPU-9250
    color("red") translate ([0, 15, 45+5]) cube(size=[20, 20, 10], center=true);
}

module vsonar() {

    // vertical sonar
    translate ([0, -10, 45]) rotate([0, 90, 0]) hcsr04();

    // mount plate
    color("gray") translate ([1.5, -10, -6]) cube(size=[3, 20, 51], center=false);
    color("gray") translate ([-8.5, -10, -6]) cube(size=[10, 20, 5], center=false);

    // sonar ray
    //color("white") translate ([20+1000/2, 0, 22.5]) rotate([0, 90, 0]) cylinder(d1=40, d2=520,h=1000, center=true);
}

module hsonar() {

    // horizontal sonar
    translate ([0, -45/2, 0]) rotate([90, 0, 90]) hcsr04();

    // mount plate
    color("gray") translate ([1.5, -45/2, -6]) cube(size=[3, 45, 26], center=false);
    color("gray") translate ([-8.5, -45/2, -6]) cube(size=[10, 45, 5], center=false);

    // sonar ray
    //color("white") translate ([20+1000/2, 0, 10]) rotate([0, 90, 0]) cylinder(d1=40, d2=520,h=1000, center=true);
}

// ful model - vertical sonars
module fullv() {
    base();
    platform();

    translate ([68, 0, 55]) vsonar();
    translate ([60, 25, 55]) rotate([0, 0, 30]) vsonar();
    translate ([60, -25, 55]) rotate([0, 0, -30]) vsonar();
    translate ([35, 35, 55]) rotate([0, 0, 60]) vsonar();
    translate ([35, -35, 55]) rotate([0, 0, -60]) vsonar();
}

// ful model - horizontal sonars
module fullh() {
    base();
    platform();

    translate ([68, 0, 55]) hsonar();
    translate ([40, 35, 55]) rotate([0, 0, 30]) hsonar();
    translate ([40, -35, 55]) rotate([0, 0, -30]) hsonar();
    translate ([-10, 35, 55]) rotate([0, 0, 60]) hsonar();
    translate ([-10, -35, 55]) rotate([0, 0, -60]) hsonar();
}

fullv();


A model was added of a sample Borg ship.

/**
 * the box for the Borg costume is 18" cubed.
 *
 * 1 inch is 25.4mm
 */
sideLength = 25.4 * 18;

sheetWidth = 203.2;
sheetHeight = 271.4;

borgShip();

module borgShip()
{
	union()
	{
		cube([sideLength, sideLength, sideLength]);

		pokePanel();

		diegoPanel1();

		soundPanel();

		diegoPanel2();
	}
}

module diegoPanel1()
{
	// bottom right
	color("red")
	translate([sideLength-sheetHeight, 0, sideLength])
	rotate(a=[90, 90, 0])
	sheet();

	// bottom left
	color("red")
	rotate(a=[90, 0, 0])
	sheet();

	// bottom right
	color("red")
	translate([sideLength-sheetHeight, 0, sheetWidth])
	rotate(a=[90, 90, 0])
	sheet();
}

module diegoPanel2()
{
	translateY = sideLength+2;

	// top left
	color("orange")
	translate([sideLength-sheetHeight, translateY, sideLength])
	rotate(a=[90, 90, 0])
	sheet();

	// bottom left
	color("orange")
	translate([sideLength-sheetHeight, translateY, sheetWidth])
	rotate(a=[90, 90, 0])
	sheet();

	// bottom right
	color("orange")
	translate([0, translateY, 0])
	rotate(a=[90, 0, 0])
	sheet();
}

module pokePanel()
{
	pokeTranslate = [0,90,0];

	// top left
	color("blue")
	translate([sideLength, 0, sideLength])
	rotate(a=pokeTranslate)
	sheet();

	// top right
	color("blue")
	translate([sideLength, sideLength-sheetHeight, sideLength])
	rotate(a=pokeTranslate)
	sheet();

	// bottom left
	color("blue")
	translate([sideLength, 0, sheetWidth])
	rotate(a=pokeTranslate)//[0,90,0])
	sheet();

	// bottom right
	color("blue")
	translate([sideLength, sideLength-sheetHeight, sheetWidth])
	rotate(a=pokeTranslate)
	sheet();
}

/**
 * printable area on letter sized paper (according to http://support-sg.canon-asia.com/contents/SG/EN/8200392300.html#2)
 *
 * 203.2 x 271.4 mm
 */
module sheet()
{
	cube([sheetWidth, sheetHeight, 2]);
}

/**
 * This panel holds the LS31FL3137 (is this right???) for sound reactive charlie plexing an
 * LED matrix.
 */
module soundPanel()
{
	horizRotate = [0,-90,0];

	verticalRotate = [-90, 180, 90];

	// top left
	color("green")
	translate([-30,sideLength-sheetHeight,sideLength-sheetWidth])
	rotate(a=horizRotate)
	sheet();

	// top right
	color("green")
	translate([0, sheetWidth, sideLength-sheetHeight])
	rotate(a=verticalRotate)
	sheet();

	// top right
	color("green")
	translate([0, sideLength, 0])
	rotate(a=verticalRotate)
	sheet();

	// bottom right
	color("green")
	translate([-30,0,0])
	rotate(a=horizRotate)
	sheet();
}

error: pathspec 'OpenSCAD/cosplay/star-trek/borg/ship/borg-ship.scad' did not match any file(s) known to git


Drop any mention of feet or inlets, neither of which we'll want.

// Raspberry Pi Case
// Hans Harder 2012
//
// Warning: this is based on the Beta board dimensions...
//          so production models can be slightly different
//          for instance SD card holder height and USB socket dimensions
//
// Since all connectors stick out, case is split on HDMI height
// so the power and sdcard holder goes in first and then the pcb drops into place.
//
// v2: Adapted version after some suggestions from David...
//     removed feet, made both surface flat
// v3: Added fliptop option and smooth the corners of the box
// v4: Different levels of case split (make it 3d printable, thx David)
//     Looks strange but it fits...
//     Added frame mode (so no bottom and top deck)
//     Moved screw locations due to split and added some support structures
//     Unsure about 2nd screw location in combination with GPIO pins
// v5  relocated a lot of code in modules
//     SDslot location was not calculated correctly
// v6  Added pcb drawing
//     Added colors
//     Cut out better so there is no debris around
//     DRAwvars and options seperated, so it is easier to do 1 part
//     Make a low as possible case, let USB stick out
// v7  PCB options
//     Low level case optimisations
//     SD card location alterations
// v8  adapted pcb dimensions, board is really 56mm width
//     adapted support studs, moved some due to component location
//     components locations adapted
// v9  Added logo in seperate dxf file
//     Option added to put logo in middle or using whole deck
//     beautified code, kr style
// v10 Added logosunken and bottomsupport structures
//     Bottom supports are located where no components are located
//       so the pcb is not only supported from the sides
//     Well got my case, so based on what I see I changed:
//     case split level changed, should be better when printed on a reprap
//     Removed screwholes (far to small) for fastening top and added some more studs
//     Made frontstud a little thicker
// v11 Different splitlevel (more simple) on back
//     keep a little margin on back split, so that top and bottom always fit
//     added openlogo option
// v12 Different component locations/sizes
//     keep a little margin on component holes
//     pcbsize to 57.0 x 86.0   (actual it is 56.17 x 85.0)
//     made casestuds wider and added 2 minor holes for self tapping screws
// v13 skip this one.... :)
// v14 Production board measurements...
//	   small differences, sometimes components are soldered differently
//     keep more space
//     should fit like a glove...
// v15 moved the rca and snd a bit to get them more centered
//     Thanks to lincomatic at Thingiverse
//     Added option for GPIO side hole in bottom or top
//     Added showing GPIO pins with component drawing
//
// All parts are draw as default just disable the ones you don't want
DRAWfull        = 0;
DRAWtop         = 1;
DRAWbottom      = 1;
DRAWpcb         = 0;

GPIOHOLE        = 2;        // GPIO opening in :  1=bottom   2=top
GPIOsize        = 2;        // define height of gpiohole

// select how the case should look like
topframe    = false;        // if false, underneath values determines how
topholes    = true;
// ---- holes sizes
holeofs=2;
holesiz=3;
holestep=10;
noholes=6;					// 12 for top,  20 for bottom
holelen=24;
topmiddle   = false;

bottomframe = false;        // if false, underneath values determines how
bottomholes = false;
bottomscrew = false;
bottomsupport = false;         // Added extra support locations for pcb
bottomclick   = true;
bottompcb    = false;		    // just a pcb holder without a top

box_thickness = 2.0;            // minimum = 1.0
inside_h      = 12.5;           // 12.1 = lowprofile    16.5 is full height
pcb_h         = 5.6;            // height needed for SD holder and solder points of pcb
//pcb_h         = box_thickness+3.5;    // height needed for SD holder and solder points of pcb
// 4.1 = no deck, box_thickness+3.5 is with deck

// just some colors to see the difference
CASEcolor="Maroon";
CONNcolor="Silver";

// Define Raspberry Pi pcb dimensions in mm
inside_l = 86.0;                //85.00 is largest length reported, so a bit room on each side
inside_w = 57.2;                //56.17 is largest width  reported, so a bit room on each side
pcb_thickness = 1.7;

// Coordinates based on RJ45 corner = 0,0,0
// pcb connectors and locations. Based on Beta Board measurements of Gert and a real RPi

// Connectors
Crj45_x=2.0;			 //2.0
Crj45_y=-1;
Crj45_w=16.4;			// 15.4
Crj45_d=21.5;           //21.8
Crj45_h=13.8;

Cusb_x=24.5;            // 23.9
Cusb_y=-7.7;
Cusb_w=13.9;            // 13.3
Cusb_d=19.0;			// 17.2
Cusb_h=16.0;

Cpwr_x=3.25;				// 3.5 3.6
Cpwr_y=80.9;
Cpwr_w=8.8;				// 7.8 7.6
Cpwr_d=5.6;
Cpwr_h=2.6;

Csd_x=16.7;
Csd_y=inside_l-24.0;            // 30 mm is the length of a  sdcard
Csd_w=27.8;
Csd_d=29.0;
Csd_h=3.4;                  // under pcb

Chdmi_x=-1.2;
Chdmi_y=32.0;               // 32.4  if 15.1
Chdmi_w=11.4;
Chdmi_d=17.8;				  // 15.7 15.3
Chdmi_h=6.4;

Csnd_x=inside_w - 11.4;
Csnd_y=16.0;
Csnd_w=11.4;
Csnd_d=10.0;
Csnd_h=10.5;
Csnd_r=6.7;
Csnd_z=3.0;
Csnd_l=3.4;

Crca_x=inside_w - 10.0 - 2.1;
Crca_y=34.2;                // 34.6 was 35.2
Crca_w=10.0;
Crca_d=10.4;                 // 9.8
Crca_h=13.0;
Crca_r=8.6;
Crca_z=4;
Crca_l=10;                  // wild guess

pcb_c = pcb_h + pcb_thickness;            // component height
casesplit = pcb_c + Chdmi_h;              // split case at top of hdmi connector
echo("casesplit=",casesplit);
echo("case dimensions: w=",box_w," l=",box_l," h=",box_h);

// side stud sizes for supporting pcb
stud_w = 2;
stud_l = 4;

// calculate box size
box_l  = inside_l + (box_thickness * 2);
box_w  = inside_w + (box_thickness * 2);
box_h  = pcb_c + (pcb_thickness * 2) + inside_h;
box_w1 = box_thickness;
box_w2 = box_w - box_thickness;
box_l1 = box_thickness;
box_l2 = box_l - box_thickness;
box_wc = box_w / 2;                 // center width
box_lc = box_l / 2;                 // center length
box_t2 = box_thickness / 2.0;           // half box_thickness
middle = true;
// rounded corners
corner_radius = box_thickness*2;

// count no of items to draw
DRAWtotal = DRAWfull + DRAWtop + DRAWbottom;

// ====================================================== DRAW items
// if one  draw it centered
if (DRAWtotal == 1) {
    translate(v = [ -box_w/2, -box_l / 2, 0]) {
        if (DRAWfull ) {
           draw_case(0,1);
           translate(v=[0,0,0.2]) draw_case(1,0);
        }
        if (DRAWtop   ) {
            rotate(a=[0,180,0]) translate(v=[-box_w,0,-box_h]) draw_case(0,1);
        }
        if (DRAWbottom) draw_case(1,0);
    }
} else {
// draw each one on there one location
    if (DRAWfull)   {
        translate(v = [ box_w+20, -box_l / 2, 0]) {
            draw_case(1,0);
            translate(v=[0,0,0.2]) draw_case(0,1);
        }
    }
    if (DRAWbottom) {
        translate(v = [ 5, 5, 0]) draw_case(1,0);
    }
    if (DRAWtop)    {
        translate(v = [ - 5,  5, box_h])  rotate(a=[0,180,0]) draw_case(0,1);
    }
}

// ======================================================= END of draw
// Module sections

module make_deckholes(no,w,d,step) {
for ( i = [0 : 1 : no - 1] ) {
        translate(v=[w/2,(i*step)+(step/2),box_thickness/2]) cube([w,d, box_thickness+18], center=true);
    }
}

// create a deck or insert
module make_deck(w,d,z,hole_no,hole_size,hole_step) {
    hole_w=(w - 12) / 2;      // change 12 for middle piece size
    ofs1=4;
    ofs2=w - ofs1 - hole_w;
    hole_ofs= ((d - hole_no*hole_step) / 2) - box_thickness/2;
    translate(v = [(box_w-w)/2, (box_l-d)/2,z]) {
        color(CASEcolor) {
            echo("deck : z=",z," w=",w+0.01," d=",d+0.01);
            difference() {
                cube([w, d, box_thickness], center = false);
                if (top && holes && hole_size>0) {
                    translate(v=[-1,hole_ofs+holeofs,-0.1]) make_deckholes(noholes,holelen,holesiz,holestep);
                    translate(v=[w/2-2,hole_ofs+holeofs,-0.1]) make_deckholes(noholes,holelen,holesiz,holestep);
                }
                if (screwholes) {
                    // --- 2x screw holes in bottom for mounting
                    translate(v = [w/2 - 4, 10-4, -1]) cube([8, 3, 5], center = false);
                    translate(v = [w/2 - 4, 10-3, -1]) cylinder(r=3, h=8, $fn=100, center=true);
                    // 2nd screw hole
                    translate(v = [w/2 - 3, d - 10 +3, -1]) cube([8, 3, 5], center = false);
                    translate(v = [w/2 + 4, d - 10 +4, -1]) cylinder(r=3, h=8, $fn=100);
                    if (!holes) {
                        // middle screw hole
                        translate(v = [w/2 - 4, d/2    , -1]) cube([8, 2, 5], center = false);
                        translate(v = [w/2 - 4, d/2 + 1, -1]) cylinder(r=2, h=8, $fn=100);
                    }
                }
                if (holes && !top) {
                    translate(v=[(w-hole_w)/2,holeofs,-0.1]) make_deckholes(noholes,hole_w,holesiz,holestep);
                }
            }
            color(CASEcolor) {
                if (top && holes) {
                    translate(v = [w/2-box_thickness,12,0]) cube([4,d-13, box_thickness], center = false);
                }
                if (middle) {
                    // --- solid area for sticker
                    translate(v = [w/2-10,d/2-5-box_thickness/2,0]) {
                        cube([20,20, box_thickness], center = false);
                    }
                }
            }
        }
    }
}

module rounded_corner(x,y,rx,ry,cx,cy) {
    translate(v = [x, y, -1]) {
        difference() {
            translate(v=[rx,ry,0])    cube([corner_radius,corner_radius,box_h+2], center=false);
            translate(v=[cx, cy, -1]) cylinder(r=corner_radius, h=box_h+2, $fn=100);
        }
    }
}

module make_topcomponents() {
    color(CONNcolor) translate(v=[box_w1,box_l1,pcb_c]) {
        translate(v=[Crj45_x,Crj45_y,0]) cube([Crj45_w,Crj45_d,Crj45_h],center=false);
        translate(v=[Cusb_x,Cusb_y,0])   cube([Cusb_w,Cusb_d,Cusb_h],center=false);
        translate(v=[Cpwr_x,Cpwr_y,0])   cube([Cpwr_w,Cpwr_d,Cpwr_h],center=false);
        translate(v=[Chdmi_x,Chdmi_y,0]) cube([Chdmi_w,Chdmi_d,Chdmi_h],center=false);

        //SND
        translate(v=[Csnd_x,Csnd_y,0]) cube([Csnd_w+0.1,Csnd_d,Csnd_h],center=false);
        translate(v=[Csnd_x+Csnd_w,Csnd_y+Csnd_d/2,Csnd_z+Csnd_r/2]) rotate(a=90,v=[0,1,0]) cylinder(r=Csnd_r/2, h=Csnd_l, $fn=100);

        //RCA
        translate(v=[Crca_x,Crca_y,0]) cube([Crca_w+0.2,Crca_d,Crca_h],center=false);
        translate(v=[Crca_x+Crca_w,Crca_y+Crca_d/2,Crca_z+Crca_r/2]) rotate(a=90,v=[0,1,0]) cylinder(r=Crca_r/2, h=Crca_l+0.1, $fn=100);
    }
    for ( i = [0 : 1 : 12] ) {
        color("black") translate(v=[box_w2-6.6,box_l2-1-34+(i*2.54),pcb_c]) cube([5.08,2.53,2.5]);
        color("Gainsboro") translate(v=[box_w2-6.6+0.97,box_l2-1-34+(i*2.54)+0.95,pcb_c-3])  cube([0.6,0.6,11.5]);
        color("Gainsboro") translate(v=[box_w2-6.6+3.61,box_l2-1-34+(i*2.54)+0.95,pcb_c-3])  cube([0.6,0.6,11.5]);

    }
}

module make_connholes() {
    // =================================== cut outs, offset from 0,0
    //RJ45:    2mm offset, 15.5mm width, 13.1mm height
    set_cutout(box_w1+Crj45_x,box_l1+Crj45_y-3,pcb_c,   Crj45_w+0.1,Crj45_d+3,Crj45_h);
    //usb:  23.9mm offset, 13.3mm width, 15.4mm height
    set_cutout(box_w1+Cusb_x,box_l1+Cusb_y,pcb_c,   Cusb_w,Cusb_d,Cusb_h+0.1);

    //power: 3.4mm offset,    8mm width,    3mm height
    set_cutout(box_w1+Cpwr_x,box_l1+Cpwr_y,pcb_c,   Cpwr_w,Cpwr_d+4,Cpwr_h+0.01);
    //sd:   15mm offset,   28mm width,    3.5mm height under pcb
    if (pcb_h >= (Csd_h+1.5) ) {
        set_cutout(box_w1+Csd_x-0.3,box_l2-28,pcb_h-Csd_h,Csd_w+0.6,box_thickness+30,Csd_h+0.1);
    } else {
        set_cutout(box_w1+Csd_x-0.3,box_l2-32,pcb_h-20,Csd_w+0.6,40,20.01);
    }
    //HDMI: 32.9mm offset,  15.3mm width,   6.3mm height
    set_cutoutv(box_w1+Chdmi_x-3,box_l1+Chdmi_y,pcb_c,    Chdmi_w+3.1,Chdmi_d,Chdmi_h+0.1);

    // snd:   14mm offset,  12mm width,   8.2 mm height
    set_cutout(box_w1+Csnd_x,box_l1+Csnd_y,pcb_c+2,    Csnd_w+7,Csnd_d,Csnd_h-2);

    // RCA:   35mm offset,  10mm width     10mm height
    translate(v=[box_w1+Crca_x+Crca_w,box_l1+Crca_y+Crca_d/2,pcb_c+Crca_z+Crca_r/2]) {
        rotate(a=90,v=[0,1,0]) cylinder(r=Crca_r/2+1, h=Crca_l, $fn=100);
    }
    translate(v=[box_w1+Crca_x+Crca_w,box_l1+Crca_y+(Crca_d-Crca_r)/2-1,pcb_c+Crca_z-1]) {
        cube([5,Crca_r+2,Crca_r/2+1]);
    }
}

module make_pcb() {
    translate(v=[box_w1,box_l1,pcb_h]) {
        color("darkgreen") cube([inside_w,inside_l,pcb_thickness], center=false);
    }
    color(CONNcolor) {
        translate(v=[box_w1+Csd_x,box_l1+Csd_y,pcb_h-Csd_h]) cube([Csd_w,Csd_d,Csd_h],center=false);
    }
    make_topcomponents();
}

// put extra supports on free spaces, used beta board image
module make_supports() {
    if (!bottomframe) {
        translate(v=[box_w1+10 ,box_l1+28,0.1]) cube([3, 2,pcb_h-0.1]);
        translate(v=[box_w2-7.5,box_l1+28,0.1]) cube([3, 2,pcb_h-0.1]);

        translate(v=[box_w1+7  ,box_l2-35,0.1])  cube([5, 5,pcb_h-0.1]);
        translate(v=[box_w2-13 ,box_l2-35,0.1])  cube([5, 5,pcb_h-0.1]);

        translate(v=[box_w1+12 ,box_l2-16,0.1])  cube([1.5 ,5,pcb_h-0.1]);
        translate(v=[box_w2-9  ,box_l2-16,0.1])  cube([1.5 ,5,pcb_h-0.1]);
    }
}

// width,depth,height,boxthickness,ledgethickness
module make_case(w,d,h,bt,lt) {
    dt=bt+lt;    // box+ledge thickness
    bt2=bt+bt;    // 2x box thickness
    // Now we just substract the shape we have created in the four corners
    color(CASEcolor) difference() {
        cube([w,d,h], center=false);
        if (rounded) {
            rounded_corner(-0.1,d+0.1, 0             ,-corner_radius,  corner_radius,-corner_radius);
            rounded_corner(w+0.1,d+0.1, -corner_radius,-corner_radius, -corner_radius,-corner_radius);
            rounded_corner(w+0.1,-0.1, -corner_radius,0             , -corner_radius, corner_radius);
            rounded_corner(-0.1,-0.1, 0             ,0             ,  corner_radius, corner_radius);
        }
        // empty inside, but keep a ledge for strength
        translate(v = [bt, bt, dt])   cube([w-bt2, d-bt2, h-(dt*2)], center = false);
        translate(v = [dt,dt,bt])     cube([w-(dt*2), d-(dt*2), h-bt2], center = false);
        // remove bottom and top deck
        translate(v = [box_thickness+2, box_thickness+5,-2]) {
            cube([inside_w-4, inside_l-10, box_h+4], center = false);
        }
    }
    if (!topframe) {
        make_deck(inside_w-4,inside_l-4,box_h-box_thickness, 12,3,5, holes=topholes,middle=topmiddle,screwholes=false,top=true);
    }
    if (!bottomframe) {
        make_deck(inside_w-4,inside_l-4,0, 12,3,5, holes=bottomholes,screwholes=bottomscrew,middle=false,top=false);
        if (bottomsupport) {
            make_supports();
        }
    }
}

module make_stud(x,y,z,w,h,l) {
    translate(v = [x, y, z]) cube([w, l, h], center = false);
}

module set_cutout(x,y,z,w,l,h) {
    color(CASEcolor)    translate(v = [x+(w/2), y+(l/2), z+(h/2)]) cube([w+0.4, l+0.2, h+0.2], center = true);
}

module set_cutoutv(x,y,z,w,l,h) {
    color(CASEcolor)    translate(v = [x+(w/2), y+(l/2), z+(h/2)]) cube([w+0.2, l+0.4, h+0.2], center = true);
}

module draw_pcbhold() {
  if (bottomclick) {
    color(CASEcolor) {
        translate(v=[0  ,22,2]) cube([box_thickness,4,pcb_c]);
        translate(v=[box_w1-0.1  ,22.5,pcb_c+0.1]) {
            difference() {
                cube([1, 3,2]);
                translate(v=[1,-0.1,0])  rotate(a=-30, v=[0,1,0])  cube([1.6, 3.2, 4]);
            }
        }
        translate(v=[0  ,60.5,2]) cube([box_thickness,5,pcb_c]);
        translate(v=[box_w1-0.1  ,61.5,pcb_c+0.1]) {
            difference() {
                cube([1,3,2]);
                translate(v=[1,-0.1,0])  rotate(a=-30, v=[0,1,0])  cube([1.6, 3.2, 4]);
            }
        }
        translate(v=[box_w2,29.5,2]) cube([box_thickness,4,pcb_c]);
        translate(v=[box_w2+0.1  ,30+3,pcb_c+0.1]) {
            rotate(a=180, v=[0,0,1]) difference() {
                cube([1, 3,3]);
                translate(v=[1,-0.1,0])  rotate(a=-30, v=[0,1,0])  cube([1.6, 3.2, 4]);
            }
        }
        translate(v=[box_w2,60.5,2]) cube([box_thickness,5,pcb_c]);
        translate(v=[box_w2+0.1  ,61+3.5,pcb_c+0.1]) {
            rotate(a=180, v=[0,0,1]) difference() {
                cube([1,3,3]);
                translate(v=[1,-0.1,0])  rotate(a=-30, v=[0,1,0])  cube([1.6, 3.2, 4]);
            }
        }
    }
  }
}

module split_top() {
    split1=box_w1+Cpwr_x;
    split2=split1+Cpwr_w;
    split3=box_w1+Csd_x - 12;   // min 16.5+28
    split4=box_w2 - 7;
    // Different splitlevels for the shells
    // 1st half on split level
    translate(v = [-1,  -1, casesplit-0.2])    cube([box_w+2, 21, 0.4], center = false);
    // back on 3 different levels
    translate(v = [-1,  20, casesplit-0.2])    cube([split1+1     , box_l, 0.4], center = false);
    translate(v = [split2, 20, pcb_c-0.2])     cube([split3-split2, box_l, 0.4], center = false);
    translate(v = [split3, 20, pcb_h-0.2])     cube([split4-split3, box_l, 0.4], center = false);
    translate(v = [split4, 20, casesplit-0.2]) cube([20           , box_l, 0.4], center = false);
}

module remove_top() {
    split1=box_w1+Cpwr_x;
    split2=split1+Cpwr_w;
    split3=box_w2 - 12;
    possd1=box_w1 + Csd_x - 0.3;
    widesd1=Csd_w+0.6;
    // Different splitlevels for the shells
    // 1st half on split level
    translate(v = [-1,  -1, casesplit])    cube([100,100, box_h], center = false);
    // back on 3 different levels
    translate(v = [split1, 20, pcb_c])     cube([split3-split1, box_l, box_h], center = false);
    translate(v = [possd1, 60, pcb_h-0.1])  cube([widesd1, box_l, 2], center = false);
//    translate(v = [split1, 20, pcb_c])     cube([20, box_l, box_h], center = false);
//    translate(v = [split2, 20, pcb_h])     cube([split3-split2, box_l, box_h], center = false);
  if (bottompcb) {
    translate(v = [-1,  -1, pcb_c])    cube([100,100, box_h], center = false);
  }
}

module remove_bottom() {
    split1=box_w1+Cpwr_x;
    split2=split1+Cpwr_w;
    split3=box_w2 - 12.1;
    possd1=box_w1 + Csd_x - 0.2;
    widesd1=Csd_w+0.6;
    // Different splitlevels for the shells
    // 1st half on split level
    translate(v = [-1,  -1, -1])    cube([box_w+2, box_l-6, casesplit+1], center = false);
    // back on 3 different levels
    translate(v = [-1, 20, -1])     cube([box_w+2  , box_l, pcb_c+1.1], center = false);
    translate(v = [-1, 20, -1])     cube([split1+1.1 , box_l, casesplit+1], center = false);
    translate(v = [-1, 20, -1])     cube([split2+1.1 , box_l, pcb_c+Cpwr_h+1.1], center = false);
    translate(v = [split3, 20, -1]) cube([20       , box_l, casesplit+1], center = false);
}

module draw_case(bottom, top) {
    difference() {
        union() {
            // make empty case
            difference() {
                make_case(box_w,box_l,box_h, box_thickness,stud_w, rounded=true);
                if (top != 0 && bottom == 0)    remove_bottom();
                if (top == 0 && bottom != 0)    remove_top();
            }
            color(CASEcolor) {
                if (bottom != 0 ) {
                    // add bottom studs for pcb
                    // add bottom studs for pcb
                    make_stud(box_w1       , box_l1         , 0, 4,pcb_h,4);      // rj45
                    make_stud(box_w1       , box_lc-stud_l/2, 0, stud_w,pcb_h,stud_l);      // hdmi
                    make_stud(box_w1, box_lc/2, 0, 4,pcb_h,stud_l);
                    make_stud(box_w1, box_lc+(box_lc/2)-5, 0, 4,pcb_h,stud_l);

                    make_stud(box_w1, box_l2-stud_l-8, 0, stud_w,pcb_h,stud_l);        // BEFORE pwr
                    make_stud(box_w2-stud_w, box_l1         , 0, stud_w,pcb_h,stud_l);      // leds
                    make_stud(box_w2-4, box_lc-stud_l/2, 0, 4,pcb_h,stud_l);                // RCA
                    make_stud(box_w2-stud_w, box_l2-stud_l  , 0, stud_w,pcb_h,stud_l);      // GPIO

                    translate(v=[box_w1+Cusb_x-6,box_l1,1])  cube([3.0, 4,pcb_h-1.1]);
                    translate(v=[box_w2-15.8    ,box_l1,1])  cube([3.0, 4,pcb_h-1.1]);

                    draw_pcbhold();
                }

                if (top != 0) {
                    // --- screw connection plates
                    translate(v = [box_w1 + Crj45_x+Crj45_w, box_l1, casesplit - 5.4]) {
                        cube([10, 3, box_h-(casesplit-5.4)], center = false);
                    }
                    translate(v = [box_w2-15, box_l2 - 1.5, casesplit - 5.4]) {
                            cube([8, 1.5, box_h-(casesplit-5.4)], center = false);
                    }
                    // extra support for shell
                    translate(v = [box_w1, box_l1, pcb_c+0.4]) {
                        cube([stud_w, 8, box_h-pcb_c-1], center = false);
                    }
                    translate(v = [box_w1, box_l2-10, pcb_c+0.4]) {
     	                   cube([stud_w, 10, box_h-pcb_c-1], center = false) ;
					 }
                    translate(v = [box_w1, box_l1+Chdmi_y+Chdmi_d+1.5, pcb_c+0.4]) {
                        cube([stud_w, 4, box_h-pcb_c-1], center = false);
                    }
                    translate(v = [box_w2-stud_w, box_l1, pcb_c+0.4]) {
                        cube([stud_w,10, box_h-pcb_c-1], center = false);
                    }
                    translate(v = [box_w2-stud_w, box_l1+Crca_y+Crca_d+1, pcb_c+0.4]) {
                        cube([stud_w, 4, box_h-pcb_c-1], center = false);
                    }
                }
            } // color
        } // end union
        // conn plate hole
        color(CASEcolor) {
        translate(v = [box_w1-5, box_l2-5, casesplit-3]) {
				rotate([0,90,0]) cylinder(r=0.5, h=10, $fn=100);
		 }
        translate(v = [box_w2-5, box_l1+5, casesplit-3]) {
				rotate([0,90,0]) cylinder(r=0.5, h=10, $fn=100);
		 }
        if (GPIOHOLE == 1 && bottom != 0) {
		     translate(v = [box_w2-5, box_l1+51, casesplit-GPIOsize]) cube([10,33.2,GPIOsize+0.1]);
        }
        if (GPIOHOLE == 2 && top != 0) {
		     translate(v = [box_w2-5, box_l1+51, casesplit-0.1]) cube([10,33.2,GPIOsize]);
        }
        }
        if (bottom != 0) {
            if (top == 0) {
                remove_top();
            } else {
                split_top();
            }
        }
        make_connholes();
    }
    if (bottom) {
        draw_pcbhold();
        if (DRAWpcb == 1)  make_pcb();
    }
} // end module

// Raspberry Pi Case
// Hans Harder 2012
//
// Warning: this is based on the Beta board dimensions...
//          so production models can be slightly different
//          for instance SD card holder height and USB socket dimensions
//
// Since all connectors stick out, case is split on HDMI height
// so the power and sdcard holder goes in first and then the pcb drops into place.
//
// v2: Adapted version after some suggestions from David...
//     removed feet, made both surface flat
// v3: Added fliptop option and smooth the corners of the box
// v4: Different levels of case split (make it 3d printable, thx David)
//     Looks strange but it fits...
//     Added frame mode (so no bottom and top deck)
//     Moved screw locations due to split and added some support structures
//     Unsure about 2nd screw location in combination with GPIO pins
// v5  relocated a lot of code in modules
//     SDslot location was not calculated correctly
// v6  Added pcb drawing
//     Added colors
//     Cut out better so there is no debris around
//     DRAwvars and options seperated, so it is easier to do 1 part
//     Make a low as possible case, let USB stick out
// v7  PCB options
//     Low level case optimisations
//     SD card location alterations
// v8  adapted pcb dimensions, board is really 56mm width
//     adapted support studs, moved some due to component location
//     components locations adapted
// v9  Added logo in seperate dxf file
//     Option added to put logo in middle or using whole deck
//     beautified code, kr style
// v10 Added logosunken and bottomsupport structures
//     Bottom supports are located where no components are located
//       so the pcb is not only supported from the sides
//     Well got my case, so based on what I see I changed:
//     case split level changed, should be better when printed on a reprap
//     Removed screwholes (far to small) for fastening top and added some more studs
//     Made frontstud a little thicker
// v11 Different splitlevel (more simple) on back
//     keep a little margin on back split, so that top and bottom always fit
//     added openlogo option
// v12 Different component locations/sizes
//     keep a little margin on component holes
//     pcbsize to 57.0 x 86.0   (actual it is 56.17 x 85.0)
//     made casestuds wider and added 2 minor holes for self tapping screws
// v13 skip this one.... :)
// v14 Production board measurements...
//	   small differences, sometimes components are soldered differently
//     keep more space
//     should fit like a glove...
// v15 moved the rca and snd a bit to get them more centered
//     Thanks to lincomatic at Thingiverse
//     Added option for GPIO side hole in bottom or top
//     Added showing GPIO pins with component drawing
//
// All parts are draw as default just disable the ones you don't want
DRAWfull        = 0;
DRAWtop         = 1;
DRAWbottom      = 1;
DRAWtopinlet    = 0;
DRAWbottominlet = 0;
DRAWpcb         = 0;

GPIOHOLE        = 2;        // GPIO opening in :  1=bottom   2=top
GPIOsize        = 2;        // define height of gpiohole

// select how the case should look like
topframe    = false;        // if false, underneath values determines how
topinlet    = false;        // false is outside, otherwise it is with an indent
topholes    = true;
// ---- holes sizes
holeofs=2;
holesiz=3;
holestep=10;
noholes=6;					// 12 for top,  20 for bottom
holelen=24;
topmiddle   = false;

bottomframe = false;        // if false, underneath values determines how
bottominlet = false;
bottomholes = false;
bottomscrew = false;
bottomfeet  = false;    // MHL: conflict w/ various through-hole components
bottomsupport = false;         // Added extra support locations for pcb
bottomclick   = true;
bottompcb    = false;		    // just a pcb holder without a top

box_thickness = 2.0;            // minimum = 1.0
inside_h      = 12.5;           // 12.1 = lowprofile    16.5 is full height
pcb_h         = 5.6;            // height needed for SD holder and solder points of pcb
//pcb_h         = box_thickness+3.5;    // height needed for SD holder and solder points of pcb
// 4.1 = no deck, box_thickness+3.5 is with deck

// just some colors to see the difference
CASEcolor="Maroon";
CONNcolor="Silver";

// Define Raspberry Pi pcb dimensions in mm
inside_l = 86.0;                //85.00 is largest length reported, so a bit room on each side
inside_w = 57.2;                //56.17 is largest width  reported, so a bit room on each side
pcb_thickness = 1.7;

// Coordinates based on RJ45 corner = 0,0,0
// pcb connectors and locations. Based on Beta Board measurements of Gert and a real RPi

// Connectors
Crj45_x=2.0;			 //2.0
Crj45_y=-1;
Crj45_w=16.4;			// 15.4
Crj45_d=21.5;           //21.8
Crj45_h=13.8;

Cusb_x=24.5;            // 23.9
Cusb_y=-7.7;
Cusb_w=13.9;            // 13.3
Cusb_d=19.0;			// 17.2
Cusb_h=16.0;

Cpwr_x=3.25;				// 3.5 3.6
Cpwr_y=80.9;
Cpwr_w=8.8;				// 7.8 7.6
Cpwr_d=5.6;
Cpwr_h=2.6;

Csd_x=16.7;
Csd_y=inside_l-24.0;            // 30 mm is the length of a  sdcard
Csd_w=27.8;
Csd_d=29.0;
Csd_h=3.4;                  // under pcb

Chdmi_x=-1.2;
Chdmi_y=32.0;               // 32.4  if 15.1
Chdmi_w=11.4;
Chdmi_d=17.8;				  // 15.7 15.3
Chdmi_h=6.4;

Csnd_x=inside_w - 11.4;
Csnd_y=16.0;
Csnd_w=11.4;
Csnd_d=10.0;
Csnd_h=10.5;
Csnd_r=6.7;
Csnd_z=3.0;
Csnd_l=3.4;

Crca_x=inside_w - 10.0 - 2.1;
Crca_y=34.2;                // 34.6 was 35.2
Crca_w=10.0;
Crca_d=10.4;                 // 9.8
Crca_h=13.0;
Crca_r=8.6;
Crca_z=4;
Crca_l=10;                  // wild guess

pcb_c = pcb_h + pcb_thickness;            // component height
casesplit = pcb_c + Chdmi_h;              // split case at top of hdmi connector
echo("casesplit=",casesplit);
echo("case dimensions: w=",box_w," l=",box_l," h=",box_h);

// side stud sizes for supporting pcb
stud_w = 2;
stud_l = 4;

// calculate box size
box_l  = inside_l + (box_thickness * 2);
box_w  = inside_w + (box_thickness * 2);
box_h  = pcb_c + (pcb_thickness * 2) + inside_h;
box_w1 = box_thickness;
box_w2 = box_w - box_thickness;
box_l1 = box_thickness;
box_l2 = box_l - box_thickness;
box_wc = box_w / 2;                 // center width
box_lc = box_l / 2;                 // center length
box_t2 = box_thickness / 2.0;           // half box_thickness
middle = true;
// rounded corners
corner_radius = box_thickness*2;

// count no of items to draw
DRAWtotal = DRAWfull + DRAWtop + DRAWbottom + DRAWtopinlet + DRAWbottominlet;

// ====================================================== DRAW items
// if one  draw it centered
if (DRAWtotal == 1) {
    translate(v = [ -box_w/2, -box_l / 2, 0]) {
        if (DRAWfull ) {
           draw_case(0,1);
           translate(v=[0,0,0.2]) draw_case(1,0);
        }
        if (DRAWtop   ) {
            rotate(a=[0,180,0]) translate(v=[-box_w,0,-box_h]) draw_case(0,1);
        }
        if (DRAWbottom) draw_case(1,0);
        if (DRAWtopinlet) make_deck(inside_w-5,inside_l-5,0, 12,3,5, holes=topholes,feet=false,middle=topmiddle,screwholes=false);
        if (DRAWbottominlet) make_deck(inside_w-5,inside_l-5,0, 12,3,5, holes=bottomholes,feet=true,middle=false,screwholes=bottomscrew);
    }
} else {
// draw each one on there one location
    if (DRAWfull)   {
        translate(v = [ box_w+20, -box_l / 2, 0]) {
            draw_case(1,0);
            translate(v=[0,0,0.2]) draw_case(0,1);
        }
    }
    if (DRAWbottom) {
        translate(v = [ 5, 5, 0]) draw_case(1,0);
    }
    if (DRAWtop)    {
        translate(v = [ - 5,  5, box_h])  rotate(a=[0,180,0]) draw_case(0,1);
    }
    if (DRAWtopinlet) {
        translate(v = [ -box_w-5,  -box_l-5, 0])    make_deck(inside_w-5,inside_l-5,0, 12,3,5, holes=topholes,feet=false,middle=topmiddle,screwholes=false);
    }
    if (DRAWbottominlet) {
        translate(v = [ 5       ,  -box_l-5, 0]) make_deck(inside_w-5,inside_l-5,0, 10,3,5 , holes=bottomholes,feet=true,middle=false,screwholes=bottomscrew);
    }
}

// ======================================================= END of draw
// Module sections

module make_deckholes(no,w,d,step) {
for ( i = [0 : 1 : no - 1] ) {
        translate(v=[w/2,(i*step)+(step/2),box_thickness/2]) cube([w,d, box_thickness+18], center=true);
    }
}

// create a deck or insert
module make_deck(w,d,z,hole_no,hole_size,hole_step) {
    hole_w=(w - 12) / 2;      // change 12 for middle piece size
    ofs1=4;
    ofs2=w - ofs1 - hole_w;
    hole_ofs= ((d - hole_no*hole_step) / 2) - box_thickness/2;
    translate(v = [(box_w-w)/2, (box_l-d)/2,z]) {
        color(CASEcolor) {
            echo("deck : z=",z," w=",w+0.01," d=",d+0.01);
            difference() {
                cube([w, d, box_thickness], center = false);
                if (top && holes && hole_size>0) {
                    translate(v=[-1,hole_ofs+holeofs,-0.1]) make_deckholes(noholes,holelen,holesiz,holestep);
                    translate(v=[w/2-2,hole_ofs+holeofs,-0.1]) make_deckholes(noholes,holelen,holesiz,holestep);
                }
                if (screwholes) {
                    // --- 2x screw holes in bottom for mounting
                    translate(v = [w/2 - 4, 10-4, -1]) cube([8, 3, 5], center = false);
                    translate(v = [w/2 - 4, 10-3, -1]) cylinder(r=3, h=8, $fn=100, center=true);
                    // 2nd screw hole
                    translate(v = [w/2 - 3, d - 10 +3, -1]) cube([8, 3, 5], center = false);
                    translate(v = [w/2 + 4, d - 10 +4, -1]) cylinder(r=3, h=8, $fn=100);
                    if (!holes) {
                        // middle screw hole
                        translate(v = [w/2 - 4, d/2    , -1]) cube([8, 2, 5], center = false);
                        translate(v = [w/2 - 4, d/2 + 1, -1]) cylinder(r=2, h=8, $fn=100);
                    }
                }
                if (holes && !top) {
                    translate(v=[(w-hole_w)/2,holeofs,-0.1]) make_deckholes(noholes,hole_w,holesiz,holestep);
                }
            }
            color(CASEcolor) {
                if (feet) {
                    translate(v=[3,3,0])          cube([8, 8, box_thickness+4], center = false);
                    translate(v=[w-3-8,3,0])      cube([8, 8, box_thickness+4], center = false);
                    translate(v=[3,d-3-8,0])      cube([8, 8, box_thickness+4], center = false);
                    translate(v=[w-3-8,d-3-8,0])  cube([8, 8, box_thickness+4], center = false);
                }
                if (top && holes) {
                    translate(v = [w/2-box_thickness,12,0]) cube([4,d-13, box_thickness], center = false);
                }
                if (middle) {
                    // --- solid area for sticker
                    translate(v = [w/2-10,d/2-5-box_thickness/2,0]) {
                        cube([20,20, box_thickness], center = false);
                    }
                }
            }
        }
    }
}

module rounded_corner(x,y,rx,ry,cx,cy) {
    translate(v = [x, y, -1]) {
        difference() {
            translate(v=[rx,ry,0])    cube([corner_radius,corner_radius,box_h+2], center=false);
            translate(v=[cx, cy, -1]) cylinder(r=corner_radius, h=box_h+2, $fn=100);
        }
    }
}

module make_topcomponents() {
    color(CONNcolor) translate(v=[box_w1,box_l1,pcb_c]) {
        translate(v=[Crj45_x,Crj45_y,0]) cube([Crj45_w,Crj45_d,Crj45_h],center=false);
        translate(v=[Cusb_x,Cusb_y,0])   cube([Cusb_w,Cusb_d,Cusb_h],center=false);
        translate(v=[Cpwr_x,Cpwr_y,0])   cube([Cpwr_w,Cpwr_d,Cpwr_h],center=false);
        translate(v=[Chdmi_x,Chdmi_y,0]) cube([Chdmi_w,Chdmi_d,Chdmi_h],center=false);

        //SND
        translate(v=[Csnd_x,Csnd_y,0]) cube([Csnd_w+0.1,Csnd_d,Csnd_h],center=false);
        translate(v=[Csnd_x+Csnd_w,Csnd_y+Csnd_d/2,Csnd_z+Csnd_r/2]) rotate(a=90,v=[0,1,0]) cylinder(r=Csnd_r/2, h=Csnd_l, $fn=100);

        //RCA
        translate(v=[Crca_x,Crca_y,0]) cube([Crca_w+0.2,Crca_d,Crca_h],center=false);
        translate(v=[Crca_x+Crca_w,Crca_y+Crca_d/2,Crca_z+Crca_r/2]) rotate(a=90,v=[0,1,0]) cylinder(r=Crca_r/2, h=Crca_l+0.1, $fn=100);
    }
    for ( i = [0 : 1 : 12] ) {
        color("black") translate(v=[box_w2-6.6,box_l2-1-34+(i*2.54),pcb_c]) cube([5.08,2.53,2.5]);
        color("Gainsboro") translate(v=[box_w2-6.6+0.97,box_l2-1-34+(i*2.54)+0.95,pcb_c-3])  cube([0.6,0.6,11.5]);
        color("Gainsboro") translate(v=[box_w2-6.6+3.61,box_l2-1-34+(i*2.54)+0.95,pcb_c-3])  cube([0.6,0.6,11.5]);

    }
}

module make_connholes() {
    // =================================== cut outs, offset from 0,0
    //RJ45:    2mm offset, 15.5mm width, 13.1mm height
    set_cutout(box_w1+Crj45_x,box_l1+Crj45_y-3,pcb_c,   Crj45_w+0.1,Crj45_d+3,Crj45_h);
    //usb:  23.9mm offset, 13.3mm width, 15.4mm height
    set_cutout(box_w1+Cusb_x,box_l1+Cusb_y,pcb_c,   Cusb_w,Cusb_d,Cusb_h+0.1);

    //power: 3.4mm offset,    8mm width,    3mm height
    set_cutout(box_w1+Cpwr_x,box_l1+Cpwr_y,pcb_c,   Cpwr_w,Cpwr_d+4,Cpwr_h+0.01);
    //sd:   15mm offset,   28mm width,    3.5mm height under pcb
    if (pcb_h >= (Csd_h+1.5) ) {
        set_cutout(box_w1+Csd_x-0.3,box_l2-28,pcb_h-Csd_h,Csd_w+0.6,box_thickness+30,Csd_h+0.1);
    } else {
        set_cutout(box_w1+Csd_x-0.3,box_l2-32,pcb_h-20,Csd_w+0.6,40,20.01);
    }
    //HDMI: 32.9mm offset,  15.3mm width,   6.3mm height
    set_cutoutv(box_w1+Chdmi_x-3,box_l1+Chdmi_y,pcb_c,    Chdmi_w+3.1,Chdmi_d,Chdmi_h+0.1);

    // snd:   14mm offset,  12mm width,   8.2 mm height
    set_cutout(box_w1+Csnd_x,box_l1+Csnd_y,pcb_c+2,    Csnd_w+7,Csnd_d,Csnd_h-2);

    // RCA:   35mm offset,  10mm width     10mm height
    translate(v=[box_w1+Crca_x+Crca_w,box_l1+Crca_y+Crca_d/2,pcb_c+Crca_z+Crca_r/2]) {
        rotate(a=90,v=[0,1,0]) cylinder(r=Crca_r/2+1, h=Crca_l, $fn=100);
    }
    translate(v=[box_w1+Crca_x+Crca_w,box_l1+Crca_y+(Crca_d-Crca_r)/2-1,pcb_c+Crca_z-1]) {
        cube([5,Crca_r+2,Crca_r/2+1]);
    }
}

module make_pcb() {
    translate(v=[box_w1,box_l1,pcb_h]) {
        color("darkgreen") cube([inside_w,inside_l,pcb_thickness], center=false);
    }
    color(CONNcolor) {
        translate(v=[box_w1+Csd_x,box_l1+Csd_y,pcb_h-Csd_h]) cube([Csd_w,Csd_d,Csd_h],center=false);
    }
    make_topcomponents();
}

// put extra supports on free spaces, used beta board image
module make_supports() {
    if (!bottomframe) {
        translate(v=[box_w1+10 ,box_l1+28,0.1]) cube([3, 2,pcb_h-0.1]);
        translate(v=[box_w2-7.5,box_l1+28,0.1]) cube([3, 2,pcb_h-0.1]);

        translate(v=[box_w1+7  ,box_l2-35,0.1])  cube([5, 5,pcb_h-0.1]);
        translate(v=[box_w2-13 ,box_l2-35,0.1])  cube([5, 5,pcb_h-0.1]);

        translate(v=[box_w1+12 ,box_l2-16,0.1])  cube([1.5 ,5,pcb_h-0.1]);
        translate(v=[box_w2-9  ,box_l2-16,0.1])  cube([1.5 ,5,pcb_h-0.1]);
    }
}

// width,depth,height,boxthickness,ledgethickness
module make_case(w,d,h,bt,lt) {
    dt=bt+lt;    // box+ledge thickness
    bt2=bt+bt;    // 2x box thickness
    // Now we just substract the shape we have created in the four corners
    color(CASEcolor) difference() {
        cube([w,d,h], center=false);
        if (rounded) {
            rounded_corner(-0.1,d+0.1, 0             ,-corner_radius,  corner_radius,-corner_radius);
            rounded_corner(w+0.1,d+0.1, -corner_radius,-corner_radius, -corner_radius,-corner_radius);
            rounded_corner(w+0.1,-0.1, -corner_radius,0             , -corner_radius, corner_radius);
            rounded_corner(-0.1,-0.1, 0             ,0             ,  corner_radius, corner_radius);
        }
        // empty inside, but keep a ledge for strength
        translate(v = [bt, bt, dt])   cube([w-bt2, d-bt2, h-(dt*2)], center = false);
        translate(v = [dt,dt,bt])     cube([w-(dt*2), d-(dt*2), h-bt2], center = false);
        // remove bottom and top deck
        translate(v = [box_thickness+2, box_thickness+5,-2]) {
            cube([inside_w-4, inside_l-10, box_h+4], center = false);
        }
    }
    if (!topframe) {
        if (!topinlet) {
            make_deck(inside_w-4,inside_l-4,box_h-box_thickness, 12,3,5, holes=topholes,feet=false,middle=topmiddle,screwholes=false,top=true);
        } else {
            make_deck(inside_w-4,inside_l-4,box_h-box_thickness*2, 12,3,5, holes=topholes,feet=false,middle=topmiddle,screwholes=false,top=true);
        }
    }
    if (!bottomframe) {
        if (!bottominlet) {
            make_deck(inside_w-4,inside_l-4,0, 12,3,5, holes=bottomholes,feet=bottomfeet,screwholes=bottomscrew,middle=false,top=false);
        } else {
            make_deck(inside_w-4,inside_l-4,box_thickness, 12,3,5, holes=bottomholes,feet=bottomfeet,screwholes=bottomscrew,middle=false,top=false);
        }
        if (bottomsupport) {
            make_supports();
        }
    }
}

module make_stud(x,y,z,w,h,l) {
    translate(v = [x, y, z]) cube([w, l, h], center = false);
}

module set_cutout(x,y,z,w,l,h) {
    color(CASEcolor)    translate(v = [x+(w/2), y+(l/2), z+(h/2)]) cube([w+0.4, l+0.2, h+0.2], center = true);
}

module set_cutoutv(x,y,z,w,l,h) {
    color(CASEcolor)    translate(v = [x+(w/2), y+(l/2), z+(h/2)]) cube([w+0.2, l+0.4, h+0.2], center = true);
}

module draw_pcbhold() {
  if (bottomclick) {
    color(CASEcolor) {
        translate(v=[0  ,22,2]) cube([box_thickness,4,pcb_c]);
        translate(v=[box_w1-0.1  ,22.5,pcb_c+0.1]) {
            difference() {
                cube([1, 3,2]);
                translate(v=[1,-0.1,0])  rotate(a=-30, v=[0,1,0])  cube([1.6, 3.2, 4]);
            }
        }
        translate(v=[0  ,60.5,2]) cube([box_thickness,5,pcb_c]);
        translate(v=[box_w1-0.1  ,61.5,pcb_c+0.1]) {
            difference() {
                cube([1,3,2]);
                translate(v=[1,-0.1,0])  rotate(a=-30, v=[0,1,0])  cube([1.6, 3.2, 4]);
            }
        }
        translate(v=[box_w2,29.5,2]) cube([box_thickness,4,pcb_c]);
        translate(v=[box_w2+0.1  ,30+3,pcb_c+0.1]) {
            rotate(a=180, v=[0,0,1]) difference() {
                cube([1, 3,3]);
                translate(v=[1,-0.1,0])  rotate(a=-30, v=[0,1,0])  cube([1.6, 3.2, 4]);
            }
        }
        translate(v=[box_w2,60.5,2]) cube([box_thickness,5,pcb_c]);
        translate(v=[box_w2+0.1  ,61+3.5,pcb_c+0.1]) {
            rotate(a=180, v=[0,0,1]) difference() {
                cube([1,3,3]);
                translate(v=[1,-0.1,0])  rotate(a=-30, v=[0,1,0])  cube([1.6, 3.2, 4]);
            }
        }
    }
  }
}

module split_top() {
    split1=box_w1+Cpwr_x;
    split2=split1+Cpwr_w;
    split3=box_w1+Csd_x - 12;   // min 16.5+28
    split4=box_w2 - 7;
    // Different splitlevels for the shells
    // 1st half on split level
    translate(v = [-1,  -1, casesplit-0.2])    cube([box_w+2, 21, 0.4], center = false);
    // back on 3 different levels
    translate(v = [-1,  20, casesplit-0.2])    cube([split1+1     , box_l, 0.4], center = false);
    translate(v = [split2, 20, pcb_c-0.2])     cube([split3-split2, box_l, 0.4], center = false);
    translate(v = [split3, 20, pcb_h-0.2])     cube([split4-split3, box_l, 0.4], center = false);
    translate(v = [split4, 20, casesplit-0.2]) cube([20           , box_l, 0.4], center = false);
}

module remove_top() {
    split1=box_w1+Cpwr_x;
    split2=split1+Cpwr_w;
    split3=box_w2 - 12;
    possd1=box_w1 + Csd_x - 0.3;
    widesd1=Csd_w+0.6;
    // Different splitlevels for the shells
    // 1st half on split level
    translate(v = [-1,  -1, casesplit])    cube([100,100, box_h], center = false);
    // back on 3 different levels
    translate(v = [split1, 20, pcb_c])     cube([split3-split1, box_l, box_h], center = false);
    translate(v = [possd1, 60, pcb_h-0.1])  cube([widesd1, box_l, 2], center = false);
//    translate(v = [split1, 20, pcb_c])     cube([20, box_l, box_h], center = false);
//    translate(v = [split2, 20, pcb_h])     cube([split3-split2, box_l, box_h], center = false);
  if (bottompcb) {
    translate(v = [-1,  -1, pcb_c])    cube([100,100, box_h], center = false);
  }
}

module remove_bottom() {
    split1=box_w1+Cpwr_x;
    split2=split1+Cpwr_w;
    split3=box_w2 - 12.1;
    possd1=box_w1 + Csd_x - 0.2;
    widesd1=Csd_w+0.6;
    // Different splitlevels for the shells
    // 1st half on split level
    translate(v = [-1,  -1, -1])    cube([box_w+2, box_l-6, casesplit+1], center = false);
    // back on 3 different levels
    translate(v = [-1, 20, -1])     cube([box_w+2  , box_l, pcb_c+1.1], center = false);
    translate(v = [-1, 20, -1])     cube([split1+1.1 , box_l, casesplit+1], center = false);
    translate(v = [-1, 20, -1])     cube([split2+1.1 , box_l, pcb_c+Cpwr_h+1.1], center = false);
    translate(v = [split3, 20, -1]) cube([20       , box_l, casesplit+1], center = false);
}

module draw_case(bottom, top) {
    difference() {
        union() {
            // make empty case
            difference() {
                make_case(box_w,box_l,box_h, box_thickness,stud_w, rounded=true);
                if (top != 0 && bottom == 0)    remove_bottom();
                if (top == 0 && bottom != 0)    remove_top();
            }
            color(CASEcolor) {
                if (bottom != 0 ) {
                    // add bottom studs for pcb
                    // add bottom studs for pcb
                    make_stud(box_w1       , box_l1         , 0, 4,pcb_h,4);      // rj45
                    make_stud(box_w1       , box_lc-stud_l/2, 0, stud_w,pcb_h,stud_l);      // hdmi
                    make_stud(box_w1, box_lc/2, 0, 4,pcb_h,stud_l);
                    make_stud(box_w1, box_lc+(box_lc/2)-5, 0, 4,pcb_h,stud_l);

                    make_stud(box_w1, box_l2-stud_l-8, 0, stud_w,pcb_h,stud_l);        // BEFORE pwr
                    make_stud(box_w2-stud_w, box_l1         , 0, stud_w,pcb_h,stud_l);      // leds
                    make_stud(box_w2-4, box_lc-stud_l/2, 0, 4,pcb_h,stud_l);                // RCA
                    make_stud(box_w2-stud_w, box_l2-stud_l  , 0, stud_w,pcb_h,stud_l);      // GPIO

                    translate(v=[box_w1+Cusb_x-6,box_l1,1])  cube([3.0, 4,pcb_h-1.1]);
                    translate(v=[box_w2-15.8    ,box_l1,1])  cube([3.0, 4,pcb_h-1.1]);

                    draw_pcbhold();
                }

                if (top != 0) {
                    // --- screw connection plates
                    translate(v = [box_w1 + Crj45_x+Crj45_w, box_l1, casesplit - 5.4]) {
                        cube([10, 3, box_h-(casesplit-5.4)], center = false);
                    }
                    translate(v = [box_w2-15, box_l2 - 1.5, casesplit - 5.4]) {
                            cube([8, 1.5, box_h-(casesplit-5.4)], center = false);
                    }
                    // extra support for shell
                    translate(v = [box_w1, box_l1, pcb_c+0.4]) {
                        cube([stud_w, 8, box_h-pcb_c-1], center = false);
                    }
                    translate(v = [box_w1, box_l2-10, pcb_c+0.4]) {
     	                   cube([stud_w, 10, box_h-pcb_c-1], center = false) ;
					 }
                    translate(v = [box_w1, box_l1+Chdmi_y+Chdmi_d+1.5, pcb_c+0.4]) {
                        cube([stud_w, 4, box_h-pcb_c-1], center = false);
                    }
                    translate(v = [box_w2-stud_w, box_l1, pcb_c+0.4]) {
                        cube([stud_w,10, box_h-pcb_c-1], center = false);
                    }
                    translate(v = [box_w2-stud_w, box_l1+Crca_y+Crca_d+1, pcb_c+0.4]) {
                        cube([stud_w, 4, box_h-pcb_c-1], center = false);
                    }
                }
            } // color
        } // end union
        // conn plate hole
        color(CASEcolor) {
        translate(v = [box_w1-5, box_l2-5, casesplit-3]) {
				rotate([0,90,0]) cylinder(r=0.5, h=10, $fn=100);
		 }
        translate(v = [box_w2-5, box_l1+5, casesplit-3]) {
				rotate([0,90,0]) cylinder(r=0.5, h=10, $fn=100);
		 }
        if (GPIOHOLE == 1 && bottom != 0) {
		     translate(v = [box_w2-5, box_l1+51, casesplit-GPIOsize]) cube([10,33.2,GPIOsize+0.1]);
        }
        if (GPIOHOLE == 2 && top != 0) {
		     translate(v = [box_w2-5, box_l1+51, casesplit-0.1]) cube([10,33.2,GPIOsize]);
        }
        }
        if (bottom != 0) {
            if (top == 0) {
                remove_top();
            } else {
                split_top();
            }
        }
        make_connholes();
    }
    if (bottom) {
        draw_pcbhold();
        if (DRAWpcb == 1)  make_pcb();
    }
} // end module


nipple_top

include <constants.scad>;
HEIGHT_NIPPLE = 0.8;
DIAMETER_NIPPLE = 3;
BORDER_NIPPLE = 0.2;
DIAMETER_BASE_NIPPLE = 6;

module top_little()
{
    color(GREY)
        translate([0,0,-BORDER_NIPPLE])
            cylinder(
                h = BORDER_NIPPLE,
                d = (DIAMETER_NIPPLE - (2 * BORDER_NIPPLE)),
                $fn = FINE);
}

module shoulder_top_little()
{
    position_ring = [0,0,-BORDER_NIPPLE];

    posicion_circle_x = radius(DIAMETER_NIPPLE)-BORDER_NIPPLE;
    position_circle = [posicion_circle_x, 0, 0];

    color(GREY)
    translate(position_ring)
        rotate_extrude(convexity = CONVEXITY, $fn = FINE)
        translate(position_circle)
        circle(r = BORDER_NIPPLE, $fn = FINE);
}
module nipple()
{
    top_little();
    shoulder_top_little();

//Main nipple cylinder
color(GREY)
translate([0,0,-(HEIGHT_NIPPLE - BORDER_NIPPLE)])
    cylinder(
        h = (HEIGHT_NIPPLE - (BORDER_NIPPLE + BORDER_NIPPLE)),
        d = DIAMETER_NIPPLE,
        $fn = FINE);

//Main nipple cylinder; base fillet
color(GREY)
difference()
{
    translate([0,0,BORDER_NIPPLE - HEIGHT_NIPPLE])
        rotate_extrude(convexity = CONVEXITY, $fn = FINE)
        translate([(DIAMETER_NIPPLE/2), 0, 0])
            square((BORDER_NIPPLE),(BORDER_NIPPLE));

    translate([0,0,(2 * BORDER_NIPPLE) - HEIGHT_NIPPLE])
        rotate_extrude(convexity = CONVEXITY, $fn = FINE)
        translate([(DIAMETER_NIPPLE/2)+ BORDER_NIPPLE, 0, 0])
            circle(r = BORDER_NIPPLE, $fn = FINE);
}

//Nipple shoulder cylinder
color(GREY)
translate([0,0,-HEIGHT_NIPPLE])
    cylinder(
        h = BORDER_NIPPLE,
        d = DIAMETER_BASE_NIPPLE - (2 * BORDER_NIPPLE),
        $fn = FINE);

//Nipple base shoulder
color(GREY)
translate([0,0,-HEIGHT_NIPPLE])
    rotate_extrude(convexity = CONVEXITY, $fn = FINE)
    translate([(DIAMETER_BASE_NIPPLE/2)-BORDER_NIPPLE, 0, 0])
        circle(r = BORDER_NIPPLE, $fn = FINE);

}

nipple();