RaspberryPi
PM2.5計測システのつくりかた

センサー故障のため、観測を中止しています。シャープ製のPM2.5センサー DN7C3CA007が入手できません。(2023/03/20)

 PM2.5は健康被害があり、最近隣国で深刻な状況で、我が国にも飛来してきます。  粒子状物質の測定法は主に、大気を吸引してフィルタ上に粒子を集め電子天秤でその重量を測定する「フィルタ法」と、同様に集めた粒子にベータ線を照射してその透過率から重量を測定する「ベータ線吸収法」、フィルタ経由でカートリッジに集めた粒子を振動により重量測定する「フィルタ振動法」 があるようです。いずれの測定器もアマチュアには手が出せませんが、空気清浄機や煙式火災報知器につかわれている、レーザ光がホコリで散乱する原理のホコリセンサーであれば、入手可能です。
 いままで神栄テクノロジー株式会社のPPD 42NJを用いていましたが、たびたびセンサーの不良で、そのたびに新品と交換してきましたが、正確な計測ができているのか、自信が持てませんでした。ケースにいれていたにもかかわらず、屋外の高温多湿の空気を取り入れるため、金属部分にさびが発生し、連続計測は困難でした。最近、PM2.5専用のシャープ製のセンサー DN7C3CA007を入手しましたので、あらたに計測システムを構築しました。なにより優れている点は、ホコリの濃度をμg/m3単位で知ることができる点です。

 (2017/09/20公開  2018/01/09温度による補正を盛り込みました) 
インターフェース2018年3月号に記事掲載されました。

DN7C3CA007センサーモジュール
 シャープ製のホコリセンサーユニットには、いくつかの種類があり、いずれも赤外発光ダイオードIRED(Infrared Emitting Diode)とフォトトランジスタを斜めに配置し、空気中の汚れからの反射光量を検出する方式です。GP2Y1010AU0Fをもちいた、ホコリセンサーの事例がいくつか発表されています。
 2013年12月にシャープは新たにPM2.5以下の浮遊している粒子だけを取り込むことを可能とした「バーチャルインパクタ方式」を応用した分粒器を開発し、これとホコリセンサーユニットを組み合わせた方式を発表しました。記者発表時の資料が公開されていますが、自信作のようです。現在入手可能なPM2.5センサモジュールは「DN7C3CA007」で、米国、あるいは中国のサイトから入手可能です。

              PM2_5専用のシャープ製のセンサー
製品名 PM2.5 Sensor module DN7C3CA007
機能 ファンによる風圧を利用し、微粒子物質(PM2.5)を通過させる|分流器とPM2.5を検知するセンサーを一体化したセンサモジュール
仕様 電源電圧:Vcc 5 ± 0.25 V 最大20mA
ファン電圧:5 ± 0.25 V 90mA
入力端子電圧:- 0.3 〜 Vcc オープンドレイン駆動入力
動作条件:-10〜60℃ 10〜90%RH 結露しないこと
寸法:51X53X37mm 53g
データシート こちら
価格 5000円程度(Digi-Key あるいはebay.comなど)

 バーチャルインパクタ方式とは、次のような説明がデータシートにあります。すなわち図のようにファンによる風圧を利用し微小粒子状物質(PM2.5)とそれ以外の大きな粒子を分流させる分粒器があり、PM2.5のみをホコリセンサーユニットで検出するものです。


 購入した製品を分解すると、次のようでした(タッピングビス等を外してはいけない)。すなわち、中央に空気が通過する穴のあるホコリセンサーユニットと、ファンの付いた本体、さらに分流するためのいくつかの黒のプラスチック部品で構成されます。このあたりが開発上のノウハウなのでしょう。つかわれているホコリセンサーユニットの型番はGP2Y1012で、一般的なGP2Y1010より高感度とのことです。ファンのON/OFFにより、ホコリセンサーユニットを通過する空気を制御しています。
 データシートには取り付けに際し次のような注意書きがあります。
「測定物質は吸気口(ファンと反対側)から入りファンから出ていきます。モジュールは気流を邪魔しない風通りの良い場所に設置してください。吸気口が上向きになる様筐体設計下さい。設置時に吸気口を下向きにすると特性が得られませんので、吸気口は下向きにしないようお願いします。」



 以下データシートを抜き書きしていきます。ホコリセンサーユニットの計測方法はGP2Y1010と同じで、発光素子を決められたパルスLEDで駆動し、ホコリ粒子により反射された光を受光素子で受けます。増幅回路から出力される電圧Voを所定のタイミングで読み取ります。


