The path was corrected.

The path was corrected.

use <../../../shapes/open-cylinder/open-cylinder.scad>

module waterPumpFilter(baseHeight = 30,
					   innerRadius = 25,
					   snorkel = false,
					   snorkelHeight = 40,
					   snorkelOuterRadius = 7,
					   xLength = 54)
{
	union()
	{
//		if(snorkel == true)
	//	{
		//	waterPump_snorkel(filter_baseHeight = baseHeight,
			//	 			  filter_xLength = xLength,
				//			  filter_yLength = yLength,
					//		  height = snorkelHeight,
						//	  snorkelOuterRadius = snorkelOuterRadius);
//		}

		zTranslate = baseHeight / 2.0;
		translate([0,0, zTranslate-0.1])
		waterPumpFilter_connector(innerRadius = innerRadius);

		yLength = (innerRadius * 2) + 4;
		waterPumpFilter_base(height = baseHeight,
							 innerRadius = innerRadius,
							 snorkel = snorkel,
							 snorkelOuterRadius = snorkelOuterRadius,
							 xLength = xLength,
							 yLength = yLength);
	}
}

module waterPumpFilter_connector(innerRadius)
{
	openCylinder(height = 5,
				 innerRadius = innerRadius,
				 outerRadius = innerRadius + 2);
}

module waterPumpFilter_base(height,
							innerRadius,
							snorkel,
							snorkelOuterRadius,
							xLength,
							yLength)
{
	difference()
	{
		// this is the outer cube
		cube([xLength, yLength, height], center = true);

		color("pink")
		translate([0,0,10])
		cylinder(r=innerRadius, h=30, center=true);

		innerCubeDifference = 4;
		color("green")
		waterPumpFilter_base_innerCube(xLength - innerCubeDifference,
									   yLength - innerCubeDifference,
									   height - innerCubeDifference);

		cutoutHeight = height - 4;

		waterPumpFilter_xCutouts(height = cutoutHeight,
								 length = xLength - 8);

		waterPumpFilter_yCutouts(height = cutoutHeight);

		if(snorkel == true)
		{
			waterPump_snorkel(filter_baseHeight = height,
							  filter_xLength = xLength,
							  filter_yLength = yLength,
							  height = 20,
							  snorkelOuterRadius = snorkelOuterRadius);
		}
	}
}

module waterPumpFilter_base_innerCube(xyLength, yLength, height)
{
	cube([xyLength, yLength, height], center = true);
}

module waterPump_snorkel(filter_baseHeight,
						 filter_xLength,
						 filter_yLength,
						 height,
						 snorkelOuterRadius)
{
	xTranslate = (filter_xLength / 2.0) - snorkelOuterRadius - 2;
	yTranslate = (filter_yLength / 2.0) - snorkelOuterRadius -2;
	zTranslate = (filter_baseHeight / 2.0) - 4;

	color("green")
	translate([xTranslate, yTranslate, zTranslate])
	cylinder(h = height, r = snorkelOuterRadius, fn = 50);
//	openCylinder(height = height,
	//			 innerRadius = snorkelOuterRadius - 2,
		//		 outerRadius = snorkelOuterRadius);

	translate([-xTranslate, -yTranslate, zTranslate])
// 	openCylinder(height = height,
 	//			 innerRadius = snorkelOuterRadius - 2,
 		//		 outerRadius = snorkelOuterRadius);
			 cylinder(h = height, r = snorkelOuterRadius, $fn = 100);
}

module waterPumpFilter_xCutouts(height, length)
{
	step = 5;

	for(x = [-length : step : length])
	{
		translate([x, 0, 0])
		cube([2, 100, height], center = true);
	}
}

module waterPumpFilter_yCutouts(height)
{
	step = 5;

	for(y = [-20 : step : 20])
	{
		translate([0, y, 0])
		cube([100, 2, height], center = true);
	}
}

use <../../shapes/open-cylinder/open-cylinder.scad>

module waterPumpFilter(baseHeight = 30,
					   innerRadius = 25,
					   snorkel = false,
					   snorkelHeight = 40,
					   snorkelOuterRadius = 7,
					   xLength = 54)
{
	union()
	{
//		if(snorkel == true)
	//	{
		//	waterPump_snorkel(filter_baseHeight = baseHeight,
			//	 			  filter_xLength = xLength,
				//			  filter_yLength = yLength,
					//		  height = snorkelHeight,
						//	  snorkelOuterRadius = snorkelOuterRadius);
//		}

		zTranslate = baseHeight / 2.0;
		translate([0,0, zTranslate-0.1])
		waterPumpFilter_connector(innerRadius = innerRadius);

		yLength = (innerRadius * 2) + 4;
		waterPumpFilter_base(height = baseHeight,
							 innerRadius = innerRadius,
							 snorkel = snorkel,
							 snorkelOuterRadius = snorkelOuterRadius,
							 xLength = xLength,
							 yLength = yLength);
	}
}

module waterPumpFilter_connector(innerRadius)
{
	openCylinder(height = 5,
				 innerRadius = innerRadius,
				 outerRadius = innerRadius + 2);
}

