1//////////////////////////////////////////////////////////////////////
  2// LibFile: nema_steppers.scad
  3//   Mounting holes for NEMA motors, and simple motor models.
  4// Includes:
  5//   include <BOSL2/std.scad>
  6//   include <BOSL2/nema_steppers.scad>
  7// FileGroup: Parts
  8// FileSummary: NEMA motor mounts and stepper motor models.
  9//////////////////////////////////////////////////////////////////////
 10
 11
 12// Section: Motor Models
 13
 14
 15// Module: nema_stepper_motor()
 16// Usage:
 17//   nema_stepper_motor(size, h, shaft_len, [$slop=], ...) [ATTACHMENTS];
 18// Topics: Parts, Motors
 19// Description:
 20//   Creates a model of a NEMA standard stepper motor.
 21// Arguments:
 22//   size = The NEMA standard size of the stepper motor.
 23//   h = Length of motor body.  Default: 24mm
 24//   shaft_len = Length of shaft protruding out the top of the stepper motor.  Default: 20mm
 25//   ---
 26//   details = If false, creates a very rough motor shape, suitable for using as a mask.  Default: true
 27//   atype = The attachment set type to use when anchoring.  Default: `"body"`
 28//   $slop = If details is false then increase size of the model by double this amount (for use as a mask)
 29//   anchor = Translate so anchor point is at origin (0,0,0).  See [anchor](attachments.scad#subsection-anchor).  Default: `TOP`
 30//   spin = Rotate this many degrees around the Z axis after anchor.  See [spin](attachments.scad#subsection-spin).  Default: `0`
 31//   orient = Vector to rotate top towards, after spin.  See [orient](attachments.scad#subsection-orient).  Default: `UP`
 32// Anchor Types:
 33//   "shaft" = Anchor relative to the shaft.
 34//   "plinth" = Anchor relative to the plinth.
 35//   "body" = Anchor relative to the motor body.
 36//   "screws" = Anchor relative to the screw hole centers.  ie: TOP+RIGHT+FRONT is the center-top of the front-right screwhole.
 37// See Also: nema_stepper_motor(), nema_mount_mask()
 38// Examples:
 39//   nema_stepper_motor(size=8, h=24, shaft_len=15);
 40//   nema_stepper_motor(size=11, h=24, shaft_len=20);
 41//   nema_stepper_motor(size=17, h=40, shaft_len=30);
 42//   nema_stepper_motor(size=23, h=50, shaft_len=40);
 43//   nema_stepper_motor(size=23, h=50, shaft_len=40, details=false);
 44module nema_stepper_motor(size=17, h=24, shaft_len=20, details=true, atype="body", anchor=TOP, spin=0, orient=UP)
 45{
 46    info = nema_motor_info(size);
 47    motor_width   = info[0];
 48    plinth_height = info[1];
 49    plinth_diam   = info[2];
 50    screw_spacing = info[3];
 51    screw_size    = info[4];
 52    screw_depth   = info[5];
 53    shaft_diam    = info[6];
 54    geom = atype=="shaft"? attach_geom(r=shaft_diam/2, h=shaft_len-plinth_height, cp=[0,0,h/2+plinth_height/2+shaft_len/2]) :
 55        atype=="plinth"? attach_geom(r=plinth_diam/2, h=plinth_height, cp=[0,0,h/2+plinth_height/2]) :
 56        atype=="body"? attach_geom(size=[motor_width, motor_width, h]) :
 57        atype=="screws"? attach_geom(size=[screw_spacing, screw_spacing, screw_depth], cp=[0,0,h/2-screw_depth/2]) :
 58        assert(in_list(atype, ["shaft", "plinth", "body", "screws"]));
 59    attachable(anchor,spin,orient, geom=geom) {
 60        up(h/2) {
 61            if (details == false) {
 62                slop = get_slop();
 63                color([0.4, 0.4, 0.4]) 
 64                    cuboid(size=[motor_width+2*slop, motor_width+2*slop, h+slop], anchor=TOP);
 65                color([0.6, 0.6, 0.6])
 66                    cylinder(h=plinth_height+slop, d=plinth_diam+2*slop);
 67                color("silver")
 68                    cylinder(h=shaft_len+slop, d=shaft_diam+2*slop, $fn=max(12,segs(shaft_diam/2)));
 69            } else if (size < 23) {
 70                difference() {
 71                    color([0.4, 0.4, 0.4]) 
 72                        cuboid(size=[motor_width, motor_width, h], chamfer=size>=8? 2 : 0.5, edges="Z", anchor=TOP);
 73                    color("silver")
 74                        xcopies(screw_spacing)
 75                            ycopies(screw_spacing)
 76                                cyl(r=screw_size/2, h=screw_depth*2, $fn=max(12,segs(screw_size/2)));
 77                }
 78                color([0.6, 0.6, 0.6]) {
 79                    difference() {
 80                        cylinder(h=plinth_height, d=plinth_diam);
 81                        cyl(h=plinth_height*3, d=shaft_diam+0.75);
 82                    }
 83                }
 84                color("silver") cylinder(h=shaft_len, d=shaft_diam, $fn=max(12,segs(shaft_diam/2)));
 85            } else {
 86                difference() {
 87                    union() {
 88                        color([0.4, 0.4, 0.4])
 89                            cuboid([motor_width, motor_width, h], rounding=screw_size, edges="Z", anchor=TOP);
 90                        color([0.6, 0.6, 0.6]) {
 91                            difference() {
 92                                cylinder(h=plinth_height, d=plinth_diam);
 93                                cyl(h=plinth_height*3, d=shaft_diam+0.75);
 94                            }
 95                        }
 96                        color("silver")
 97                            cylinder(h=shaft_len, d=shaft_diam, $fn=max(12,segs(shaft_diam/2)));
 98                    }
 99                    color([0.4, 0.4, 0.4]) {
100                        xcopies(screw_spacing) {
101                            ycopies(screw_spacing) {
102                                cyl(d=screw_size, h=screw_depth*3, $fn=max(12,segs(screw_size/2)));
103                                down(screw_depth) cuboid([screw_size*2, screw_size*2, h], anchor=TOP);
104                            }
105                        }
106                    }
107                }
108            }
109        }
110        children();
111    }
112}
113
114
115
116// Section: Masking Modules
117
118
119// Module: nema_mount_mask()
120// Usage:
121//   nema_mount_mask(size, depth, l, [$slop], ...);
122// Topics: Parts, Motors
123// Description: Creates a mask to use when making standard NEMA stepper motor mounts.
124// Arguments:
125//   size = The standard NEMA motor size to make a mount for.
126//   depth = The thickness of the mounting hole mask.  Default: 5
127//   l = The length of the slots, for making an adjustable motor mount.  Default: 5
128//   ---
129//   anchor = Translate so anchor point is at origin (0,0,0).  See [anchor](attachments.scad#subsection-anchor).  Default: `CENTER`
130//   spin = Rotate this many degrees around the Z axis after anchor.  See [spin](attachments.scad#subsection-spin).  Default: `0`
131//   orient = Vector to rotate top towards, after spin.  See [orient](attachments.scad#subsection-orient).  Default: `UP`
132//   $slop = The printer-specific slop value to make parts fit just right.
133// Anchor Types:
134//   "full" = Anchor relative the full mask.
135//   "screws" = Anchor relative to the screw hole centers.  ie: TOP+RIGHT+FRONT is the center-top of the front-right screwhole.
136// See Also: nema_stepper_motor(), nema_mount_mask()
137// Examples:
138//   nema_mount_mask(size=14, depth=5, l=5);
139//   nema_mount_mask(size=17, depth=5, l=5);
140//   nema_mount_mask(size=17, depth=5, l=0);
141module nema_mount_mask(size, depth=5, l=5, atype="full", anchor=CENTER, spin=0, orient=UP)
142{
143    slop = get_slop();
144    info = nema_motor_info(size);
145    motor_width   = info[0];
146    plinth_height = info[1];
147    plinth_diam   = info[2] + slop;
148    screw_spacing = info[3];
149    screw_size    = info[4] + slop;
150    screw_depth   = info[5];
151    shaft_diam    = info[6];
152    screwfn = quantup(max(8,segs(screw_size/2)),4);
153    plinthfn = quantup(max(8,segs(plinth_diam/2)),4);
154    s = atype=="full"? [screw_spacing+screw_size, screw_spacing+screw_size+l, depth] :
155        atype=="screws"? [screw_spacing, screw_spacing, depth] :
156        assert(in_list(atype, ["full", "screws"]));
157    attachable(anchor,spin,orient, size=s) {
158        union() {
159            xcopies(screw_spacing) {
160                ycopies(screw_spacing) {
161                    if (l > 0) {
162                        ycopies(l) cyl(h=depth, d=screw_size, $fn=screwfn);
163                        cube([screw_size, l, depth], center=true);
164                    } else {
165                        cyl(h=depth, d=screw_size, $fn=screwfn);
166                    }
167                }
168            }
169            if (l > 0) {
170                ycopies(l) cyl(h=depth, d=plinth_diam, $fn=plinthfn);
171                cube([plinth_diam, l, depth], center=true);
172            } else {
173                cyl(h=depth, d=plinth_diam, $fn=plinthfn);
174            }
175        }
176        children();
177    }
178}
179
180
181
182// Section: Functions
183
184
185// Function: nema_motor_info()
186// Usage:
187//   info = nema_motor_info(size);
188// Description:
189//   Gets various dimension info for a NEMA stepper motor of a specific size.
190//   Returns a list of scalar values, containing, in order:
191//   - MOTOR_WIDTH: The full width and length of the motor.
192//   - PLINTH_HEIGHT: The height of the circular plinth on the face of the motor.
193//   - PLINTH_DIAM: The diameter of the circular plinth on the face of the motor.
194//   - SCREW_SPACING: The spacing between screwhole centers in both X and Y axes.
195//   - SCREW_SIZE: The diameter of the screws.
196//   - SCREW_DEPTH: The depth of the screwholes.
197//   - SHAFT_DIAM: The diameter of the motor shaft.
198// Arguments:
199//   size = The standard NEMA motor size.
200function nema_motor_info(size) =
201    let(
202        info_arr = [
203            [ 6, [ 14.0, 1.50, 11.0, 11.50, 1.6,  2.5,  4.00]],
204            [ 8, [ 20.3, 1.50, 16.0, 15.40, 2.0,  2.5,  4.00]],
205            [11, [ 28.2, 1.50, 22.0, 23.11, 2.6,  3.0,  5.00]],
206            [14, [ 35.2, 2.00, 22.0, 26.00, 3.0,  4.5,  5.00]],
207            [17, [ 42.3, 2.00, 22.0, 31.00, 3.0,  4.5,  5.00]],
208            [23, [ 57.0, 1.60, 38.1, 47.00, 5.1,  4.8,  6.35]],
209            [34, [ 86.0, 2.00, 73.0, 69.60, 6.5, 10.0, 14.00]],
210            [42, [110.0, 1.50, 55.5, 88.90, 8.5, 12.7, 19.00]],
211        ],
212        found = [for(info=info_arr) if(info[0]==size) info[1]]
213    )
214    assert(found, "Unsupported NEMA size.")
215    found[0];
216
217
218
219// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap