Caso práctico: nodo LoRaWAN agro MKR WAN 1310+BME680+DS18B20

Caso práctico: nodo LoRaWAN agro MKR WAN 1310+BME680+DS18B20 — hero

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

Ir a 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.

Quiz rápido

Pregunta 1: ¿Cuál es el sistema operativo probado para el uso de Arduino CLI?




Pregunta 2: ¿Qué versión de la librería MKRWAN es la recomendada?




Pregunta 3: ¿Cuál es el voltaje lógico que el MKR WAN 1310 no tolera?




Pregunta 4: ¿Qué tipo de sensor es el BME680?




Pregunta 5: ¿Qué herramienta se recomienda para verificar la continuidad?




Pregunta 6: ¿Qué tipo de conexión se requiere para el sensor DS18B20?




Pregunta 7: ¿Qué tipo de batería es opcional para pruebas de campo?




Pregunta 8: ¿Qué es necesario para dar de alta un dispositivo en la aplicación LoRaWAN?




Pregunta 9: ¿Qué cable se recomienda para la conexión de datos?




Pregunta 10: ¿Cuál es la resistencia recomendada para el pull-up en la línea 1-Wire?




Carlos Núñez Zorrilla
Carlos Núñez Zorrilla
Electronics & Computer Engineer

Ingeniero Superior en Electrónica de Telecomunicaciones e Ingeniero en Informática (titulaciones oficiales en España).

Sígueme:
Scroll al inicio