Compare versions
4 files changed, +81 −14 1.1.0: Real tooth grooves. detail = simple keeps a plain cylinder.
| @@ -1,9 +1,11 @@ | ||
| 1 | """Flanged timing pulley, 2GT (GT2), 3GT (GT3) and MXL: envelope for assemblies. | |
| 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; | |
| 2 | optionally the hub (diameter D, up to the overall length L) above the top flange. Set screws are not modelled. | |
| 2 | 3 | |
| 3 | The toothed body is drawn at its outside diameter O.D. (teeth not modelled: only the tooth groove's depth is published), | |
| 4 | 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 | |
| 5 | width W; optionally the hub (diameter D, up to the overall length L) above the top flange. Set screws are not modelled. | |
| 4 | detail = "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). | |
| 5 | 2GT 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 | 6 | """ |
| 7 | import math | |
| 8 | ||
| 7 | 9 | from steve import Model |
| 8 | 10 | |
| 9 | 11 | profile = "2GT" # Belt profile |
| @@ -11,6 +13,7 @@ | ||
| 11 | 13 | belt_width = 6 # mm Nominal belt width |
| 12 | 14 | bore = 5 # mm Bore |
| 13 | 15 | hub = False # Hub above the top flange (shape B) |
| 16 | detail = "full" # full: tooth grooves; simple: a plain cylinder at the outside diameter | |
| 14 | 17 | |
| 15 | 18 | # profile: {teeth: (P.D., O.D., D, F, E)}, D None: no hub offered. MISUMI FA Mechanical Components, High Torque Timing |
| 16 | 19 | # Pulleys 2GT pp. 1381-1382, 3GT pp. 1383-1384, Timing Pulleys MXL pp. 1389-1390 (2014), Number of Teeth / Dimension tables. |
| @@ -58,9 +61,45 @@ | ||
| 58 | 61 | if bore + 2 > e: |
| 59 | 62 | raise ValueError(f"Bore {bore} leaves no wall under the teeth: at most {e - 2} mm.") |
| 60 | 63 | |
| 64 | # profile: groove depth, from the Standard Tooth Profile drawings of the same pages (2GT 0.75; 3GT 1.14; MXL 0.64). | |
| 65 | GROOVE_DEPTH = {"2GT": 0.75, "3GT": 1.14, "MXL": 0.64} | |
| 66 | PITCH = {"2GT": 2.0, "3GT": 3.0, "MXL": 2.032} | |
| 67 | GROOVE_WIDTH = 0.62 # x pitch: mouth of the rounded 2GT and 3GT grooves, a proportion for looks | |
| 68 | MXL_BOTTOM = 0.67 # bottom of the MXL groove, same pages | |
| 69 | ||
| 70 | if teeth not in PULLEYS[profile]: | |
| 71 | raise ValueError(f"{profile} tooth counts in the source: {', '.join(str(t) for t in PULLEYS[profile])}.") | |
| 72 | if belt_width not in WIDTHS[profile]: | |
| 73 | raise ValueError(f"{profile} belt widths: {', '.join(str(w) for w in WIDTHS[profile])} mm.") | |
| 74 | pd, od, d_hub, f, e = PULLEYS[profile][teeth] | |
| 75 | a, w, l = WIDTHS[profile][belt_width] | |
| 76 | if hub and d_hub is None: | |
| 77 | raise ValueError(f"{profile} {teeth} teeth: the source offers no hub for this size.") | |
| 78 | if bore + 2 > e: | |
| 79 | raise ValueError(f"Bore {bore} leaves no wall under the teeth: at most {e - 2} mm.") | |
| 80 | ||
| 61 | 81 | model = Model() |
| 62 | with model.sketch("body_sketch", on="XY", name="Toothed body") as sk: | |
| 63 | sk.circle("body_od", (0, 0), od / 2) | |
| 82 | radius = od / 2 | |
| 83 | depth = GROOVE_DEPTH[profile] | |
| 84 | if detail == "simple": | |
| 85 | with model.sketch("body_sketch", on="XY", name="Toothed body") as sk: | |
| 86 | sk.circle("body_od", (0, 0), radius) | |
| 87 | else: | |
| 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) | |
| 64 | 103 | model.extrude("body", "body_sketch", distance=w, name="Toothed body") |
| 65 | 104 | with model.sketch("flange_low_sketch", on="XY", name="Lower flange") as sk: |
| 66 | 105 | sk.circle("flange_low_od", (0, 0), f / 2) |
| @@ -1,12 +1,11 @@ | ||
| 1 | 1 | name = "steve/timing-pulley" |
| 2 | version = "1.0.0" | |
| 2 | version = "1.1.0" | |
| 3 | 3 | runtime = "steve" |
| 4 | 4 | license = "MIT" |
| 5 | 5 | summary = "Flanged timing pulley envelope: GT2 (2GT), GT3 (3GT) and MXL, tooth counts, belt widths and bores as presets." |
| 6 | description = """Flanged timing pulley for 2GT, 3GT and MXL belts as an envelope for assemblies: the toothed body at its outside \ | |
| 7 | diameter, two flanges and the bore, optionally with a hub. Teeth and set screws are not modelled. Axis along Z, bottom flange \ | |
| 8 | on the XY plane. Dimensions from a maker's public catalogue (see the README); not affiliated with any maker or belt brand.""" | |
| 6 | description = """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.""" | |
| 9 | 7 | tags = ["pulley", "timing-pulley", "gt2", "gt3", "mxl", "belt", "power-transmission"] |
| 8 | changes = "Real tooth grooves. detail = simple keeps a plain cylinder." | |
| 10 | 9 | |
| 11 | 10 | [parameters.profile] |
| 12 | 11 | type = "choice" |
| @@ -45,3 +44,10 @@ | ||
| 45 | 44 | label = "Hub" |
| 46 | 45 | description = "Hub above the top flange (the source's shape B), on sizes that offer one." |
| 47 | 46 | |
| 47 | [parameters.detail] | |
| 48 | type = "choice" | |
| 49 | default = "full" | |
| 50 | choices = ["full", "simple"] | |
| 51 | label = "Detail" | |
| 52 | description = "full: tooth grooves. simple: a plain cylinder at the outside diameter, for big assemblies." | |
| 53 |
| @@ -1512,3 +1512,24 @@ | ||
| 1512 | 1512 | aliases = ["MXL 40 tooth", "MXL 40T", "MXL pulley 40 tooth", "MXL 40T 10mm bore", "MXL 40 teeth bore 10", "MXL", "belt profile=MXL; teeth=40; bore=10 mm; belt width=6.35 mm; flanged"] |
| 1513 | 1513 | standard = "MISUMI catalogue" |
| 1514 | 1514 | |
| 1515 | [[presets]] | |
| 1516 | id = "GT2-20T-B5-W6-simple" | |
| 1517 | title = "GT2 20 teeth, bore 5, belt 6 mm, simple (no grooves)" | |
| 1518 | params = { profile = "2GT", teeth = 20, belt_width = 6, bore = 5, hub = false, detail = "simple" } | |
| 1519 | aliases = ["GT2 20T simple"] | |
| 1520 | standard = "MISUMI catalogue" | |
| 1521 | ||
| 1522 | [[presets]] | |
| 1523 | id = "GT2-40T-B8-W6-hub" | |
| 1524 | title = "GT2 40 teeth, bore 8, belt 6 mm, with hub" | |
| 1525 | params = { profile = "2GT", teeth = 40, belt_width = 6, bore = 8, hub = true } | |
| 1526 | aliases = ["GT2 40T hub"] | |
| 1527 | standard = "MISUMI catalogue" | |
| 1528 | ||
| 1529 | [[presets]] | |
| 1530 | id = "MXL-40T-B8-W6.4-hub" | |
| 1531 | title = "MXL 40 teeth, bore 8, belt 6.4 mm, with hub" | |
| 1532 | params = { profile = "MXL", teeth = 40, belt_width = 6.4, bore = 8, hub = true } | |
| 1533 | aliases = ["MXL 40T hub"] | |
| 1534 | standard = "MISUMI catalogue" | |
| 1535 |
| @@ -6,13 +6,13 @@ | ||
| 6 | 6 | |
| 7 | 7 | Axis along Z, bottom flange's outer face on the XY plane: |
| 8 | 8 | |
| 9 | - the toothed body, a cylinder at the **outside diameter O.D.** over the width **W**. Teeth aren't modelled: the source | |
| 10 | gives the tooth groove's depth, not its full shape, and it says the groove varies with the number of teeth; | |
| 9 | - the toothed body at the **outside diameter O.D.** over the width **W**, with its grooves cut in; | |
| 11 | 10 | - a flange of diameter **F**, 1 mm thick, at each end of W; |
| 12 | 11 | - the bore; with `hub`, a hub of diameter **D** up to the overall length **L**. |
| 13 | 12 | |
| 14 | The pitch diameter **P.D.** sits outside the O.D. and is in the table below, for centre distances. Set screws aren't | |
| 15 | modelled. | |
| 13 | **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. | |
| 14 | ||
| 15 | 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. | |
| 16 | 16 | |
| 17 | 17 | ## Parameters |
| 18 | 18 | |
| @@ -23,6 +23,7 @@ | ||
| 23 | 23 | | `belt_width` | Nominal belt width: 2GT 6, 9; 3GT 6, 9, 15; MXL 4.8, 6.4, 9.5, 12.7 | |
| 24 | 24 | | `bore` | Bore, mm | |
| 25 | 25 | | `hub` | Hub above the top flange, on sizes that offer one | |
| 26 | | `detail` | `full` (tooth grooves) or `simple` (plain cylinder at O.D.) | | |
| 26 | 27 | |
| 27 | 28 | ## Source |
| 28 | 29 |