|
|
@@ -0,0 +1,127 @@
|
|
|
+// Waveshare 2.13" e-Paper HAT (B) — ESP32 Nametag Case
|
|
|
+// Display slides in from X+; FPC cable exits out the closed X- face through a hull slot
|
|
|
+
|
|
|
+// --- Display Dimensions (landscape: portrait rotated 90°) ---
|
|
|
+DISP_W = 59.20; // overall width (X) — portrait height
|
|
|
+DISP_D = 29.20; // overall depth (Y) — portrait width
|
|
|
+DISP_T = 1.0; // thickness (Z)
|
|
|
+
|
|
|
+// --- Active (Visible) Area ---
|
|
|
+ACT_W = 48.55; // active area width (X) — portrait AA height
|
|
|
+ACT_D = 23.71; // active area depth (Y) — portrait AA width
|
|
|
+
|
|
|
+// Border offsets from display edge to active area:
|
|
|
+// X-: portrait FPC border ≈ 8.70 mm (closed/backstop side — cable exits here)
|
|
|
+// X+: portrait top border ≈ 1.95 mm (open/entry side)
|
|
|
+// Y±: symmetric ≈ 2.75 mm each side
|
|
|
+ACT_X_OFFSET = 8.70;
|
|
|
+ACT_Y_OFFSET = 2.75;
|
|
|
+
|
|
|
+// --- FPC Cable (exits X- side) ---
|
|
|
+FPC_W = 12.5;
|
|
|
+FPC_T = 0.3;
|
|
|
+FPC_LEN = 20.0; // visualization length of hanging tail
|
|
|
+
|
|
|
+// --- Case Parameters ---
|
|
|
+WALL = 3.0; // must exceed MAG_LIP_H (2.0) to keep pocket floor
|
|
|
+LIP = 1.5; // front bezel lip thickness (Z)
|
|
|
+TOL = 0.3; // per-side display clearance
|
|
|
+CHAM = 1.0;
|
|
|
+CHAM_ANGLE = 60;
|
|
|
+CORNER_R = 2.5;
|
|
|
+CLIP_Z = 0; // preview: mm to remove from Z+ (0 = full model)
|
|
|
+SHOW_DISP = true;
|
|
|
+SCREEN_EXPLODE = 0; // mm to pull display toward X+ in preview
|
|
|
+
|
|
|
+// --- Magnetic Strip Locating Lip (rear face) ---
|
|
|
+MAG_L = 1.772 * 25.4; // strip length ≈ 45.01 mm
|
|
|
+MAG_W = 0.512 * 25.4; // strip width ≈ 13.00 mm
|
|
|
+MAG_LIP_H = 2.0; // lip height protruding from rear face
|
|
|
+MAG_LIP_WALL = 1.0; // lip wall thickness
|
|
|
+MAG_TOL = 0.2; // per-side clearance for strip fit
|
|
|
+
|
|
|
+// --- Derived Dimensions ---
|
|
|
+cav_w = DISP_W + TOL * 2;
|
|
|
+cav_d = DISP_D + TOL * 2;
|
|
|
+case_w = WALL + cav_w; // no X+ wall; open for display entry
|
|
|
+case_h = WALL + DISP_T + LIP;
|
|
|
+case_d = WALL * 2 + cav_d;
|
|
|
+
|
|
|
+_cham_xy = CHAM * tan(CHAM_ANGLE);
|
|
|
+
|
|
|
+win_x = WALL + TOL + ACT_X_OFFSET;
|
|
|
+win_y = WALL + TOL + ACT_Y_OFFSET;
|
|
|
+
|
|
|
+// Magnetic strip recess geometry (centered on back face)
|
|
|
+_lip_il = MAG_L + 2 * MAG_TOL;
|
|
|
+_lip_iw = MAG_W + 2 * MAG_TOL;
|
|
|
+_lip_x = case_w / 2 - _lip_il / 2;
|
|
|
+_lip_y = case_d / 2 - _lip_iw / 2;
|
|
|
+
|
|
|
+// -------------------------------------------------------------------
|
|
|
+// Display mockup — approximate geometry for preview only
|
|
|
+// -------------------------------------------------------------------
|
|
|
+module EPD213B() {
|
|
|
+ color([0.82, 0.84, 0.80])
|
|
|
+ cube([DISP_W, DISP_D, DISP_T]);
|
|
|
+ color("white")
|
|
|
+ translate([ACT_X_OFFSET, ACT_Y_OFFSET, DISP_T])
|
|
|
+ cube([ACT_W, ACT_D, 0.02]);
|
|
|
+ color([1.0, 0.85, 0.1])
|
|
|
+ translate([-FPC_LEN, (DISP_D - FPC_W) / 2, (DISP_T - FPC_T) / 2])
|
|
|
+ cube([FPC_LEN, FPC_W, FPC_T]);
|
|
|
+}
|
|
|
+
|
|
|
+// -------------------------------------------------------------------
|
|
|
+
|
|
|
+module rounded_box(l, w, h, r) {
|
|
|
+ hull()
|
|
|
+ for (dx = [r, l-r], dy = [r, w-r])
|
|
|
+ translate([dx, dy, 0]) cylinder(r=r, h=h, $fn=32);
|
|
|
+}
|
|
|
+
|
|
|
+module epd_case() {
|
|
|
+ difference() {
|
|
|
+ rounded_box(case_w, case_d, case_h, CORNER_R);
|
|
|
+
|
|
|
+ // Display cavity — extends 0.01 mm past X+ face to leave that side open
|
|
|
+ translate([WALL, WALL, WALL])
|
|
|
+ cube([cav_w + 0.01, cav_d, DISP_T + TOL]);
|
|
|
+
|
|
|
+ // Active area window + chamfered top edges
|
|
|
+ translate([win_x, win_y, WALL + DISP_T - 0.01])
|
|
|
+ cube([ACT_W, ACT_D, LIP - CHAM + 0.02]);
|
|
|
+ hull() {
|
|
|
+ translate([win_x, win_y, case_h - CHAM])
|
|
|
+ cube([ACT_W, ACT_D, 0.01]);
|
|
|
+ translate([win_x - _cham_xy, win_y - _cham_xy, case_h])
|
|
|
+ cube([ACT_W + 2*_cham_xy, ACT_D + 2*_cham_xy, 0.01]);
|
|
|
+ }
|
|
|
+
|
|
|
+ // FPC slot through X- wall — hulled path, 2 mm padding each side of cable
|
|
|
+ hull() {
|
|
|
+ translate([-0.01, WALL + TOL + (DISP_D - FPC_W) / 2 - 2, WALL - 0.01])
|
|
|
+ cube([0.01, FPC_W + 4, DISP_T + TOL + 0.02]);
|
|
|
+ translate([WALL, WALL + TOL + (DISP_D - FPC_W) / 2 - 2, WALL - 0.01])
|
|
|
+ cube([0.01, FPC_W + 4, DISP_T + TOL + 0.02]);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Magnetic strip recess in back face
|
|
|
+ translate([_lip_x, _lip_y, -0.01])
|
|
|
+ cube([_lip_il, _lip_iw, MAG_LIP_H + 0.01]);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+color("#004B49")
|
|
|
+ intersection() {
|
|
|
+ epd_case();
|
|
|
+ cube([case_w + 1, case_d + 1,
|
|
|
+ ($preview && CLIP_Z > 0)
|
|
|
+ ? max(0.01, case_h - CLIP_Z)
|
|
|
+ : case_h + 1]);
|
|
|
+ }
|
|
|
+
|
|
|
+if ($preview && SHOW_DISP)
|
|
|
+ translate([WALL + TOL + SCREEN_EXPLODE, WALL + TOL, WALL])
|
|
|
+ EPD213B();
|
|
|
+
|