Skip to content

Commit ce41a08

Browse files
committed
updated docs page
1 parent a709a26 commit ce41a08

8 files changed

Lines changed: 366 additions & 172 deletions

File tree

‎docs/_config.yml‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
title: Tecovolt
2-
description: Un nodo inteligente que protege tu hogar antes de que llegue el apagón — Qualcomm Sustainable Power Cities · Talent Land 2025
2+
description: Un nodo inteligente que protege tu hogar antes de que llegue el apagón — Qualcomm Sustainable Power Cities · Genius Arena 2026
33
remote_theme: just-the-docs/just-the-docs@v0.10.1
44

55
url: "https://JocelynVelarde.github.io"
@@ -20,11 +20,11 @@ nav_enabled: true
2020
back_to_top: true
2121
back_to_top_text: "Subir"
2222

23-
footer_content: '<b>Slop as a Service (SAAS)</b> — Tecovolt · Qualcomm Sustainable Power Cities · Talent Land 2025<br>Bini Vázquez · Diego Pérez Rossi · Jocelyn Velarde Barrón · Armando Mac Beath'
23+
footer_content: "<b>Slop as a Service (SAAS)</b> — Tecovolt · Qualcomm Sustainable Power Cities · Genius Arena 2026<br>Bini Vázquez · Diego Pérez Rossi · Jocelyn Velarde Barrón · Armando Mac Beath"
2424

2525
callouts:
2626
warning:
27-
title: Pendiente
27+
title: Pendiente / Crítico
2828
color: yellow
2929
info:
3030
title: Nota

‎docs/blog/index.md‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
---
22
title: Blog
3-
nav_order: 11
3+
nav_order: 12
44
---
55

66
# Blog
7+
78
{: .fs-8 }
89

910
Actualizaciones y reflexiones del equipo durante el desarrollo de Tecovolt.
@@ -12,6 +13,7 @@ Actualizaciones y reflexiones del equipo durante el desarrollo de Tecovolt.
1213
---
1314

1415
## Por qué construimos Tecovolt
16+
1517
**Abril 2025**
1618

1719
Cuando CENACE declaró en alerta al Sistema Eléctrico Nacional por tercer día consecutivo en mayo de 2024, no fue una noticia abstracta para nosotros. Fue el momento en que el taller de la familia dejó de funcionar, cuando el refrigerador del negocio de la esquina perdió toda su mercancía, cuando los equipos médicos domiciliarios se apagaron sin aviso.
@@ -27,6 +29,7 @@ Sense Energy y Emporia Vue son productos excelentes para el mercado norteamerica
2729
### La apuesta técnica
2830

2931
Decidimos construir un sistema que:
32+
3033
1. **Opera sin internet** — toda la inferencia on-device
3134
2. **Actúa físicamente** — relay que protege antes del colapso
3235
3. **Aprende continuamente** — OTA updates vía Foundries.io
@@ -38,4 +41,4 @@ Estamos en Talent Land construyendo el prototipo funcional. Cada dato que captur
3841

3942
---
4043

41-
*Más actualizaciones próximamente...*
44+
_Más actualizaciones próximamente..._

