Sign in with STEVE

Compare versions

4 files changed, +75 −10 1.1.0: The screw shaft now has its ball track (detail = full, the default); detail = simple keeps the plain shaft.

part.py +54 −4
@@ -1,13 +1,15 @@
1"""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
2outside 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
1"""Ball screw with a DIN 69051 Form B flanged single nut, TBI MOTION's SFU and SFNU series: the screw shaft by length, with its ball track
2(detail = full) or plain at the screw's outside diameter (detail = simple), 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
33plane and the body rising from it, the two flats parallel to Y. Dimensions from TBI MOTION's catalogue, listed in the README."""
44import math
55
6import cadquery as cq
67from steve import Model
78
89model_no = "SFNU01605-4" # TBI MOTION model number
910part = "screw" # screw (the shaft) or nut (the flanged ball nut)
1011length = 500 # mm Shaft length (screw only)
12detail = "full" # full: the shaft with its ball track; simple: a plain shaft at the outside diameter d
1113
1214# 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,
1315# bolt hole X), mm. TBI MOTION Ball Screw catalogue (copy hosted by Anaheim Automation, L011848, PDF of 2025-03-12), "SFNU/SFU (DIN 69051
@@ -22,17 +24,65 @@
2224# 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
2325# (90 +- 45 and 270 +- 45 degrees, none on the flats' side).
2426HOLE_ANGLES = (45, 90, 135, 225, 270, 315)
27# The ball track, proportions (the catalogue says the groove is a Gothic arch, page C02 Fig 1.1.2, but doesn't dimension it): one circular groove
28# of radius TRACK x the ball's radius, its centre on the outside diameter d, so it is that deep; drawn with ARC_STEPS straight steps a side.
29TRACK = 1.04
30ARC_STEPS = 6
31MAX_TURNS = 150 # grooved all the way up to this length / lead, else END_TURNS at each end and a plain middle
32END_TURNS = 40
33
34
35def track(d, lead, ball, run, low=True, high=True):
36 """The grooved shaft, one solid sewn from the groove's own helical faces and trimmed flat at both ends (as lead-screw's thread)."""
37 top, rg = d / 2, TRACK * ball / 2
38 root = top - rg
39 up = [(top - rg * math.cos(math.radians(a)), rg * math.sin(math.radians(a))) for a in [90 * i / ARC_STEPS for i in range(ARC_STEPS + 1)]]
40 profile = up + [(r, lead - z) for r, z in reversed(up)] # groove bottom, up its side, the land, down the other side, next bottom
41
42 def helix(r, z):
43 return cq.Wire.makeHelix(lead, lead, r).moved(cq.Location(cq.Vector(0, 0, z)))
44
45 wires = [helix(r, z) for r, z in profile]
46 piece = [cq.Face.makeRuledSurface(a, b) for a, b in zip(wires, wires[1:])]
47 levels = math.ceil(run / lead) + 4
48 bottom = -2 * lead
49 faces = [face.moved(cq.Location(cq.Vector(0, 0, bottom + k * lead))) for k in range(levels) for face in piece]
50 for low_z in (bottom, bottom + levels * lead):
51 axis = cq.Wire.assembleEdges([cq.Edge.makeLine(cq.Vector(0, 0, low_z), cq.Vector(0, 0, low_z + lead))])
52 faces.append(cq.Face.makeRuledSurface(axis, wires[0].moved(cq.Location(cq.Vector(0, 0, low_z)))))
53 outline = [cq.Vector(0, 0, low_z)] + [w.startPoint().add(cq.Vector(0, 0, low_z)) for w in wires] + [cq.Vector(0, 0, low_z + lead)]
54 faces.append(cq.Face.makeFromWires(cq.Wire.makePolygon(outline + [outline[0]])))
55 body = cq.Workplane(obj=cq.Solid.makeSolid(cq.Shell.makeShell(faces)))
56 clear, spare = d + 1, 3 * lead + 1
57 body = body.cut(cq.Workplane("XY").workplane(offset=run).circle(clear).extrude(spare + levels * lead))
58 body = body.cut(cq.Workplane("XY").workplane(offset=-spare).circle(clear).extrude(spare))
59 shape = body.val()
60 if len(shape.Solids()) != 1 or not shape.isValid() or not math.pi * root * root * run < shape.Volume() < math.pi * top * top * run:
61 raise ValueError(f"The ball track could not be made one solid at d={d}, lead={lead}, length={run}")
62 return body
2563
2664if model_no not in NUTS:
2765 raise ValueError(f"no TBI MOTION model {model_no!r}: {', '.join(NUTS)}")
2866d, lead, ball, D, A, B, L, W, H, X = NUTS[model_no]
2967
3068model = Model()
31if part == "screw":
32 # The screw shaft as its outside diameter d (the catalogue entries' plain "simple" shaft; the ball groove isn't drawn).
69if part == "screw" and detail == "simple":
70 # The screw shaft as its outside diameter d (the catalogue entries' plain "simple" shaft).
3371 with model.sketch("shaft_sketch", on="XY", name="Shaft") as sk:
3472 sk.circle("shaft_circle", (0, 0), d / 2)
3573 model.extrude("shaft", "shaft_sketch", distance=length, name="Screw shaft")
74 model.material("steel-generic", color="#b9bdc2")
75elif part == "screw":
76 if length <= MAX_TURNS * lead:
77 model.add("shaft", track(d, lead, ball, length), name="Screw shaft")
78 else:
79 end = END_TURNS * lead
80 model.add("shaft", track(d, lead, ball, end), name="Screw shaft")
81 model.add("shaft_end", track(d, lead, ball, end).translate((0, 0, length - end)), name="Screw shaft")
82 model.plane("middle_plane", on="XY", offset=end, name="Plain middle")
83 with model.sketch("middle_sketch", on="middle_plane", name="Plain middle") as sk:
84 sk.circle("middle_circle", (0, 0), d / 2)
85 model.extrude("middle", "middle_sketch", distance=length - 2 * end, name="Plain middle")
3686 model.material("steel-generic", color="#b9bdc2")
3787elif part == "nut":
3888 with model.sketch("flange_sketch", on="XY", name="Flange") as sk:
pypart.toml +10 −2
@@ -1,9 +1,10 @@
11name = "steve/ball-screw"
2version = "1.0.0"
2version = "1.1.0"
3changes = "The screw shaft now has its ball track (detail = full, the default); detail = simple keeps the plain shaft."
34runtime = "steve"
45license = "MIT"
56summary = "Ball screw shaft and DIN 69051 Form B flanged ball nut, TBI MOTION SFU01204-4, SFNU01605-4, SFNU01610-3, SFNU02005-4 and SFNU02505-4."
6description = """A ball screw's shaft, cut to length, or its flanged single nut to DIN 69051 Form B (flange with two flats and six bolt holes), from TBI MOTION's SFU/SFNU series table: 12 x 4, 16 x 5, 16 x 10, 20 x 5 and 25 x 5 mm (diameter x lead), the sizes sold as SFU1204, SFU1605, SFU1610, SFU2005 and SFU2505. The shaft is plain at the screw's outside diameter; the ball groove isn't drawn. See the README."""
7description = """A ball screw's shaft, cut to length, or its flanged single nut to DIN 69051 Form B (flange with two flats and six bolt holes), from TBI MOTION's SFU/SFNU series table: 12 x 4, 16 x 5, 16 x 10, 20 x 5 and 25 x 5 mm (diameter x lead), the sizes sold as SFU1204, SFU1605, SFU1610, SFU2005 and SFU2505. The shaft has its ball track (detail = full) or is plain at the outside diameter (simple). See the README."""
78tags = ["ball-screw", "ball-nut", "din-69051", "linear-motion", "tbi", "sfu1605", "motion"]
89
910[parameters.model_no]
@@ -29,3 +30,10 @@
2930label = "Shaft length"
3031description = "The screw shaft's length (part = screw)."
3132
33[parameters.detail]
34type = "choice"
35default = "full"
36choices = ["full", "simple"]
37label = "Detail"
38description = "full: the shaft with its ball track. simple: a plain shaft at the outside diameter d."
39
presets.toml +7 −0
@@ -315,3 +315,10 @@
315315aliases = ["SFU2505", "ball screw family=SFU2505; component=ball_nut; generic envelope", "SFU2505 ball nut", "SFU2505 flange ball nut", "SFNU02505-4", "TBI SFNU02505-4", "SFU2505 nut DIN 69051", "Ball nut SFNU02505-4, DIN 69051 Form B flange (SFU2505 nut)", "ball screw family=SFU2505; component=flange_ball_nut; generic envelope"]
316316standard = "TBI MOTION"
317317
318[[presets]]
319id = "SFNU01605-4-L500-simple"
320title = "Ball screw shaft SFNU01605-4 (DIN 69051 Form B, SFU1605), 500 mm, simple"
321params = { model_no = "SFNU01605-4", part = "screw", length = 500, detail = "simple" }
322aliases = ["SFU1605 ball screw 500 simple"]
323standard = "TBI MOTION"
324
README.md +4 −4
@@ -2,7 +2,7 @@
22
33A ball screw's shaft, or its flanged single ball nut, from TBI MOTION's SFU and SFNU series. The nut's flange follows DIN 69051 Form B: a round flange with two flats and six bolt holes.
44
5- **Screw** (`part = "screw"`): the shaft, a plain cylinder at the screw's outside diameter d, `length` long, standing on the XY plane along +Z. The ball groove isn't drawn.
5- **Screw** (`part = "screw"`): the shaft, `length` long, standing on the XY plane along +Z, with its ball track, a right-hand helical groove of the lead (`detail = "full"`, the default). `detail = "simple"` gives a plain cylinder at the screw's outside diameter d. A shaft up to 150 leads long is grooved all the way. A longer one has 40 leads of track at each end and a plain middle at d. A real screw is grooved throughout, so read the plain middle as an envelope.
66- **Nut** (`part = "nut"`): the flange, A across and B thick, with its face on the XY plane and its flats H apart, parallel to Y. Six X holes sit on the bolt circle W. The body, D across, rises from the flange to the nut's length L. The bore is the screw's outside diameter d.
77
88| Model | d x lead | Ball Da | D | A | B | L | W | H | X | Nut weight | Shaft weight |
@@ -23,11 +23,11 @@
2323
2424**The names.** The old catalogue names these sfu1204, sfu1605, sfu1610, sfu2005 and sfu2505. The names carry no maker: in the market they mean a ball screw of that diameter and lead with a DIN 69051 Form B flanged nut. Each is mapped to TBI MOTION's model with that standard, diameter and lead. For 12 x 4 that is TBI's SFU01204-4. For the others it is TBI's SFNU type, a single flanged nut with TBI's NU-type nut inside, in the same DIN 69051 Form B table. TBI's SFU (U-type nut) rows don't have 16 x 5, 16 x 10, 20 x 5 or 25 x 5.
2525
26**Proportions, stated plainly.** The catalogue doesn't dimension the nut's inside, so the bore is the screw's outside diameter d, with no ball track drawn. The oil hole Q and the wiper aren't drawn. The shaft is a plain cylinder at d, which is what the old catalogue's "simple" shafts are.
26**Proportions, stated plainly.** The catalogue says TBI's groove is a Gothic arch (page C02, Fig 1.1.2) but doesn't dimension it. So the track is drawn as one circular groove of 1.04 times the ball's radius, its centre on the outside diameter d, which makes it that deep. It is drawn in six straight steps a side. The outside of the shaft is drawn at d. The catalogue doesn't dimension the nut's inside, so the nut's bore is plain at d, with no track. The oil hole Q and the wiper aren't drawn.
2727
28**Mass.** The material is steel (`steel-generic`). The shafts come out at 0.888 kg/m (12) and 1.578 kg/m (16), against TBI's 0.87 and 1.56: within 2 %. The nuts are solid between the bore and the outside, without the ball track and return channels, so they come out heavier than TBI's weights: SFU01204-4 148 g against 130 g, and SFNU01605-4 218 g against 183 g.
28**Mass.** The material is steel (`steel-generic`). TBI's shaft weights are the plain cylinder at d: 0.888 kg/m for 12 and 1.578 kg/m for 16, against TBI's 0.87 and 1.56. The `simple` shaft matches them within 2 %. The grooved shaft is about a fifth lighter, 1.27 kg/m for 16 x 5, because the track takes that much away and TBI's weight list doesn't count it. The nuts are solid between the bore and the outside, without the ball track and return channels, so they come out heavier than TBI's weights: SFU01204-4 148 g against 130 g, and SFNU01605-4 218 g against 183 g.
2929
3030## Catalogue models
3131
32The old catalogue's ball-screw entries have no models to measure. Each `<name> ball screw L<n> simple` entry maps to that model's shaft preset of that length. `<name> ball nut` and `<name> flange ball nut` both map to the model's nut, which has a flange. The `<name> nut housing` entries are left out: a nut housing isn't part of TBI MOTION's ball screw series, and the entries name no maker of one.
32The old catalogue's ball-screw entries have no models to measure. Each `<name> ball screw L<n> simple` entry maps to that model's shaft preset of that length, which has the track. `detail = "simple"` gives the old catalogue's plain shaft. `<name> ball nut` and `<name> flange ball nut` both map to the model's nut, which has a flange. The `<name> nut housing` entries are left out: a nut housing isn't part of TBI MOTION's ball screw series, and the entries name no maker of one.
3333