sprint-0: fundaciones VMS-Sailor

Sprint 0 completo del producto VMS-Sailor (Vessel Management System
integrado para buques 30-40m). Brief de referencia en
VMS_Sailor_v2_Parte_*.md (intacto).

Core (vmssailor.core, 95.17% coverage, 99 tests verde):
- ShipCoord: sistema naval x_pp/y_cl/z_bl frozen
- Vessel, Deck, Bulkhead
- Equipment, EquipmentModel, Sensor, EquipmentSpec
- Tag, AlarmConfig, TagBinding, Scaling
- CardInstance, Bus, Topology con validacion 21 puntos I/O AR-NMEA-IO-v1.0
- Alarm, PermissiveRule, Condition
- Project agregado raiz con validacion cross-entity
- Persistencia portable .vmsproj (SQLite) con roundtrip verificable

Biblioteca curada seed (vmssailor.library):
- systems_catalog.json completo (catalogo maestro Parte 1 sec 7)
- 2 vessels: Sunseeker 76, Ferretti 850
- 2 motores: MTU 12V 2000 M96, Volvo D13-900
- 1 genset: Northern Lights M65C13
- yacht_motor_planeo.yaml (reglas heuristicas)
- TODO marcado data_source=seed_estimate - requiere validacion datasheets

Tools:
- vms-validate-library: CLI valida biblioteca completa
- vms-generate-test-project: CLI demo + verificacion roundtrip persistencia

Design System + 8 mockups HTML estaticos:
- docs/design_system.md (paleta Deep Ocean, gradientes, typography, motion)
- docs/brand/ (logo + variantes SVG)
- docs/mockups/splash, studio_main, runtime_overview,
  runtime_mimic_fuel (P&ID animado), runtime_alarms, runtime_trim (panel
  estrella con horizonte artificial), mobile_overview, mobile_trim
- docs/mockups/index.html (galeria)

Firmware (Sprint 12+ implementacion):
- firmware/ar_nmea_io_v1/src/config/pinout.h con macros GPIO

Decisiones autonomas documentadas en docs/decisions_sprint0.md.

Stack: Python 3.11 + uv + Pydantic v2 + SQLite stdlib + hatchling +
pytest 9 + ruff + mypy. Sin PySide6, FastAPI, Flutter ni firmware
funcional (entran en sprints siguientes).