発光素子に与える電圧V-LEDには注3で示されるC,Rを接続します。また発光と読み取りのタイミングは注4の通り規定されていおります。


これにより得られたサンプリング電圧を次のようなステップで、PM2.5の濃度(μg/m3)に換算します。

(1) ほこりの少ない環境下あるいは、ファンを止め数分経過後(ほこりが重力で落ち着いた状態)に出力電圧を計測し、それを基準電圧(Vs)とします。(キャリブレーション)
(2) つぎにファンを回した状態の出力電圧(Vo)と基準電圧(Vs)との差(Vo[mV] - Vs[mV])から、次の式によりPM2.5の濃度(μg/m3)に換算します。
換算式:
PM2.5 濃度(μg/m3)= α × β × (Vo[mV] - Vs[mV])
α : 実環境における換算係数 ( "0.6" を推奨 )
β : 湿度hによる補正係数
   h>50%の場合 β = 1 - 0.01467 × (h - 50)
   h≦50%の場合  β = 1
(3) ここでβについては、次のように記述されています。
「大気中のほこりなどが湿気により吸湿した場合、検出可能粒径 (大気含有0.5um)以下のほこりの粒径が大きくなります。その結果、検出可能粒径以下のほこりの粒径が検出可能粒径範囲内に入り、 濃度係数を補正する必要があります。そのため、湿度による影響を”β”で補正することを推奨します。」
たしかに、湿度が10%変化した場合、測定値は15%変化しますから、無視できません。
(4) このモジュールは温度が増加することにより基準電圧及び出力電圧が増加します。温度特性 は、データシートによれば、温度1℃に対して、6mVです。モジュールの標準的な特性は25℃で得られていますので、次のような温度Tによる補正値γを計算します。
γ = 6×(T-25)  [mV] 
そして計測された電圧からVo − γのように差し引くこととします。(2018/01/09温度による補正追記)
(5) ファンモータのON/OFFがキイです。次のような注意書きがあります。
「ファンの平均寿命(MTTF)を 15,000時間 としております。そのため、当モジュールは長寿命化のため間欠動作を推奨しています。PM2.5物質を測定するときだけファンを動作することにより、ファン寿命が延び、ほこりもたまりにくくなりますので、その使用方法を強く推奨します。ファンの間欠動作の ON時間は Min : 10秒 となります。ただし、ON時間を長くする方がより安定した値を得ることができます。」
 これらの条件により、プログラムを作成していきます。


 こまかなタイミングをとり、またアナログ出力を読み取る必要があること、またファンモータのON/OFFをプログラムから制御する必要があります。(1)の基準電圧の決定時にはファンモータをOFFにして計測、本番時(2)ではファンモータをONしなければなりません。
 このようなセンサーを直接RaspberryPiで制御するのは難しいので、Arduinoマイコンを用いることとします。また、従来からRaspberryPiをWindowsPCからファイルとしてアクセスしデータを取り込んできたので、それは継承したいとおもいます。したがって系としては
DN7C3CA007 → Arduino → RaspberryPi → WindowsPC
となります。


ArduinoとRaspberryPiの接続
 ArduinoとRaspberryPiの接続には、I2C通信による方法、シリアル通信による方法があります。さらにシリアル通信はUSBを使う場合とGPIOのUART(Universal Asynchronous Receiver/Transmitter)端子をもちいる方法があり、ここでは後者をトライします。

 RaspberryPiは3.3V 系、Arduinoは5V系ですので、直接接続しない方がよさそうなので、抵抗で分圧し、下の図のように接続します。Arduinoではデジタル端子D2、D3を用いています。RaspberryPiでは、GPIO8,10がUART端子です。


 RaspberryPiとの通信テストを行ってみます。Arduino側には次のプログラム(スケッチ)を用意します。
 #include <SoftwareSerial.h>ソフトウェアシリアルライブラリをincludeします。ソフトウェアシリアルライブラリはArduinoの標準ポート以外のピンを使ってシリアル通信を行うために開発されました。06行でRX,TXをどのピンを用いるかを指定しています。
 18行のRasPiSerial.available() はソフトウェアシリアルポートのバッファに何バイトのデータが到着しているかを返しますので、RaspberryPiからデータが届いたことを監視することができます。1文字ずつバッファにとりこんで、くみたて、文字列が所定のコマンドか確認し、メッセージ "Hello Pi"をRaspberryPiに返送します。

 RaspberryPiとの通信テスト  RaspberryPi_serialtest.ino
