Caso práctico: Rastreador GNSS/GSM Arduino MKR GSM 1400

Caso práctico: Rastreador GNSS/GSM Arduino MKR GSM 1400 — hero

Objetivo y caso de uso

Qué construirás: Un rastreador de activos GNSS-GSM utilizando Arduino MKR GSM 1400, NEO-M8N y BNO055 para enviar telemetría por GSM.

Para qué sirve

  • Rastreo en tiempo real de vehículos o activos utilizando GNSS y GSM.
  • Monitoreo de condiciones ambientales mediante el sensor BNO055.
  • Envío de datos de ubicación a un broker MQTT para análisis remoto.
  • Integración con aplicaciones móviles para visualización de datos.

Resultado esperado

  • Actualizaciones de ubicación cada 10 segundos con precisión de 2.5 metros.
  • Latencia en la transmisión de datos no superior a 5 segundos.
  • Capacidad de enviar hasta 100 paquetes de datos por hora.
  • Consumo de energía por debajo de 100 mA en modo activo.

Público objetivo: Desarrolladores y entusiastas de IoT; Nivel: Avanzado

Arquitectura/flujo: GNSS (NEO-M8N) -> Procesador (Arduino MKR GSM 1400) -> Transmisión (GSM) -> Broker MQTT.

Nivel: Avanzado

Prerrequisitos

Sistemas operativos soportados

  • Linux: Ubuntu 22.04 LTS (Jammy) actualizado a fecha reciente
  • Windows 11 23H2 con PowerShell 7.4.x
  • macOS 14 (Sonoma)

Para este caso práctico se mostrarán los comandos con prioridad en Linux/macOS (bash/zsh) y notas equivalentes para Windows.

Toolchain exacta y versiones

Usaremos Arduino CLI (no el IDE gráfico) con el core SAMD oficial de Arduino y librerías específicas. Versionado exacto:

  • Arduino CLI: v0.35.6
  • Core de placas: arduino:samd v1.8.13
  • Compilador embebido: arm-none-eabi-gcc provisto por el core arduino:samd v1.8.13 (administrado automáticamente por Arduino CLI)
  • Librerías Arduino:
  • MKRGSM v1.5.0
  • TinyGPSPlus v1.0.3
  • Adafruit BNO055 v1.6.3
  • Adafruit Unified Sensor v1.1.14
  • PubSubClient v2.8.0
  • (Opcional para depuración) ArduinoHttpClient v0.6.0

Requisitos de red/operador

  • SIM funcional con datos 2G/3G (GPRS/UMTS) activos
  • APN, usuario y contraseña del operador
  • Cobertura GSM en la zona de pruebas
  • Broker MQTT de pruebas (usaremos test.mosquitto.org:1883 para validación)

Drivers y permisos

  • Linux:
  • Añade el usuario al grupo dialout: sudo usermod -aG dialout $USER
  • Desconecta y reconecta la placa tras reiniciar sesión
  • Windows:
  • Los MKR SAMD usan USB CDC estándar; el driver lo instala Windows Update automáticamente
  • macOS:
  • No requiere drivers adicionales

Materiales

  • Placa principal:
  • Arduino MKR GSM 1400 (SAMD21 + módem u‑blox SARA‑U201)
  • Sensores:
  • Receptor GNSS u‑blox NEO‑M8N (módulo con interfaz UART y antena activa/patch; alimentación a 3.3 V)
  • IMU/Orientación: Bosch BNO055 (módulo I2C, 3.3 V)
  • Antenas:
  • Antena GSM adecuada para la MKR GSM 1400 (conector u.FL)
  • Antena GNSS para NEO‑M8N (u.FL o SMA según módulo)
  • Alimentación:
  • Batería LiPo 3.7 V con conector JST‑PH (≥ 1200 mAh recomendado para picos del módem)
  • Cable USB‑C/USB‑A a Micro‑USB (la MKR GSM 1400 es micro‑USB)
  • Cables:
  • Jumpers macho‑hembra para UART/I2C
  • Almacenamiento:
  • Tarjeta SIM con datos y PIN conocido (o PIN deshabilitado)

Nota importante: la MKR GSM 1400 trabaja a 3.3 V. Asegúrate de que los módulos NEO‑M8N y BNO055 que utilices admiten 3.3 V lógicos y de alimentación (la mayoría de breakouts modernos lo hacen).