‎docs/demo/index.md‎

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
---
2+
title: Estrategia de Demo
3+
nav_order: 8
4+
has_children: false
5+
---
6+
7+
# Estrategia de Demo
8+
9+
{: .fs-8 }
10+
11+
PicoScope como validador independiente, script AWG automatizado y argumentos técnicos para el jurado.
12+
{: .fs-5 .fw-300 }
13+
14+
---
15+
16+
## Filosofía del demo
17+
18+
El PicoScope 2208B MSO **no es un display redundante** — actúa como **validador independiente.** Muestra la waveform física en tiempo real mientras Tecovolt clasifica y actúa el relay. Dos sistemas independientes mostrando el mismo fenómeno fortalece la credibilidad de las detecciones ante el jurado.
19+
20+
---
21+
22+
## Secuencia AWG automatizada (~60 segundos)
23+
24+
El script `tecovolt_demo_awg.py` automatiza el AWG del PicoScope para reproducir la secuencia de fenómenos que activa el relay:
25+
26+
| Fase | Config AWG | Duración |
27+
| :----------------- | :--------------- | :---------------------------------- |
28+
| **normal** | 1500 mV, 60.0 Hz | 8 s — baseline |
29+
| **sag_leve × 3** | 1000 mV, 59.8 Hz | 3 s cada uno — patrón acumulándose |
30+
| **sag_severo × 2** | 600 mV, 59.5 Hz | 4 s cada uno — **RELAY ACTÚA aquí** |
31+
| **outage** | 0 mV | 6 s — relay ya protegió el circuito |
32+
| **normal** | 1500 mV, 60.0 Hz | 5 s — recuperación |
33+
34+
{: .note }
35+
36+
> La escala del AWG (1500 mV) corresponde a la señal de referencia que el ZMPT procesa para generar ~0.115 V RMS en el ADC del Arduino — equivalente a la red normal de 127V en México.
37+
38+
El relay actúa en `sag_severo` porque el MPU acumula ≥2 detecciones de esa clase en su historial de 10 ventanas — no en la primera detección aislada.
39+
40+
---
41+
42+
## Argumento contra overfitting
43+
44+
El modelo final tiene **99.3% accuracy en validation set con AUC=1.00.**
45+
46+
Puntos de defensa ante el jurado:
47+
48+
**1. La curva de entrenamiento no diverge.** Train y validation convergen juntas — evidencia de generalización correcta, no de memorización.
49+
50+
**2. Los fenómenos físicos tienen diferencias matemáticas reales y medibles:**
51+
52+
| Clase | RMS medido | Diferencia vs normal |
53+
| :--------- | :--------- | :---------------------------------- |
54+
| normal | 0.1175 V | — |
55+
| outage | 0.0007 V | **164x menor** |
56+
| sag_severo | ~0.04 V | ~3x menor |
57+
| flicker | ~0.1175 V | ~idéntico en RMS — separado por THD |
58+
59+
**3. El modelo aprendió física, no ruido.** Una diferencia de 164x entre outage y normal no es un artefacto del dataset — es voltaje presente vs voltaje ausente.
60+
61+
**4. THD separa lo que RMS no puede.** `flicker` y `normal` tienen el mismo RMS. El modelo los distingue por distorsión armónica (THD 10–20x mayor en flicker) — una propiedad física real de la modulación de amplitud.
62+
63+
---
64+
65+
## Diferenciadores técnicos para el pitch
66+
67+
| # | Diferenciador | Argumento |
68+
| :-- | :-------------------------------------- | :------------------------------------------------------------------------------------------------------ |
69+
| 1 | Tres modelos simultáneos en un solo MCU | Gestión de memoria embebida en 786 KB RAM con inferencia en paralelo |
70+
| 2 | INT8 via Qualcomm AI Hub | ~200 KB → ~50 KB por modelo. Diferencia entre 12h y 72h de batería |
71+
| 3 | Separación MCU/MPU deliberada | Inferencia < 1ms en MCU, lógica compuesta y comunicación en MPU |
72+
| 4 | Relay físico | Cierra el loop de protección — no es un dashboard, es una respuesta autónoma |
73+
| 5 | OTA via Foundries.io | Modelos actualizables en campo sin tocar el hardware |
74+
| 6 | DSP block custom con THD | Feature que detecta flicker por distorsión armónica, no amplitud — imposible con bloques estándar de EI |

‎docs/edge-ai/index.md‎

Lines changed: 96 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ nav_order: 5
44
---
55

66
# Edge AI & Modelos
7+
78
{: .fs-8 }
89

910
Pipeline de datos, entrenamiento de modelos, custom DSP blocks y cuantización INT8 para inferencia on-device.
@@ -19,88 +20,129 @@ El resultado es un modelo que vive dentro del Arduino, aprende el comportamiento
1920

2021
---
2122