/* 2017/09/17 RaspberryPiとの通信テスト
 * RaspberryPiからコマンド"get"が来たら、"Hello Pi"を送り返す
 */

#include <SoftwareSerial.h>
SoftwareSerial RasPiSerial( 2, 3 );// RX, TX

void setup()
{
  Serial.begin(9600);
  RasPiSerial.begin(9600);
}

void loop() {
  String RasPi = "";
  char inChar;
  int length_buf = 0;
  if (RasPiSerial.available() > 0) {//RaspberryPiからバッファに文字が入ったら
    delay(100);
    length_buf = RasPiSerial.available();
    for (int iii = 0; iii < length_buf; iii++) {//1文字づつ取り込んで
      inChar = RasPiSerial.read();
      RasPi.concat(inChar);//つなげる
    }
    Serial.println(RasPi);
    if (RasPi == "get") {//"get"だったら
      RasPiSerial.println("Hello Pi");//"Hello Pi"を送り返す
    }
  }
}





 つぎにRaspberryPi側の準備です。UARTを使えるようにします。


RaspberryPi モデルB (OSはRASPBIAN WHEEZY)の場合

ステップ1  /boot/cmdline.txtを次のように編集
$ sudo nano /boot/cmdline.txt
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait

dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
のように編集。すなわちconsole=ttyAMA0,115200 という部分を外し、ttyAMA0をコンソールとして使用しないようにします。

ステップ2 /etc/inittabの最後の行をコメントアウト
$ sudo nano /etc/inittab
#Spawn a getty on Raspberry Pi serial line
#T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100

ステップ3 リブートして/devディレクトリのなかに、ttyAMA0 があるのを確認します。このデバイス名は、後ほどプログラムに必要です。

ステップ4 つぎにPythonからUARTを使えるようにするために、シリアルポート操作ライブラリpython-serialをインストール
$ sudo apt-get install python-serial


RaspberryPi モデルB3(OSはRaspbian Jessie)の場合(こちらを参考)

ステップ1  /boot/cmdline.txtを次のように編集
$ sudo nano /boot/cmdline.txt
dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p7 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait

dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p7 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
のように編集。すなわちconsole=serial0,115200という部分を外します。

ステップ2 /dev/ttyS0 をGPIOから使えるようにつぎの2つを実行します。
$ sudo systemctl stop serial-getty@ttyS0.service
$ sudo systemctl disable serial-getty@ttyS0.service

ステップ3 config.txtを次のように編集
$ sudo nano /boot/config.txt
config.txtの最後に
enable_uart=1
を追加

ステップ4 リブートして/devディレクトリのなかに、ttyS0 があるのを確認します。このデバイス名は、後ほどプログラムに必要です。

ステップ5 つぎにPythonからUARTを使えるようにするために、シリアルポート操作ライブラリpython-serialをインストール
$ sudo apt-get install python-serial


 つぎにRaspberryPi側に次のArduinoとの通信テストプログラム  arduino_serialtest.pyを準備します。ttyのデバイス名は上記により変更します。

Arduino側でRaspberryPi_serialtest.inoが動いていれば、このプログラムが定期的に"get"コマンドをおり、Arduinoから返事"Hello Pi"が返されます。
 Arduinoとの通信テスト  arduino_serialtest.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 2017/09/17 Arduinoとの通信テスト
# Arduinoにコマンド"get"を送り、相手側からのデータを受信する

import serial #UARTを読めるようにserialをinclude
import time


def setup():
	global s
	s = serial.Serial('/dev/ttyAMA0',baudrate=9600, timeout=5)#ttyAMA0 にUARTの設定 

def readdata():#受信
	return s.readline()

if __name__ == '__main__':
	setup()
	while True:
		s.write("get")#コマンドを送る
		print (readdata())#受信データをプリント
		time.sleep(5)
		

 これにより、ArduinoとRaspberryPiとの間で通信が可能となり、RaspberryPiの指示に従ってArduinoからデータを送ることができるようになりました。

