01 · El punto de partida
El proyecto y sus requisitos
El producto es un registrador de temperatura que viaja dentro de un contenedor refrigerado. Mide la temperatura, guarda un historial, avisa por radio si se sale de rango y se actualiza por el aire. Los requisitos son los del tema 48, en una versión resumida y con identificador:
| Id | Requisito | Verificación |
|---|---|---|
| R-1 | El registrador debe funcionar al menos 2 años con 2 pilas AA de 1875 mAh (objetivo de diseño: 3 años, margen de 1,5). | Análisis con el consumo medido de cada modo (tema 36) |
| R-2 | Cuando la temperatura supere 8 °C, el registrador debe transmitir una alarma en menos de 5 s. | Prueba en el banco con una rampa de temperatura (tema 47) |
| R-3 | El registrador debe reportar su estado al menos cada 15 minutos. | Prueba en simulación y en el banco |
| R-4 | Si el programa se cuelga, el registrador debe recuperarse sin intervención y no pasar más de 300 s sin medir. | Prueba con cuelgue provocado desde el modo de prueba |
| R-5 | Si el sensor no responde, el registrador debe informarlo en menos de 120 s. | Inyección de falla del sensor |
| R-6 | El registrador debe poder actualizarse por radio sin quedar inutilizable aunque se corte la energía en cualquier instante. | Corte de energía en cada paso de la actualización (tema 47) |
| R-7 | El registrador debe guardar 30 días de medidas, sobreviviendo a cortes de energía. | Prueba del registro circular con cortes (tema 41) |
El registrador tiene cuatro modos de operación (tema 48): activo (mide cada 60 s y reporta cada 15 min), alarma (mide cada 2 s y reporta cada minuto), falla (el sensor no responde) y los modos de almacenado y de descarga (antes de la activación y al llegar), que dejamos fuera de la simulación para centrarnos en el viaje. Las hipótesis de energía son las del tema 48: sueño de 2,0 µA, 3 mA durante 20 ms para medir, 4 mA durante 5 ms para calcular y 28 mA durante 400 ms para cada reporte de radio, sobre dos pilas de 1875 mAh con el 80 % utilizable y 5,70 µA de autodescarga.
02 · Todo junto
La arquitectura integrada
La arquitectura que sale de los temas 48 y 49 es dirigida por eventos: casi todo el tiempo el microcontrolador duerme; lo despiertan el reloj de tiempo real (para medir y reportar), la radio (al terminar de enviar o al recibir) y el botón. Cada fuente solo deposita un evento en una cola; un único bucle de aplicación los procesa de a uno, y cuando no queda ninguno, vuelve a dormir.
Dos propiedades de este diseño importan para todo lo que sigue. Primera: la lógica del producto corre en un solo contexto (el bucle de aplicación), así que casi no hay condiciones de carrera sobre sus datos (tema 46); las interrupciones solo encolan. Segunda: el reposo es el estado por defecto y todo consumo extra se debe a eventos reales, sin un tick periódico (tema 49). El presupuesto de memoria (73 KB de flash y 10 KB de RAM con margen) y la elección del microcontrolador de 128 KB con la imagen de respaldo en la flash externa también vienen de aquel tema.
03 · El código
El esqueleto del firmware
El punto de entrada es corto a propósito: inicializa en un orden que importa, y entra en el bucle de eventos. Todo lo demás está en los módulos del tema 49.
/* main.c: inicialización y bucle de eventos del registrador */
int main(void) {
hal_iniciar(); /* relojes, pines, RTC (capa 0) */
causa_reinicio_registrar(); /* ¿arranque normal, watchdog, caída de tensión? (tema 37) */
wdt_iniciar(WDT_PLAZO_S); /* el watchdog se arma temprano, con un plazo de 120 s */
registro_iniciar(); /* recupera el registro circular tras un corte (tema 41) */
sensor_iniciar();
radio_iniciar();
arranque_confirmar_si_corresponde(); /* si es la primera vez de una versión nueva, la confirma (sección 7) */
app_iniciar(); /* estado inicial y primera medida */
for (;;) {
Evento e;
if (evento_tomar(&e)) { app_procesar(&e); }
else { energia_dormir(); } /* sin eventos: reposo profundo hasta la próxima interrupción (tema 35) */
}
}
/* app.c: la máquina de estados reacciona a los eventos; las interrupciones solo los publicaron */
void app_procesar(const Evento *e) {
switch (e->tipo) {
case EV_MEDIDA: app_medir(); break; /* el RTC despierta cada 60 s (cada 2 s en la zona de alerta) */
case EV_REPORTE: app_reportar_periodico(); break; /* cada 15 min (cada minuto en alarma) */
case EV_RADIO_FIN: radio_apagar(); break;
case EV_BOTON: app_atender_boton(); break;
case EV_ACTUALIZACION: arranque_proceso_fragmento(e->dato); break;
default: contador_eventos_desconocidos++; break; /* un evento imposible se cuenta, no se ignora (tema 39) */
}
}
Algunas decisiones que el esqueleto hace visibles. El watchdog se arma antes que lo demás, para que cubra también las inicializaciones lentas. La causa del reinicio se registra apenas arranca, antes de que se pierda. El caso default del switch cuenta los eventos que no esperaba en lugar de descartarlos en silencio. Y el bucle principal no tiene esperas activas: o procesa un evento o duerme, que es lo que permite los 2,0 µA de reposo.
04 · El corazón del producto
Sensores, estados y lógica de alarma
La medida cruda del sensor pasa por tres pasos antes de convertirse en una decisión: validar (¿respondió?, ¿está en rango físicamente posible?), convertir a unidades con signo y resolución fija (centésimas de grado, en un entero de 16 bits) y evaluar contra el límite. La evaluación implementa dos ideas del tema 48: la histéresis (la alarma se activa por encima de 8,00 °C y se desactiva recién por debajo de 7,50 °C, para no parpadear en el límite) y la zona de alerta (cuando la temperatura se acerca al límite, se mide cada 2 s en lugar de cada 60 s).
#define LIM_ALTO_C 800 /* 8,00 °C en centésimas de grado */
#define HIST_C 50 /* se desactiva por debajo de 7,50 °C */
#define ZONA_C 300 /* 3,00 °C = pendiente máxima (0,05 °C/s) x 60 s entre medidas lentas */
#define MED_LENTA_S 60u
#define MED_RAPIDA_S 2u
#define REP_NORMAL_S 900u
#define REP_ALARMA_S 60u
static bool alarma;
static uint8_t fallas_seguidas;
void app_medir(void) {
int16_t t; /* centésimas de grado */
if (!sensor_leer(&t)) { /* el sensor no respondió o dio un valor imposible */
if (++fallas_seguidas == 1u) { radio_enviar_falla(); } /* se informa en la primera falla (R-5) */
energia_programar_medida(MED_LENTA_S);
wdt_alimentar(); /* el programa sigue vivo aunque el sensor no */
return;
}
fallas_seguidas = 0u;
registro_agregar(&(Muestra){ ahora_s(), t, estado_actual() });
if (!alarma && t > LIM_ALTO_C) { /* cruzó el límite */
alarma = true; radio_enviar_alarma(t); energia_programar_reporte(REP_ALARMA_S);
} else if (alarma && t <= LIM_ALTO_C - HIST_C) { /* volvió con histéresis */
alarma = false; energia_programar_reporte(REP_NORMAL_S);
}
bool rapido = alarma || (t >= LIM_ALTO_C - ZONA_C); /* cerca del límite: medir seguido */
energia_programar_medida(rapido ? MED_RAPIDA_S : MED_LENTA_S);
wdt_alimentar(); /* latido: solo si la cadena de medida terminó */
}
El tamaño de la zona de alerta no es un número arbitrario: es lo que la temperatura puede subir entre dos medidas lentas. Con una pendiente máxima de 0,05 °C/s (un supuesto que hay que confirmar con datos reales), en 60 s sube 3 °C, de modo que la zona debe ser de al menos 3 °C. Con menos, existe una fase desfavorable en la que una medida cae justo por fuera de la zona y la siguiente, 60 s después, ya encuentra la temperatura por encima del límite. La Parte 2 del programa y el laboratorio lo muestran con una excursión de la temperatura de 4 a 12 °C que empieza 30 s después de una medida lenta (la fase que hace daño):
| Excursión | Zona de alerta | Latencia de la alarma | R-2 (5 s) | Corriente media | Vida |
|---|---|---|---|---|---|
| Lenta (0,01 °C/s) | 2 °C | 0,405 s | Cumple | 19,82 µA | 6,71 años |
| Lenta (0,01 °C/s) | Ninguna (medir cada 60 s) | 56,405 s | No cumple | 19,72 µA | 6,74 años |
| Rápida (0,05 °C/s) | 2 °C | 10,405 s | No cumple | 19,13 µA | 6,90 años |
| Rápida (0,05 °C/s) | 3 °C | 0,405 s | Cumple | 19,15 µA | 6,89 años |
| Rápida (0,05 °C/s) | 4 °C | 0,405 s | Cumple | 40,22 µA | 3,73 años |
La tabla enseña tres cosas. Sin zona de alerta, el equipo detecta la excursión lenta con 56,4 s de retraso en esta fase (el peor caso teórico es 60,4 s): el requisito R-2 solo se cumple por casualidad de fase, no por diseño. Con una zona de 2 °C la excursión lenta se resuelve (0,6 °C entre medidas lentas, menos que la zona), pero la rápida no: la temperatura sube 3 °C entre medidas y atraviesa el límite antes de que el equipo acelere (10,4 s). Con 3 °C, justo la pendiente por 60 s, ambas se cumplen y el costo en energía casi no cambia (19,15 µA). Y con 4 °C se «sobrediseña»: la zona empieza en 4,0 °C, que la temperatura normal (4,0 ± 0,5 °C) toca la mitad del tiempo, así que el equipo mide cada 2 s casi siempre (66 903 medidas en lugar de 6196) y la vida cae de 6,89 a 3,73 años. Cumple los requisitos, pero tira casi la mitad de la autonomía. El tamaño correcto de la zona es una consecuencia de los datos físicos, ni más angosta ni más ancha.
Y una observación de método: la latencia depende de la fase entre la excursión y las medidas. Una prueba que usa un único instante de inicio puede salir bien por suerte (los 0,405 s de la zona de 2 °C con la excursión lenta) o mal por mala suerte. Se prueba con varias fases (o con la peor, que se puede calcular, como hicimos al fijar los 30 s) y se compara el resultado con la cota teórica: periodo de medida más el tiempo de proceso y de radio.
05 · El presupuesto frente a la realidad
Bajo consumo en el conjunto
El tema 48 calculó un consumo del circuito de 15,78 µA y una vida de 7,97 años. La simulación del equipo completo, tres días de funcionamiento normal con reporte cada 15 minutos, da 15,90 µA y 7,93 años: el presupuesto estaba bien, con una diferencia explicable. La simulación cuenta lo que el presupuesto no contaba: escribir cada medida en la flash (0,01 mC por medida, unos 0,17 µA más) y, por el contrario, 287 reportes en tres días en lugar de 288 (porque el primero sale a los 900 s). El resultado de cualquier integración sirve para eso: comparar lo previsto con lo medido y explicar la diferencia. Una diferencia sin explicación es un modelo equivocado.
La energía en un producto con radio se la lleva casi toda la radio. Del total de 15,90 µA, la radio consume 12,4 µA (el 78 %), las medidas 1,5 µA y el reposo 2,0 µA. El laboratorio permite ver la consecuencia de un cambio de requisito: si el cliente pidiera un reporte cada 5 minutos en lugar de cada 15, la corriente subiría a 40,79 µA y la vida bajaría de 7,93 a 3,68 años: sigue cumpliendo los 2 años y el objetivo de diseño de 3 años, pero con un margen mucho menor. Es la conversación del tema 48 («cada reporte cuesta 11,2 mC») en forma de números.
| Consumidor | Corriente media | Qué lo reduce |
|---|---|---|
| Radio (reportes) | 12,4 µA (78 %) | Menos reportes, mensajes más cortos, potencia de transmisión menor, agrupar medidas en cada reporte |
| Medidas (sensor, cálculo, flash) | 1,5 µA (9 %) | Medir menos seguido fuera de la zona de alerta; agrupar escrituras en flash (tema 41) |
| Reposo | 2,0 µA (13 %) | Elegir un chip con menor corriente de sueño; apagar el regulador y los pines flotantes (tema 35) |
Dos advertencias para pasar del modelo a la realidad. Primera: la energía de la radio y del sueño se mide, no se supone (tema 36): una corriente de sueño de 2,0 µA en la hoja de datos puede ser 10 µA en la placa por un pin flotante o un regulador mal elegido, y eso por sí solo cambiaría la conclusión de la tabla. Segunda: el modelo no sabe de la temperatura ni de la pila: con frío la capacidad de la pila baja (la simulación usa el 80 % utilizable, un supuesto que se confirma midiendo a −30 °C, que es donde viaja el producto), y la autodescarga y la resistencia interna cambian. El objetivo de diseño de 3 años con margen de 1,5 existe para absorber esas diferencias.
06 · Cuando algo sale mal
Watchdog y recuperación de fallas
El registrador debe poder fallar sin dejar de ser útil. Dos fallas del requisito están modeladas en el proyecto: que el programa se cuelgue (R-4) y que el sensor deje de responder (R-5). La Parte 3 las simula a los dos días de funcionamiento:
| Escenario | Corriente | Medidas | Resultado |
|---|---|---|---|
| Sin fallas | 15,90 µA | 4320 | — |
| Programa colgado, watchdog de 120 s | 17,15 µA | 4319 | 1 reinicio; 125 s sin medir (cumple R-4: menos de 300 s) |
| El sensor deja de responder | 15,94 µA | 4320 | Falla informada en la primera medida fallida (cumple R-5) |
El caso del cuelgue enseña dos cosas que el diseño del watchdog (tema 38) ya anticipaba. Primera: los 125 s son 120 s más 5 s de arranque contados desde la última medida y no desde el cuelgue. El watchdog se alimenta tras cada medida; si el programa se cuelga justo después de alimentarlo, pasan los 120 s completos de cuelgue; si se cuelga poco antes de la próxima medida, el reinicio llega antes. El tiempo sin medir es siempre el plazo del watchdog más el arranque, y por eso el plazo (120 s) se elige a partir del requisito (300 s) y del período de medida (60 s), con la regla de que sea mayor que el período de alimentación (si fuera de 30 s, el watchdog reiniciaría el equipo sano cada medio minuto, el error clásico del tema 38). Segunda: durante el cuelgue la CPU quedó ejecutando un bucle a 4 mA: unos 80 s en este caso, 320 mC, que son 1,25 µA promedio sobre los tres días. Un cuelgue por semana en todo el parque costaría poco; uno por hora vaciaría la pila, y por eso el informe de causa de reinicio (tema 37) debe viajar a la nube y alguien debe leerlo.
El watchdog solo detecta lo que se le pregunta. Alimentarlo desde una interrupción lo volvería inútil (se alimenta aunque el programa principal esté colgado, tema 38); alimentarlo en el bucle principal sin más detecta cuelgues del bucle pero no que una parte del sistema dejó de funcionar. Por eso el ejemplo lo alimenta al final de una medida completa: si el temporizador de medidas se detiene, si el sensor traba el bus, si la escritura en flash nunca termina, no hay latido y el equipo se reinicia. Para sistemas con varias tareas, la técnica es la de los puntos de control: cada tarea marca que cumplió su parte y solo se alimenta el watchdog si todas lo hicieron en su plazo.
Para la falla del sensor el requisito pide informarla en menos de 120 s, y el diseño lo hace en la primera medida fallida: como mucho 60 s después de que ocurra (en la simulación, 0 s porque la falla comienza justo en una medida). Dos detalles importan: se informa una vez (no un reporte por cada medida fallida, que vaciaría la pila) y el equipo sigue vivo (alimenta el watchdog, sigue midiendo cada 60 s por si el sensor se recupera, sigue reportando que está en falla). Un sensor roto no debería convertirse en un equipo roto.
07 · Registro y actualización
Registro y actualización segura
El registro de las medidas (R-7) usa la técnica del tema 41: un registro circular en la flash externa, con un CRC por registro y un número de secuencia, de modo que tras un corte de energía el equipo recupera el último registro válido y sigue desde allí. A 8 bytes por medida y una medida por minuto, los 30 días requeridos son 345 600 bytes; la flash externa de 512 KB alcanza con margen, y su desgaste (tema 40) se calcula con el número de borrados por sector, que el registro circular reparte parejo.
La actualización por radio (R-6) es donde más se paga haber pensado en el corte de energía. La imagen nueva llega en fragmentos y se graba en la flash externa; recién cuando está completa y verificada (CRC y firma, tema 43) se marca como candidata, se reinicia, se arranca en prueba y, solo si la versión nueva confirma que funciona, se vuelve definitiva; si no, el cargador vuelve a la anterior (tema 42). El orden de los pasos es lo que hace segura la secuencia, y la Parte 4 lo demuestra cortando la energía después de cada paso:
| Orden de los pasos | Cargador | Cortes seguros |
|---|---|---|
| Datos, validez y marca de prueba al final | Comprueba la imagen antes de saltar | 7 de 7 |
| Datos, validez y marca de prueba al final | Salta sin comprobar | 7 de 7 |
| Marca de prueba primero | Comprueba la imagen antes de saltar | 7 de 7 |
| Marca de prueba primero | Salta sin comprobar | 2 de 7 (el equipo no arranca si se corta después de los pasos 1 a 5) |
La lección es la de la defensa en profundidad: con el orden correcto, hasta un cargador ingenuo es seguro; con un cargador que comprueba la imagen, hasta el orden equivocado es seguro; solo la combinación de las dos fallas deja el equipo sin arrancar, en cinco de siete puntos de corte. Un producto serio hace las dos cosas: graba la marca de prueba al final, y el cargador verifica siempre lo que va a ejecutar. Y se prueba sistemáticamente, con un modelo de la flash que corta en cada paso (como la Parte 4) y, en el banco, con la fuente programable cortando durante cada fase.
/* Decisión del cargador de arranque: robusta ante una imagen incompleta y ante una versión nueva que no funciona */
typedef enum { BOOT_A, BOOT_B_PRUEBA, BOOT_B_CONFIRMADA } Marca;
void cargador_arrancar(void) {
Marca m = marca_leer();
if (m == BOOT_B_PRUEBA) {
if (!imagen_b_valida()) { marca_escribir(BOOT_A); } /* incompleta o dañada: seguir con la anterior (nunca saltar a ciegas) */
else if (intentos_prueba_incrementar() > 3u) { marca_escribir(BOOT_A); } /* la nueva no se confirmó en 3 arranques: vuelta atrás */
}
saltar_a(marca_leer() == BOOT_A ? SLOT_A : SLOT_B);
}
/* La aplicación nueva confirma que funciona después de completar una medida y un reporte con éxito */
void arranque_confirmar_si_corresponde(void) {
if (marca_leer() == BOOT_B_PRUEBA && autochequeo_ok()) { marca_escribir(BOOT_B_CONFIRMADA); }
}
08 · Antes de liberar
Pruebas del proyecto y liberación
Cada requisito tiene su método de verificación, y la mayor parte de las pruebas del proyecto ya las conocemos de los temas 44 a 47. Aquí se juntan en un plan de pruebas con su nivel en la pirámide:
| Requisito | Prueba | Nivel |
|---|---|---|
| R-1 Vida | Consumo medido de cada modo con fuente programable y medidor de corriente; vida calculada con el modelo; prueba de pila a −30 °C | Hardware en el lazo y análisis |
| R-2 Alarma | Rampa de temperatura a distintas pendientes y varias fases; latencia medida con pin y analizador lógico | Hardware en el lazo |
| R-3 Reporte | Simulación de varios días con el reloj acelerado; conteo de reportes | Simulación |
| R-4 Cuelgue | Cuelgue provocado desde el modo de prueba en distintos puntos; medir el tiempo sin medir | Hardware en el lazo |
| R-5 Falla del sensor | Inyección de falla (desconexión del bus) y verificación del informe y de que sigue vivo | Hardware en el lazo y unitaria con un sensor falso |
| R-6 Actualización | Corte de energía en cada paso, imágenes dañadas, versión nueva que no confirma, retroceso rechazado (temas 42, 43 y 47) | Unitaria con flash simulada y hardware en el lazo |
| R-7 Registro | Cortes de energía durante cada escritura; recuperación; desgaste (tema 41) | Unitaria con flash simulada |
| Lógica (histéresis, zona, estados) | Tabla de casos en los límites a ambos lados (8 casos como mínimo), mutación y propiedades (tema 47) | Unitaria en la PC |
Antes de liberar una versión se recorre una lista de verificación que reúne los temas anteriores. Si algún punto no se puede marcar, no se libera:
| Punto | Tema |
|---|---|
| Todos los requisitos tienen su prueba, y la matriz de trazabilidad no tiene huecos | 48 y 50 |
La integración continua está en verde: compilación con -Werror, análisis estático, pruebas con sanitizers, presupuestos de flash, RAM y pila respetados | 46, 47 y 50 |
| Versión marcada, huella de la compilación y ELF con su mapa archivados; la compilación se puede reproducir | 45 y 50 |
| Depuración cerrada, sin información de prueba, imagen firmada, contador anti-retroceso actualizado | 43 y 45 |
| Watchdog armado y alimentado solo al final de la medida; causa de reinicio informada | 37 y 38 |
| Consumo medido en cada modo, sin la sonda conectada, y dentro del objetivo de diseño | 36 y 45 |
| Actualización probada con cortes de energía y con versión nueva que falla; despliegue gradual planeado | 42 y 47 |
| Documentación: README, arquitectura, ADR y registro de cambios al día; versiones de firmware, hardware y protocolo definidas | 49 y 50 |
| Revisión de código hecha y desviaciones del estándar documentadas | 50 |
| Plan de mantenimiento: política de versiones soportadas, seguimiento de avisos de seguridad, componentes con su ciclo de vida | 50 |
09 · Comprobar que funciona
Verificación y diagnóstico
| Qué verificar | Cómo | Resultado esperado |
|---|---|---|
| El modelo coincide con la realidad | Comparar la simulación con las medidas del banco, modo por modo | Diferencias explicadas (o el modelo se corrige) |
| Los requisitos con plazo se cumplen en todas las fases | Repetir la prueba con varias fases de la excursión y comparar con la cota teórica | La peor fase cumple, no solo la casual |
| Los parámetros derivados están justificados | Zona de alerta = pendiente máxima × período lento; plazo del watchdog > período de alimentación | Cada parámetro tiene su cuenta anotada en el ADR |
| El equipo se recupera de cada falla modelada | Cuelgue, falla de sensor, corte de energía, imagen dañada: provocarlas en el banco | Recuperación sin intervención dentro del plazo |
| La actualización es segura en cada punto de corte | Modelo exhaustivo de cortes más fuente programable | Siempre arranca una versión válida |
| La versión liberada es la probada | Huella de la compilación y firma verificadas sobre el binario que se entrega | Coincide con la probada |
| Síntoma | Causa probable | Qué hacer |
|---|---|---|
| La alarma tarda mucho solo con ciertas excursiones | Zona de alerta menor que la pendiente por el período lento | Dimensionar la zona con la pendiente máxima medida; probar varias fases |
| El consumo real es el doble del calculado | Zona de alerta demasiado ancha, reportes más frecuentes de lo supuesto, un pin flotante o un regulador | Contar medidas y reportes por día; medir el sueño; revisar la zona |
| El equipo se reinicia cada medio minuto | Plazo del watchdog menor que el período de alimentación | Plazo mayor que el período, derivado del requisito (R-4) |
| El equipo no arranca después de una actualización cortada | Marca de prueba grabada antes de terminar la imagen, y un cargador que no verifica | Marca al final; el cargador verifica siempre; probar todos los cortes |
| Un sensor roto vacía la pila | Un reporte por cada medida fallida, o reintentos sin límite | Informar una vez, reintentar con espera creciente y límite |
| La versión de campo no coincide con lo probado | Compilación sin huella ni versiones fijas | Manifiesto, compilación reproducible, binario firmado desde la integración continua |
| Los requisitos pasan en la simulación y fallan en el banco | Hipótesis del modelo (corrientes, pendiente, capacidad) distintas de las reales | Reemplazar cada supuesto por una medida y reajustar el modelo |
10 · Analogía con programación
Probar el modelo en Python
El programa es el modelo ejecutable del registrador completo: simula tres días a un paso de un segundo la máquina de estados (activo, alarma, falla), la zona de alerta, los reportes periódicos y de alarma, el consumo de cada operación, el watchdog con un cuelgue provocado y la falla del sensor; y, en la Parte 4, modela la actualización con corte de energía en cada paso con dos cargadores y dos órdenes. Es el mismo modelo que corre el laboratorio.
Python en tu navegador. Los bloques son editables: cambiá los valores y presioná «Ejecutar Python». La primera vez tarda unos segundos en cargar; esta simulación recorre 259 200 pasos por escenario y puede tardar algunos segundos más.
# Proyecto integrador: el registrador de temperatura completo, simulado tres días a un paso de un segundo (energía, alarma, watchdog) y una actualización con corte de energía en cada paso.
import math
# ---- El modelo del dispositivo --------------------------------------------------------------------------------------------------------------------
N, L, HIST = 3 * 86400, 8.0, 0.5 # tres días simulados; límite de alarma 8 °C con histéresis de 0,5 °C
T_MED, T_RAPIDO, T_REP_ALARMA, WDT = 60, 2, 60, 120 # períodos de medida, de reporte en alarma y plazo del watchdog (s)
CARGA_MED, CARGA_TX, SUENO_MC, CPU_MA = 0.09, 11.2, 0.002, 4.0 # mC por medida (sensor, cálculo y escritura en flash), mC por reporte, mC por segundo de sueño, mA de una CPU colgada
FALLA_T, HANG_T, T0 = 2 * 86400, 2 * 86400 + 1000, 86400 + 6 * 3600 + 30 # instante en que falla el sensor, en que se cuelga el programa y en que empieza la excursión (30 s después de una medida lenta: la fase importa)
def temperatura(t, esc):
base = 4.0 + 0.5 * math.sin(2 * math.pi * t / 21600)
if esc in ("lenta", "rapida"):
p = 0.01 if esc == "lenta" else 0.05 # °C por segundo
r = 8.0 / p
if T0 <= t < T0 + r: return base + p * (t - T0)
if T0 + r <= t < T0 + r + 3600: return base + 8.0
if T0 + r + 3600 <= t < T0 + 2 * r + 3600: return base + 8.0 - p * (t - (T0 + r + 3600))
return base
def simular(esc, zona, t_rep, cuelgue=False):
carga = 0.0; prox_med = 0; prox_rep = t_rep; alarma = False; rapido = False
regs = reportes = reinicios = 0; lats = []; cruce = None; falla_rep = None
colgado = False; ult_alim = 0; ult_med = 0; ant_hang = None; gap = None
for t in range(N):
carga += SUENO_MC
v = temperatura(t, esc)
if v > L and cruce is None and not alarma: cruce = t
if cuelgue and not colgado and ant_hang is None and t == HANG_T:
colgado, ant_hang = True, ult_med
if colgado:
carga += CPU_MA # una CPU colgada en un bucle consume la corriente de funcionamiento
if t - ult_alim >= WDT:
colgado = False; reinicios += 1; prox_med = t + 5; prox_rep = t + 5 + t_rep
continue
if t >= prox_med:
carga += CARGA_MED; regs += 1; ult_alim = t
if reinicios and gap is None: gap = t - ant_hang
ult_med = t
if esc == "falla" and t >= FALLA_T: # el sensor no responde: se informa la falla una vez
if falla_rep is None: falla_rep = t; reportes += 1; carga += CARGA_TX
rapido = False
else:
if v > L and not alarma:
alarma = True; lats.append(t - cruce + 0.405); cruce = None; reportes += 1; carga += CARGA_TX; prox_rep = t + T_REP_ALARMA
elif alarma and v <= L - HIST: alarma = False
rapido = alarma or (zona > 0 and v >= L - zona)
prox_med = t + (T_RAPIDO if rapido else T_MED)
if t >= prox_rep:
reportes += 1; carga += CARGA_TX; prox_rep = t + (T_REP_ALARMA if alarma else t_rep)
ua = carga / N * 1000
return dict(ua=ua, vida=1500 / ((ua + 5.70) / 1000) / 24 / 365, regs=regs, reportes=reportes, lat=max(lats) if lats else None,
reinicios=reinicios, gap=gap, falla=None if falla_rep is None else falla_rep - FALLA_T)
def mostrar(titulo, r):
lat = "sin alarma" if r["lat"] is None else f"{r['lat']:.3f} s"
extra = (f"; sin medir {r['gap']} s tras {r['reinicios']} reinicio(s)" if r["gap"] is not None else "") + (f"; falla del sensor informada en {r['falla']} s" if r["falla"] is not None else "")
print(f" {titulo:<48} {r['ua']:6.2f} µA, vida {r['vida']:5.2f} años, {r['regs']:>5} medidas, {r['reportes']:>3} reportes, latencia de alarma {lat}{extra}")
print("Parte 1: tres días de funcionamiento normal (4 °C con una variación de ±0,5 °C), reporte cada 15 min")
mostrar("normal, zona de alerta de 2 °C", simular("normal", 2, 900))
print(" el presupuesto del tema 48 daba 15,78 µA; la simulación incluye además la escritura de cada medida en la flash (0,01 mC), que el presupuesto no contaba")
print()
print("Parte 2: una excursión de temperatura (sube 8 °C, se mantiene una hora y vuelve) y el requisito de alarma en menos de 5 s")
mostrar("lenta (0,01 °C/s), zona de 2 °C", simular("lenta", 2, 900))
mostrar("lenta (0,01 °C/s), sin zona (medir cada 60 s)", simular("lenta", 0, 900))
mostrar("rápida (0,05 °C/s), zona de 2 °C", simular("rapida", 2, 900))
mostrar("rápida (0,05 °C/s), zona de 3 °C", simular("rapida", 3, 900))
mostrar("rápida (0,05 °C/s), zona de 4 °C", simular("rapida", 4, 900))
print()
print("Parte 3: fallas del equipo: el programa se cuelga a los dos días con el watchdog de 120 s, y el sensor deja de responder")
mostrar("sin cuelgue", simular("normal", 2, 900))
mostrar("con cuelgue y watchdog de 120 s", simular("normal", 2, 900, cuelgue=True))
mostrar("falla del sensor a los dos días", simular("falla", 2, 900))
# ---- Parte 4: actualización con corte de energía en cada paso -------------------------------------------------------------------------------------
BUENO = ["fragmento 1", "fragmento 2", "fragmento 3", "fragmento 4", "imagen válida", "marca de prueba"] # primero los datos, después la validez y por último la marca
MALO = ["marca de prueba"] + BUENO[:-1] # la marca antes de terminar de grabar
def aplicar(pasos):
e = {"frag": 0, "valida": False, "marca": False}
for p in pasos:
if p.startswith("fragmento"): e["frag"] += 1
elif p == "imagen válida": e["valida"] = e["frag"] == 4
elif p == "marca de prueba": e["marca"] = True
return e
def arranque(e, robusto):
if not e["marca"]: return "A" # sin marca: sigue la versión anterior
if e["valida"]: return "B"
return "A" if robusto else "NO ARRANCA" # imagen incompleta: el cargador robusto la comprueba antes de saltar
print()
print("Parte 4: se corta la energía después de cada paso de la actualización y se mira qué versión arranca")
for nombre, orden in (("orden correcto (datos, validez, marca)", BUENO), ("orden incorrecto (marca primero)", MALO)):
for robusto in (True, False):
res = [arranque(aplicar(orden[:k]), robusto) for k in range(len(orden) + 1)]
seguros = sum(r != "NO ARRANCA" for r in res)
print(f" {nombre}, cargador {'que comprueba la imagen' if robusto else 'que salta sin comprobar'}: {seguros} de {len(res)} cortes seguros; resultados {res}")
Resultado, parte 1: tres días de funcionamiento normal dan 15,90 µA, vida de 7,93 años, 4320 medidas y 287 reportes (el presupuesto del tema 48 daba 15,78 µA, sin contar la escritura de cada medida en la flash). Parte 2: excursión lenta con zona de 2 °C: 0,405 s, 19,82 µA y 6,71 años; lenta sin zona: 56,405 s (no cumple 5 s); rápida con zona de 2 °C: 10,405 s (no cumple); rápida con zona de 3 °C: 0,405 s, 19,15 µA; rápida con zona de 4 °C: 0,405 s pero 40,22 µA, 3,73 años y 66 903 medidas. Parte 3: con un cuelgue a los dos días y un watchdog de 120 s: 1 reinicio, 125 s sin medir, 17,15 µA, 7,49 años y 4319 medidas; con la falla del sensor: informada en 0 s (en la primera medida fallida), 288 reportes. Parte 4: con el orden correcto (datos, validez y marca al final), 7 de 7 cortes seguros con cualquier cargador; con la marca primero, 7 de 7 si el cargador comprueba la imagen y 2 de 7 si salta sin comprobar.
Probá cambiar en la Parte 2 la zona de alerta (zona) a 2,5 y a 3,5 °C, o el período de reporte a 300 s (la vida baja a 3,68 años); cambiar el plazo del watchdog (WDT) a 30 s y ver que el tiempo sin medir tras el cuelgue baja a 35 s (el modelo aplica el watchdog solo durante el cuelgue: el reinicio continuo de un plazo menor que el período de alimentación habría que agregarlo), o mover el instante de inicio de la excursión (T0) para ver cómo cambia la latencia con la fase. La lección del programa es que un modelo ejecutable del producto completo, con las hipótesis a la vista, descubre en segundos lo que de otro modo se descubriría con el hardware construido.
11 · Exploración interactiva
El registrador completo
El laboratorio ejecuta el modelo del programa, tres días a un paso de un segundo, y muestra la corriente media, la vida estimada, el número de medidas y reportes, la latencia de la alarma y un tablero de requisitos con cumple o no cumple. Elegís el escenario de temperatura (normal, excursión lenta, excursión rápida, falla del sensor), el tamaño de la zona de alerta (0 la desactiva), el período de reporte y si se provoca un cuelgue del programa con un watchdog de 120 s.
Simular el registrador tres días
Tablero de requisitos
Elegí un escenario.
Recorrido guiado
- Con los valores iniciales (normal, zona de 2 °C, reporte cada 15 min): 15,90 µA, 7,93 años, 4320 medidas y 287 reportes. R-1 y R-3 se cumplen; los demás requisitos no se ejercen, porque no pasó nada. Un tablero verde en un escenario tranquilo no prueba lo que no se ejercitó.
- Elegí la excursión lenta: la alarma sale en 0,405 s (R-2 cumple) y la corriente sube a 19,82 µA (la zona de alerta y la alarma consumen), vida 6,71 años. Ahora poné la zona en «Ninguna»: la latencia salta a 56,405 s y R-2 no cumple: el equipo medía cada 60 s y la temperatura ya había pasado el límite. El costo de la zona de alerta fue de apenas 0,10 µA.
- Elegí la excursión rápida con zona de 2 °C: latencia de 10,405 s, R-2 no cumple, aunque la zona «funciona» con la lenta. La temperatura sube 3 °C entre medidas lentas y atraviesa la zona de 2 °C sin que el equipo acelere. Probá 1 °C y verás lo mismo.
- Con la rápida y la zona de 3 °C (la pendiente por el período lento): 0,405 s, R-2 cumple y la corriente es 19,15 µA. Es el tamaño correcto. Con 4 °C también cumple, pero la corriente se dispara a 40,22 µA, con 66 903 medidas y una vida de 3,73 años: la zona toca la temperatura normal y el equipo mide cada 2 s casi siempre. «Más ancho» no es «más seguro»: es otro costo.
- Volvé al escenario normal y marcá «Provocar un cuelgue»: 4319 medidas (una menos), 17,15 µA, 7,49 años y R-4 cumple con 125 s sin medir (120 s del watchdog más 5 s de arranque, contados desde la última medida). El cuelgue costó 1,25 µA promedio en tres días porque la CPU colgada consumió 4 mA durante unos 80 s.
- Elegí «El sensor deja de responder»: R-5 cumple (informado en la primera medida fallida, 0 s en esta simulación; como máximo 60 s en el peor caso), 288 reportes (uno más: el de la falla) y el equipo sigue vivo. Y probá el período de reporte de 5 minutos en el escenario normal: 40,79 µA y 3,68 años. Sigue cumpliendo R-1, pero la radio pasó del 78 % a casi todo el consumo, y el margen se redujo a la mitad.
Desafío: ¿qué cambiarías del diseño para que la alarma cumpla en la excursión rápida sin gastar más de 25 µA?
Hay varias salidas, y el laboratorio sirve para comprobarlas con números. La más directa es la zona de 3 °C (la pendiente por el período lento), que cumple con 19,15 µA. Otras: acortar el período lento (a 30 s la zona mínima baja a 1,5 °C, pero el consumo de medidas se duplica: de 1,5 a unos 3,0 µA, todavía barato), medir con un umbral de pendiente (si entre dos medidas la temperatura subió más de 1 °C, pasar a modo rápido aunque esté lejos del límite: detecta la excursión rápida por su velocidad, no por su nivel), o usar la alarma por hardware (un sensor con comparador que despierte al microcontrolador al cruzar un umbral, sin necesidad de medir seguido: consume menos pero exige un componente que lo tenga y fija una decisión de hardware, tema 49). Cada una cambia un presupuesto distinto: la primera, nada; la segunda, medidas; la tercera, lógica y pruebas; la cuarta, hardware y costo. La elección se registra en un ADR con estos números.
12 · Método de trabajo
Método: integrar con orden
- Empezá por los requisitos con número y verificación (tema 48) y por los presupuestos con margen (tema 49): son el tablero contra el que se mide todo.
- Armá un esqueleto que funcione de punta a punta lo antes posible (entrada, cola de eventos, una medida falsa, una salida) y hacelo crecer. Un sistema integrado temprano muestra los problemas de interacción cuando todavía es barato corregirlos.
- Construí un modelo ejecutable del producto (en Python, en la PC) con las hipótesis a la vista, y usalo para dimensionar los parámetros derivados: la zona de alerta, el plazo del watchdog, los períodos.
- Calculá cada parámetro derivado y anotá la cuenta (en un ADR): zona = pendiente × período lento; watchdog > período de alimentación y plazo ≤ requisito; período de reporte según la energía.
- Probá en varias fases y en los casos extremos, no solo en el caso feliz: una latencia que cumple por casualidad de fase no cumple. Comparála con la cota teórica.
- Comparás siempre lo previsto con lo medido (15,78 contra 15,90 µA) y explicás la diferencia; una diferencia sin explicar indica un modelo o un presupuesto equivocado.
- Diseñá cada falla modelada con su recuperación (cuelgue, sensor, corte de energía, actualización) y provocala a propósito con un modo de prueba.
- Hacé que la actualización sea segura por orden y por verificación: marca al final, cargador que verifica siempre, versión nueva que debe confirmarse, vuelta atrás, y probalo cortando en cada punto.
- Automatizá todo en la integración continua y recorré la lista de verificación antes de liberar, con la matriz de trazabilidad sin huecos y los artefactos archivados.
- Documentá las decisiones y planificá la vida del producto: mantenimiento, avisos de seguridad, componentes y retirada (tema 50).
13 · Comprensión
Confusiones frecuentes
«Si cada módulo funciona por separado, el sistema funciona»
Los problemas de un producto aparecen en las interacciones: una zona de alerta que cumple con una pendiente y no con otra, un watchdog cuya cuenta depende del período de medida, una marca de actualización cuyo orden importa. Por eso se integra temprano y se prueba el conjunto con escenarios completos.
«Un tablero de requisitos en verde significa que el producto está bien»
Solo significa que los requisitos ejercitados se cumplieron en ese escenario. En el escenario normal, cinco de los siete requisitos no se ejercen. Hay que cubrir los escenarios que ponen a prueba cada uno, en distintas fases y condiciones extremas.
«La zona de alerta, cuanto más ancha, más segura»
Con 4 °C la alarma cumple, pero la zona toca la temperatura normal y el equipo mide cada 2 s casi todo el tiempo: la vida baja de 6,89 a 3,73 años. El tamaño correcto sale de los datos físicos (pendiente máxima por período lento); más ancho es otro costo, no más seguridad.
«El watchdog mide el tiempo desde el cuelgue»
Mide desde la última vez que se lo alimentó. El tiempo sin medir tras un cuelgue es siempre el plazo del watchdog más el arranque (125 s en el ejemplo), sea cual sea el instante del cuelgue. Y si el plazo fuera menor que el período de alimentación, reiniciaría el equipo sano.
«Para que una actualización sea segura basta con verificar la imagen al terminar»
También importa el orden de los pasos y qué hace el cargador: con la marca de prueba grabada antes de terminar y un cargador que salta sin comprobar, 5 de los 7 puntos de corte dejan el equipo sin arrancar. Se necesitan el orden correcto y la verificación, y se prueba cortando la energía en cada punto.
«El presupuesto de energía del diseño ya es el consumo real»
Es una estimación con hipótesis. La simulación completa agregó la escritura en flash y los reportes reales; la medición real agregará pines, regulador, temperatura y pila. La verificación consiste en comparar y explicar cada diferencia, y en reemplazar los supuestos por medidas.
«El proyecto termina cuando se libera la primera versión»
Empieza el mantenimiento: avisos de seguridad, correcciones, actualizaciones por el aire, componentes que se discontinúan, soporte de la flota (tema 50). La lista de verificación incluye el plan de mantenimiento antes de liberar, no después.
«Un modelo en Python es un juguete y no sirve para decidir»
Un modelo con las hipótesis a la vista permite dimensionar parámetros y descubrir contradicciones en segundos, antes de tener hardware. Su valor está en que sus supuestos se pueden discutir y reemplazar por medidas, y en que se puede repetir cada vez que cambia un requisito o una hipótesis.
14 · Práctica guiada
Ejercicios
1. Reportes más frecuentes
El cliente pide un reporte cada 5 minutos en lugar de cada 15. Cada reporte cuesta 11,2 mC. ¿Cuál es la corriente de la radio, la total (el resto del circuito consume 1,5 µA de medidas más 2,0 µA de reposo) y la vida estimada con 5,70 µA de autodescarga? ¿Se cumple el objetivo de diseño de 3 años?
Ver solución
Radio: 11,2 mC / 300 s = 0,03733 mA = 37,33 µA (contra 12,44 µA a 900 s). Total del circuito: 37,33 + 1,5 + 2,0 = 40,83 µA (la simulación da 40,79 µA porque cuenta un reporte menos al comienzo). Con la autodescarga: 46,53 µA; vida = 1500 mAh / 0,04653 mA = 32 237 h ≈ 3,68 años. Cumple los 2 años y el objetivo de 3 años, pero el margen sobre este último bajó de más del doble a un 23 %. Si el cliente quisiera reportes cada 2 minutos, ya no cumpliría el objetivo, y habría que renegociar o cambiar la batería.
2. Dimensionar la zona de alerta
Un contenedor puede calentarse como máximo 0,04 °C/s. El período lento es de 60 s y el límite, 8 °C; la temperatura normal máxima es 4,5 °C. ¿Qué zona mínima hace falta? ¿Y si la pendiente máxima fuera 0,1 °C/s?
Ver solución
Zona mínima = pendiente × período lento = 0,04 × 60 = 2,4 °C: la zona empieza en 8 − 2,4 = 5,6 °C, por encima de la temperatura normal máxima (4,5 °C), de modo que el equipo mide lento en condiciones normales. Con 0,1 °C/s: 0,1 × 60 = 6 °C, y la zona empezaría en 2 °C, dentro de la temperatura normal: el equipo mediría cada 2 s siempre. La solución es acortar el período lento: para que la zona no toque la temperatura normal, debe ser menor que 8 − 4,5 = 3,5 °C, es decir, 0,1 × T ≤ 3,5, T ≤ 35 s. Cambió una hipótesis física (la pendiente) y con ella el diseño de la medida.
3. El tiempo sin medir
El watchdog es de 120 s, se alimenta tras cada medida (cada 60 s) y el arranque tarda 5 s. ¿Cuánto tiempo sin medir deja un cuelgue? ¿Depende de cuándo ocurre? ¿Qué pasaría con un watchdog de 30 s?
Ver solución
El reinicio ocurre 120 s después de la última alimentación y la primera medida después, 5 s más tarde: 125 s sin medir, sea cual sea el instante del cuelgue (entre dos medidas). Lo que sí varía es cuánto tiempo estuvo colgada la CPU consumiendo 4 mA: entre 61 s (cuelgue justo antes de la medida siguiente) y 120 s (justo después de la anterior), es decir entre 244 y 480 mC. Con un watchdog de 30 s, que es menor que el período de alimentación de 60 s, el equipo sano se reiniciaría cada 30 s sin medir nunca: el plazo debe superar el período de alimentación.
4. Cortes de energía
Una actualización tiene seis pasos (cuatro fragmentos, validez y marca de prueba) y se prueba un corte antes de cada paso y uno al final. ¿Cuántos puntos de corte hay? Con la marca primero y un cargador que salta sin comprobar, ¿cuáles dejan al equipo sin arrancar?
Ver solución
Con 6 pasos hay 7 puntos de corte (después de 0, 1, 2, 3, 4, 5 o 6 pasos). Con la marca primero, el corte tras el paso 0 es seguro (no hay marca: sigue la versión anterior); tras los pasos 1 a 5 hay marca pero la imagen está incompleta o sin validar: el cargador ingenuo salta a una imagen inválida y el equipo no arranca (5 de 7 cortes); tras el paso 6 la imagen está completa y arranca la nueva. El cargador que comprueba la imagen antes de saltar vuelve a la anterior en los cinco casos: los 7 son seguros.
5. Presupuesto contra simulación
El presupuesto del tema 48 daba 15,78 µA y la simulación da 15,90 µA. Explicá la diferencia con números.
Ver solución
El presupuesto suponía 0,08 mC por medida (3 mA × 20 ms más 4 mA × 5 ms): 1,33 µA cada 60 s. La simulación agrega la escritura en flash, 0,01 mC (0,09 mC en total): 1,5 µA, o 0,17 µA más. Eso da 15,78 + 0,17 = 15,94 µA. La simulación da 15,90 µA y no 15,94 porque en tres días hay 287 reportes y no 288 (el primero sale a los 900 s): 11,2 mC × 287 / 259 200 s = 12,40 µA contra 12,44 µA, 0,04 µA menos. 15,94 − 0,04 = 15,90 µA. La diferencia queda explicada punto por punto: eso es validar un modelo.
6. Una liberación con un hueco
Al repasar la lista de verificación antes de liberar, descubrís que la matriz de trazabilidad no tiene prueba para R-5 (falla del sensor) y que la versión de campo se compiló en una máquina sin guardar el ELF. ¿Se libera? ¿Qué hacés?
Ver solución
No se libera. Un requisito sin prueba (R-5) es un deseo sin verificar: se escribe la prueba (inyección de falla en el banco y una unitaria con un sensor falso) y se ejecuta antes de liberar. La compilación sin ELF ni huella no se puede diagnosticar ni reproducir: un HardFault en el campo mostraría solo direcciones (tema 45). Se recompila desde la marca en el entorno de la integración continua, se archivan el ELF, el mapa y la huella, y se libera ese binario firmado. Los dos huecos se cierran por proceso: la matriz se comprueba en la integración continua (tema 50) y la liberación sale únicamente de ella.
15 · Síntesis
Ideas para recordar
- Un proyecto integrador reúne las decisiones del curso y las pone a prueba juntas. El registrador tiene siete requisitos con número y verificación, una arquitectura dirigida por eventos (el reloj, la radio y el botón encolan; un solo bucle procesa; sin eventos, duerme) y un esqueleto de firmware sin esperas activas, con el watchdog armado primero y la causa de reinicio registrada.
- La lógica de alarma combina histéresis y una zona de alerta. La zona debe ser al menos la pendiente máxima por el período lento (3 °C): con 2 °C la excursión rápida da 10,4 s (no cumple los 5 s); con 3 °C, 0,4 s y 19,15 µA; con 4 °C también cumple, pero toca la temperatura normal y la vida cae de 6,89 a 3,73 años. Sin zona, la alarma de la excursión lenta tardó 56,4 s.
- La latencia depende de la fase entre la excursión y las medidas: se prueba en varias fases y se compara con la cota teórica, porque cumplir en una sola puede ser casualidad.
- El consumo simulado (15,90 µA, 7,93 años) coincide con el presupuesto (15,78 µA, 7,97 años) salvo diferencias que se explican: la escritura en flash (+0,17 µA) y un reporte menos (−0,04 µA). La radio es el 78 % del consumo: pasar el reporte de 15 a 5 minutos lleva la corriente a 40,79 µA y la vida a 3,68 años.
- El watchdog de 120 s reinicia un programa colgado y deja 125 s sin medir (plazo más arranque, contados desde la última alimentación); debe ser mayor que el período de alimentación y se alimenta al final de una medida completa. Una falla del sensor se informa una vez y el equipo sigue vivo.
- La actualización es segura por orden y por verificación: marca de prueba al final y cargador que comprueba la imagen. Solo la combinación de las dos fallas (marca primero y cargador sin comprobar) deja 5 de 7 cortes sin arrancar. Se prueba cortando la energía en cada punto, con una flash simulada y con el banco.
- Se libera con un plan de pruebas y una lista de verificación: trazabilidad sin huecos, integración continua en verde, versión marcada con huella y ELF archivados, depuración cerrada, consumo medido sin la sonda, actualización probada, documentación y plan de mantenimiento. Un tablero en verde solo prueba lo que se ejercitó.
¿Listo para el tema siguiente?
Antes de avanzar, tomá un proyecto tuyo, aunque sea pequeño, y probá este ejercicio: escribí sus cinco requisitos principales con número, construí un modelo ejecutable de veinte líneas que calcule su consumo y su latencia, y compará con lo que medís en una placa. Donde no coincidan, vas a aprender más que en cualquier tema.
En el último tema del curso hacemos el cierre: una revisión de lo recorrido, las buenas prácticas que se repiten en todos los bloques y el puente hacia el Internet de las Cosas, con los próximos pasos.