Sign in with STEVE

steve/timing-pulley

Flanged timing pulley envelope: GT2 (2GT), GT3 (3GT) and MXL, tooth counts, belt widths and bores as presets.

v1.1.0 Latest STEVE MIT 0
Isometric
part.py 123 lines · Python · STEVE runtime · checked
Download
1"""Flanged timing pulley, 2GT (GT2), 3GT (GT3) and MXL. Axis along Z, the bottom flange's outer face on the XY plane; a flange of diameter F, 1 mm thick, at each end of the width W;
2optionally the hub (diameter D, up to the overall length L) above the top flange. Set screws are not modelled.
3
4detail = "full": the body at its outside diameter O.D. with its tooth grooves cut in. MXL grooves follow the published rack: depth 0.64, bottom 0.67, flanks 20 degrees (28 under 24 teeth).
52GT and 3GT publish the groove depth only, so the rounded groove's width is a proportion for looks, not for design. detail = "simple": a plain cylinder at O.D.
6"""
7import math
8
9from steve import Model
10
11profile = "2GT" # Belt profile
12teeth = 20 # Number of teeth
13belt_width = 6 # mm Nominal belt width
14bore = 5 # mm Bore
15hub = False # Hub above the top flange (shape B)
16detail = "full" # full: tooth grooves; simple: a plain cylinder at the outside diameter
17
18# profile: {teeth: (P.D., O.D., D, F, E)}, D None: no hub offered. MISUMI FA Mechanical Components, High Torque Timing
19# Pulleys 2GT pp. 1381-1382, 3GT pp. 1383-1384, Timing Pulleys MXL pp. 1389-1390 (2014), Number of Teeth / Dimension tables.
20PULLEYS = {
21 "2GT": {
22 14: (8.91, 8.40, None, 13, 6), 15: (9.55, 9.04, None, 14, 7), 16: (10.19, 9.68, None, 14, 7), 18: (11.46, 10.95, None, 16, 8),
23 20: (12.73, 12.22, None, 17, 9), 21: (13.37, 12.86, None, 18, 10), 22: (14.01, 13.50, 8, 18, 10), 24: (15.28, 14.77, 10, 20, 12),
24 25: (15.92, 15.41, 10, 20, 12), 26: (16.55, 16.04, 10, 21, 12), 28: (17.83, 17.32, 10, 23, 14), 30: (19.10, 18.59, 11, 24, 15),
25 32: (20.37, 19.86, 13, 25, 17), 34: (21.65, 21.14, 14, 27, 18), 36: (22.92, 22.41, 14, 27, 18), 38: (24.19, 23.68, 16, 29, 20),
26 40: (25.46, 24.95, 17, 30, 21), 44: (28.01, 27.50, 19, 32, 23), 48: (30.56, 30.05, 22, 35, 26), 50: (31.83, 31.32, 22, 36, 27),
27 60: (38.20, 37.69, 28, 42, 33),
28 },
29 "3GT": {
30 16: (15.28, 14.52, None, 19, 11), 18: (17.19, 16.43, None, 21, 12), 20: (19.10, 18.34, None, 23, 14), 22: (21.01, 20.25, 12, 24, 16),
31 24: (22.92, 22.16, 14, 26, 18), 25: (23.87, 23.11, 14, 27, 18), 26: (24.83, 24.07, 15, 28, 19), 28: (26.74, 25.98, 17, 30, 21),
32 30: (28.65, 27.89, 19, 32, 23), 32: (30.56, 29.80, 20, 34, 25), 34: (32.47, 31.71, 22, 36, 27), 36: (34.38, 33.62, 24, 38, 29),
33 40: (38.20, 37.44, 28, 42, 33), 44: (42.02, 41.26, 30, 46, 36), 48: (45.84, 45.08, 32, 49, 40), 50: (47.75, 46.99, 34, 51, 42),
34 60: (57.30, 56.54, 36, 61, 52),
35 },
36 "MXL": {
37 20: (12.94, 12.43, 9, 18, 11), 21: (13.58, 13.07, 9, 18, 11), 22: (14.23, 13.72, 9, 18, 11), 23: (14.88, 14.37, 11, 20, 13),
38 24: (15.52, 15.02, 11, 20, 13), 25: (16.17, 15.66, 11, 20, 13), 26: (16.82, 16.31, 12, 22, 14), 27: (17.46, 16.96, 12, 22, 14),
39 28: (18.11, 17.60, 12, 22, 14), 30: (19.40, 18.90, 14, 25, 16), 32: (20.70, 20.19, 14, 25, 16), 34: (21.99, 21.48, 14, 25, 16),
40 36: (23.29, 22.78, 16, 28, 18), 38: (24.58, 24.07, 16, 28, 18), 40: (25.87, 25.36, 18, 30, 20), 42: (27.17, 26.66, 18, 30, 20),
41 44: (28.46, 27.95, 20, 32, 23), 46: (29.75, 29.24, 20, 32, 23), 48: (31.05, 30.54, 22, 35, 25), 50: (32.34, 31.83, 22, 35, 25),
42 60: (38.81, 38.30, 28, 44, 32), 72: (46.57, 46.06, 30, 52, 40),
43 },
44}
45# profile: {nominal belt width: (A, W, L)}: Belt Nominal Width / Dimension tables of the same pages.
46WIDTHS = {
47 "2GT": {6: (7.0, 10.3, 18.0), 9: (10.0, 13.3, 21.0)},
48 "3GT": {6: (7.3, 11.0, 19.0), 9: (10.3, 14.0, 22.0), 15: (16.3, 20.0, 28.0)},
49 "MXL": {4.8: (6.0, 10.0, 16.5), 6.4: (7.5, 11.5, 18.0), 9.5: (11.0, 15.0, 22.0), 12.7: (14.0, 18.0, 25.0)},
50}
51FLANGE_THICKNESS = 1.0 # t1.0 on the same pages' drawings
52
53if teeth not in PULLEYS[profile]:
54 raise ValueError(f"{profile} tooth counts in the source: {', '.join(str(t) for t in PULLEYS[profile])}.")
55if belt_width not in WIDTHS[profile]:
56 raise ValueError(f"{profile} belt widths: {', '.join(str(w) for w in WIDTHS[profile])} mm.")
57pd, od, d_hub, f, e = PULLEYS[profile][teeth]
58a, w, l = WIDTHS[profile][belt_width]
59if hub and d_hub is None:
60 raise ValueError(f"{profile} {teeth} teeth: the source offers no hub for this size.")
61if bore + 2 > e:
62 raise ValueError(f"Bore {bore} leaves no wall under the teeth: at most {e - 2} mm.")
63
64# profile: groove depth, from the Standard Tooth Profile drawings of the same pages (2GT 0.75; 3GT 1.14; MXL 0.64).
65GROOVE_DEPTH = {"2GT": 0.75, "3GT": 1.14, "MXL": 0.64}
66PITCH = {"2GT": 2.0, "3GT": 3.0, "MXL": 2.032}
67GROOVE_WIDTH = 0.62 # x pitch: mouth of the rounded 2GT and 3GT grooves, a proportion for looks
68MXL_BOTTOM = 0.67 # bottom of the MXL groove, same pages
69
70if teeth not in PULLEYS[profile]:
71 raise ValueError(f"{profile} tooth counts in the source: {', '.join(str(t) for t in PULLEYS[profile])}.")
72if belt_width not in WIDTHS[profile]:
73 raise ValueError(f"{profile} belt widths: {', '.join(str(w) for w in WIDTHS[profile])} mm.")
74pd, od, d_hub, f, e = PULLEYS[profile][teeth]
75a, w, l = WIDTHS[profile][belt_width]
76if hub and d_hub is None:
77 raise ValueError(f"{profile} {teeth} teeth: the source offers no hub for this size.")
78if bore + 2 > e:
79 raise ValueError(f"Bore {bore} leaves no wall under the teeth: at most {e - 2} mm.")
80
81model = Model()
82radius = od / 2
83depth = GROOVE_DEPTH[profile]
84if detail == "simple":
85 with model.sketch("body_sketch", on="XY", name="Toothed body") as sk:
86 sk.circle("body_od", (0, 0), radius)
87else:
88 if profile == "MXL":
89 flank = math.tan(math.radians(28 if teeth < 24 else 20))
90 half_bottom = MXL_BOTTOM / 2
91 groove = [(half_bottom + depth * flank, 0.0), (half_bottom, depth), (-half_bottom, depth), (-half_bottom - depth * flank, 0.0)]
92 else:
93 half_mouth = GROOVE_WIDTH * PITCH[profile] / 2
94 groove = [(half_mouth * math.cos(math.pi * i / 6), depth * math.sin(math.pi * i / 6)) for i in range(7)]
95 outline = []
96 for n in range(teeth):
97 centre = 2 * math.pi * n / teeth
98 for u, v in groove:
99 angle = centre - u / radius
100 outline.append(((radius - v) * math.sin(angle), (radius - v) * math.cos(angle)))
101 with model.sketch("body_sketch", on="XY", name="Toothed body") as sk:
102 sk.polyline("body_outline", outline, closed=True)
103model.extrude("body", "body_sketch", distance=w, name="Toothed body")
104with model.sketch("flange_low_sketch", on="XY", name="Lower flange") as sk:
105 sk.circle("flange_low_od", (0, 0), f / 2)
106model.extrude("flange_low", "flange_low_sketch", distance=FLANGE_THICKNESS, name="Lower flange")
107model.plane("flange_plane", on="XY", offset=w - FLANGE_THICKNESS, name="Upper flange face")
108with model.sketch("flange_high_sketch", on="flange_plane", name="Upper flange") as sk:
109 sk.circle("flange_high_od", (0, 0), f / 2)
110model.extrude("flange_high", "flange_high_sketch", distance=FLANGE_THICKNESS, name="Upper flange")
111top = w
112if hub:
113 model.plane("hub_plane", on="XY", offset=w, name="Hub base")
114 with model.sketch("hub_sketch", on="hub_plane", name="Hub") as sk:
115 sk.circle("hub_od", (0, 0), d_hub / 2)
116 model.extrude("hub_body", "hub_sketch", distance=l - w, name="Hub")
117 top = l
118with model.sketch("bore_sketch", on="XY", name="Bore") as sk:
119 sk.circle("bore_d", (0, 0), bore / 2)
120model.extrude("bore_cut", "bore_sketch", distance=top, op="cut", name="Bore")
121model.material("aluminum-generic", color="#c9ccd0")
122result = model.result()
123