PM2.5センサの作成
 つぎにハードウエアの工作です。回路図は下記の通りです。RaspberryPiとArduinoとの接続は上と同じです。DN7C3CA007とArduinoとは6ピンのヘッダで接続します。データシートの通りLED駆動のために150Ωと220μFのケミコンが必要です。さらにFANのON/OFFをソフトから行うためにArduinoのデジタル端子D8を使います。ファンモータ駆動に90mA必要ですので、トランジスタ2SC1815で電流増幅しています。


 Arduinoとしてはさまざまモデルがありますが、安価な秋月電子のAE−ATMEGA−328 MINIをつかいました。この回路を組み立てる基板としては同じく秋月電子のRaspberry Pi用ユニバーサル基板を使用してみました。RaspberryPiのGPIOの配線やVcc、グランド線のとりまわしがとてもやりやすく、お勧めです。
 写真はくみ上げたもので、下から旧型のRaspberryPiモデルB(RCAビデオ端子は撤去)、その上にRaspberry Pi用ユニバーサル基板、さらにその上に部品とArduinoがのっています。この基板はRaspberryPi B3でも使えます。
 


 DN7C3CA007とArduino、RaspberryPiを一つのケースに納め、屋外に設置します。タカチのTW13-5-13がセンサーの高さにぴったりでした。空気の取り入れ口の工作が必要です。



雨のかからない場所で、上から風を取り込み下に吹き出すように設置します。



Arduinoの読み取りソフトの作成

 通常ArduinoとPCとはUSB接続して、スケッチ(プログラム)をPCから送り込んだり、Arduinoからの出力をPCに送信したりします。開発時はこの通りですが、いったん運用に入ってからは、PCから離れた場所に設置されるため、USB接続はできません。したがってArduinoにあるプログラムはPCからの遠隔更新はできず、ROMに焼き付けたプログラムと考えたほうがよろしい。これを前提にRaspberryPiとの機能分担を考えます。すなわちArduino側ではなるべく汎用的な基本機能に限定し、変更があり得るものはRaspberryPiに持たせることとします。細かな機能に分割しすぎるとArduinoとRaspberryPiの通信量がふえますので、悩ましいところです。

 そこで、次のようなArduinoプログラムを作りました。

(1)  センサーのFanをONして計測する場合と、OFFにして計測する場合があるので、RaspberryPiから、"FanOFF"あるいは "FanON"というコマンドをおくり、それによりファンモータを制御し計測をする。
(2) 複数回計測し、平均値をRaspberryPiに返す。
(3) 測定の間隔、リファレンスとの差の計算、湿度の補正、ppm値への換算、ファイルへの書き込み、LANとの接続などはRaspberryPiで実行する。

  DN7C3CA007センサー読み取りArduinoプログラム  PM2_5.ico
/*
  PM2.5 Sensor Reader
  RaspberryPiからのコマンド(FanOFF FanON)があると1回計測 
  VsRead(0-1023の値)を返す
*/

//   Arduinoピン番号
#define SensorPin 0  // DN7C3CA007のA Voを A0につなぐ
#define PowerLEDPin 7  // DN7C3CA007のC LEDを D7につなぐ
#define PowerFanPin  8 // Fanを D8につなぐ

// データシートにより各種タイミングを設定:   パルス幅 = 0.32ms サンプリング = 0.28ms
int Tsample = 280; // サンプリングのタイミング 0.28ms 
int deltaTime = 40; // サンプリングのあとLEDをoffにするまでの時間 0.32ms - 0.28ms

// global variables
unsigned long time1;
int timer0 = 10000;//Fanを回転してから計測開始まで
int timer1 = 1000;//読み取り周期
int timer2 = 100;//0.1秒 文字読み取り
int countReading = 10; //reading counter
float OutputVoltage = 0.0;
String data = "";
String FAN = "FanOFF";

//RaspberryPi接続用SoftwareSerial
#include <SoftwareSerial.h>
SoftwareSerial RasPiSerial( 2, 3 );// RX, TXのピン番号

// セットアップ
void setup() {
  RasPiSerial.begin(9600);
  Serial.begin(9600);
  pinMode(PowerLEDPin, OUTPUT); //declare LED output
  pinMode(PowerFanPin, OUTPUT); //declare Fan output
  SensorVoltage();//1回読み飛ばし
  Serial.println("Measurement start");
}