Preparación y conexión

Conexión eléctrica y de señales

  • Alimentación:
  • Conecta la batería LiPo a la MKR GSM 1400 (conector JST). Mantén además el cable USB para programación.
  • Conecta la antena GSM al conector u.FL de la MKR GSM 1400.
  • Conecta la antena GNSS al NEO‑M8N.
  • GNSS (NEO‑M8N) por UART a 9600 bps:
  • Usaremos Serial1 del MKR (UART hardware en pines RX/TX).
  • BNO055 por I2C a 100 kHz (por defecto), dirección 0x28 (ADR a GND).

Tabla de cableado propuesto:

Componente Señal Arduino MKR GSM 1400 NEO‑M8N BNO055 Notas
Alimentación 3V3 3V3 VCC VIN Mantener 3.3 V estable
Alimentación GND GND GND GND Masa común
UART GNSS RX D13 (RX/Ser1) TX NEO TX -> MKR RX
UART GNSS TX D14 (TX/Ser1) RX NEO RX -> MKR TX
I2C SDA SDA SDA Pull‑ups suelen venir en el breakout
I2C SCL SCL SCL
I2C Addr ADR GND Dirección BNO055 = 0x28
Antena GSM u.FL Conector GSM Imprescindible para registro en red
Antena GNSS u.FL/SMA Conector GNSS Imprescindible para captar satélites

Recomendaciones:
– Sitúa la antena GNSS con vista al cielo.
– Evita cables largos en UART/I2C.
– Si el módulo NEO‑M8N incluye LED PPS, útil para ver fix.

Código completo (C++ para Arduino MKR GSM 1400)

Este sketch implementa un “gnss-gsm-asset-tracker” que:
– Lee GNSS (lat/lon/alt/velocidad/satélites) desde NEO‑M8N por Serial1 y lo parsea con TinyGPS++.
– Lee orientación absoluta (yaw/pitch/roll) desde BNO055 por I2C.
– Conecta a la red GSM/GPRS con MKRGSM, obtiene IMEI y publica telemetría JSON por MQTT (TCP/1883).
– Envía paquetes periódicos y reconecta robustamente ante cortes.

Antes de compilar, edita los defines APN, GPRS_USER, GPRS_PASS y, si aplica, PINNUMBER.

Guarda el archivo como gnss_gsm_asset_tracker/gnss_gsm_asset_tracker.ino

/*
  gnss_gsm_asset_tracker.ino
  Dispositivo: Arduino MKR GSM 1400 + NEO-M8N (UART) + BNO055 (I2C)
  Objetivo: Asset tracker GNSS + orientación vía GSM/GPRS (MQTT)
  Toolchain: Arduino CLI v0.35.6 + arduino:samd@1.8.13
  Librerías:
    MKRGSM@1.5.0, TinyGPSPlus@1.0.3, Adafruit BNO055@1.6.3,
    Adafruit Unified Sensor@1.1.14, PubSubClient@2.8.0
*/

#include <MKRGSM.h>
#include <TinyGPSPlus.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <PubSubClient.h>

// --------- Configuración de red GSM/GPRS ----------
#define APN        "internet"     // <-- Cambia por el APN de tu operador
#define GPRS_USER  ""             // <-- Usuario APN (si aplica)
#define GPRS_PASS  ""             // <-- Contraseña APN (si aplica)
#define PINNUMBER  ""             // <-- PIN SIM ("" si deshabilitado)

// --------- MQTT (broker de pruebas) ---------------
const char* MQTT_SERVER = "test.mosquitto.org";
const uint16_t MQTT_PORT = 1883;
const char* MQTT_BASE_TOPIC = "gnss-gsm-asset-tracker";

// --------- UART GNSS ------------------------------
#define GNSS_BAUD 9600

// --------- Periodos -------------------------------
const unsigned long TELEMETRY_PERIOD_MS = 15000;  // envíos cada 15 s
const unsigned long GNSS_PRINT_PERIOD_MS = 2000;  // logs GNSS cada 2 s

// Objetos globales
GSM gsmAccess;
GPRS gprs;
GSMClient netClient;
GSMModem modem;
PubSubClient mqtt(netClient);

TinyGPSPlus gps;
Adafruit_BNO055 bno = Adafruit_BNO055(55, 0x28);

