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/main.py
"""MicroPython safety supervisor for the iSV57T-090 controller.
This is a fail-closed safety supervisor, not a motion-command implementation.
GPIO12 drives only the board's low-current external relay-coil output; the
relay's suitably rated contacts must interrupt the motor's separate DC supply.
"""
from machine import ADC, I2C, Pin, WDT
import time
from thermal_guard import ThermalGuard, remote_ntc_temperature_c, tmp117_temperature_c
# Set every motion/safety output inactive before enabling the sensor bus.
pulse = Pin(2, Pin.OUT, value=0)
direction = Pin(3, Pin.OUT, value=0)
safe_relay = Pin(12, Pin.OUT, value=0)
status_led = Pin(25, Pin.OUT, value=1) # Solid=fault/off, blink=armed.
estop = Pin(4, Pin.IN) # NC switch to GND; high/open is a fault.
motor_alarm = Pin(5, Pin.IN) # iSV57T: low=normal, high/open=fault.
remote_ntc = ADC(26) # ADC0, never a digital-only GPIO.
i2c = I2C(0, sda=Pin(8), scl=Pin(9), freq=100000)
guard = ThermalGuard()
watchdog = WDT(timeout=2000)
last_fault = None
heartbeat = 0
def read_board_temperature_c():
sample = i2c.readfrom_mem(0x48, 0x00, 2)
return tmp117_temperature_c(sample[0], sample[1])
while True:
try:
board_c = read_board_temperature_c()
remote_c = remote_ntc_temperature_c(remote_ntc.read_u16())
allow_power = guard.update(
board_c,
remote_c,
estop_closed=(estop.value() == 0),
alarm_ok=(motor_alarm.value() == 0),
)
except Exception as exc:
allow_power = guard.trip("temperature_read_error")
print("SAFETY SENSOR ERROR:", exc)
# The motor alarm cannot be valid until its supply contactor closes.
# ThermalGuard allows a bounded alarm-startup window, but motion must
# remain disabled until guard.ready is true. This file generates no motion.
# Removing power or rebooting releases the relay by base pull-down.
if not allow_power:
safe_relay.value(0)
pulse.value(0)
status_led.value(1)
else:
safe_relay.value(1)
if not guard.ready:
pulse.value(0)
status_led.value(1)
if guard.fault != last_fault:
last_fault = guard.fault
if last_fault is not None:
print("LATCHED SAFETY FAULT:", last_fault)
heartbeat += 1
if allow_power and guard.ready and heartbeat >= 10:
heartbeat = 0
status_led.value(1 - status_led.value())
watchdog.feed()
time.sleep_ms(50)