🛠 Publier capteurs et batterie en MQTT via une passerelle
Objetivos
Cerrar el bucle de un nodo sensor alimentado por batería que publica temperatura y nivel de batería hasta un broker MQTT. Arquitectura impuesta por el hardware: el Nicla (sin WiFi) actúa como dispositivo BLE con un servicio personalizado, y la placa anfitriona MKR WiFi 1010 actúa como pasarela BLE-a-MQTT. En el lado del Nicla, la API Nicla_System proporciona un nivel de batería fiable leído en los registros del cargador BQ25120 (nicla::getBatteryVoltagePercentage, nicla::getCurrentBatteryVoltage), mucho más fiable que un simple divisor de tensión. Este es el esquema de referencia para las redes de sensores inalámbricos en formato Nicla descrito por Arduino Pro.
Hardware
- Nicla Sense ME (ABX00050) + batería LiPo en J4 (con o sin NTC según la batería:
nicla::setBatteryNTCEnabled(false)si no está presente) - MKR WiFi 1010 (o Portenta C33) como pasarela; bibliotecas ArduinoBLE en el Nicla, WiFi101 + PubSubClient en el anfitrión
- Broker MQTT accesible (broker local o alojado)
- >
Código completo
// Sketch NICLA : peripheral BLE batterie + temperature
#include "Nicla_System.h"
#include "Arduino_BHY2.h"
#include <ArduinoBLE.h>
Sensor temp(SENSOR_ID_TEMP);
BLEService batteryService("180F");
BLEUnsignedCharCharacteristic battLevel("2A19", BLERead | BLENotify);
BLEFloatCharacteristic tempChar("2A6E", BLERead | BLENotify);
void setup {
Serial.begin(9600);
nicla::begin;
nicla::setBatteryNTCEnabled(false);
nicla::leds.begin;
nicla::leds.setColor(green);
BHY2.begin;
temp.begin;
if (!BLE.begin) { while (1); }
BLE.setLocalName("NiclaNode");
BLE.setAdvertisedService(batteryService);
batteryService.addCharacteristic(battLevel);
batteryService.addCharacteristic(tempChar);
BLE.addService(batteryService);
BLE.advertise;
}
void loop {
static auto t = millis;
BHY2.update;
BLE.poll;
if (millis - t >= 10000) {
t = millis;
battLevel.writeValue((unsigned char)nicla::getBatteryVoltagePercentage);
if (temp.dataAvailable) tempChar.writeValue(temp.value);
}
}
// Sketch HOTE (MKR WiFi 1010) : passerelle BLE -> MQTT
#include <WiFi101.h>
#include <PubSubClient.h>
WiFiClient net;
PubSubClient mqtt(net);
BLEDevice node;
void setup {
WiFi.begin("MON_WIFI", "MON_MOT_DE_PASSE");
mqtt.setServer("192.168.1.40", 1883);
BLE.begin;
BLE.setScanTimeout(5000);
node = BLE.scanForName("NiclaNode");
while (!node) { node = BLE.scanForName("NiclaNode"); }
node.connect;
mqtt.connect("nicla-gateway");
}
void loop {
if (!node.connected || !mqtt.connected) { return; } // reconnexion a gerer
BLE.poll;
static auto t = millis;
if (millis - t >= 30000) {
t = millis;
unsigned char batt = node.characteristic("2A19").readValue;
char payload[96];
snprintf(payload, sizeof(payload), "{\"batt_pct\":%u}", batt);
mqtt.publish("maison/nicla1", payload);
}
}
Verificación esperada
mosquitto_sub -t 'maison/nicla1' muestra un JSON periódico con el porcentaje de batería leído en el cargador. El LED verde del Nicla indica la alimentación; con nRF Connect se pueden auditar las características 2A19/2A6E entre dos publicaciones. Al descargar la batería LiPo, el porcentaje debe disminuir regularmente (recalibrar si la curva parece plana, ya que la tensión de una LiPo es poco lineal).
Errores frecuentes
- Publicar a ciegas sin gestionar las desconexiones: el BLE del Nicla duerme, el WiFi del anfitrión cae; prever bucles de reconexión completos antes de dejar el nodo solo en producción.
- Olvidar
BLE.pollen el lado del Nicla: los centrales leen valores congelados; el mismo síntoma si faltaBHY2.update. - Confiar en un porcentaje bruto sin tener en cuenta la carga:
nicla::getOperatingStatusy la tensión de carga modifican la lectura; mostrar también la tensión bruta para depurar. - Frecuencia demasiado alta: 10 s en el lado del Nicla y 30 s en el lado MQTT son cómodos para una LiPo de 200 mAh; la hoja de datos indica 1,15 mA típicos en publicidad + una medición por hora, cada segundo extra de radio se paga en autonomía.
- >
Otros tutoriales para esta placa
Ejemplos de código para esta placa
led_rgb.inoArduinoimu_bhi260.inoArduinorotation_fusion.inoArduinopression_bmp390.inoArduinonose_electronique.inoArduinoboussole_bmm150.inoArduino