ほこりモニタキット (HMK) の作り方

要約:

ほこりやエアロゾルなど室内空気中の微粒子(室内微粒子)への関心が高まっています。一方で室内微粒子は種類が多い上に、家電の動作や生活行動で変化し、換気や住宅構造にも影響されるなど、複雑な要因が絡んでいて、各住宅内での室内微粒子の状況を把握するのは難しいとされています。

そこで、まずは各住宅の生活者自身が、状況把握の参考とできるような計測装置(HMK:ほこりモニタキット)を開発しました。誰もが簡易かつ安価に室内微粒子を多点計測できるようにすることが目的です。

当ページでは、このキットの製作方法を説明します。

HMKは、室内微粒子(ほこりなど)を多点で計測し、その計測値を、無線で一台のPCに集めることができます。センサ部一個につき4000円以下のコストで、初歩的なIT知識があれば製作できるので、工作感覚で作ってみて下さい。

HMK (Hokori Monitor Kit) は、空気中の微粒子(ほこりなど)を計測し、その計測値を、無線で一台のPCに集めることのできる装置です。

特徴は以下の通りです。

  • 複数のほこりセンサを同時に使うことができます。家の中にたくさん置いて計測できます。
  • ほこりセンサは10秒間、空気中の微粒子量を測って、小さな表示窓に計測値を表示します。(計測間隔は変更可能)
  • 微粒子の量が多いと赤く表示されたり、黄色く表示されたりします。10秒ごとに更新します。
  • ほこりセンサが計測したデータを1分ごとに(1分間の平均値を)、PCに無線で送ります。(送信間隔も変更可能)
  • ほこりセンサ1個につき4000円以下の材料費なので、比較的安価に計測数を増やせます。

図1に計測中の様子を示します。

HMKを使って、どういうものを計測できるのかは、資料1「住宅内での簡易な空気中微粒子計測IoTの可能性と課題」(PDFファイル813kb)を参照してください。

図1 計測中のHMK