Flanged timing pulley for 2GT, 3GT and MXL belts: the toothed body with its grooves cut in, two flanges and the bore, optionally with a hub. Set screws are not modelled. detail = simple is a plain cylinder at the outside diameter for big assemblies. Axis along Z, bottom flange on the XY plane. Dimensions from a maker's public catalogue (see the README); not affiliated with any maker or belt brand.

Timing pulley (GT2, GT3, MXL)

Flanged timing pulley for 2GT (GT2), 3GT (GT3) and MXL belts, as an envelope for assemblies.

Geometry

Axis along Z, bottom flange's outer face on the XY plane:

  • the toothed body at the outside diameter O.D. over the width W, with its grooves cut in;
  • a flange of diameter F, 1 mm thick, at each end of W;
  • the bore; with hub, a hub of diameter D up to the overall length L.

MXL grooves follow the published rack: depth 0.64, bottom 0.67, flanks 20° (28° under 24 teeth). 2GT and 3GT: the source draws a rounded groove and dimensions its depth (0.75 and 1.14) only, adding that it varies with the number of teeth, so the groove's width is a proportion for looks, not for design.

The pitch diameter P.D. sits outside the O.D. and is in part.py, for centre distances. detail = "simple" is a plain cylinder at O.D., for big assemblies. Set screws aren't modelled.

