fpc_adapter.scad 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. // Waveshare e-Paper FPC Adapter — parametric mockup
  2. //
  3. // Coordinate system:
  4. // Origin at PCB Z- face, lower-left corner (X=0, Y=0, Z=0).
  5. // X: board long axis (width)
  6. // Y: board short axis (height)
  7. // Z: 0 = bottom face (Z-); PCB_T = top face (Z+, component side)
  8. //
  9. // Two FPC connectors sit on the Z+ face:
  10. // Connector A (Y+): FPC exits in +Y direction
  11. // Connector B (Y-): FPC exits in -Y direction
  12. //
  13. // Mounting bosses hang from the Z- face (z=0, downward in -Z).
  14. // Stud pins extend upward from z=0 through the PCB locating holes.
  15. // When the board is flipped for ceiling-mount (rotate([0,180,0])):
  16. // bosses point toward the ceiling, stud tips snap down through the PCB.
  17. //
  18. // fpc_adapter() always produces boss geometry.
  19. // PCB / connector / FPC visuals are shown only in $preview.
  20. // ── PCB ────────────────────────────────────────────────────────────────
  21. PCB_W = 32.0;
  22. PCB_H = 18.0;
  23. PCB_T = 1.6; // standard; measured ~1.72
  24. PCB_R = 3.0; // corner radius
  25. // ── Mounting holes ─────────────────────────────────────────────────────
  26. HOLE_D = 3.0;
  27. HOLE_MX = 3.75; // hole center from nearest X edge (2.25 clearance + 1.5 radius)
  28. HOLE_MY = 3.75; // hole center from nearest Y edge
  29. // ── FPC connectors (simple box approximation) ──────────────────────────
  30. CON_W = 15.5; // connector width along X
  31. CON_D = 5.85; // connector depth along Y
  32. CON_H = 2.05; // connector height above Z+ face (total stack 3.65 − PCB_T)
  33. CON_CX = PCB_W / 2;
  34. CON_A_Y1 = PCB_H - CON_D; // Connector A inner face (Y+ side)
  35. CON_B_Y0 = 0; // Connector B outer face (Y- side)
  36. // ── FPC cable (simple flat box) ────────────────────────────────────────
  37. FPC_W = 12.5;
  38. FPC_T = 0.3;
  39. // Default stub lengths. 0 = no cable; >0 = stub that many mm.
  40. FPC_YP = 20;
  41. FPC_YN = 0;
  42. // ── Mounting bosses ────────────────────────────────────────────────────
  43. BOSS_D = 6.0; // boss outer diameter
  44. BOSS_H = 2.0; // boss standoff height (extends below Z- face)
  45. SCREW_D = 3.2; // screw diameter; hole drilled at 0.7× for self-tap
  46. STUD_R = 1.5; // locating stud radius
  47. STUD_H = PCB_T + 1.0; // stud height: pierces PCB with 1 mm snap-through
  48. // ═══════════════════════════════════════════════════════════════════════
  49. // Private helpers
  50. // ═══════════════════════════════════════════════════════════════════════
  51. module _pcb_shape(h) {
  52. r = PCB_R;
  53. linear_extrude(h)
  54. offset(r=r)
  55. translate([r, r])
  56. square([PCB_W - 2*r, PCB_H - 2*r]);
  57. }
  58. // Boss hangs from Z- face (z=0) downward; stud pin rises through PCB hole.
  59. // Stud diagonal: (X1,Y1)+(X2,Y2); screw diagonal: (X1,Y2)+(X2,Y1).
  60. module _adapt_boss(px, py, stud=false) {
  61. translate([px, py, 0]) {
  62. translate([0, 0, -BOSS_H])
  63. difference() {
  64. cylinder(d=BOSS_D, h=BOSS_H, $fn=24);
  65. if (!stud)
  66. translate([0, 0, -0.1])
  67. cylinder(d=SCREW_D * 0.7, h=BOSS_H + 0.2, $fn=18);
  68. }
  69. if (stud) {
  70. cylinder(r=STUD_R, h=STUD_H, $fn=24);
  71. translate([0, 0, STUD_H])
  72. sphere(r=STUD_R, $fn=24);
  73. }
  74. }
  75. }
  76. // ═══════════════════════════════════════════════════════════════════════
  77. // Public module
  78. // ═══════════════════════════════════════════════════════════════════════
  79. module fpc_adapter(fpc_yp=FPC_YP, fpc_yn=FPC_YN) {
  80. // ── Visual geometry (preview only) ──────────────────────────────────
  81. if ($preview) {
  82. color("darkgray", 0.85) {
  83. difference() {
  84. _pcb_shape(PCB_T);
  85. for (xi = [HOLE_MX, PCB_W - HOLE_MX])
  86. for (yi = [HOLE_MY, PCB_H - HOLE_MY])
  87. translate([xi, yi, -0.1])
  88. cylinder(d=HOLE_D, h=PCB_T + 0.2, $fn=24);
  89. }
  90. // Connector A (Y+ edge, FPC exits +Y)
  91. translate([CON_CX - CON_W/2, CON_A_Y1, PCB_T])
  92. cube([CON_W, CON_D, CON_H]);
  93. if (fpc_yp > 0)
  94. translate([CON_CX - FPC_W/2, PCB_H, PCB_T + (CON_H - FPC_T)/2])
  95. cube([FPC_W, fpc_yp, FPC_T]);
  96. // Connector B (Y- edge, FPC exits -Y)
  97. translate([CON_CX - CON_W/2, CON_B_Y0, PCB_T])
  98. cube([CON_W, CON_D, CON_H]);
  99. if (fpc_yn > 0)
  100. translate([CON_CX - FPC_W/2, -fpc_yn, PCB_T + (CON_H - FPC_T)/2])
  101. cube([FPC_W, fpc_yn, FPC_T]);
  102. }
  103. }
  104. // ── Mounting bosses (always — structural geometry for host part) ─────
  105. color("#004B49") {
  106. _adapt_boss(HOLE_MX, HOLE_MY, stud=true);
  107. _adapt_boss(PCB_W - HOLE_MX, PCB_H - HOLE_MY, stud=true);
  108. _adapt_boss(HOLE_MX, PCB_H - HOLE_MY, stud=false);
  109. _adapt_boss(PCB_W - HOLE_MX, HOLE_MY, stud=false);
  110. }
  111. }
  112. // Standalone render
  113. fpc_adapter(fpc_yp=FPC_YP, fpc_yn=FPC_YN);