module waterPumpFilter_base(height,
							innerRadius,
							snorkel,
							snorkelOuterRadius,
							xLength,
							yLength)
{
	difference()
	{
		// this is the outer cube
		cube([xLength, yLength, height], center = true);

		color("pink")
		translate([0,0,10])
		cylinder(r=innerRadius, h=30, center=true);

		innerCubeDifference = 4;
		color("green")
		waterPumpFilter_base_innerCube(xLength - innerCubeDifference,
									   yLength - innerCubeDifference,
									   height - innerCubeDifference);

		cutoutHeight = height - 4;

		waterPumpFilter_xCutouts(height = cutoutHeight,
								 length = xLength - 8);

		waterPumpFilter_yCutouts(height = cutoutHeight);

		if(snorkel == true)
		{
			waterPump_snorkel(filter_baseHeight = height,
							  filter_xLength = xLength,
							  filter_yLength = yLength,
							  height = 20,
							  snorkelOuterRadius = snorkelOuterRadius);
		}
	}
}

module waterPumpFilter_base_innerCube(xyLength, yLength, height)
{
	cube([xyLength, yLength, height], center = true);
}

module waterPump_snorkel(filter_baseHeight,
						 filter_xLength,
						 filter_yLength,
						 height,
						 snorkelOuterRadius)
{
	xTranslate = (filter_xLength / 2.0) - snorkelOuterRadius - 2;
	yTranslate = (filter_yLength / 2.0) - snorkelOuterRadius -2;
	zTranslate = (filter_baseHeight / 2.0) - 4;

	color("green")
	translate([xTranslate, yTranslate, zTranslate])
	cylinder(h = height, r = snorkelOuterRadius, fn = 50);
//	openCylinder(height = height,
	//			 innerRadius = snorkelOuterRadius - 2,
		//		 outerRadius = snorkelOuterRadius);

	translate([-xTranslate, -yTranslate, zTranslate])
// 	openCylinder(height = height,
 	//			 innerRadius = snorkelOuterRadius - 2,
 		//		 outerRadius = snorkelOuterRadius);
			 cylinder(h = height, r = snorkelOuterRadius, $fn = 100);
}

module waterPumpFilter_xCutouts(height, length)
{
	step = 5;

	for(x = [-length : step : length])
	{
		translate([x, 0, 0])
		cube([2, 100, height], center = true);
	}
}

module waterPumpFilter_yCutouts(height)
{
	step = 5;

	for(y = [-20 : step : 20])
	{
		translate([0, y, 0])
		cube([100, 2, height], center = true);
	}
}


config/xaxis: Switch back to 10mm rods/bearings

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

include <MCAD/stepper.scad>

use <thing_libutils/misc.scad>

e=0.01*mm;

// high quality etc
is_build = false;

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

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

$show_vit = is_build ? false : true;

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

extrusion_height            = 0.4*mm;

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

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

thick_wall_factor           = 4;

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

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

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

extrusion_mount_thread = ThreadM4;

// for tapped ends
extrusion_end_nut = NutHexM6;

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

gantry_connector_thickness = 5;

rod_fit_tolerance=1.01;

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

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

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

xaxis_belt = TimingBelt_GT2_2;
xaxis_belt_width = 6*mm;
xaxis_beltpath_width = max(xaxis_belt_width+3*mm, xaxis_pulley[0]+2*mm);
xaxis_beltpath_z_offset_pulley = xaxis_pulley_inner_d/2;
/*xaxis_beltpath_z_offsets = [xaxis_beltpath_z_offset_pulley];*/
xaxis_beltpath_z_offsets = [-3*mm-xaxis_beltpath_z_offset_pulley, 3*mm+xaxis_beltpath_z_offset_pulley];
xaxis_beltpath_height_body = xaxis_pulley_outer_d/2+3*mm+v_sum(v_abs(xaxis_beltpath_z_offsets))+5*mm;
xaxis_beltpath_height_holders = max(xaxis_pulley_outer_d+2*mm, xaxis_pulley_inner_d+xaxis_beltpath_z_offsets[0]+3*mm);

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

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

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

yaxis_rod_distance = 170*mm;
yaxis_rod_d = 11.975*mm;
yaxis_rod_l = 500*mm;
yaxis_bearing = LinearBearingKH1228;
yaxis_bearing_distance_y = 7*cm;

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

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

yaxis_belt = TimingBelt_GT2_2;
yaxis_belt_width = 6*mm;
yaxis_belt_path_offset_x = -yaxis_pulley_inner_d/2;
yaxis_belt_path_offset_z = yaxis_motor_offset_z + 10*mm;

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

yaxis_carriage_size = [220*mm,220*mm,5*mm];
printbed_size = [213*mm,213*mm,3*mm];
Mat_PrintCarriage = Mat_Aluminium;
Mat_PrintBed = [.6,.5,.5];

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

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

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

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

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

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

zmotor_mount_clamp_dist = zaxis_rod_d*2.5;
zmotor_mount_clamp_thread = extrusion_mount_thread;
zmotor_mount_clamp_nut = NutHexM4;
zmotor_mount_clamp_thread_dia = lookup(ThreadSize, zmotor_mount_clamp_thread);
zmotor_mount_clamp_nut_dia = lookup(NutWidthMin, zmotor_mount_clamp_nut);
zmotor_mount_clamp_nut_thick = lookup(NutThickness, zmotor_mount_clamp_nut);
zmotor_mount_clamp_width = zmotor_mount_clamp_dist+zmotor_mount_clamp_thread_dia*3;

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

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

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

// z screw offset from lower extrusion (outer)
zmotor_mount_screw_offset_x = zmotor_w/2 + zmotor_mount_motor_offset;

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

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

include <MCAD/stepper.scad>

use <thing_libutils/misc.scad>

e=0.01*mm;

// high quality etc
is_build = false;

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

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

$show_vit = is_build ? false : true;

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

extrusion_height            = 0.4*mm;

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

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

thick_wall_factor           = 4;

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

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

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

