// ===================================================================== // Coupon Test Cell Hardware (build plan phase 2E) // Small Zn-MnO2 test cells that match the full cell's plate thickness, // felt compression and current per area, at 1/124 of the active area. // // Parts: // clamp_plate - print 2 per coupon. Sets the stack gap with built-in // standoffs. // box, lid - small electrolyte cup with tab slots and a vent hole. // die_base, die_frame, die_punch, notch_shim // - press die that makes 30 x 30 x 2.90 mm cathode // coupons with the Ti mesh tab in the middle. // Units: mm. // ===================================================================== // // FILAMENT: PETG (same as the cell case; see cell_module_case.scad). // Box, lid, clamp plates: 4 perimeters, 100% infill, 0.2 mm layers. // Press die: 100% infill, 6+ perimeters. A PETG die is fine up to // about 1-1.5 tonnes on the punch (about 10-15 MPa on the coupon). // The punch stops at its shoulder, so the coupon thickness is set by // the die, not by the force. If the shoulder won't seat at 1.5 t, the // mix is too dry or overweight. For higher force, use this model as a // pattern for an aluminum die. // // --------------------------------------------------------------------- // COUPON STACK (front to back): // clamp plate | Zn 0.20 | felt 0.88 | cathode 2.90 | felt 0.88 | Zn 0.20 | clamp plate // Gap between plates = 5.06 mm, set by standoffs (2.53 mm per plate). // // Coupon cathode: 30 x 30 mm, 4.87 g mix (3.65 g MnO2 + 1.22 g carbon // + about 0.2 g PTFE solids), with a Ti mesh 30 x 30 + tab 6 wide x 45 // above the coupon (75 overall). // Zinc coupons: 30 x 30 x 0.20 mm + tab 6 wide x 45 above (2 per coupon cell). // Tab positions: front zinc 6 mm, cathode 15 mm, back zinc // 24 mm from the coupon's left edge (centres). // Felt: 34 x 34 mm (2 mm overhang all round), 2 per coupon cell. // Bolts: 4 x M4 x 20 nylon pan-head + nylon nuts. // Test current: 28 mA (= 1.56 mA/cm2, same as 3.5 A in the full cell). // Electrolyte: about 45 mL to the fill-line groove (flooded; the full cell is lean, so the // coupon shows electrode behaviour, not electrolyte limits). // Join the two zinc tabs together outside the cup with a short wire. // --------------------------------------------------------------------- part = "assembly"; // "clamp_plate", "box", "lid", "die_base", "die_frame", "die_punch", // "notch_shim", "assembly", "print_cell" (box + lid + 2 plates), // "print_die" (die parts laid out) $fn = 48; eps = 0.01; // ---- coupon stack ---- cp = 30; // coupon size zn_t = 0.20; felt_t = 0.88; // compressed cath_t = 2.90; gap = 2*zn_t + 2*felt_t + cath_t; // 5.06 felt_sz = 34; tab_w = 6; tab_len = 75; // from coupon bottom: reaches about 20 mm above the lid // ---- clamp plate ---- pl_w = 50; // X pl_h = 50; // Z (height) pl_t = 5; // Y cp_x0 = (pl_w - cp)/2; // coupon X start on the plate = 10 cp_z0 = 10; // coupon bottom height on the plate bolt_d = 4.4; // M4 clearance bolt_in = 4.5; // bolt centre from plate edges pad = 7; // standoff pad size stand_h = gap/2; // 2.53 per plate // tab X positions across the coupon (relative to coupon left edge) tab_cath_x = 15; // centre tab_zf_x = 6; // front zinc tab_zb_x = 24; // back zinc // ---- cup ---- wall = 2.0; bolt_stick = 6.5; // M4 head (3 mm) + nut (3.2) + slack, per side in_x = pl_w + 4; // 54 in_y = pl_t*2 + gap + 2*bolt_stick; // about 28 in_z = 62; floor_t = 2.0; lid_t = 3.0; lip_h = 3; lip_w = 1.2; lip_gap = 0.2; vent_d = 2.5; fill_line = cp_z0 + cp + 8; // electrolyte level above the floor // ---- press die ---- die_sz = 60; cav = 30.2; // cavity (coupon + 0.1 clearance per side) base_t = 8; frame_h = 14; pin_d = 4; pin_h = 4; pin_clear = 0.3; pin_pos = [[6, 6], [54, 54]]; punch_cl = 0.15; // punch clearance per side shoulder = 50; shoulder_t = 6; notch_h = cath_t/2 + 0.1; // 1.55: tab top at mid thickness shim_h = notch_h - 0.2; // 1.35: sits under the 0.2 mm tab // ===================================================================== module clamp_plate() { // Inner face is at y = pl_t (pads stick out toward the coupon). difference() { union() { cube([pl_w, pl_t, pl_h]); for (x = [bolt_in, pl_w - bolt_in], z = [bolt_in, pl_h - bolt_in]) translate([x - pad/2, pl_t - eps, z - pad/2]) cube([pad, stand_h + eps, pad]); } for (x = [bolt_in, pl_w - bolt_in], z = [bolt_in, pl_h - bolt_in]) translate([x, -1, z]) rotate([-90, 0, 0]) cylinder(d = bolt_d, h = pl_t + stand_h + 2); } } module coupon_stack_ghost() { // visual only: zinc, felt, cathode and tabs between the plates y0 = pl_t; layers = [["zn", zn_t], ["felt", felt_t], ["cath", cath_t], ["felt", felt_t], ["zn", zn_t]]; color("Silver") translate([cp_x0, y0, cp_z0]) cube([cp, zn_t, cp]); color("Khaki") translate([cp_x0 - 2, y0 + zn_t, cp_z0 - 2]) cube([felt_sz, felt_t, felt_sz]); color("DimGray") translate([cp_x0, y0 + zn_t + felt_t, cp_z0]) cube([cp, cath_t, cp]); color("Khaki") translate([cp_x0 - 2, y0 + zn_t + felt_t + cath_t, cp_z0 - 2]) cube([felt_sz, felt_t, felt_sz]); color("Silver") translate([cp_x0, y0 + gap - zn_t, cp_z0]) cube([cp, zn_t, cp]); // tabs color("Silver") translate([cp_x0 + tab_zf_x - tab_w/2, y0, cp_z0 + cp]) cube([tab_w, zn_t, tab_len - cp]); color("LightSlateGray") translate([cp_x0 + tab_cath_x - tab_w/2, y0 + gap/2 - 0.1, cp_z0 + cp]) cube([tab_w, 0.2, tab_len - cp]); color("Silver") translate([cp_x0 + tab_zb_x - tab_w/2, y0 + gap - zn_t, cp_z0 + cp]) cube([tab_w, zn_t, tab_len - cp]); } module clamp_pair() { // front plate, then the back plate mirrored so the pads meet clamp_plate(); translate([0, 2*pl_t + gap, 0]) mirror([0, 1, 0]) clamp_plate(); } // ===================================================================== // position of the clamp pair inside the cup (inner corner = origin) stack_x = (in_x - pl_w)/2; stack_y = (in_y - (2*pl_t + gap))/2; module box() { difference() { cube([in_x + 2*wall, in_y + 2*wall, in_z + floor_t]); translate([wall, wall, floor_t]) cube([in_x, in_y, in_z + 1]); // fill line groove on the outside, 0.4 mm deep translate([-eps, -eps, floor_t + fill_line]) cube([in_x + 2*wall + 2*eps, 0.4, 0.6]); } // two locating rails on the floor so the clamp pair sits centred for (y = [stack_y - 1.2, stack_y + 2*pl_t + gap]) translate([wall + stack_x + 8, wall + y, floor_t - eps]) cube([pl_w - 16, 1.2, 2 + eps]); } module lid() { // underside at z = 0 difference() { union() { cube([in_x + 2*wall, in_y + 2*wall, lid_t]); translate([wall + lip_gap, wall + lip_gap, -lip_h]) difference() { cube([in_x - 2*lip_gap, in_y - 2*lip_gap, lip_h + eps]); translate([lip_w, lip_w, -eps]) cube([in_x - 2*lip_gap - 2*lip_w, in_y - 2*lip_gap - 2*lip_w, lip_h + 3*eps]); } } // tab slots (tab + 1 mm each way) sy = wall + stack_y + pl_t; tab_slot(wall + stack_x + cp_x0 + tab_zf_x, sy); tab_slot(wall + stack_x + cp_x0 + tab_cath_x, sy + gap/2); tab_slot(wall + stack_x + cp_x0 + tab_zb_x, sy + gap); // vent hole translate([wall + in_x - 6, wall + in_y/2, -lip_h - 1]) cylinder(d = vent_d, h = 20); // labels translate([wall + stack_x + cp_x0 + tab_cath_x, wall + 3, lid_t - 0.6]) linear_extrude(1) text("+", size = 4, halign = "center", valign = "center"); translate([wall + stack_x + cp_x0 + tab_zf_x, wall + 3, lid_t - 0.6]) linear_extrude(1) text("-", size = 4, halign = "center", valign = "center"); } } module tab_slot(xc, yc) { translate([xc - (tab_w + 2)/2, yc - 1.2, -lip_h - 1]) cube([tab_w + 2, 2.4, lid_t + lip_h + 2]); } // ===================================================================== // Press die: base with pins, removable frame, stepped punch. // Use: frame on base -> notch shim in notch -> half the mix -> // mesh (tab out through the notch, resting on the shim) -> rest of mix -> // punch -> press until the shoulder seats -> remove punch -> lift the // frame straight up -> slide the coupon off. module die_base() { difference() { cube([die_sz, die_sz, base_t]); } for (p = pin_pos) translate([p[0], p[1], base_t - eps]) cylinder(d = pin_d, h = pin_h + eps); } module die_frame() { c0 = (die_sz - cav)/2; difference() { cube([die_sz, die_sz, frame_h]); translate([c0, c0, -1]) cube([cav, cav, frame_h + 2]); for (p = pin_pos) translate([p[0], p[1], -1]) cylinder(d = pin_d + pin_clear, h = pin_h + 1.5); // tab notch through the +X wall, open at the bottom translate([c0 + cav - 1, die_sz/2 - (tab_w + 0.6)/2, -1]) cube([c0 + 2, tab_w + 0.6, notch_h + 1]); // mark the tab side translate([die_sz - 4, die_sz/2, frame_h - 0.6]) linear_extrude(1) text("TAB", size = 3, halign = "center", valign = "center"); } } module die_punch() { // Upside down for printing: shoulder on the bed, body upward. // Body length = frame_h - cath_t, so the punch face stops 2.90 mm // above the base when the shoulder sits on the frame. body = cav - 2*punch_cl; union() { translate([-shoulder/2, -shoulder/2, 0]) cube([shoulder, shoulder, shoulder_t]); translate([-body/2, -body/2, shoulder_t - eps]) cube([body, body, frame_h - cath_t + eps]); } } module notch_shim() { // fills the notch under the tab so powder can't escape c0 = (die_sz - cav)/2; cube([c0, tab_w + 0.4, shim_h]); // flush with the cavity wall } // ===================================================================== if (part == "clamp_plate") { rotate([90, 0, 0]) clamp_plate(); // outer face on the bed, pads up } else if (part == "box") { box(); } else if (part == "lid") { translate([0, 0, lip_h]) lid(); } else if (part == "die_base") { die_base(); } else if (part == "die_frame") { die_frame(); } else if (part == "die_punch") { die_punch(); } else if (part == "notch_shim") { notch_shim(); } else if (part == "print_cell") { box(); translate([in_x + 2*wall + 8, 0, lip_h]) lid(); translate([0, in_y + 2*wall + 10 + pl_h, 0]) rotate([90, 0, 0]) clamp_plate(); translate([pl_w + 8, in_y + 2*wall + 10 + pl_h, 0]) rotate([90, 0, 0]) clamp_plate(); } else if (part == "print_die") { die_base(); translate([die_sz + 8, 0, 0]) die_frame(); translate([2*die_sz + 16 + shoulder/2, shoulder/2, 0]) die_punch(); translate([0, die_sz + 8, 0]) notch_shim(); } else if (part == "assembly") { color("LightSteelBlue", 0.35) box(); translate([wall + stack_x, wall + stack_y, floor_t]) { color("SteelBlue") clamp_pair(); coupon_stack_ghost(); } color("SteelBlue", 0.5) translate([0, 0, floor_t + in_z + 15]) lid(); // die, shown beside the cup translate([in_x + 30, 0, 0]) { color("Gainsboro") die_base(); color("LightGray") translate([0, 0, base_t]) die_frame(); color("DarkGray") translate([die_sz/2, die_sz/2, base_t + frame_h + shoulder_t + 20]) mirror([0, 0, 1]) die_punch(); } }