2. 用意するもの

  • Raspberry Pi (別途ACアダプタ、SDカードを用意)1個(データ収集用PCとして用いる)
  • M5StickC(別途USB-Cケーブル、USB-ACアダプタを用意)1個以上(必要数)
  • Grove Dustセンサ 1個以上(必要数
図2 M5StickC
図3 Grove Dustセンサ

Raspberry Pi[1]は、ほこりセンサからのデータを受け取って保存するPCとして用います。動作確認をしたRaspberry PiはRaspberry Pi 3です。なお、Raspberry Piでなくても無線LANのアクセスポイントとMQTTでの通信機能を備えていれば、任意のPCが利用できます。Raspberry Piを用いた場合の設定方法を次章で説明します。HMKの処理・通信の全体フローは6.1節で述べます。

ほこりセンサは、M5StickC[2](図2)とGrove Dustセンサ(図3)を接続して作ります。Grove Dustセンサは1μm以上の微粒子を計測でき、販売元がホームページに詳しい仕様を開示しています[3]。また、文献[1]をはじめ多数の論文において、その性能と限界が議論されています。M5StickCは1650円(税込み)[4]、Grove Dustセンサは1720円(税込み)[5]と安価ですので、比較的安価に微粒子計測が可能です。計測値の単位はpcs/0.01cf(pcs/283ml)です。

以下では、Raspberry PiやM5StickCにHMK用のプログラムを書き込んだり、設定をしたりする方法を説明します。Raspberry Pi自体の操作(OSのインストールやコマンド操作など)や、M5StickCへのプログラム書き込み方法は、Webおよび関連書籍を参照ください。

[1] https://www.raspberrypi.org/(2021年2月3日アクセス)
[2] https://m5stack.com/products/stick-c(2021年2月3日アクセス)
[3] 「Grove ダストセンサー(PPD42NS) – Seeedウィキ(日本語版)」https://wiki.seeedstudio.com/jp/Grove-Dust_Sensor/(2021年2月3日アクセス)
「浮遊粒子計測機器 PPD42NJ(ホコリセンサユニット)| 神栄テクノロジー株式会社」https://www.shinyei.co.jp/stc/products/optical/ppd42nj.html(2021年3月4日アクセス)
[4] https://www.switch-science.com/catalog/6350/(SwitchScienceでの2021年2月4日の価格)
[5] https://www.switch-science.com/catalog/3081/(SwitchScienceでの2021年2月4日の価格)

3. ほこりセンササーバー(Raspberry Pi)の設定

3.1設定の概要

センサで計測したデータは、Raspberry Piで受信して、内部に蓄積します。そのための各種ソフトウェア(無線LANのアクセスポイント、DHCPサーバー、DNSサーバー、MQTTブローカー)をインストールします。

3.2 動作を確認したOSとnodeのバージョン

本節以降の設定・プログラムは、以下をインストールしたRaspberry Pi 3で動作を確認しています。

  • Raspbian GNU/Linux 10 (buster)
  • node v 8.17.0 (mqttライブラリ、foreverライブラリをインストール済)

Raspberry PiへのOSインストールと初期設定が完了して、インターネットに接続が完了したら、以下の方法で、nodeおよびmqttライブラリ等をインストールします。$で始まる文字列はターミナルでの入力を意味します。

まず、OSを最新の状態に更新します。

$ sudo apt-get update
$ sudo apt-get dist-upgrade

次にnodeをインストールします。nodeのバージョンを8.17と古いバージョンにしているのは、これは本資料執筆時点で、foreverライブラリが最新バージョンに対応していないためです。

$ sudo apt install npm
$ sudo apt install nodejs
$ sudo npm install n -g
$ sudo n stable
$ sudo apt purge -y nodejs npm
$ sudo n 8.17.0

その後、foreverライブラリと、mqttライブラリをインストールします。foreverは-gを付けてインストールします。

$ sudo npm install -g forever
$ npm install mqtt

最後に、MQTTブローカーをインストールし、起動します。

$ sudo apt install mosquitto
$ sudo systemctl start mosquitto

上記のコマンド入力中には、インターネットから多数のソフトウェアがダウンロードされます。かなり時間がかかりますので、焦らず休憩しながら進めてください。

3.3 無線LANアクセスポイント等の設定

最新のRaspberry Pi OSでは、簡易なアクセスポイントソフトウェア(RaspAP[6])が開発されており、以下のコマンドでインストール可能です。

$ curl -sL https://install.raspap.com | bash

RaspAPをインストール中に、複数回Yes/Noでの問い合わせがありますが、すべてYを指定してください。

[6] https://docs.raspap.com/(2021年3月11日アクセス)

3.4 MQTT関連のインストールと設定

ほこりセンサから受信したデータをcsvファイルとして保存するプログラム(mqttSub200606.js)を保存し、電源ON時に起動するようにします。mqttSub200606.jsのソースコードを以下に示します(MITライセンスとします)。データの保管場所は”/home/pi/omk/log”に固定していますので、変更したい場合はコードを修正ください。このmqttSub200606.jsを”/home/pi/omk”の下に配置ください。

まずプログラムやログを保存するディレクトリを作ります。

$ mkdir ~/omk
$ mkdir ~/omk/log

以下がプログラムのソースコードです(MITライセンスとします)。このコードをmqttSub200606.jsにコピーしてください。Raspberry Piへの持っていく方法としては、PCでテキストファイルとして作成し、USBメモリに保存し、Raspberry Piにコピーする方法が使えます。

/*! mqttSub200606.js v1.0 | MIT License  */ 
var mqtt = require('mqtt');
var fs = require('fs');
var omkhome = "/home/pi/omk/";
var groupname = "dust";
var client = mqtt.connect("mqtt://10.3.141.1", {clientId: "mqttjs01"});

var topic = "/pub/dust";
var message = "";
var CRLF = "\r\n";
var LN = "\n";

var saveData = {};

client.subscribe(topic, {qos:1});

client.on("message", function(topic, message, packet) {
  console.log("message is " + message);
  console.log("topic is " + topic);
  messageobj = JSON.parse(message);
    fs.appendFile(omkhome + "log/"+groupname+"-"+dateString()+".csv", timeString() +","+ messageobj.deviceid +","+ messageobj.value + CRLF, 'utf8', function(err) { });
    checkDust(messageobj.deviceid, messageobj.value); // regist data to array
    saveDataToLog(); // save one shot log
})

client.on("connect", function() {
  console.log("connected " + client.connected);
})

//--------------------------------

function checkDust(sid, data) {
    var sname = sid;
    saveData[sname] = data;
    saveData[sname+'_name'] = 'dust';
    saveData[sname+'_time'] = timeString();
};

function saveDataToLog() {
    var logf = omkhome+"logdust.csv";
    fs.writeFileSync(logf, "", 'utf8', function(err) {} );
    for (var key in saveData) {
	fs.appendFileSync(logf, key+","+saveData[key]+LN, 'utf8', function(err){});
    }
};

function timeString() {
    date = new Date();
    yyyy = date.getFullYear();
    mm = date.getMonth() + 1;
    dd = date.getDate();
    hour = date.getHours();
    min = date.getMinutes();
    sec = date.getSeconds();
    return yyyy+"/"+mm+"/"+dd+"-"+hour+":"+min+":"+sec;
};

function dateString() {
    date = new Date();
    yyyy = date.getFullYear();
    mm = date.getMonth() + 1;
    dd = date.getDate();
    return yyyy+"-"+mm+"-"+dd;
};

プログラム中のclientに指定している10.3.141.1は、このRaspberry PiのIPアドレスです。デフォルトは10.3.141.1ですが、もしRaspAPの設定で変更した場合は、変更後のIPアドレスを指定してください。

Raspberry Pi起動時に、このプログラムが自動的に起動するように、以下のファイルを修正します。

$ sudo nano /etc/rc.local

このファイルのexit 0の前に、以下を追記してください。なお、mqttSub200606.jsを”/home/pi/omk”以下に置いたものと想定しています。異なる場所に置いた場合は、そのパスを指定してください。

/usr/local/bin/forever start /home/pi/omk/mqttSub200606.js

なお、ここでは”/usr/local/bin”に foreverがインストールされている場合を示しています。他の場所にインストールした場合は、sudo which foreverでパスを調べて、そのパスを指定ください。

3.5 再起動時の注意事項とインターネット接続について

以上を修正したら、再起動します。再起動後に、Raspberry Piの無線LANアクセスポイントのパスワードを変更してください。デフォルトは、SSIDがraspi-webgui、パスワードがChangeMeとなっていますが、このまま使い続けるのは止めてください。パスワードの変更手順は以下です。

  1. PCやスマートフォンで、上記アクセスポイント(SSID:raspi-webgui)にアクセスする。
  2. Webブラウザで、https://10.3.141.1にアクセスする。
  3. RaspAPの設定画面が表示されるので、「ホットスポット」メニューの「セキュリティ」タブを選び、パスワードを変更する。

なお、再起動後は、Raspberry Piは、無線LANを使ってインターネットに接続できなくなることに注意ください。理由は、Raspberry Pi標準搭載の無線LAN(wlan0)をアクセスポイント用に利用しているためです。よって、ソフトウェアのインストール等は再起動前に全て終わらせてください。(なお、インストールを忘れたソフトウェアがある場合などのために、付録BにRaspAPを一時的に停止して、無線LANを使えるようにする方法を示します。)

HMKを使うにはインターネットに接続する必要はありませんが、計測したデータをクラウドにアップロードしたりするには、インターネットに接続する必要があります。その場合は、有線LANを使うか、USBポートに3G/LTEモデム(SORACOM Air + AK-020等)を挿入するなどして、標準の無線LAN以外の方法でインターネットに接続してください。または6.2節で述べるようにRaspberry Pi以外に無線LANのアクセスポイントがあれば、M5StickCとRaspberry Piを両方ともそちらに接続することでインターネットに接続できます。

3.6 時計の設定

インターネットに接続していない状態でRaspberry Piを再起動すると、内蔵の時計が正しくない値になり、そのままですとセンサデータの記録時刻も正しく記録されません。よって、手動で時計合わせをするか、インターネットに接続して時刻合わせをする必要があります。手動で設定する場合は、以下のように現在時刻を指定してください。

(2021年2月16日 11:01に設定する例)

$ sudo date --set='2021/02/16 11:01:00'

なお3.5節に述べた方法で、有線LANなどでインターネット接続があれば手動設定は不要です。自動的に時刻合わせが行われます。インターネット接続ができているのに、時刻が狂っている場合は、NTP関連の設定を確認ください。

4. ほこりセンサの接続と設定

4.1 ほこりセンサの組み立て

ほこりセンサは、M5StickCとGrove Dustセンサで構成されます。Grove DustセンサのGroveコネクタをM5StickCに接続します(図4)。Grove Dustセンサは立てて(銀色のフードを上にして)使う必要があるため、ケース等が必要です。もっとも簡単なのは厚紙などで自作する方法です(図5、図6)。ただし、センサに外光が入ると誤計測するので、空気の通り道はふさがないように全体を覆うケースが必要です。

この資料の付録(付録A)に簡単な厚紙ケースの型紙を示します。

図4 M5StickCとGrove Dustセンサを接続した状態
(なお、センサは金属部分が上になるように立てて使用しないと計測できません)
図5 厚紙製のケースに入れた例

M5StickCにはUSB-ACアダプタから電源を供給します。プログラムをM5StickCに書き込む際には、PCとUSBケーブルで接続し、ARDUINO IDE[7]を用いて書き込んでください。

なお、市販のUSB-ACアダプタの中には、電源にノイズが多数含まれているものがあります。そのような製品ですと、計測値が不正確になりますので、ACアダプタを交換して下さい。また2個口(USB出力が2個あるもの)の両方をM5StickCに接続(ACアダプタ1個に対しM5StickCを2個接続)するとノイズを拾いやすいことが分かっています。ACアダプタ1個に対し、M5StickCは1個接続することを推奨します。

[7] https://www.arduino.cc/en/software(2021年2月4日アクセス)
図6 厚紙製ケースの中身
(Grove Dustセンサが箱の中で立つようにしています)

4.2 プログラムの設定

M5StickCに書き込むプログラムを以下に示します(MITライセンスとします)。これをARDUINO IDE経由でM5StickCに書き込んでください。

/*! sketch_GroveDust_mqtt.io v1.0 | MIT License  */
/*
By using this program, you can measure fine particles 
 with Grove Dust sensor by m5stickC and send the data 
 to a MQTT broker. To use it, you need to set the following:
(1) SSID and password of the Wi-Fi access point to which m5stick C connects
(2) m5stick C identifier (deviceID)
(3) IP address of the MQTT broker (Port: 1883, pubTopic = "/pub/dust")
 */
#include <WiFi.h>
#include <ESPmDNS.h>
#include <WiFiClient.h>
#include <M5StickC.h> // comment-out for M5Stack
//#include <M5Stack.h> // for M5Stack
#include <PubSubClient.h>

// 2021.3.10 Fujio Tsutsumi, CRIEPI Japan, tutumi@criepi.denken.or.jp

//----------------------------------------
// User configuration

// Wi-Fi access point information
String wifiSsid = "raspi-webgui"; // Set the SSID of your Wi-Fi access point
String wifiPassword = "PASSWORD"; // Set the password of the Wi-Fi access point

// Device Setting
char *deviceID = "Dust01-01"; // Dust01-01, Dust01-02, ... device ID as mqtt message

// pin asign
int pin = 33; // M5StickC
//int pin = 2; // M5Stack

// MQTT Broker Address
const char *endpoint = "10.3.141.1"; // Set the Raspberry Pi (mqtt broker) IP address

//----------------------------------------
// defaulat parameters

// color range
const int yellowLevel = 2000;
const int redLevel = 7000;

// Wi-Fi setting
int wifiStatus = WiFi.status();
int delayTime = 1000; // wait time for Wi-Fi re-connection

// send data and display interval setting
int interval = 60000; // mqtt send interval (ms)
int dinterval = 10000; // display update interval (ms)
unsigned long sendTime;
unsigned long displayTime;

// MQTT setting
const int port = 1883;
char *pubTopic = "/pub/dust";
char *subTopic = "/sub/dust";
char pubMessage[128];
WiFiClient httpsClient;
PubSubClient mqttClient(httpsClient);

// sensor data global
unsigned long lowpulseoccupancy = 0;
unsigned long lowpulseoccupancyShort = 0; // for display

// 
float brightnessControlAngle = (redLevel - yellowLevel) / (15.0 - 8.0) ;

//----------------------------------------

// initial setup
void setup()
{
M5.begin();
  M5.Axp.ScreenBreath(15); // comment-out for M5Stack
  M5.Lcd.setRotation(1);
  M5.Lcd.setTextSize(2);
  M5.Lcd.fillScreen(BLACK);

  // for DUST Sensor
  pinMode(pin, INPUT);
  
  sendTime = millis();
  displayTime = sendTime;
}

// main loop
void loop()
{
if (wifiSsid.length() > 0 && wifiPassword.length() > 0) // Wi-Fi setting is done
  {
if (wifiStatus != WL_CONNECTED) wifiConnectingProcess(); // Wi-Fi is not connected -> connect to Wi-Fi
    else getDustData();  // Wi-Fi has been already connected -> get dust data and send mqtt broker
  }

  delay(delayTime);
}

// get dust data from sensor and send converted data to MQTT broker
void getDustData() {
  unsigned long duration = pulseIn(pin, LOW);
  lowpulseoccupancy = lowpulseoccupancy + duration; // for send data to MQTT
  lowpulseoccupancyShort = lowpulseoccupancyShort + duration; // for display data

  unsigned long currentTime = millis();
  if (currentTime - displayTime >= dinterval || currentTime < displayTime) {
    // See the Grove web page for the formula below
    // https://wiki.seeedstudio.com/Grove-Dust_Sensor/
    float ratio = lowpulseoccupancyShort / (dinterval * 10.0);
    float value = 1.1 * pow(ratio, 3 ) - 3.8 * pow(ratio, 2) + 520 * ratio + 0.62;

    // display value on the m5stickC LCD
    
    if (value < yellowLevel) displayValue(value, WHITE, BLACK);
    else if (value < redLevel) displayValue(value, BLACK, YELLOW);
    else displayValue(value, BLACK, RED);

    displayTime = currentTime;
    lowpulseoccupancyShort = 0;

    // send data to mqtt broker 
    if (currentTime - sendTime >= interval || currentTime < sendTime) {
      float ratioL = lowpulseoccupancy / (interval * 10.0);
      float valueL = 1.1 * pow(ratioL, 3 ) - 3.8 * pow(ratioL, 2) + 520 * ratioL + 0.62;
    
      // check Wi-Fi connection
      if (wifiStatus != WL_CONNECTED) {
        displayMessage("Wifi disconnected.", WHITE, BLACK);
        return; // when wifi disconnected then exit
      }

      // check MQTT connection
      mqttLoop(); 
        
      // publish message to MQTT broker
      sprintf(pubMessage, "{\"deviceid\": \"%s\", \"value\": %f}", deviceID, valueL);
      mqttClient.publish(pubTopic, pubMessage);
      mqttClient.disconnect();
  
      sendTime = currentTime;
      lowpulseoccupancy = 0;
    }
  }
}

// connect to the MQTT broker
// if disconnected then try to reconnect N=10 times
void connectMQTT() {
  int trialNumber = 0;
  while (!mqttClient.connected() && trialNumber < 10) {
    if (mqttClient.connect(deviceID)) {
      int qos = 0;
      mqttClient.subscribe(subTopic, qos);
    } else {
      trialNumber++;
      wifiStatus = WiFi.status();
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

// check the MQTT connection
void mqttLoop() {
  if (!mqttClient.connected()) connectMQTT();
  mqttClient.loop();
}

// connect to Wi-Fi access point
void wifiConnectingProcess() {
  WiFi.begin(wifiSsid.c_str(), wifiPassword.c_str());
  int trial = 0; // 2020.6.14
  while (wifiStatus != WL_CONNECTED && trial < 10) // check 10 times if failure (0.5 sec interval)
  {
    trial++;
    delay(500);
    wifiStatus = WiFi.status();
    displayMessage("WiFi connecting", WHITE, BLACK);
  }

  if (wifiStatus == WL_CONNECTED) {
    displayMessage("Connected!", WHITE, BLACK);
    delay(500);

    // for MQTT connection
    mqttClient.setServer(endpoint, port);
    connectMQTT();

    delayTime = 0;
  } else {
    delayTime = 1000;
  }
}

// display message on LCD
void displayMessage(String mes, uint16_t fgcolor, uint16_t bgcolor) {
    M5.Lcd.setCursor(0, 0, 1);
    M5.Lcd.setTextColor(fgcolor);
    M5.Lcd.fillScreen(bgcolor);
    M5.Lcd.print(mes);
};

void displayValue(float value, uint16_t fgcolor, uint16_t bgcolor) {
    // Brightness control corresponding to the value
    if (value < yellowLevel) M5.Axp.ScreenBreath(8);
    else if (value > redLevel) M5.Axp.ScreenBreath(15);
    else M5.Axp.ScreenBreath((int)((value - yellowLevel) / brightnessControlAngle + 8));
    
    M5.Lcd.setCursor(15, 25);
    M5.Lcd.setTextSize(4);
    M5.Lcd.setTextColor(fgcolor);
    M5.Lcd.fillScreen(bgcolor);
    int intValue = floor(value);
    if (intValue < 10000) M5.Lcd.print(intValue);
    else { // overshoot
      M5.Axp.ScreenBreath(8);
      M5.Lcd.setTextColor(WHITE);
      M5.Lcd.fillScreen(BLACK);
      M5.Lcd.print("XXXXXX"); // overshoot
    }
};

上記のプログラム中には、ネットワーク接続先の無線LANアクセスポイントのSSIDパスワード(PASSWORD)を記述しています。PASSWORDは3.5節で設定した値に修正ください。またRaspberry PiのIPアドレスをendpointに指定ください。上述のプログラムでは10.3.141.1とデフォルトを指定しています。

また、ほこりセンサを複数台使う場合は、各センサを区別するためにdeviceIDを違うものにしてください。上述のプログラムでは”Dust01-01”としています。これを、例えば、Dust01-01とDust01-02など違うものにして、M5StickCに書き込んでください。

M5StickCの表示窓は、2000を超えると黄色、7000を超えると赤色になるようにしています。これらのしきい値を変更する場合は、以下の箇所を変更ください。

const int yellowLevel = 2000;
const int redLevel = 7000;

5. HMKの使い方

5.1 使用手順

図7 HMKの使用手順

HMKの使用手順を図7に示します。

  1. Raspberry Piに3章で述べた設定を施して、電源を入れます。Raspberry PiとM5StickCの間は無線LANで通信するので、M5StickCからの電波が届く場所にRaspberry Piを配置します。Raspberry Piの時計の設定を忘れないようにします(3.6節)。
  2. M5StickCとGrove Dustセンサを接続します。M5StickCに、4章で述べたプログラムをインストールします。センサごとにプログラム中のIDを変えてください(Dust01-01, Dust01-02など)。
  3. センサをケースに入れて、ほこりなど微粒子を計測したい場所に設置します。ただし、センサにはAC電源が必要なので、付近にコンセントがある場所を選びます。
  4. M5StickCに接続したUSB-ACアダプタをコンセントに差し込みます。M5StickCが起動して、計測を開始すると同時に、Raspberry Piに向かって通信を開始します。

Grove Dust センサは、1μm以上の微粒子を計測できます[8]。計測値の単位はpcs/0.01cf(pcs/283ml)です。単位を「個/cm3」に変換する場合は283で割って下さい。

初期設定では、10秒間隔で計測し、ほこりセンサの画面を更新します。間隔を変更したい場合は4.2節のプログラムの以下の箇所を変更ください。単位はミリ秒です。

int dinterval = 10000; // display update interval (ms)

同じく、初期設定では1分ごとに、センサデータをRaspberry Piに送信します。この間隔を変更したい場合も同じプログラムの以下の箇所を変更ください。

int interval = 60000; // mqtt send interval (ms)

Raspberry Piに保存された過去の計測データは、/home/pi/omk/logの下に一日単位でまとめて保存されています。Raspberry Piにモニタ、キーボード、マウス等を接続して中を確認することができます。また、Raspberry Piの外にデータを持ち出す方法としては、USBメモリ等をRaspberry Piに接続してコピーする方法が使えます。また、Raspberry Piの無線LANアクセスポイントにPC等で接続して、リモートアクセスしダウンロードすることも可能です。

[8] https://wiki.seeedstudio.com/jp/Grove-Dust_Sensor/(2021年2月4日アクセス)

5.2 使用上の注意点

ほこりセンサは、赤外線を計測対象の空気に当てて、フォトダイオードで赤外線のチラツキを計測するという原理で微粒子を計測しています[1] 。そのため、センサの計測室(黒いプラスチック部分の穴の中)に外光が入ると誤計測をします。一定の明るさ(明るくても、暗くても)であれば、外光を無視できますが、チラチラと明るさが変わると、あたかも微粒子があるかのように誤計測します。ある程度はケースで遮蔽することで回避できますが、窓際やカーテンの近くなど光が変化しやすい場所に置く場合は、外光がセンサに当たらないように設置に注意ください。

また、一度、外光によって誤計測をすると、不正確な値を出し続ける場合があります(ほこりが全く無い状態で数百の値を出し続けるなど)。その場合は、一度USBケーブルを抜いた状態で、M5StickCの電源をオフにして、再度オンにしてください。電源オフは、画面を前にUSBを右に見て、下のボタンを6秒間押し続けます。オンは同じボタンを2秒押します(図8)。

図8 M5StickCのオンオフ方法

6. HMKの処理フローの全体説明とシステム拡張への示唆

6.1 処理の全体フロー

図9 HMKの処理フロー

図9にHMKの計測からデータ保存に至る全体の処理フローを示します。M5StickCが起動すると、プログラム(sketch_GroveDust_mqtt.io)により、raspi-webguiというSSIDの無線LANアクセスポイントに接続します。Raspberry Pi側はM5StickCにIPアドレスを割り当てて、通信が可能な状態にします。Grove Dustセンサの計測データは、M5StickCで10秒ごとに集約され画面表示され、1分間隔で集約されてmqttでRaspberry Piに送信されます。Raspberry Piではmqttブローカー(mosquitto)が動作しており、データを受信します。Raspberry Piでは、別途mqttSub200606.jsというnode.jsのプログラムが動作しており、mqttブローカーが受信したデータを受け取って、csvファイルの形式で保存します。

6.2 システム拡張への示唆

(1)Raspberry Piへのモニタ搭載

Raspberry Piに小型モニタ等を付けて、計測記録を画面表示することも可能です。標準の7インチモニタとして「Raspberry Pi用 7インチ タッチスクリーン付き液晶ディスプレイ[9]」が販売されています。グラフ表示方法はWebなどに多数の実例が紹介されています。

(2)既に無線LANのアクセスポイントが別にある場合

既に無線LANのアクセスポイント(AP)が別にある場合は、M5StickCとRaspberry Piを、そのAPに接続することで、Raspberry Piの設定を省略でき、かつインターネットに接続可能です。その場合は3.3節の設定は不要です。Raspberry PiをAPに接続してIPアドレスを取得してください。その上で、3.4節のプログラムのclientに指定している10.3.141.1を、そのIPアドレスに修正ください。さらに、4.2節のプログラムの中の、wifiSsidとwifiPasswordを当該APのSSIDとパスワードに変更し、IPアドレスをendpointに指定ください。この拡張を行うと、Raspberry PiとWi-Fiで直接通信できる範囲を超えて、広い範囲で計測することができます。

(3)クラウドへのデータアップロード

クラウド等にデータをアップロードして、インターネット経由でデータを確認するように拡張することも可能です。簡易な手段としてはAmbientサービス[10]を推奨します。Pythonやnode.jsを用いて簡単にデータをアップロード可能です。また、グラフ化機能も豊富でスマートフォンなどから履歴を確認できます。図10にAmbientを用いたグラフ表示例を示します。

(4)質量濃度への変換

HMKの計測値の単位はpcs/0.01cfという個数濃度ですが、空気中の微粒子量は一般的にμg/m3など質量濃度で示されることが多いようです。この単位変換を行う方法が、以下のWebページに紹介されています。

「【Arduino】ダストセンサーでPM2.5測定(μg/m^3単位) | 西住工房」[11]

ただし、この変換は文献[2] を原典とする、粒子径や質量濃度変換係数などに関する、複数の仮定に基づく換算値ですので、あくまで参考として用いるのが妥当と考えます。

[9] https://www.switch-science.com/catalog/2556/(2021年2月4日アクセス)
[10] https://ambidata.io/
(2021年2月4日アクセス)
[11] https://algorithm.joho.info/arduino/grove-dust-sensor-pm2-5-microg-per-m3/
(2021年2月5日アクセス)
図10 Ambientサービスを用いたHMKデータの可視化例

7. おわりに

この資料では、ほこりなど空気中の微粒子を多点で計測できる装置として、HMKの作り方を紹介しました。既存のほこりセンサなどと違い、比較的安価に、10秒毎に連続計測できたり、計測データを長期間記録できたり、また多点を同時に計測できる、といった特徴があります。いろいろな所に置いて計測してみると、空気中の微粒子の空間分布がわかります。

なお、本資料の内容に間違いがある場合は、下記の問い合わせ先に連絡ください。また掲載したプログラムは全てMITライセンス[12]として配布しますので、自由に改造してください。

問い合わせ先:(一財)電力中央研究所 エネルギーイノベーション創発センター

[12] https://opensource.org/licenses/mit-license.php(2021年2月4日アクセス)

【参考文献】

  1. Michaël Canu, Boris Gálvis, and Malika Madelin, “What does the Shinyei PPD42NS Low-Cost Dust Sensor Really Measure?”, International Journal of Environmental Science and Development, Vol. 12, No. 1, January 2021.
  2. M. Uva, R. Falcone, A. McClellan, and E. Ostapowicz, “Preliminary Screening System for Ambient Air Quality in Southeast Philadelphia”, Drexel University, May 13, 2009,  https://www.yumpu.com/en/document/view/31692906/preliminary-screening-system-for-ambient-air-quality-in-southeast- (2021/2/5 access).

付録A 厚紙ケースの型紙

付録B RaspAPを停止して無線LANによるネット接続を復活させる方法

RaspAPをインストールすると無線LANがアクセスポイント用に使われるため、Raspberry Piから無線でネットアクセスができなくなります。常時ネットアクセスするには、有線LANなどを使うしかありませんが、一時的にインターネットアクセスを復活させたい時は以下の方法が使えます。

まず、RaspAPのWebサイト(http://10.3.141.1)で、「ホットスポット」メニューから「ホットスポットを停止」を選びます。

次にRaspberry Piのコンソールで、dhcpcd.confファイルを修正します。

$ sudo cp /etc/dhcpcd.conf /etc/dhcpcd.conf.raspap
$ sudo nano /etc/dhcpcd.conf

修正箇所は、# RaspAP wlan0 configuration以下で、これらを全て削除します。その後、以下のコマンドを実行すると、無線LANによるネットアクセスが復活します。

$ sudo systemctl restart dhcpcd

再びRaspAPに戻す場合は、以下のようにdhcpcd.confファイルを元にもどします。

$ sudo cp /etc/dhcpcd.conf.raspap /etc/dhcpcd.conf

その後、再起動すると、再びRaspAPが動き始めます。