"""Hybrid stepper motor, NEMA frame sizes 8, 11, 14, 17, 23 and 34: envelope for assemblies. The mounting face is on the XY plane at the origin: the square body runs down along -Z for `body_length`, the round pilot and the shaft stand up along +Z. Four mounting holes on a square pattern (threads drawn at their nominal diameter; NEMA 23 and 34 have plain holes through the front flange). The D-flat on the smaller frames' shaft faces +Y. Windings, end bell, wires and connector are not modelled, and a NEMA 34 shaft's key is not drawn. """ import math from steve import Model frame = "NEMA17" # NEMA frame size body_length = 40 # mm Body length, mounting face to the back of the motor shaft_diameter = 5 # mm Shaft diameter # frame: (square side, hole spacing, hole diameter, hole depth, pilot diameter, pilot height, shaft length, # flat length from the shaft end) # Leadshine, CM Series Stepper Motors data sheet (c) 2018, section 2.3, printed pp. 07-14 (NEMA 8 to 34 drawings); NEMA 17 # side, hole depth and pilot height: SOYO SY42STH47-1206A sheet (42.3 max, depth 4.5 min, pilot 2), Leadshine shows 42, # depth 4, pilot 1.8. NEMA 34 pilot height: Novanta NEMA 34 data sheet 2022 (2.5 +-0.5 mm). FRAMES = { "NEMA8": (20.3, 15.4, 2.0, 2.0, 16.0, 1.5, 10.0, 0.0), "NEMA11": (28.2, 23.0, 2.5, 2.5, 22.0, 2.0, 20.0, 15.0), "NEMA14": (35.2, 26.0, 3.0, 4.5, 22.0, 2.0, 24.0, 15.0), "NEMA17": (42.3, 31.0, 3.0, 4.5, 22.0, 2.0, 24.0, 15.0), "NEMA23": (56.4, 47.14, 5.0, 5.0, 38.1, 1.6, 21.0, 15.0), "NEMA34": (86.0, 69.6, 5.5, 10.0, 73.0, 2.5, 32.0, 0.0), } # frame: {shaft diameter: width across the flat} (0: round shaft, no flat). Leadshine, as above: 4.5 on the 5 mm shafts; # NEMA 23 table: D 6.35 E 5.8, D 8 E 7.5. SHAFTS = { "NEMA8": {4: 0}, "NEMA11": {5: 4.5}, "NEMA14": {5: 4.5}, "NEMA17": {5: 4.5}, "NEMA23": {6.35: 5.8, 8: 7.5}, "NEMA34": {12.7: 0, 14: 0}, } # frame: (shortest, longest) body length of the sourced models: Leadshine's tables (NEMA 8 33-45, 11 32-51, 14 31-47, # 17 33-60, 23 41-85, 34 65-129), the body length is the maker's choice within a frame. BODY_RANGE = {"NEMA8": (33, 45), "NEMA11": (32, 51), "NEMA14": (31, 47), "NEMA17": (33, 60), "NEMA23": (41, 85), "NEMA34": (65, 129)} side, spacing, hole_d, hole_depth, pilot_d, pilot_h, shaft_l, flat_l = FRAMES[frame] if shaft_diameter not in SHAFTS[frame]: raise ValueError(f"{frame} shafts: {', '.join(str(d) for d in SHAFTS[frame])} mm.") low, high = BODY_RANGE[frame] if not low <= body_length <= high: raise ValueError(f"{frame} body lengths in the sourced data: {low} to {high} mm.") across_flat = SHAFTS[frame][shaft_diameter] half = spacing / 2 model = Model() with model.sketch("body_sketch", on="XY", name="Body") as sk: sk.rect("square", (-side / 2, -side / 2), (side / 2, side / 2)) model.extrude("body", "body_sketch", distance=-body_length, name="Body") with model.sketch("pilot_sketch", on="XY", name="Pilot") as sk: sk.circle("pilot_circle", (0, 0), pilot_d / 2) model.extrude("pilot", "pilot_sketch", distance=pilot_h, name="Pilot") with model.sketch("shaft_sketch", on="XY", name="Shaft") as sk: sk.circle("shaft_circle", (0, 0), shaft_diameter / 2) model.extrude("shaft", "shaft_sketch", distance=shaft_l, name="Shaft") with model.sketch("holes_sketch", on="XY", name="Mounting holes") as sk: for i, (x, y) in enumerate([(-half, -half), (half, -half), (half, half), (-half, half)]): sk.circle(f"hole_{i + 1}", (x, y), hole_d / 2) model.extrude("holes", "holes_sketch", distance=-hole_depth, op="cut", name="Mounting holes") if across_flat: model.plane("flat_plane", on="XY", offset=shaft_l - flat_l, name="Flat start") y0 = across_flat - shaft_diameter / 2 with model.sketch("flat_sketch", on="flat_plane", name="Shaft flat") as sk: sk.rect("flat", (-shaft_diameter, y0), (shaft_diameter, shaft_diameter)) model.extrude("flat_cut", "flat_sketch", distance=flat_l, op="cut", name="Shaft flat") model.material("steel-generic", color="#3a3c40") result = model.result()