"""Ball screw with a DIN 69051 Form B flanged single nut, TBI MOTION's SFU and SFNU series: the screw shaft by length (plain, as the screw's outside diameter) or the flanged ball nut. Shaft axis along Z from the XY plane up. The nut's axis along Z too, its flange face on the XY plane and the body rising from it, the two flats parallel to Y. Dimensions from TBI MOTION's catalogue, listed in the README.""" import math from steve import Model model_no = "SFNU01605-4" # TBI MOTION model number part = "screw" # screw (the shaft) or nut (the flanged ball nut) length = 500 # mm Shaft length (screw only) # model: (screw diameter d, lead I, ball Da, nut body D, flange A, flange thickness B, nut length L, bolt circle W, across the flats H, # bolt hole X), mm. TBI MOTION Ball Screw catalogue (copy hosted by Anaheim Automation, L011848, PDF of 2025-03-12), "SFNU/SFU (DIN 69051 # FORM B) Series Specifications": rolled ball screws page C76 (the same rows as the precision ground series, page C48). NUTS = { "SFU01204-4": (12, 4, 2.5, 24, 40, 10, 40, 32, 30, 4.5), "SFNU01605-4": (16, 5, 3.175, 28, 48, 10, 45, 38, 40, 5.5), "SFNU01610-3": (16, 10, 3.175, 28, 48, 10, 57, 38, 40, 5.5), "SFNU02005-4": (20, 5, 3.175, 36, 58, 10, 51, 47, 44, 6.6), "SFNU02505-4": (25, 5, 3.175, 40, 62, 10, 51, 51, 48, 6.6), } # Bolt holes, page C48/C76 drawing for d <= 32: six X holes on the bolt circle W, at 45 degree steps either side of the axis between the flats # (90 +- 45 and 270 +- 45 degrees, none on the flats' side). HOLE_ANGLES = (45, 90, 135, 225, 270, 315) if model_no not in NUTS: raise ValueError(f"no TBI MOTION model {model_no!r}: {', '.join(NUTS)}") d, lead, ball, D, A, B, L, W, H, X = NUTS[model_no] model = Model() if part == "screw": # The screw shaft as its outside diameter d (the catalogue entries' plain "simple" shaft; the ball groove isn't drawn). with model.sketch("shaft_sketch", on="XY", name="Shaft") as sk: sk.circle("shaft_circle", (0, 0), d / 2) model.extrude("shaft", "shaft_sketch", distance=length, name="Screw shaft") model.material("steel-generic", color="#b9bdc2") elif part == "nut": with model.sketch("flange_sketch", on="XY", name="Flange") as sk: sk.circle("flange_circle", (0, 0), A / 2) model.extrude("flange", "flange_sketch", distance=B, name="Flange") # the two flats, H apart model.box("flat_left", A, A, B, at=(-H / 2 - A / 2, 0, B / 2), op="cut", name="Flat") model.box("flat_right", A, A, B, at=(H / 2 + A / 2, 0, B / 2), op="cut", name="Flat") model.plane("body_plane", on="XY", offset=B, name="Body") with model.sketch("body_sketch", on="body_plane", name="Body") as sk: sk.circle("body_circle", (0, 0), D / 2) model.extrude("body", "body_sketch", distance=L - B, op="join", name="Nut body") with model.sketch("holes_sketch", on="XY", name="Bolt holes") as sk: for i, a in enumerate(HOLE_ANGLES): sk.circle(f"hole_{i}", (W / 2 * math.cos(math.radians(a)), W / 2 * math.sin(math.radians(a))), X / 2) model.extrude("holes", "holes_sketch", distance=B, op="cut", name="Bolt holes") # The bore: the screw's outside diameter d, a proportion (the catalogue doesn't dimension the nut's inside or its ball track). with model.sketch("bore_sketch", on="XY", name="Bore") as sk: sk.circle("bore_circle", (0, 0), d / 2) model.extrude("bore", "bore_sketch", distance=L, op="cut", name="Bore") model.material("steel-generic", color="#8d9298") else: raise ValueError("part is screw or nut") result = model.result()