--- /dev/null
+// -*- C -*-
+
+include <nutbox.scad>
+
+// pimoroni 3000mAh
+battery = [ 51.5,
+ 81.3,
+ 8.0 ];
+
+battery_wall = 2.0;
+battery_wall_unsupp = 4.0;
+battery_wall_top_gap = 0.75;
+
+battery_keeper_m_th = 4;
+battery_keeper_m_w = 4;
+battery_keeper_x_gap = 0.75; // each side
+battery_keeper_y_gap_overhang = 0.75;
+battery_keeper_y_gap_nutbox = 1.0;
+battery_keeper_z_gap_nutbox = 0.50;
+battery_keeper_z_gap_overhang = 0.75;
+
+battery_keeper_x_th_min = 1.5 * 1.5;
+battery_keeper_x_th_max = 2.5 * 1.5;
+battery_keeper_x_w = 5;
+battery_keeper_x_n = 5;
+
+battery_keeper_screw_x_off = -2.5;
+
+battery_wire_y = 4;
+
+battery_nutbox = nutbox_data_M3;
+
+// calculated
+
+battery_nutbox_z = max( battery[2] + battery_wall_top_gap,
+ NutBox_h_base(battery_nutbox) );
+battery_keeper_overhang_z = battery[2] + battery_keeper_m_th
+ + battery_keeper_z_gap_overhang;
+battery_keeper_overhang_wall = battery_keeper_m_w;
+battery_keeper_overhang_th = battery_keeper_m_th;
+
+module BatteryPlan(){
+ rectfromto([ -battery[0]/2, 0 ],
+ [ +battery[0]/2, battery[1] ]);
+}
+
+module BatteryBase(){ ////toplevel
+ // wall
+ linextr(-0.1, battery[2] - battery_wall_top_gap, convexity=7) {
+ difference(){
+ union(){
+ offset(r=battery_wall) BatteryPlan();
+ rectfromto([ 0,0 ],
+ [ -(battery[0]/2 + battery_wall_unsupp), battery[1]/3 ]);
+ }
+ BatteryPlan();
+ rectfromto([ fix_sz/2 - 0.5
+ + battery_keeper_screw_x_off, -30 ],
+ [ -battery[0], battery_wire_y ]);
+ }
+ }
+
+ // nutbox
+ translate([battery_keeper_screw_x_off, -fix_sz/2, battery_nutbox_z])
+ NutBox(battery_nutbox, battery_nutbox_z + 0.1);
+
+ // overhang for legs at rear
+ for (m=[0,1]) {
+ mirror([m,0,0]) {
+ translate([ battery[0]/2, battery[1], 0]) {
+ difference(){
+ linextr(-0.1,
+ battery_keeper_overhang_z
+ + battery_keeper_overhang_th,
+ convexity=1)
+ rectfromto([ -battery_keeper_m_w*2, -battery_keeper_m_w ],
+ [ battery_keeper_overhang_wall, battery_wall ]);
+ linextr(-1, battery_keeper_overhang_z,
+ convexity=1)
+ rectfromto([-20, -20], [0,0]);
+ }
+ }
+ }
+ }
+}
+
+module BatteryKeeper(){ ////toplevel
+ // A-frame
+ translate([0,0, battery[2]]) {
+ linextr(0, battery_keeper_m_th) {
+ intersection(){
+ // main legs
+ translate([0, +battery[1], 0])
+ multmatrix([[ 1, -battery_keeper_screw_x_off/battery[1], 0, 0, ],
+ [ 0,1,0, 0, ],
+ [ 0,0,1, 0, ]])
+ translate([0, -battery[1], 0])
+ for (sx=[-1,+1]) {
+ multmatrix([[ 1,0,0, 0, ],
+ [ 0,1,0, 0, ],
+ [ 0,0,1, 0, ]] +
+ sx *
+ ( battery[0]/2 - 0.5 * battery_keeper_m_w
+ - battery_keeper_x_gap ) /
+ ( battery[1] - 0.5 * battery_keeper_m_w )
+ *
+ [[ 0,1,0, 0, ],
+ [ 0,0,0, 0, ],
+ [ 0,0,0, 0, ]])
+ rectfromto([ -battery_keeper_m_w/2,
+ battery_keeper_y_gap_nutbox ],
+ [ +battery_keeper_m_w/2,
+ battery[1] - battery_keeper_y_gap_overhang ]);
+ }
+
+ // shape to round off the leg end corners
+ hull(){
+ for (sx=[-1,+1]) {
+ translate([ sx * ( battery[0]/2 - battery_keeper_m_w/2
+ -battery_keeper_x_gap) ,
+ battery[1] - battery_keeper_m_w/2
+ -battery_keeper_y_gap_overhang ])
+ circle(r = battery_keeper_m_w/2);
+ }
+ square(center=true, [ battery[0], 1 ]);
+ }
+ }
+ }
+
+ // x struts
+ for (i=[0 : battery_keeper_x_n-1]) {
+ linextr(0,
+ battery_keeper_x_th_min +
+ (battery_keeper_x_th_max - battery_keeper_x_th_min)
+ * pow( i/(battery_keeper_x_n-1)*2 - 1 , 2)
+ ) {
+ difference(){
+ translate([0, battery[1] * ((i + 0.5) / battery_keeper_x_n)])
+ square(center=true, [ battery[0], battery_keeper_x_w ]);
+ rectfromto([ -battery[1], -20 ],
+ [ +pi_sz[1] - pi_usb_from_other_side,
+ pi_usb_over_battery_proportion * battery[1] ]);
+ }
+ }
+ }
+ }
+
+ // tab for screw and nutbox
+ translate([battery_keeper_screw_x_off,
+ 0,
+ battery_nutbox_z + battery_keeper_z_gap_nutbox])
+ linextr(0, battery_keeper_m_th, convexity=4) {
+ difference(){
+ rectfromto([ -fix_sz/2, -fix_sz ],
+ [ +fix_sz/2,
+ 0.5 * battery[1] / battery_keeper_x_n +
+ 0.5 * battery_keeper_m_w ]);
+ translate([ 0, -fix_sz/2 ])
+ circle(r = battery_nutbox[0]/2);
+ }
+ }
+}
+
+module BatteryDemo(){ ////toplevel
+ color("grey") BatteryBase();
+ BatteryKeeper();
+}
+