// メイン
void loop() {
  String RasPi = "";
  char inChar;
  int length_buf = 0;
 //RaspberryPiとの通信
  if (RasPiSerial.available() > 0) {//RaspberryPiからバッファに文字が入ったら
    delay(timer2);
    length_buf = RasPiSerial.available();
    for (int iii = 0; iii < length_buf; iii++) {//1文字づつ取り込んで
      inChar = RasPiSerial.read();
      RasPi.concat(inChar);//つなげる
    }
  //コマンドに従って計測
    if (RasPi.indexOf("FanOFF") >= 0) {//RaspberryPiからの指示が"FanOFF"の場合
      digitalWrite(PowerFanPin, LOW); // Fan停止
      FAN = "FanOFF";
      Serial.println(FAN);
      measure();//Fan停止して計測
    } else if (RasPi.indexOf("FanON") >= 0) {//RaspberryPiからの指示がFanONの場合
      digitalWrite(PowerFanPin, HIGH); // Fanを回す
      FAN = "FanON";
      Serial.println(FAN);
      delay(timer0); //FanONしてから10秒後に計測開始
      measure();
      digitalWrite(PowerFanPin, LOW); // Fan停止
    }
  }
}

// LEDをパルスで駆動し出力される電圧Voを所定のタイミングで読み取る
int SensorVoltage() {
  int VsRead = 0;
  digitalWrite(PowerLEDPin, LOW); // LED点灯 逆相に注意
  delayMicroseconds(Tsample); //Tsampleを待つ
  VsRead = analogRead(SensorPin); // 出力電圧を読む
  delayMicroseconds(deltaTime); //残り時間を待つ
  digitalWrite(PowerLEDPin, HIGH); // LED消灯 
  return  VsRead ;//出力は0-1023の値
}

// 複数回読んで平均する
void measure() {
  long VsTotal = 0;
  for (int i = 0; i < countReading; i++) {
    VsTotal = VsTotal + SensorVoltage();
    delay(timer1);
  }
  OutputVoltage = VsTotal / (float)countReading;
  time1 = millis() ;
  data = (String)time1 + "," + (String)OutputVoltage + "," +  (String)FAN;
  Serial.println(data);  
  RasPiSerial.println(data);//RaspberryPiに報告
}




本番用プログラムの作成


 そしていよいよRaspberryPiで動く、計測ソフトの作成です。Pythonの6つの関数と一つのmainプログラムからなります。

setup()でUARTをオープンします。

readdata()はArduinoからの報告を読みます。返されたデータはCSV形式ですから、","で分割、aryに入れます。さらに0-1023の電圧を、0-5000mVに変換します。そして下に述べるγを引きます。

calibrate()は基準電圧を求める関数です。ホコリが重力で落ち着いた状態を作るため5分間モータを停止した後、readdata()し、何回かの平均値を基準電圧とします。

weather()は、現在の温度、湿度を求めます。 私の場合、別途温度湿度をリアルタイムに計測しておりWindowsPCに保持していますので、その値で補正することとしました。この関数ではWindowsPCファイル(ファイル名currentweather.csv)を読みに行き、変数temperaturehumidityを最新の値に更新します。
 Windows上のファイルにRaspberryPiからアクセスするにはmount.cifsというコマンドを用います。mount.cifsは、「samba-client」パッケージに含まれてており、インストールしておきます。 そして、RaspberryPi上でWindowsPCのIPアドレスに対し
$ sudo mount.cifs //192.168.X.XX/MyDocuments /mnt/win
を実行します。これにより、WindowsPCのMyDocumentsファイルがRaspberryPiのプログラムから/mnt/winディレクトリとして見えるようになります。
専用の湿度計を実装する方法もあり、手っ取り早いかもしれません。

beta()においては、湿度により変化するβ値を求めています。
gamma()において、温度からγ値を求めています。

メインプログラムでは、はじめにsetup()calibrate()を呼んでいます。
つぎにRaspberryPiからs.write('FanON') によりArduinoにFanONのコマンドを送った後、readdata()します。データシートの換算式に基づき、PM2.5の濃度を計算します。タイムスタンプと共にファイルに出力します。1分に1回観測します。

 PM2.5計測プログラム  PM2_5.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 2018/01/10 (C)Dr.Ishikawa
# sudo mount.cifs //192.168.1.6/MyDocuments /mnt/winでマウントしておく

import serial #UARTを読めるようにserialをinclude
import time
import datetime
RefVoltage =  2000.0
alpha = 0.4 #alpha factor 本文参照
Vcc = 5.0
temperature = 25.0
humidity = 50.0

#WindowsPCにある気象データ
winfilename = '/mnt/win/weatherdata/logfiles/currentweather.csv'

def setup():
	global s
	s = serial.Serial('/dev/ttyAMA0', baudrate=9600 )

