Wahl’s curvature factor for helical springs (1929)#

The wire of a helical spring is a bar in torsion, twisted by the torque \(FD/2\), so the nominal shear stress is \(8FD/\pi d^3\) and the rate \(k = Gd^4/8D^3N\) (spring_rate()). Springs broke in fatigue at loads this predicted to be safe. Arthur Wahl, at Westinghouse, analysed the wire as a curved bar: on the inside of the coil the fibres are shorter, so the same twist strains them more, and the direct shear of the load adds on that side too. His factor \(K_W = (4C - 1)/(4C - 4) + 0.615/C\) (wahl_factor()), with \(C = D/d\), multiplies the nominal stress (spring_shear_stress()). The 1929 paper is cited from Wahl’s Mechanical Springs (1944) and Shigley.

import matplotlib.pyplot as plt
import numpy as np

from engineeringkit.mechanical_engineering import bergstrasser_factor, spring_index, spring_rate, spring_shear_stress, wahl_factor

Rate from the strain energy of the wire#

\(U = T^2 L/2GJ\) with \(T = FD/2\), \(L = \pi DN\) and \(J = \pi d^4/32\); Castigliano’s theorem gives the deflection \(\partial U/\partial F\).

d, D, N, G, F = 0.003, 0.024, 10, 79.3e9, 60.0
J, length = np.pi * d**4 / 32, np.pi * D * N
energy = lambda load: (load * D / 2) ** 2 * length / (2 * G * J)  # noqa: E731
deflection = (energy(F + 1e-3) - energy(F - 1e-3)) / 2e-3
print(f"k = {spring_rate(d, D, N, G):.1f} N/m; F / deflection = {F / deflection:.1f} N/m")
assert np.isclose(F / deflection, spring_rate(d, D, N, G))
k = 5808.1 N/m; F / deflection = 5808.1 N/m

The curvature correction#

Wahl’s factor exceeds the direct-shear factor \(1 + 0.5/C\) by the curvature effect; Bergsträsser’s simpler factor follows it within 2%.

C = spring_index(D, d)
for correction in ("none", "direct", "wahl", "bergstrasser"):
    print(f"{correction:>12}: {spring_shear_stress(F, D, d, correction) / 1e6:.1f} MPa")
c = np.linspace(3, 16, 300)
curvature = wahl_factor(c) / (1 + 0.5 / c)
assert np.all(curvature > 1) and np.all(np.diff(curvature) < 0)
assert np.allclose(bergstrasser_factor(c), wahl_factor(c), rtol=0.02)
print(f"at C = {C:.0f} curvature alone raises the stress by {100 * (wahl_factor(C) / (1 + 0.5 / C) - 1):.1f}%")

fig, ax = plt.subplots()
ax.plot(c, wahl_factor(c), label="Wahl")
ax.plot(c, bergstrasser_factor(c), "--", label="Bergsträsser")
ax.plot(c, 1 + 0.5 / c, ":", label="direct shear only")
ax.set(xlabel="spring index C = D/d", ylabel="stress factor K")
ax.legend()

plt.show()
plot 06 wahl spring factor
        none: 135.8 MPa
      direct: 144.3 MPa
        wahl: 160.8 MPa
bergstrasser: 159.2 MPa
at C = 8 curvature alone raises the stress by 11.4%

Total running time of the script: (0 minutes 0.069 seconds)

Gallery generated by Sphinx-Gallery