abse/isv57t090-motion-controller

A 36 V-powered RP2040 motion-controller PCB that regulates 5 V, drives isolated STEP/DIR servo inputs, monitors alarms, temperature, limits and E-stop signals, and provides protected safety/field connectors.

Version
0.0.67
License
unset
Stars
0

examples/ISV57T090MotionController/firmware/test_thermal_guard.py

import unittest

from thermal_guard import ThermalGuard, remote_ntc_temperature_c, tmp117_temperature_c


class ThermalGuardTests(unittest.TestCase):
    def test_tmp117_signed_format(self):
        self.assertEqual(tmp117_temperature_c(0x19, 0x00), 50.0)
        self.assertEqual(tmp117_temperature_c(0xF6, 0x00), -20.0)

    def test_ntc_at_25_degrees(self):
        self.assertAlmostEqual(remote_ntc_temperature_c(32768), 25.0, delta=0.1)

    def test_open_and_short_ntc_trip(self):
        self.assertIsNone(remote_ntc_temperature_c(0))
        self.assertIsNone(remote_ntc_temperature_c(65535))
        self.assertIsNone(remote_ntc_temperature_c(999))

    def test_delayed_arm_then_latched_overheat(self):
        guard = ThermalGuard(startup_samples=3)
        self.assertFalse(guard.update(30, 30, True, False))
        self.assertFalse(guard.update(30, 30, True, False))
        self.assertTrue(guard.update(30, 30, True, False))
        self.assertFalse(guard.ready)
        self.assertTrue(guard.update(30, 30, True, True))
        self.assertTrue(guard.ready)
        self.assertFalse(guard.update(30, 65, True, True))
        self.assertEqual(guard.fault, "motor_overheat")
        self.assertFalse(guard.update(30, 25, True, True))

    def test_missing_sensor_and_open_estop_trip(self):
        self.assertEqual(
            ThermalGuard().update(30, None, True, True), False
        )
        guard = ThermalGuard()
        self.assertFalse(guard.update(30, 30, False, True))
        self.assertEqual(guard.fault, "estop_open")

    def test_motor_alarm_trip(self):
        guard = ThermalGuard(startup_samples=1)
        self.assertTrue(guard.update(30, 30, True, True))
        self.assertFalse(guard.update(30, 30, True, False))
        self.assertEqual(guard.fault, "motor_alarm")

    def test_board_overheat_and_sensor_io_failure(self):
        guard = ThermalGuard(startup_samples=1)
        self.assertFalse(guard.update(75, 30, True, False))
        self.assertEqual(guard.fault, "board_overheat")
        self.assertFalse(guard.update(30, 30, True, True))
        guard = ThermalGuard()
        self.assertFalse(guard.trip("temperature_read_error"))
        self.assertFalse(guard.update(30, 30, True, True))

    def test_unpowered_motor_alarm_gets_bounded_startup_window(self):
        guard = ThermalGuard(startup_samples=1, alarm_startup_samples=2)
        self.assertTrue(guard.update(30, 30, True, False))
        self.assertTrue(guard.update(30, 30, True, False))
        self.assertFalse(guard.update(30, 30, True, False))
        self.assertEqual(guard.fault, "motor_alarm_startup_timeout")


if __name__ == "__main__":
    unittest.main()