"""T8 lead screw nut, brass: the flanged nut, or the anti-backlash nut (flanged nut, spring and second nut). Axis along Z, the flange's face on the XY plane, the body below it. The internal thread isn't modelled: the bore is the screw's 8 mm. Dimensions from the seller's drawing in the README.""" import math import cadquery as cq from steve import Model style = "flange" # flange or anti-backlash lead = 2 # mm Lead of the screw it fits (2, 4 or 8) detail = "full" # full: with holes and, for anti-backlash, the spring; simple: the nut's outline # Handson Technology data sheet MCH-1179, Anti-Backlash T-Nut for Lead Screw, Mechanical Dimension, p. 2, https://handsontec.com/dataspecs/Anti-backlash-T-nut.pdf FLANGE_D, FLANGE_T, BODY_D, LENGTH, PCD = 22, 4, 10.3, 15, 16 # the flanged nut COLLAR_D, COLLAR_T = 14, 4 # the second nut: a 14 mm collar 4 thick on the same 10.3 body, 15 long OVERALL = 50 # the anti-backlash nut over both nuts, the spring between them BORE = 8 HOLE = 3.5 # four mounting holes for M3; the drawing's hole figure is unclear, so this is an M3 clearance, for looks if lead not in (2, 4, 8): raise ValueError("The T8 nut fits leads 2, 4 and 8 (P2 with 1, 2 or 4 starts).") model = Model() first = cq.Workplane("XY").circle(FLANGE_D / 2).extrude(FLANGE_T).union(cq.Workplane("XY").workplane(offset=FLANGE_T - LENGTH).circle(BODY_D / 2).extrude(LENGTH - FLANGE_T), clean=False) first = first.cut(cq.Workplane("XY").workplane(offset=FLANGE_T - LENGTH - 1).circle(BORE / 2).extrude(LENGTH + 2)) if detail == "full": for k in range(4): a = math.radians(90 * k) first = first.cut(cq.Workplane("XY").workplane(offset=-1).center(PCD / 2 * math.cos(a), PCD / 2 * math.sin(a)).circle(HOLE / 2).extrude(FLANGE_T + 2)) model.add("nut", first, op="new", body="nut_body", name="Flanged nut") bodies = ["nut_body"] if style == "anti-backlash": bottom = FLANGE_T - OVERALL second = cq.Workplane("XY").workplane(offset=bottom).circle(COLLAR_D / 2).extrude(COLLAR_T).union(cq.Workplane("XY").workplane(offset=bottom + COLLAR_T).circle(BODY_D / 2).extrude(LENGTH - COLLAR_T), clean=False) second = second.cut(cq.Workplane("XY").workplane(offset=bottom - 1).circle(BORE / 2).extrude(LENGTH + 2)) model.add("second_nut", second, op="new", body="second_body", name="Second nut") bodies.append("second_body") if detail == "full": start = bottom + COLLAR_T # the spring sits over the bodies, from the second nut's collar to the flange wire = 0.8 # the spring's wire and coil count are proportions, for looks height = -start path = cq.Wire.makeHelix(height / 8, height - wire, COLLAR_D / 2 - wire).moved(cq.Location(cq.Vector(0, 0, start + wire / 2))) spring = cq.Workplane("XZ").center(COLLAR_D / 2 - wire, start + wire / 2).circle(wire / 2).sweep(cq.Workplane(obj=path), isFrenet=True) model.add("spring", spring, op="new", body="spring_body", name="Spring") model.material("steel-generic", bodies=["spring_body"], color="#8c8f94") model.material("brass", bodies=bodies, color="#c9a14a") result = model.result()