22-
## Modelo A · Anomalía de voltaje
23-
24-
| Parámetro | Valor |
25-
|:----------|:------|
26-
| **Tipo** | Clasificador de 6 clases |
27-
| **Bloque DSP** | Custom `tecovolt_block` (5 features físicas) |
28-
| **Frecuencia** | 1000 Hz |
29-
| **Ventana** | 200 ms, stride 200 ms (sin overlap) |
30-
| **Clases** | `normal`, `sag_leve`, `sag_severo`, `swell`, `outage`, `flicker` |
23+
## Modelo A · Anomalía de voltaje (TecovoltClassifier)
24+
25+
| Parámetro | Valor |
26+
| :------------------ | :--------------------------------------------------------------- |
27+
| **Proyecto EI** | tecovolt-voltage |
28+
| **Tipo** | Clasificador de 6 clases |
29+
| **Bloque DSP** | Custom `tecovolt_block` — 6 features físicas vía Python/ngrok |
30+
| **Frecuencia** | 1000 Hz |
31+
| **Ventana** | 200 ms (200 samples), stride 200 ms |
32+
| **Arquitectura NN** | Dense 16 → Dense 8 → Softmax 6 clases |
33+
| **Training cycles** | 100, lr=0.001 |
34+
| **Accuracy final** | **99.3% validation, AUC=1.00** |
35+
| **Clases** | `normal`, `sag_leve`, `sag_severo`, `swell`, `outage`, `flicker` |
36+
37+
### Features extraídas (6)
38+
39+
| Feature | Descripción |
40+
| :------------------- | :--------------------------------------------------------------------------- |
41+
| **rms_v** | Voltaje RMS de la ventana — feature más discriminante para outage vs normal |
42+
| **peak_to_peak_v** | Diferencia máximo–mínimo de la ventana |
43+
| **crest_factor** | Peak / RMS — detecta distorsión de forma de onda |
44+
| **rms_ripple_v** | Desviación estándar del RMS por ciclo — detecta inestabilidad |
45+
| **dominant_freq_hz** | Frecuencia dominante vía FFT — detecta deriva de frecuencia |
46+
| **thd** | Total Harmonic Distortion — feature clave para separar `flicker` de `normal` |
3147

32-
### Features extraídas
48+
{: .note }
3349

34-
- **RMS (mV):** Voltaje eficaz de la ventana
35-
- **Peak-to-peak (mV):** Rango máximo de la señal
36-
- **Crest factor:** Relación pico/RMS — indicador de distorsión
37-
- **RMS ripple (mV):** Variabilidad del RMS — detecta flicker
38-
- **Frecuencia dominante (Hz):** Componente frecuencial principal
50+
> **¿Por qué THD?** `flicker` y `normal` tienen RMS casi idéntico (~0.1175V). El flicker genera modulación de amplitud que produce armónicos de 2° y 3° grado. En el dataset final: normal THD=0.005–0.015, flicker THD=0.15–0.30 — una diferencia de 10–20x. Sin esta feature el modelo confunde las dos clases.
3951
40-
### Dataset
52+
{: .warning }
4153

42-
Datos sintéticos generados con `tecovolt_synth.py`, calibrados con **PicoScope 2208B** usando señales reales de la red eléctrica de Puebla, MX. El AWG del PicoScope permite crear condiciones controladas de cada clase.
54+
> **Crítico — no normalizar.** El RMS absoluto es la feature más discriminante. Normalizado, outage (0.0018 V) y normal (0.1175 V) se acercan y el modelo pierde su clase más fácil. outage vs normal es una diferencia de 164x — el modelo aprende física, no ruido.
4355
44-
### Resultados de entrenamiento
56+
### Historia de iteraciones
4557

46-
| Iteración | Accuracy (float32) | Notas |
47-
|:----------|:-------------------|:------|
48-
| 1er entrenamiento | 92.6% | Confusión: `sag_leve` ↔ `normal` en bordes de RMS |
49-
| **2do entrenamiento** | **94.5%** | +100 ciclos, Flatten layer, dataset ampliado en clases con traslape |
58+
| Versión | Accuracy | Notas |
59+
| :------ | :-------- | :-------------------------------------------------------------------------- |
60+
| v1 | 94.5% | Dataset sintético puro, 5 features |
61+
| v2 | 63.7% | Dataset mixto (real + sintético). Confusión: `normal` ↔ `sag_leve` |
62+
| v3 | 63% | THD como 6ta feature, arquitectura 20→10, auto-weight. Collapse a `flicker` |
63+
| **v4** | **99.3%** | Fix bug `fs` hardcodeado + separación agresiva en synth |
5064

