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

112 lines
8.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: Firmware v3.1 — Modo B / $PHLG en banda — Design Brief & Execution Prompt
tags: [project-drogheda, firmware, epct, modo-b, phlg, telemetria, design-brief, prompt]
project: Project Drogheda
author: Helgen CTO + Claude (decisión registrada 2026-08-08)
date: 2026-08-08
status: Active — EL prompt para la sesión de implementación de la telemetría en banda (v3.1 núcleo EPCT)
authority: 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.