工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

Arduino MKR1000 & Environment Click で実現するリアルタイム環境モニタリング

必要な部品と材料

必要な工具

使用するアプリとオンラインサービス

プロジェクト概要

Environment Clickセンサー (温度・湿度・気圧・ガス抵抗・高度) をArduino MKR1000に接続し、WolkAbout IoT Platformで可視化するプロジェクト。1分ごとに測定、15分ごとに送信。送信失敗時はフラッシュメモリに蓄積 (最大96回/日、書き込み寿命10,000回を考慮) し、次回送信時にリトライする堅牢な設計です。

ハードウェア接続

Environment ClickをI2Cピン (MKR1000の11=SDA, 12=SCL)、VCC、GNDに接続するだけ。

ソフトウェア構成

以下のライブラリをArduino IDEのライブラリマネージャーからインストール、またはGitHubからZIPダウンロードして追加:

スケッチの主な機能:

スケッチ修正箇所

// WiFi認証情報 (33-34行目)
const char* ssid = "<*YOUR SSID*>";
const char* wifi_pass = "<*YOUR WIFI PASSWORD*>";

// WolkAboutデバイス認証情報
const char *device_key = "device_key";
const char *device_password = "device_password";

WolkAbout IoT Platformでのデバイス作成

  1. 添付の Environment click-deviceType.json をダウンロード
  2. WolkAboutにログインし、デバイス管理 > デバイスタイプ管理 で「アップロード」からJSONをインポート
  3. デバイス作成: 名前入力、接続タイプ MQTT、デフォルトセマンティック作成 にチェック
  4. 表示されるデバイスキー・パスワードをスケッチに入力

ダッシュボード作成

  1. 可視化と監視 > ダッシュボード追加 で新規作成、スコープをデバイス名に設定
  2. ウィジェット追加: トレンド で温度・湿度・気圧、リーディング で高度、カード でガス抵抗
  3. レイアウト調整して完成

結論

MKR1000 + Environment Click + WolkAboutで、省電力・堅牢なリモート環境モニタリングが実現できます。WolkAboutのルールエンジンを使えば、閾値超過時の通知 (メール、SMS、Webhook等) もノーコードで設定可能です。詳細は ユーザーガイド を参照。

コード

Environment monitoring sketch (Arduino)

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#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;
const byte readEvery = 1;      // 毎分測定
bool publish;
const byte publishEvery = 10;  // 10分ごと送信
byte publishMin;

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) {
        data.head = 0; data.tail = 0; data.empty = true; data.full = false;
    }
}

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

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

bool _pop(outbound_message_t* msg) {
    memcpy(msg, &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) {
            if (++numAttempts == 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;
}

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": "..." } },
      { "name": "Humidity", "reference": "H", "unit": { "name": "HUMIDITY_PERCENT", "guid": "..." } },
      { "name": "Pressure", "reference": "P", "unit": { "name": "MILLIBAR", "guid": "..." } },
      { "name": "Gas Resistance", "reference": "GR", "unit": { "name": "OHM", "guid": "..." } },
      { "name": "Altitude", "reference": "A", "unit": { "name": "METRE", "guid": "..." } }
    ],
    "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 }
    ]
  }
]

関連リポジトリ・ライブラリ

回路図

Arduino MKR1000 & Environment Click で実現するリアルタイム環境モニタリング

製造プロセス

  1. Bluetooth操作のArduinoスパイボットを自作する
  2. K30 CO2センサで室内空気質をリアルタイム監視する
  3. FlickMote:ジェスチャー操作のIRリモコンでスマートホームを制御
  4. 自作Arduino TV-B-Gone:全テレビ対応の万能リモコン
  5. 12メートル先から見える大型LEDマスタークロック(アラーム機能付き)を自作しよう
  6. ArduinoとBluetoothで作るスマート紛失防止タグ「Find Me」
  7. Arduinoプロジェクトのための最適化電源ソリューション
  8. Arduino三目並べ:MAX7219 LEDマトリクスと段ボールケースで自作
  9. スマートArduino四足歩行ロボットの製作:ステップバイステップガイド
  10. 非接触温度スクリーニングゲート:Arduino MKR1000で迅速・高精度な検温
  11. リアルタイム森林火災監視システム: SMSアラート機能付き