Drogheda/03-Architecture-Hardware/2026-08-08_Drogheda_Firmware-v3.1_ModoB-PHLG_Design-Brief_v1.0.md

8.1 KiB
Raw Permalink Blame History

title tags project author date status authority
Firmware v3.1 — Modo B / $PHLG en banda — Design Brief & Execution Prompt
project-drogheda
firmware
epct
modo-b
phlg
telemetria
design-brief
prompt
Project Drogheda Helgen CTO + Claude (decisión registrada 2026-08-08) 2026-08-08 Active — EL prompt para la sesión de implementación de la telemetría en banda (v3.1 núcleo EPCT) ejecuta la decisión A de `Informe-Tecnico-V3-V4` §4.7–4.8 (v1.2); hardware canónico = watchdog-electrical-design-state.md; hallazgos F1–F9 = firmware-review-v2.3-EinarBoard.md

Firmware v3.1 (núcleo EPCT) — encender la telemetría en banda

Cómo usar este doc. Es la instrucción autocontenida para convertir la decisión «A = $PHLG tal cual, en banda por Modo B, es la palabra canónica de telemetría» (Leo, 2026-08-08) en software corriendo sobre V3 (EinarBoard 1.0, vía adaptador inversor) y V4 (HBOX v4). Una sesión (humana o Claude) debe poder arrancar solo con este archivo. Reglas vigentes: hostsim en verde antes de tocar hardware; banco antes de campo; el NC de K1 es la garantía de hardware — ningún cambio puede debilitarla.

0. La decisión y su estado de partida

Hecho Estado hoy (v2.3 flota / v3.0 escrito)
Flujo NMEA al servidor Sin alterar — posición pura; K1 desenergizado (PB5 sin manejar), ENABLE_PHLG_RELAY=0
$PHLG Se construye y emite cada 30 s solo al log USB (21 campos v2.3 / 25 v3.0, checksum XOR correcto)
Camino Modo B en cobre Listo y verificado en ambas tarjetas (PA10 tap · PA9→NO · PB5→Q6→bobina · NC fail-safe)
Transparencia del módem Probada 2026-06-22: $PUBX inyectada llegó byte-idéntica al servidor
Palabra canónica DECIDIDA 2026-08-08: opción A — la misma $PHLG del log USB, sin recortar ni re-empacar (una sola palabra en USB y aire; append-only se mantiene)

Consecuencia inmediata útil: el decodificador del backend puede desarrollarse y probarse HOY contra capturas USB de banco — son los mismos bytes que llegarán por aire.

1. Fases (cada una con compuerta propia; 1 y 2 pueden correr en paralelo)

Fase Qué Compuerta de salida
1 — Servidor primero (cero riesgo, sin tocar firmware) htracker: extender PHLG_FIELDS a los 24 campos de datos v3.0; parser tolerante por longitud (20 = v2.3, 24 = v3.0+, extras = ignorar); validar checksum XOR; sentinelas −127/−1 → null; almacenar por unidad (llave cell_id) + panel/alertas (limp=1, rec subiendo, cflt=1, nmea_age>60000, tmax≥75 o celda ≥55) Decodifica al 100 % un log USB real de banco (v2.3 y v3.0)
2 — Prerrequisitos F4 (firmware, sin encender nada) SHT40 no bloqueante en dos fases + rings UART de 256 B (§3.1–3.2) hostsim verde; TLM intacta; sin delay() en el lazo
3 — Relevo Modo B en banco V3 ENABLE_PHLG_RELAY=1 + driver PB5 (§3.3–3.5) en una 1.0 de banco (adaptador inversor) Los 5 gates de banco de §4 en verde
4 — Piloto en vivo Una unidad transmitiendo; Fase 1 ya desplegada $PHLG visible en el panel; RTK fix≥4 sostenido con relevo insertado; consumo medido
5 — V4 Mismo código bajo TARGET_HBOXV4 (PA9/PA10/PB5 = nets idénticas); después v3.2 = espejo de la MISMA palabra por W5500/TCP bring-up V4 + gates §4 repetidos

2. Diseño de la inserción (política de K1)

  • Insertar solo en la transición BOOTING→RUNNING (después de «Boot complete»), una vez por sesión de energía: orden estricto RELAY.begin(115200) → digitalWrite(PB5, HIGH). El transfer del G5V-1 (~ms) puede morder una sentencia en el switchover — aceptable una vez por sesión; jamás conmutar por-sentencia.
  • Retirar en TODA salida de RUNNING — dentro de setPower(false) (cubre beginPowerCycle y SLEEP): digitalWrite(PB5, LOW) (NC restituye al instante) → RELAY.end() → pinMode(PA9, INPUT) (flotar TX, espejo del patrón PA2 — no retroalimentar el riel).
  • Fallas: cuelgue del MCU → IWDG resetea → GPIO a default → PB5 cae → el NC restituye el camino por hardware (R41 10 k garantiza Q6 apagado durante el reset). Nada que programar: documentar como la historia de seguridad y probarla (gate G4).
  • Presupuesto: bobina ~30 mA de SYS5V mientras está insertado. En respaldo queremos la telemetría viva (¡ahí viaja vbat!) — se queda insertado; 30 mA contra 12 Ah es ruido. Datos: ~95 B/30 s ≈ ~0.3 MB/mes/unidad — despreciable.