5165
{: .warning }
52-
> **Pendiente:** Reentrenamiento con datos reales capturados del ACS712 y ZMPT101B en el Arduino Uno Q.
53-
54-
---
5566

56-
## Modelo B · Riesgo térmico
67+
> **Bug crítico resuelto (v2→v4):** el DSP block tenía `fs=6279.8` hardcodeado (sample rate del PicoScope) pero el dataset v2/v3 fue generado a 1000 Hz. Esto rompía el cálculo de RMS ripple y THD completamente. Fix: `fs = 1000.0` hardcodeado, alineado con el parámetro de Edge Impulse.
5768
58-
| Parámetro | Valor |
59-
|:----------|:------|
60-
| **Tipo** | Clasificador de 3 clases |
61-
| **Bloque DSP** | Flatten (temperatura cambia lento — sin análisis frecuencial) |
62-
| **Frecuencia** | 1 Hz (BMP280) |
63-
| **Ventana** | 10 muestras = 10 s |
64-
| **Clases** | `bajo` (20–45 °C), `medio` (45–65 °C), `alto` (65–90 °C + baja humedad) |
69+
### Dataset
6570

66-
**Features:** `avg_temperature` y `avg_humidity` por ventana de 10 muestras.
71+
Dataset mixto real + sintético. Datos reales capturados con PicoScope 2208B MSO del ZMPT101B a 6279.8 Hz (submuestreado a 1000 Hz para el modelo). Augmentation ×50 por captura real usando el perfil de ruido real medido (std diff-to-diff). Dataset final: **1440 train / 360 test, 6 clases balanceadas.**
6772

68-
**Dataset:** Datos sintéticos (`tecovolt_temp_synth.py`). 150 ventanas × 3 clases = 450 total, split 80/20.
73+
Para `outage` no se amplifica la señal — solo ruido mínimo, ya que la señal es ~0 V y amplificar introduciría artefactos.
6974

7075
---
7176

72-
## Modelo C · Predicción de demanda
77+
## Modelo B · Demanda energética (DemandClassification)
78+
79+
| Parámetro | Valor |
80+
| :------------------ | :---------------------------------------------------- |
81+
| **Proyecto EI** | tecovolt-demand |
82+
| **Tipo** | Clasificador de 3 clases |
83+
| **Bloque DSP** | Flatten — Average, RMS, Std deviation (normalizado) |
84+
| **Frecuencia** | ~2 Hz (lecturas rawRMS del ACS712) |
85+
| **Ventana** | 10 muestras = 5 s |
86+
| **Arquitectura NN** | Dense 8 → Softmax 3 clases |
87+
| **Training cycles** | 100, lr=0.0005 |
88+
| **Clases** | `baja` (rawRMS <8), `media` (~42.81), `alta` (~87.60) |
89+
90+
{: .note }
7391

74-
| Parámetro | Valor |
75-
|:----------|:------|
76-
| **Tipo** | Clasificador de 3 clases |
77-
| **Bloque DSP** | Flatten |
78-
| **Frecuencia** | ~1.67 Hz (thread Zephyr: 1000 muestras ADC a 10 kHz + 500 ms sleep) |
79-
| **Ventana** | 10 lecturas de rawRMS |
80-
| **Clases** | `baja` (rawRMS < 3.0), `media` (3.0–120), `alta` (rawRMS ≥ 120) |
92+
> A diferencia del modelo de voltaje, el modelo de demanda **sí requiere normalización.** Las 3 features (avg, rms, std) están en la misma escala y el modelo necesita aprender proporciones, no valores absolutos.
8193
82-
### Dataset base
94+
### Valores reales medidos (ACS712-30A, dos calentadores ~1900 W)
8395

