Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Manufacturing Technology >> Proceso de manufactura

Monitorización Ambiental en Tiempo Real con Arduino MKR1000 y Sensor Environment Click

Componentes y materiales

Componente Cantidad
Arduino MKR1000 1
MikroE Environment Click (BME680) 1

Herramientas necesarias

Software y servicios en línea

Sobre el proyecto

Introducción

Teníamos sensores Environment Click (BME680) a mano y decidimos conectarlos al Arduino MKR1000 para visualizar datos en WolkAbout IoT Platform.

Objetivo: medir cada minuto y publicar cada 15 minutos. Si falla la publicación (red ocupada, etc.), los datos se persisten en Flash del dispositivo (buffer circular). Máx. 96 escrituras/día → minimiza desgaste Flash (garantía 10.000 ciclos).

Montaje hardware

Environment Click se conecta a pines I2C del MKR1000 (pines 11=SDA, 12=SCL), Vcc y GND.

Configuración software

Librerías necesarias (instalables desde Gestor de librerías Arduino IDE o descargando .zip de GitHub):

Copia el sketch Environment monitoring (adjunto) al IDE. Implementa buffer circular + persistencia en Flash (FlashStorage). Lectura y publicación temporizadas con RTCZero. Al conectar WiFi, hace ping a WolkAbout para obtener epoch actual y sincronizar RTC.

Una interrupción de alarma pone flags read / publish; el loop() ejecuta tareas. Para bajo consumo: WiFi en low-power mode, MKR1000 en low-power, sensor BME680 entra en low-power automáticamente hasta que se pide lectura.

Modificaciones obligatorias en el sketch

  1. Credenciales WiFi (líneas 33-34):
    const char* ssid = "<*TU_SSID*>";
    const char* wifi_pass = "<*TU_PASSWORD_WIFI*>";
  2. Credenciales dispositivo WolkAbout:
    const char *device_key = "device_key";
    const char *device_password = "device_password";

Para obtener credenciales: crea Device Type en WolkAbout (archivo Environment click-deviceType.json adjunto). En WolkAbout → Device Management > Device Type Management > + > Upload → selecciona JSON. Luego Create device: nombre, Connectivity Type = MQTT, marca Create Default Semantic. Guarda → te da device_key y device_password.

Dashboard en WolkAbout

  1. Ve a Visualisation and Monitoring > + Add dashboard (nombre, scope = nombre dispositivo).
  2. Add widget > Trending → selecciona Temperature de tu dispositivo.
  3. Repite para Pressure y Humidity.
  4. Añade widget Reading → Altitude.
  5. Añade widget Card → Gas Resistance.
  6. Reorganiza a tu gusto.

Despliega el dispositivo en el entorno elegido y monitoriza condiciones remotamente.

Conclusión

Conectando Arduino MKR1000 + Environment Click a WolkAbout IoT Platform, creas una forma eficiente energéticamente de reportar condiciones ambientales remotas. Extensible con motor de reglas de WolkAbout para notificaciones al superar umbrales. Más info en User Guides de WolkAbout.

Código

Sketch principal (Environment monitoring sketch)

#include <Adafruit_Sensor.h>
#include <Adafruit_BME680.h>
#include <bme680_defs.h>
#include <bme680.h>
#include <WiFi101.h>
#include <RTCZero.h>
#include <FlashStorage.h>
#include "WolkConn.h"
#include "MQTTClient.h"

#define STORAGE_SIZE 32
#define SEALEVELPRESSURE_HPA (1013.25)

typedef struct {
  boolean valid;
  outbound_message_t outbound_messages[STORAGE_SIZE];
  uint32_t head;
  uint32_t tail;
  boolean empty;
  boolean full;
} Messages;

static Messages data;

const char* ssid = "ssid";
const char* wifi_pass = "wifi_pass";
const char *device_key = "device_key";
const char *device_password = "device_password";
const char* hostname = "api-demo.wolkabout.com";
int portno = 1883;

WiFiClient espClient;
PubSubClient client(espClient);
static wolk_ctx_t wolk;

FlashStorage(flash_store, Messages);

