空気を読む技術2020 (エアクオリティセンサを使ってみた)

5 min read読了の目安(約5100字

本記事はSORACOM Advent Calendar 12月10日分の投稿です

はじめに

PS5 の抽選が外れまくっていて悲しい今日この頃、みなさんいかがお過ごしでしょうか?

昨日発売された LTE-M Shield for Arduino(通称Dragino)、早速注文された方もいらっしゃいますでしょうか?
Arduino で LTE-M 通信を実現するためのボードとしては比較的安価で、Arduino 系でよく用いられているライブラリ TinyGSM に対応している使い勝手の良いモジュールかなと思います。

今回は IoT スターターキット for Arduino にエアクオリティセンサをチョイ足しして、お部屋の空気をセンサーで読み取ってみたいと思います。

エアクオリティセンサ

使用するセンサはこちら(スイッチサイエンスさんの販売ページ)の製品になります。
ルネサスエレクトロニクス製の室内空気質(IAQ)センサと温湿度センサを搭載した基板と、それをArduino 等にI2CやUART接続するための変換基板のセットになっています。

詳細についてはこちらのレポジトリにもありますが、I2C 通信で簡単に空気のクオリティに関連する数値を読み出すことができ、また総合的な空気の質の指標として IAQ と言う数値も得られるので、これを元に換気を行うべきタイミングに促すような使い方が出来そうです。

https://github.com/meerstern/Air_Quality_Sensor_Module

今回は GROVE で接続を行うために、IoT スターターキットに含まれる Grove Beginner Kit for Arduino の GROVE I2C コネクタにセンサを接続していますが、Arduino UNO などでも GROVE コネクタからジャンパーケーブルに変換するケーブルや、GROVE 端子を持つシールドを組み合わせても利用可能だと思います。

全体図

さて、まずはセンサを動かしてみたいと思います。
先ほどのレポジトリにある、AQS.inoというスケッチを動かしてみましょう。

センサーを接続し、スケッチを書き込んで、シリアルモニタを確認すると

Sensor is Found! Sensor is Ready! 
 TEMP: 27.88 'C  HUMD: 38.06 %  Etoh: 0.01 ppm  TVOC: 0.02 mg/m^3  eCO2: 403.20 ppm  IAQ: 1.12   log_Rcda: 4.85 log ohm 
Sensor is Found! Sensor is Ready! 
 TEMP: 27.91 'C  HUMD: 37.99 %  Etoh: 0.01 ppm  TVOC: 0.02 mg/m^3  eCO2: 403.20 ppm  IAQ: 1.10   log_Rcda: 4.85 log ohm 

のようなログが確認出来ました。この数字の中の、eCO2IAQ が換気の目安になりそうです。

データ送信

さて、Grove Beginner Kit には、温湿度・気圧・照度・音量などのセンサーが搭載されておりますので、これらのセンサー情報に加えて eCO2IAQ の情報を Harvest Data にデータを送りつつ、最終的には Lagoon で可視化とアラート通知を行いたいと思います。

Dragino のサンプルコードは以下のレポジトリにまとまっています。

https://github.com/soracom-labs/arduino-dragino-unified

このレポジトリのsend_multiple_sensor_data_with_soracom.ino スケッチを起点にして、ここにエアクオリティセンサの数値を足していきたいと思います。

AQI.ino を見ながら、このスケッチに必要な行を追加していきます。

まず I2C 通信に必要な Wire.h をインクルードします。void setup() の前あたりに入れると良いでしょう。また I2C でセンサにアクセスするための情報もここで定義します。

#include <Wire.h>
#define AQS_ADDRESS   0x32
#define AQS_DATA_LEN  16
#define AQS_ID        0x43

次に setup() の中に Wire.begin(); を追加します(一番最後)。

最後に void loop() の中に センサー情報の読み取り処理を足し、payload にも追加するように変更します。

まずセンサ情報の読み取りについては void loop() の先頭あたりに

  uint8_t rdata[AQS_DATA_LEN];
  int16_t int_eco2,int_iaq;
  float eco2,iaq;
  char buf_eco2[7],buf_iaq[5]]
  
  Wire.requestFrom(AQS_ADDRESS, AQS_DATA_LEN);
  for(int i=0;i<AQS_DATA_LEN;i++)
  {
    rdata[i]=Wire.read();
  }
  Wire.endTransmission();

  if(rdata[0]==AQS_ID)  Serial.print("Sensor is Found! ");
  else                  Serial.print("Sensor is Not Found! ");

  if(rdata[1]==1)       Serial.println("Sensor is Ready! ");
  else                  Serial.println("Sensor is Not Ready! ");
  
  int_eco2 = ((rdata[10]&0xFF)<<8) +(rdata[11]&0xFF);
  int_iaq  = ((rdata[12]&0xFF)<<8) +(rdata[13]&0xFF);
  
  eco2 = int_eco2/10.0;
  iaq = int_iaq/100.0;
  
  dtostrf(eco2, 0, 2, eco2);
  dtostrf(iaq, 0, 2, iaq);

のように処理を足します。

payload へ eco2iaq を足すためには、

  char payload[90];
  sprintf_P(payload, PSTR("{\"light\":%d,\"sound\":%d,\"temp_c\":%s,\"humi\":%d,\"air_pressure_hpa\":%s}"),
    light_mapped_value, sound_mapped_value, temp_buf, humi, hPa_buf);

この部分を下記のように変更します。

  char payload[128];
  sprintf_P(payload, PSTR("{\"light\":%d,\"sound\":%d,\"temp_c\":%s,\"humi\":%d,\"air_pressure_hpa\":%s,\"co2\":%s,\"iaq\":%s}"),
    light_mapped_value, sound_mapped_value, temp_buf, humi, hPa_buf, buf_eco2, buf_iaq);

送信するデータが大きくなったので payload の長さも増やす必要があることに注意が必要です

※コード全体はここから参照できます

https://gist.github.com/j3tm0t0/69cc2c5fa087b1ac818d54bfc15b6cec

さて、このスケッチを動作させると

{"light":62,"sound":19,"temp_c": 26.0,"humi":30,"air_pressure_hpa":1013.7,"co2":405.20,"iaq":1.28}

のようなデータが SORACOM Harvest Data に送信されているようです。

ユーザコンソールでグラフを確認してみましょう。

気圧のデータの桁が多いので、CO2 のグラフだけにしてみると、

ちゃんとデータが送信できているようですね。

ダッシュボード化

次にこのデータを元に SORACOM Lagoon で可視化してみることにします。

空気がものすごく乾いていることがわかりました...どうりで目がすぐ乾いたり、鼻の穴が乾くはずです。加湿器の購入を検討したいと思います。
二酸化炭素濃度については、一人でいる分にはそこまで悪化する事はなさそうですね。オフィスなど人の多い場所ではもっと違った結果を得られるかもしれませんので、後日試してみたいと思います。

ちなみに寝室のモニタリングをしようと思ったんですが、LED が眩しくて断念しました...

まとめ

データをアップロードするサンプルコードを元に、自分で別途用意したセンサの情報を追加で送信したいというケースって結構あると思います。そういった場合、

  1. まずセンサとマイコンだけでデータの読み取りを行ってみる
  2. データ送信を行うコードに、1 の中の処理を移植していく
  3. 送信するデータにセンサデータを含めるように変更する

といった感じでアプローチすると実現できますので、ぜひみなさんもやってみてください。