Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Manufacturing Technology >> Processo de manufatura

Monitoramento Ambiental em Tempo Real com Arduino MKR1000 e Sensores Environment Click

Componentes e Materiais

Componente Quantidade
Arduino MKR1000 1
MikroE Environment Click (sensor BME680) 1

Ferramentas Necessárias

Software e Serviços Online

Sobre o Projeto

Introdução

Tínhamos alguns sensores Environment Click à mão, então decidimos conectá-los ao Arduino MKR1000 e visualizá-los na Plataforma IoT WolkAbout. A ideia era fazer uma medição a cada minuto e publicar os resultados a cada 15 minutos. Se a publicação das leituras dos sensores falhar (devido a rede ocupada ou outro problema), os resultados devem ser persistidos na memória Flash do dispositivo. Com um máximo potencial de 96 escritas por dia, minimizamos as chances de colocar a memória Flash em um estado errado (o Arduino garante 10.000 ciclos de escrita).

Configuração de Hardware

O sensor Environment Click é conectado aos pinos de comunicação I2C (nomeadamente 11 e 12 no MKR1000), Vcc e terra.

Monitoramento Ambiental em Tempo Real com Arduino MKR1000 e Sensores Environment Click

Configuração de Software

Usamos algumas bibliotecas para tornar este projeto possível, todas podem ser instaladas pelo Gerenciador de Bibliotecas da Arduino IDE, ou baixando arquivos .zip dos repositórios GitHub listados nos anexos e adicionando-os à IDE. As bibliotecas necessárias são:

Uma vez instaladas todas as bibliotecas necessárias, copie o conteúdo do sketch Environment monitoring dos anexos para a Arduino IDE.

Ele implementa uma estrutura de buffer circular e a usa para armazenar os resultados das medições. Há também uma implementação de como armazenar essa estrutura na memória Flash usando a biblioteca FlashStorage. A leitura e publicação temporizadas dos dados são alcançadas usando a biblioteca RTCZero. Inicialmente, após conectar ao WiFi, enviamos um ping para a Plataforma IoT WolkAbout para obter a época atual (epoch) que será alimentada na biblioteca RTC para que as leituras dos sensores possam ser devidamente marcadas com timestamp.

Uma interrupção de alarme altera flags para tarefas que precisam ser feitas (ler e publicar) e o resto do trabalho é tratado na função loop. Aqui verificamos se precisamos ler ou publicar. Para consumo mínimo de energia, o WiFi é colocado em modo de baixa potência, assim como o MKR1000. O sensor no Environment Click entra em modo de baixa potência automaticamente até que uma leitura seja solicitada.

Mudanças que devem ser feitas no sketch incluem inserir credenciais WiFi nas linhas 33 e 34:

const char* ssid = "<*SEU_SSID*>";
const char* wifi_pass = "<*SUA_SENHA_WIFI*>";

Assim como inserir as credenciais do dispositivo da Plataforma IoT WolkAbout.

Para obter essas credenciais, você precisa criar um dispositivo primeiro usando um tipo de dispositivo.

O tipo de dispositivo para este projeto, Environment click-deviceType.json, está disponível nos anexos do projeto, então faça uma cópia dele. Faça login ou crie sua conta na Plataforma IoT WolkAbout e abra o aplicativo Gerenciamento de Dispositivos.

Monitoramento Ambiental em Tempo Real com Arduino MKR1000 e Sensores Environment Click

Selecione a aba Gerenciamento de Tipo de Dispositivo e pressione o sinal + e selecione a opção Upload, navegando até sua cópia local do tipo de dispositivo.

Agora que um tipo de dispositivo está disponível, você pode criar um dispositivo a partir dele clicando em Criar dispositivo.

Aqui, você precisa dar um nome ao seu dispositivo, definir o Tipo de Conectividade para MQTT e marcar a caixa para Criar Semântica Padrão (necessário para criar widgets no seu dashboard depois).

Pressione Salvar e o formulário com as credenciais do dispositivo será exibido. Armazene essa informação como quiser e então insira no seu sketch na Arduino IDE:

const char *device_key = "device_key";
const char *device_password = "device_password";

Agora você pode verificar e carregar este sketch na sua placa, mas ainda precisa criar uma forma de exibir os dados dos sensores recebidos.

Para exibir esses dados, mude para a seção Visualização e Monitoramento na Plataforma IoT WolkAbout e crie um novo dashboard pressionando + Adicionar dashboard e inserindo um nome para o dashboard e definindo o escopo para o nome do dispositivo. Então você pode começar a adicionar widgets ao seu dashboard pressionando Adicionar widget.

Monitoramento Ambiental em Tempo Real com Arduino MKR1000 e Sensores Environment Click
  1. Selecione Tendência (Trending)
  2. Selecione Temperatura do seu dispositivo.
  3. Repita o processo para Pressão e Umidade.
  4. Crie outro widget do tipo Leitura (Reading), selecione Altitude.
  5. Crie outro widget do tipo Cartão (Card) para Resistência de Gás.
  6. Você pode reorganizar os widgets como preferir.

Após adicionar widgets para todas as leituras individuais do sensor que você espera receber do seu dispositivo, o seguinte dashboard estará pronto para receber os dados.

Monitoramento Ambiental em Tempo Real com Arduino MKR1000 e Sensores Environment Click

Vá em frente e implante o dispositivo no ambiente que você escolheu e monitore as condições remotamente.

Conclusão

Ao conectar o Arduino MKR1000 e o Environment Click à Plataforma IoT WolkAbout, você criou uma maneira energeticamente eficiente de relatar as condições ambientais do local que deseja monitorar remotamente. Esta solução pode ser estendida através do uso do motor de regras da Plataforma IoT WolkAbout, que permite receber diferentes tipos de notificações se um certo valor passar um limite que você definiu.

