LED Frame.scad 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. // -----------------------------------------------------------------------
  2. // Modular LED Matrix Outer Frame / Diffuser Clamp (Through-Holes)
  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. borderWidth = 10;
  14. // --- Frame Settings ---
  15. thickness = 3;
  16. overhang = 1; // 1mm bite inwards to clamp the diffuser without blocking LEDs
  17. overW = borderWidth + overhang; // Total width of the frame bars
  18. lap_len = 6; // Length of the hidden half-lap joint
  19. tol = 0.2; // 0.2mm tolerance for a friction fit without sanding
  20. // --- Logic ---
  21. hasLeft = (part == 1 || part == 4) ? 1 : 0;
  22. hasRight = (part == 3 || part == 6) ? 1 : 0;
  23. hasTop = (part == 1 || part == 2 || part == 3) ? 1 : 0;
  24. hasBottom = (part == 4 || part == 5 || part == 6) ? 1 : 0;
  25. gridWidth = cellsX * pitch;
  26. gridHeight = cellsY * pitch;
  27. leftOffset = hasLeft * borderWidth;
  28. bottomOffset = hasBottom * borderWidth;
  29. totalWidth = gridWidth + (hasLeft * borderWidth) + (hasRight * borderWidth);
  30. totalHeight = gridHeight + (hasTop * borderWidth) + (hasBottom * borderWidth);
  31. $fn = 32;
  32. // --- Countersunk Hole Module ---
  33. module cs_hole(x, y) {
  34. // M3 shaft clearance (3.2mm diameter)
  35. translate([x, y, -0.1])
  36. cylinder(h=thickness + 0.2, r=1.6);
  37. // Countersink cone for 5mm head (using 5.2mm for flush fit)
  38. // 1mm depth matches standard 90-degree profile for this head size
  39. translate([x, y, thickness - 1])
  40. cylinder(h=1.1, r1=1.6, r2=2.6);
  41. }
  42. difference() {
  43. union() {
  44. // Base Perimeter Bars
  45. if(hasLeft) translate([0, 0, 0]) cube([overW, totalHeight, thickness]);
  46. if(hasRight) translate([totalWidth - overW, 0, 0]) cube([overW, totalHeight, thickness]);
  47. if(hasTop) translate([0, totalHeight - overW, 0]) cube([totalWidth, overW, thickness]);
  48. if(hasBottom) translate([0, 0, 0]) cube([totalWidth, overW, thickness]);
  49. // Male Half-Lap Tabs (Hidden on the bottom half, Z = 0 to thickness/2)
  50. // Extending Right (P1, P2) on Top Bar
  51. if(hasTop && !hasRight) translate([totalWidth, totalHeight - overW, 0]) cube([lap_len, overW, thickness/2]);
  52. // Extending Right (P4, P5) on Bottom Bar
  53. if(hasBottom && !hasRight) translate([totalWidth, 0, 0]) cube([lap_len, overW, thickness/2]);
  54. // Extending Down (P1) on Left Bar
  55. if(hasLeft && !hasBottom) translate([0, -lap_len, 0]) cube([overW, lap_len, thickness/2]);
  56. // Extending Down (P3) on Right Bar
  57. if(hasRight && !hasBottom) translate([totalWidth - overW, -lap_len, 0]) cube([overW, lap_len, thickness/2]);
  58. }
  59. // Female Half-Lap Slots (Cut from Z = -0.1 to thickness/2 + tol)
  60. // Cut from Left (P2, P3) on Top Bar
  61. if(hasTop && !hasLeft) translate([-0.1, totalHeight - overW - tol, -0.1]) cube([lap_len + 0.1, overW + 2*tol, thickness/2 + tol]);
  62. // Cut from Left (P5, P6) on Bottom Bar
  63. if(hasBottom && !hasLeft) translate([-0.1, -tol, -0.1]) cube([lap_len + 0.1, overW + 2*tol, thickness/2 + tol]);
  64. // Cut from Top (P4) on Left Bar
  65. if(hasLeft && !hasTop) translate([-tol, totalHeight - lap_len, -0.1]) cube([overW + 2*tol, lap_len + 0.1, thickness/2 + tol]);
  66. // Cut from Top (P6) on Right Bar
  67. if(hasRight && !hasTop) translate([totalWidth - overW - tol, totalHeight - lap_len, -0.1]) cube([overW + 2*tol, lap_len + 0.1, thickness/2 + tol]);
  68. // Countersunk Mounting Holes
  69. // Left Border
  70. if (hasLeft) {
  71. for (i = [1 : 3]) {
  72. cs_hole(borderWidth / 2, bottomOffset + (i * gridHeight/4));
  73. }
  74. }
  75. // Right Border
  76. if (hasRight) {
  77. for (i = [1 : 3]) {
  78. cs_hole(totalWidth - (borderWidth / 2), bottomOffset + (i * gridHeight/4));
  79. }
  80. }
  81. // Top Border
  82. if (hasTop) {
  83. for (i = [1 : 3]) {
  84. cs_hole(leftOffset + (i * gridWidth/4), totalHeight - (borderWidth / 2));
  85. }
  86. }
  87. // Bottom Border
  88. if (hasBottom) {
  89. for (i = [1 : 3]) {
  90. cs_hole(leftOffset + (i * gridWidth/4), borderWidth / 2);
  91. }
  92. }
  93. }