Parameters

Parameter Meaning
profile 2GT, 3GT or MXL
teeth Number of teeth: 2GT 14 to 60, 3GT 16 to 60, MXL 20 to 72
belt_width Nominal belt width: 2GT 6, 9; 3GT 6, 9, 15; MXL 4.8, 6.4, 9.5, 12.7
bore Bore, mm
hub Hub above the top flange, on sizes that offer one
detail full (tooth grooves) or simple (plain cylinder at O.D.)

Source

MISUMI, FA Mechanical Components catalogue (2014), Number of Teeth / Dimension and Belt Nominal Width / Dimension tables and drawings:

Every row is in part.py (PULLEYS, WIDTHS); flange thickness t1.0 is on the drawings.

The source lists which bores it machines per tooth count. This part accepts any bore that leaves at least 1 mm of wall under E, so common bores (such as 16 teeth, 5 mm) can be drawn; check a real pulley's bore with its seller. MXL pulleys under 20 teeth have another shape in the source (shape K) and aren't offered. Names of belt profiles identify the belt; this part isn't made by or affiliated with any maker.

Preset list: sizes of the step.parts catalogue (MIT), see library/NOTICE.md.

  1. 1.1.0 Latest Compare with 1.0.0

    Real tooth grooves. detail = simple keeps a plain cylinder.

  2. 1.0.0
More #pulley
STEVEMIT

steve/timing-belt

GT2 (2GT) open timing belt as a straight envelope: width and length as parameters, with common lengths as presets.

0 15 sizes 0 1 hour ago v1.1.0
STEVEMIT

steve/gear-rack

Straight gear rack, ISO 53 basic rack, modules 0.5 to 2, any length, with common lengths as presets.

0 38 sizes 0 1 hour ago v1.0.0
STEVEMIT

steve/miter-gear

Straight miter gear (1:1 bevel, 90 degree) envelope, modules 1 to 3, with catalogue numbers as presets.

0 22 sizes 0 1 hour ago v1.1.0
STEVEMIT

steve/shaft-collar

Shaft collar: DIN 705 A set collar, bores 3 to 20 mm, and one-piece clamp collars.

0 12 sizes 0 3 hours ago v1.0.0