Objetivo y caso de uso
Qué construirás: Un nodo de microclima LoRaWAN utilizando Arduino MKR WAN 1310, BME680 y DS18B20 para medir y transmitir datos ambientales en agricultura.
Para qué sirve
- Monitoreo de temperatura y humedad del suelo mediante el sensor BME680.
- Medición de la temperatura del aire utilizando el sensor DS18B20.
- Transmisión de datos en tiempo real a través de LoRaWAN para análisis remoto.
- Optimización del riego basado en datos ambientales.
- Integración con plataformas de gestión agrícola para visualización de datos.
Resultado esperado
- Transmisión de datos cada 15 minutos con una latencia menor a 5 segundos.
- Precisión de medición de temperatura de ±0.5 °C y humedad de ±3%.
- Consumo de energía del nodo menor a 100 mA durante la transmisión.
- Capacidad de enviar hasta 10.000 paquetes de datos por mes.
- Alertas automáticas si los parámetros ambientales superan umbrales críticos.
Público objetivo: Ingenieros agrónomos y desarrolladores de IoT; Nivel: Avanzado
Arquitectura/flujo: Sensor BME680 y DS18B20 -> Arduino MKR WAN 1310 -> Transmisión LoRaWAN -> Plataforma de gestión.
Nivel: Avanzado
Prerrequisitos
- Sistemas operativos probados:
- Ubuntu 22.04 LTS (amd64)
- Windows 11 23H2 (64-bit)
-
macOS 14 Sonoma (Apple Silicon o Intel)
-
Toolchain exacta (línea de comandos, sin IDE gráfico):
- Arduino CLI 1.1.1
- Core “Arduino SAMD Boards (32-bits ARM Cortex-M0+)” 1.8.14
-
Librerías Arduino (versiones probadas y fijadas para reproducibilidad):
- MKRWAN 1.1.0
- Adafruit BME680 Library 2.0.2
- Adafruit BusIO 1.14.5 (dependencia de Adafruit BME680)
- OneWire 2.3.7
- DallasTemperature 3.11.0
-
Cuenta y aplicación en red LoRaWAN (The Things Stack v3 o compatible):
- Región/frequency plan (ejemplos): EU868, US915, AU915, AS923, etc.
-
Dispositivo dado de alta en la aplicación (OTAA):
- DevEUI (lo ideal: leerlo del módem y registrarlo)
- JoinEUI/AppEUI
- AppKey
-
Hardware y electricidad:
- Conocimientos de 3.3 V lógicos (MKR WAN 1310 NO tolera 5 V en GPIO).
-
Sondas y herramientas:
- Multímetro para verificación de 3.3 V y continuidad.
- Resistencia 4.7 kΩ para pull‑up en la línea 1‑Wire del DS18B20.
-
Recomendaciones:
- Editor de texto/código (p. ej., VS Code) con resaltado Arduino.
- Cable micro‑USB de datos (no solo carga).
Materiales
- Placa y sensores exactos:
- Arduino MKR WAN 1310 (ATSAMD21 + CMWX1ZZABZ LoRaWAN)
- Sensor ambiental BME680 (I2C, dirección típica 0x76)
- Sensor de temperatura DS18B20 (tubo o encapsulado TO‑92)
- Componentes y pasivos:
- 1 × resistencia 4.7 kΩ (pull‑up para línea de datos del DS18B20)
- Cables Dupont hembra‑macho
- Protoboard (opcional, recomendado)
- Alimentación:
- Cable micro‑USB
- Batería LiPo 3.7 V (opcional, para pruebas de campo)
- Red:
- Pasarela LoRaWAN operativa con cobertura, o acceso a la red pública (TTN) con gateway cercano.
Objetivo del proyecto: construir un nodo “lora‑agro‑microclima‑node” que mida microclima local (temperatura y humedad del aire, presión, resistencia de gas del BME680, temperatura de suelo con DS18B20) y envíe paquetes binarios por LoRaWAN (OTAA) a intervalos configurables.
Preparación y conexión
Instalación de Arduino CLI y toolchain
1) Instala Arduino CLI 1.1.1:
– Linux (x86_64):
– Descarga: https://github.com/arduino/arduino-cli/releases/download/1.1.1/arduino-cli_1.1.1_Linux_64bit.tar.gz
– Extrae y coloca en /usr/local/bin o en tu PATH.
– Windows 11:
– Descarga: arduino-cli_1.1.1_Windows_64bit.zip
– Añade la ruta de arduino-cli.exe al PATH del usuario.
– macOS 14:
– Descarga: arduino-cli_1.1.1_macOS_64bit.zip (o arm64 si aplica)
– Coloca arduino-cli en /usr/local/bin o en /opt/homebrew/bin.
2) Inicializa el entorno (primera vez):
– Crea el archivo de configuración si no existe:
– arduino-cli config init
3) Actualiza el índice e instala el core SAMD exacto:
– arduino-cli core update-index
– arduino-cli core install arduino:samd@1.8.14
4) Instala las librerías con versiones fijadas:
– arduino-cli lib install «MKRWAN@1.1.0»
– arduino-cli lib install «Adafruit BME680 Library@2.0.2»
– arduino-cli lib install «Adafruit BusIO@1.14.5»
– arduino-cli lib install «OneWire@2.3.7»
– arduino-cli lib install «DallasTemperature@3.11.0»
5) Verifica que el FQBN esté disponible:
– arduino-cli board listall | grep mkrwan
– Debe aparecer: arduino:samd:mkrwan1310
Conexiones eléctricas
- Consideraciones:
- Todos los módulos comparten GND.
- Alimentación a 3.3 V desde la MKR WAN 1310.
- La interfaz I2C del BME680 es 3.3 V; no uses 5 V.
- El DS18B20 es 3.0–5.5 V; úsalo a 3.3 V en este montaje.
- Añade pull‑up de 4.7 kΩ entre DATA (DS18B20) y 3.3 V.
Tabla de pines/puertos y cableado:
| Módulo/Sensor | Señal | Pin del sensor | Pin en MKR WAN 1310 | Notas |
|---|---|---|---|---|
| BME680 | VCC | VCC | 3V3 | 3.3 V regulados de la placa |
| BME680 | GND | GND | GND | Tierra común |
| BME680 | SDA (I2C) | SDA | SDA | Pin etiquetado SDA en cabecera MKR |
| BME680 | SCL (I2C) | SCL | SCL | Pin etiquetado SCL en cabecera MKR |
| DS18B20 | VDD | VDD | 3V3 | 3.3 V |
| DS18B20 | GND | GND | GND | Tierra común |
| DS18B20 | DATA | DQ | D2 | Línea 1‑Wire; requiere pull‑up de 4.7 kΩ a 3.3 V |
| Pull‑up | 4.7 kΩ | DQ—3.3 V | — | Conectar entre DQ (D2) y 3.3 V |
Notas:
– En placas MKR, los pines SDA y SCL están claramente etiquetados cerca de AREF. Usa la cabecera marcada (no confundir con D11/D12 en otros form factors).
– La dirección I2C del BME680 suele ser 0x76; si tu breakout usa 0x77, lo ajustaremos en el código.
Preparación de credenciales LoRaWAN
- Registra un dispositivo OTAA en tu aplicación (TTN o similar).
- Obtén:
- JoinEUI/AppEUI (16 hex dígitos)
- AppKey (32 hex dígitos)
- DevEUI: puedes leer el DevEUI del módem y registrar ese valor en la consola para evitar errores.
Comprobación de DevEUI desde el propio sketch (lo implementaremos); alternativamente, se puede usar un sketch corto de ejemplo MKRWAN para imprimirlo por Serial.
Código completo (Arduino/C++)
Estructura del proyecto en disco:
– lora-agro-microclima-node/
– lora-agro-microclima-node.ino
– secrets.h
El archivo secrets.h contendrá tus claves OTAA. No lo publiques.
secrets.h (plantilla)
Crea lora-agro-microclima-node/secrets.h con el siguiente contenido y reemplaza las X:
#pragma once
// Claves OTAA (hex ASCII, sin 0x ni espacios)
static const char APP_EUI[] = "0011223344556677"; // JoinEUI/AppEUI, 16 hex
static const char APP_KEY[] = "00112233445566778899AABBCCDDEEFF"; // 32 hex
// Opcional: si conoces el DevEUI de consola y quieres fijarlo,
// de lo contrario, lo leeremos del módem y lo mostraremos.
static const char DEV_EUI_OVERRIDE[] = ""; // deja vacío para usar el del módem
// Región LoRaWAN: usa uno de: EU868, US915, AU915, AS923, IN865, KR920
// Para compilar neutral, usamos define en código; aquí puedes documentar tu plan.
lora-agro-microclima-node.ino
El sketch implementa:
– Inicialización de sensores (BME680 por I2C, DS18B20 en D2).
– Inicialización de módem LoRaWAN (MKRWAN.h) y unión OTAA.
– Empaquetado binario compacto: T_air, RH, P, Gas, T_soil, VBAT.
– Ciclo con envío periódico y backoff si falla la red.
/*
lora-agro-microclima-node
Dispositivo: Arduino MKR WAN 1310 + BME680 + DS18B20
Toolchain: Arduino CLI 1.1.1, SAMD Core 1.8.14, MKRWAN 1.1.0,
Adafruit BME680 2.0.2, OneWire 2.3.7, DallasTemperature 3.11.0
*/
#include <Arduino.h>
#include <MKRWAN.h>
#include <Wire.h>
#include <Adafruit_BME680.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include "secrets.h"
// Región por compilación: ajusta EU868/US915/AU915/AS923/IN865/KR920
#ifndef LORA_REGION
#define LORA_REGION EU868
#endif
// Pines
static const uint8_t ONE_WIRE_PIN = 2; // D2 para DS18B20
// BME680: dirección por defecto 0x76 (ajusta a 0x77 si tu placa lo requiere)
Adafruit_BME680 bme; // I2C
OneWire oneWire(ONE_WIRE_PIN);
DallasTemperature ds18b20(&oneWire);
// Módem LoRa
LoRaModem modem;
// Configuración
static const uint32_t MEASUREMENT_INTERVAL_MS = 60UL * 1000UL; // 60 s (ajusta)
static const bool USE_CONFIRMED_UPLINK = false; // paquetes no confirmados por defecto
static const uint8_t FPORT = 1;
// Helpers de lectura de batería (ADC AREF = 3.3V, divisor interno del MKR)
float readBatteryVoltage() {
// En MKR WAN 1310, el pin ADC interno puede leer VBAT a través de un canal dedicado.
// Para simplificar, podemos usar analogRead(ADC_BATTERY) si está mapeado.
// Alternativa: si tu core no expone ADC_BATTERY, deja 0.0f o implementa lectura externa.
#ifdef ADC_BATTERY
uint16_t raw = analogRead(ADC_BATTERY);
float v = (raw / 1023.0f) * 3.3f * 2.0f; // si hay divisor 1:1 interno (ajustar según placa)
return v;
#else
return 0.0f; // placeholder si no está disponible
#endif
}
// Empaquetado binario: escalado fijo
// Layout (12 bytes):
// [0-1] T_air (°C * 100, int16)
// [2-3] RH (% * 100, uint16)
// [4-5] P (hPa * 10, uint16)
// [6-7] Gas (kΩ * 10, uint16) – recorte a 65535
// [8-9] T_soil (°C * 100, int16)
// [10-11] Vbat (mV, uint16)
uint16_t clamp_u16(int32_t v) {
if (v < 0) return 0;
if (v > 65535) return 65535;
return (uint16_t)v;
}
void packPayload(uint8_t* buf, size_t len,
float t_air, float rh, float p_hpa, float gas_ohms, float t_soil, float vbat) {
if (len < 12) return;
int16_t t_air_i16 = (int16_t)roundf(t_air * 100.0f);
uint16_t rh_u16 = clamp_u16(lroundf(rh * 100.0f));
uint16_t p_u16 = clamp_u16(lroundf(p_hpa * 10.0f));
float gas_kohm = gas_ohms / 1000.0f;
uint16_t gas_u16 = clamp_u16(lroundf(gas_kohm * 10.0f));
int16_t t_soil_i16 = (int16_t)roundf(t_soil * 100.0f);
uint16_t vbat_u16 = clamp_u16(lroundf(vbat * 1000.0f));
buf[0] = (uint8_t)(t_air_i16 >> 8);
buf[1] = (uint8_t)(t_air_i16 & 0xFF);
buf[2] = (uint8_t)(rh_u16 >> 8);
buf[3] = (uint8_t)(rh_u16 & 0xFF);
buf[4] = (uint8_t)(p_u16 >> 8);
buf[5] = (uint8_t)(p_u16 & 0xFF);
buf[6] = (uint8_t)(gas_u16 >> 8);
buf[7] = (uint8_t)(gas_u16 & 0xFF);
buf[8] = (uint8_t)(t_soil_i16 >> 8);
buf[9] = (uint8_t)(t_soil_i16 & 0xFF);
buf[10] = (uint8_t)(vbat_u16 >> 8);
buf[11] = (uint8_t)(vbat_u16 & 0xFF);
}
bool initBME680() {
if (!bme.begin(0x76)) {
// Intenta en 0x77
if (!bme.begin(0x77)) {
Serial.println(F("[BME680] No detectado en 0x76/0x77"));
return false;
}
}
// Configura oversampling y filtro
bme.setTemperatureOversampling(BME680_OS_8X);
bme.setHumidityOversampling(BME680_OS_2X);
bme.setPressureOversampling(BME680_OS_4X);
bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
// Habilita gas heater
bme.setGasHeater(320, 150); // 320°C durante 150 ms
return true;
}
bool readBME680(float& t, float& h, float& p_hpa, float& gas_ohms) {
// Realiza lectura forzada
if (!bme.performReading()) return false;
t = bme.temperature; // °C
h = bme.humidity; // %
p_hpa = bme.pressure / 100.0; // Pa -> hPa
gas_ohms = bme.gas_resistance; // ohmios
return true;
}
bool readDS18B20(float& t_soil) {
ds18b20.requestTemperatures();
float t = ds18b20.getTempCByIndex(0);
if (t == DEVICE_DISCONNECTED_C) return false;
t_soil = t;
return true;
}
bool loraJoinOTAA() {
Serial.println(F("[LoRa] Inicializando módem..."));
if (!modem.begin(LORA_REGION)) {
Serial.println(F("[LoRa] Error al iniciar el módem (begin)"));
return false;
}
// Habilita ADR
modem.setADR(true);
// Muestra DevEUI real y permite override si se desea
String devEUI = modem.deviceEUI();
Serial.print(F("[LoRa] DevEUI (módem): ")); Serial.println(devEUI);
if (strlen(DEV_EUI_OVERRIDE) == 16) {
Serial.print(F("[LoRa] Usando DEV_EUI_OVERRIDE: ")); Serial.println(DEV_EUI_OVERRIDE);
modem.setDevEUI(DEV_EUI_OVERRIDE);
}
// Configura AppEUI y AppKey
if (strlen(APP_EUI) != 16 || strlen(APP_KEY) != 32) {
Serial.println(F("[LoRa] APP_EUI/AppKey inválidos (tamaño)."));
return false;
}
// Intenta unión con reintentos exponenciales
const uint8_t MAX_TRIES = 6;
uint32_t backoff = 3000; // ms
for (uint8_t i = 1; i <= MAX_TRIES; ++i) {
Serial.print(F("[LoRa] joinOTAA intento ")); Serial.println(i);
if (modem.joinOTAA(APP_EUI, APP_KEY)) {
Serial.println(F("[LoRa] ¡Unión OTAA exitosa!"));
return true;
}
Serial.print(F("[LoRa] Fallo en join, esperando ")); Serial.print(backoff); Serial.println(F(" ms"));
delay(backoff);
backoff = min<uint32_t>(backoff * 2, 120000);
}
Serial.println(F("[LoRa] No se pudo unir tras varios intentos."));
return false;
}
bool loraSend(const uint8_t* payload, size_t len, uint8_t fport, bool confirmed) {
if (!payload || len == 0) return false;
int err = modem.beginPacket();
if (err <= 0) {
Serial.print(F("[LoRa] beginPacket err=")); Serial.println(err);
return false;
}
modem.write(payload, len);
// confirmed = true => uplink confirmado; false => no confirmado
int res = modem.endPacket(confirmed);
if (res > 0) {
Serial.print(F("[LoRa] Uplink OK, bytes=")); Serial.println(len);
// Cambia FPORT si la librería lo soporta por API; si no, envía en port por defecto
modem.setPort(fport); // en algunas versiones se fija antes de enviar; lo hacemos aquí por compatibilidad
return true;
} else {
Serial.print(F("[LoRa] Uplink FAIL, code=")); Serial.println(res);
return false;
}
}
void printHex(const uint8_t* buf, size_t len) {
for (size_t i = 0; i < len; ++i) {
if (buf[i] < 16) Serial.print('0');
Serial.print(buf[i], HEX);
}
}
void setup() {
Serial.begin(115200);
while (!Serial) { ; }
Serial.println(F("\n[lora-agro-microclima-node] Inicio"));
// Sensores
Wire.begin();
if (!initBME680()) {
Serial.println(F("[BME680] ERROR inicialización"));
} else {
Serial.println(F("[BME680] OK"));
}
ds18b20.begin();
Serial.print(F("[DS18B20] Dispositivos 1-Wire: "));
Serial.println(ds18b20.getDeviceCount());
if (!ds18b20.getAddress(NULL, 0)) {
Serial.println(F("[DS18B20] Atención: no se encontró dirección en índice 0 (puede seguir, pero verifique cableado)"));
}
// LoRa
if (!loraJoinOTAA()) {
Serial.println(F("[LoRa] No unido. Se reintentará más tarde."));
}
}
void loop() {
float t_air = NAN, rh = NAN, p_hpa = NAN, gas_ohms = NAN, t_soil = NAN;
bool ok_bme = readBME680(t_air, rh, p_hpa, gas_ohms);
bool ok_ds = readDS18B20(t_soil);
float vbat = readBatteryVoltage();
if (!ok_bme) Serial.println(F("[BME680] Lectura fallida"));
if (!ok_ds) Serial.println(F("[DS18B20] Lectura fallida"));
uint8_t payload[12];
// Valores por defecto si falla lectura
if (!ok_bme) { t_air = 0; rh = 0; p_hpa = 0; gas_ohms = 0; }
if (!ok_ds) { t_soil = 0; }
if (!(vbat > 0.1f)) vbat = 0.0f;
packPayload(payload, sizeof(payload), t_air, rh, p_hpa, gas_ohms, t_soil, vbat);
Serial.print(F("[Payload HEX] "));
printHex(payload, sizeof(payload));
Serial.println();
bool sent = loraSend(payload, sizeof(payload), FPORT, USE_CONFIRMED_UPLINK);
if (!sent) {
Serial.println(F("[LoRa] Reintentará unión y envío en próximo ciclo."));
// Intentar re-unirse si se perdió sesión
loraJoinOTAA();
} else {
// Opción: leer downlink en ventana RX (si librería lo expone)
if (modem.available()) {
Serial.print(F("[Downlink] "));
while (modem.available()) {
int b = modem.read();
if (b < 0) break;
if (b < 16) Serial.print('0');
Serial.print(b, HEX);
}
Serial.println();
}
}
// Espera
delay(MEASUREMENT_INTERVAL_MS);
}
Puntos clave del código:
– Inicialización BME680: oversampling, filtro y gas heater para lecturas estables.
– DS18B20 en D2 con OneWire; el pull‑up de 4.7 kΩ es obligatorio.
– LoRaWAN: begin(LORA_REGION), setADR(true), joinOTAA con reintentos exponenciales.
– Empaquetado binario compacto de 12 bytes: fácil de decodificar en el backend.
– Envío no confirmado (endPacket(false)) para ahorro de aire y energía; ajustable.
Compilación/flash/ejecución
Asegúrate de que la placa se detecte y toma nota del puerto serie.
1) Detecta la placa y el puerto:
– arduino-cli board list
– Debe listar algo como:
– Port: /dev/ttyACM0 (Linux)
– Port: COM5 (Windows)
– Port: /dev/cu.usbmodemXXX (macOS)
– Board Name: Arduino MKR WAN 1310
– FQBN: arduino:samd:mkrwan1310
2) Compila el proyecto (desde la carpeta que contiene lora-agro-microclima-node):
– arduino-cli compile \
-b arduino:samd:mkrwan1310 \
–warnings all \
–build-property compiler.cpp.extra_flags=»-DLORA_REGION=EU868″ \
lora-agro-microclima-node
Observaciones:
– Cambia -DLORA_REGION=EU868 por tu plan de frecuencias (US915, AU915, etc.).
– Asegúrate de haber creado secrets.h con APP_EUI y APP_KEY válidos.
3) Sube el firmware:
– Linux/macOS:
– arduino-cli upload \
-b arduino:samd:mkrwan1310 \
-p /dev/ttyACM0 \
–verify \
lora-agro-microclima-node
– Windows (ejemplo COM5):
– arduino-cli upload \
-b arduino:samd:mkrwan1310 \
-p COM5 \
–verify \
lora-agro-microclima-node
4) Abre el monitor serie para validar:
– Linux/macOS:
– arduino-cli monitor -p /dev/ttyACM0 -c baudrate=115200
– Windows:
– arduino-cli monitor -p COM5 -c baudrate=115200
5) Cambios de región:
– Recompila alterando el flag:
– … –build-property compiler.cpp.extra_flags=»-DLORA_REGION=US915″ …
6) Instalación/actualización del core y librerías (si faltan):
– arduino-cli core update-index
– arduino-cli core install arduino:samd@1.8.14
– arduino-cli lib install «MKRWAN@1.1.0» «Adafruit BME680 Library@2.0.2» «OneWire@2.3.7» «DallasTemperature@3.11.0»
Validación paso a paso
1) Validación eléctrica rápida:
– Con multímetro:
– 3V3 de la MKR: ~3.28–3.32 V.
– Continuidad GND entre sensores y placa.
– Pull‑up de 4.7 kΩ entre D2 y 3.3 V.
2) Validación de detección de placa:
– arduino-cli board list
– Si no aparece, prueba otro cable o puerto USB.
3) Validación de sensores por consola serie:
– Tras reset, debes ver:
– [BME680] OK (o mensaje de error si no detectado)
– [DS18B20] Dispositivos 1-Wire: N (N ≥ 1)
– Cuando hay lectura, se mostrará el payload HEX; por ejemplo:
– [Payload HEX] 07D00FA00E10002A03E807D005DC
– Esto varía según tus mediciones.
4) Validación de unión LoRaWAN:
– Mensajes esperados:
– [LoRa] Inicializando módem…
– [LoRa] DevEUI (módem): XXXXXXXXXXXXXXXX
– [LoRa] joinOTAA intento 1
– [LoRa] ¡Unión OTAA exitosa!
– Si falla, verás reintentos con backoff.
5) Validación de uplink en la consola de la red:
– Abre tu aplicación en The Things Stack (TTN v3).
– En “Live data” del dispositivo, deberías ver uplinks cada ~60 s.
– Payload Length = 12 bytes; Port = 1.
6) Decodificación del payload (servidor):
– Crea un decodificador personalizado con el layout descrito:
– T_air = int16 (big-endian) / 100
– RH = uint16 / 100
– P = uint16 / 10 (hPa)
– Gas = uint16 / 10 (kΩ)
– T_soil = int16 / 100
– Vbat = uint16 (mV)
– Verifica que T_air y T_soil son razonables (20–35 °C según ambiente/suelo), RH (20–90 %),
presión ~ 980–1050 hPa, gas suele fluctuar ampliamente, Vbat según alimentación.
7) Estabilidad:
– Deja el nodo 10–15 minutos:
– Sin pérdida de sesiones (sin rejoin continuos).
– Uplinks regulares a tu intervalo.
– Observa ADR en la red: la tasa de datos podría adaptarse.
Troubleshooting (errores típicos y soluciones)
1) No se detecta el BME680 ([BME680] No detectado en 0x76/0x77)
– Causas:
– Cable SDA/SCL invertido o mal pin.
– Breakout con dirección 0x77; ajusta el begin(0x77).
– Falta de GND común o VCC incorrecto.
– Solución:
– Revisa tabla de pines.
– Prueba ambas direcciones en el código (ya está implementado).
– Ejecuta un I2C scanner para verificar dirección.
2) DS18B20 devuelve DEVICE_DISCONNECTED_C o lectura fallida
– Causas:
– Falta pull‑up de 4.7 kΩ en la línea D2.
– GND/VDD invertidos o cable roto.
– Sensor sumergible con cable demasiado largo sin pull‑up adecuado.
– Solución:
– Añade o verifica la resistencia 4.7 kΩ entre D2 y 3.3 V.
– Usa cables más cortos o baja la frecuencia de sondeo.
3) No aparece el puerto serie en arduino-cli board list
– Causas:
– Cable solo de carga.
– Controladores USB (Windows).
– Puerto bloqueado por otro programa.
– Solución:
– Cambia a un cable de datos.
– Cierra programas que usan el puerto.
– En Windows, actualiza drivers USB nativos (MKR usa CDC estándar, no requiere drivers especiales).
4) joinOTAA falla repetidamente
– Causas:
– Región/banda incorrecta (EU868 vs US915/AU915).
– AppKey/AppEUI con formato o longitud incorrecta.
– Gateway fuera de cobertura o sin backhaul.
– Lista de sub‑bandas en US915/AU915 (TTN usa sub‑band específicas).
– Solución:
– Recompila con -DLORA_REGION adecuado.
– Verifica que APP_EUI = 16 hex y APP_KEY = 32 hex (sin espacios).
– Ubica el nodo cerca del gateway.
– Para US915/AU915, configura sub‑banda si tu librería/firmware lo permite; si no, asegúrate de la compatibilidad del gateway.
5) Uplinks no llegan a la consola, pero el nodo dice “Uplink OK”
– Causas:
– Port incorrecto filtrado por integración.
– Desfase de canales/frecuencias por región.
– RX windows desalineadas (raro si join OK).
– Solución:
– Verifica FPORT=1.
– Asegura misma región en dispositivo y aplicación.
– Re‑join para resincro.
6) Lecturas de gas del BME680 anómalas o lentas en estabilizar
– Causas:
– BME680 requiere “burn‑in” (tiempo de calentamiento) para lecturas significativas de gas.
– Cambios bruscos ambientales.
– Solución:
– Deja el sensor operando ~5–20 minutos para estabilización.
– Evita flujos de aire directos.
7) Vbat siempre 0.0 V
– Causas:
– El macro ADC_BATTERY no está disponible en tu core/placa, o no hay batería conectada.
– Solución:
– Conecta una LiPo a la MKR para lectura real.
– Implementa medición con pin analógico y divisor externo si lo requieres.
– O deja el campo en 0 y evita usarlo en análisis.
8) Error de compilación por librerías/cores en otra versión
– Causas:
– Versiones diferentes a las fijadas.
– Solución:
– Verifica versiones exactas:
– arduino-cli core list
– arduino-cli lib list
– Ajusta con:
– arduino-cli core install arduino:samd@1.8.14
– arduino-cli lib install «MKRWAN@1.1.0» …
Mejoras/variantes
- Eficiencia energética:
- Uso de modos de bajo consumo y RTCZero para dormir entre mediciones, reduciendo el consumo a pocos µA.
-
Incrementar el intervalo de envío (5–15 min) según el caso agro, para alargar la batería.
-
Payload y decodificación:
- Cambiar a CayenneLPP para compatibilidad con plataformas sin decodificador custom.
-
Añadir checksum simple en payload si tu backend lo solicita.
-
Calidad de datos:
- Integrar la librería BSEC (Bosch) para índices IAQ/VOC/CO2e; requiere más memoria y gestión de licencia/arquitectura.
-
Calibración de sensores (offset de temperatura en DS18B20, validación con termómetro de referencia).
-
LoRaWAN:
- Confirmed uplink solo para mensajes críticos; activar con USE_CONFIRMED_UPLINK = true.
- Manejar downlinks para reconfigurar intervalo de medición sobre FPORT 10 (p. ej., 1 byte con minutos).
-
Persistir frame counters y sesión (OTAA) en flash para evitar join frecuente tras reinicios.
-
Hardware:
- Carcasa IP65 con desecante y filtro sinterizado para BME680 (protección y respuesta de gas).
-
Añadir sensor de humedad de suelo (capacitivo 3.3 V) y pluviómetro de pulsos para un nodo agro más completo.
-
Robustez:
- Watchdog por software/hardware para recuperación ante bloqueos.
- Registro de errores en EEPROM/flash para diagnóstico.
Checklist de verificación
- [ ] Arduino CLI 1.1.1 instalado y en PATH.
- [ ] Core arduino:samd@1.8.14 instalado.
- [ ] Librerías instaladas con versiones: MKRWAN 1.1.0, Adafruit BME680 2.0.2, OneWire 2.3.7, DallasTemperature 3.11.0.
- [ ] Proyecto creado: lora-agro-microclima-node/ con .ino y secrets.h.
- [ ] APP_EUI (16 hex) y APP_KEY (32 hex) configurados en secrets.h.
- [ ] BME680 cableado a SDA/SCL, 3V3 y GND.
- [ ] DS18B20 en D2 con pull‑up 4.7 kΩ a 3.3 V; GND y VDD correctos.
- [ ] Compilación exitosa con FQBN arduino:samd:mkrwan1310 y región correcta.
- [ ] Subida exitosa al puerto correcto (/dev/ttyACM0, COMx, etc.).
- [ ] Consola serie a 115200 bps muestra BME680 OK, conteo DS18B20 y payload HEX.
- [ ] Unión OTAA exitosa y uplinks visibles en la consola LoRaWAN.
- [ ] Decodificador en backend interpreta los 12 bytes en unidades correctas.
- [ ] Ciclo estable durante 10–15 min con uplinks a intervalos regulares.
Apéndice: comandos clave (resumen rápido)
- Listar placas:
- arduino-cli board list
- Actualizar e instalar core:
- arduino-cli core update-index
- arduino-cli core install arduino:samd@1.8.14
- Instalar librerías:
- arduino-cli lib install «MKRWAN@1.1.0» «Adafruit BME680 Library@2.0.2» «OneWire@2.3.7» «DallasTemperature@3.11.0»
- Compilar (EU868):
- arduino-cli compile -b arduino:samd:mkrwan1310 –build-property compiler.cpp.extra_flags=»-DLORA_REGION=EU868″ lora-agro-microclima-node
- Subir (Linux ejemplo):
- arduino-cli upload -b arduino:samd:mkrwan1310 -p /dev/ttyACM0 –verify lora-agro-microclima-node
- Monitor serie:
- arduino-cli monitor -p /dev/ttyACM0 -c baudrate=115200
Con esto, dispones de un nodo “lora‑agro‑microclima‑node” fiable en Arduino MKR WAN 1310 que integra BME680 y DS18B20, con toolchain y versiones fijadas, conexiones claras, código reproducible y validación end‑to‑end en LoRaWAN.
Encuentra este producto y/o libros sobre este tema en Amazon
Como afiliado de Amazon, gano con las compras que cumplan los requisitos. Si compras a través de este enlace, ayudas a mantener este proyecto.