Adafruit_BME680 bme;
RTCZero rtc;

bool read = false;
const byte readEvery = 1;    // Leer cada minuto (<60)
bool publish = false;
const byte publishEvery = 10; // Publicar cada 10 min (<60)
byte publishMin;

void _flash_store() { data.valid = true; flash_store.write(data); }
void increase_pointer(uint32_t* p) { *p = (*p == STORAGE_SIZE-1) ? 0 : *p+1; }

void _init() {
  data = flash_store.read();
  if (!data.valid) { data.head=0; data.tail=0; data.empty=true; data.full=false; }
}
bool _push(outbound_message_t* m) {
  if (data.full) increase_pointer(&data.head);
  memcpy(&data.outbound_messages[data.tail], m, sizeof(outbound_message_t));
  increase_pointer(&data.tail);
  data.empty=false; data.full=(data.tail==data.head); return true;
}
bool _peek(outbound_message_t* m) { memcpy(m, &data.outbound_messages[data.head], sizeof(outbound_message_t)); return true; }
bool _pop(outbound_message_t* m) {
  memcpy(m, &data.outbound_messages[data.head], sizeof(outbound_message_t));
  increase_pointer(&data.head);
  data.full=false; data.empty=(data.tail==data.head); return true;
}
bool _is_empty() { return data.empty; }

void init_wifi() {
  if (WiFi.status() != WL_CONNECTED) {
    while (WiFi.begin(ssid, wifi_pass) != WL_CONNECTED) delay(1000);
  }
}
void setup_wifi() {
  delay(10);
  if (WiFi.status() != WL_CONNECTED) {
    int n=0;
    while (WiFi.begin(ssid, wifi_pass) != WL_CONNECTED) {
      if (++n == 10) { Serial.println("Couldn't reach WiFi!"); break; }
      delay(1000);
    }
  }
}

void setup() {
  pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, LOW);
  _init();
  init_wifi();
  wolk_init(&wolk, NULL, NULL, NULL, NULL, device_key, device_password, &client, hostname, portno, PROTOCOL_JSON_SINGLE, NULL, NULL);
  wolk_init_custom_persistence(&wolk, _push, _peek, _pop, _is_empty);
  if (!bme.begin()) digitalWrite(LED_BUILTIN, HIGH);
  bme.setTemperatureOversampling(BME680_OS_8X);
  bme.setHumidityOversampling(BME680_OS_2X);
  bme.setPressureOversampling(BME680_OS_4X);
  bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
  bme.setGasHeater(320, 150);
  delay(200);
  read = true; publish = true;
  wolk_connect(&wolk); delay(100);
  wolk_update_epoch(&wolk);
  while (!wolk.pong_received) { wolk_process(&wolk); digitalWrite(LED_BUILTIN, HIGH); delay(1000); }
  digitalWrite(LED_BUILTIN, LOW);
  wolk_disconnect(&wolk);
  rtc.begin(); rtc.setEpoch(wolk.epoch_time);
  rtc.setAlarmTime(rtc.getHours(), (rtc.getMinutes()+readEvery)%60, rtc.getSeconds());
  rtc.enableAlarm(rtc.MATCH_MMSS);
  rtc.attachInterrupt(alarmMatch);
  publishMin = (rtc.getMinutes()+publishEvery)%60;
  WiFi.lowPowerMode();
}

void loop() {
  if (read) {
    read = false;
    if (!bme.performReading()) digitalWrite(LED_BUILTIN, HIGH);
    wolk_add_numeric_sensor_reading(&wolk, "T", bme.temperature, rtc.getEpoch());
    wolk_add_numeric_sensor_reading(&wolk, "H", bme.humidity, rtc.getEpoch());
    wolk_add_numeric_sensor_reading(&wolk, "P", bme.pressure/100.0, rtc.getEpoch());
    wolk_add_numeric_sensor_reading(&wolk, "GR", bme.gas_resistance, rtc.getEpoch());
    wolk_add_numeric_sensor_reading(&wolk, "A", bme.readAltitude(SEALEVELPRESSURE_HPA), rtc.getEpoch());
    int alarmMin = (rtc.getMinutes()+readEvery)%60;
    rtc.setAlarmMinutes(alarmMin);
    delay(100);
  }
  if (publish) {
    publish = false;
    setup_wifi();
    wolk_connect(&wolk);
    if (!wolk.is_connected) _flash_store();
    delay(100);
    if (wolk_publish(&wolk) == W_TRUE) _flash_store();
    publishMin = (rtc.getMinutes()+publishEvery)%60;
    delay(100);
    wolk_disconnect(&wolk);
    delay(100);
  }
  delay(100);
}