extrusion_mount_thread = ThreadM4;

// for tapped ends
extrusion_end_nut = NutHexM6;

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

gantry_connector_thickness = 5;

rod_fit_tolerance=1.01;

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

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

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

xaxis_belt = TimingBelt_GT2_2;
xaxis_belt_width = 6*mm;
xaxis_beltpath_width = max(xaxis_belt_width+3*mm, xaxis_pulley[0]+2*mm);
xaxis_beltpath_z_offset_pulley = xaxis_pulley_inner_d/2;
/*xaxis_beltpath_z_offsets = [xaxis_beltpath_z_offset_pulley];*/
xaxis_beltpath_z_offsets = [-3*mm-xaxis_beltpath_z_offset_pulley, 3*mm+xaxis_beltpath_z_offset_pulley];
xaxis_beltpath_height_body = xaxis_pulley_outer_d/2+3*mm+v_sum(v_abs(xaxis_beltpath_z_offsets))+5*mm;
xaxis_beltpath_height_holders = max(xaxis_pulley_outer_d+2*mm, xaxis_pulley_inner_d+xaxis_beltpath_z_offsets[0]+3*mm);

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

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

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

yaxis_rod_distance = 170*mm;
yaxis_rod_d = 11.975*mm;
yaxis_rod_l = 500*mm;
yaxis_bearing = LinearBearingKH1228;
yaxis_bearing_distance_y = 7*cm;

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

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

yaxis_belt = TimingBelt_GT2_2;
yaxis_belt_width = 6*mm;
yaxis_belt_path_offset_x = -yaxis_pulley_inner_d/2;
yaxis_belt_path_offset_z = yaxis_motor_offset_z + 10*mm;

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

yaxis_carriage_size = [220*mm,220*mm,5*mm];
printbed_size = [213*mm,213*mm,3*mm];
Mat_PrintCarriage = Mat_Aluminium;
Mat_PrintBed = [.6,.5,.5];

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

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

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

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

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

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

zmotor_mount_clamp_dist = zaxis_rod_d*2.5;
zmotor_mount_clamp_thread = extrusion_mount_thread;
zmotor_mount_clamp_nut = NutHexM4;
zmotor_mount_clamp_thread_dia = lookup(ThreadSize, zmotor_mount_clamp_thread);
zmotor_mount_clamp_nut_dia = lookup(NutWidthMin, zmotor_mount_clamp_nut);
zmotor_mount_clamp_nut_thick = lookup(NutThickness, zmotor_mount_clamp_nut);
zmotor_mount_clamp_width = zmotor_mount_clamp_dist+zmotor_mount_clamp_thread_dia*3;

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

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

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

// z screw offset from lower extrusion (outer)
zmotor_mount_screw_offset_x = zmotor_w/2 + zmotor_mount_motor_offset;

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


properly display sample objects

properly display sample objects

//
// Common extrusions
// Author: Joseph M. Joy FTC 12598 mentor
//
EPSILON = 0.01; // For moving things to properly punch out holes

// Makes a flat (horizontal) "T":
//
// --------------
// |wtXht     --|
// ----\     /---
//      |wbX|
//      |hb |
//      -----
//<xoff>
//
// It could also be an inverted L shape
// if the lower (vertical) bar is wide enough to extend beyond the right
// hand side of the upper (horizontal) bar.
//
// {xoff} is horizontal distance to the start of the bar.
// {ro} curve of convex corners (not shown above)
// {ri} is the radius of two concave curves
// curve shown as diagonals above.
// t is the thickness of the plate - in
// the z direction.
// Origin is the left hand corner
// of the bounding rectangle.
//
// WARNING: If {ro} and {ri} are too large it will generate sharp
// extrusion artifacts because the straight surfaces are not large to accomodate
// the inner-radius curves.
//
module T_channelOld(wb, hb, wt, ht, xoff, r, t) {
    ow = 2*wt; // wide enough to
    oh = 2*(hb+ht); // high enough to descend below the shape

    difference() {
        cube([wt, hb+ht, t]);
        translate([xoff-ow,hb-oh,-EPSILON]) oblong(ow, oh, r, t+2*EPSILON);
        translate([xoff+wb,hb-oh,-EPSILON]) oblong(ow, oh, r, t+2*EPSILON);
    }
}

module T_channel(wb, hb, wt, ht, xoff, ro, ri, t) {

    // ow and oh are used to create cutout patterns
    ow = 2*wt; // wide enough to extend to the left and right of shape
    oh = 2*(hb+ht); // high enough to descend below the shape

    // Dimensions of the plate that will be cut out - it is just
    // big enough so that the inner-radii can be cut out, no more.
    wp = wb + 2*ri + 2*EPSILON; // dimensions of plate to be cut out
    hp = max(ro, ri) + 2*EPSILON;
    xoffp = xoff - ri - EPSILON;
    yoffp = hb - max(ro, ri) - EPSILON;
    difference() {
        translate([xoffp, yoffp, 0]) cube([wp, hp, t]);
        translate([xoff-ow,hb-oh,-EPSILON]) oblong(ow, oh, ri, t+2*EPSILON);
        translate([xoff+wb,hb-oh,-EPSILON]) oblong(ow, oh, ri, t+2*EPSILON);
    }
    translate([xoff, 0, 0]) oblong(wb, hb, ro, t);
    translate([0, hb, 0]) oblong(wt, ht, ro, t);
}

// Makes a flat (horizontal) "O":
//
// /-------------\
// |             |
// | /--------\  |
// | |         | |
// | |         | |
// | |         | |
// | \         / |
// |  ---------  |
// \------------/
//
//
// It could also be a U or L
// if the oblong hole extends outside the outer
// boundary.
//
// ({xoff},{yoff} is origin of bounding-rectangle of the oblong hole
// {(wo}, {ho}) is the bounding box of the outer oblong.
// {(wi}, {hi}) is the bounding box of the inner (hole) oblong.
// {r} is the radius of the
// curve shown as diagonals above.
// t is the thickness of the plate - in
// the z direction.
// Origin is the left hand corner
// of the bounding rectangle.
//
module O_channel(wo, ho, wi, hi, xoff, yoff, ro, ri, t) {
    difference() {
        oblong(wo, ho, ro, t);
        translate([xoff, yoff, -EPSILON]) oblong(wi, hi, ri, t+2*EPSILON);
    }
}

// A rectangular prism that fits within {w} x {h} and
// has rounded corners with radius {r} on all 4 sides.
// The actual radius may be reduced so keep the oblong
// viable. {t} is the thickness (in z).
module oblong(w, h, r, t) {
    r = min(r, w/2-EPSILON, h/2-EPSILON);
    translate([r, r, 0])
    linear_extrude(height = t, center = false, convexity = 10) {
        offset(r = r) square([w-2*r, h-2*r]);
    }
}

// A cube that fits within ({w}, {h}, {d}) and has
// all corners rounded with radius r.
module rounded_cube(w, h, d, r) {
        r =  min(r, w/2-EPSILON, h/2-EPSILON, d/2-EPSILON);
        di = 2*r;
    translate([r, r, r]) {
        minkowski() {
            echo(di);
            cube([w-di, h-di, d-di]);
            sphere(r=r);
        }
    }
}

//
// Example code
//
wb = 10;
hb = 20;
wt = 40;
ht = 30;
t = 5;
ro = 5;
ri = 2;
xoff = 10;
move = 30;
$fn = 50;
oblong(wb, hb, ro, t);
translate([0, move, 0]) rounded_cube(wb, hb, t, ro);//, $fn=100);
translate([move, 0, 0]) T_channel(wb, hb, wt, ht, xoff, 5, 1, t);
translate([move, 2*move, 0]) O_channel(wt, hb+ht, wb, 10*hb, xoff, xoff, ro, ri, t);

//
// Common extrusions
// Author: Joseph M. Joy FTC 12598 mentor
//
EPSILON = 0.01; // For moving things to properly punch out holes

// Makes a flat (horizontal) "T":
//
// --------------
// |wtXht     --|
// ----\     /---
//      |wbX|
//      |hb |
//      -----
//<xoff>
//
// It could also be an inverted L shape
// if the lower (vertical) bar is wide enough to extend beyond the right
// hand side of the upper (horizontal) bar.
//
// {xoff} is horizontal distance to the start of the bar.
// {ro} curve of convex corners (not shown above)
// {ri} is the radius of two concave curves
// curve shown as diagonals above.
// t is the thickness of the plate - in
// the z direction.
// Origin is the left hand corner
// of the bounding rectangle.
//
// WARNING: If {ro} and {ri} are too large it will generate sharp
// extrusion artifacts because the straight surfaces are not large to accomodate
// the inner-radius curves.
//
module T_channelOld(wb, hb, wt, ht, xoff, r, t) {
    ow = 2*wt; // wide enough to
    oh = 2*(hb+ht); // high enough to descend below the shape

    difference() {
        cube([wt, hb+ht, t]);
        translate([xoff-ow,hb-oh,-EPSILON]) oblong(ow, oh, r, t+2*EPSILON);
        translate([xoff+wb,hb-oh,-EPSILON]) oblong(ow, oh, r, t+2*EPSILON);
    }
}

module T_channel(wb, hb, wt, ht, xoff, ro, ri, t) {

    // ow and oh are used to create cutout patterns
    ow = 2*wt; // wide enough to extend to the left and right of shape
    oh = 2*(hb+ht); // high enough to descend below the shape

    // Dimensions of the plate that will be cut out - it is just
    // big enough so that the inner-radii can be cut out, no more.
    wp = wb + 2*ri + 2*EPSILON; // dimensions of plate to be cut out
    hp = max(ro, ri) + 2*EPSILON;
    xoffp = xoff - ri - EPSILON;
    yoffp = hb - max(ro, ri) - EPSILON;
    difference() {
        translate([xoffp, yoffp, 0]) cube([wp, hp, t]);
        translate([xoff-ow,hb-oh,-EPSILON]) oblong(ow, oh, ri, t+2*EPSILON);
        translate([xoff+wb,hb-oh,-EPSILON]) oblong(ow, oh, ri, t+2*EPSILON);
    }
    translate([xoff, 0, 0]) oblong(wb, hb, ro, t);
    translate([0, hb, 0]) oblong(wt, ht, ro, t);
}

// Makes a flat (horizontal) "O":
//
// /-------------\
// |             |
// | /--------\  |
// | |         | |
// | |         | |
// | |         | |
// | \         / |
// |  ---------  |
// \------------/
//
//
// It could also be a U or L
// if the oblong hole extends outside the outer
// boundary.
//
// ({xoff},{yoff} is origin of bounding-rectangle of the oblong hole
// {(wo}, {ho}) is the bounding box of the outer oblong.
// {(wi}, {hi}) is the bounding box of the inner (hole) oblong.
// {r} is the radius of the
// curve shown as diagonals above.
// t is the thickness of the plate - in
// the z direction.
// Origin is the left hand corner
// of the bounding rectangle.
//
module O_channel(wo, ho, wi, hi, xoff, yoff, ro, ri, t) {
    difference() {
        oblong(wo, ho, ro, t);
        translate([xoff, yoff, -EPSILON]) oblong(wi, hi, ri, t+2*EPSILON);
    }
}

