PM2.5をラズパイで計測するために海外通販BanggoodでPM2.5 PPD42NJを買ってウチのPM2.5を計測してみました。XiaomiのPM2.5計測器も持っているので比較してみます。
計測したデータはラズパイのInfluxDBに登録して、Grafanaで表示させています。
だいぶ前に完成していましたが、ちゃんと計測しない時があって・・・ちょっと使いづらいダストセンサーです。
PM2.5センサー PPD42NJ
使用したセンサーはこちら↓
センサーの仕様
ちょっと違う?ようですが同じようなセンサーの仕様がありました。

ラズパイ・InfluxDB・Grafana構築・使い方
ラズパイ構築やInfluxDB・Grafanaの使い方インストールは以下の別サイトを参考にしてください。



以下、Raspi・InfluxDB・Grafanaのシステムができていること前提で書いていきます。
WxBeacon2を使った記事も書きました。↓

完成図
分かりづらいのですが↓ラズパイに各種センサーを付けて温度・湿度・明るさなども一緒に計測してInfluxDBにあげてGrafanaでグラフにしてます。

本当は風を送ってホコリを計測するのですが、今のところファンは付けてない。

ラズパイとダストセンサーをつないでPM2.5を計測してみる
参考にしたソース
こちらを参考にさせていただきました。ありがとうございますm(_ _)m
PIN
4PINにGPIO18さしたら反応しました。
PM2.5 PPD42NJ | Raspberry Pi |
---|---|
1:GND | GND |
2:? | – |
3:5V | 5V |
4:PIN | GPIO18 |
5:? | – |
下準備
$ sudo apt-get update && sudo apt-get upgrade -y
bluepyなど必要なライブラリをインストールします。
$ sudo apt-get install libglib2.0-dev $ sudo pip install bluepy $ sudo apt-get install -y git openssl libssl-dev libbz2-dev libreadline-dev libsqlite3-dev $ sudo pip install timeout-decorator
Pythonファイル
しばらくWhileしてデータを取得するので数十秒かかる。
改良点は1回実行時に1回だけデータを取得して、定期的にCronでpm2.5.pyを実行するようにしました。
#!/usr/bin/env python # -*- coding: utf-8 -*- import RPi.GPIO as GPIO GPIO.setwarnings(False) import time import binascii import base64 import requests from bluepy.btle import UUID, Peripheral, ADDR_TYPE_PUBLIC, DefaultDelegate from influxdb import InfluxDBClient client = InfluxDBClient(host='192.168.31.53', port=8086, username='root', password='xxxxxxx', database='sensor') measurement = 'air5' tags = {'place': 'raspi-pm2.5','host': 'raspi3B+'} # HIGH or LOWの時計測 def pulseIn(PIN, start=1, end=0): if start==0: end = 1 t_start = 0 t_end = 0 # ECHO_PINがHIGHである時間を計測 while GPIO.input(PIN) == end: t_start = time.time() while GPIO.input(PIN) == start: t_end = time.time() return t_end - t_start # 単位をμg/m^3に変換 def pcs2ugm3 (pcs): pi = 3.14159 # 全粒子密度(1.65E12μg/ m3) density = 1.65 * pow (10, 12) # PM2.5粒子の半径(0.44μm) r25 = 0.44 * pow (10, -6) vol25 = (4/3) * pi * pow (r25, 3) mass25 = density * vol25 # μg K = 3531.5 # per m^3 # μg/m^3に変換して返す return pcs * K * mass25 # pm2.5計測 def get_pm25(PIN): t0 = time.time() t = 0 ts = 30 # サンプリング時間 while(1): # LOW状態の時間tを求める dt = pulseIn(PIN, 0) if dt<1: t = t + dt if ((time.time() - t0) > ts): # LOWの割合[0-100%] ratio = (100*t)/ts # ほこりの濃度を算出 concent = 1.1 * pow(ratio,3) - 3.8 * pow(ratio,2) + 520 * ratio + 0.62 print(t, "[sec]") print(ratio, " [%]") print(concent, " [pcs/0.01cf]") print(pcs2ugm3(concent), " [ug/m^3]") pm25 = round(pcs2ugm3(concent)) json_body = [ { 'measurement': measurement, 'tags': tags, 'fields': {'aqi': pm25} } ] print(json_body) client.write_points(json_body) break PIN = 18 # ピン番号をGPIOで指定 GPIO.setmode(GPIO.BCM) # TRIG_PINを出力, ECHO_PINを入力 GPIO.setup(PIN,GPIO.IN) GPIO.setwarnings(False) if __name__ == '__main__': get_pm25(PIN) # ピン設定解除 GPIO.cleanup()
試してみるとエラーが出る
エラー?が出ているけどちゃんと計測できてる??
$ python pm2.5.py pm2.5.py:58: RuntimeWarning: This channel is already in use, continuing anyway. Use GPIO.setwarnings(False) to disable warnings. GPIO.setup(PIN,GPIO.IN) (0.8397605419158936, '[sec]') (2.799201806386312, ' [%]') (1450.5564774811437, ' [pcs/0.01cf]') (2.2619621467487887, ' [ug/m^3]') ------------------- (1.7081043720245361, '[sec]') (5.693681240081787, ' [%]') (3041.18139406269, ' [pcs/0.01cf]') (4.742343577488136, ' [ug/m^3]') ------------------- (0.9526140689849854, '[sec]') (3.175380229949951, ' [%]') (1648.7214021565205, ' [pcs/0.01cf]') (2.570975663552621, ' [ug/m^3]') -------------------
最初はGPIO15に誤ってさしていて、他のセンサーが使ってたのでエラーになったみたい。
Cronで定期的に実行
最後にCronで定期的にpm2.5.pyを実行します。
3-58/3 * * * * /usr/bin/python /home/pi/script/pm2.5.py
注:GPIOを接続しないまま、Cronで定期的にこのプログラムを実行するとCronが溜まっていってCPU使用率100%近くになって温度が急上昇してラズパイがハングアップします。ご注意ください。
Grafanaの設定
Grafanaをご利用の方はPM2.5.jsonを用意しました。Xiaomi PM2.5測定器も一緒に表示するようになっているので必要なければ削除してください。
こちら↓のJsonファイルを右クリックしてダウンロード後、Grafanaにコピペもしくはアップロードしてみてください。
jsonファイルのインサート方法は以下で書きました。

