include BASE_MODEL_SCALE = [1.1, 1, 1.1]; BASE_MODEL_TRANSLATE = [-0.4, 0, 16.978]; EPS = 0.01; $fn = 50; module pin_header(cols = 4, rows = 1, anchor = BOTTOM, spin = 0, orient = UP) { // Standard pin header dimensions (in mm) base_height = 2.54; // Height of the plastic base pin_width = 0.64; // Width/thickness of the square pin pin_length = 6.0; // Length of pin sticking up pitch = 2.54; // 1. The Plastic Base is the Parent // It directly receives your anchor, spin, and orient arguments. color("darkgrey") cuboid([cols * pitch, rows * pitch, base_height], anchor=anchor, spin=spin, orient=orient) { // 2. Metal Pins are the Children // Placed relative to the center of the plastic base color("silver") xcopies(spacing=pitch, n=cols) { ycopies(spacing=pitch, n=rows) { up(base_height / 2) cuboid([pin_width, pin_width, pin_length], anchor=BOTTOM); } } // Allows attaching other objects to this header if needed children(); } } module main_display(pin_header = false) { // Outer dimensions width = 55.04; length = 89.35; height = 2.7; display_height = 3; display_length = 77.6; display_inset = 5.7; sd_width = 26.6; sd_height = 3; sd_length = 16.6; sd_inset = 29.4; hole_diameter = 3; hole_inset = 1.5; difference() { cuboid([length, width, height]) { position(TOP + RIGHT) left(display_inset) color("black") cuboid([display_length, width, display_height], anchor=BOTTOM + RIGHT); position(BOTTOM + RIGHT + FRONT) left(sd_inset) cuboid([sd_width, sd_length, sd_height], anchor=TOP + RIGHT + FRONT); if (pin_header) position(BOTTOM + LEFT) xrot(180) pin_header(14, spin=90, anchor=BOTTOM + BACK); } xcopies(length - (2 * hole_inset) - hole_diameter) { ycopies(width - (2 * hole_inset) - hole_diameter) { zcyl(d=hole_diameter, h=height + EPS); } } } } module pad() { // A button has 4.2 x 6 mm -> At least ~20x20 are required for the PCB cube([20, 20, 10]); } module secondary_display(pin_header = false) { // https://de.aliexpress.com/item/1005003753680706.html length = 45.8; width = 20; height = 3.7; hole_diameter = 2; hole_inset = 1.5; difference() { cuboid([length, width, height]) { if (pin_header) position(LEFT + TOP) pin_header(7, spin=90, anchor=BACK + BOTTOM); } right(length / 2 - hole_inset) { ycopies(width - (2 * hole_inset) - hole_diameter) { zcyl(d=hole_diameter, h=height + EPS, anchor=RIGHT); } } } } module battery(anchor = BOTTOM) { // 18650 rotate([0, 90, 0]) cylinder(d=18, h=65, anchor=anchor); } /// USB-C port and switch not 100% dimensionally accurate, take care! module micro_controller(battery_holder = false, battery = false) { pcb_length = 91.5; pcb_height = 6.5; // including components, highest point: jst connector, followed by uC pcb_height_no_components = 1.1; pcb_width = 28.8; hole_diameter = 2.5; hole_inset = 1; usb_protrusion = 1.7; usb_width = 9; usb_inset_from_pcb_end = 5; power_switch_protrusion = 2.1; power_switch_inset_from_pcb_end = 8.1; power_switch_width = 4; battery_holder_height = 15; battery_holder_width = 21; battery_holder_length = 77.3; battery_length = 65; battery_protrusion = 4.5; difference() { cuboid([pcb_length, pcb_width, pcb_height], rounding=2, edges="Z") { if (battery_holder) position(TOP) cube([battery_holder_length, battery_holder_width, battery_holder_height], anchor=BOTTOM + CENTER) { if (battery) position(TOP) up(battery_protrusion) battery(anchor=CENTER + LEFT); } position(RIGHT + BOTTOM) { position(FRONT) left(usb_inset_from_pcb_end) cube([usb_width, usb_protrusion, pcb_height - pcb_height_no_components], orient=FRONT, anchor=RIGHT + BOTTOM + FRONT); position(BACK) left(power_switch_inset_from_pcb_end) cube([power_switch_width, power_switch_protrusion, pcb_height - pcb_height_no_components], orient=FRONT, anchor=RIGHT + TOP + FRONT); } } xcopies(pcb_length - (2 * hole_inset) - hole_diameter) { ycopies(pcb_width - (2 * hole_inset) - hole_diameter) { cyl(d=hole_diameter, h=pcb_height + EPS, orient=UP); } } } } module nfc(pin_header = true) { length = 43; width = 40.5; height = 4; pin_protrusion = 2.2; hole_diameter = 3; hole_inset = 6; x_span = length - (2 * hole_inset) - hole_diameter; y_span = width - (2 * hole_inset) - hole_diameter; color("red") difference() { cuboid([length, width, height], rounding=2, edges="Z") { // pin header is lower than highest other component -> in the cube. if (pin_header) right(6 - pin_protrusion) // ugly: 6mm is the pin height position(LEFT + TOP) yrot(-90) pin_header(7, spin=90, anchor=FRONT + TOP); } move_copies( [ [x_span / 2, -y_span / 2], // Bottom-Left corner [-x_span / 2, y_span / 2], // Top-Right corner ] ) { zcyl(d=hole_diameter, h=height + EPS); } } } module tertiary_display(pin_headers = true) { // https://de.aliexpress.com/item/1005006034531826.html pcb_length = 81; pcb_width = 36.1; pcb_height = 3.7; hole_diameter = 2.8; hole_inset = 1; display_length = 71.2; display_width = 24.4; display_height = 7; piggy_length = 41.8; piggy_width = 19.1; piggy_height = 8.5 - 2.6; piggy_inset = 6.2; jumper_protrusion = 6.6; pin_protrusion = 6.2; color("green") difference() { cuboid([pcb_length, pcb_width, pcb_height]) { position(TOP) cuboid([display_length, display_width, display_height], anchor=BOTTOM); } xcopies(pcb_length - (2 * hole_inset) - hole_diameter) { ycopies(pcb_width - (2 * hole_inset) - hole_diameter) { zcyl(d=hole_diameter, h=pcb_height + 1); } } } // Replaces position(BOTTOM + BACK + LEFT) so that difference cannot mess with color. translate([-pcb_length / 2 + piggy_inset, pcb_width / 2, -pcb_height / 2]) { color("black") cuboid([piggy_length, piggy_width, piggy_height], anchor=TOP + BACK + LEFT); if (pin_headers) { // Replaces position(LEFT + BOTTOM) so that parent child cannot mess with color. translate([0, -piggy_width / 2, -piggy_height]) right(6 - pin_protrusion) yrot(-90) pin_header(4, spin=90, anchor=BACK + TOP); // Replaces position(RIGHT + BOTTOM) so that parent child cannot mess with color. translate([piggy_length, -piggy_width / 2, -piggy_height]) left(6 - pin_protrusion) yrot(90) back(1.6) pin_header(2, spin=-90, anchor=BACK + TOP); // Replaces position(BACK + TOP) so that parent child cannot mess with color. translate([piggy_length / 2, -EPS, 0]) pin_header(16, anchor=BACK + TOP); } } } // show different components as overview if (false) { back(30) tertiary_display(true); back(80) yrot(180) secondary_display(true); right(100) zrot(90) main_display(true); fwd(20) micro_controller(true, true); fwd(60) nfc(true); }