// A rectangular prism that fits within {w} x {h} and
// has rounded corners with radius {r} on all 4 sides.
// The actual radius may be reduced so keep the oblong
// viable. {t} is the thickness (in z).
module oblong(w, h, r, t) {
    r = min(r, w/2-EPSILON, h/2-EPSILON);
    translate([r, r, 0])
    linear_extrude(height = t, center = false, convexity = 10) {
        offset(r = r) square([w-2*r, h-2*r]);
    }
}

// A cube that fits within ({w}, {h}, {d}) and has
// all corners rounded with radius r.
module rounded_cube(w, h, d, r) {
        r =  min(r, w/2-EPSILON, h/2-EPSILON, d/2-EPSILON);
        di = 2*r;
    translate([r, r, r]) {
        minkowski() {
            echo(di);
            cube([w-di, h-di, d-di]);
            sphere(r=r);
        }
    }
}

//
// Example code
//
wb = 10;
hb = 20;
wt = 40;
ht = 30;
t = 5;
ro = 5;
ri = 2;
xoff = 10;
move = 30;
oblong(wb, hb, ro, t);
!translate([0, move, 0]) rounded_cube(wb, hb, t, 0);//, $fn=100);
translate([move, 0, 0]) T_channel(wb, hb, wt, ht, xoff, 5, 1, t);
translate([move, 2*move, 0]) O_channel(wt, hb+ht, wb, 10*hb, xoff, xoff, ro, ri, t);


config: fix ziptie width

config: fix ziptie width

Was hacked to wrong width due to bug in hollow_cylinder

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

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, 4*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";


inverted base orientation

inverted base orientation

use <projector_plate.scad>;
include <projector.scad>;
use <plate.scad>;
include <profile.scad>;
use <../scad/ob_wheel.scad>
use <../scad/ob_spacer.scad>
include <gantry_cart.scad>
use <../scad/brackets.scad>
use <../scad/geom.scad>
use <support_projector_beam.scad>
include <materials.scad>
use <basin_support.scad>
use <big_screw.scad>

module printer(projector_position = 0) {
  offset_depth = 50;

  middle_sections = 2;

  height = 500;
  width = 560;
  base_depth = 400;
  display_projection = false;
  base_sections = 3;

  projector_movement = height / 2 - acer_projector_distances[projector_position] + middle_sections * 20;

  // projector
  translate([0, 0, -offset_depth]) {
    translate([0, projector_movement, 0]) {
      center_projector() {
        Acer_Plate(160, 120, 85, 100);
        Acer_H6510BD(display_projection);
      }
    }
  }
  beam_offset = 10;
  beam_width = width - 2 * beam_offset;

  carriage_tower_sections = 3;

  translate([0, projector_movement, -offset_depth]) {
    translate([-beam_width/2,-20 * base_sections,-10])
      rotate([90,90,90])
        profile(base_sections, beam_width);
  /*
    translate([beam_width/2,-60,-10])
      rotate([90,0,90])
        gantry_cart_big(carriage_tower_sections, offset = 1);
    translate([-beam_width/2,-60,-10])
      rotate([90,0,-90])
        gantry_cart_big(carriage_tower_sections, offset = 1);
  */
  }

  // projector towers
  translate([0, 0, -offset_depth]) {
    translate([-width/2,-height/2,-10])
      rotate([-90,0,0])
        profile(carriage_tower_sections, height);
    translate([width/2,-height/2,-10])
      rotate([-90,0,0])
        profile(carriage_tower_sections, height);
  }

  // supports for horizontal beam
  translate([0, middle_sections * 20, -offset_depth])
  for(d = acer_projector_distances) {
    translate([0,d-height/2+10,0])
      support_projector_beam(width-60);
  }
  //height / 2 - d

  // base
  module base(width, depth, sections = 2) {
    translate([-width/2,0,-base_depth/2])
      rotate([0,0,0])
        profile(sections, base_depth);

    translate([width/2,0,-base_depth/2])
      rotate([0,0,0])
        profile(sections, base_depth);

    lateral_beam_width = width - 20;
    translate([-lateral_beam_width/2,0,-base_depth/2+10])
      rotate([0,90,0])
        profile(sections, lateral_beam_width);

    translate([-lateral_beam_width/2,0,base_depth/2-10])
      rotate([0,90,0])
        profile(sections, lateral_beam_width);
  }

  module baser(width, depth, sections = 2) {
    translate([(- width + sections * 20) / 2 - 10, -10, -base_depth/2])
      rotate([0,0,90])
        profile(sections, base_depth);

    translate([(  width - sections * 20) / 2 + 10, -10, -base_depth/2])
      rotate([0,0,90])
        profile(sections, base_depth);

    lateral_beam_width = width - 30 * sections;
    translate([-lateral_beam_width/2, -10, -base_depth/2+30])
      rotate([90,0,90])
        profile(sections, lateral_beam_width);
    translate([-lateral_beam_width/2, -10, base_depth/2-30])
      rotate([90,0,90])
        profile(sections, lateral_beam_width);
  }

  bottom_sections = 3;
  translate([0,-(height+bottom_sections*20)/2,0])
    base(width, base_depth, bottom_sections);

  translate([0,(height+middle_sections*20)/2,0])
    baser(width, base_depth, 3);

