Una helada de madrugada puede quemar en pocas horas los almácigos de un invernadero, y casi siempre ocurre cuando nadie está mirando. Lo que necesitas es un sensor que mida temperatura y humedad toda la noche, que no dependa del WiFi de la casa (que rara vez llega hasta el fondo del terreno) y que funcione semanas con una batería pequeña. Esa combinación tiene nombre: un nodo LoRaWAN.
En esta guía vas a entender cómo se arma un nodo sensor con un ESP32-S3, un radio SX1262 (el módulo E22-900M22S) y un BME280, cómo se registra en una red LoRaWAN con un gateway y cómo llegan los datos a un panel web en Datacake. Además, vas a ver qué cambia al configurarlo para Chile, donde se usa el plan de frecuencias AU915 y no el US915 del proyecto original, y cómo aprovechar el punto de rocío que calcula el nodo para anticipar una helada.
Cómo funciona el sistema completo
El recorrido de un dato tiene cuatro saltos:
- El nodo despierta, lee el BME280 y calcula dos valores derivados: el punto de rocío y el déficit de presión de vapor (VPD).
- Empaqueta las cinco cifras en un mensaje de solo 11 bytes y lo transmite por radio LoRa.
- El gateway (en el original, un Dragino LPS8N de interior) recibe el paquete y lo reenvía por internet al servidor de red.
- Datacake actúa como servidor de red LoRaWAN (Datacake LNS), decodifica los bytes y los guarda en campos que puedes graficar.
Entre una transmisión y la siguiente, el ESP32-S3 entra en deep sleep. En las pruebas duerme 30 segundos; para uso real conviene subir a 15 minutos.

Por qué LoRaWAN y no WiFi
El WiFi consume decenas de miliamperes solo para mantener la asociación con el router, y su alcance práctico en exteriores es de unas decenas de metros. LoRa usa modulación por espectro ensanchado (chirp spread spectrum): cada bit se reparte en un barrido de frecuencia que el receptor puede reconocer incluso por debajo del nivel de ruido. Por eso un nodo LoRa alcanza cientos de metros a kilómetros con muy poca potencia. La contracara es el ancho de banda: mandas pocos bytes y cada cierto tiempo, justo lo que necesita un sensor ambiental.
LoRaWAN agrega la capa de red: cifrado de extremo a extremo con claves AES de 128 bits, contadores de tramas contra repetición y un servidor que administra muchos nodos a la vez.
El hardware, bloque por bloque
El autor original diseñó una PCB propia. Vale la pena recorrerla aunque tú uses una placa de desarrollo, porque cada bloque resuelve un problema que cualquier nodo a batería tiene.
Entrada USB-C y carga de la batería
El conector USB-C entrega 5 V para cargar la batería. Las líneas CC1 y CC2 van a tierra con resistencias de 5,1 kΩ: así un cargador USB-C reconoce la placa como consumidor y le entrega tensión. Sin esas resistencias, muchos cargadores USB-C simplemente no encienden la salida.

La carga la maneja un MCP73831, un cargador lineal para una celda de litio. Una resistencia de 2 kΩ en el pin PROG fija la corriente en unos 500 mA, y un LED en el pin STAT se enciende mientras carga.

Entre la batería y el resto del circuito hay un MOSFET canal P (AO3401A) que protege contra la conexión invertida de la batería. Es un detalle que se agradece en terreno, con las manos frías y poca luz.
Regulación a 3,3 V con buck boost
Una celda LiPo va de unos 4,2 V cargada a cerca de 3,0 V descargada. Un regulador lineal común (como el AMS1117) deja de regular cuando la batería baja de unos 4,3 V, así que el ESP32 quedaría alimentado con menos de 3,3 V buena parte del tiempo. El TPS63020 es un convertidor buck boost: reduce la tensión cuando la batería está llena y la eleva cuando se descarga, entregando 3,3 V estables durante toda la vida útil de la carga.

El ESP32-S3 y su programación automática
El ESP32-S3 lee el sensor, arma el mensaje y controla el radio. Trae WiFi y Bluetooth, que este proyecto no usa, pero que quedan disponibles si un día quieres configurar el nodo desde el celular.

La placa no tiene USB nativo hacia el ESP32: se programa con un conversor USB serial externo (tipo FTDI) por un header de 6 pines (3,3 V, DTR, TXD, RXD, RTS y GND). Dos transistores S8050 usan DTR y RTS para mover EN y GPIO0, de modo que el IDE pone el chip en modo bootloader sin que tengas que apretar BOOT y RESET a mano.

