LoginSignup
3
1

More than 1 year has passed since last update.

ArduinoとGCPで部屋の環境をモニタリングしてみた

Last updated at Posted at 2022-09-22

概要

センサーとArduinoを使って、温度・湿度などをモニタリングしてみました
image.png

使ったもの

準備編

Arduino Yun MiniをWiFiに接続する

こちらの記事を参考に接続しました。

Arduino Yun MiniとI2C接続する

Arduino Yun MiniでのSDA・SCLのアドレスを確認します。
公式ドキュメントの「SCHEMATICS IN .PDF」が回路図で、3Pを見ると次のようになります。

  • SDA: D2
  • SCL: D3

Arduino IDEでスケッチ例「i2c_scanner」を使うことで、接続を確認できます。
image.png

image.png

参考
https://www.denshi.club/cookbook/stem/maker-uno-stem-7-accuracy.html

BME680とArduino Yun Miniを接続する

秋月電子の資料に書いてある手順を参考に、ArduinoIDEにBME680用ライブラリを導入します。
Adafruit 社の"AdafruitBME680Library"のv2.0.2をインストールしました。

Arduino Yun Mini BME680
3.3V 1. VIN
D3(SCL) 2. SCL
D2(SDA) 3. SDA
GND 4. GND

DSC_0001.JPG

サンプルソースが無事動きました🙌
image.png

Temperature = 29.03 *C
Pressure = 1006.25 hPa
Humidity = 64.55 %
Gas = 11.43 KOhms
Approx. Altitude = 16.16 m

実装編

データの保存先をつくる

今回もGCPを使います。
Firestoreだとデータポータルと連動させにくいので、BigQueryにデータを保存します。

  1. データセットを作成
  2. テーブルを作成
    1. ソース: テーブルの作成元「空のテーブル」
    2. スキーマimage.png
    3. パーティショニングなし、クラスタリングの順序はcreatedAt

※フィールド名にキャメルケースとスネークケース混ざってしまったのは失敗

データを受け付けるWEB APIを用意する

Functionsを使います。
第2世代が出ていたのでついそちらを使いました。

Arduinoでうまく認証させられる気がしなかったので、「未認証の呼び出しを許可」で作成しています。
また第2世代なのでHTTPSです。

main.py
import datetime
import os

import functions_framework
from google.cloud import bigquery


@functions_framework.http
def register_monitoring_data(request):
    request_json = request.get_json(silent=True)
    dt_now_iso = datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=9))).isoformat()
    print(request_json, dt_now_iso)

    rows_to_insert = [{
        'createdAt': dt_now_iso,
        'temperature': request_json['temperature'],  # 温度(℃)
        'pressure': request_json['pressure'],  # 気圧(hPa)
        'humidity': request_json['humidity'],  # 湿度(%)
        'gas_resistance': request_json['gas_resistance'],  # 気体抵抗(KOhms)
        'elevation': request_json['elevation']  # 標高(m)
    }]

    table_id = os.environ.get('BIGQUERY_TABLE_ID', 'Specified environment variable is not set.')

    client = bigquery.Client()
    table = client.get_table(table_id)
    errors = client.insert_rows(table, rows_to_insert)
    if errors:
        print("Encountered errors while inserting rows: {}".format(errors))
        return 'NG {}'.format(dt_now_iso)

    return 'OK {}'.format(dt_now_iso)

ランタイム環境変数にBIGQUERY_TABLE_IDで登録先のBigQueryテーブルIDを設定します

ArduinoからJSONでデータを送る

サンプルソースをもとに、API通信を追加しました。
送信先APIがHTTPSなのですが、証明書登録が容量不足でできなかったため、証明書チェックをclient.noCheckSSL()で無視しています。

// 計測まわり
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"
// データ送信まわり
#include <Bridge.h>
#include <HttpClient.h>
#include <Arduino_JSON.h>

#define SEALEVELPRESSURE_HPA (1008.2)
#define HTTP_URL "your url"

Adafruit_BME680 bme; // I2C
const int STATUS_LED = 13;

void setup() {
  pinMode(STATUS_LED, OUTPUT);
  digitalWrite(STATUS_LED, LOW);
  Bridge.begin();
  digitalWrite(STATUS_LED, HIGH);
  delay(3000);

  if (!bme.begin()) {
    digitalWrite(STATUS_LED, LOW);
    Serial.println("Could not find a valid BME680 sensor, check wiring!");
    while (1);
  }

  // Set up oversampling and filter initialization
  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 for 150 ms
}

void exec() {
  if (! bme.performReading()) {
    Serial.println("Failed to perform reading :(");
    for(int i = 0; i < 10; i++) {
       digitalWrite(STATUS_LED, HIGH);
       delay(1000);
       digitalWrite(STATUS_LED, LOW);
       delay(1000);
    }
    return;
  }

  // データ作成
  JSONVar json;
  json["temperature"] = bme.temperature;
  json["pressure"] = bme.pressure / 100.0;
  json["humidity"] = bme.humidity;
  json["gas_resistance"] = bme.gas_resistance / 1000.0;
  json["elevation"] = bme.readAltitude(SEALEVELPRESSURE_HPA);

  String jsonStr = JSON.stringify(json);
  int str_len = jsonStr.length() + 1; 
  char char_array[str_len];
  jsonStr.toCharArray(char_array, str_len); 

  // HTTP通信
  HttpClient client;
  client.noCheckSSL();
  client.setHeader("Content-Type: application/json");

  client.post(HTTP_URL, char_array);
  String payload = client.readString();
  Serial.println(payload);

  client.close();
}

void loop() {
  exec();
  delay(5 * 60 * 1000UL); // 5分(ms)
}

#define HTTP_URL "your url"にさきほど作ったFuctionsのトリガーURLを設定します。
このコードだと容量ぎりぎり98%になってしまったので、他の処理を入れるならJSONをライブラリ無で生成した方がいいかもしれません。

データを表示する

データポータル(旧Data Studio)で、BigQueryのデータを参照してグラフを表示します。
スマホで確認したかったので縦長に配置しました。
image.png
コントロール部品を設定したので、デフォルト今日のデータが表示されます。

まとめ

思っていたよりは手間がかからずモニタリングができました🤗

ソースコードはGitHubに置いてあります。
https://github.com/k-akie/room-monitor

  • これからやりたいこと
    • 値によってSlack通知する(アラート機能)
    • センサー以外に天気などの情報も一緒に表示する
    • 気体抵抗をCO2濃度に換算する
3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1