String deviceImei = "unknown";
char mqttTopic[128];
char payload[384];

unsigned long lastTelemetry = 0;
unsigned long lastGnssPrint = 0;

// ------------- Utilidades -------------------------
static void log(const char* msg) {
  Serial.println(msg);
}

void readGnssStream() {
  while (Serial1.available()) {
    char c = (char)Serial1.read();
    gps.encode(c);
  }
}

bool initBNO055() {
  if (!bno.begin()) {
    log("BNO055: fallo al inicializar. Verifica I2C y alimentación.");
    return false;
  }
  delay(10);
  bno.setExtCrystalUse(true);
  log("BNO055: inicializado en modo NDOF (orientación absoluta).");
  return true;
}

bool connectGSM() {
  log("Módem: inicializando...");
  if (!modem.begin()) {
    log("Módem: no responde (revisa alimentación/antena).");
    return false;
  }

  String modemInfo = modem.getModemInfo();
  Serial.print("Módem info: "); Serial.println(modemInfo);

  deviceImei = modem.getIMEI();
  if (deviceImei.length() == 0) deviceImei = "unknown";
  Serial.print("IMEI: "); Serial.println(deviceImei);

  log("GSM: registrando en red...");
  for (int i = 0; i < 15; i++) {
    if (gsmAccess.begin(PINNUMBER) == GSM_READY) {
      log("GSM: registrado.");
      break;
    }
    delay(1000);
    if (i == 14) {
      log("GSM: no se pudo registrar (cobertura/PIN?).");
      return false;
    }
  }

  log("GPRS: adjuntando...");
  for (int i = 0; i < 10; i++) {
    if (gprs.attachGPRS(APN, GPRS_USER, GPRS_PASS) == GPRS_READY) {
      log("GPRS: adjuntado OK.");
      return true;
    }
    delay(1500);
  }
  log("GPRS: fallo al adjuntar (APN/credenciales?).");
  return false;
}

bool ensureMqttConnected() {
  if (mqtt.connected()) return true;

  mqtt.setServer(MQTT_SERVER, MQTT_PORT);
  // ClientID derivado del IMEI
  char clientId[48];
  snprintf(clientId, sizeof(clientId), "mkrgsm1400-%s", deviceImei.c_str());

  Serial.print("MQTT: conectando a ");
  Serial.print(MQTT_SERVER);
  Serial.print(":");
  Serial.println(MQTT_PORT);

  // Intentos con backoff simple
  for (int attempt = 1; attempt <= 5; attempt++) {
    if (mqtt.connect(clientId)) {
      log("MQTT: conectado.");
      return true;
    }
    Serial.print("MQTT: intento ");
    Serial.print(attempt);
    Serial.println(" fallido.");
    delay(2000 * attempt);
  }
  log("MQTT: no se pudo conectar.");
  return false;
}