void alarmMatch() {
  read = true;
  if (publishMin == rtc.getMinutes()) publish = true;
}

Device Type JSON (Environment click-deviceType.json)

[
  {
    "name": "Environment click",
    "description": "Device type for the BME680 sensor on MikroElektronika's board Environment Click",
    "guid": "def68ff6-63c5-4f9c-a066-bcc944b7bd2d",
    "deviceType": "STANDARD",
    "protocol": "JSON",
    "connectivityType": null,
    "firmwareUpdateType": null,
    "feeds": [
      { "name": "Temperature", "reference": "T", "unit": { "name": "CELSIUS", "guid": "7c805d10-a879-11e9-83cd-0a0027000005" } },
      { "name": "Humidity", "reference": "H", "unit": { "name": "HUMIDITY_PERCENT", "guid": "7c8080a3-a879-11e9-83cd-0a0027000005" } },
      { "name": "Pressure", "reference": "P", "unit": { "name": "MILLIBAR", "guid": "7c807980-a879-11e9-83cd-0a0027000005" } },
      { "name": "Gas Resistance", "reference": "GR", "unit": { "name": "OHM", "guid": "7c805890-a879-11e9-83cd-0a0027000005" } },
      { "name": "Altitude", "reference": "A", "unit": { "name": "METRE", "guid": "7c805a59-a879-11e9-83cd-0a0027000005" } }
    ],
    "actuators": [],
    "alarms": [],
    "configs": [],
    "attributes": [
      { "name": "CONNECTIVITY_TYPE", "dataType": "ENUM", "validationRegex": "^(MQTT|HTTP)$", "options": ["MQTT","HTTP"], "defaultValue": "MQTT", "required": true, "readOnly": true },
      { "name": "FIRMWARE_UPDATE_ENABLED", "dataType": "BOOLEAN", "validationRegex": "^(true|false)$", "defaultValue": null, "required": false, "readOnly": true },
      { "name": "FIRMWARE_VERSION", "dataType": "STRING", "defaultValue": null, "required": false, "readOnly": true },
      { "name": "FILE_DIRECT_DOWNLOAD_ENABLED", "dataType": "BOOLEAN", "validationRegex": "^(true|false)$", "required": false, "readOnly": true },
      { "name": "FILE_URL_DOWNLOAD_ENABLED", "dataType": "BOOLEAN", "validationRegex": "^(true|false)$", "required": false, "readOnly": true }
    ]
  }
]

Enlaces de librerías y repositorios

Esquemático

Ver imagen en sección "Schematics" (conexión I2C Environment Click a MKR1000).

Proceso de manufactura

  1. Construye un Spybot controlado por Bluetooth con Arduino
  2. Sensor K30 CO₂: Monitorización en tiempo real de la calidad del aire interior
  3. FlickMote: Mando IR por gestos para Smart Home
  4. TV‑B‑Gone DIY con Arduino: Mando universal para apagar cualquier TV
  5. Construye un Reloj Maestro LED Personalizado con Alarma – Visible desde 12 Metros
  6. Find Me: Localizador Inteligente de Objetos con Arduino y Bluetooth
  7. Soluciones de Alimentación Optimizadas para Proyectos Arduino
  8. Tres en raya con Arduino, matriz LED MAX7219 y carcasa de cartón
  9. Construye un Robot Cuadrúpedo Inteligente con Arduino: Guía Paso a Paso
  10. Puerta de control de temperatura sin contacto para detección rápida y precisa
  11. Sistema de monitorización de incendios forestales en tiempo real con alertas SMS