sl-firmware created pull request seb/saltylab-firmware#69

sl-firmware
Sun, 01 Mar 2026 00:57:22 -0500

69#feat(safety): remote e-stop over 4G MQTT (Issue #63)#

Summary

Implements remote e-stop over 4G cellular MQTT — closes Issue #63 (P0 safety-critical).

STM32 Firmware

safety.h/c: EstopSource enum (ESTOP_CLEAR/TILT/RC_KILL/REMOTE/CELLULAR_TIMEOUT); safety_remote_estop(), safety_remote_estop_clear(), safety_get_estop(), safety_remote_estop_active() — latched until explicit Z clear + robot DISARMED

usbd_cdc_if.c/h: CDC commands E (ESTOP_REMOTE), F (ESTOP_CELLULAR_TIMEOUT), Z (clear latch)

status.h/c: status_update() +remote_estop param; both LEDs fast-blink 200ms (highest priority)

main.c: Immediate motor cutoff on E/F (before RC handling); arming blocked while safety_remote_estop_active(); motor estop auto-clear gated; "es" field in JSON telemetry (0–4); status_update() updated to 5-arg signature

Safety Guarantees

Motor cutoff is IMMEDIATE (bypasses PID, latches motors.estop)

Latch persists until explicit Z + robot must be DISARMED

Cannot re-arm via MQTT alone — requires RC arm hold after clear

IWDG-safe: no blocking code in e-stop path

Jetson Bridge

remote_estop_node.py: paho-mqtt subscriber + pyserial writer; cellular watchdog fires F\n after 5s MQTT drop in AUTO mode

estop_params.yaml: mqtt_host, cellular_timeout_s, auto_estop_on_disconnect

remote_estop.launch.py + setup.py + package.xml updates

docker-compose.yml: remote-estop service, depends_on: stm32-bridge

test_remote_estop.py: kill/clear/watchdog/latency unit tests

Test Plan

STM32: Send E\n via USB CDC → verify motors stop immediately, LED fast-blinks 200ms

STM32: Send Z\n → verify estop cleared, robot re-armable via RC hold

STM32: F\n → same as E\n but telemetry shows "es":4

Telemetry: verify "es" field in JSON stream

Jetson: MQTT {"kill":true} → verify E\n reaches STM32 in <500ms

Jetson: Disconnect 4G in AUTO mode → verify watchdog fires F\n after 5s

Unit tests: pytest test/test_remote_estop.py

Fixes #63

🤖 Generated with Claude Code