- box_height = 26.75;
- box_wall_thickness = 2;
- box_board_spacing = 0.25;
- box_connector_spacing = 0.25;
- //
- // Utilities
- //
- module mirror_copy(v = [1, 0, 0]) {
- children();
- mirror(v) children();
- }
- //
- // Board
- //
- board_thickness = 1.60;
- board_size = [57.0, 40.6];
- board_hole_dia = 3;
- board_hole_spacing = [52.5, 36.5];
- led_hole_dia = 3.0;
- led_standoff = 1.5;
- led_hole_chamfer_dia = led_hole_dia + 2.0;
- led_wall_thickness = box_wall_thickness / 2;
- led_positions = [
- [-board_size[0] / 2 + 20.5, 11.75],
- [-board_size[0] / 2 + 20.5, -11.75],
- [-board_size[0] / 2 + 4.5, -board_size[1] / 2 + 6.0]
- ];
- module led() {
- color([1, 1, 0]) linear_extrude(0.70) square([3.0, 1.25], center=true);
- }
- module board() {
- color([0.8, 0, 0]) translate([0, 0, -board_thickness]) linear_extrude(board_thickness) {
- difference() {
- square(board_size, center=true);
- mirror_copy([1, 0]) mirror_copy([0, 1])
- translate(board_hole_spacing / 2)
- circle(d=board_hole_dia, $fn=16);
- }
- }
- }
- relay_size = [18.8, 15.0, 15.5];
- relay_position = [board_size[0] / 2 - relay_size[0] / 2 - 8.5, relay_size[1] / 2 + 1.0];
- module relay() {
- color([0.2, 0.4, 0.9])
- translate([-relay_size[0]/2, -relay_size[1]/2, 0])
- cube(relay_size);
- }
- usb_connector_size = [16.5, 12.3, 11.0];
- usb_connector_overhang = 6.0;
- usb_connector_position = [-board_size[0] / 2 + usb_connector_size[0] / 2 - usb_connector_overhang, 0];
- module usb_connector() {
- color([0.75, 0.75, 0.75])
- translate([-usb_connector_size[0]/2, -usb_connector_size[1]/2, 0])
- cube(usb_connector_size);
- }
- terminal_block_size = [7.5, 15];
- terminal_block_height = 10.0;
- terminal_block_spacing = 1.5;
- terminal_block_total_width = terminal_block_size[1] * 2 + terminal_block_spacing;
- terminal_block_position = [board_size[0] / 2 - terminal_block_size[0] / 2,
- -terminal_block_size[1] / 2 - terminal_block_spacing / 2];
- module terminal_block() {
- color([0.3, 0.8, 0.2])
- translate(-terminal_block_size/2) rotate([0, -90, -90]) linear_extrude(15.0)
- polygon([[0, 0], [7.0, 0], [10.0, 2.0], [10.0, 6.5], [7.0, 7.5], [0.0, 7.5]]);
- }
- module board_assembly() {
- board();
- mirror_copy([0, 1, 0]) translate(relay_position) relay();
- translate(usb_connector_position) usb_connector();
- mirror_copy([0, 1, 0]) translate(terminal_block_position) terminal_block();
- for (p=led_positions) translate(p) led();
- }
- //
- // Common
- //
- box_hole_dia = 3.2;
- screw_head_dia = 5.7;
- screw_head_height = 1.8;
- box_inside_width = board_size[1] + box_board_spacing * 2;
- module box_inside() {
- translate([-board_size[0] / 2 - usb_connector_overhang + box_wall_thickness,
- -box_inside_width / 2])
- square([board_size[0] + usb_connector_overhang - box_wall_thickness + box_board_spacing,
- box_inside_width]);
- }
- terminal_block_cutout_width = terminal_block_total_width + box_connector_spacing * 2;
- terminal_block_cotout_start = terminal_block_position[0] - terminal_block_size[0] / 2 + 2;
- module connector_cutouts() {
- translate([0, 0, -box_connector_spacing])
- linear_extrude(usb_connector_size[2] + box_connector_spacing * 2)
- translate([-100, -usb_connector_size[1]/2 - box_connector_spacing])
- square([100, usb_connector_size[1] + box_connector_spacing * 2]);
- translate([terminal_block_cotout_start, 0, -box_connector_spacing])
- linear_extrude(100)
- translate([0, -terminal_block_cutout_width/2])
- square([100, terminal_block_cutout_width]);
- }
- module back_pillars() {
- mirror([1, 0]) mirror_copy([0, 1])
- translate(board_hole_spacing / 2)
- children();
- }
- module pillars() {
- mirror_copy([1, 0]) back_pillars() children();
- }
- //
- // Bottom
- //
- bottom_height = 7.0;
- box_lip_height = 2.0;
- box_lip_offset = 0.1;
- box_base_thickness = 3.0;
- bottom_pillar_width = box_inside_width - board_hole_spacing[1];
- nut_dia = 5.6 / cos(30);
- nut_thickness = 2.5;
- module bottom() {
- render() difference() {
- union() {
- difference() {
- translate([0, 0, -bottom_height])
- linear_extrude(bottom_height + box_lip_height)
- offset(box_wall_thickness, $fn=32)
- box_inside();
- linear_extrude(100)
- offset(box_wall_thickness / 2 + box_lip_offset, $fn=16)
- box_inside();
- translate([0, 0, -bottom_height + box_base_thickness])
- linear_extrude(100)
- box_inside();
- }
- translate([0, 0, -bottom_height]) linear_extrude(bottom_height - board_thickness)
- pillars() offset(box_wall_thickness / 2, $fn=32)
- square([bottom_pillar_width, bottom_pillar_width], center=true);
- }
- connector_cutouts();
- translate([0, 0, -100]) linear_extrude(100) pillars() circle(d=box_hole_dia, $fn=32);
- translate([0, 0, -bottom_height]) linear_extrude(nut_thickness) pillars() circle(d=nut_dia, $fn=6);
- }
- }
- //
- // Top
- //
- text_spacing = 5;
- text_depth = 0.5;
- text_height = 2.5;
- text_label_offset = 10;
- module relay_label(label) {
- rotate([0, 0, 180]) union() {
- translate([text_label_offset, 0, 0]) text(label, text_height * 2, font="Arial", valign="center");
- translate([0, -text_spacing, 0]) text("NC", text_height, font="Arial", valign="center");
- text("COM", text_height, font="Arial", valign="center");
- translate([0, text_spacing, 0]) text("NO", text_height, font="Arial", valign="center");
- }
- }
- module labels() {
- translate([terminal_block_cotout_start - 2.0, terminal_block_position[1]]) relay_label("1");
- translate([terminal_block_cotout_start - 2.0, -terminal_block_position[1]]) relay_label("2");
- }
- top_height = box_height - bottom_height;
- top_pillar_width = box_hole_dia;
- module top() {
- render() difference() {
- union() {
- difference() {
- minkowski($fn=32) {
- linear_extrude(top_height - box_wall_thickness) box_inside();
- sphere(box_wall_thickness);
- }
- linear_extrude(top_height - box_wall_thickness) box_inside();
- connector_cutouts();
- translate([-50, -50, -100]) cube([100, 100, 100]);
- }
- mirror_copy([0, 1, 0])
- translate([terminal_block_cotout_start - 2.0, terminal_block_cutout_width / 2, 0])
- linear_extrude(top_height - box_wall_thickness)
- square([
- board_size[0] / 2 + box_board_spacing + box_wall_thickness - terminal_block_cotout_start,
- (box_inside_width - terminal_block_cutout_width) / 2]);
- linear_extrude(top_height - box_wall_thickness)
- back_pillars() offset(box_wall_thickness / 2, $fn=32)
- translate([-top_pillar_width/2, -top_pillar_width/2])
- square([top_pillar_width, top_pillar_width/2 + (box_inside_width - board_hole_spacing[1]) / 2]);
- translate([terminal_block_cotout_start, box_inside_width / 2, 0])
- rotate([90, 0, 0]) linear_extrude(box_inside_width)
- polygon([
- [-2.0, terminal_block_height + box_connector_spacing - 3.0],
- [-2.0, top_height],
- [0.0, top_height],
- [0.0, terminal_block_height + box_connector_spacing]]);
- for (p=led_positions) {
- translate([0, 0, led_standoff])
- translate(p) linear_extrude(top_height - led_standoff - box_wall_thickness)
- circle(d=led_hole_dia + led_wall_thickness * 2, $fn=32);
- }
- }
- linear_extrude(100) pillars() circle(d=box_hole_dia, $fn=32);
- translate([0, 0, top_height - screw_head_height])
- linear_extrude(100) pillars() circle(d=screw_head_dia, $fn=32);
- difference() {
- linear_extrude(box_lip_height) offset(100, $fn=4) box_inside();
- linear_extrude(100) offset(box_wall_thickness / 2 + box_lip_offset, $fn=32)
- box_inside();
- }
- translate([0, 0, top_height - text_depth]) linear_extrude(100) labels();
- for (p=led_positions) {
- translate(p) linear_extrude(100) circle(d=led_hole_dia, $fn=16);
- translate([0, 0, top_height - led_hole_chamfer_dia/2])
- translate(p) cylinder(h=led_hole_chamfer_dia/2, r1=0, r2=led_hole_chamfer_dia/2, $fn=32);
- }
- }
- }
- board_assembly();
- bottom();
- top();