diff --git a/library/mechatronics.py b/library/mechatronics.py index fbb244d..a5def89 100644 --- a/library/mechatronics.py +++ b/library/mechatronics.py @@ -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 + ) diff --git a/tests/test_gear_electrical_mechatronics.py b/tests/test_gear_electrical_mechatronics.py index 8d06873..a37caf5 100644 --- a/tests/test_gear_electrical_mechatronics.py +++ b/tests/test_gear_electrical_mechatronics.py @@ -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)