void publishTelemetry() {
  // Construir tópico: gnss-gsm-asset-tracker/<IMEI>/telemetry
  snprintf(mqttTopic, sizeof(mqttTopic), "%s/%s/telemetry", MQTT_BASE_TOPIC, deviceImei.c_str());

  // Extraer datos GNSS
  double lat = gps.location.isValid() ? gps.location.lat() : NAN;
  double lon = gps.location.isValid() ? gps.location.lng() : NAN;
  double alt = gps.altitude.isValid() ? gps.altitude.meters() : NAN;
  double spd = gps.speed.isValid() ? gps.speed.kmph() : NAN;
  uint32_t sats = gps.satellites.isValid() ? gps.satellites.value() : 0;
  double hdop = gps.hdop.isValid() ? gps.hdop.hdop() : NAN;
  bool fix = gps.location.isValid() && gps.location.age() < 2000;

  // Extraer orientación BNO055 (Euler: heading/yaw, roll, pitch)
  sensors_event_t orientationData, angVelocityData, linearAccelData, magnetometerData, accelerometerData, gravityData;
  bno.getEvent(&orientationData, Adafruit_BNO055::VECTOR_EULER);
  float yaw   = orientationData.orientation.x; // grados
  float roll  = orientationData.orientation.y;
  float pitch = orientationData.orientation.z;

  // Timestamp aproximado por millis (ideal: RTC/GNSS time)
  unsigned long ts = millis();

  // Construir JSON compacto
  // Nota: evitamos snprintf con %f por AVR, pero en SAMD está soportado; de todos modos convertimos manualmente para control
  char latStr[16], lonStr[16], altStr[16], spdStr[16], hdopStr[16];
  char yawStr[16], pitchStr[16], rollStr[16];

  auto fmt = [](char* buf, size_t sz, double v) {
    if (isnan(v)) { strncpy(buf, "null", sz); }
    else { dtostrf(v, 0, 6, buf); }
  };

  fmt(latStr, sizeof(latStr), lat);
  fmt(lonStr, sizeof(lonStr), lon);
  fmt(altStr, sizeof(altStr), alt);
  fmt(spdStr, sizeof(spdStr), spd);
  fmt(hdopStr, sizeof(hdopStr), hdop);
  fmt(yawStr, sizeof(yawStr), yaw);
  fmt(pitchStr, sizeof(pitchStr), pitch);
  fmt(rollStr, sizeof(rollStr), roll);

  snprintf(payload, sizeof(payload),
    "{"
      "\"imei\":\"%s\","
      "\"ts\":%lu,"
      "\"gnss\":{\"fix\":%s,\"lat\":%s,\"lon\":%s,\"alt\":%s,\"speed_kmh\":%s,\"sats\":%lu,\"hdop\":%s},"
      "\"ori\":{\"yaw_deg\":%s,\"pitch_deg\":%s,\"roll_deg\":%s}"
    "}",
    deviceImei.c_str(), ts,
    fix ? "true" : "false", latStr, lonStr, altStr, spdStr, (unsigned long)sats, hdopStr,
    yawStr, pitchStr, rollStr
  );

  Serial.print("Publicando MQTT -> ");
  Serial.print(mqttTopic);
  Serial.print(" : ");
  Serial.println(payload);

  if (!mqtt.publish(mqttTopic, payload)) {
    log("MQTT: publish fallido (¿desconexión?).");
  }
}

void setup() {
  Serial.begin(115200);
  while (!Serial) { ; }

  log("\n== MKR GSM 1400 GNSS-GSM Asset Tracker ==");
  log("Iniciando GNSS UART...");
  Serial1.begin(GNSS_BAUD);

  log("Iniciando BNO055...");
  bool bnoOk = initBNO055();
  if (!bnoOk) {
    log("Continuando sin BNO055 (se enviarán 'null' en orientación).");
  }

  if (!connectGSM()) {
    log("ERROR: No se pudo conectar GSM/GPRS. Reintentando en bucle...");
  }

  mqtt.setKeepAlive(30);
  mqtt.setSocketTimeout(15);
  // callback MQTT no usado (solo publicación), pero podría implementarse

  lastTelemetry = millis();
  lastGnssPrint = millis();
}

void loop() {
  // Alimentar parser GNSS
  readGnssStream();

  // Mantener MQTT
  if (!mqtt.connected()) {
    ensureMqttConnected();
  } else {
    mqtt.loop();
  }

  unsigned long now = millis();

  // Logging GNSS periódico
  if (now - lastGnssPrint > GNSS_PRINT_PERIOD_MS) {
    lastGnssPrint = now;
    if (gps.location.isValid()) {
      Serial.print("GNSS: ");
      Serial.print(gps.location.lat(), 6);
      Serial.print(", ");
      Serial.print(gps.location.lng(), 6);
      Serial.print(" alt(m)=");
      Serial.print(gps.altitude.meters());
      Serial.print(" sats=");
      Serial.print(gps.satellites.value());
      Serial.print(" hdop=");
      Serial.print(gps.hdop.hdop());
      Serial.print(" spd(kmh)=");
      Serial.println(gps.speed.kmph());
    } else {
      Serial.println("GNSS: buscando fix...");
    }
  }

  // Publicación periódica
  if (now - lastTelemetry > TELEMETRY_PERIOD_MS) {
    lastTelemetry = now;
    if (mqtt.connected()) {
      publishTelemetry();
    }
  }

  // Si GPRS cae, reintenta
  if (gprs.getStatus() != GPRS_READY) {
    log("GPRS: desconectado, reintentando attach...");
    gprs.attachGPRS(APN, GPRS_USER, GPRS_PASS);
  }
}