  // support towers
  tower_pos = base_depth / 2 - 10;
  translate([-width/2,-height/2,tower_pos])
    rotate([-90,0,0])
      profile(1, height);
  translate([width/2,-height/2,tower_pos])
    rotate([-90,0,0])
      profile(1, height);

  rotate([0,180,0]) {

    offset = 16;
    plate_width = width - 20 - offset * 2;
    plate_depth = base_depth - 60 * 2;
    cut_width = 440;
    cut_offset = 7.5;
    translate([
      -plate_width/2,
      height/2 + 20,
      -plate_depth / 2 + 20 - offset])
      basin_support(plate_width, plate_depth, cut_width, cut_offset);

    translate([0, height/2 + 20 * middle_sections, base_depth / 2 + 20])
      big_screw();

    // TODO review
    screw_height = 640;
    rail_sections = 2;
    rotate([-90, 0, 0]) {
      translate([65, -base_depth / 2 - 20, -height / 2 - 20 * (bottom_sections)]) {
        profile(rail_sections, screw_height + height + 20 * (bottom_sections + middle_sections));
      }
      translate([-65, -base_depth / 2 - 20, -height / 2 - 20 * (bottom_sections)]) {
        profile(rail_sections, screw_height + height + 20 * (bottom_sections + middle_sections));
      }
    }
    translate([0,0,30]) {
      translate([40, height / 2 + 20 * middle_sections + 260, base_depth / 2 + 20])
        rotate([0, 180, 0])
          profile(4, 240);
      translate([-40, height / 2 + 20 * middle_sections + 260, base_depth / 2 + 20])
        rotate([0, 180, 0])
          profile(4, 240);
      translate([-50, height / 2 + 20 * middle_sections + 300, base_depth / 2 -60])
        plate(100, 4, 80);
      translate([-50, height / 2 + 20 * middle_sections + 216, base_depth / 2 -60])
        plate(100, 4, 80);
      translate([0, height / 2 + 20 * middle_sections + 300, base_depth / 2 - 210])
        rotate([90,90,0])
          profile(3, 140);

      translate([65, height / 2 + 20 * middle_sections + 300 - 10, base_depth / 2 - 20 - rail_sections * 10])
        rotate([0,90,0])
          ob_solid_wheel();
      translate([65, height / 2 + 20 * middle_sections + 240 - 10, base_depth / 2 - 20 - rail_sections * 10])
        rotate([0,90,0])
          ob_solid_wheel();
      translate([65, height / 2 + 20 * middle_sections + 270 - 10, base_depth / 2 + rail_sections * 10])
        rotate([0,90,0])
          ob_solid_wheel();

      translate([-65, height / 2 + 20 * middle_sections + 300 - 10, base_depth / 2 - 20 - rail_sections * 10])
        rotate([0,90,0])
          ob_solid_wheel();
      translate([-65, height / 2 + 20 * middle_sections + 240 - 10, base_depth / 2 - 20 - rail_sections * 10])
        rotate([0,90,0])
          ob_solid_wheel();
      translate([-65, height / 2 + 20 * middle_sections + 270 - 10, base_depth / 2 + rail_sections * 10])
        rotate([0,90,0])
          ob_solid_wheel();
    }
  }
}

use <projector_plate.scad>;
include <projector.scad>;
use <plate.scad>;
include <profile.scad>;
use <../scad/ob_wheel.scad>
use <../scad/ob_spacer.scad>
include <gantry_cart.scad>
use <../scad/brackets.scad>
use <../scad/geom.scad>
use <support_projector_beam.scad>
include <materials.scad>
use <basin_support.scad>
use <big_screw.scad>

module printer(projector_position = 0) {
  offset_depth = 50;

  middle_sections = 2;

  height = 500;
  width = 500;
  base_depth = 360;
  display_projection = false;
  base_sections = 3;

  projector_movement = height / 2 - acer_projector_distances[projector_position] + middle_sections * 20;

  // projector
  translate([0, 0, -offset_depth]) {
    translate([0, projector_movement, 0]) {
      center_projector() {
        Acer_Plate(160, 120, 85, 100);
        Acer_H6510BD(display_projection);
      }
    }
  }
  beam_offset = 10;
  beam_width = width - 2 * beam_offset;

  carriage_tower_sections = 3;

  translate([0, projector_movement, -offset_depth]) {
    translate([-beam_width/2,-20 * base_sections,-10])
      rotate([90,90,90])
        profile(base_sections, beam_width);
  /*
    translate([beam_width/2,-60,-10])
      rotate([90,0,90])
        gantry_cart_big(carriage_tower_sections, offset = 1);
    translate([-beam_width/2,-60,-10])
      rotate([90,0,-90])
        gantry_cart_big(carriage_tower_sections, offset = 1);
  */
  }

  // projector towers
  translate([0, 0, -offset_depth]) {
    translate([-width/2,-height/2,-10])
      rotate([-90,0,0])
        profile(carriage_tower_sections, height);
    translate([width/2,-height/2,-10])
      rotate([-90,0,0])
        profile(carriage_tower_sections, height);
  }

  // supports for horizontal beam
  translate([0, middle_sections * 20, -offset_depth])
  for(d = acer_projector_distances) {
    translate([0,d-height/2+10,0])
      support_projector_beam(width-60);
  }
  //height / 2 - d

  // base
  module base(width, depth, sections = 2) {
    profile_height = sections * 20;
    translate([-width/2,0,-base_depth/2])
      rotate([0,0,0])
        profile(sections, base_depth);