def readdata():
	result = s.readline()
	ary = result.split(",") #CSVファイルデータを","で分割、aryに入れる
	if len(ary) > 2:
		OutputVoltage = Vcc * float(ary[1]) / 1024 * 1000.0 #0-1023の電圧を、0-Vcc mVに変換
	else:
		OutputVoltage = 0.0
	return OutputVoltage  - gamma() #γ補正値 本文参照

def calibrate():
	print "wait for calibration"
	s.write('FanOFF')
	for i in range(5):#5分
		print " ."
		time.sleep(60)#1分停止
	VsTotal = 0.0
	cnt = 0
	Vs = 0.0
	weather()
	while cnt < 10: 
		s.write('FanOFF') #ファンを停止した状態で、Voltageを求める
		VsTotal = VsTotal + readdata()
		cnt = cnt + 1
		Vs = VsTotal / float(cnt)
		now = datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S")
		data = now + ","  + str(Vs)  + "," + str(cnt)
	print "RefVoltage =" + str(Vs)
	return Vs

def weather():
	#WindowsPCにある気象データを読み変数temperatureとhumidityを最新の値に更新
	try:
		global temperature
		global humidity
		win_data = open(winfilename , "r" )
		win_data.readline()
		currentweather = win_data.readline()  #1行目はタイトル 読み飛ばし
		win_data.close()
		ary1 = currentweather.split(",")
		temperature = float(ary1[1]) #温度は1番目にある
		humidity = float(ary1[2]) #湿度は2番目にある
	except:
		print "WinPC reed error"

def beta():	
	#湿度からβを求める 
	if humidity > 50.0:
		b = 1.0 - 0.01467 * (humidity - 50.0)#データシートによる
	else:
		b = 1.0
	return b

def gamma():
	#温度からγ値を求める
	return 6 * (temperature - 25) #本文参照

if __name__ == '__main__':
	setup()
	RefVoltage = calibrate() #始めにキャリブレートを行う
	while True:
		s.write('FanON') #ArduinoにFanONのコマンドを送る
		weather() #WindowsPCの温度と湿度を読み変数temperatureとhumidityを最新の値に更新
		OutputVoltage = readdata()
		if (OutputVoltage > RefVoltage) :
			DustDensity = alpha * beta() * (OutputVoltage - RefVoltage) #PM2.5の濃度に換算
		else :
			DustDensity = 0.0
		now = datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") #タイムスタンプ
		data = now + "," + str(OutputVoltage) + "," + str(DustDensity) + "," + str(RefVoltage) + "\n"
		filename = 'dustdata/' + datetime.datetime.now().strftime("%Y%m") + 'pm2_5.txt'
		file_data = open(filename , "a" )
		file_data.write(data)
		print (data)
		file_data.close() #書き損じの無いようにすぐ閉じる
		time.sleep(60) #計測周期は1分



観測の実行

 Arduinoのプログラムは、パソコンから書込まれると電源の入っている間はいつも動いています。 RaspberryPi側ではホームディレクトリにプログラムを置き、dustdataというディレクトリを作っておきます。
 Windows上のファイルにRaspberryPiからアクセスするため、上述のmount.cifsコマンドを実行します。そして
$ sudo python ./PM2_5.py で起動します。
 次のようなデータを1分ごとに書込んで、CSVファイルPM2_5.txtができています。
年月日 時刻,OutputVoltage,PM2.5濃度(ppm)
2017/09/05 16:14:42,2206.05,3.15317 
 ファイル PM2_5.txtを、親機のWindowsPCからよんで、適宜グラフ化します。計測された生データはかなり上下に変化が激しいので、30分の移動平均値を求めています。10分に1回グラフを描画し、生データをグレイ、移動平均値をオレンジで示します。こちら
 長時間観測すると、ホコリセンサーユニットはホコリの付着、発光ダイオードの出力低下などにより感度が低下するようです。時々PM2_5.pyを再起動しキャリブレーションを行った方が良いでしょう。私の場合は、1週間に1回、ホコリの少ない深夜に、自動再起動しています。またα(実環境における換算係数)は推奨値 "0.6"としていますが、環境省サイトなどと比較してあまりにかけ離れている場合は、調整したほうが良いかもしれません。

 


 環境省はPM2.5環境基準を「1年平均値 15μg/m3以下 かつ 1日平均値 35μg/m3以下」と定めています。
 傾向としては、PM2.5濃度は日中は高く、深夜には低下します。また。強い風が吹くと高くなり、降雨があると低下します。どうやら近間の人工的活動によるのではないかと考えられます。この上に、近隣国からの飛来が加わります。

top