84-
| Clase | Fuente | rawRMS |
85-
|:------|:-------|:-------|
86-
| Baja | Datos reales PicoScope | ≈ 0.0 (sin carga) |
87-
| Alta | Datos reales PicoScope | ≈ 169.5 (dos calentadores ~1900 W) |
88-
| Media | Estimado (pendiente) | Captura real pendiente con ~950 W |
96+
| Clase | rawRMS | Carga real |
97+
| :------ | :----------- | :------------------------- |
98+
| `baja` | 0.00 | Sin carga |
99+
| `media` | 42.81 ± 0.21 | Un calentador (~950 W) |
100+
| `alta` | 87.60 ± 0.23 | Dos calentadores (~1900 W) |
89101

90-
**1er entrenamiento:** Accuracy = 87.5%. Confusión: `media` vs. `alta` (clase media usa rawRMS estimado, no real).
102+
**Dataset final:** 638 train (600 sintéticos anclados a valores reales + 38 reales). Transitorios de arranque descartados (fronteras entre clases).
91103

92104
{: .note }
93-
> **En curso:** Captura real de clase 'media' con ACS712 y carga de ~950 W para mejorar el modelo.
105+
106+
> **Insight de diseño:** la corriente (ACS712) **no** debe mezclarse como feature en el modelo de voltaje. Un sag con calentador encendido se ve diferente a un sag sin calentador — la corriente depende de las cargas del usuario, no de la calidad de la red.
107+
108+
---
109+
110+
## Modelo C · Riesgo térmico
111+
112+
| Parámetro | Valor |
113+
| :------------- | :---------------------------------------------------------------------- |
114+
| **Tipo** | Clasificador de 3 clases |
115+
| **Bloque DSP** | Flatten (temperatura cambia lento — sin análisis frecuencial) |
116+
| **Frecuencia** | 1 Hz (BMP280) |
117+
| **Ventana** | 10 muestras = 10 s |
118+
| **Clases** | `bajo` (20–45 °C), `medio` (45–65 °C), `alto` (65–90 °C + baja humedad) |
119+
120+
Desarrollado por Jocelyn Velarde. Usa datos de temperatura/humedad del BMP280. Separado correctamente en proyecto EI propio porque tiene bloque de procesamiento distinto (Flatten, no DSP custom).
94121

95122
---
96123

97124
## Custom DSP Blocks
98125

99-
A diferencia del flujo estándar de Edge Impulse, Tecovolt implementa **bloques DSP custom** desplegados vía Docker:
126+
A diferencia del flujo estándar de Edge Impulse, Tecovolt implementa **bloques DSP custom** desplegados vía Docker y expuestos al servidor de EI vía ngrok:
127+
128+
**`tecovolt_block` (Voltaje)** — Extrae las 6 features físicas del modelo de voltaje, incluyendo THD. Implementado en Python (`dsp.py`), servido vía HTTP (`dsp-server.py`). Fix aplicado: parámetros JSON con guiones (`scale-axes`) se convierten a underscores antes de pasar como kwargs de Python.
129+
130+
**`tecotemp_block` (Temperatura)** — Procesa ventanas de temperatura/humedad del BMP280 con Flatten block.
100131

101-
**`tecovolt_block` (Voltaje)** — Extrae las 5 features físicas relevantes para clasificación de anomalías de voltaje. Implementado en Python, empaquetado en Docker y registrado en Edge Impulse Studio como bloque personalizado.
132+
---
133+
134+
## Lógica de predicción compuesta (MPU)
135+
136+
El relay no actúa en una sola detección. El MPU acumula un historial de las últimas 10 clasificaciones del MCU y evalúa patrones:
137+
138+
```python
139+
history = deque(maxlen=10)
140+
141+
if history.count('sag_leve') >= 3: → alerta_amarilla (WhatsApp)
142+
if history.count('sag_severo') >= 2: → alerta_roja → relay_off
143+
```
102144

103-
**`tecotemp_block` (Temperatura)** — Procesa las ventanas de temperatura y humedad del BMP280 con un Flatten block optimizado para señales de baja frecuencia.
145+
Esta lógica es lo que diferencia Tecovolt de un monitor pasivo: actúa de forma **predictiva** antes del colapso total, desconectando cargas no críticas para proteger el transformador local.
104146

105147
---
106148

0 commit comments

Comments
 (0)