cpu_case.scad 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. // ============================================================
  2. // XIAO ePaper Display Board EE04 — 3D-Printed Case (base only)
  3. // OpenSCAD parametric model
  4. // ============================================================
  5. include <params.scad>
  6. use <ee04.scad>
  7. /* [Preview] */
  8. SHOW_BOARD = true;
  9. SHOW_BATTERY = true;
  10. // ============================================================
  11. // HELPERS
  12. // ============================================================
  13. // Standoff boss: screw variant has through-hole; stud variant has locating pin instead.
  14. // Diagonal (X1,Y1)+(X2,Y2) → studs; (X1,Y2)+(X2,Y1) → screws.
  15. module pcb_boss(px, py, stud=false) {
  16. translate([PCB_OX + px, PCB_OY + py, FLOOR]) {
  17. difference() {
  18. cylinder(d=BOSS_D, h=BOSS_H + 0.01, $fn=24);
  19. if (!stud)
  20. translate([0, 0, -0.1])
  21. cylinder(d=SCREW_PILOT_D, h=BOSS_H + 0.2, $fn=18);
  22. }
  23. if (stud)
  24. translate([0, 0, BOSS_H]) {
  25. cylinder(r=STUD_R, h=STUD_H, $fn=24);
  26. translate([0, 0, STUD_H])
  27. sphere(r=STUD_R, $fn=24);
  28. }
  29. }
  30. }
  31. // ============================================================
  32. // BASE
  33. // ============================================================
  34. module base() {
  35. color("#004B49") {
  36. difference() {
  37. rounded_box(OUT_L, OUT_W, BASE_H, CORNER_R);
  38. // Interior cavity (open top)
  39. translate([WALL, WALL, FLOOR])
  40. cube([CAV_L, CAV_W, BASE_H]);
  41. // ---- +Y wall cutouts ----
  42. // Sliding power switch pocket — closed exterior face, interior clearance only
  43. translate([PCB_OX + PWR_CX - PWR_W/2,
  44. OUT_W - WALL - 0.1,
  45. PCB_Z + PWR_CZ - PWR_H/2])
  46. cube([PWR_W, WALL - PWR_COVER_T + 0.1, PWR_H]);
  47. // USB-C slot
  48. translate([PCB_OX + USBC_CX - (USBC_W + 2*USBC_CBL_CLEAR)/2,
  49. OUT_W - WALL - 0.1,
  50. PCB_Z + USBC_CZ - (USBC_H + 2*USBC_CBL_CLEAR)/2])
  51. cube([USBC_W + 2*USBC_CBL_CLEAR, WALL + 0.2, USBC_H + 2*USBC_CBL_CLEAR]);
  52. // 4× button holes (3 user + 1 reset)
  53. for (bcx = BTN_CX)
  54. translate([PCB_OX + bcx,
  55. OUT_W + 0.1,
  56. PCB_Z + BTN_CZ])
  57. rotate([90, 0, 0])
  58. cylinder(d=BTN_D, h=WALL + 0.3, $fn=32);
  59. // ---- Y- wall step for lid flange clearance ----
  60. // Remove the full Y- wall above z=BASE_H-FLANGE_H-SLIDE_CLEAR so the lid
  61. // flanges can enter freely from Y-.
  62. translate([-0.1, -0.1, BASE_H - LIP_H - SLIDE_CLEAR])
  63. cube([OUT_L + 0.2, WALL + 0.2, LIP_H + SLIDE_CLEAR + 0.1]);
  64. }
  65. // Standoff bosses (added outside diff so cavity doesn't subtract them)
  66. pcb_boss(PCB_BOSS_X1, PCB_BOSS_Y1, stud=true); // stud diagonal
  67. pcb_boss(PCB_BOSS_X2, PCB_BOSS_Y2, stud=true); // stud diagonal
  68. pcb_boss(PCB_BOSS_X1, PCB_BOSS_Y2, stud=false); // screw diagonal
  69. pcb_boss(PCB_BOSS_X2, PCB_BOSS_Y1, stud=false); // screw diagonal
  70. }
  71. // Lid-retention flanges — right triangles, wide face flush with case top (z=BASE_H),
  72. // tip pointing down to (WALL, BASE_H-FLANGE_H). Hypotenuse faces down-into-cavity;
  73. // lid flanges slide underneath it for Z retention.
  74. color("#2C3863") {
  75. hull() {
  76. translate([WALL, WALL, BASE_H - 0.01])
  77. cube([FLANGE_W, CAV_W, 0.01]);
  78. translate([WALL, WALL, BASE_H - FLANGE_H])
  79. cube([0.01, CAV_W, 0.01]);
  80. }
  81. hull() {
  82. translate([OUT_L - WALL - FLANGE_W, WALL, BASE_H - 0.01])
  83. cube([FLANGE_W, CAV_W, 0.01]);
  84. translate([OUT_L - WALL - 0.01, WALL, BASE_H - FLANGE_H])
  85. cube([0.01, CAV_W, 0.01]);
  86. }
  87. // Y+ locking flanges — same angled profile as side flanges, in YZ plane;
  88. // split around FPC notch for cable clearance
  89. for (seg = [
  90. [WALL, PCB_OX + FPC_CX - FPC_NOTCH_W/2 - WALL],
  91. [PCB_OX + FPC_CX + FPC_NOTCH_W/2, OUT_L - WALL - (PCB_OX + FPC_CX + FPC_NOTCH_W/2)]
  92. ])
  93. hull() {
  94. translate([seg[0], OUT_W - WALL - FLANGE_W, BASE_H - 0.01])
  95. cube([seg[1], FLANGE_W, 0.01]);
  96. translate([seg[0], OUT_W - WALL - 0.01, BASE_H - FLANGE_H])
  97. cube([seg[1], 0.01, 0.01]);
  98. }
  99. }
  100. }
  101. // ============================================================
  102. // PREVIEW-ONLY COMPONENTS
  103. // ============================================================
  104. module stl_board() {
  105. translate([PCB_OX, PCB_OY, PCB_Z])
  106. EE04();
  107. }
  108. module battery() {
  109. color("darkgray", 0.85)
  110. translate([CAV_L - BATT_W - CLR_BATX,
  111. CAV_W - BATT_D - CLR_BATY,
  112. FLOOR + 0.01])
  113. cube([BATT_W, BATT_D, BATT_T]);
  114. }
  115. // ============================================================
  116. // RENDER
  117. // ============================================================
  118. base();
  119. if ($preview) {
  120. if (SHOW_BOARD) stl_board();
  121. if (SHOW_BATTERY) battery();
  122. }