El radio LoRa E22-900M22S
El E22-900M22S lleva el chip SX1262 de Semtech y se comunica con el ESP32-S3 por SPI. Las líneas de control llevan resistencias en serie de 22 Ω para amortiguar reflexiones en flancos rápidos. TXEN y RXEN conmutan el camino de radiofrecuencia entre transmisión y recepción, BUSY avisa cuando el chip está ocupado y DIO1 genera las interrupciones.

| Señal del radio | GPIO del ESP32-S3 | Función |
|---|---|---|
| DIO2 | GPIO4 | Conectada, sin uso en este programa |
| DIO1 | GPIO5 | Interrupciones y eventos del radio |
| TXEN | GPIO6 | Activa el camino de transmisión |
| RXEN | GPIO7 | Activa el camino de recepción |
| BUSY | GPIO15 | Indica que el radio está ocupado |
| NRST | GPIO16 | Reinicia el radio |
| NSS / CS | GPIO10 | Selección del radio en el bus SPI |
| MOSI | GPIO11 | Datos SPI hacia el radio |
| SCK | GPIO12 | Reloj SPI |
| MISO | GPIO13 | Datos SPI hacia el ESP32-S3 |
El BME280 va por I2C con SDA en GPIO8 y SCL en GPIO9, con resistencias pull up de 4,7 kΩ a 3,3 V. Se conecta con cuatro cables: 3,3 V, GND, SDA y SCL.
Antena y batería
Antes de transmitir, atornilla la antena. Encender un radio LoRa sin antena puede dañar la etapa de potencia, porque la energía que no se irradia rebota hacia el chip. La antena tiene que ser de la banda correcta: para Chile, 915 MHz. El original alimenta todo con una LiPo de 3,7 V y 600 mAh, que se recarga por el USB-C (el LED rojo se enciende mientras carga).
Configurar el gateway y Datacake
El gateway
El gateway es el puente entre el radio y el internet. El original usa un Dragino LPS8N, que se conecta por WiFi o Ethernet y se configura desde su interfaz web. Los pasos clave son:
- En Network → WiFi, conecta el gateway a tu red y guarda con Save & Apply.
- En LoRaWAN → LoRaWAN, copia el Gateway EUI (el identificador del gateway, distinto del DevEUI del nodo).
- En Datacake, entra a Gateways → Add Gateway, pega el EUI y elige el plan de frecuencias. En Chile corresponde AU915; el original usa US915 FSB2 porque está en otra región.
- Datacake te muestra la dirección del servidor y el puerto (el original usa el UDP Packet Forwarder en el puerto 1700). Vuelve al gateway, elige Custom / Private LoRaWAN como proveedor, escribe esa dirección sin
https://y deja la subida y la bajada en el puerto que te indiquen. - En LoRa → LoRa, selecciona el plan AU915 y la misma sub banda que configures en Datacake y en el nodo.
Si el gateway aparece en verde (Online) después de unos minutos, la conexión funciona. Si no, revisa en el gateway el registro LogRead → LoRa Log: los mensajes PULL_ACK received repetidos indican que el servidor le está respondiendo.
Registrar el nodo
En Datacake, Devices → Add Device → LoRaWAN → New Product. Elige Datacake LNS como servidor de red y completa:
| Campo | Qué poner |
|---|---|
| DevEUI | Identificador hexadecimal de 16 caracteres del nodo; el mismo va en el programa |
| AppEUI / JoinEUI | 0000000000000000, igual que en el programa |
| AppKey | Clave privada de 32 caracteres hexadecimales; la misma va en APP_KEY |
| Frecuencia | AU915, con la misma sub banda del gateway |
| Clase | Class A |
La activación es OTAA (Over The Air Activation) con LoRaWAN 1.0: el nodo pide unirse a la red, el servidor verifica su clave y le entrega claves de sesión nuevas. Escribe los identificadores sin espacios ni prefijo 0x y conserva los ceros iniciales. Nunca publiques tu AppKey en capturas ni en repositorios.
Hasta que subas el programa, el dispositivo va a decir Last Update: Never. Es normal.
El programa
Se programa desde el Arduino IDE con el paquete de placas de Espressif, eligiendo ESP32S3 Dev Module. Instala desde el gestor de librerías:
- RadioLib (versión de referencia 7.3.0): maneja el SX1262 y toda la pila LoRaWAN.
- Adafruit BME280 Library, Adafruit Unified Sensor y Adafruit BusIO.
Wire, SPI y Preferences ya vienen con el paquete del ESP32.
Este es el bloque de configuración del programa original. Es lo único que tienes que tocar:
// ============================================================================
// 1. USER SETTINGS
// ============================================================================
constexpr uint32_t SLEEP_SECONDS = 30; // 900 = 15 minutes; 30 for testing
constexpr uint32_t RETRY_BASE_SECONDS = 60;
constexpr uint32_t RETRY_MAX_SECONDS = 3600;
constexpr uint32_t FAULT_SLEEP_SECONDS = 3600;
constexpr uint32_t WATCHDOG_SECONDS = 45;
constexpr uint32_t SERIAL_BAUD = 115200;
constexpr uint16_t I2C_TIMEOUT_MS = 50;
constexpr uint32_t MEASUREMENT_TIMEOUT_MS = 300;
constexpr uint8_t LOCAL_RETRIES = 3;
constexpr uint8_t MAX_UPLINK_ERRORS_BEFORE_REJOIN = 3;
constexpr uint8_t LORA_SUB_BAND = 2;
constexpr uint8_t UPLINK_DATA_RATE = 1;
constexpr uint8_t FPORT = 10;
constexpr size_t PAYLOAD_SIZE = 11;
constexpr float TCXO_VOLTAGE = 1.8f;
constexpr size_t MIN_FREE_HEAP = 20000;
static_assert(SLEEP_SECONDS >= 1 && SLEEP_SECONDS <= 86400, "Sleep must be 1..86400 seconds");
// Preserve this namespace when updating the same device identity.
const char NVS_NAMESPACE[] = "dc_test10";
const char NONCE_KEY[] = "nonces";
// ============================================================================
// 2. EXISTING PCB PIN CONNECTIONS
// ============================================================================
constexpr uint8_t I2C_SDA = 8, I2C_SCL = 9;
constexpr uint8_t LORA_DIO1 = 5, LORA_TXEN = 6, LORA_RXEN = 7;
constexpr uint8_t LORA_CS = 10, LORA_MOSI = 11, LORA_SCK = 12, LORA_MISO = 13;
constexpr uint8_t LORA_BUSY = 15, LORA_RST = 16;
constexpr uint8_t LORA_DIO2_UNUSED = 4;
// DIO2 is connected on the PCB but must remain an ESP32 INPUT.
// ============================================================================
// 3. YOUR DATACAKE DEVICE CREDENTIALS
// ============================================================================
// Replace these placeholders. Use the same byte order as Datacake.
const uint64_t JOIN_EUI = 0x0000000000000000ULL;
const uint64_t DEV_EUI = 0x0000000000000000ULL;
const uint8_t APP_KEY[16] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
const LoRaWANBand_t REGION = US915;
Para Chile, los cambios son:
REGION = US915pasa aAU915, que RadioLib trae definido.LORA_SUB_BANDtiene que coincidir con la sub banda configurada en el gateway y en Datacake.DEV_EUI,JOIN_EUIyAPP_KEYcon tus credenciales de Datacake. Cada par de caracteres hexadecimales de la clave es un byte del arreglo, en el mismo orden.SLEEP_SECONDS = 900para uso continuo (unas 96 lecturas diarias). Revisa cuántos datos permite tu plan de Datacake.
Lo que hace el programa por dentro
El ciclo normal es: restaurar la sesión, medir, transmitir, esperar las dos ventanas de recepción (RX1 y RX2) que exige la Clase A y dormir. Dos detalles de diseño explican por qué el código es más largo de lo que esperarías:
- La sesión vive en la memoria RTC. La memoria RTC del ESP32 sobrevive al deep sleep, así que el nodo guarda ahí sus claves de sesión y contadores, protegidos con un CRC. Al despertar no tiene que volver a unirse a la red, lo que ahorra energía y tiempo de aire.
- El DevNonce se guarda en la flash. Cada solicitud de unión lleva un número (el DevNonce) que el servidor no acepta dos veces. Si el nodo se reinicia y repite un número ya usado, el servidor lo rechaza para siempre. Por eso el programa reserva el siguiente número en la flash antes de pedir la unión, y por eso no debes activar Erase All Flash Before Sketch Upload en las cargas siguientes ni cambiar
NVS_NAMESPACEpara la misma identidad.
Además trae watchdog, reintentos con espera creciente y recuperación del bus I2C si el sensor se cuelga. Abre el monitor serie a 115200 baudios para ver la unión, las sesiones restauradas y cada envío.
El decodificador en Datacake
El nodo manda 11 bytes por el puerto 10 (FPORT). En Datacake, el decodificador del producto convierte esos bytes en temperatura, humedad, presión, punto de rocío y VPD, y cada valor se guarda en su propio campo. Con eso armas tarjetas con el último valor y gráficos con la historia.
La alerta de helada: el ángulo para un invernadero chileno
El punto de rocío que calcula el nodo es la pieza clave. Cuando la temperatura del aire baja y se acerca al punto de rocío, el vapor se condensa y libera calor; con aire seco, en cambio, la temperatura cae sin freno y aparece la helada negra, la que no deja escarcha visible pero quema los tejidos de la planta. En la zona central de Chile eso pasa en noches despejadas de otoño y primavera.
Una regla práctica para armar la alerta en Datacake:
- Aviso cuando la temperatura baja de 3 °C y la diferencia con el punto de rocío es mayor a 3 °C (aire seco, la temperatura puede seguir cayendo).
- Alarma cuando la temperatura baja de 1 °C.
Datacake permite crear reglas que envían un correo o un aviso cuando un campo cruza un umbral. Para estas alertas conviene que el nodo reporte cada 5 a 10 minutos durante la noche.
Ojo con la ubicación del sensor: mídelo a la altura de las plantas, protegido del sol directo y de la lluvia con una garita ventilada. Un BME280 al sol puede marcar varios grados de más.
Errores comunes
- El nodo no se une a la red. Revisa que región y sub banda sean las mismas en el nodo, el gateway y Datacake. Es la causa número uno.
- El gateway está en verde pero no llegan datos. Revisa el DevEUI y la AppKey: un solo carácter cambiado basta para que el servidor descarte la solicitud.
- El sensor no aparece. El BME280 puede tener dirección 0x76 o 0x77 según el módulo; si el programa no lo encuentra, revisa cuál usa el tuyo. Revisa también que va a 3,3 V y no a 5 V.
- Alcance menor al esperado. Sube la antena del gateway lo más alto posible y evita estructuras metálicas cerca del nodo. En un invernadero, el plástico casi no atenúa la señal, pero los perfiles metálicos sí.
Variantes y mejoras
- Medir el suelo además del aire. Agrega un sensor capacitivo de humedad de suelo a una entrada analógica del ESP32-S3 y suma 2 bytes al mensaje; así sabes también cuándo regar.
- Un panel solar pequeño. Con un panel de 5 a 6 V y el mismo circuito de carga, el nodo puede funcionar todo el año sin que vuelvas a sacarlo para cargarlo.
- Varios nodos para comparar. Uno dentro y otro fuera del invernadero te muestran cuántos grados te está ganando la cubierta en una noche de helada, y si conviene poner una manta térmica.
Personalización para Chile
En Chile consigues todo lo necesario en MechatronicStore:
- Placa LoRaWAN ESP32 S3 SX1262 Display (SKU X5-6V1): reemplaza la PCB propia del original. Trae el mismo par de chips (ESP32-S3 y SX1262), cargador de batería y conector de antena, así que el programa se adapta cambiando solo la tabla de pines.
- Sensor BME280 temperatura humedad y presión barométrica 3.3V I2C (SKU GR1-10): el sensor del proyecto, en su versión I2C.
- Seed Studio Antena 915MHz 2.6dBi SMA LoRa (SKU F-312): antena de la banda correcta para AU915.
- Batería LiPo 852540 3.7V 600mAh (SKU GE1-11): la misma capacidad que usa el original.
- Interfaz Conversor USB Serial TTL FT232BL FTDI USB C (SKU B-311): para programar la PCB original por su header de 6 pines. Con la placa de desarrollo no hace falta.
El gateway Dragino LPS8N no está en el catálogo. Si en tu zona hay cobertura de una red comunitaria como The Things Network, puedes usarla en vez de montar un gateway propio.
Recursos
- Tutorial original (inglés): DIY ESP32 LoRaWAN Sensor Node for Environmental Monitoring, en el que se basa esta guía.
- Librería del radio: RadioLib
- Librería del sensor: Adafruit BME280 Library
- Plataforma: Datacake
Versión chilena con componentes en stock local en MechatronicStore.