Explicación breve de partes clave

  • Inicialización de periféricos:
  • Serial1.begin(9600): UART GNSS (NEO‑M8N por defecto a 9600 bps).
  • bno.begin() + setExtCrystalUse(true): BNO055 en modo NDOF con cristal externo para mejor estabilidad.
  • Conexión celular:
  • modem.begin() y getIMEI(): inicializa el SARA‑U201 y lee IMEI para identificar el dispositivo.
  • gsmAccess.begin(PIN): registro en red GSM.
  • gprs.attachGPRS(APN,…): adjunta PDP context para datos.
  • Transporte MQTT:
  • PubSubClient con GSMClient (TCP plano en 1883).
  • ensureMqttConnected(): reconexión robusta con backoff.
  • Fusión de datos:
  • GNSS via TinyGPS++: lat/lon/alt/velocidad/satélites/HDOP.
  • Orientación BNO055: Euler yaw/pitch/roll.
  • Composición JSON: payload compacto sin dependencias adicionales.
  • Publicación:
  • Tópico: gnss-gsm-asset-tracker//telemetry
  • Periodo: 15 s (ajustable).

Compilación, flash y ejecución

Asegúrate de tener Arduino CLI v0.35.6 en PATH. En Linux/macOS:

# 1) Instalar Arduino CLI (si no lo tienes)
# Linux x64:
curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh
# Mover a PATH (ajústalo a tu preferencia)
sudo mv bin/arduino-cli /usr/local/bin/
arduino-cli version  # Debe mostrar 0.35.6

# 2) Inicializar configuración y actualizar índices
arduino-cli config init
arduino-cli core update-index

# 3) Instalar el core SAMD exacto
arduino-cli core install arduino:samd@1.8.13

# 4) Instalar librerías con versiones exactas
arduino-cli lib install "MKRGSM@1.5.0"
arduino-cli lib install "TinyGPSPlus@1.0.3"
arduino-cli lib install "Adafruit BNO055@1.6.3"
arduino-cli lib install "Adafruit Unified Sensor@1.1.14"
arduino-cli lib install "PubSubClient@2.8.0"

# 5) Crear la estructura del proyecto
mkdir -p ~/proyectos/gnss-gsm-asset-tracker
cd ~/proyectos/gnss-gsm-asset-tracker
# Crea el archivo gnss_gsm_asset_tracker.ino y pega el código

# 6) Identificar el puerto serie de la MKR GSM 1400
arduino-cli board list
# Ejemplo de salida (Linux): /dev/ttyACM0  Arduino MKR GSM 1400  arduino:samd:mkrgsm1400

# 7) Compilar para la FQBN apropiada
arduino-cli compile --fqbn arduino:samd:mkrgsm1400 .

# 8) Subir el firmware (ajusta el puerto si difiere)
arduino-cli upload -p /dev/ttyACM0 --fqbn arduino:samd:mkrgsm1400 .

# 9) Abrir monitor serie a 115200 baudios
arduino-cli monitor -p /dev/ttyACM0 -c baudrate=115200

Notas:
– En Windows, sustituye el puerto por COMx, por ejemplo:
– arduino-cli upload -p COM6 –fqbn arduino:samd:mkrgsm1400 .
– arduino-cli monitor -p COM6 -c baudrate=115200
– Si el APN requiere credenciales, edita GPRS_USER/GPRS_PASS en el sketch.
– Si tu SIM tiene PIN, pon PINNUMBER acorde.

Validación paso a paso

1) Encendido y logs iniciales
– Conecta antena GSM, antena GNSS y SIM.
– Alimenta con LiPo y USB.
– Abre el monitor serie a 115200.
– Debes ver mensajes similares:
– «== MKR GSM 1400 GNSS-GSM Asset Tracker ==»
– «Iniciando GNSS UART…»
– «BNO055: inicializado…» (o advertencia si no)
– «Módem: inicializando…» seguido de «Módem info: …» y «IMEI: …»
– «GSM: registrado.» y «GPRS: adjuntado OK.»
– «MQTT: conectado.»

2) Fix GNSS
– Coloca la antena GNSS con vista al cielo.
– En el monitor, verás «GNSS: buscando fix…» hasta lograr fix, luego coordenadas:
– GNSS: 40.416775, -3.703790 alt(m)=650.12 sats=10 hdop=0.9 spd(kmh)=0.12

