|
@@ -0,0 +1,163 @@
|
|
|
|
|
+// -----------------------------------------------------------------------
|
|
|
|
|
+// Modular LED Matrix X-Brace Backplate with Flush Snaps
|
|
|
|
|
+// -----------------------------------------------------------------------
|
|
|
|
|
+// NATIVE LANDSCAPE LAYOUT (3 columns x 2 rows)
|
|
|
|
|
+// Select which tile to generate:
|
|
|
|
|
+// 1 = Top Left | 2 = Top Mid | 3 = Top Right
|
|
|
|
|
+// 4 = Bottom Left | 5 = Bottom Mid | 6 = Bottom Right
|
|
|
|
|
+part = 1; // [1:6]
|
|
|
|
|
+
|
|
|
|
|
+// --- Matrix Parameters ---
|
|
|
|
|
+cellsX = 16;
|
|
|
|
|
+cellsY = 16;
|
|
|
|
|
+pitch = 10;
|
|
|
|
|
+
|
|
|
|
|
+// Flat 1.6mm Z-plane for fast FDM printing
|
|
|
|
|
+thickness = 1.6;
|
|
|
|
|
+brace_width = 15;
|
|
|
|
|
+hub_diameter = 40; // Added central hub for structural integrity
|
|
|
|
|
+
|
|
|
|
|
+// --- Frame Parameters ---
|
|
|
|
|
+borderWidth = 10;
|
|
|
|
|
+holeRad = 2;
|
|
|
|
|
+inner_rim = 8; // Solid rim on interior seams for the snaps to anchor into
|
|
|
|
|
+
|
|
|
|
|
+// --- Logic ---
|
|
|
|
|
+hasLeft = (part == 1 || part == 4) ? 1 : 0;
|
|
|
|
|
+hasRight = (part == 3 || part == 6) ? 1 : 0;
|
|
|
|
|
+hasTop = (part == 1 || part == 2 || part == 3) ? 1 : 0;
|
|
|
|
|
+hasBottom = (part == 4 || part == 5 || part == 6) ? 1 : 0;
|
|
|
|
|
+
|
|
|
|
|
+gridWidth = cellsX * pitch;
|
|
|
|
|
+gridHeight = cellsY * pitch;
|
|
|
|
|
+
|
|
|
|
|
+leftOffset = hasLeft * borderWidth;
|
|
|
|
|
+bottomOffset = hasBottom * borderWidth;
|
|
|
|
|
+
|
|
|
|
|
+totalWidth = gridWidth + (hasLeft * borderWidth) + (hasRight * borderWidth);
|
|
|
|
|
+totalHeight = gridHeight + (hasTop * borderWidth) + (hasBottom * borderWidth);
|
|
|
|
|
+
|
|
|
|
|
+left_rim = hasLeft ? borderWidth : inner_rim;
|
|
|
|
|
+right_rim = hasRight ? borderWidth : inner_rim;
|
|
|
|
|
+top_rim = hasTop ? borderWidth : inner_rim;
|
|
|
|
|
+bottom_rim = hasBottom ? borderWidth : inner_rim;
|
|
|
|
|
+
|
|
|
|
|
+$fn = 32;
|
|
|
|
|
+
|
|
|
|
|
+// --- Flush Puzzle Snaps (XY Plane) ---
|
|
|
|
|
+module puzzle_tab_x() {
|
|
|
|
|
+ // Points out to the right
|
|
|
|
|
+ translate([0, -3, 0]) cube([3, 6, thickness]);
|
|
|
|
|
+ translate([3, 0, 0]) cylinder(r=4, h=thickness);
|
|
|
|
|
+}
|
|
|
|
|
+module puzzle_slot_x() {
|
|
|
|
|
+ // Cuts inwards from the left
|
|
|
|
|
+ translate([-0.1, -3.2, -1]) cube([3.2, 6.4, thickness+2]);
|
|
|
|
|
+ translate([3, 0, -1]) cylinder(r=4.2, h=thickness+2);
|
|
|
|
|
+}
|
|
|
|
|
+module puzzle_tab_y() {
|
|
|
|
|
+ // Points downwards
|
|
|
|
|
+ rotate([0, 0, -90]) puzzle_tab_x();
|
|
|
|
|
+}
|
|
|
|
|
+module puzzle_slot_y() {
|
|
|
|
|
+ // Cuts downwards from the top
|
|
|
|
|
+ rotate([0, 0, -90]) puzzle_slot_x();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+difference() {
|
|
|
|
|
+ union() {
|
|
|
|
|
+ // Main solid frame with hollowed center
|
|
|
|
|
+ difference() {
|
|
|
|
|
+ cube([totalWidth, totalHeight, thickness], center=false);
|
|
|
|
|
+
|
|
|
|
|
+ // Punch out the dead space
|
|
|
|
|
+ translate([left_rim, bottom_rim, -1])
|
|
|
|
|
+ cube([
|
|
|
|
|
+ totalWidth - left_rim - right_rim,
|
|
|
|
|
+ totalHeight - top_rim - bottom_rim,
|
|
|
|
|
+ thickness + 2
|
|
|
|
|
+ ]);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Internal X-Braces with Central Hub
|
|
|
|
|
+ intersection() {
|
|
|
|
|
+ cube([totalWidth, totalHeight, thickness]);
|
|
|
|
|
+ union() {
|
|
|
|
|
+ // Diagonal /
|
|
|
|
|
+ hull() {
|
|
|
|
|
+ translate([left_rim, bottom_rim, 0])
|
|
|
|
|
+ cylinder(d=brace_width, h=thickness);
|
|
|
|
|
+ translate([totalWidth - right_rim, totalHeight - top_rim, 0])
|
|
|
|
|
+ cylinder(d=brace_width, h=thickness);
|
|
|
|
|
+ }
|
|
|
|
|
+ // Diagonal \
|
|
|
|
|
+ hull() {
|
|
|
|
|
+ translate([totalWidth - right_rim, bottom_rim, 0])
|
|
|
|
|
+ cylinder(d=brace_width, h=thickness);
|
|
|
|
|
+ translate([left_rim, totalHeight - top_rim, 0])
|
|
|
|
|
+ cylinder(d=brace_width, h=thickness);
|
|
|
|
|
+ }
|
|
|
|
|
+ // Central Hub
|
|
|
|
|
+ translate([totalWidth/2, totalHeight/2, 0])
|
|
|
|
|
+ cylinder(d=hub_diameter, h=thickness);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Add Male Puzzle Tabs on internal mating edges
|
|
|
|
|
+ if (!hasRight) {
|
|
|
|
|
+ translate([totalWidth, totalHeight/3, 0]) puzzle_tab_x();
|
|
|
|
|
+ translate([totalWidth, 2*totalHeight/3, 0]) puzzle_tab_x();
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!hasBottom) {
|
|
|
|
|
+ translate([totalWidth/3, 0, 0]) puzzle_tab_y();
|
|
|
|
|
+ translate([2*totalWidth/3, 0, 0]) puzzle_tab_y();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Cut Female Puzzle Slots on internal mating edges
|
|
|
|
|
+ if (!hasLeft) {
|
|
|
|
|
+ translate([0, totalHeight/3, 0]) puzzle_slot_x();
|
|
|
|
|
+ translate([0, 2*totalHeight/3, 0]) puzzle_slot_x();
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!hasTop) {
|
|
|
|
|
+ translate([totalWidth/3, totalHeight, 0]) puzzle_slot_y();
|
|
|
|
|
+ translate([2*totalWidth/3, totalHeight, 0]) puzzle_slot_y();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // --- Mounting Holes ---
|
|
|
|
|
+ // Left Border
|
|
|
|
|
+ if (hasLeft) {
|
|
|
|
|
+ for (i = [1 : 3]) {
|
|
|
|
|
+ translate([borderWidth / 2, bottomOffset + (i * gridHeight/4), -1])
|
|
|
|
|
+ cylinder(h=thickness + 2, r=holeRad);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Right Border
|
|
|
|
|
+ if (hasRight) {
|
|
|
|
|
+ for (i = [1 : 3]) {
|
|
|
|
|
+ translate([totalWidth - (borderWidth / 2), bottomOffset + (i * gridHeight/4), -1])
|
|
|
|
|
+ cylinder(h=thickness + 2, r=holeRad);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Top Border
|
|
|
|
|
+ if (hasTop) {
|
|
|
|
|
+ for (i = [1 : 3]) {
|
|
|
|
|
+ translate([leftOffset + (i * gridWidth/4), totalHeight - (borderWidth / 2), -1])
|
|
|
|
|
+ cylinder(h=thickness + 2, r=holeRad);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Bottom Border
|
|
|
|
|
+ if (hasBottom) {
|
|
|
|
|
+ for (i = [1 : 3]) {
|
|
|
|
|
+ translate([leftOffset + (i * gridWidth/4), borderWidth / 2, -1])
|
|
|
|
|
+ cylinder(h=thickness + 2, r=holeRad);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Central wire pass-through hole in the middle of the X
|
|
|
|
|
+ translate([totalWidth/2, totalHeight/2, -1])
|
|
|
|
|
+ cylinder(d=25, h=thickness + 2);
|
|
|
|
|
+}
|