Source code for cubemarspycan.faults

"""Driver fault codes.

The manual defines **two incompatible fault tables** and they must never be mixed:

* :class:`CanFault` - the 0-7 code in byte 7 of a CAN feedback frame (manual v1.0.18 p.45),
  used by both MIT and servo-over-CAN.
* :class:`SerialFault` - the much longer ``mc_fault_code`` enum returned by the serial
  ``GET_VALUES`` reply (p.52), where 1 means over-voltage rather than over-temperature.

Serial is out of scope for v1; :class:`SerialFault` is defined anyway so that nobody
later reaches for :class:`CanFault` on the serial path, which is the mistake the table
layout invites.
"""

from __future__ import annotations

from enum import IntEnum


[docs] class CanFault(IntEnum): """Fault code from a CAN feedback frame (MIT and servo). Manual v1.0.18 p.45.""" NONE = 0 MOTOR_OVER_TEMPERATURE = 1 OVER_CURRENT = 2 OVER_VOLTAGE = 3 UNDER_VOLTAGE = 4 ENCODER = 5 MOSFET_OVER_TEMPERATURE = 6 MOTOR_STALL = 7
_CAN_FAULT_TEXT = { CanFault.NONE: "no fault", CanFault.MOTOR_OVER_TEMPERATURE: "motor over-temperature", CanFault.OVER_CURRENT: "over-current", CanFault.OVER_VOLTAGE: "over-voltage", CanFault.UNDER_VOLTAGE: "under-voltage", CanFault.ENCODER: "encoder fault", CanFault.MOSFET_OVER_TEMPERATURE: "MOSFET over-temperature", CanFault.MOTOR_STALL: "motor stall", }
[docs] def describe_can_fault(code: int) -> tuple[CanFault | None, str]: """Map a raw fault byte to ``(enum_or_None, human_text)``. Never raises, never throws ``KeyError``. Codes outside 0-7 are reported verbatim rather than crashing the receive path. TMotorCANControl indexes a dict directly here and dies with ``KeyError: 7`` on the motor-stall code that v1.0.18 added. """ try: fault = CanFault(code) except ValueError: return None, f"unknown fault code {code} (not defined in manual v1.0.18)" return fault, _CAN_FAULT_TEXT[fault]
[docs] class SerialFault(IntEnum): """``mc_fault_code`` from the serial GET_VALUES reply. Manual v1.0.18 p.52. NOT interchangeable with :class:`CanFault`. Reserved for v1.1. """ NONE = 0 OVER_VOLTAGE = 1 UNDER_VOLTAGE = 2 DRV = 3 ABS_OVER_CURRENT = 4 OVER_TEMP_FET = 5 OVER_TEMP_MOTOR = 6 GATE_DRIVER_OVER_VOLTAGE = 7 GATE_DRIVER_UNDER_VOLTAGE = 8 MCU_UNDER_VOLTAGE = 9 BOOTING_FROM_WATCHDOG_RESET = 10 ENCODER_SPI = 11 ENCODER_SINCOS_BELOW_MIN_AMPLITUDE = 12 ENCODER_SINCOS_ABOVE_MAX_AMPLITUDE = 13 FLASH_CORRUPTION = 14 HIGH_OFFSET_CURRENT_SENSOR_1 = 15 HIGH_OFFSET_CURRENT_SENSOR_2 = 16 HIGH_OFFSET_CURRENT_SENSOR_3 = 17 UNBALANCED_CURRENTS = 18