Commit Graph

3 Commits

Author SHA1 Message Date
alro65 2b574b57f6 feat: Python-native ESP32 simulator + 7-TC HIL protocol (all pass)
tools/esp32_sim.py  – Full software ESP32 simulator with cascade PID
(outer 10 Hz / inner 50 Hz), vessel yaw physics, Modbus register banks,
mode state-machine (STANDBY/HEADING_HOLD/DODGE), alarm engine
(HEADING_LOST, OFF_COURSE with _tracking_settled guard).

Sim-specific parameter tuning vs. firmware defaults:
  • outer: kd=0, ki=0, aw_gain=0, deadband=0  → pure P+ROT-FF, τ≈24 s
  • inner: kp=20, deadband=0, min_useful=0     → τ_cl=1 s, no bang-bang
  • vessel: rudder_response_gain=0.004         → 30 m yacht dynamics

tools/sim_protocol.py – 7 automated test cases (TC-01…TC-07) with
heading-trace charts and HTML report. All 7 PASS:
  TC-02 settle 49.8 s, error 0.488°   (crit <60 s, <1°)
  TC-03 settle 134 s, error 0.985°    (crit <180 s, <2°)
  TC-04 settle 56.5 s, error 0.570°   (crit <90 s, <1°)
  TC-07 dodge 1.73°, return 0.527°    (crit <2°, <1°)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 04:18:01 -04:00
alro65 65860948b4 sprint-1: firmware ESP32 base -- STANDBY + Modbus + NMEA 2000 + watchdog
End-to-end implementation of Sprint 1 per docs/sprint-1-plan.md.

Builds: pio run -e esp32-dev SUCCESS, RAM 6.7%, Flash 26.5% (347 KB).
Tests: pytest 110/110 green; pio test -e native deferred (needs host
       C++ compiler -- none on this Windows machine).

Firmware (firmware/ar_autopilot_v1/):

- platformio.ini: 4 envs (esp32-dev release, esp32-debug, native unity
  tests, check static analysis). NMEA2000-library@4.22, NMEA2000_esp32@
  1.0, eModbus@1.7.4 pinned.
- main.cpp: boot in STANDBY, FreeRTOS task spawn, returns to scheduler.
- system/: ar_log.h facade, task_config.h (priorities/stacks/cores
  central table), heartbeat (1 Hz LED + uptime).
- modes/: STANDBY-only state machine; non-STANDBY rejected.
- hal/: di_do.cpp (5 DI + 10 DO with debounce + last-state cache),
  rudder_sensor.cpp (100 Hz ADC + 5-sample median filter, Core 1),
  rudder_actuator.cpp (DO1/DO2/DO3 with three safety interlocks:
  power-off, STANDBY mode, limit switch).
- safety/: TWDT @ 2 s panic-on-expire; 50 Hz safety task on Core 1
  enforcing DI1 physical disengage button, DI4 external alarm,
  both-limit-switch interlock.
- protocols/modbus_slave.cpp: eModbus RTU server on UART2 @ 38400 8N1,
  slave ID 1. 17 inputs + 19 discretes + 5 holdings + 4 coils. Reads
  pull live telemetry; writes validate range and route to handlers.
- protocols/nmea2000_consumer.cpp: stack open with CAN TX=GPIO3
  RX=GPIO1, subscribed to PGN 127250 (Heading) + PGN 127251 (Rate of
  Turn). 5 s staleness flag built in for Sprint 6 alarm wiring.
- filters/median.h: templated MedianFilter<T,N> (host testable).

Cross-cutting:

- modbus_registers.yaml: single source of truth for the Modbus register
  map. 45 entries.
- tools/gen_modbus_registers.py: YAML -> C++ header + Python module
  generator with --check for drift detection.
- arautopilot/shared/modbus_register_map.py: generated Python mirror,
  imported by Studio + tools.
- arautopilot/tests/test_modbus_register_map.py: 30 tests covering
  schema, address uniqueness, range, spot-checks, and drift detection
  (fails if YAML edited without regenerating).
- firmware/ar_autopilot_v1/tools/modbus_client_test.py: manual Modbus
  client for poking the slave from a PC with USB-RS485 dongle.
- firmware/ar_autopilot_v1/test/test_median_filter/test_median.cpp:
  8 Unity tests of the median filter (host-side, no Arduino dependency).
- docs/firmware.md: full operator + integrator guide (toolchain, build,
  flash, expected boot log, troubleshooting, Sprint 1 capability matrix).

Architecture note: opted for Arduino-on-ESP32 only instead of the
proposed dual Arduino-as-ESP-IDF-component setup. Rationale documented
in CHANGELOG and docs/firmware.md -- Arduino-on-ESP32 already provides
the FreeRTOS primitives we need; dual framework adds fragility without
benefit at Sprint 1 scope. Reconsider in Sprint 8 (OTA + secure boot).

NOT in Sprint 1 (intentional per brief sec. 12):
  - PID loops (inner/outer)
  - True Course / Track Keeping
  - Full alarm catalogue beyond DI1/DI4
  - Knob driver
  - Studio GUI / dedicated display

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 10:45:56 -04:00
alro65 700756c16f sprint-0: foundations -- data model, seed library, tests, demo
Initial commit. Delivers what the brief calls 'Sprint 0 - Foundations'
(see docs/AR_Autopilot_brief.md section 12):

- Complete repository structure (arautopilot package + firmware, display,
  installer, tools placeholders + docs).
- Core data model (Pydantic v2): modes, alarms, actuator config, PID
  config + gain scheduling, vessel config, knob state machine, project
  config with YAML/JSON serialisation.
- Seed library: 2 actuator profiles (hydraulic & electric DC reversible)
  and 2 default tunings (yacht motor planeo 30 m and 40 m). Conservative
  literature values, NOT the integrator's production tuning IP.
- Firmware skeleton: only src/hal/pinout.h with the 21 I/O contract for
  the AR-NMEA-IO v1.0 board. No drivers, no main loop.
- Studio stubs (real PySide6 app starts in Sprint 4).
- pytest suite (80 tests, all green): modes, alarms, actuator, PID
  (incl. gain interpolation and the +/-50% adaptive bound from brief
  section 6), vessel, knob state, project config, library loader,
  end-to-end roundtrip.
- examples/sprint0_demo.py - the acceptance demo from the brief.

Acceptance criteria met:
- pytest green (80/80)
- demo creates, saves (YAML + JSON), reloads, and verifies a full
  ProjectConfig using the seed library
- repository ready for tag `sprint-0-approved`

See CHANGELOG.md for the detailed scope.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 23:57:18 -04:00