// CyberDeck case — CLAMSHELL // Two-part hinged laptop-style shell: keyboard deck on the bottom half, // touchscreen + Pi + LoRa board on the lid, joined by a printed pivot hinge. // Fits: Raspberry Pi 4/5, Meshtastic-class LoRa board, 5-7" DSI/HDMI display, // BB Q10/Q20-class keyboard. See ../bom.json for source hardware. // // Print settings: 0.2mm layer height, 25% infill, supports ON for the hinge // knuckles only (use "supports touching build plate" if your slicer allows // per-feature support painting). PETG recommended for the hinge (better // layer adhesion under repeated flex than PLA). // // Compile: openscad -o clamshell.stl clamshell.scad // ---- hardware envelope (from bom.json) ---- pi_w = 85; pi_d = 56; pi_h = 17; lora_w = 51; lora_d = 26; lora_h = 14; disp_w = 194; disp_d = 110; disp_h = 20; kb_w = 116; kb_d = 43; kb_h = 10; wall = 3; gap = 4; // clearance around each component hinge_len = 90; hinge_r = 6; lid_w = disp_w + 2*(wall+gap); lid_d = disp_d + 2*(wall+gap); lid_h = disp_h + wall + 6; // + room for Pi/LoRa stacked behind the panel base_w = lid_w; base_d = max(kb_d + 2*(wall+gap), 70); base_h = kb_h + wall + 8; function max(a,b) = a > b ? a : b; module rounded_box(w,d,h,r=3) { hull() { for (x=[r, w-r]) for (y=[r, d-r]) translate([x,y,0]) cylinder(r=r, h=h, $fn=32); } } module logo_badge(w) { // engraved wordmark badge, cut into the underside of the base translate([w/2, 10, 0]) linear_extrude(height=0.6) text("PERFECT WORLD PROJECT", size=4.2, halign="center", valign="center", font="Liberation Sans:style=Bold"); } module base_shell() { difference() { rounded_box(base_w, base_d, base_h, 4); // keyboard cavity translate([wall+gap, wall+gap, wall]) cube([kb_w, kb_d, kb_h+2]); // hollow interior below wall thickness translate([wall, wall, wall]) cube([base_w-2*wall, base_d-2*wall, base_h]); } // engraved logo on the front lip, raised text (embossed, not cut) translate([base_w/2, base_d-6, base_h]) linear_extrude(height=0.6) text("PWP", size=6, halign="center", valign="center", font="Liberation Sans:style=Bold"); // hinge knuckles (male) along the back edge for (x=[10, base_w-10-hinge_r*2]) translate([x, base_d-hinge_r, base_h]) rotate([0,90,0]) cylinder(r=hinge_r, h=hinge_r*2, $fn=48); } module lid_shell() { difference() { rounded_box(lid_w, lid_d, lid_h, 4); translate([wall+gap, wall+gap, wall+2]) cube([disp_w, disp_d, disp_h+2]); translate([wall, wall, wall]) cube([lid_w-2*wall, lid_d-2*wall, lid_h]); } logo_badge(lid_w); // hinge sockets (female), offset to interlock with base knuckles translate([0,0,0]) for (x=[10+hinge_r*2+1, lid_w-10-hinge_r*4-1]) translate([x, lid_d-1, 0]) rotate([0,90,0]) difference(){ cylinder(r=hinge_r+1.2, h=hinge_r*2+2, $fn=48); translate([0,0,-1]) cylinder(r=hinge_r+0.4, h=hinge_r*2+4, $fn=48); } } // Layout: base on plate, lid printed alongside, flat, hinge-open translate([0,0,0]) base_shell(); translate([base_w+20, 0, 0]) lid_shell();