stirrer: decode and report Pololu SMC status errors instead of guessing
Adds StatusError flags for the STATUS register and get_status_errors(); go() now reports if a fail-safe (safe-start violation or other error) persists after GO instead of failing silently. _on_process uses the same decoding to log any active error and only auto-recovers on a safe-start violation, rather than the old narrow status & limit_status heuristic. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EU3NTwLygh8jkrnqPoHNXF
This commit is contained in:
@@ -48,6 +48,24 @@ class Varid(enum.Enum):
|
||||
MOTOR_CURRENT_LIMIT_OCCURRENCE_COUNT = 45
|
||||
|
||||
|
||||
# Bit flags of the STATUS variable (Varid.STATUS). A non-zero
|
||||
# SAFE_START_VIOLATION is the "fail-safe" state: the controller accepted
|
||||
# the GO command but still refuses to spin the motor. The other bits are
|
||||
# the SMC's other error conditions, which also stop the motor and can
|
||||
# make GO fail to bring it back.
|
||||
class StatusError(enum.IntFlag):
|
||||
SAFE_START_VIOLATION = 0x0001
|
||||
REQUIRED_CHANNEL_INVALID = 0x0002
|
||||
SERIAL_ERROR = 0x0004
|
||||
COMMAND_TIMEOUT = 0x0008
|
||||
LIMIT_KILL_SWITCH = 0x0010
|
||||
LOW_VIN = 0x0020
|
||||
HIGH_VIN = 0x0040
|
||||
OVER_TEMPERATURE = 0x0080
|
||||
MOTOR_DRIVER_ERROR = 0x0100
|
||||
ERR_LINE_HIGH = 0x0200
|
||||
|
||||
|
||||
class Pololu1376:
|
||||
def __init__(self, serial_port):
|
||||
# Deferred-open pyserial idiom: serial_port is constructed with no
|
||||
@@ -117,8 +135,15 @@ class Pololu1376:
|
||||
|
||||
return rsp[1:]
|
||||
|
||||
def get_status_errors(self):
|
||||
return StatusError(self.get_variable(Varid.STATUS))
|
||||
|
||||
def go(self):
|
||||
return self.cmd("GO")
|
||||
rsp = self.cmd("GO")
|
||||
errors = self.get_status_errors()
|
||||
if errors:
|
||||
print(f"Pololu1376: ERROR - still in fail-safe after GO, active errors: {errors!r}")
|
||||
return rsp
|
||||
|
||||
def stop(self):
|
||||
return self.cmd("X")
|
||||
|
||||
@@ -75,11 +75,11 @@ class StirrerPololu1376(AStirrer):
|
||||
if not self.connected:
|
||||
return
|
||||
try:
|
||||
status = self.drv.get_variable(Varid.STATUS)
|
||||
limit_status = self.drv.get_variable(Varid.STATUS_LIMIT_STATUS)
|
||||
if status & 0x01 == 0x01:
|
||||
if limit_status & 0x01 == 0x01:
|
||||
print("Recover after motor error!")
|
||||
errors = self.drv.get_status_errors()
|
||||
if errors:
|
||||
print(f"StirrerPololu1376: motor controller reports errors: {errors!r}")
|
||||
if StatusError.SAFE_START_VIOLATION in errors:
|
||||
print("Recover after safe start violation!")
|
||||
self.drv.go()
|
||||
except Exception as e:
|
||||
print(f"StirrerPololu1376: comm error in _on_process: {e}")
|
||||
|
||||
Reference in New Issue
Block a user