// Nissan Leaf Battery Shield // Designed to be cut out of flat plastic with a laser cutter topWidth = 203.2; //mm = 8 inches topLength = 152.4; //mm = 6 inches shieldHeight = 30; // mm = 1.181 inches thickness = 2.9; // mm = 0.118 inches, of the plastic. screwHead = 10; //mm, Diameter extra for the screw head on side panels, also extra sidePanel width/height on left/right/top. screwHole = 4; // mm, diameter extra for the screw holes. terminalCutout = 41; //mm (1.5+ inches) terminalCutoutH = 19; //mm, (0.75 inches) numTabsLength= 10; // Total number of tabs along the "length" tabSizeLength = (topLength / numTabsLength )/2; numTabsWidth = 10; tabSizeWidth = (topWidth / numTabsWidth) / 2; numTabsHeight = 5; tabSizeHeight = (shieldHeight / numTabsHeight) /2; //*********************************************************** // The top panel: //*********************************************************** module topPanel(reversed=false, halfwayTerminal = true) { difference() { square( [topWidth, topLength] ); // Cutouts to form the tabs that mesh with the // side panels for( pos = [0: numTabsLength-1] ) { // left translate([-0.001,pos * tabSizeLength*2-0.001]) square( [thickness, tabSizeLength] ); // right translate([topWidth-thickness+0.001,pos * tabSizeLength*2]) square( [thickness, tabSizeLength] ); } // end for // Cutouts to make the holes that interface with the longDivider tabs. for (pos = [0:numTabsWidth] ) { // Non terminal end translate([pos *tabSizeWidth*2,topLength-thickness ]) square( [tabSizeWidth, thickness] ); // Terminal end. translate([pos *tabSizeWidth*2,0]) square( [tabSizeWidth, thickness] ); // First Interior divider (closer to terminal end) translate([pos *tabSizeWidth*2,74]) square( [tabSizeWidth, thickness] ); // Second Interior divider (closer to non-terminal end) translate([pos *tabSizeWidth*2,74+36.5]) square( [tabSizeWidth, thickness] ); // Holes for the Leaf Cell terminal bolts. for( pos = [0: 33.866666 : topWidth-33.866666]) { // Non-terminal end. translate([pos+16.93333,topLength - 19-thickness]) circle(r=8, $fn=30); // Sense bolts (half size) translate([pos+16.93333,topLength - 19 - 36.5-thickness]) circle(r=4, $fn=30); // Terminal end. translate([pos+16.93333,topLength - 19 - 74 -thickness]) circle(r=8, $fn=30); } // Cutouts to interface with centerWall // The -5 is a hack here... for (pos = [0:numTabsWidth-5] ) { // Non terminal end translate([topWidth/2-thickness/2, pos *tabSizeWidth*2, ]) square( [thickness, tabSizeWidth] ); } // Opening for a sense terminal halfway through the battery for my PakTrakr system. if (halfwayTerminal == true) { translate([ topWidth-67.7333, topLength - 19-thickness]) circle(r=11); } // end if halfwayTerminal // + and - cutouts for the terminals // Left hand side. if (reversed == false) { // Four squares for the plus sign translate([terminalCutout+thickness*4.5,terminalCutout-thickness*5.5]) square([thickness/2,thickness*2]); translate([terminalCutout+thickness*4.5,terminalCutout-thickness*9]) square([thickness/2,thickness*2]); translate([terminalCutout+thickness*5.5,terminalCutout-thickness*6.5]) square([thickness*2,thickness/2]); translate([terminalCutout+thickness*2,terminalCutout-thickness*6.5]) square([thickness*2,thickness/2]); // One slot for the negative sign... (phew!) translate([topWidth - terminalCutout*1.5, terminalCutout/2]) square([thickness*4,thickness/2] ); } else { // Reversed = True! // Four squares for the plus sign translate([topWidth - terminalCutout*1.75+thickness*4.5,terminalCutout-thickness*5.5]) square([thickness/2,thickness*2]); translate([topWidth - terminalCutout*1.75+thickness*4.5,terminalCutout-thickness*9]) square([thickness/2,thickness*2]); translate([topWidth - terminalCutout*1.75+thickness*5.5,terminalCutout-thickness*6.5]) square([thickness*2,thickness/2]); translate([topWidth - terminalCutout*1.75+thickness*2,terminalCutout-thickness*6.5]) square([thickness*2,thickness/2]); // One slot for the negative sign... (phew!) translate([terminalCutout*1.3, terminalCutout/2]) square([thickness*4,thickness/2] ); } // End if reversed == False (for the terminals } // end for // Terminal cutouts translate([-0.01,-0.01]) square([terminalCutout, terminalCutout]); translate([topWidth-terminalCutout+0.01,-0.01]) square([terminalCutout, terminalCutout]); } // end difference } //*********************************************************** // The (2) side Panels //*********************************************************** module sidePanel() { numTabs = 10; tabSize = (topLength / numTabs )/2; difference() { square( [shieldHeight+screwHead , topLength+ 2*screwHead] ); //3 screw holes. // bottom near cutout translate([shieldHeight,screwHead/2]) circle(r=screwHole/2, $fn=30); // Middle near the non-terminal end. translate([shieldHeight/2+screwHead/2,topLength+screwHead+screwHead/2]) circle(r=screwHole/2, $fn=30); // top near cutout translate([screwHead/2,terminalCutout + screwHead + screwHead/2]) circle(r=screwHole/2, $fn=30); // Cutouts for the topPanel tabs. for (pos = [0:numTabsLength-1] ) { color([0,1,0]) translate([screwHead,pos * tabSizeLength*2 + tabSizeLength + screwHead ]) square( [thickness, tabSizeLength] ); } // end for // Cutouts to make the holes that interface with the longDivider tabs. for (pos = [0:numTabsHeight] ) { // Non Terminal End. translate([pos *tabSizeHeight*2+screwHead,topLength+screwHead-thickness]) square( [tabSizeHeight, thickness] ); // Terminal end. translate([pos *tabSizeHeight*2+screwHead,0+screwHead]) square( [tabSizeHeight, thickness] ); // First interior translate([pos *tabSizeHeight*2+screwHead,77+screwHead-thickness]) square( [tabSizeHeight, thickness] ); // Second interior translate([pos *tabSizeHeight*2+screwHead,78+35.5 + screwHead-thickness]) square( [tabSizeHeight, thickness] ); } // end for // Terminal end piece cutout translate([-0.01,-0.01]) square([shieldHeight+screwHead-terminalCutoutH,terminalCutout+screwHead]); } // end difference } //******************************************** // Long Divider - base for all 4 dividers //******************************************** module longDivider() { holeRadius = 7; difference() { square([topWidth,shieldHeight]); // Cutouts to make the tabs that interface with the topPanel holes. for (pos = [0:numTabsWidth-1] ) { color([0,1,0]) translate([pos * tabSizeWidth*2 + tabSizeWidth,0 ]) square( [tabSizeWidth, thickness] ); } // end for // Cutouts to make the tabs that interface with the sidePanel holes. for (pos = [0:numTabsHeight-1] ) { translate([0, pos * tabSizeHeight*2 + tabSizeHeight]) square( [tabSizeHeight, thickness] ); translate([topWidth-thickness, pos * tabSizeHeight*2 + tabSizeHeight]) square( [tabSizeHeight, thickness] ); } // end for /********************** Removed // hole in top center. translate([topWidth/2, thickness*2]) intersection() { circle(r=holeRadius, $fn=30); translate([-holeRadius,0]) square([holeRadius*2, holeRadius]); }// end intersection ***********************/ // Holes along the bottom for( pos = [33.8666: 33.866666 : topWidth-33.86666]) { translate([pos,shieldHeight]) circle(r=holeRadius, $fn=30); // These square cutouts at the bottom allow metal pieces // between the modules (if the bolts are cut off) from // "back" of the Nissan Leaf battery.... You can remove // them if you don't use the metal pieces. translate([pos-holeRadius*1.25,shieldHeight-holeRadius/1.5]) square([holeRadius*2.5,holeRadius]); } // Small air holes in middle. for (pos = [0: 20: topWidth] ) { translate([pos+7,8]) circle(r=holeRadius/3, $fn=30); translate([pos+17,14]) circle(r=holeRadius/3, $fn=30); translate([pos+7,20]) circle(r=holeRadius/3, $fn=30); } // end for } // end difference } // end module longDivider /****************************************** InnerDividerSlots - crosswise, meet with ends of center wall *******************************************/ module innerDividerSlots(){ difference() { longDivider(); for (pos = [0:numTabsHeight] ) { // Middle translate([topWidth/2-thickness/2, pos *tabSizeHeight*2]) square( [tabSizeHeight, thickness] ); } // end for } // end difference } // end innerDividerSlots() /***************************************** innerDividerHalfWall - slots around the center wall ******************************************/ module innerDividerHalfWall() { difference() { longDivider(); // Cutout to allow it to slot through the center Wall translate([topWidth/2-thickness/2,shieldHeight/2]) square([thickness, shieldHeight/2]); } // end difference } /****************************************** frontDivider ********************************************/ module frontDivider(){ difference() { innerDividerSlots(); // Terminal end piece cutout 1 & 2 translate([-0.01,-0.01]) square([terminalCutout,shieldHeight-terminalCutoutH]); translate([topWidth-terminalCutout,0]) square([terminalCutout,shieldHeight-terminalCutoutH]); } } /**************************************** centerWall *****************************************/ module centerWall() { difference() { // The -7 makes it sit up higher, so that metal dividers // from the "back" part of the nissan leaf battery can be // used. square([shieldHeight-7, 74+36.5+thickness]); // These two holes are NOT visible when the -7 is applied // to shieldHeight above, but if you take the -7 out, they // are needed to match up to the end walls. // Holes at each end translate([shieldHeight,0]) circle(r=7, $fn=30); translate([shieldHeight,74+36.5+thickness]) circle(r=7, $fn=30); // Cutout to allow it to slot through the first interior divider translate([0,74]) square([shieldHeight/2, thickness]); // Cutouts to make the tabs that interface with the topPanel holes. for (pos = [0:numTabsWidth-1] ) { translate([0,pos * tabSizeWidth*2 + tabSizeWidth ]) square( [thickness,tabSizeWidth] ); } // end for // Cutouts to make the tabs that interface with the longDividers holes. for (pos = [0:numTabsHeight-1] ) { translate([pos * tabSizeHeight*2 + tabSizeHeight,0]) square( [thickness, tabSizeHeight] ); translate([ pos * tabSizeHeight*2 + tabSizeHeight,74+36.5]) square( [thickness, tabSizeHeight] ); } // end for } // end difference } translate([-shieldHeight-thickness/2-screwHead,0]) //translate([-shieldHeight-thickness/2,-screwHead]) sidePanel(); translate([topWidth+thickness/2, 0] ) sidePanel(); translate([topWidth-shieldHeight+thickness,-90]) centerWall(); translate([0,topLength+thickness/2]) longDivider(); translate([-shieldHeight,-thickness/2]) rotate([0,180,180]) frontDivider(); translate([-shieldHeight,-thickness-shieldHeight]) rotate([0,180,180]) innerDividerHalfWall(); translate([-shieldHeight,-thickness*1.5-shieldHeight*2]) rotate([0,180,180]) innerDividerSlots(); topPanel(reversed=false);