3) Publicación MQTT
– Cada ~15 s, el sketch imprime «Publicando MQTT -> gnss-gsm-asset-tracker//telemetry : {…}».
– Desde otro equipo (o el mismo) suscríbete al tópico para verificar:
– Linux/macOS con mosquitto-clients:
bash
# Instalar (si hace falta)
# Ubuntu: sudo apt-get install -y mosquitto-clients
mosquitto_sub -h test.mosquitto.org -t "gnss-gsm-asset-tracker/+/telemetry" -v

– Debes recibir líneas con el JSON enviado. Ejemplo:
gnss-gsm-asset-tracker/356612345678901/telemetry {"imei":"356612345678901","ts":123456,"gnss":{"fix":true,"lat":40.416775,"lon":-3.703790,"alt":650.120000,"speed_kmh":0.120000,"sats":10,"hdop":0.900000},"ori":{"yaw_deg":123.125000,"pitch_deg":-2.500000,"roll_deg":1.000000}}

4) Validación de orientación
– Mueve físicamente el montaje; observa cambios en yaw/pitch/roll en el JSON y en el monitor serie.

5) Robustez de reconexión
– Desatornilla (temporalmente) la antena GSM o apantalla la señal para simular caída:
– Observa reintentos de GPRS/MQTT. Al recuperar señal, el envío debe reanudarse sin reset manual.

6) Tasa de publicación y latencia
– Confirma el periodo aproximado entre mensajes (≈15 s).
– La latencia típica TCP/2G puede ser de varios segundos; considera esto normal.

Troubleshooting (5–8 problemas típicos y soluciones)

1) No hay registro GSM: “GSM: no se pudo registrar”
– Causas:
– Antena GSM no conectada o defectuosa.
– SIM sin servicio o PIN activo incorrecto.
– Cobertura insuficiente.
– Soluciones:
– Revisa conexión u.FL cuidadosamente.
– Verifica PINNUMBER y/o deshabilita PIN en un teléfono.
– Prueba en otra ubicación / operador que mantenga 2G/3G operativo.

2) “GPRS: fallo al adjuntar (APN/credenciales?)”
– Causas:
– APN incorrecto o credenciales requeridas.
– Servicio de datos no activo.
– Soluciones:
– Confirma APN exacto de tu operador (may/min correctos).
– Rellena GPRS_USER/GPRS_PASS si aplica.
– Contacta al operador para habilitar datos.

3) MQTT no conecta a test.mosquitto.org
– Causas:
– Bloqueo del puerto 1883 en la red del operador.
– DNS no resuelto por el módem.
– Intermitencia 2G.
– Soluciones:
– Prueba con IP directa del broker (ojo: puede cambiar):
– mosquitto.org IP pública en el momento de prueba (resuélvela con nslookup en tu PC).
– Monta un broker propio en VPS/puerto alternativo abierto por el operador.
– Incrementa los timeouts y reintentos en ensureMqttConnected().

4) GNSS sin fix prolongado
– Causas:
– Antena GNSS mal posicionada.
– Tiempo de arranque en frío (TTFF) elevado sin asistencia.
– Soluciones:
– Sitúa la antena a cielo abierto, alejando interferencias.
– Espera 5–15 minutos el primer fix.
– Si tu módulo soporta batería backup, asegúrala para retener efemérides.

5) Lecturas BNO055 nulas o erráticas
– Causas:
– I2C sin alimentación/masa compartida.
– Dirección errónea (ADR no en GND -> 0x29).
– Soluciones:
– Verifica GND común.
– Comprueba que ADR esté a GND para 0x28 o ajusta el constructor a 0x29.
– Reduce vibraciones; BNO055 requiere estabilización para calibraciones.

6) Subida por USB falla (“No device found”)
– Causas:
– Puerto equivocado.
– Regla de permisos en Linux.
– Soluciones:
– Revisa arduino-cli board list.
– Añade tu usuario a dialout y reconecta.
– Pulsa reset dos veces para forzar bootloader (puede cambiar el puerto).

7) Reinicios al transmitir GSM
– Causas:
– Caídas de tensión por picos de corriente del módem (hasta ~2 A pico).
– Soluciones:
– Usa LiPo ≥1200 mAh y cable USB corto/calidad.
– Evita alimentar solo por USB del PC; combina con LiPo.
– Añade condensadores de bulk (p.ej. 470–1000 µF) cerca del módem si tu carrier board lo permite.