    translate([width/2,0,-base_depth/2])
      rotate([0,0,0])
        profile(sections, base_depth);

    lateral_beam_width = width - 20;
    translate([-lateral_beam_width/2,0,-base_depth/2+10])
      rotate([0,90,0])
        profile(sections, lateral_beam_width);

    translate([-lateral_beam_width/2,0,base_depth/2-10])
      rotate([0,90,0])
        profile(sections, lateral_beam_width);
  }

  bottom_sections = 3;
  translate([0,-(height+bottom_sections*20)/2,0])
    base(width, base_depth, bottom_sections);

  translate([0,(height+middle_sections*20)/2,0])
    base(width, base_depth, middle_sections);

  // support towers
  tower_pos = base_depth / 2 - 10;
  translate([-width/2,-height/2,tower_pos])
    rotate([-90,0,0])
      profile(1, height);
  translate([width/2,-height/2,tower_pos])
    rotate([-90,0,0])
      profile(1, height);

  rotate([0,180,0]) {

    offset = 16;
    plate_width = width + 20 - offset * 2;
    plate_depth = base_depth - 20 * 2;
    cut_width = 440;
    cut_offset = 7.5;
    translate([
      -plate_width/2,
      height/2 + middle_sections * 20,
      -plate_depth / 2 + 20 - offset])
      basin_support(plate_width, plate_depth, cut_width, cut_offset);

    translate([0, height/2 + 20 * middle_sections, base_depth / 2 + 20])
      big_screw();

    // TODO review
    screw_height = 640;
    rail_sections = 2;
    rotate([-90, 0, 0]) {
      translate([65, -base_depth / 2 - 20, -height / 2 - 20 * (bottom_sections)]) {
        profile(rail_sections, screw_height + height + 20 * (bottom_sections + middle_sections));
      }
      translate([-65, -base_depth / 2 - 20, -height / 2 - 20 * (bottom_sections)]) {
        profile(rail_sections, screw_height + height + 20 * (bottom_sections + middle_sections));
      }
    }
    translate([0,0,30]) {
      translate([40, height / 2 + 20 * middle_sections + 260, base_depth / 2 + 20])
        rotate([0, 180, 0])
          profile(4, 240);
      translate([-40, height / 2 + 20 * middle_sections + 260, base_depth / 2 + 20])
        rotate([0, 180, 0])
          profile(4, 240);
      translate([-50, height / 2 + 20 * middle_sections + 300, base_depth / 2 -60])
        plate(100, 4, 80);
      translate([-50, height / 2 + 20 * middle_sections + 216, base_depth / 2 -60])
        plate(100, 4, 80);
      translate([0, height / 2 + 20 * middle_sections + 300, base_depth / 2 - 210])
        rotate([90,90,0])
          profile(3, 140);

      translate([65, height / 2 + 20 * middle_sections + 300 - 10, base_depth / 2 - 20 - rail_sections * 10])
        rotate([0,90,0])
          ob_solid_wheel();
      translate([65, height / 2 + 20 * middle_sections + 240 - 10, base_depth / 2 - 20 - rail_sections * 10])
        rotate([0,90,0])
          ob_solid_wheel();
      translate([65, height / 2 + 20 * middle_sections + 270 - 10, base_depth / 2 + rail_sections * 10])
        rotate([0,90,0])
          ob_solid_wheel();

      translate([-65, height / 2 + 20 * middle_sections + 300 - 10, base_depth / 2 - 20 - rail_sections * 10])
        rotate([0,90,0])
          ob_solid_wheel();
      translate([-65, height / 2 + 20 * middle_sections + 240 - 10, base_depth / 2 - 20 - rail_sections * 10])
        rotate([0,90,0])
          ob_solid_wheel();
      translate([-65, height / 2 + 20 * middle_sections + 270 - 10, base_depth / 2 + rail_sections * 10])
        rotate([0,90,0])
          ob_solid_wheel();
    }
  }
}


Added washer to toggle switch

Added washer to toggle switch

/*
    Vitamin: Mini Toggle Switch

    Local Frame:
        Switch is centred in XY
        Toggle is pointing up Z+
        Mounting face lies in XY plane at Z=0
*/

// Type Getters
function MiniToggleSwitch_TypeSuffix(t)    = t[0];
function MiniToggleSwitch_BodyWidth(t)     = t[1];
function MiniToggleSwitch_BodyDepth(t)     = t[2];
function MiniToggleSwitch_BodyHeight(t)    = t[3];
function MiniToggleSwitch_BarrelOD(t)      = t[4];
function MiniToggleSwitch_BarrelLength(t)  = t[5];
function MiniToggleSwitch_WasherOD(t)      = t[6];

// Type table
//                          TypeSuffix  BodyW BodyD BodyH BarrelOD BarrelL WasherOD
MiniToggleSwitch_SPST6A  = ["SPST6A",   12.5, 8,    10,   5,       9,      12       ];

// Type collection
MiniToggleSwitch_Types = [
    MiniToggleSwitch_SPST6A
];

// Vitamin catalogue
module MiniToggleSwitch_Catalogue() {
    for (t = MiniToggleSwitch_Types) MiniToggleSwitch(t);
}

// Connectors

MiniToggleSwitch_Con_Def				= [ [0,0,0], [0,0,1], 0, 0, 0];

module MiniToggleSwitch(type=MiniToggleSwitch_SPST6A, showWasher=true, washerOffset=3) {

    ts = MiniToggleSwitch_TypeSuffix(type);

