Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions library/mechatronics.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,67 @@ def acceleration_torque(self, *, inertia, angular_acceleration):
:returns: torque [N*m]
"""
return inertia * angular_acceleration

def calculate_inertia_ratio(self, *, j_motor, mass, pitch, teeth_motor_pulley, teeth_screw_pulley, j_screw, j_pulley_motor, j_pulley_screw):
"""
Calculates the inertia ratio of a servomotor driving a ballscrew via a timing belt.

:param j_motor: motor rotor inertia [kg*m^2]
:param mass: linear mass [kg]
:param pitch: ballscrew pitch [m/rev]
:param teeth_motor_pulley: number of teeth on the motor pulley
:param teeth_screw_pulley: number of teeth on the ballscrew pulley
:param j_screw: ballscrew inertia [kg*m^2]
:param j_pulley_motor: motor pulley inertia [kg*m^2]
:param j_pulley_screw: ballscrew pulley inertia [kg*m^2]
:returns: dictionary containing inertia ratio, total load inertia, and reduction ratio
"""
# 1. Calculate the mechanical reduction ratio of the timing belt
reduction_ratio = teeth_screw_pulley / teeth_motor_pulley

# 2. Calculate the inertia of the linear mass reflected to the ballscrew shaft
j_mass = mass * (pitch / (2 * math.pi)) ** 2

# 3. Sum the inertias on the ballscrew shaft
j_ballscrew_total = j_pulley_screw + j_screw + j_mass

# 4. Reflect the ballscrew shaft inertia through the timing belt to the motor
j_reflected_to_motor = self.reflected_inertia(
load_inertia=j_ballscrew_total, gear_ratio=reduction_ratio
)

# 5. Add the motor pulley inertia to get the total load inertia
j_load_total = j_pulley_motor + j_reflected_to_motor

# 6. Calculate the inertia ratio
inertia_ratio = j_load_total / j_motor

return {
"inertia_ratio": inertia_ratio,
"j_load_total": j_load_total,
"reduction_ratio": reduction_ratio,
}

def _calculate_acceleration_torque(self, *, j_total, j_motor, linear_acceleration, pitch, reduction_ratio):
"""
Uses linear acceleration to find the required motor acceleration torque.

:param j_total: total reflected load inertia [kg*m^2]
:param j_motor: motor rotor inertia [kg*m^2]
:param linear_acceleration: linear acceleration [m/s^2]
:param pitch: ballscrew pitch [m/rev]
:param reduction_ratio: mechanical reduction ratio
:returns: required acceleration torque [N*m]
"""
total_system_inertia = j_total + j_motor

# Convert linear acceleration to angular acceleration at the ballscrew (rad/s^2)
alpha_screw = linear_acceleration * (2 * math.pi / pitch)

# Convert angular acceleration at the ballscrew to the motor shaft
alpha_motor = alpha_screw * reduction_ratio

# Calculate Required Torque (T = J * alpha)
return self.acceleration_torque(
inertia=total_system_inertia, angular_acceleration=alpha_motor
)
45 changes: 45 additions & 0 deletions tests/test_gear_electrical_mechatronics.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,48 @@ def test_motor_power_from_torque_and_speed():
assert mechatronics.motor_power(
torque=2.0, speed_rpm=3000.0,
) == pytest.approx(expected)


def test_calculate_inertia_ratio():
"""Test inertia ratio calculation with example values."""
results = mechatronics.calculate_inertia_ratio(
j_motor=0.00005,
mass=50.0,
pitch=0.01,
teeth_motor_pulley=20,
teeth_screw_pulley=40,
j_screw=0.0001,
j_pulley_motor=0.00001,
j_pulley_screw=0.00004,
)
assert results["reduction_ratio"] == pytest.approx(2.0)
# j_mass = 50.0 * (0.01 / (2 * math.pi))**2 = 0.000126651...
# j_ballscrew_total = 0.00004 + 0.0001 + 0.000126651 = 0.000266651...
# j_reflected_to_motor = 0.000266651 / 4.0 = 0.000066662...
# j_load_total = 0.00001 + 0.000066662 = 0.000076662...
assert results["j_load_total"] == pytest.approx(0.0000766628, rel=1e-3)
# inertia_ratio = 0.000076662 / 0.00005 = 1.5332...
assert results["inertia_ratio"] == pytest.approx(1.53325, rel=1e-3)


def test__calculate_acceleration_torque():
"""Test required motor acceleration torque calculation with example values."""
# Reusing the total load inertia from the previous test result
j_load_total = 0.0000766627
j_motor = 0.00005
target_acceleration_m_s2 = 2.0
reduction_ratio = 2.0
pitch = 0.01

req_torque = mechatronics._calculate_acceleration_torque(
j_total=j_load_total,
j_motor=j_motor,
linear_acceleration=target_acceleration_m_s2,
pitch=pitch,
reduction_ratio=reduction_ratio,
)
# Total system inertia = 0.0000766627 + 0.00005 = 0.0001266627
# alpha_screw = 2.0 * (2 * math.pi / 0.01) = 1256.637...
# alpha_motor = 1256.637... * 2.0 = 2513.274...
# req_torque = 0.0001266627 * 2513.274... = 0.3183...
assert req_torque == pytest.approx(0.318338, rel=1e-3)
Loading