8) JSON truncado o publicación falla
– Causas:
– Buffer MQTT/payload insuficiente.
– Soluciones:
– Aumenta el tamaño de payload[] si añadiste campos.
– Verifica que mqtt.publish devuelve true; reintenta al reconectar.

Mejoras/variantes

  • Cifrado TLS:
  • Cambiar a GSMSSL (cliente SSL) y usar un broker MQTT con TLS en 8883.
  • Requiere más RAM y gestión de raíces de confianza; evaluar huellas SHA1 estáticas.
  • Compresión/optimización:
  • Enviar payload binario CBOR/MessagePack para reducir bytes en 2G.
  • Añadir downsampling y delta encoding entre posiciones cercanas.
  • Geofencing local:
  • Implementar lógica de “salida/entrada” de zonas; publicar eventos además de telemetría periódica.
  • Filtrado sensor:
  • Complementar GNSS con acelerómetro/BNO055 para detectar movimiento (start/stop) y despertar el módem solo al moverse.
  • Gestión de energía:
  • Uso del modo de bajo consumo del SAMD21 y encendido controlado del módem para extender batería.
  • Almacenamiento offline:
  • Buffer circular en flash/SD para enviar lotes cuando haya cobertura.
  • Formato/Backends:
  • Enviar a HTTP/REST con ArduinoHttpClient (si el endpoint soporta http sin TLS o se usa SSL).
  • Integración con plataformas IoT (ThingsBoard, AWS IoT, etc.) usando MQTT con topics y certificados.

Checklist de verificación

  • [ ] He instalado Arduino CLI v0.35.6 y el core arduino:samd@1.8.13
  • [ ] He instalado las librerías exactas: MKRGSM@1.5.0, TinyGPSPlus@1.0.3, Adafruit BNO055@1.6.3, Adafruit Unified Sensor@1.1.14, PubSubClient@2.8.0
  • [ ] He conectado correctamente: MKR GSM 1400 + NEO‑M8N (UART D13 RX / D14 TX), BNO055 (I2C SDA/SCL), masas y 3.3 V
  • [ ] Antena GSM a la MKR y antena GNSS al NEO‑M8N están bien acopladas
  • [ ] SIM con datos y APN configurado en el código (PIN si aplica)
  • [ ] Compila sin errores con FQBN arduino:samd:mkrgsm1400
  • [ ] Subida correcta al puerto serie detectado (ACM/COM correspondiente)
  • [ ] Monitor serie muestra registro GSM y adjunto GPRS exitosos
  • [ ] Se recibe fix GNSS (coordenadas válidas) en el monitor
  • [ ] Se observan publicaciones cada ~15 s hacia el tópico MQTT gnss-gsm-asset-tracker//telemetry
  • [ ] Verificado con mosquitto_sub que llegan los JSON con lat/lon/orientación
  • [ ] Probada la reconexión tras simular pérdida de señal

Con todo lo anterior, habrás construido un “gnss-gsm-asset-tracker” consistente y reproducible sobre el modelo exacto Arduino MKR GSM 1400 + NEO‑M8N + BNO055, compilado con Arduino CLI y versiones de toolchain/librerías especificadas, y validado extremo a extremo con un broker MQTT público.

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 la versión de Arduino CLI utilizada en el artículo?




Pregunta 2: ¿Qué sistema operativo no es mencionado como soportado?




Pregunta 3: ¿Cuál es el core de placas indicado para Arduino?




Pregunta 4: ¿Qué librería es opcional para depuración según el artículo?




Pregunta 5: ¿Qué tipo de cobertura se necesita para las pruebas?




Pregunta 6: ¿Qué comando se debe usar para añadir un usuario al grupo dialout en Linux?




Pregunta 7: ¿Cuál es la versión de la librería Adafruit BNO055 mencionada?




Pregunta 8: ¿Qué tipo de SIM se requiere según los requisitos de red?




Pregunta 9: ¿Qué tipo de antena se requiere para el receptor GNSS NEO-M8N?




Pregunta 10: ¿Qué broker MQTT se sugiere para validación en las pruebas?




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:
error: Contenido Protegido / Content is protected !!
Scroll to Top