auto-sync 2026-08-08 18:00

This commit is contained in:
Leopoldo Rodríguez 2026-08-08 18:00:15 -06:00
parent 811f110174
commit 6e9f6e06cf
7 changed files with 111 additions and 0 deletions

View File

@ -0,0 +1,111 @@
---
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.