3. Cambios de código (archivo único blackpillrtkcode_v3.ino → v3.1)

  1. SHT40 en dos fases (F4): sustituir readSHT40() bloqueante por máquina de dos estados dentro de thermalService(): pasada N dispara (Wire write 0xFD, marca sht40TrigMs), pasada N+1 (≥10 ms después; THERMAL_PERIOD=2 s sobra) cosecha los 6 bytes. Cero delay() en el lazo. TMP102 queda igual (free-running, lectura corta).
  2. Rings UART de 256 B: build_opt.h en la carpeta del sketch con -DSERIAL_RX_BUFFER_SIZE=256 -DSERIAL_TX_BUFFER_SIZE=256 (vía STM32duino; equivalente --build-property en arduino-cli). Aplica a GNSS y RELAY.
  3. Driver de inserción: #define PIN_BYP_CTRL PB5; en setup() OUTPUT + LOW antes de cualquier otra cosa; helper setModoB(bool) con el orden de §2; llamada ON en la transición a RUNNING, OFF dentro de setPower(false).
  4. Flags: ENABLE_PHLG_RELAY 1 en el build EinarBoard; el pump (pumpRelay()) y la cola pendingPhlg ya existen y son correctos (reenvío byte a byte + inyección solo tras ≥8 ms de línea ociosa, solo en RUNNING) — no reescribir, solo encender.
  5. Target V4: introducir TARGET_HBOXV4 (tercer target excluyente): hereda TODO el EPCT de TARGET_EINARBOARD; difiere en medidor/RGB→PCF8574 y en no tocar PB12–15 (SPI2 del W5500). El Modo B es idéntico — cero cambios.
  6. hostsim: nuevo escenario relay: alimentar 10 min de GGA sintéticas a 1 Hz por el stub, verificar (a) salida byte-exacta salvo líneas $PHLG completas en fronteras de línea, (b) ninguna inyección con <8 ms de hueco, (c) setModoB(false) al salir de RUNNING. Correr toda la red existente (ladder/sps/rtkloss/gga/phlg/charge/gauge) sin regresión.
  7. Docs: CHANGELOG v3.1; LOGGING-SPEC §5b marcar «relay ON por default en EinarBoard»; PINOUT.md (la reescritura F7 pendiente absorbe esto).

4. Compuertas de banco (todas en una 1.0 con adaptador, antes de piloto)

  • G1 — Integridad byte-exacta: capturar simultáneo F9P TX2 y módem DIN (o segunda USB-UART en el nodo DIN) 10 min @1 Hz → diff = solo líneas $PHLG íntegras, ninguna GGA partida ni byte alterado.
  • G2 — Sin regresión RTK/VRS: con relevo insertado y caster real, la unidad alcanza y sostiene fix ≥4 (la GGA de cortesía al caster sigue siendo válida).
  • G3 — Llegada al servidor: repetir la prueba $PUBX pero con $PHLG real → Fase 1 la decodifica en el panel.
  • G4 — Fail-safe: forzar cuelgue (bucle infinito de prueba) → IWDG resetea → verificar con osciloscopio/continuidad que PB5 cae y el NC restituye ANTES del re-arranque; el flujo de posición nunca se detiene.
  • G5 — Presupuesto de lazo: con relevo activo, TLM sigue a 2 s, IWDG jamás dispara, sin rxbad creciente (los rings de 256 aguantan la ráfaga de época GNSS).

5. Riesgos / notas

  • F4 es prerrequisito duro — encender el relevo sin él corrompe el uplink GGA del caster VRS (10 ms bloqueados ≈ 115 bytes vs ring de 64). El orden de fases no es opcional.
  • El switchover de K1 muerde ~1 sentencia una vez por sesión — el backend ya tolera pérdida de época (heartbeat 1 Hz); documentado, no mitigado.
  • v2.3 en flota no cambia: unidades sin re-flashear siguen transmitiendo posición pura por el NC — el backend debe seguir aceptando flujo sin $PHLG indefinidamente.
  • La opción C (Modbus, Bloque M de V4) queda como espejo por consulta para el cliente — no sustituye la palabra canónica; su mapa de registros sigue gateado por firma del cliente.
  • No tocar: la doctrina de recuperación, el formato $PHLG (append-only), ni el NC de K1.