Created
June 28, 2020 11:55
-
-
Save nophead/d148f2ec63454c9e8e36a14b3e4ccb69 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| //! Arduino thermostat to control a beer fridge to use it as an environmental chamber. | |
| // | |
| // GNU GPL v2 | |
| // [email protected] | |
| // hydraraptor.blogspot.com | |
| // | |
| // Top level model | |
| // | |
| $pp1_colour = "grey"; | |
| $pp2_colour = "white"; | |
| $extrusion_width = 0.5; | |
| include <NopSCADlib/lib.scad> | |
| use <NopSCADlib/printed/foot.scad> | |
| use <NopSCADlib/printed/printed_box.scad> | |
| iec = IEC_inlet_atx; | |
| iec2 = IEC_outlet; | |
| lcd = LCD1602A; | |
| switch_pcb = PERF80x20; | |
| tx = SMALLTX; | |
| arduino = ArduinoUno3; | |
| expansion = Keyes5p1; | |
| lcd_pcb = display_pcb(lcd); | |
| foot = Foot(d = 13, h = 5, t = 2, r = 1, screw = M3_dome_screw); | |
| module foot_stl() foot(foot); | |
| base_overlap = 2; | |
| height_overlap = 1; | |
| base_outset = 1; | |
| base_thickness = 2; | |
| base_screw = foot_screw(foot); | |
| base_insert = screw_insert(base_screw); | |
| base_boss_r = insert_hole_radius(base_insert) + 2; | |
| base_washer = screw_washer(base_screw); | |
| base_screw_used = base_thickness + washer_thickness(base_washer) + insert_length(base_insert) + foot_thickness(foot); | |
| base_screw_length = screw_shorter_than(base_screw_used); | |
| base_screw_overlap = max(0, base_screw_length - base_screw_used) + 0.5; | |
| base_boss_h = insert_length(base_insert) + base_screw_overlap; | |
| top_thickness = 2; | |
| partition_t = 2; | |
| tx_screw = tx_screw(tx); | |
| tx_insert = screw_insert(tx_screw); | |
| tx_washer = screw_washer(tx_screw); | |
| tx_screw_length = screw_shorter_than(tx_foot_thickness(tx) + 2 * washer_thickness(tx_washer) + insert_length(tx_insert) + 1); | |
| tx_z = insert_length(tx_insert) + 1.5; | |
| thermo_width = 15.5; | |
| thermo_length = 54; | |
| thermo_height = 15.5; | |
| case_inner_rad = 6; | |
| case_width = 1 + tx_foot_width(tx) / 2 + tx_bobbin_width(tx) / 2 + iec_width(iec) + case_inner_rad; | |
| case_depth = thermo_width + 2 + pcb_width(switch_pcb) + 2 + pcb_width(lcd_pcb) + 2 + partition_t + 3 + tx_depth(tx) + 3; | |
| case_height = 50; | |
| case_wall = 2; | |
| echo(case_width = case_width, case_depth = case_depth, case_height = case_height); | |
| tx_x = -case_width / 2 + tx_foot_width(tx) / 2 + 1; | |
| tx_y = case_depth / 2 - 3 - tx_depth(tx) / 2; | |
| wire_hole_x = -case_width / 2 + 7.5; | |
| wire_hole_z = top_thickness + 15; | |
| wire_hole_d = 5; | |
| thermo_y = -case_depth / 2 + thermo_width / 2; | |
| thermo_z = top_thickness + thermo_height / 2; | |
| switch_screw = pcb_screw(switch_pcb); | |
| switch_washer = screw_washer(switch_screw); | |
| switch_insert = screw_insert(switch_screw); | |
| switch_screw_length = 6; | |
| switch_positions = [[2.5, 3, "yellow"], [9.5, 3, "yellow"], [17.5, 3, "red"], [24.5, 3, "red"]]; | |
| switch_x = -case_width / 2 + 2 + pcb_length(switch_pcb) / 2; | |
| switch_y = thermo_y + thermo_width / 2 + pcb_width(switch_pcb) / 2 + 2; | |
| switch_z = 12.5 - pcb_thickness(switch_pcb); | |
| switch = button_12mm; | |
| thermo_x = switch_x; | |
| lcd_x = switch_x; | |
| lcd_y = switch_y + pcb_width(switch_pcb) / 2 + 2 + pcb_width(lcd_pcb) / 2; | |
| lcd_z = 1; | |
| lcd_screw = pcb_screw(lcd_pcb, hs_pan); | |
| lcd_insert = screw_insert(lcd_screw); | |
| lcd_screw_length = screw_shorter_than(pcb_thickness(lcd_pcb) + insert_length(lcd_insert)); | |
| partition_y = lcd_y + pcb_width(lcd_pcb) / 2 + 2 + partition_t / 2; | |
| iec_x = tx_x + tx_bobbin_width(tx) / 2 + iec_width(iec) / 2; | |
| iec_y = case_depth / 2 + case_wall; | |
| iec_z = top_thickness + iec_body_h(iec) / 2 + 1; | |
| iec2_z = iec_z + iec_flange_h(iec) / 2 + 1 + iec_flange_h(iec2) / 2; | |
| iec_insert = screw_insert(iec_screw(iec)); | |
| ssr_length = 44; | |
| ssr_depth = 11; | |
| ssr_height = 26; | |
| ssr_pin_l = 7; | |
| ssr_pin_d = 1; | |
| ssr_pin_y = ssr_depth / 2 - 1.5; | |
| ssr_pins = [2, 4, 9, 13]; | |
| ssr_x = case_width / 2 - ssr_depth / 2 - base_outset; | |
| ssr_y = partition_y -inch(0.1) * ((ssr_pins[1] + ssr_pins[2]) / 2 - 8); | |
| ssr_z = top_thickness + ssr_height / 2; | |
| ssr_wall = 1.6; | |
| ssr_clearance = 0.2; | |
| fence_t = 1; | |
| fence_h = case_height - ssr_height; | |
| arduino_screw = pcb_screw(arduino); | |
| arduino_insert = screw_insert(arduino_screw); | |
| arduino_screw_length = screw_shorter_than(pcb_thickness(arduino) + insert_length(arduino_insert)); | |
| arduino_x = -case_width / 2 - case_wall + 7 + pcb_length(arduino) / 2 ; | |
| arduino_y = thermo_y + thermo_width / 2 + pcb_width(arduino) / 2 + 2; | |
| arduino_z = case_height + top_thickness - insert_length(arduino_insert); | |
| expansion_z = arduino_z + 12.65; | |
| thermo_socket_width = 16; | |
| thermo_socket_width2 = 18; | |
| thermo_socket_depth = 8; | |
| thermo_socket_height = 26; | |
| thermo_socket_screw_z = 23; | |
| thermo_socket_screw_pitch = 12; | |
| thermo_socket_screw = M2_cap_screw; // actually 8BA. | |
| thermo_socket_x = case_width / 2 - thermo_socket_width2 / 2; | |
| thermo_socket_y = -case_depth / 2 + case_inner_rad + thermo_socket_depth / 2; | |
| thermo_socket_z = thermo_socket_height / 2; | |
| thermo_socket_wall = 2.5; | |
| power_jack_depth = 9; | |
| power_jack_width = 22.8; | |
| power_jack_width2 = 11; | |
| power_jack_height = 11.38; | |
| power_jack_t = 2; | |
| power_jack_hole_pitch = 17.925; | |
| power_jack_hole_d = 2.3; | |
| power_jack_r = 1.5; | |
| power_jack_bore = 6.2; | |
| power_jack_pin_d = 2; | |
| power_jack_screw = M2_cap_screw; | |
| power_jack_insert = screw_insert(power_jack_screw); | |
| power_jack_washer = screw_washer(power_jack_screw); | |
| power_jack_screw_length = screw_shorter_than(washer_thickness(power_jack_washer) + power_jack_t + insert_length(power_jack_insert)); | |
| power_jack_x = thermo_socket_x; | |
| power_jack_y = switch_y + inch(0.05); // line up with the buttons for aesthetics but a bit close for inserting the insert. | |
| power_jack_z = round_to_layer(top_thickness + insert_length(power_jack_insert)); | |
| power_plug_d = 8.3; | |
| power_plug_h = 2; | |
| module power_jack_holes() | |
| for(side = [-1, 1]) | |
| translate([side * power_jack_hole_pitch / 2, 0]) | |
| children(); | |
| module power_jack() { | |
| vitamin("PWRSOCK: 6mm panel mount barrel jack socket"); | |
| d = power_jack_depth; | |
| h = power_jack_height; | |
| b = power_jack_bore; | |
| pin_d = power_jack_pin_d; | |
| contact_d = 3; | |
| contact_w = 4; | |
| contact_t = 0.2; | |
| inset = 0.5; | |
| color(grey(20)) render() difference() { | |
| union() { | |
| rounded_rectangle([power_jack_width, d, power_jack_t], r = power_jack_r, center = false); | |
| hull() { | |
| cylinder(d = d, h = h); | |
| translate([0, -d / 2]) | |
| cube([power_jack_width2 - d / 2, d, h]); | |
| } | |
| } | |
| hull() { | |
| cylinder(d = b, h = h - 1); | |
| translate([0, -b / 2]) | |
| cube([power_jack_width2 - (d - b) - b / 2, b, h - 1]); | |
| } | |
| power_jack_holes() | |
| cylinder(d = power_jack_hole_d, h = 100, center = true); | |
| } | |
| color("silver") render() { | |
| hull() { | |
| translate_z(pin_d / 2 + inset) | |
| sphere(pin_d / 2); | |
| translate_z(h - 1) | |
| cylinder(d = pin_d, h = eps); | |
| } | |
| difference() { | |
| hull() | |
| translate([b / 2 + contact_d / 2 - 1, 0, contact_d / 2 + inset]) { | |
| rotate([90, 0, 0]) | |
| cylinder(d = contact_d, h = contact_w, center = true); | |
| translate_z(h - 1 - inset - contact_d / 2) | |
| cube([contact_d + 1, contact_w, eps], center = true); | |
| } | |
| hull() | |
| translate([b / 2 + contact_d / 2 - 1, 0, contact_d / 2 + inset]) { | |
| rotate([90, 0, 0]) | |
| cylinder(d = contact_d - 2 * contact_t, h = contact_w, center = true); | |
| translate_z(h - 1 - inset - contact_d / 2) | |
| cube([contact_d + 1 - 2 * contact_t, contact_w + 1, 2 * eps], center = true); | |
| } | |
| } | |
| } | |
| } | |
| module ssr() { | |
| vitamin("SMT20004: SMT 2000/4 Solid state relay"); | |
| color(grey(20)) render() | |
| cube([ssr_length, ssr_depth, ssr_height], center = true); | |
| color("silver") render() | |
| for(i = [0 : 16]) | |
| if(in(ssr_pins, i)) | |
| translate([i * inch(0.1) - inch(0.8), ssr_pin_y, -ssr_height / 2 - ssr_pin_l]) | |
| cylinder(d = ssr_pin_d, h = ssr_pin_l); | |
| } | |
| module thermo_socket_holes() { | |
| for(side = [-1, 1]) | |
| translate([side * thermo_socket_screw_pitch / 2, 0, thermo_socket_screw_z -thermo_socket_height / 2]) | |
| rotate([90, 0, 180]) | |
| children(); | |
| } | |
| module thermo_socket() { | |
| vitamin("THRMSKT: Thermocouple socket"); | |
| pin_pitch = 7.9; | |
| pin_t = 0.8; | |
| pin_w1 = 3.1; | |
| pin_w2 = 2.3; | |
| pin_l = 12.7; | |
| insert = screw_insert(thermo_socket_screw); | |
| color("yellow") render() difference() { | |
| union() { | |
| cube([thermo_socket_width, thermo_socket_depth, thermo_socket_height], center = true); | |
| translate_z(-thermo_socket_height / 2 + 2.5) | |
| cube([thermo_socket_width2, thermo_socket_depth, 1], center = true); | |
| translate_z(thermo_socket_screw_z -thermo_socket_height / 2) | |
| rotate([90, 0, 0]) | |
| rounded_rectangle([thermo_socket_width2, 6, thermo_socket_depth], 1, center = true); | |
| } | |
| thermo_socket_holes() | |
| cylinder(r = screw_clearance_radius(thermo_socket_screw), h = 100, center = true); | |
| for(side = [-1, 1]) | |
| translate([side * pin_pitch / 2, 0, - thermo_socket_height / 2]) | |
| cube([side > 0 ? pin_w1 : pin_w2 + 0.2, pin_t + 0.2, pin_l * 2], center = true); | |
| } | |
| thermo_socket_holes() | |
| translate_z(-thermo_socket_depth / 2 - eps) | |
| not_on_bom() no_explode() vflip() insert(insert); | |
| } | |
| module switch_assembly() | |
| assembly("switch") { | |
| pcb(switch_pcb); | |
| for(p = switch_positions) | |
| pcb_grid(switch_pcb, p.x, p.y, - pcb_thickness(switch_pcb)) | |
| vflip() | |
| square_button(switch, p.z); | |
| pcb_screw_positions(switch_pcb) | |
| translate_z(pcb_thickness(switch_pcb)) | |
| screw(switch_screw, switch_screw_length); | |
| } | |
| module case_additions() { | |
| translate([switch_x, switch_y]) | |
| pcb_screw_positions(switch_pcb) | |
| insert_boss(switch_insert, switch_z, 1.7); | |
| translate([lcd_x, lcd_y]) | |
| pcb_screw_positions(lcd_pcb) | |
| insert_boss(lcd_insert, display_thickness(lcd) + lcd_z, 1.5); | |
| translate([0, partition_y]) | |
| cube([case_width, partition_t, (case_height + top_thickness) * 2], center = true); | |
| translate([tx_x, tx_y]) | |
| rounded_rectangle([tx_foot_width(tx), tx_foot_depth(tx), tx_z ], 2, center = false); | |
| translate([iec_x, iec_y]) | |
| for(side = [-1, 1]) | |
| translate([side * iec_pitch(iec) / 2, 0]) | |
| cube([2 * (insert_hole_radius(iec_insert) + 2), | |
| 2 * (insert_hole_length(iec_insert) + 2), | |
| 2 * (iec2_z + insert_hole_radius(iec_insert) + 2)], center = true); | |
| translate([ssr_x - ssr_depth / 2 - ssr_wall - ssr_clearance / 2, ssr_y - ssr_length / 2 - ssr_wall - ssr_clearance / 2, 0]) | |
| cube([100, ssr_length + 2 * ssr_wall + ssr_clearance, ssr_z]); | |
| translate([thermo_socket_x - thermo_socket_width2 / 2 + 50, thermo_socket_y + thermo_socket_depth / 2 + thermo_socket_wall / 2, thermo_socket_z]) | |
| cube([100, thermo_socket_wall, thermo_socket_height], center = true); | |
| translate([power_jack_x, power_jack_y]) { | |
| cylinder(d = power_plug_d + 2 * case_wall, h = power_jack_z); | |
| rotate(90) | |
| power_jack_holes() | |
| insert_boss(power_jack_insert, power_jack_z, 1.8); | |
| } | |
| } | |
| module case_holes() { | |
| translate([switch_x, switch_y, switch_z]) { | |
| pcb_screw_positions(switch_pcb) | |
| insert_hole(switch_insert, switch_z - insert_hole_length(switch_insert) - 0.5); | |
| for(p = switch_positions) | |
| pcb_grid(switch_pcb, p.x, p.y, - pcb_thickness(switch_pcb)) { | |
| poly_cylinder(r = square_button_cap_d(switch) / 2 + 0.25, h = 100, center = true); | |
| h = square_button_h(switch) + square_button_cap_stem(switch) + square_button_cap_flange_h(switch) + 0.25; | |
| poly_cylinder(r = square_button_cap_flange_d(switch) / 2 + 0.25, h = 2 * h, center = true); | |
| } | |
| } | |
| translate([lcd_x, lcd_y, lcd_z]) { | |
| display_aperture(lcd, 0.1); | |
| translate([0, 0, display_thickness(lcd)] + display_pcb_offset(lcd)) | |
| pcb_screw_positions(lcd_pcb) | |
| insert_hole(lcd_insert, lcd_z + display_thickness(lcd) - insert_hole_length(lcd_insert) - 0.5); | |
| } | |
| translate([tx_x, tx_y, tx_z]) | |
| transformer_hole_positions(tx) | |
| insert_hole(tx_insert, tx_z - insert_hole_length(tx_insert) - 0.5); | |
| translate([wire_hole_x, partition_y, wire_hole_z]) | |
| rotate([90, 0, 0]) | |
| teardrop_plus(r = wire_hole_d / 2, h = partition_t + 1); | |
| translate([iec_x, iec_y, iec_z]) | |
| rotate([-90, 180, 0]) | |
| iec_holes(iec, h = 20, horizontal = true, insert = true); | |
| translate([iec_x, iec_y, iec2_z]) | |
| rotate([-90, 180, 0]) | |
| iec_holes(iec2, h = 20, horizontal = true, insert = true); | |
| translate([arduino_x, arduino_y, arduino_z]) | |
| vflip() | |
| clip(zmax = 20) pcb_cutouts(arduino); | |
| translate([thermo_socket_x - 0.1, thermo_socket_y - 0.05 ]) | |
| cube([thermo_socket_width + 0.2, thermo_socket_depth + 0.1, 80], center = true); | |
| translate([thermo_socket_x, thermo_socket_y, thermo_socket_z]) | |
| thermo_socket_holes() | |
| teardrop_plus(r = screw_clearance_radius(thermo_socket_screw), h = thermo_socket_depth + 2 * thermo_socket_wall + 1); | |
| translate([ssr_x, ssr_y, ssr_z - ssr_height / 2 + 50]) | |
| cube([ssr_depth + ssr_clearance, ssr_length + ssr_clearance, 100], center = true); | |
| for(side = [-1, 1]) | |
| translate([case_width / 2 - 5, partition_y + side * (partition_t / 2 + (fence_t + 1) / 2), case_height + top_thickness]) | |
| cube([10, fence_t + 1, 20], center = true); | |
| translate([power_jack_x, power_jack_y]) | |
| hanging_hole(power_jack_z - power_plug_h, power_jack_bore / 2) | |
| poly_circle(power_plug_d / 2 + 0.2); | |
| } | |
| module fence_stl() { | |
| stl("fence"); | |
| w1 = ssr_depth; | |
| t1 = partition_t; | |
| w2 = w1 + 2 - 0.2; | |
| t = partition_t + 2 * fence_t + 0.2; | |
| linear_extrude(height = fence_h - layer_height) | |
| difference() { | |
| square([w2, t], center = true); | |
| for(side = [-1, 1]) | |
| translate([side * w2 / 2, 0]) | |
| square([w2 - w1, partition_t + 0.2], center = true); | |
| } | |
| } | |
| module base_additions() { | |
| translate([arduino_x, -arduino_y]) | |
| pcb_screw_positions(arduino) { | |
| insert_boss(arduino_insert, case_height + top_thickness + base_thickness - arduino_z); | |
| insert_boss(arduino_insert, case_height + top_thickness + base_thickness - arduino_z - 2, 2); | |
| } | |
| } | |
| module base_holes() { | |
| } | |
| box = pbox(name = "case", wall = case_wall, top_t = top_thickness, base_t = base_thickness, foot = foot, radius = case_inner_rad, size = [case_width, case_depth, case_height]); | |
| module case_stl() pbox(box) { case_additions(); case_holes(); } | |
| module case_base_stl() pbox_base(box) { base_additions(); base_holes(); } | |
| module arduino_assembly() { | |
| pcb(arduino); | |
| pcb_screw_positions(arduino) | |
| translate_z(pcb_thickness(arduino)) | |
| screw(arduino_screw, arduino_screw_length); | |
| explode(50) | |
| translate_z(expansion_z - arduino_z) | |
| pcb(expansion); | |
| } | |
| module base_inserts_assembly(alpha = 1) | |
| assembly("base_inserts") { | |
| translate([arduino_x, -arduino_y, case_height + top_thickness + base_thickness - arduino_z + eps]) | |
| pcb_screw_positions(arduino) | |
| insert(arduino_insert); | |
| stl_colour(pp2_colour, alpha) render() case_base_stl(); | |
| } | |
| module base_assembly(alpha = 1) | |
| assembly("base") { | |
| translate([arduino_x, -arduino_y, case_height + top_thickness + base_thickness - arduino_z + eps]) | |
| arduino_assembly(); | |
| base_inserts_assembly(alpha = alpha); | |
| } | |
| module case_assembly() pose([26, 0, 164], [0, 0, 36]) | |
| assembly("case") { | |
| stl_colour(pp1_colour) render() case_stl(); | |
| pbox_inserts(box); | |
| translate([iec_x, iec_y, iec_z]) | |
| rotate([-90, 0, 0]) | |
| iec_inserts(iec); | |
| translate([iec_x, iec_y, iec2_z]) | |
| rotate([-90, 0, 0]) | |
| iec_inserts(iec2); | |
| translate([lcd_x, lcd_y, lcd_z]) | |
| translate([0, 0, display_thickness(lcd)] + display_pcb_offset(lcd)) | |
| pcb_screw_positions(lcd_pcb) | |
| insert(lcd_insert); | |
| translate([tx_x, tx_y, tx_z]) | |
| transformer_hole_positions(tx) | |
| insert(tx_insert); | |
| translate([power_jack_x, power_jack_y, power_jack_z]) | |
| rotate(90) | |
| power_jack_holes() | |
| insert(power_jack_insert); | |
| translate([switch_x, switch_y, switch_z]) | |
| pcb_screw_positions(switch_pcb) | |
| insert(switch_insert); | |
| } | |
| module main_assembly() pose([230, 0, 315], exploded = false) | |
| assembly("main") { | |
| case_assembly(); | |
| pbox_base_screws(box, base_thickness); | |
| translate([switch_x, switch_y, switch_z]) | |
| switch_assembly(); | |
| translate([lcd_x, lcd_y, lcd_z]) { | |
| display(lcd); | |
| translate([0, 0, display_thickness(lcd)] + display_pcb_offset(lcd)) | |
| pcb_screw_positions(lcd_pcb) | |
| translate_z(pcb_thickness(lcd_pcb)) | |
| screw(lcd_screw, lcd_screw_length); | |
| } | |
| translate([tx_x, tx_y, tx_z]) { | |
| transformer(tx); | |
| transformer_hole_positions(tx) | |
| translate_z(tx_foot_thickness(tx)) | |
| screw_and_washer(tx_screw, tx_screw_length, true); | |
| } | |
| translate([iec_x, iec_y, iec_z]) | |
| rotate([-90, 0, 0]) | |
| iec_assembly(iec, 0); | |
| translate([iec_x, iec_y, iec2_z]) | |
| rotate([-90, 0, 0]) | |
| iec_assembly(iec2, 0); | |
| translate([ssr_x, ssr_y, ssr_z]) | |
| rotate([180, 0, 90]) | |
| ssr(); | |
| translate([ssr_x, partition_y, ssr_z + ssr_height / 2]) | |
| fence_stl(); | |
| translate([thermo_x, thermo_y, thermo_z]) | |
| color("Ivory") cube([thermo_length, thermo_width, thermo_height], center = true); | |
| translate([thermo_socket_x, thermo_socket_y, thermo_socket_z]) { | |
| thermo_socket(); | |
| thermo_socket_holes() | |
| translate_z(thermo_socket_depth / 2 + thermo_socket_wall) | |
| screw_and_washer(thermo_socket_screw, 12); | |
| } | |
| translate([power_jack_x, power_jack_y, power_jack_z]) | |
| rotate(90) { | |
| power_jack(); | |
| power_jack_holes() | |
| translate_z(power_jack_t) | |
| screw_and_washer(power_jack_screw, power_jack_screw_length); | |
| } | |
| translate_z(case_height + top_thickness + base_thickness + eps) vflip() base_assembly(0.5); | |
| } | |
| if($preview) | |
| main_assembly(); | |
| else rotate(90) | |
| if(1) { | |
| case_stl(); | |
| translate([lcd_x, lcd_y]) | |
| fence_stl(); | |
| } | |
| else base_stl(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment