| | @@ -1,9 +1,14 @@ |
| 1 | | -"""Straight miter gear (ratio 1:1), KHK SM series: an envelope for assemblies, the solid of revolution of the published outline with the teeth filled in: |
| 2 | | -hub of diameter B and width H on the XY plane, the back cone out to the outside diameter D at G above the back (the crown), and the tip cone at 45 degrees |
| 3 | | -up to the total length F, with the bore A through. Axis along Z; the back is on the XY plane. The teeth aren't modelled.""" |
| 1 | +"""Straight miter gear (ratio 1:1), KHK SM series. The outline is the published one: hub of diameter B and width H on the XY plane, the back cone out to the outside diameter D |
| 2 | +at G above the back (the crown), a 45 degree tip cone up to the total length F, and the bore A through. detail = "full" cuts the teeth into it: each gap runs along the pitch cone |
| 3 | +to the apex, its section computed with Tredgold's approximation (the involute of the equivalent spur gear of z / cos 45 degrees teeth, ISO 53 proportions). This is close for looks and |
| 4 | +fits, not a tooth-contact model. detail = "simple" keeps the teeth filled in. Axis along Z; the back is on the XY plane.""" |
| 5 | +import math |
| 6 | + |
| 4 | 7 | from steve import Model |
| 5 | 8 | |
| 9 | + |
| 6 | 10 | designation = "SM1-20" # Catalogue number |
| 11 | +detail = "full" # full: real teeth; simple: the outline with the teeth filled in |
| 7 | 12 | |
| 8 | 13 | # number: (module, teeth, bore A, hub diameter B, outside diameter D, total length F, crown to back G, hub width H). |
| 9 | 14 | # KHK Gears catalogue 2025, Miter Gears, SM table, PDF p. 26, https://khkgears.us/media/lblpmezm/catalog-2025-miter-gears.pdf |
| | @@ -37,6 +42,41 @@ |
| 37 | 42 | with model.sketch("outline", on="XZ", name="Outline") as sk: |
| 38 | 43 | sk.polyline("profile", [(A / 2, 0), (B / 2, 0), (B / 2, H), (D / 2, G), (tip_radius, F), (A / 2, F)], closed=True) |
| 39 | 44 | model.revolve("gear", "outline", axis="Z", name="Gear") |
| 45 | +if detail == "full": |
| 46 | + pressure = math.radians(20) |
| 47 | + cone = math.radians(45) |
| 48 | + pitch_r = module * teeth / 2 |
| 49 | + equivalent = pitch_r / math.cos(cone) |
| 50 | + base = equivalent * math.cos(pressure) |
| 51 | + root_r = pitch_r - 1.25 * module * math.cos(cone) |
| 52 | + apex = G + D / 2 |
| 53 | + |
| 54 | + |
| 55 | + def involute(angle): |
| 56 | + return math.tan(angle) - angle |
| 57 | + |
| 58 | + |
| 59 | + def half_gap(r): |
| 60 | + rho = equivalent + (r - pitch_r) / math.cos(cone) |
| 61 | + angle = math.acos(base / rho) if rho > base else 0 |
| 62 | + half_tooth = (math.pi / (2 * teeth / math.cos(cone)) + involute(pressure) - involute(angle)) * rho / r |
| 63 | + return math.pi / teeth - half_tooth |
| 64 | + |
| 65 | + |
| 66 | + top_r = D / 2 |
| 67 | + radii = [root_r + (top_r - root_r) * i / 4 for i in range(5)] |
| 68 | + section = [(r, half_gap(r)) for r in radii] |
| 69 | + section.append((top_r * 1.3, half_gap(top_r))) |
| 70 | + planes = (("gap_low", H), ("gap_high", F + 0.5)) |
| 71 | + for name, z in planes: |
| 72 | + scale = (apex - z) / (apex - G) |
| 73 | + model.plane(f"{name}_plane", on="XY", offset=z, name="Gap section") |
| 74 | + points = [(r * scale * math.sin(-g), r * scale * math.cos(g)) for r, g in section] |
| 75 | + points += [(r * scale * math.sin(g), r * scale * math.cos(g)) for r, g in reversed(section)] |
| 76 | + with model.sketch(f"{name}_sketch", on=f"{name}_plane", name="Gap section") as sk: |
| 77 | + sk.polyline(f"{name}_outline", points, closed=True) |
| 78 | + model.loft("gap", ["gap_low_sketch", "gap_high_sketch"], ruled=True, op="cut", name="Tooth gap") |
| 79 | + model.circular_pattern("gaps", axis="Z", count=teeth, features=["gap"], name="Tooth gaps") |
| 40 | 80 | model.material("steel-generic", color="#b4b8bd") |
| 41 | 81 | result = model.result() |
| 42 | 82 | |