Criterio de aceptacion Sprint 0: cumplido.
- uv sync: OK
- pytest: 99/99 verde
- cov vmssailor.core: 95.17% (objetivo >=80%)
- ruff: clean
- vms-validate-library: OK
- vms-generate-test-project: INTEGRIDAD OK

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-17 07:26:06 -04:00
commit deb04c9315
96 changed files with 15335 additions and 0 deletions
+27
View File
@@ -0,0 +1,27 @@
# AR-NMEA-IO-v1.0 firmware
> Hardware: tarjeta I/O distribuida diseñada por Álvaro. ESP32-DOWD + RS485 + CAN/NMEA 2000 + 21 puntos I/O.
**Sprint 0 (este commit):** sólo `src/config/pinout.h` con las macros de GPIO.
**Sprint 12:** implementación completa (Modbus RTU esclava + discovery + filtros locales).
**Sprint 13:** NMEA 2000 publishing + J1939 listening.
**Sprint 14:** OTA seguro + permissives locales + alarmas locales.
**Sprint 15:** pruebas integradas + hardening.
Detalle completo en `../../VMS_Sailor_v2_Parte_04_Hardware_Firmware.md`.
## Toolchain (cuando arranque Sprint 12)
- PlatformIO O ESP-IDF (decisión pendiente en Sprint 12)
- C/C++
- Tests: Unity + PlatformIO test runner
## Filosofía clave
**Una sola SKU. Un solo firmware base. Plug-and-produce.**
La tarjeta sale de fábrica con firmware idéntico. Su rol y configuración
(esclava N, qué hace cada puerto, filtros, permissives locales, alarmas
locales) se descargan del VMS al conectarse al bus por primera vez.
Patrón estándar industrial (Beckhoff EtherCAT, Wago I/O System).
+183
View File
@@ -0,0 +1,183 @@
/*
* AR-NMEA-IO-v1.0 — pinout.h
*
* Header de configuración de pines GPIO para la tarjeta I/O distribuida
* del producto VMS-Sailor. Hardware diseñado por Álvaro.
*
* Este header es la ÚNICA fuente de verdad para la asignación de GPIOs.
* Sprint 0 sólo define las macros — el firmware funcional viene en Sprint 12.
*
* Referencias:
* - VMS_Sailor_v2_Parte_04_Hardware_Firmware.md sec 1
* - Esquemático PCB AR-NMEA-IO-v1.0 (en archivos del proyecto)
*
* Capacidades por tarjeta (Parte 4 sec 1):
* - 10 DO (MOSFET IRLML6344TRPBF + opto PC817 + diodo flyback SS14)
* - 5 DI (opto PC817, contacto o 24VDC, R-limit 4.7kΩ)
* - 1 RPM (opto, pickup magnético / tacómetro / inductivo)
* - 4 AI (divisor + filtro V3061, ADC ESP32 12 bits + oversampling)
* - 1 RS485 (SN65HVD1781)
* - 1 CAN/NMEA 2000 (MCP2562T-E_MF)
* - 1 WiFi (integrado ESP32)
* - 1 USB (programación inicial CH340/CP2102)
*
* ATENCIÓN — restricciones del ESP32:
* - GPIO0, GPIO2, GPIO5, GPIO12, GPIO15 son boot strapping. Cuidar
* niveles al arranque para no romper boot sequence.
* - GPIO34, GPIO35, GPIO36, GPIO39 son input-only (sin pull-up/down
* internos, sin output). Usar sólo para AI / DI.
* - GPIO6-GPIO11 conectados a la SPI flash interna — NO usar.
*
* NOTA SPRINT 0: los pines exactos están sujetos a verificación contra
* el esquemático real durante Sprint 12. Si hay discrepancias, ESTE
* archivo manda; el firmware se debe ajustar a estos defines.
*/
#ifndef VMSSAILOR_AR_NMEA_IO_PINOUT_H
#define VMSSAILOR_AR_NMEA_IO_PINOUT_H
/* ===================================================================== */
/* Identidad del hardware */
/* ===================================================================== */
#define AR_NMEA_IO_HW_VERSION "1.0"
#define AR_NMEA_IO_BOARD_NAME "AR-NMEA-IO-v1.0"
#define CAP_DO_COUNT 10
#define CAP_DI_COUNT 5
#define CAP_RPM_COUNT 1
#define CAP_AI_COUNT 4
#define TOTAL_IO_POINTS (CAP_DO_COUNT + CAP_DI_COUNT + CAP_RPM_COUNT + CAP_AI_COUNT)
/* = 20 + 1 frecuencia = 21 (Parte 4 sec 1) */
/* ===================================================================== */
/* Salidas digitales (DO) — MOSFET IRLML6344 a través de opto PC817 */
/* ===================================================================== */
/* Provisional. Cuidado con boot-straps: DO1=GPIO15, DO9=GPIO5 son STRAP. */
/* Firmware debe forzar OFF (estado seguro) antes de subir WiFi/CAN. */
#define DO1_PIN 15
#define DO2_PIN 17
#define DO3_PIN 16 /* atento: Rx2 si UART2 activo */
#define DO4_PIN 18
#define DO5_PIN 19
#define DO6_PIN 22
#define DO7_PIN 25
#define DO8_PIN 26
#define DO9_PIN 27
#define DO10_PIN 5 /* boot-strap */
#define DO_ACTIVE_HIGH 1
#define DO_INITIAL_STATE 0 /* safe state on boot = off */
/* ===================================================================== */
/* Entradas digitales (DI) — opto PC817 */
/* ===================================================================== */
#define DI1_PIN 13
#define DI2_PIN 12 /* boot-strap si HIGH al boot fuerza 1.8V flash */
#define DI3_PIN 14
#define DI4_PIN 32
#define DI5_PIN 33
#define DI_DEBOUNCE_MS 25
/* ===================================================================== */
/* Entrada de frecuencia (RPM) — pickup magnético / tacómetro / inductivo */
/* ===================================================================== */
#define RPM1_PIN 4
#define RPM_MAX_FREQ_HZ 5000 /* margen amplio */
#define RPM_FILTER_DEFAULT FILTER_MOVING_AVG
/* ===================================================================== */
/* Entradas analógicas (AI) — ADC ESP32 12 bits + oversampling */
/* ===================================================================== */
/* Todos son ADC1 (ADC2 conflicta con WiFi). Input-only OK aquí. */
#define AI1_PIN 34 /* SPARE / BAT divider */
#define AI2_PIN 35 /* OIL_PRESS divider */
#define AI3_PIN 36 /* WATER_TEMP sensor */
#define AI4_PIN 39 /* SPARE2 / RTD bias */
#define AI_RESOLUTION_BITS 12
#define AI_OVERSAMPLE_FACTOR 8
#define AI_VREF_MV 3300
#define AI_FILTER_DEFAULT FILTER_MOVING_AVG
#define AI_DEFAULT_UPDATE_RATE_MS 200
/* ===================================================================== */
/* RS485 — SN65HVD1781 (Modbus RTU) */
/* ===================================================================== */
#define RS485_UART_NUM 1
#define RS485_TX_PIN 10
#define RS485_RX_PIN 9
#define RS485_DE_PIN 2 /* boot-strap, pull-down externo */
#define RS485_DEFAULT_BAUD 115200
#define RS485_DEFAULT_PARITY 'N'
#define RS485_DEFAULT_STOP_BITS 1
/* ===================================================================== */
/* CAN / NMEA 2000 — MCP2562T-E_MF */
/* ===================================================================== */
#define CAN_TX_PIN 21
#define CAN_RX_PIN 23
#define CAN_STBY_PIN 22 /* compartido con DO6 — revisar mux en schematic */
#define CAN_DEFAULT_BITRATE_HZ 250000 /* NMEA 2000 estándar */
/* ===================================================================== */
/* Dipswitches físicos para slot number (1-16) */
/* ===================================================================== */
/* 4 dipswitches binarios. Se leen UNA vez al boot, no en bucle. */
/* TODO Sprint 12: revisar contra schematic — provisional. */
#define DIPSW_BIT0_PIN 0 /* boot-strap! pull-up externo */
#define DIPSW_BIT1_PIN 3 /* RX0 — desconectar USB serial al booteo */
#define DIPSW_BIT2_PIN 1 /* TX0 — idem */
#define DIPSW_BIT3_PIN 7 /* atención: SPI flash CMD si presente */
/* ===================================================================== */
/* LED de estado (firmware health) */
/* ===================================================================== */
#define LED_STATUS_PIN 2 /* coincide con onboard LED del DevKit */
#define LED_BLINK_OK_HZ 1
#define LED_BLINK_ERROR_HZ 5
/* ===================================================================== */
/* Power monitoring (opcional) */
/* ===================================================================== */
#define VIN_MONITOR_PIN AI1_PIN
#define VIN_DIVIDER_RATIO (1.0f / 11.0f) /* 10k+1k típico */
#define VIN_NOMINAL_V 12.0f
#define VIN_LOW_THRESHOLD_V 10.5f
#define VIN_HIGH_THRESHOLD_V 15.0f
/* ===================================================================== */
/* Watchdog y timing */
/* ===================================================================== */
#define WDT_TIMEOUT_S 30
#define HEALTH_BEACON_PERIOD_S 60
#define DISCOVERY_RETRY_S 30
/* ===================================================================== */
/* Capacidades reportadas en discovery broadcast */
/* ===================================================================== */
/* Se envían al maestro Modbus en el mensaje function-code 65 */
/* (DISCOVERY_BROADCAST) al arranque (Parte 4 sec 4). */
#define DISCOVERY_FC 65
#define CONFIG_PUSH_FC 66
#define CONFIG_ACK_FC 67
#define HEALTH_BEACON_FC 68
#define OTA_BEGIN_FC 69
#define OTA_CHUNK_FC 70
#define OTA_END_FC 71
#define LOCAL_ALARM_FC 72
#define LOCAL_PERMISSIVE_FC 73
#endif /* VMSSAILOR_AR_NMEA_IO_PINOUT_H */