01 · Objetivo
Dónde estamos
Quien llega a este tema tiene una caja de herramientas poco común: sabe qué pasa en un cable cuando dos dispositivos se hablan (niveles, tiempos, bits), sabe organizar una conversación (tramas, direcciones, confirmaciones, formatos), sabe verla y depurarla con instrumentos, sabe protegerla de un adversario y sabe elegir la tecnología adecuada y combinarlas en un sistema. Lo que falta para convertir eso en un producto ya no es comunicación: es todo lo que rodea a la comunicación dentro de un dispositivo que debe funcionar durante años sin que nadie lo toque. Ese es el territorio de los sistemas embebidos, y este tema marca la frontera.
02 · Mirar atrás
El recorrido, bloque por bloque
| Bloque | Idea central | Una cifra para recordar |
|---|---|---|
| 1 · Fundamentos (temas 1 a 6) | Comunicarse es acordar quién habla, cuándo, a qué velocidad y con qué niveles. El modelo de capas separa el medio, la trama y el significado. La serie ganó a la paralela | 3,3 V y 5 V no se mezclan sin cuidado; la velocidad de bits y la de baudios no siempre coinciden |
| 2 · UART (7 a 11) | Asíncrona, sin reloj: inicio, datos, paridad y parada, con el acuerdo previo de la velocidad | 8N1 son 10 bits por byte; a 9600 baudios, 104 µs por bit; tolerancia total de 2 a 3 % |
| 3 · SPI (12 a 15) | Síncrono, rápido, un maestro y una línea de selección por esclavo; los modos CPOL y CPHA deben coincidir | De 1 a 50 MHz, a pocos centímetros |
| 4 · I²C (16 a 20) | Dos hilos de colector abierto con resistencias de elevación; direcciones, confirmación de cada byte, estiramiento de reloj | 112 direcciones; subida de 1000 ns a 100 kHz y de 300 ns a 400 kHz; tr = 0,8473·R·C |
| 5 · 1-Wire (21) | Un hilo de datos que también alimenta; el bit va en la duración del pulso; cada dispositivo tiene una ROM única | Reset de 480 µs; ROM de 64 bits con un CRC-8 |
| 6 · Buses industriales (22 a 28) | Señal diferencial para el ruido y la distancia: RS-232 punto a punto, RS-485 multipunto, Modbus RTU de maestro y esclavos, CAN con arbitraje por prioridad | RS-485: 1200 m a 100 kbit/s o 12 m a 10 Mbit/s; CAN: 40 m a 1 Mbit/s |
| 7 · Ethernet y redes IP (29 a 33) | La pila de capas completa: MAC, IP, TCP o UDP, HTTP o MQTT; publicar y suscribirse desacopla productores de consumidores | 100 m por tramo; el tráfico de un mensaje corto es casi todo encabezado |
| 8 · Inalámbrica (34 a 40) | Espectro, potencia y alcance; Wi-Fi, Bluetooth, BLE, LoRa, Zigbee, nRF24, ESP-NOW; el presupuesto de energía decide los años de una batería | Un ciclo de BLE con un ESP32 cuesta 19,9 mC; con 2000 mAh y 5 minutos de período, 2,2 años |
| 9 · Protocolos y errores (41 a 47) | Una trama delimitada con largo y CRC, direcciones, causas físicas del error, detección (CRC), reparación (ACK, secuencia, reintentos), formato de los datos | CRC-16/Modbus de «123456789» = 4B37; la pérdida del 20 % con 3 reintentos deja 0,16 % sin entregar |
| 10 · Depuración, selección y proyectos (48 a 52) | Ver antes de suponer, proteger con criptografía, elegir con números y construir un sistema completo con puerta de enlace | Un HMAC de 8 bytes: 1 en 1,8 × 10¹⁹ de falsificarlo; RS-485 con 8 nodos: 1,3 % del bus |
Si hubiera que quedarse con un solo recorrido, sería este: bits y tiempos (bloques 1 a 5), distancia y ruido (6), redes (7 y 8), significado y confiabilidad (9) y método (10). Cada nivel descansa en el anterior, y el error más caro de todos suele ser el que se comete en el nivel más bajo y se paga en el más alto.
03 · Lo que no cambia
Seis principios que atraviesan todo
Las tecnologías cambian cada década; estas ideas, no. Aparecen con otros nombres en cada bloque, y quien las tiene claras aprende cualquier protocolo nuevo en una tarde:
- Todo es acuerdo. Los bytes no traen etiqueta: su significado está en un acuerdo previo entre los dos extremos (velocidad, formato, orden de bytes, unidad, escala). Cuando dos dispositivos no se entienden, casi siempre difieren en algo que cada uno daba por obvio. Se escribe el acuerdo (una tabla de campos), se prueba con vectores y se valida lo que llega (temas 7, 13, 41 y 46).
- El medio es compartido y el tiempo manda. Dos que hablan a la vez se pisan. Cada tecnología resuelve la convivencia de una manera: un maestro que pregunta (SPI, Modbus, el sondeo del tema 51), direcciones y arbitraje (I²C, CAN), turnos por ranuras (Bluetooth), escucha antes de hablar (Wi-Fi). Y todo se mide en tiempos: de bit, de byte, de trama, de espera, de reintento (temas 6, 16, 28, 36 y 45).
- El mundo es ruidoso y se supone que va a fallar. Los errores no son una excepción sino el régimen normal. Se detectan (paridad, suma, CRC) y se reparan (confirmaciones, reintentos, corrección). Se diseña para la pérdida: no hay enlace sin ella (temas 43 a 45).
- Nada espera, todo se cuenta. Un programa que se bloquea esperando pierde datos y no puede reaccionar: se usan máquinas de estados y tiempos de vencimiento. Y como lo que no se mide no se puede reparar, cada falla posible tiene su contador, y los contadores de los dos extremos se leen juntos (temas 9, 33, 47 y 51).
- La velocidad anunciada no es la útil. Entre los bits de la línea y los datos del usuario hay encabezados, confirmaciones, silencios y reintentos; entre la hoja de datos y la realidad hay cables, ruido y software. Se calcula con el mensaje real y se mide en el hardware real (temas 4, 48 y 50).
- Cada capa protege su tramo, y lo seguro se diseña. El CRC protege del ruido, no de una persona; el cifrado del Wi-Fi llega al punto de acceso, no al servidor. La seguridad exige autenticar, rechazar repeticiones, cuidar las claves y verificar certificados, y no se agrega al final (temas 44 y 49).
04 · Elegir sin dudar
Un árbol de decisión
El árbol es un atajo, no una regla: resume el resultado del método del tema 50 para los casos más comunes. Sirve para empezar por la rama correcta; después se verifican los números (distancia a la velocidad necesaria, cantidad de nodos, consumo, entorno), se descartan las que no cumplen y se prueba el riesgo mayor. Si el caso cae entre dos ramas, normalmente se necesita una puerta de enlace (tema 51): el campo en la tecnología que le conviene y la red en la que le conviene al servidor.
05 · Soluciones que se repiten
El catálogo de patrones
El curso fue construyendo, casi sin nombrarlas, un conjunto de soluciones de diseño que se reutilizan en cualquier protocolo. Reunirlas con su nombre ayuda a reconocer el problema que resuelven cuando se lo encuentra en otro lugar:
| Patrón | Problema que resuelve | Dónde se vio |
|---|---|---|
| Máquina de estados no bloqueante | Esperar sin detener al resto del programa | Receptor de tramas (41); sondeo del maestro (47, 51); reconexión (33, 36) |
| Trama delimitada con largo y CRC | Encontrar el comienzo y el final de un mensaje en un flujo de bytes y saber si llegó íntegro | 41, 44; todo el bloque 9 |
| Consulta y respuesta con secuencia | Ligar cada respuesta a su pregunta y descartar las tardías | 45, 47, 51 |
| Reintentos con espera creciente | Recuperarse de pérdidas sin agravar la congestión | 45; reconexión MQTT (33, 51) |
| Filtro de duplicados con ventana | No entregar dos veces lo que se reenvió, tolerando el desorden | 45, 47, 49 |
| Búfer circular con descarte de lo más viejo | Desacoplar quien produce de quien consume y soportar cortes | UART (9, 10); cola de la puerta de enlace (51) |
| Validación de rangos | No confiar en un dato porque su CRC cierre | 46, 47, 51 |
| Contador por cada falla | Localizar un problema comparando los dos extremos | 9, 47, 48, 51 |
| Estado retenido y última voluntad | Saber si algo está vivo, incluso cuando se cae en silencio | 32, 33, 51 |
| Capas separadas | Cambiar el medio sin rehacer el formato, ni el formato sin rehacer la seguridad | 1, 46, 50, 51 |
| Puerta de enlace | Unir dos tecnologías, cada una con lo que le conviene | 39, 50, 51 |
| Vector de prueba | Comprobar que dos implementaciones coinciden con un caso de resultado conocido | CRC «123456789» (44); AES y HMAC (49); tramas de referencia (26, 47, 51) |
| Reservar por bloques | Persistir un contador sin desgastar la memoria flash ni repetir un valor tras un reinicio | 49 |
| Caer de manera segura | Que un fallo deje al sistema en un estado conocido (nodo fuera de línea, transmisor apagado, relé abierto) | 24, 26, 33, 51 |
06 · De la idea al producto
Buenas prácticas por etapa
| Etapa | Qué hacer | Error que evita |
|---|---|---|
| Requisitos | Escribirlos con números (distancia, velocidad útil, nodos, latencia, consumo, entorno, costo, seguridad) y separar lo obligatorio de lo deseable | Descubrir el requisito real cuando ya está instalado |
| Elección | Descartar por los obligatorios, comparar lo que queda, probar el mayor riesgo, escribir la decisión y qué la cambiaría (tema 50) | Elegir por costumbre o por el dato de catálogo más vistoso |
| Diseño | Separar medio, trama, control de errores, formato y seguridad en capas. Documentar una tabla de campos con unidades, escala y rango. Calcular los presupuestos de tiempo, de energía y de tráfico | Un diseño que no admite cambios y cuentas hechas «de memoria» |
| Implementación | Sin esperas bloqueantes; tipos de tamaño fijo; orden de bytes explícito; CRC y validación en cada recepción; búferes dimensionados con una cuenta; todo valor externo es sospechoso | Pérdidas de datos, desbordes, interpretaciones distintas entre plataformas |
| Prueba | Provocar cada falla (pérdida, corrupción, corte, reinicio, valor imposible, nodo caído); medir con instrumentos en el hardware y el cable reales; automatizar lo que se pueda | Un protocolo que nunca vio una falla y se rompe el primer día en campo |
| Seguridad | Modelo de amenazas, autenticación y contador en los mensajes de control, claves por dispositivo fuera del código, TLS verificado, firmware firmado | Una clave en el repositorio que abre todos los equipos |
| Producción | EMC y ESD, normativa de radio, conectores y cables adecuados, actualización remota con retroceso, identificación y claves cargadas por equipo, documentación | Un producto que anda en el laboratorio y falla en la certificación |
| Mantenimiento | Registros y contadores accesibles, alarmas por estado, rotación de claves y certificados, plan de fin de vida | Un sistema del que nadie sabe por qué falla, ni cómo arreglarlo |
La lista de verificación de la herramienta 5 convierte esta tabla en 21 preguntas para evaluar un proyecto propio: señala el área más débil y la primera práctica pendiente en ella. No mide la calidad del diseño, pero asegura que no se olvidó una categoría entera, que es la forma habitual de fracasar.
07 · Lo que viene después
El puente: de Arduino a un sistema embebido
Los programas del curso usan un bucle principal que se mantiene siempre en movimiento y máquinas de estados que no esperan. Es un diseño excelente para un dispositivo con una o dos funciones, y es el que se debe dominar primero. Un sistema embebido de verdad suma exigencias que ese diseño empieza a no poder cubrir: atender varias cosas con plazos distintos, gastar microamperios, sobrevivir años sin intervención, actualizarse a distancia y superar una certificación. Siete temas conectan lo ya visto con ese mundo.
1. Interrupciones y DMA: que los bytes no esperen al bucle
Un byte llega a una UART cada 87 µs a 115 200 baudios. Si el programa tiene que leerlo en ese tiempo, no puede hacer nada más. Los microcontroladores resuelven esto por hardware, en tres niveles: un FIFO de hardware que guarda varios bytes (128 en las UART del ESP32); una interrupción que detiene el programa un instante para mover el byte a un búfer en memoria; y el DMA (acceso directo a memoria), que mueve bloques de bytes de la UART a la memoria sin ocupar el procesador en absoluto. La biblioteca Serial que se usó en todo el curso es un búfer circular lleno por una interrupción, y es lo que hace posible el patrón «leer cuando se pueda».
El costo de una interrupción por byte es medible: si cada una dura 5 µs, a 115 200 baudios son 11 520 interrupciones por segundo, un 5,8 % del procesador solo en atender una UART. Con DMA, el procesador ve una interrupción por bloque o por línea. Las reglas de una rutina de interrupción son pocas y severas: corta (mover el dato y marcar un indicador), sin bloqueos (nada de delay, de printf ni de esperar un semáforo), con datos compartidos protegidos (variables volatile y secciones críticas, o mejor, una cola pensada para eso), y el trabajo largo se hace en el bucle o en una tarea. La herramienta 2 calcula la consecuencia práctica: cuánto tarda en desbordarse un búfer, es decir, cuánto puede tardar el programa en volver a leer.
2. Un sistema operativo de tiempo real: tareas, colas y prioridades
Cuando hay varias actividades con plazos distintos (atender el bus cada 10 ms, publicar en la red cada tanto, informar cada segundo), la máquina de estados única se vuelve difícil de razonar. Un sistema operativo de tiempo real (RTOS) como FreeRTOS, que ya corre debajo de Arduino en el ESP32, ofrece lo que falta: tareas (cada una con su bucle y su pila) que el planificador reparte el procesador según su prioridad, colas para pasar datos de una a otra sin compartir variables, semáforos y exclusión mutua para los recursos compartidos y temporizadores. La tarea de mayor prioridad que esté lista siempre se ejecuta; una de menor prioridad se interrumpe en cuanto una mayor la reclama.
| Aspecto | Bucle con máquinas de estados | RTOS con tareas |
|---|---|---|
| Cuándo conviene | Pocas funciones, plazos holgados, poca memoria | Varias actividades con plazos distintos, comunicación junto con una interfaz, red y sensores |
| Esperar | Con estado explícito y tiempos de vencimiento | Una tarea se bloquea en una cola o en un retardo, y el planificador usa el tiempo para otra |
| Plazos | El peor caso es el recorrido más largo del bucle | La tarea urgente tiene prioridad alta y se atiende en cuanto está lista |
| Memoria | Una sola pila, poca RAM | Una pila por tarea (2 a 4 kB cada una) y las estructuras del núcleo |
| Riesgos | Una función lenta retrasa todo lo demás | Condiciones de carrera, inversión de prioridades, bloqueos mutuos, pilas que se desbordan |
| Depuración | Determinista y fácil de seguir | Concurrente: hace falta registrar y medir (tema 48) |
Las dos formas no se excluyen: dentro de cada tarea de un RTOS sigue habiendo una máquina de estados, y la puerta de enlace del tema 51 se reescribe con tres tareas sin cambiar su lógica (sección 8). Las reglas que evitan los problemas de la concurrencia son tres: (1) cada dato tiene un solo dueño, la única tarea que lo escribe; (2) las tareas se comunican por colas y no por variables globales; (3) nadie espera un recurso para siempre: toda espera tiene un tiempo máximo y una salida. Y la pregunta clave de un diseño con prioridades es si todas las tareas cumplen siempre sus plazos. Con prioridades por tasa (el período menor, la mayor prioridad), una condición suficiente es que la utilización total esté por debajo de n(21/n − 1) (75,7 % con cuatro tareas, 69 % en el límite); el análisis exacto calcula el tiempo de respuesta en el peor caso de cada tarea, sumando la interferencia de las de mayor prioridad. Es la herramienta 3.
3. El tiempo: latencia, plazos y la edad del dato
Un sistema en tiempo real no es uno rápido, sino uno predecible: el peor caso está acotado. Se distingue un plazo duro (perderlo es una falla: el freno, la parada de emergencia) de uno blando (perderlo degrada la calidad: la actualización de un tablero). Cuatro números describen un camino: la latencia de una interrupción (cuánto tarda en empezar a atenderse), el jitter (cuánto varía), el tiempo de respuesta (de que ocurre un evento a que el sistema termina de reaccionar) y la edad de un dato (cuánto hace que se midió cuando alguien lo usa). En una red de sensores, casi toda la latencia son las esperas periódicas de la cadena (medir, sondear, refrescar) y no el tiempo de transmitir: la herramienta 4 lo muestra con la red del tema 51, donde un cambio tarda 25 s en verse en el peor caso aunque cada transmisión dure milisegundos. Mejorar la latencia es eliminar o acortar una espera periódica, no comprar una red más rápida.
4. La energía: dormir casi todo el tiempo
El tema 40 mostró que la duración de una batería sale de la corriente media: el sueño más la carga de cada ciclo repartida en el período. Un sistema embebido de bajo consumo organiza todo alrededor de eso: el procesador y la radio duermen salvo un instante; el despertar se programa por un temporizador, por un pin o por la llegada de un byte (algunas UART pueden despertar al procesador); se apagan los periféricos que no se usan; se agrupan las transmisiones para pagar una sola vez el costo de encender la radio; y se mide con un instrumento de microamperios, porque los consumos del sueño son del orden de lo que gasta un regulador, un LED o una resistencia mal elegida. Una placa de desarrollo (con su conversor USB y su regulador) gasta miliamperios aun dormida y no sirve para un nodo a pila (tema 40). La elección del chip pesa tanto como la de la tecnología (tema 50).
5. Un dispositivo que se recupera solo
Un dispositivo instalado en un tejado no tiene a nadie que lo reinicie. Las defensas de fondo son, en orden: un perro guardián (watchdog), un temporizador que reinicia el procesador si el programa no lo «alimenta» a tiempo (en un RTOS, cada tarea importante informa que está viva y una tarea supervisora decide); un detector de baja tensión que reinicia limpio cuando la alimentación cae; la causa del último reinicio registrada y publicada (reinicio por watchdog, por baja tensión, por falla de la pila), para que un reinicio no pase inadvertido; la vigilancia de la memoria (el uso máximo de la pila de cada tarea, que el programa de la sección 8 imprime, y la memoria libre, para detectar fugas); y un estado seguro definido al arrancar y ante cualquier fallo (el transmisor RS-485 en escucha, el relé abierto). Combinados con los contadores y el estado retenido de la comunicación, permiten saber desde lejos que algo falla y por qué.
6. Del prototipo a la producción
| Tema | Prototipo | Producto |
|---|---|---|
| Actualización | Cable USB y el computador | Actualización remota (OTA) con dos particiones de arranque, firma del firmware y retroceso automático si la nueva versión no arranca bien |
| Claves | Constantes en el código | Una clave por equipo, cargada en fábrica, con cifrado de la memoria flash y arranque seguro (tema 49) |
| Interferencia | Cables sueltos sobre una mesa | Diseño de EMC: planos de masa, filtros, ferritas; protección contra descargas (diodos TVS) en cada conector que sale del equipo, y aislación en los buses largos (RS-485, CAN) |
| Radio | Un módulo de desarrollo | Un módulo precertificado, o la certificación del equipo (CE, FCC), con su antena y su potencia; las reglas de la banda (ciclo de trabajo, canales) |
| Fabricación | Una unidad armada a mano | Un banco de prueba que carga el firmware, las claves y la identidad de cada equipo, y verifica sus comunicaciones |
| Documentación | El código y la memoria del autor | Esquemas, tabla de campos, notas de decisión, vectores de prueba, manual de instalación y de diagnóstico |
| Ciclo de vida | Hasta que funcione | Disponibilidad de los chips a diez años, soporte, rotación de claves y plan de retiro |
7. Probar de verdad: calidad del software de comunicaciones
La parte más cara de un protocolo es el análisis de los bytes que llegan, y es también la más fácil de probar sin hardware: un decodificador de tramas es una función pura. Se compila en una computadora y se prueba con vectores de referencia (las tramas del tema 47 con su CRC), con datos corruptos (cada bit de una trama invertido, uno por uno, como en el modelo del tema 48) y con basura al azar (fuzzing: millones de entradas aleatorias que no deben producir una caída, un bucle infinito ni una escritura fuera de límites). Después se prueba el conjunto con hardware en el lazo: la placa real conectada a un simulador de fallas que pierde, daña y retrasa tramas, como el canal simulado del tema 47. Y todo se automatiza para que se ejecute en cada cambio: el error que se descubre al día siguiente cuesta una fracción del que se descubre en el campo.
08 · Con el microcontrolador
Tareas y colas con FreeRTOS
El programa siguiente reproduce con tareas el patrón central de la puerta de enlace del tema 51: una tarea del bus produce una lectura cada 100 ms (el ritmo del sondeo), una tarea de red las consume y las publica, y una cola de 32 entradas las separa. Una tercera tarea, de mínima prioridad, informa el estado cada segundo y provoca un corte de la red entre los 4 y los 9 segundos para ver lo que ya se estudió con la herramienta 4 del tema 51: la cola se llena, la tarea del bus descarta lo más viejo sin esperar y, al volver la red, se vacía rápido. No necesita ningún hardware extra.
// Del bucle con máquinas de estados a tareas de FreeRTOS: el patrón de la puerta de enlace del tema 51.
// Una tarea produce lecturas a un ritmo fijo (el bus), otra las consume (la red) y una cola las separa.
// Se simula un corte de la red de 5 segundos para ver cómo se llena la cola y cómo se descarta lo más viejo.
struct Lectura { uint32_t n; uint32_t tms; };
const uint8_t CAPACIDAD = 32; // entradas de la cola
const uint32_t PERIODO_BUS_MS = 100; // el bus entrega una lectura cada 100 ms (10 por segundo)
QueueHandle_t cola;
TaskHandle_t manejadorBus, manejadorRed;
volatile uint32_t producidas = 0, descartadas = 0, consumidas = 0; // cada contador lo escribe una sola tarea
volatile bool redCaida = false; // lo escribe solo la tarea de informe
// Tarea del bus: prioridad alta, período exacto con vTaskDelayUntil (no acumula el error de cada vuelta).
void tareaBus(void *) {
TickType_t ultimo = xTaskGetTickCount();
for (;;) {
Lectura l = { ++producidas, millis() };
if (xQueueSend(cola, &l, 0) != pdTRUE) { // cola llena: no se espera, se descarta la más vieja
Lectura vieja;
xQueueReceive(cola, &vieja, 0);
xQueueSend(cola, &l, 0);
descartadas++;
}
vTaskDelayUntil(&ultimo, pdMS_TO_TICKS(PERIODO_BUS_MS));
}
}
// Tarea de red: prioridad menor. Con la red caída no consume; con la red disponible publica a unas 200 por segundo.
void tareaRed(void *) {
for (;;) {
if (redCaida) { vTaskDelay(pdMS_TO_TICKS(100)); continue; }
Lectura l;
if (xQueueReceive(cola, &l, pdMS_TO_TICKS(200)) == pdTRUE) {
consumidas++;
vTaskDelay(pdMS_TO_TICKS(5)); // aquí iría mqtt.publish(...)
}
}
}
// Tarea de informe: prioridad mínima. Provoca el corte entre los 4 y los 9 segundos.
void tareaInforme(void *) {
for (;;) {
vTaskDelay(pdMS_TO_TICKS(1000));
uint32_t seg = millis() / 1000;
redCaida = (seg >= 4 && seg < 9);
Serial.printf("t=%2lu s | red %s | producidas %3lu | consumidas %3lu | en cola %2u | descartadas %3lu | pila libre bus %u, red %u\n",
seg, redCaida ? "CAIDA" : "ok ", producidas, consumidas, (unsigned)uxQueueMessagesWaiting(cola), descartadas,
(unsigned)uxTaskGetStackHighWaterMark(manejadorBus), (unsigned)uxTaskGetStackHighWaterMark(manejadorRed));
}
}
void setup() {
Serial.begin(115200);
cola = xQueueCreate(CAPACIDAD, sizeof(Lectura));
// (nombre, pila en bytes en el ESP32, argumento, prioridad, manejador)
xTaskCreate(tareaBus, "bus", 2048, NULL, 3, &manejadorBus);
xTaskCreate(tareaRed, "red", 4096, NULL, 2, &manejadorRed);
xTaskCreate(tareaInforme, "informe", 3072, NULL, 1, NULL);
}
void loop() { vTaskDelay(portMAX_DELAY); } // el loop() ya no hace nada: trabajan las tareas
Qué hay que notar:
- El
loop()ya no hace nada (queda dormido para siempre): el trabajo está en tres tareas. En el ESP32, Arduino corre sobre FreeRTOS, de modo quexTaskCreateyxQueueCreateestán disponibles sin instalar nada. - Prioridades: el bus (3) por encima de la red (2) y de los informes (1). Si la red se atrasa o se bloquea publicando, no puede retrasar el sondeo, porque la tarea del bus la desaloja en cuanto está lista. Es exactamente la independencia que la puerta de enlace conseguía a mano con máquinas de estados.
- Período exacto:
vTaskDelayUntilmantiene el ritmo de 100 ms sin acumular el error de cada vuelta, a diferencia de undelay(100)que suma el tiempo de trabajo al período. - La cola no bloquea al productor:
xQueueSend(..., 0)con espera nula devuelve de inmediato si está llena, y entonces se descarta la lectura más vieja y se cuenta, como el anillo del tema 51. Un productor que esperara a una cola llena perdería su plazo. - El consumidor espera con un tiempo máximo (
pdMS_TO_TICKS(200)): nunca se bloquea para siempre. Mientras no hay datos, la tarea duerme y el procesador queda libre. - Cada contador tiene un solo dueño:
producidasydescartadaslas escribe el bus,consumidasla red yredCaidael informe. Sin dueños compartidos no hacen falta exclusiones mutuas. - El informe imprime la marca de agua de la pila de cada tarea (
uxTaskGetStackHighWaterMark): lo que sobra de la pila en el peor momento. Si se acerca a cero, hay que agrandar la pila antes de que se desborde y corrompa la memoria. - Lo que se espera ver por el monitor serie: unas 10 lecturas producidas por segundo; hasta el segundo 4, la cola casi vacía; durante el corte (segundos 4 a 9), la cola sube hasta 32 y, desde el segundo 7 aproximadamente,
descartadascrece de a una por lectura hasta unas 18 al final del corte (50 lecturas producidas durante el corte contra 32 que caben); a partir del segundo 9,consumidasse recupera a unas 200 por segundo y la cola se vacía en menos de un segundo.
09 · Analogía con programación
Las cuentas del puente en Python
Las cuatro cuentas del puente caben en pocas líneas de Python: el error de velocidad de una UART según su divisor, el tiempo que tarda en desbordarse un búfer, el tiempo de respuesta en el peor caso de varias tareas con prioridades por tasa y la latencia de punta a punta de un cambio. Con los valores de las herramientas del laboratorio:
Python en tu navegador. Los bloques son editables: cambiá los valores y presioná «Ejecutar Python». La primera vez tarda unos segundos en cargar.
import math
def error_uart(reloj_hz, baudios, divisor=16):
"""Velocidad real de una UART tipo AVR (UBRR = reloj / (divisor × baudios) − 1) y su error en %."""
ubrr = round(reloj_hz / (divisor * baudios)) - 1
real = reloj_hz / (divisor * (ubrr + 1))
return ubrr, real, (real - baudios) / baudios * 100
def desborde_ms(baudios, capacidad, bits=10):
"""Cuánto tarda en llenarse un búfer de recepción si nadie lo vacía."""
return capacidad * bits / baudios * 1000
def respuestas(tareas):
"""Tiempo de respuesta en el peor caso de cada tarea, con prioridad por tasa (período menor = prioridad mayor).
tareas: [(nombre, período en ms, tiempo de ejecución en ms)]. El plazo de cada tarea es su período."""
orden = sorted(tareas, key=lambda t: t[1])
salida = {}
for i, (nombre, periodo, ejecucion) in enumerate(orden):
r = ejecucion
while True:
nuevo = ejecucion + sum(math.ceil(r / tj) * cj for _, tj, cj in orden[:i]) # interferencia de las de mayor prioridad
if nuevo == r or nuevo > periodo:
r = nuevo
break
r = nuevo
salida[nombre] = r
return salida
def latencia_s(medicion, sondeo, bus_ms, publicacion_ms, red_ms, panel):
"""Peor caso y caso medio de la latencia de un cambio, de que ocurre a que se ve en el panel."""
fijo = (bus_ms + publicacion_ms + red_ms) / 1000
return medicion + sondeo + fijo + panel, medicion / 2 + sondeo / 2 + fijo + panel / 2
print("UART a 16 MHz:")
for baudios, divisor in ((9600, 16), (115200, 16), (115200, 8), (230400, 16)):
ubrr, real, error = error_uart(16_000_000, baudios, divisor)
print(f" {baudios:>6} baudios, ÷{divisor:<2}: UBRR {ubrr:>3}, real {real:>9.1f}, error {error:+.2f} %")
print(f"Búfer de 64 bytes: a 115200 se llena en {desborde_ms(115200, 64):.1f} ms; a 9600, en {desborde_ms(9600, 64):.1f} ms")
print(f"A 115200 llegan {30 / 1000 * 115200 / 10:.1f} bytes en 30 ms: un delay(30) con 64 bytes pierde {30 / 1000 * 115200 / 10 - 64:.0f}")
tareas = [("bus", 10, 2), ("red", 50, 10), ("sensor", 100, 20), ("informe", 1000, 50)]
utilizacion = sum(c / t for _, t, c in tareas)
n = len(tareas)
print(f"Tareas: utilización {utilizacion:.0%}, cota de tasa monótona {n * (2 ** (1 / n) - 1):.1%}")
print(" respuestas en el peor caso (ms):", respuestas(tareas))
mas_carga = [("bus", 10, 2), ("red", 50, 25), ("sensor", 100, 20), ("informe", 1000, 50)]
print(f" con la tarea de red en 25 ms ({sum(c / t for _, t, c in mas_carga):.0%}):", respuestas(mas_carga))
peor, medio = latencia_s(10, 10, 132, 20, 100, 5)
print(f"Latencia de un cambio: peor caso {peor:.2f} s, promedio {medio:.2f} s")
peor, medio = latencia_s(0, 10, 132, 20, 100, 5)
print(f" si el nodo mide al recibir la consulta: peor caso {peor:.2f} s, promedio {medio:.2f} s")
peor, medio = latencia_s(0, 1, 132, 20, 100, 0)
print(f" con sondeo de 1 s y panel por suscripción: peor caso {peor:.2f} s, promedio {medio:.2f} s")
Resultado: a 16 MHz, 9600 baudios da UBRR 103, 9615,4 baudios reales y +0,16 %; 115 200 en modo normal, UBRR 8, 111 111,1 y −3,55 %; con doble velocidad (÷8), UBRR 16, 117 647,1 y +2,12 %; y 230 400, UBRR 3, 250 000 y +8,51 %, que no funciona. Un búfer de 64 bytes se desborda en 5,6 ms a 115 200 baudios y en 66,7 ms a 9600; a 115 200 llegan 345,6 bytes en 30 ms, y un delay(30) con 64 bytes pierde 282. Las cuatro tareas del ejemplo (bus de 10 ms que ejecuta 2, red de 50 ms que ejecuta 10, sensor de 100 ms que ejecuta 20 e informe de 1000 ms que ejecuta 50) usan 65 % del procesador, por debajo de la cota de 75,7 %, y sus tiempos de respuesta en el peor caso son {'bus': 2, 'red': 14, 'sensor': 38, 'informe': 150} ms, todos muy dentro de sus plazos. Con la tarea de red en 25 ms (95 %): {'bus': 2, 'red': 33, 'sensor': 88, 'informe': 500}, que todavía cumple aunque la prueba simple no lo garantizaba. La latencia de un cambio es de 25,25 s en el peor caso y 12,75 s en promedio; si el nodo mide al recibir la consulta, 15,25 y 7,75 s; y con sondeo de 1 s y un panel por suscripción, 1,25 s y 0,75 s.
Tres lecciones. Primera: un divisor entero engaña; las velocidades «estándar» no siempre se generan con exactitud, y el error de cada extremo se suma. Segunda: la utilización sola no decide: un sistema con el 95 % del procesador ocupado puede ser planificable (aquí lo es) y otro con el 93 % (una tarea de 5 ms que ejecuta 2,5 y otra de 7 ms que ejecuta 3) no cumplir; el análisis del tiempo de respuesta sí decide. Tercera: la latencia son las esperas, no las transmisiones: 25 s de peor caso, de los cuales apenas 0,25 s son bus, cola y red.
10 · Exploración interactiva
Laboratorio: baudios, búfer, tareas, latencia y verificación
El laboratorio tiene cinco herramientas, una por cada cuenta del puente hacia los sistemas embebidos. La primera calcula el error de velocidad que introduce el divisor de un reloj. La segunda, cuánto tarda en desbordarse un búfer de recepción. La tercera comprueba si un conjunto de tareas con prioridades cumple sus plazos. La cuarta calcula la latencia de un cambio en una cadena de sensado. La quinta es una lista de verificación con la que se evalúa un proyecto propio.
1. Error de velocidad según el divisor
Escribí el reloj y la velocidad.
2. Desborde de un búfer de recepción
Escribí la velocidad y la latencia.
3. Planificabilidad de tareas (tasa monótona)
Escribí los períodos y los tiempos de ejecución.
4. Latencia de un cambio, de punta a punta
Escribí los períodos y los retardos.
5. Lista de verificación de un proyecto
Marcá solo lo que está hecho y probado.
Marcá las prácticas cumplidas.
En la herramienta 1, los modos AVR calculan UBRR = round(reloj ÷ (divisor × velocidad)) − 1; el modo fraccionario usa un divisor con cuatro bits de fracción. En la 2, el desborde se calcula suponiendo que el programa no lee nada durante la latencia. En la 3, las tareas tienen prioridad por tasa (el período menor, la mayor), el plazo de cada una es su período y los tiempos de respuesta se calculan con la iteración del peor caso. En la 4, cada espera periódica aporta su período completo al peor caso y la mitad al promedio. En la 5, las prácticas se agrupan en seis áreas.
Recorrido guiado
- En la herramienta 1, con 16 MHz y 115 200 baudios en modo normal: UBRR 8, 111 111,1 baudios reales, error de −3,55 % («peligroso»). Con doble velocidad: UBRR 16, 117 647,1 y +2,12 % («aceptable»). Con 230 400: UBRR 3, 250 000 y +8,51 % (no funciona). Con 9600: +0,16 %. Con un cristal de 7,3728 MHz: 115 200 sale con error 0,00 %. Con 80 MHz y el modo fraccionario: error de +0,00 %. Con 9600 y un 2 % de error en el otro extremo: 2,16 % de desajuste total.
- En la herramienta 2, a 115 200 baudios con 30 ms sin atender y un búfer de 64: llegan 345,6 bytes, se desborda a los 5,56 ms, se pierden 281 y hace falta un búfer de 512. Con un búfer de 256: 22,2 ms y 89 perdidos. Con FIFO de 128, búfer de 256 y 10 ms: 115 bytes y ninguno perdido. A 9600 el mismo búfer de 64 aguanta 66,7 ms.
- En la herramienta 3, con los valores por defecto: 65 % de utilización, cota de 75,7 %, respuestas en el peor caso de 2, 14, 38 y 150 ms: planificable con holgura. Con la tarea 2 en 25 ms: 95 %, por encima de la cota, pero con respuestas de 33, 88 y 500 ms: planificable según el análisis exacto. Con la tarea 2 en 30 ms: 105 %, y la tarea 4 no llega a su plazo. Con dos tareas de 5 ms que ejecuta 2,5 y de 7 ms que ejecuta 3 (93 % de utilización): la segunda no cumple, aunque no se use todo el procesador.
- En la herramienta 4, con los valores del proyecto del tema 51: 25,3 s en el peor caso, 12,8 s en promedio, el eslabón más largo es la medición del nodo (10 s, 40 %). Sin medición periódica (el nodo mide al recibir la consulta): 15,3 s. Con sondeo de 1 s, sin medición periódica y sin refresco del panel: 1,25 s. Subir la red a 500 ms casi no cambia el resultado.
- En la herramienta 5, con todo en blanco: 0 de 21 («es un prototipo»). Marcando las 14 prácticas que cumple el proyecto del tema 51 (las de diseño, protocolo y robustez, y dos de pruebas): 14 de 21 (67 %), el área más débil es Seguridad (0 de 3), y la primera práctica pendiente es autenticar los mensajes de control. Con las 21 marcadas: «completo».
Desafío: llevar la red de sensores a un producto
Una empresa quiere vender la red del tema 51 como producto, con 8 a 30 nodos, mantenimiento remoto y una garantía de dos años. Con lo aprendido, el plan: (1) Requisitos y decisiones: reescribir los requisitos con números y volver a confirmar la elección de RS-485 (tema 50) con el cable real de cada instalación; la nota de decisión incluye qué hechos la cambiarían. (2) Tiempo: pasar la pasarela a tareas (sección 8) con prioridades por tasa y comprobar con la herramienta 3 que cumplen sus plazos con el peor caso (todos los nodos caídos, la red cortada, una publicación lenta); medir el tiempo real de cada tarea con el analizador. (3) Latencia: el cliente quiere ver una alarma en menos de 5 s: con la cadena actual son 25 s en el peor caso; el rediseño es que el nodo mida al recibir la consulta, que el sondeo sea de 2 s y que el panel reciba por suscripción: 2,25 s (herramienta 4), con el bus al 6,6 %. (4) Robustez del dispositivo: perro guardián por tarea, detector de baja tensión, causa del último reinicio publicada, marcas de agua de las pilas y estado seguro al arrancar. (5) Seguridad: TLS al broker con certificado por dispositivo, HMAC y contador en el bus (con una clave por nodo derivada de una maestra), firmware firmado con arranque seguro y los puertos de depuración cerrados; es el área en blanco de la lista de verificación. (6) Producción: placas con aislación y protección contra descargas (diodos TVS) en los conectores del bus, módulo de radio precertificado, un banco de prueba que carga el firmware, las claves y la identidad de cada equipo, y actualización remota con retroceso. (7) Calidad: pruebas del decodificador en una computadora con las tramas de referencia, con cada bit invertido y con basura al azar; hardware en el lazo con el canal simulado; y todo en cada cambio. (8) Mantenimiento: el panel con los contadores, las alarmas por nodo fuera de línea y por la última voluntad de la pasarela, y un plan de rotación de claves y certificados. Cada punto es una pieza del curso aplicada: por eso el curso termina en un proyecto y no en una teoría.
11 · El camino de acá en adelante
Por dónde seguir
| Ruta | Qué estudiar | Un proyecto para practicarla |
|---|---|---|
| Sistemas operativos de tiempo real | FreeRTOS o Zephyr: tareas, colas, semáforos, temporizadores, prioridades, análisis de plazos, bajo consumo con sueño por inactividad | La puerta de enlace del tema 51 con tareas y un perro guardián por tarea |
| Más protocolos de campo | Modbus TCP, CANopen y J1939, BACnet, PROFINET, EtherCAT, OPC UA | Una pasarela que lee Modbus RTU y CAN y publica en MQTT |
| Internet de las cosas | MQTT 5, CoAP, LwM2M, LoRaWAN con una red completa, Thread y Matter, BLE Mesh | Una red de sensores LoRaWAN con un servidor de red propio o de un proveedor |
| Seguridad aplicada | Infraestructura de claves, certificados por dispositivo, arranque seguro, elementos seguros, modelado de amenazas | Provisión de claves en fábrica y autenticación mutua con el broker |
| Electrónica y diseño de placas | Integridad de señal, terminación, EMC, protección contra descargas, aislación, diseño de PCB con una herramienta como KiCad | Una placa de nodo RS-485 con aislación y protecciones |
| Calidad y producción | Pruebas automáticas y en el lazo con hardware, integración continua de firmware, actualización remota, certificaciones | Un banco de pruebas que programa, prueba y registra cada nodo |
| Datos | Series temporales, paneles, alarmas, detección de anomalías, almacenamiento y retención | Un panel con Grafana sobre una base de series temporales alimentada por planta/# |
Tres consejos para cualquiera de las rutas. Leer las fuentes: las hojas de datos de los chips, los estándares (la RFC de un protocolo, la especificación de Modbus, de CAN o de Bluetooth) y el código de las bibliotecas que se usan; son más claros que casi cualquier resumen y dicen qué es obligatorio y qué es opcional. Construir con instrumentos: un analizador lógico económico cambia la forma de aprender, porque convierte lo que se supone en algo que se ve. Escribir lo que se decide: la nota de decisión de una página, con los números que la sostienen, enseña más que diez proyectos hechos sin pensar.
12 · Comprensión
Confusiones frecuentes
«Si funciona en la mesa, ya funciona»
En la mesa no hay ruido, ni distancia, ni cortes, ni años de uso. Los errores se descubren provocando las fallas: pérdida, corrupción, corte de energía, reinicio, valor imposible, nodo caído. Un diseño que nunca vio una falla no está probado.
«Un RTOS hace al sistema más rápido»
No: lo hace más ordenado y predecible. Agrega un costo (cambios de contexto, una pila por tarea) y permite razonar sobre plazos. Un sistema simple con un bucle y máquinas de estados es más rápido y más sencillo si alcanza. El RTOS se justifica cuando hay varias actividades con plazos distintos.
«Con el procesador libre al 30 %, siempre cumple sus plazos»
La utilización total no decide. Una tarea larga de período corto puede perder su plazo con mucho procesador libre (dos tareas que usan el 93 % pueden fallar), y otro conjunto al 95 % puede cumplir. El análisis del tiempo de respuesta en el peor caso, tarea por tarea, es el que dice la verdad.
«Para mejorar la latencia hay que comprar una red más rápida»
En una red de sensores, casi toda la latencia son las esperas periódicas (medir cada 10 s, sondear cada 10 s, refrescar cada 5 s), no el tiempo de transmitir. Subir la velocidad de la red no cambia el total; acortar o eliminar una espera sí.
«Un perro guardián tapa los errores del programa»
Es el último recurso, no la solución. Reinicia un programa colgado, pero hay que registrar la causa del reinicio y corregirla; un dispositivo que se reinicia cada hora «porque el perro guardián lo arregla» tiene un error que se está ocultando. El perro guardián debe supervisar cada tarea importante, no solo el bucle.
«La seguridad se agrega al final»
Se agrega al final solo lo que se diseñó desde el principio: el contador en la trama, la clave por dispositivo, el firmware firmado y los permisos del broker condicionan el formato, la producción y la actualización. Agregarla al final suele significar rehacer.
«Un prototipo que anda es un producto casi terminado»
Falta lo que no se ve funcionando: actualización remota, claves por equipo, interferencia, descargas, radio certificada, banco de pruebas, documentación y soporte durante años. Suele ser la mayor parte del trabajo.
«Ya aprendí los protocolos, no necesito más»
Aprendiste los principios que sostienen a todos: acuerdos, medios compartidos, errores, formatos, medición y seguridad. Los protocolos nuevos (y los que seguirán apareciendo) son combinaciones de las mismas ideas con otros números. Lo que hay que seguir ejercitando es el método: requisitos con números, cuentas, pruebas con fallas y notas de decisión.
13 · Práctica guiada
Predecí antes de comprobar
1. La velocidad de una UART a 8 MHz
Un AVR a 8 MHz debe hablar a 115 200 baudios con un ESP32 (error despreciable). ¿Funciona en modo normal? ¿Y con doble velocidad? ¿Qué cambiarías?
Ver solución
En modo normal: UBRR = round(8 000 000 / (16 × 115 200)) − 1 = round(4,34) − 1 = 3, velocidad real 125 000: +8,5 %, no funciona. Con doble velocidad: round(8,68) − 1 = 8, real 111 111: −3,55 %, peligroso (la mitad del margen total). Opciones: bajar a 9600 (UBRR 51, +0,16 %), o cambiar el cristal por uno de 7,3728 o 11,0592 MHz, que dan divisores exactos para todas las velocidades estándar, o usar un chip con divisor fraccionario.
2. Un búfer que se desborda
Una UART de un ESP32 recibe a 57 600 baudios, con un búfer de 256 bytes y el FIFO de 128. El programa actualiza una pantalla y no lee el puerto durante 100 ms. ¿Qué pasa? ¿Y si la actualización dura 20 ms?
Ver solución
A 57 600 baudios (10 bits por byte) llegan 5760 bytes por segundo. En 100 ms llegan 576, y la capacidad es de 256 + 128 = 384: se pierden 192 (se desborda a los 66,7 ms). En 20 ms llegan 115 bytes, que caben de sobra. La latencia máxima tolerable es de 66,7 ms: la actualización de la pantalla debe partirse en pasos más cortos o hacerse en una tarea de menor prioridad que no impida atender el puerto.
3. ¿Cumplen sus plazos?
Tres tareas: A de 20 ms que ejecuta 5; B de 50 ms que ejecuta 15; C de 100 ms que ejecuta 10. ¿Cuál es la utilización, la cota y el tiempo de respuesta de cada una?
Ver solución
U = 0,25 + 0,30 + 0,10 = 65 %, por debajo de la cota de 3 tareas, 3(21/3 − 1) = 78 %: planificable. Respuestas: A (la de mayor prioridad) = 5 ms; B = 15 + 5 = 20 ms (A la interrumpe una vez); C = 10 + 2·5 + 15 = 35 ms (A la interrumpe dos veces y B una). Todas muy por debajo de sus plazos (20, 50 y 100 ms).
4. Ver una alarma en 5 segundos
Con la red del tema 51 (medición de 10 s, sondeo de 10 s, panel de 5 s), una alarma tarda 25 s en verse en el peor caso. ¿Qué tres cambios la bajan de 5 s sin cambiar la velocidad de la red, y cuánto queda?
Ver solución
(1) Que el nodo mida al recibir la consulta (se elimina el término de 10 s). (2) Acortar el sondeo a 2 s: el bus pasa de 1,3 % a 6,6 % del tiempo (132 ms cada 2 s). (3) Que el panel reciba por suscripción en lugar de refrescar cada 5 s. Queda 0 + 2 + 0,25 + 0 = 2,25 s en el peor caso (1,25 s en promedio). Ningún cambio toca la red: son las esperas periódicas las que se acortan. Si la alarma debe ser todavía más rápida, el nodo la comunica sin esperar su turno, a costa de dejar de ser un esclavo puro.
5. Un nodo que se cuelga
La tarea de red se bloquea dentro de mqtt.connect() con un broker caído (hasta 15 s en la configuración por defecto). ¿Qué consecuencias tiene en un RTOS y en un bucle simple? ¿Cómo se mitiga?
Ver solución
En un bucle simple, todo se detiene 15 s: el sondeo, la lectura del bus y el desborde del búfer de la UART. En un RTOS, solo se bloquea la tarea de red: el planificador sigue ejecutando la del bus (de mayor prioridad), que descarta lo más viejo cuando se llena la cola. Se mitiga con un tiempo máximo corto (setSocketTimeout(2)), con reintentos y espera creciente, y con un perro guardián por tarea: si la de red no avisa que está viva en un tiempo razonable, se registra el hecho y se reinicia solo lo necesario.
6. Reconocer el patrón
Nombrá el patrón del catálogo que resuelve cada situación: (a) un nodo que contesta tarde a una consulta que ya expiró; (b) un nodo que cae sin avisar y el panel debe enterarse; (c) un contador que debe sobrevivir a un reinicio sin desgastar la flash; (d) una pasarela que debe seguir sondeando aunque se caiga el Wi-Fi.
Ver solución
(a) Consulta y respuesta con secuencia: la respuesta atrasada trae una secuencia vieja y se descarta. (b) Estado retenido y última voluntad: el broker publica el estado cuando se corta la conexión, y el estado de cada nodo se retiene. (c) Reservar por bloques: se guarda un techo cada N valores y se arranca desde él. (d) Búfer circular con descarte de lo más viejo, con la lectura y la publicación desacopladas por una cola.
7. ¿Por qué no se vende la placa de desarrollo?
Nombrá cuatro razones por las que un producto no puede usar la placa de desarrollo tal cual, aun si el programa funciona perfecto.
Ver solución
(1) Consumo: el conversor USB, el regulador lineal y los LED consumen miliamperios aun con el procesador dormido; un nodo a pila dura días. (2) Interferencia y descargas: sin planos de masa, filtros ni diodos de protección en los conectores, la placa falla frente a una descarga electrostática o un motor cercano, y no pasa las pruebas de EMC. (3) Certificación de radio: el módulo y la antena de una placa genérica no están certificados para vender el producto con la potencia y los canales de cada región. (4) Fabricación y seguridad: el programa y las claves se cargan por USB a mano y la memoria flash se puede leer; un producto necesita un banco de prueba, claves por equipo, arranque seguro y actualización remota.
8. Tu próximo paso
De las siete rutas de la sección 11, elegí una y escribí en cinco líneas: qué te interesa resolver, qué vas a estudiar primero, qué proyecto pequeño harías, qué número vas a calcular antes de construirlo y qué falla vas a provocar para probarlo.
Ver solución
No hay una respuesta única; sí una forma. Un ejemplo para la ruta de tiempo real: «Quiero que mi pasarela no se detenga cuando la red falla. Estudio FreeRTOS: tareas, colas y prioridades. Reescribo la puerta de enlace del tema 51 con tres tareas. Antes calculo con la planificabilidad de tareas que cumplen sus plazos (utilización y tiempos de respuesta). Pruebo cortando el Wi-Fi 3 minutos y comprobando que no se detiene el sondeo y que se cuenta lo que se descarta». Fijate que cada línea del ejemplo es un paso del método: un problema con un número, una cuenta previa, una construcción mínima y una falla provocada.
14 · Síntesis final
Ideas para llevarse
- El curso recorrió la comunicación entre dispositivos de abajo hacia arriba: bits y tiempos (UART, SPI, I²C, 1-Wire), distancia y ruido (RS-232, RS-485, Modbus, CAN), redes (Ethernet, IP, TCP, UDP, HTTP, MQTT, Wi-Fi, Bluetooth, BLE, LoRa y otras), significado y confiabilidad (tramas, direcciones, CRC, confirmaciones, formatos) y método (depurar, proteger, elegir, construir).
- Seis principios se repiten bajo todas las tecnologías: todo es acuerdo; el medio es compartido y el tiempo manda; el mundo es ruidoso y se supone que va a fallar; nada espera y todo se cuenta; la velocidad anunciada no es la útil; y cada capa protege su tramo, con la seguridad diseñada desde el principio.
- La elección de una tecnología es en buena parte mecánica si se hace en orden: requisitos con números, descartar lo que no cumple, comparar lo que queda, probar el mayor riesgo y escribir la decisión con lo que la cambiaría. El árbol de decisión resume los casos comunes; cuando no alcanza una tecnología, se usa una puerta de enlace.
- El catálogo de patrones (máquina de estados no bloqueante, trama con CRC, secuencia y reintentos, ventana de duplicados, búfer circular, validación de rangos, contadores, estado retenido, capas separadas, puerta de enlace, vectores de prueba) se reutiliza en cualquier protocolo. Reconocer el problema es reconocer el patrón.
- El puente hacia los sistemas embebidos: las interrupciones y el DMA sacan los bytes del camino del programa (un byte cada 87 µs a 115 200 baudios; un búfer de 64 bytes se desborda en 5,6 ms); un sistema operativo de tiempo real organiza varias actividades con prioridades, colas y plazos que se pueden verificar con el tiempo de respuesta en el peor caso; la energía se gestiona durmiendo casi todo el tiempo; y la latencia de punta a punta son las esperas periódicas de la cadena, no las transmisiones.
- Un dispositivo instalado se recupera solo (perro guardián, detector de baja tensión, causa del reinicio, estado seguro), se actualiza a distancia con firma y retroceso, lleva claves propias y supera las pruebas de interferencia y radio. El prototipo que funciona es una parte menor del camino al producto.
- La calidad se prueba, no se declara: el decodificador se prueba en una computadora con vectores, con cada bit invertido y con datos al azar; el conjunto, con hardware en el lazo y fallas provocadas; y todo en cada cambio. Los contadores de cada falla y los estados retenidos permiten saber desde lejos qué ocurre.
- Lo que sigue depende de lo que se quiera construir: tiempo real, más protocolos de campo, internet de las cosas, seguridad aplicada, diseño de placas, calidad y producción, o datos. En cualquiera de ellas sirven los mismos hábitos: leer las fuentes, medir con instrumentos, escribir lo que se decide y probar provocando las fallas.
Para cerrar
Un curso sobre comunicación entre dispositivos trata, en el fondo, de lo mismo que cualquier conversación: ponerse de acuerdo sobre cómo hablar, entenderse a pesar del ruido, no confundir lo que se dijo con lo que se entendió, y saber qué hacer cuando el otro no contesta. Los bits, los cables y los protocolos son la forma que toma esa conversación entre máquinas. Quien entiende por qué cada pieza existe puede leer la hoja de datos de un chip que todavía no se fabricó, depurar un enlace que nunca vio y diseñar uno propio con menos sorpresas.
El índice del curso queda disponible para volver a cualquier tema, y las herramientas interactivas, para seguir probando con otros números. Buena suerte con lo que construyas.