From ef1dbbccfae9b4cbb9d644257b9ae1dd76191126 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Dante=20Ursini?= Date: Thu, 13 Feb 2025 13:28:06 -0300 Subject: [PATCH] Implementation and doc --- .gitignore | 6 + .openscad_docsgen_rc | 4 + Readme.md | 20 + battery-holder.json | 6 + battery-holder.scad | 648 +++++++++++++++++++++ doc/.source_hashes | 1 + doc/AlphaIndex.md | 10 + doc/TOC.md | 16 + doc/Topics.md | 4 + doc/_Sidebar.md | 10 + doc/battery-holder.scad.md | 72 +++ doc/images/battery-holder/battery_case.png | Bin 0 -> 21735 bytes doc/images/battery-holder/case.png | Bin 0 -> 21735 bytes run.sh | 61 ++ 14 files changed, 858 insertions(+) create mode 100644 .gitignore create mode 100644 .openscad_docsgen_rc create mode 100644 battery-holder.json create mode 100644 battery-holder.scad create mode 100644 doc/.source_hashes create mode 100644 doc/AlphaIndex.md create mode 100644 doc/TOC.md create mode 100644 doc/Topics.md create mode 100644 doc/_Sidebar.md create mode 100644 doc/battery-holder.scad.md create mode 100644 doc/images/battery-holder/battery_case.png create mode 100644 doc/images/battery-holder/case.png create mode 100755 run.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8837fe9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.DS_Store + + +docgen + +*.swp diff --git a/.openscad_docsgen_rc b/.openscad_docsgen_rc new file mode 100644 index 0000000..bb17041 --- /dev/null +++ b/.openscad_docsgen_rc @@ -0,0 +1,4 @@ +DocsDirectory: doc/ +TargetProfile: githubwiki +ProjectName: Battery Holder +GenerateDocs: Files, TOC, Index, Topics, CheatSheet, Sidebar diff --git a/Readme.md b/Readme.md index 3de1bed..ffca2d5 100644 --- a/Readme.md +++ b/Readme.md @@ -1,5 +1,18 @@ # Battery Holder +Here's the documentation: + + +
+ +```include doc/_Sidebar.md``` +
+ +- [Battery Holder](doc/battery-holder.scad.md) +- [Table of Contents](doc/TOC.md) +- [Alphabetical Index](doc/AlphaIndex.md) +- [Topics](doc/Topics.md) + ## Connection Use 4mm nickel strip available at Aliexpress [Nickel Plated Steel Strip Connector](https://www.aliexpress.com/item/1005005127569726.html) R$9.12 (0.1x4mm (50pcs)) @@ -12,4 +25,11 @@ Use 4mm nickel strip available at Aliexpress [Nickel Plated Steel Strip Connecto +## Generate Doc + +```bash +openscad-docsgen -m *.scad +``` + + diff --git a/battery-holder.json b/battery-holder.json new file mode 100644 index 0000000..d30e6b8 --- /dev/null +++ b/battery-holder.json @@ -0,0 +1,6 @@ +{ + "fileFormatVersion": "1", + "parameterSets": { + "New set 1": "" + } +} diff --git a/battery-holder.scad b/battery-holder.scad new file mode 100644 index 0000000..6164115 --- /dev/null +++ b/battery-holder.scad @@ -0,0 +1,648 @@ + +////////////////////////////////////////////////////////////////////// +// LibFile: battery-holder.scad +// Functions and modules for creating battery holders +// Includes: +// include +// FileGroup: Batteries +// FileSummary: This file generates battery holders for arbitrary cylindrical sizes.. +////////////////////////////////////////////////////////////////////// + + +/* [Battery Holder specs] */ + +// Battery Type +battery_type="AAA"; // [None,AA,AAA,18650*,18650P,C,D,CR123A] + +// Number of battery slots to generate +battery_slots = 1; + + + +strip_holes = true; +wire_channels = true; + +battery_symbol = true; +poles_symbol = true; + +contact_bulges = true; + + +// Section: Batteries + + + +////////////////////////////////////////////////////////////////////////////////////// +/// +/// FLEXBATTER: Flexing battery holder with built-in spring +/// +/// This file generates battery holders for arbitrary cylindrical sizes. +/// The number of batteries and their size is fully parametrized. +/// +/// The usual metallic spring at the minus pole is replaced by a +/// flexible printed spring, which is pressing the contacts firmly to +/// the battery. +/// +/// The contacts for the plus and minus pole can easily be made by +/// a few windings of the uninsulated ends of the connecting wires. +/// Each battery compartment contains are several holes to the outside +/// as well ad to the neighboring compartments, through which connecting +/// wires can be passed for easy configuring of parallel, serial or +/// balanced-serial battery packs. +/// +/// The preconfigured battery sizes are: +/// AA, AAA, C, D, 18650(Li-Ion), 18650P(protected Li-Ion), CR123A(16340) +/// +/// Given that the printed plastic spring needs to be flexible, ABS is the material +/// of choice here. +/// +////////////////////////////////////////////////////////////////////////////////////// +/// +/// 2014-09-09 Heinz Spiess, Switzerland +/// +/// released under Creative Commons - Attribution - Share Alike licence (CC BY-SA) +////////////////////////////////////////////////////////////////////////////////////// + + + + + + +/** + * Generates a flexible battery holder for 'n' cylindrical batteries with complex + * features like wire channels, screw holes, and contact points. + * + * @param {number} [n=1] - Number of battery slots to generate. + * @param {number} [l=65] - Length of each battery slot. + * @param {number} [d=18] - Diameter of the battery. + * @param {number} [hf=0.75] - Height factor for the battery holder relative to the battery diameter. + * @param {number} [r=4] - Radius for the plastic spring (calculated inside). + * @param {number} [shd=3] - Screw hole diameter. + * @param {number} [eps=0.28] - Epsilon for additional cavity space around the battery. + * @param {number} [el=0] - Extra length for the spring. + * @param {array} [xchan=[1/4,3/4]] - Relative positions for traversal wire channels. + * @param {number} [$fn=24] - Number of fragments for circles/cylinders for smoother curves. + * + * @description + * This module constructs a battery holder with: + * - A main body with a cavity for each battery. + * - Plastic springs for negative pole contact using the `sline` module. + * - Contact points (+ and -) for electrical connectivity. + * - Wire channels for routing electrical connections. + * - Screw holes for mounting. + * - Engraving for battery orientation symbols. + * + * Key Features: + * - **Chamfering** of edges for a more finished look (`chamfered_cube`). + * - **Deepening** for better grip on batteries (optional). + * - **Wire Channels**: Both longitudinal and transversal for wire routing. + * - **Spring**: Utilizes `sline` to create a complex spring shape for battery contact. + * - **Contact Points**: Bulges for ensuring good electrical contact. + * - **Engraving**: Symbols to indicate battery polarity. + * + * Note: + * - The module uses recursion implicitly through the `for` loop to create multiple slots. + * - Adjustments for middle separators are commented out but could be uncommented for use. + * - Some parameters like `r` are calculated within the module to adjust based on input. + */ + +// Module: battery_case() +// Usage: +// battery_case(n); +// Description: +// Generates a flexible battery holder for 'n' cylindrical batteries with complex +// features like wire channels, screw holes, and contact points. +// +// DefineHeader(BulletList): Parts +// Parts: This module constructs a battery holder with +// A main body with a cavity for each battery. +// Plastic springs for negative pole contact using the `sline` module. +// Contact points (+ and -) for electrical connectivity. +// Wire channels for routing electrical connections. +// Screw holes for mounting. +// Engraving for battery orientation symbols. +// +// DefineHeader(BulletList): Key Features +// Key Features: +// **Chamfering** of edges for a more finished look (`chamfered_cube`). +// **Deepening** for better grip on batteries (optional). +// **Wire Channels**: Both longitudinal and transversal for wire routing. +// **Spring**: Utilizes `sline` to create a complex spring shape for battery contact. +// **Contact Points**: Bulges for ensuring good electrical contact. +// **Engraving**: Symbols to indicate battery polarity. +// +// Arguments: +// n = Number of battery slots to generate. (default: 1) +// l = Length of each battery slot. (default: 65) +// d = Diameter of the battery. (default: 18) +// hf = Height factor for the battery holder relative to the battery diameter. (default: 0.75) +// r = Radius for the plastic spring (calculated inside). (default: 4) +// shd = Screw hole diameter. (default: 3) +// eps = Epsilon for additional cavity space around the battery. (default: 0.28) +// el = Extra length for the spring. (default: 0) +// xchan = Relative positions for traversal wire channels. (default: [1/4, 3/4]) +// $fn = Number of fragments for circles/cylinders for smoother curves. (default: 24) +// +// Example: Simple Case +// battery_case(n=1,l=46.1,d=10.45,hf=0.84,shd=2,el=1,xchan=[0.5],eps=0); + +module battery_case(n=1,l=65,d=18,hf=0.75,r=4,shd=3,eps=0.28,el=0,xchan=[1/4,3/4],$fn=24){ + ew=0.56; // extrusion width + eh=0.25; // extrusion height + w = 4*ew; // case wall thickness + ws = 2*ew; // spring wall thickness + ch = w-ws; // edge chamfering + deepen=0; //deepening for side grip of batteries + //el = 0; // extra length in spring + //eps = 0.28; + //shd = 3; // screw hole diameter + //hf=0.75; + //xchan=[1/4,3/4]; // relative position of traversal wire channels + + r = d/5+2*ws; // linear spring length (depends on sline() call!) + + for(i=[0:n-1])translate([0,i*(d+w+ws),0]){ // generate n battery cases + difference(){ + + union(){ + difference(){ + // main body + translate([0,-w-d/2,0]) + chamfered_cube([l+w,d+2*w+(i0)translate([-1,0,d/2+w])rotate([0,90,0])cylinder(r=d/2+eps,h=l+1); + } + + // plastic spring for minus pole + for(sy=[-1,1])scale([1,sy,1]) //assign(D=d+2*w-2*ws-0.7) + { + D=d+2*w-2*ws-0.7; + translate([ch,d/2+w-ws/2,0])rotate(-90) + //sline([90,0,120,90,120,90,0],[d/8+2,d/6,d/8-1,d/8,-d/8,d/8,d/2],0,ws,hf*d+w); + sline([0,180,0,180,0,-180,0,90,0],[r+ch+el,D/4,el,D/12,el/2,D/12,1+el/2,D/5,D/3],0,ws,hf*d+w); + + + } + } + + // lower and upper holes for contacts + if (strip_holes) + stripHoles(case_wall_thickness = w,spring_wall_thickness=ws,battery_diam = d,slot_length=l); + /* + for(z=[-2*ws,2*ws]) + translate([-2*ws,-w,w-ws/2+d/2+z]) + cube([l+2*w+2,2*w,ws]); + */ + + + // Wire channels + if (wire_channels) + wireChannels( + case_wall_thickness = w, + spring_wall_thickness = ws, + slot_length = l, + battery_diam = d, + spring_radius = r, + channel_pos = xchan, + extrusion_height = eh + ); + + + // grip deepening + if (deepen>0) + translate([w+l/2-0.5,-d/2-w-0.01,w+d+l]) + rotate([-90,0,0]){ + cylinder(r=l+deepen*d,h=d+2*w+2*ws+2,$fn=72); + if(i==0)cylinder(r1=l+deepen*d+ch,r2=l+deepen*d,h=ch+0.02,$fn=72); + if(i==n-1)translate([0,0,d+2*w-ch])cylinder(r2=l+deepen*d+ch,r1=l+deepen*d,h=ch+0.02,$fn=72); + + } + // conical screw holes in corners + for(x=[7+shd,l-2*shd])for(y=[-d/2+shd,d/2-shd]) + translate([x,y,-1]){ + cylinder(r=shd/2,h=w+2); + translate([0,0,w-shd/2+1])cylinder(r1=shd/2,r2=shd,h=shd/2+0.01); + } + + // holes for wires passing inside + for(sy=[-1,1])scale([1,sy,1]){ + translate([l-1,-d/2,w])cube([w+2,2,2]); + for(x=[3,l-7])translate([x,-d/2-w-ws-1,w])cube([3,w+ws+3,2]); + translate([3,-d/2+w/2-0.75,-1])cube([3,1.5,w+2]); + translate([-0.5,-d/2+w/2,0])rotate([0,90,0])cylinder(r=w/2,h=6.5,$fn=5); + } + + + if (battery_symbol) + batterySymbol( + case_wall_thickness = w, + battery_diam = d, + slot_length = l, + extrusion_height = eh, + ); + + // engrave plus symbol + //assign(sy=(l>12*shd)?1:-1) + if (poles_symbol) + polesSymbol( + case_wall_thickness = w, + battery_diam = d, + slot_length = l, + screw_hole_diameter = shd, + extrusion_height = eh, + + ); + + + + + if (contact_bulges) + contactBulges( + case_wall_thickness = w, + spring_wall_thickness = ws, + battery_diam = d, + slot_length = l, + spring_extra_length = el, + vertical_bulge = true + + + ); + + } +} + +module contactBulges( case_wall_thickness, spring_wall_thickness, battery_diam,slot_length, spring_extra_length, vertical_bulge ) { + // horizontal contact bulges (+ and - pole) + for( x = [ -0.3,slot_length ] ) + hull() + for(y=[ + -3+spring_extra_length, + +3-spring_extra_length + ]) + translate([ + x, + y, + case_wall_thickness + battery_diam / 2 + ]) + sphere(r=spring_wall_thickness); + + // vertical contact bulge (+ pole only) + + if (vertical_bulge) hull() + for(z=[-3+spring_extra_length,3-spring_extra_length]) + for(x=[0,case_wall_thickness-spring_wall_thickness]) + translate([ slot_length + x,0,case_wall_thickness + battery_diam / 2 + z]) + sphere(r=spring_wall_thickness); +} + + +/** + * Engraves a simple battery symbol on the side of a battery case. + * + * @param {number} case_wall_thickness - Thickness of the case walls. + * @param {number} slot_length - Length of the battery slot. + * @param {number} battery_diam - Diameter of the battery, used for symbol size and positioning. + * @param {number} extrusion_height - Height of the extrusion for the symbol. + * + * @description + * This module creates a visual representation of a battery by engraving: + * - A rectangle representing the battery body. + * - A smaller rectangle at one end to symbolize the positive terminal or battery cap. + * + * The positioning of the symbol is: + * - Centered along the length of the slot with an offset for the case wall thickness. + * - Placed slightly above the bottom of the battery diameter for visibility. + * + * Notes: + * - Both rectangles are centered (`true` in the `cube` calls) for symmetrical engraving. + * - The dimensions of the symbol parts are proportional to `slot_length` and `battery_diam`, ensuring the symbol scales appropriately with different battery sizes. + */ +module batterySymbol( case_wall_thickness, slot_length, battery_diam,extrusion_height ) { + translate( + [ + case_wall_thickness+slot_length/2, + battery_diam/4+1, + case_wall_thickness + ]) + cube( + [ + slot_length/5, + battery_diam/4.5, + 4*extrusion_height + ],true); + translate( + [ + case_wall_thickness+slot_length/2+slot_length/10, + battery_diam/4+1, + case_wall_thickness + ]) + cube([battery_diam/7,battery_diam/10,4*extrusion_height],true); +}; + + +/** + * Creates strip-like holes on both ends of the battery slot for contact purposes. + * + * @param {number} case_wall_thickness - Thickness of the case walls. + * @param {number} spring_wall_thickness - Thickness of the spring or contact wall. + * @param {number} battery_diam - Diameter of the battery, used for positioning. + * @param {number} slot_length - Length of the battery slot. + * + * @description + * This module generates two rectangular holes at each end of the battery compartment: + * - These holes are designed to facilitate contact between the battery terminals and external connectors or springs. + * - They are positioned at the top and bottom of the battery diameter area, relative to the case's interior. + * + * Key features: + * - **Positioning**: Holes are placed at the ends of the battery slot, with one at `z = -2*spring_wall_thickness` and another at `z = 2*spring_wall_thickness` above and below the battery's center line. + * - **Dimensions**: + * - Width spans the length of the slot plus additional space for case walls. + * - Height is twice the case wall thickness, ensuring enough room for contact. + * - Depth (or height in OpenSCAD's coordinate system) is equal to the spring wall thickness. + * + * Note: + * - The module uses a loop to create both holes symmetrically around the battery's center. + * - The exact positioning ensures these holes do not interfere with the battery's body but are accessible for contacts. + */ +module stripHoles( case_wall_thickness,spring_wall_thickness,battery_diam,slot_length ) { + for( z = [-2*spring_wall_thickness,2*spring_wall_thickness] ) + translate([ + -2*spring_wall_thickness, + -case_wall_thickness, + case_wall_thickness-spring_wall_thickness/2+battery_diam/2+z + ]) + cube([ + slot_length+2*case_wall_thickness+2, + 2*case_wall_thickness, + spring_wall_thickness + ]); +} + + +/** + * Creates wire channels in the battery case to route electrical connections. + * + * @param {number} case_wall_thickness - Thickness of the case walls. + * @param {number} spring_wall_thickness - Thickness of the spring or contact wall. + * @param {number} slot_length - Length of the battery slot. + * @param {number} battery_diam - Diameter of the battery. + * @param {number} spring_radius - Radius of the spring or additional space for wiring. + * @param {array} channel_pos - Array of relative positions for transversal channels along the slot's length. + * @param {number} extrusion_height - Height of the extrusion for positioning the wire channel. + * + * @description + * This module constructs wire channels for guiding wires: + * - **Longitudinal Channel**: Runs along the bottom of the battery case for wires connecting multiple batteries or exiting the case. + * - **Transversal Channels**: Provides paths for wires to cross the width of the case, positioned according to `channel_pos`. + * + * Key Features: + * - **Longitudinal Channel**: + * - Positioned at the base of the case, extending the length of the slot plus additional space. + * - Rotated to lie horizontally under the battery for ease of wire routing. + * - **Transversal Channels**: + * - Created at specified positions along the slot's length (`channel_pos`). + * - Run perpendicular to the longitudinal channel, allowing for cross-connection of wires or external connections. + * + * Notes: + * - Cylinders are used to form these channels, with $fn determining the number of facets for a smoother or more angular appearance. + * - The longitudinal channel's height includes the slot length plus extra space for routing flexibility. + * - Transversal channels are placed just below the battery's diameter to avoid interfering with battery placement. + */ +module wireChannels( case_wall_thickness, spring_wall_thickness,slot_length, battery_diam, spring_radius, channel_pos,extrusion_height ) { + // longitudinal bottom wire channel + translate([-2*spring_wall_thickness,0,0]) + rotate([0,90,0]) + cylinder( + r=case_wall_thickness/2, + h=slot_length + case_wall_thickness + 2 +spring_radius, + $fn=5 + ); + + // traversal bottom wire channels + for ( x = slot_length * channel_pos ) + translate([x,-battery_diam/2-case_wall_thickness-1,extrusion_height]) + rotate([-90,0,0]) + cylinder( + r = case_wall_thickness/2, + h = battery_diam +2 * case_wall_thickness + spring_wall_thickness+2, + $fn=6 + ); + +} + + +/** + * Engraves symbols for battery polarity (+ and -) on the side of the battery case. + * + * @param {number} case_wall_thickness - Thickness of the case walls. + * @param {number} slot_length - Length of the battery slot. + * @param {number} screw_hole_diameter - Diameter of the screw holes, used to determine symbol orientation. + * @param {number} battery_diam - Diameter of the battery, used for symbol size and positioning. + * @param {number} extrusion_height - Height of the extrusion for the symbols. + * + * @description + * This module adds visual indicators for battery polarity: + * - For longer batteries, symbols are placed horizontally. + * - For shorter batteries, symbols are adjusted vertically to fit within the available space. + * + * The symbols are: + * - **Plus (+)**: Created by intersecting two cubes to form a cross. + * - **Minus (-)**: A single cube representing a line. + * + * The placement and orientation of these symbols depend on: + * - `slot_length` compared to `screw_hole_diameter` to determine if the battery is considered 'short' or 'long'. + * - `sy` (scale y) determines whether symbols are placed on the top or side based on the comparison. + * + * Note: + * - The `echo` statement is included for debugging or informational purposes, to verify the battery diameter. + * - The commented-out code for middle separators suggests this module might have been part of a larger context where such adjustments were necessary but have since been removed or commented out. + */ +module polesSymbol( case_wall_thickness, slot_length,screw_hole_diameter, battery_diam, extrusion_height ) { + sy=( slot_length > 12 * screw_hole_diameter)?1:-1; + echo ("battery_diam",battery_diam); + { // for short batteries +- on the side + translate([ + case_wall_thickness+slot_length/2+slot_length/(sy>0?5:10), + sy*(battery_diam/4+1), + case_wall_thickness + ]){ + cube([1,battery_diam/4,4*extrusion_height],true); + cube([battery_diam/4,1,4*extrusion_height],true); + } + // engrave minus symbol + translate([ + case_wall_thickness+slot_length/2-slot_length/(sy>0?5:10), + sy*(battery_diam/4+1), + case_wall_thickness + ]) + cube([1,battery_diam/4,4*extrusion_height],true); + } + + //correction for middle separators + //if(i0) translate([-d,-d/2-w-0.1,-1])cube([d,ws/2+0.1,d+2]); + //else translate([1,-d/2-w,-0.01])cylinder(r1=ch,r2=0,h=ch); + } +} + + + + +//caseCR123A(n=2); +if (battery_type == "AAA") { + battery_case(n=battery_slots,l=46.1,d=10.45,hf=0.84,shd=2,el=1,xchan=[0.5],eps=0); +} else if ( battery_type == "AA" ) { + battery_case(n=battery_slots,l=51.6,d=14.4,hf=0.80,shd=2.5,el=0.5,eps=0.28); +} else if ( battery_type == "C" ) { + battery_case(n=battery_slots,l=51.6,d=26.4,hf=0.75,shd=3,eps=0.28); +} else if ( battery_type == "D" ) { + battery_case(n=battery_slots,l=61.5,d=34.0,hf=0.75,shd=3,eps=0.28); +} else if ( battery_type == "18650*" ) { + battery_case(n=battery_slots,l=65.5,d=18.4,hf=0.75,shd=3,eps=0.28); +} else if ( battery_type == "18650P") { + battery_case(n=battery_slots,l=67.5,d=18.4,hf=0.75,shd=3,eps=0.28); +} else if ( battery_type == "CR123A") { + battery_case(n=battery_slots,l=35.1,d=16.7,hf=0.75,shd=3,xchan=[0.5],eps=0.28); +} else { + echo (str("ERROR for battery type :'",battery_type,"'")); +} + + + + + +/** + * Creates an arc or a segment of a cylinder with inner and outer radii. + * + * @param {number} r1 - Inner radius of the arc. + * @param {number} r2 - Outer radius of the arc. + * @param {number} height - The height of the arc segment. + * @param {number} [a1=0] - Starting angle of the arc in degrees. + * 0 degrees is along the positive X-axis. + * @param {number} [a2=0] - Ending angle of the arc in degrees. + * Positive values are counter-clockwise from a1. + * + * @description + * This module constructs a 3D arc segment between two radii (`r1` and `r2`) + * from `a1` to `a2` degrees. The arc's height is determined by `height`. + * If `a2 - a1` is less than or equal to 180 degrees, it uses a direct + * difference operation to carve out the arc, otherwise, it uses intersection + * for arcs greater than 180 degrees to ensure proper geometry. + * + * The function uses cylinders and cubes for creating and subtracting shapes: + * - A larger cylinder (`r2`) forms the outer arc. + * - A smaller cylinder (`r1`) is subtracted to make the inner void. + * - Cubes are positioned and rotated to cut away the unwanted parts of the + * cylinders, forming the arc or segment shape. + * + * Note: + * - All rotations are in the XY plane (around the Z-axis). + * - The height parameter includes an extra 2 units for the difference and + * intersection operations to ensure clean cuts through the cylinders. + */ +module arc( r1, r2, height, a1=0, a2=0 ) { + if (a2 - a1 <= 180) { + // For arcs less than or equal to 180 degrees, we can directly cut the shape + difference() { + // Create the outer cylinder + cylinder(r=r2, h=height); + // Remove the inner part to make it hollow + translate([0,0,-1]) cylinder(r=r1, h=height+2); + // Cut off one side of the arc + rotate(a2) translate([-r1-r2,0,-1]) cube([2*(r1+r2),2*(r1+r2),height+2]); + // Cut off the other side of the arc + rotate(a1+180) translate([-r1-r2,0,-1]) cube([2*(r1+r2),2*(r1+r2),height+2]); + } + } else { + // For arcs greater than 180 degrees, we use intersection to ensure we keep the correct shape + difference() { + cylinder(r=r2, h=height); // Outer shape + translate([0,0,-1]) cylinder(r=r1, h=height+2); // Inner void + intersection() { + // First cut to carve the arc shape + rotate(a2) translate([-r1-r2,0,-1]) cube([2*(r1+r2),2*(r1+r2),height+2]); + // Second cut for arcs greater than 180 degrees to ensure we keep only the arc + rotate(a1+180) translate([-r1-r2,0,-1]) cube([2*(r1+r2),2*(r1+r2),height+2]); + } + } + } +} + + +/** + * Generates a "snake line" or a path with segments that can turn or go straight. + * + * @param {array} angle - An array of angles for each segment. + * Positive values indicate a left/counter-clockwise turn, + * negative for right/clockwise, and zero for straight segments. + * @param {array} radius - An array of radii for each segment. + * The absolute value of radius[i] is used for turning segments, + * and directly for straight segments. + * @param {number} i - Current index in the angle and radius arrays. + * @param {number} w - Width of the snake line. + * @param {number} h1 - Height of the snake line. + * + * @description + * This module constructs a continuous line that can bend at specified angles + * and lengths. It uses recursion to build the path segment by segment: + * + * - For each segment: + * - If the angle is non-zero (`a != 0`), it creates an arc using the `arc` module, + * where the radii of the arc are adjusted by `w/2` to account for the line's width. + * - For zero angle (`a == 0`), it simply extends straight using a cube. + * - The `scale` operation ensures the correct orientation of the arc for negative angles. + * - The `translate` and `rotate` operations move and orient each new segment relative + * to the last one. + * + * Notes: + * - The module uses a tiny overlap (`-r-0.01`) when placing cubes to ensure a seamless join. + * - Recursive calls to `sline` build the whole path until all angles in the array are processed. + */ +module sline(angle, radius, i, w, h1) { + scale([angle[i] >= 0 ? 1 : -1, 1, 1]) { // Flip for negative angles + // Declare variables for current segment + r = abs(radius[i]); // Radius for current segment + a = angle[i]; // Angle for current segment + + translate([a ? r : 0, 0, 0]) { // Move to start of segment + translate([-w/2, -r - 0.01, 0]) // Position for overlap + cube([w, 0.02, h1]); // Small cube for overlap + + if (a) { + // Create an arc if there's an angle (turn) + arc( + r1 = r - w/2, // Inner radius of arc + r2 = r + w/2, // Outer radius of arc + a1 = a, // Start angle, adjusted to be from 0 to a + height = h1 // Height of the arc + ); + } else if (r > 0) { + // Create straight segment if no turn and radius is positive + translate([-w/2, -r, 0]) cube([w, r, h1]); + } + + if (i + 1 < len(angle)) { // Check if there's another segment to process + rotate(angle[i]) // Rotate for the next segment + translate([a ? -r : 0, a ? 0 : -r, 0]) // Translate to the end of current segment + sline(angle, radius, i + 1, w, h1); // Recursively call for next segment + } + } + } +} +// build a cube with chamfered edges +module chamfered_cube(size,d=1){ + hull(){ + translate([d,d,0])cube(size-2*[d,d,0]); + translate([0,d,d])cube(size-2*[0,d,d]); + translate([d,0,d])cube(size-2*[d,0,d]); + } +} + + + + diff --git a/doc/.source_hashes b/doc/.source_hashes new file mode 100644 index 0000000..50c8c74 --- /dev/null +++ b/doc/.source_hashes @@ -0,0 +1 @@ +battery-holder.scad|6ed4929e3433db05a34a3565e39c611c992f9c4d586969cd2e0d3cd5bb49db3e diff --git a/doc/AlphaIndex.md b/doc/AlphaIndex.md new file mode 100644 index 0000000..4a75674 --- /dev/null +++ b/doc/AlphaIndex.md @@ -0,0 +1,10 @@ +# Alphabetical Index + +An index of Functions, Modules, and Constants by name. + +[B](#b) + +## B + +- [`battery_case()`](battery-holder.scad#module-battery_case) Mod + diff --git a/doc/TOC.md b/doc/TOC.md new file mode 100644 index 0000000..600050d --- /dev/null +++ b/doc/TOC.md @@ -0,0 +1,16 @@ +# Table of Contents + +## List of Files + +**Batteries:** + +- [battery-holder.scad](#1-battery-holderscad) ([docs](battery-holder.scad)) +This file generates battery holders for arbitrary cylindrical sizes.. + +## 1. [battery-holder.scad](battery-holder.scad) + +This file generates battery holders for arbitrary cylindrical sizes.. +- [Batteries](battery-holder.scad#section-batteries) + - [`battery_case()`](battery-holder.scad#module-battery_case) Mod + + diff --git a/doc/Topics.md b/doc/Topics.md new file mode 100644 index 0000000..3afd7c7 --- /dev/null +++ b/doc/Topics.md @@ -0,0 +1,4 @@ +# Topic Index + +An index of topics, with related functions, modules, and constants. + diff --git a/doc/_Sidebar.md b/doc/_Sidebar.md new file mode 100644 index 0000000..7af479d --- /dev/null +++ b/doc/_Sidebar.md @@ -0,0 +1,10 @@ +[Table of Contents](TOC) +[Function Index](AlphaIndex) +[Topics Index](Topics) + +## List of Files: + +**Batteries:** + +- [battery-holder.scad](battery-holder.scad) + diff --git a/doc/battery-holder.scad.md b/doc/battery-holder.scad.md new file mode 100644 index 0000000..47ecf64 --- /dev/null +++ b/doc/battery-holder.scad.md @@ -0,0 +1,72 @@ +# LibFile: battery-holder.scad + +Functions and modules for creating battery holders + +To use, add the following lines to the beginning of your file: + + include + +## File Contents + +1. [Section: Batteries](#section-batteries) + - [`battery_case()`](#module-battery_case) + + +## Section: Batteries + + +### Module: battery\_case() + +**Usage:** + +- battery_case(n); + +**Description:** + +Generates a flexible battery holder for 'n' cylindrical batteries with complex + features like wire channels, screw holes, and contact points. + +**Parts:** This module constructs a battery holder with + +- A main body with a cavity for each battery. +- Plastic springs for negative pole contact using the `sline` module. +- Contact points (+ and -) for electrical connectivity. +- Wire channels for routing electrical connections. +- Screw holes for mounting. +- Engraving for battery orientation symbols. + +**Key Features:** + +- **Chamfering** of edges for a more finished look (`chamfered_cube`). +- **Deepening** for better grip on batteries (optional). +- **Wire Channels**: Both longitudinal and transversal for wire routing. +- **Spring**: Utilizes `sline` to create a complex spring shape for battery contact. +- **Contact Points**: Bulges for ensuring good electrical contact. +- **Engraving**: Symbols to indicate battery polarity. + +**Arguments:** + +By Position | What it does +-------------------- | ------------ +`n` | Number of battery slots to generate. (default: 1) +`l` | Length of each battery slot. (default: 65) +`d` | Diameter of the battery. (default: 18) +`hf` | Height factor for the battery holder relative to the battery diameter. (default: 0.75) +`r` | Radius for the plastic spring (calculated inside). (default: 4) +`shd` | Screw hole diameter. (default: 3) +`eps` | Epsilon for additional cavity space around the battery. (default: 0.28) +`el` | Extra length for the spring. (default: 0) +`xchan` | Relative positions for traversal wire channels. (default: [1/4, 3/4]) +`$fn` | Number of fragments for circles/cylinders for smoother curves. (default: 24) + +**Example 1:** Simple Case + +battery\_case() Example 1 + +
+ + include + battery_case(n=1,l=46.1,d=10.45,hf=0.84,shd=2,el=1,xchan=[0.5],eps=0); + +--- + diff --git a/doc/images/battery-holder/battery_case.png b/doc/images/battery-holder/battery_case.png new file mode 100644 index 0000000000000000000000000000000000000000..775a92677ce0006ce033be499eaf787dc711f900 GIT binary patch literal 21735 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 O0000