PM2.5の値が正確ではないのかもしれない
高い数値が出る
グラフの緑の線が洗面所に置いたXiaomiのPM2.5測定器ですが、通常は9~12くらいをウロウロしてますが、ラズパイで作ったPPD42NJ のほうは40~80くらいの高い数値。で、たまに120μg/m3も行くので、もしかしたら?正確ではないのかもしれません。

ラズパイ+PPD42NJ の設置場所は窓際の棚の裏に磁石でくっつけています。ファンで風を起こさないと正確ではないのかもしれませんね。
洗面所でデオドラントスプレーやヘアスプレーを使うとPM2.5の数値が高くなります。

4月ごろのデータと値が違う
2019/4頃に調子が良かった時は、10~15くらいだったので、今とちょっと違うようです。

このダストセンサーあまり当てにならないかな?
XiaomiのPM2.5測定器
洗面所に置いたXiaomiのPM2.5測定器↓こちらはハックしてデータをInfluxDBに登録したので、その設定方法など後ほど書いていきます。

こちら↓でレビューしました。

以下のトラブルはメモです。読み飛ばしてください。
トラブル・ESP32ではうまくいかなかった
以下ちょっとしたトラブルと、現状ではESP32でやってもうまくいきませんでした。
ラズパイで18番接続しているはずだけど?「0」になってる・・・?
$ gpio readall +-----+-----+---------+------+---+---Pi 3B+-+---+------+---------+-----+-----+ | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM | +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+ | | | 3.3v | | | 1 || 2 | | | 5v | | | | 2 | 8 | SDA.1 | ALT0 | 1 | 3 || 4 | | | 5v | | | | 3 | 9 | SCL.1 | ALT0 | 1 | 5 || 6 | | | 0v | | | | 4 | 7 | GPIO. 7 | IN | 1 | 7 || 8 | 1 | ALT5 | TxD | 15 | 14 | | | | 0v | | | 9 || 10 | 1 | ALT5 | RxD | 16 | 15 | | 17 | 0 | GPIO. 0 | IN | 0 | 11 || 12 | 0 | IN | GPIO. 1 | 1 | 18 | | 27 | 2 | GPIO. 2 | IN | 0 | 13 || 14 | | | 0v | | | | 22 | 3 | GPIO. 3 | IN | 0 | 15 || 16 | 0 | IN | GPIO. 4 | 4 | 23 | | | | 3.3v | | | 17 || 18 | 0 | IN | GPIO. 5 | 5 | 24 | | 10 | 12 | MOSI | ALT0 | 0 | 19 || 20 | | | 0v | | | | 9 | 13 | MISO | ALT0 | 0 | 21 || 22 | 0 | IN | GPIO. 6 | 6 | 25 | | 11 | 14 | SCLK | ALT0 | 0 | 23 || 24 | 1 | OUT | CE0 | 10 | 8 | | | | 0v | | | 25 || 26 | 1 | OUT | CE1 | 11 | 7 | | 0 | 30 | SDA.0 | IN | 1 | 27 || 28 | 1 | IN | SCL.0 | 31 | 1 | | 5 | 21 | GPIO.21 | IN | 1 | 29 || 30 | | | 0v | | | | 6 | 22 | GPIO.22 | IN | 1 | 31 || 32 | 0 | IN | GPIO.26 | 26 | 12 | | 13 | 23 | GPIO.23 | IN | 0 | 33 || 34 | | | 0v | | | | 19 | 24 | GPIO.24 | IN | 0 | 35 || 36 | 0 | IN | GPIO.27 | 27 | 16 | | 26 | 25 | GPIO.25 | IN | 0 | 37 || 38 | 0 | IN | GPIO.28 | 28 | 20 | | | | 0v | | | 39 || 40 | 0 | IN | GPIO.29 | 29 | 21 | +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+ | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM | +-----+-----+---------+------+---+---Pi 3B+-+---+------+---------+-----+-----+
PINがちゃんとハマってないだけだったみたい・・・違うジャンパピンに変えたら動いた。
ESP32で試したけどうまくいかなかったが、Arduino UNOだとうまくいくみたい。
コメント