    vitamin(
        "vitamins/MiniToggleSwitch.scad",
        str(ts,"Mini Toggle Switch"),
        str("MiniToggleSwitch(",ts,")")
    ) {
        view(t=[6.9, 13.6, 10.3], r=[72,0,33], d=280);

        if (DebugCoordinateFrames) frame();
        if (DebugConnectors) {
            connector(MiniToggleSwitch_Con_Def);
        }

        // parts
        MiniToggleSwitch_Body(type, showWasher, washerOffset);
    }
}

module MiniToggleSwitch_Body(t, showWasher=true, washerOffset=3) {
    ts = MiniToggleSwitch_TypeSuffix(t);

    // local shortcuts
    bw = MiniToggleSwitch_BodyWidth(t);
    bd = MiniToggleSwitch_BodyDepth(t);
    bh = MiniToggleSwitch_BodyHeight(t);
    bod = MiniToggleSwitch_BarrelOD(t);
    bl = MiniToggleSwitch_BarrelLength(t);
    wod = MiniToggleSwitch_WasherOD(t);

    // light metal bits
    color([0.8, 0.8, 0.8]) {
        // toggle
        // Assume half the barrel OD, and same length
        translate([0,0,bl- bod/2])
            rotate([0,15,0])
            cylinder(r=bod/4, h=bl+ bod/2);

        // threaded barrel
        cylinder(r=bod/2, h=bl);

        // body
        translate([-bw/2, -bd/2, -0.5])
            cube([bw,bd,0.5]);
        translate([-(bw-2)/2, -(bd+0.5)/2, -bh/2])
            cube([(bw-2),(bd+0.5), bh/2]);

        // terminals
        // TODO: parameterise this to account for diff terminal layouts/sizes
        for (i=[-1,0])
            translate([i* 4, -bd/6, -bh-4])
            cube([0.5, bd/3, 4]);

        if (showWasher) {
            // washer
            translate([0,0,washerOffset])
                tube(wod/2, bod/2, 1, center=false);

            // nut
            translate([0,0,washerOffset + 1])
                cylinder(r=bod/2 + 2, h=1.5, $fn=6);
        }

    }

    // plastic bits
    color([0.2, 0.6, 1]) {
        // body
        translate([-bw/2, -bd/2, -bh])
            cube([bw,bd,bh-0.5]);
    }
}

/*
    Vitamin: Mini Toggle Switch

    Local Frame:
        Switch is centred in XY
        Toggle is pointing up Z+
        Mounting face lies in XY plane at Z=0
*/

// Type Getters
function MiniToggleSwitch_TypeSuffix(t)    = t[0];
function MiniToggleSwitch_BodyWidth(t)     = t[1];
function MiniToggleSwitch_BodyDepth(t)     = t[2];
function MiniToggleSwitch_BodyHeight(t)    = t[3];
function MiniToggleSwitch_BarrelOD(t)      = t[4];
function MiniToggleSwitch_BarrelLength(t)  = t[5];

// Type table
//                          TypeSuffix  BodyW BodyD BodyH BarrelOD BarrelL
MiniToggleSwitch_SPST6A  = ["SPST6A",   12.5, 8,    10,   5,       9       ];

// Type collection
MiniToggleSwitch_Types = [
    MiniToggleSwitch_SPST6A
];

// Vitamin catalogue
module MiniToggleSwitch_Catalogue() {
    for (t = MiniToggleSwitch_Types) MiniToggleSwitch(t);
}

// Connectors

MiniToggleSwitch_Con_Def				= [ [0,0,0], [0,0,1], 0, 0, 0];

module MiniToggleSwitch(type=MiniToggleSwitch_SPST6A) {

    ts = MiniToggleSwitch_TypeSuffix(type);

    vitamin(
        "vitamins/MiniToggleSwitch.scad",
        str(ts,"Mini Toggle Switch"),
        str("MiniToggleSwitch(",ts,")")
    ) {
        view(t=[6.9, 13.6, 10.3], r=[72,0,33], d=280);

        if (DebugCoordinateFrames) frame();
        if (DebugConnectors) {
            connector(MiniToggleSwitch_Con_Def);
        }

        // parts
        MiniToggleSwitch_Body(type);
    }
}

module MiniToggleSwitch_Body(t) {
    ts = MiniToggleSwitch_TypeSuffix(t);

    // local shortcuts
    bw = MiniToggleSwitch_BodyWidth(t);
    bd = MiniToggleSwitch_BodyDepth(t);
    bh = MiniToggleSwitch_BodyHeight(t);
    bod = MiniToggleSwitch_BarrelOD(t);
    bl = MiniToggleSwitch_BarrelLength(t);

    // light metal bits
    color([0.8, 0.8, 0.8]) {
        // toggle
        // Assume half the barrel OD, and same length
        translate([0,0,bl- bod/2])
            rotate([0,15,0])
            cylinder(r=bod/4, h=bl+ bod/2);

        // threaded barrel
        cylinder(r=bod/2, h=bl);

        // body
        translate([-bw/2, -bd/2, -0.5])
            cube([bw,bd,0.5]);
        translate([-(bw-2)/2, -(bd+0.5)/2, -bh/2])
            cube([(bw-2),(bd+0.5), bh/2]);

        // terminals
        // TODO: parameterise this to account for diff terminal layouts/sizes
        for (i=[-1,0])
            translate([i* 4, -bd/6, -bh-4])
            cube([0.5, bd/3, 4]);

    }

    // plastic bits
    color([0.2, 0.6, 1]) {
        // body
        translate([-bw/2, -bd/2, -bh])
            cube([bw,bd,bh-0.5]);
    }
}