En WiFi, los bits viajan en ondas portadoras de alta frecuencia (2.4 GHz) muy rápidas pero frágiles. Si hay un muro, la onda rebota y muere. LoRa (Long Range), por su parte, utiliza una modulación llamada CSS (Chirp Spread Spectrum), inspirada en el canto de los delfines y murciélagos. La señal "barre" un rango de frecuencias (ej. de 902 MHz a 928 MHz en América), creando un Chirp (trino) que puede atravesar hormigón, selva y ruido electromagnético extremo, y ser escuchado kilómetros más allá, incluso si la señal es más débil que el ruido de fondo.
En la física no hay magia, solo intercambios (Trade-offs). Para llegar a 15 kilómetros con una simple batería, LoRa sacrifica la velocidad. Tarda casi 1 segundo entero en transmitir un minúsculo paquete de 50 bytes.
Debido a que LoRa utiliza bandas de radio libres (ISM, como 915 MHz), las leyes gubernamentales imponen un límite llamado Duty Cycle (Ciclo de Trabajo) del 1%. Esto significa que si tu chip transmite durante 1 segundo, la ley te prohíbe transmitir durante los siguientes 99 segundos. Enviar un JSON de 200 bytes por LoRa está matemáticamente prohibido. Aquí es donde nuestro Protocolo Binario Estricto de 21 bytes (Día 222) se convierte en tu mayor ventaja competitiva.
Circuito: Usaremos un módulo LoRaWAN pre-certificado con stack interno (Ej. RAK3172 o RN2903). Esto mantiene intacta nuestra arquitectura de Offloading del Día 233. El STM32 se conecta al módulo por UART y usa comandos AT. ¡Atención! Los comandos AT de LoRaWAN no aceptan JSON, **solo aceptan texto en formato Hexadecimal Puro**.
Ejercicio 1: Tu STM32 tiene la estructura de la venta de gas en binario puro (Día 222). Como no podemos usar las lentas funciones estándar de C para formatear *strings*, escribiremos nuestra propia y letal función *Bare-Metal* de Bin_To_Hex para convertir nuestra estructura de C en un String Hexadecimal, y la enviaremos por el módem LoRaWAN.
/**
* @file lorawan_driver.c
* @brief Offloading de Telemetría LPWAN con Conversión Hexadecimal Ultra-Rápida
*/
#include "stm32f401xe.h"
#include "protocolo_iot.h"
#include <stdint.h>
#include <stdbool.h>
extern void UART_Transmit(uint8_t* data, uint16_t length);
extern bool AT_Enviar_Comando(const char* cmd, uint32_t timeout);
// =======================================================
// HERRAMIENTA BARE-METAL: BINARIO A HEXADECIMAL
// =======================================================
/**
* @brief Convierte un bloque de bytes crudos a su representación Hex-String.
* No utiliza snprintf ni funciones lentas de stdlib. 10x más rápido.
* @param in_bin Puntero a la estructura C original
* @param in_len Tamaño de la estructura (sizeof)
* @param out_hex Puntero al buffer de salida (Debe ser mínimo in_len * 2 + 1)
*/
void Bin_To_Hex_String(const uint8_t* in_bin, uint16_t in_len, char* out_hex) {
const char lookup_hex[] = "0123456789ABCDEF";
for(uint16_t i = 0; i < in_len; i++) {
// Extraemos los 4 bits superiores (Nibble alto)
out_hex[i * 2] = lookup_hex[(in_bin[i] >> 4) & 0x0F];
// Extraemos los 4 bits inferiores (Nibble bajo)
out_hex[i * 2 + 1] = lookup_hex[in_bin[i] & 0x0F];
}
// Terminador Nulo de C
out_hex[in_len * 2] = '\0';
}
// =======================================================
// ENVÍO AL MÓDEM LORAWAN (Ejemplo RAK3172)
// =======================================================
/**
* @brief Empaqueta una venta y la dispara por el éter vía LoRaWAN
*/
void LoRaWAN_Enviar_Venta(uint32_t folio, float litros) {
// 1. Armamos la Trama Exacta de nuestra Arquitectura (Día 222)
// Recordemos que con #pragma pack(1), esto pesa 21 bytes.
Trama_Binaria_t trama;
trama.header.sync_word = FRAME_SYNC_WORD;
trama.header.comando = CMD_ENVIAR_VENTA;
trama.header.longitud = sizeof(Payload_Venta_t);
trama.payload.venta.folio_ticket = folio;
trama.payload.venta.litros_gas = litros;
trama.crc8 = Calcular_CRC8((uint8_t*)&trama, sizeof(Trama_Header_t) + trama.header.longitud);
// 2. Buffer para almacenar el Hexadecimal (El doble del tamaño original + 1 nulo)
char payload_hex[ (sizeof(Trama_Binaria_t) * 2) + 1 ];
// 3. Conversión de Silicio Puro (Zero-Overhead)
Bin_To_Hex_String((uint8_t*)&trama, sizeof(Trama_Binaria_t), payload_hex);
// 4. Armar el comando AT del módem LoRaWAN
// Sintaxis RAK3172: AT+SEND=<Puerto>:<Datos_Hex>
// Puerto 2 es nuestro puerto lógico para Ventas.
char comando_at[128];
uint16_t cmd_len = 0;
// Formado básico manualmente para evitar librerías pesadas si es posible
// Pero asumiendo que un sprintf básico es permitido para comandos de control
// El núcleo de la eficiencia fue la conversión del payload de datos en sí.
sprintf(comando_at, "AT+SEND=2:%s\r\n", payload_hex);
// 5. El Disparo a la Nube (Gasta menos de 40mA, a diferencia de los 2000mA de LTE)
// El módem encriptará el Hexadecimal internamente (AES-128) y lo enviará al aire.
AT_Enviar_Comando(comando_at, 5000);
}
Objetivo del día: Cobertura Rural y Despliegue de Ultra-Bajo Consumo (LPWAN).
Imagínate un escenario agrícola. El cliente tiene 50 tanques de almacenamiento de Gas LP esparcidos por una cordillera de 10 kilómetros. Ponerle un módem LTE a cada tanque implicaría pagar 50 tarjetas SIM mensuales y depender de paneles solares masivos porque el LTE devora la batería en 3 días. El costo logístico sería inviable.
Al dotar a tu máquina de telemetría **LoRaWAN**, eliminas a las operadoras telefónicas de la ecuación. Instalas una sola antena (Gateway) en el punto más alto del rancho o mina. Esta antena recibe los "chirps" de las 50 máquinas gratuitas y ella sola se encarga de subir todo por un único enlace de satélite o internet a AWS. Gracias a la conversión `Bin_To_Hex` desarrollada, tu STM32 empaqueta la venta en **21 bytes**, y el módem RAK3172 los lanza al aire en fracción de segundo, utilizando apenas 40mA. Una batería de litio primaria no-recargable en el tanque de Gas LP durará **10 años** sin intervención humana, emitiendo su nivel diariamente. Esto es la cúspide de la ingeniería de hardware escalable.
stdio.h (como sprintf dinámicos) en los datos críticos de telemetría de nuestro RTOS.