Para mais informações sobre o motor de regras e outros recursos da Plataforma IoT WolkAbout, você pode visitar nossa página de Guias do Usuário.

Código

Sketch de Monitoramento Ambiental (Arduino)

Importe este sketch na Arduino IDE e edite as credenciais WiFi e do dispositivo.

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "WolkConn.h"
#include "MQTTClient.h"

/* Número de mensagens outbound_message_t para armazenar */
#define STORAGE_SIZE 32
#define SEALEVELPRESSURE_HPA (1013.25)

/* Buffer circular para armazenar mensagens de saída para persistência */
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;

/* Detalhes de conexão */
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);

/* Contexto do Conector WolkConnect-Arduino */
static wolk_ctx_t wolk;

/* Inicialização do armazenamento Flash */
FlashStorage(flash_store, Messages);

/* Inicialização comunicação I2C do sensor */
Adafruit_BME680 bme;
RTCZero rtc;

bool read;
const byte readEvery = 1; // Ler sensor a cada minuto. Se mudar, certifique-se que seja <60
bool publish;
const byte publishEvery = 10; // Publicar a cada 10 minutos. Se mudar, certifique-se que seja <60
byte publishMin;

/* Implementação de persistência personalizada e armazenamento Flash */
void _flash_store() {
  data.valid = true;
  flash_store.write(data);
}

void increase_pointer(uint32_t* pointer) {
  if ((*pointer) == (STORAGE_SIZE - 1)) {
    (*pointer) = 0;
  } else {
    (*pointer)++;
  }
}

void _init() {
  data = flash_store.read();
  if (data.valid == false) {
    data.head = 0;
    data.tail = 0;
    data.empty = true;
    data.full = false;
  }
}

bool _push(outbound_message_t* outbound_message) {
  if (data.full) {
    increase_pointer(&data.head);
  }
  memcpy(&data.outbound_messages[data.tail], outbound_message, sizeof(outbound_message_t));
  increase_pointer(&data.tail);
  data.empty = false;
  data.full = (data.tail == data.head);
  return true;
}

bool _peek(outbound_message_t* outbound_message) {
  memcpy(outbound_message, &data.outbound_messages[data.head], sizeof(outbound_message_t));
  return true;
}

bool _pop(outbound_message_t* outbound_message) {
  memcpy(outbound_message, &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 numAttempts = 0;
    while (WiFi.begin(ssid, wifi_pass) != WL_CONNECTED) {
      numAttempts++;
      if (numAttempts == 10) {
        Serial.println("Não conseguiu alcançar 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); // 320°C por 150 ms
  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);
}

/* Rotina de interrupção temporizada */
void alarmMatch() {
  read = true;
  if (publishMin == rtc.getMinutes()) {
    publish = true;
  }
}

Environment click-deviceType.json (JSON)

Tipo de dispositivo usado para criar um dispositivo na Plataforma IoT WolkAbout.

[
  {
    "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",
        "description": null,
        "reference": "T",
        "unit": { "name": "CELSIUS", "guid": "7c805d10-a879-11e9-83cd-0a0027000005" }
      },
      {
        "name": "Humidity",
        "description": null,
        "reference": "H",
        "unit": { "name": "HUMIDITY_PERCENT", "guid": "7c8080a3-a879-11e9-83cd-0a0027000005" }
      },
      {
        "name": "Pressure",
        "description": null,
        "reference": "P",
        "unit": { "name": "MILLIBAR", "guid": "7c807980-a879-11e9-83cd-0a0027000005" }
      },
      {
        "name": "Gas Resistance",
        "description": null,
        "reference": "GR",
        "unit": { "name": "OHM", "guid": "7c805890-a879-11e9-83cd-0a0027000005" }
      },
      {
        "name": "Altitude",
        "description": null,
        "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)$",
        "options": null,
        "defaultValue": null,
        "required": false,
        "readOnly": true
      },
      {
        "name": "FIRMWARE_VERSION",
        "dataType": "STRING",
        "validationRegex": null,
        "options": null,
        "defaultValue": null,
        "required": false,
        "readOnly": true
      },
      {
        "name": "FILE_DIRECT_DOWNLOAD_ENABLED",
        "dataType": "BOOLEAN",
        "validationRegex": "^(true|false)$",
        "options": null,
        "defaultValue": null,
        "required": false,
        "readOnly": true
      },
      {
        "name": "FILE_URL_DOWNLOAD_ENABLED",
        "dataType": "BOOLEAN",
        "validationRegex": "^(true|false)$",
        "options": null,
        "defaultValue": null,
        "required": false,
        "readOnly": true
      }
    ]
  }
]

Links Úteis

Esquemático

Monitoramento Ambiental em Tempo Real com Arduino MKR1000 e Sensores Environment Click

Processo de manufatura

  1. Construa um Spybot Controlado por Bluetooth com Arduino
  2. Sensor K30 CO₂: Monitoramento de Qualidade do Ar Interno em Tempo Real
  3. FlickMote: Controle Remoto IR por Gestos para Casa Inteligente
  4. DIY Arduino TV B-Gone: Controle Remoto Universal para Todas as TVs
  5. Construa um Relógio Mestre LED Personalizado com Alarme – Visível a 12 Metros
  6. Find Me: Localizador Inteligente de Objetos com Arduino e Bluetooth
  7. Soluções de Energia Otimizadas para Projetos Arduino
  8. Jogo da Velha com Arduino, Matriz LED MAX7219 e Caixa de Papelão
  9. Construa um Robô Quadrúpede Inteligente com Arduino: Guia Passo a Passo
  10. Portão de Triagem de Temperatura Sem Contato para Monitoramento Rápido e Preciso