LED Grill support.scad 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. // -----------------------------------------------------------------------
  2. // Modular LED Matrix X-Brace Backplate with Flush Snaps
  3. // -----------------------------------------------------------------------
  4. // NATIVE LANDSCAPE LAYOUT (3 columns x 2 rows)
  5. // Select which tile to generate:
  6. // 1 = Top Left | 2 = Top Mid | 3 = Top Right
  7. // 4 = Bottom Left | 5 = Bottom Mid | 6 = Bottom Right
  8. part = 1; // [1:6]
  9. // --- Matrix Parameters ---
  10. cellsX = 16;
  11. cellsY = 16;
  12. pitch = 10;
  13. // Flat 1.6mm Z-plane for fast FDM printing
  14. thickness = 1.6;
  15. brace_width = 15;
  16. hub_diameter = 40; // Added central hub for structural integrity
  17. // --- Frame Parameters ---
  18. borderWidth = 10;
  19. holeRad = 2;
  20. inner_rim = 8; // Solid rim on interior seams for the snaps to anchor into
  21. // --- Logic ---
  22. hasLeft = (part == 1 || part == 4) ? 1 : 0;
  23. hasRight = (part == 3 || part == 6) ? 1 : 0;
  24. hasTop = (part == 1 || part == 2 || part == 3) ? 1 : 0;
  25. hasBottom = (part == 4 || part == 5 || part == 6) ? 1 : 0;
  26. gridWidth = cellsX * pitch;
  27. gridHeight = cellsY * pitch;
  28. leftOffset = hasLeft * borderWidth;
  29. bottomOffset = hasBottom * borderWidth;
  30. totalWidth = gridWidth + (hasLeft * borderWidth) + (hasRight * borderWidth);
  31. totalHeight = gridHeight + (hasTop * borderWidth) + (hasBottom * borderWidth);
  32. left_rim = hasLeft ? borderWidth : inner_rim;
  33. right_rim = hasRight ? borderWidth : inner_rim;
  34. top_rim = hasTop ? borderWidth : inner_rim;
  35. bottom_rim = hasBottom ? borderWidth : inner_rim;
  36. $fn = 32;
  37. // --- Flush Puzzle Snaps (XY Plane) ---
  38. module puzzle_tab_x() {
  39. // Points out to the right
  40. translate([0, -3, 0]) cube([3, 6, thickness]);
  41. translate([3, 0, 0]) cylinder(r=4, h=thickness);
  42. }
  43. module puzzle_slot_x() {
  44. // Cuts inwards from the left
  45. translate([-0.1, -3.2, -1]) cube([3.2, 6.4, thickness+2]);
  46. translate([3, 0, -1]) cylinder(r=4.2, h=thickness+2);
  47. }
  48. module puzzle_tab_y() {
  49. // Points downwards
  50. rotate([0, 0, -90]) puzzle_tab_x();
  51. }
  52. module puzzle_slot_y() {
  53. // Cuts downwards from the top
  54. rotate([0, 0, -90]) puzzle_slot_x();
  55. }
  56. difference() {
  57. union() {
  58. // Main solid frame with hollowed center
  59. difference() {
  60. cube([totalWidth, totalHeight, thickness], center=false);
  61. // Punch out the dead space
  62. translate([left_rim, bottom_rim, -1])
  63. cube([
  64. totalWidth - left_rim - right_rim,
  65. totalHeight - top_rim - bottom_rim,
  66. thickness + 2
  67. ]);
  68. }
  69. // Internal X-Braces with Central Hub
  70. intersection() {
  71. cube([totalWidth, totalHeight, thickness]);
  72. union() {
  73. // Diagonal /
  74. hull() {
  75. translate([left_rim, bottom_rim, 0])
  76. cylinder(d=brace_width, h=thickness);
  77. translate([totalWidth - right_rim, totalHeight - top_rim, 0])
  78. cylinder(d=brace_width, h=thickness);
  79. }
  80. // Diagonal \
  81. hull() {
  82. translate([totalWidth - right_rim, bottom_rim, 0])
  83. cylinder(d=brace_width, h=thickness);
  84. translate([left_rim, totalHeight - top_rim, 0])
  85. cylinder(d=brace_width, h=thickness);
  86. }
  87. // Central Hub
  88. translate([totalWidth/2, totalHeight/2, 0])
  89. cylinder(d=hub_diameter, h=thickness);
  90. }
  91. }
  92. // Add Male Puzzle Tabs on internal mating edges
  93. if (!hasRight) {
  94. translate([totalWidth, totalHeight/3, 0]) puzzle_tab_x();
  95. translate([totalWidth, 2*totalHeight/3, 0]) puzzle_tab_x();
  96. }
  97. if (!hasBottom) {
  98. translate([totalWidth/3, 0, 0]) puzzle_tab_y();
  99. translate([2*totalWidth/3, 0, 0]) puzzle_tab_y();
  100. }
  101. }
  102. // Cut Female Puzzle Slots on internal mating edges
  103. if (!hasLeft) {
  104. translate([0, totalHeight/3, 0]) puzzle_slot_x();
  105. translate([0, 2*totalHeight/3, 0]) puzzle_slot_x();
  106. }
  107. if (!hasTop) {
  108. translate([totalWidth/3, totalHeight, 0]) puzzle_slot_y();
  109. translate([2*totalWidth/3, totalHeight, 0]) puzzle_slot_y();
  110. }
  111. // --- Mounting Holes ---
  112. // Left Border
  113. if (hasLeft) {
  114. for (i = [1 : 3]) {
  115. translate([borderWidth / 2, bottomOffset + (i * gridHeight/4), -1])
  116. cylinder(h=thickness + 2, r=holeRad);
  117. }
  118. }
  119. // Right Border
  120. if (hasRight) {
  121. for (i = [1 : 3]) {
  122. translate([totalWidth - (borderWidth / 2), bottomOffset + (i * gridHeight/4), -1])
  123. cylinder(h=thickness + 2, r=holeRad);
  124. }
  125. }
  126. // Top Border
  127. if (hasTop) {
  128. for (i = [1 : 3]) {
  129. translate([leftOffset + (i * gridWidth/4), totalHeight - (borderWidth / 2), -1])
  130. cylinder(h=thickness + 2, r=holeRad);
  131. }
  132. }
  133. // Bottom Border
  134. if (hasBottom) {
  135. for (i = [1 : 3]) {
  136. translate([leftOffset + (i * gridWidth/4), borderWidth / 2, -1])
  137. cylinder(h=thickness + 2, r=holeRad);
  138. }
  139. }
  140. // Central wire pass-through hole in the middle of the X
  141. translate([totalWidth/2, totalHeight/2, -1])
  142. cylinder(d=25, h=thickness + 2);
  143. }