LoginSignup
376
340

More than 1 year has passed since last update.

窓を開けて新鮮な空気をいれよう!Raspberry Pi でCO2 濃度を測ろう

Last updated at Posted at 2015-12-22

English version of this document is available here.

始めに

その会議が眠いのはテーマや議事運営が眠いからというのはもちろんそうなのかもしれませんが、二酸化炭素濃度が上がっていることも原因なのかもしれません。
CO2濃度が2500ppmをこえたあたりから急激に思考力が低下するなんて報告もありますが、人間のCO2排出量って結構すごくて、会議室に数人あつまっただけでかなりCO2濃度は高くなります。冬の閉め切った室内でちょっと灯油ストーブとかつけるとすぐに凄いCO2濃度になったりします。

建設的な会議を進めるために、まずは現状のCO2 濃度を把握してみませんか?

MH-Z19センサー

CO2センサーは non-dispersive infrared (NDIR) といって、赤外線の吸収率がCO2濃度によって変わることを利用して測るのだそうです、かっこいい。 こういうセンサーではスウェーデンの SenseAir 社の K-30 がポピュラーです。使っていらっしゃる方の報告がいくつもありますし、Raspberry Pi でつかうためのアプリケーショノート も通販屋さんから出てるので繋いですぐに使える手軽さと安心感が魅力ですが、安い通販で買ってもかなり高いです

なんか安いセンサーがないかなと探していて見つけたのがこちらです。送料込みで20$代は安いです。ちなみにポチった頃(先月末)よりさらに値段が下がってる気が...

センサー外観

届いたセンサーはあのずっしりとたくましい K-30 とちがってもの凄くちっちゃくて軽いです。開発元サイトをみると15g だそうです。本当に動くのか、ケースの中にちゃんと物が入っているのか心配になるレベルの軽さです ^^;;;
金属光沢がありますが、樹脂性のケースにメッキがしてあるようです

スクリーンショット 2015-12-22 19.02.07.png

接続

どうやって使うんだろうと思って mh-z19 と Raspberry とかで検索してもめぼしいものがでてきません。ますます不安になります。とはいえ、みつけたドキュメントを見ていると PWM(!) と UART のインターフェースがあるようなので、下図のように普通にRaspberry Pi のUART のGPIOと4線でつなぎます。

※2018.09.04 近況
これを書いた2015年末は検索しても本当になにもない状況だったのですが今は随分賑やかになってるみたいで、ちょっと最近の状況とあってないですね ^^/
PWM にびっくりマークを付けたのはそれまで知らなくて「デジタルデータをわざわざ擬似アナログで送るの?」っていう驚きだったんですけど、個人的な感想なので蛇足だったです

mz-h19_ブレッドボード.jpg

事前準備(UARTを空ける)

以前、ToCoStick で Raspberry Pi 同士を SLIP で繋ぐにも書きましたが、Raspberry Pi は起動時に自動的に uart でコンソールを開いてくれている(のでシリアルでバッグができます)ので、uart が塞がっています。
そこで uart を空けるために、事前に下記のように /etc/inittab の末尾の、ttuUSB0 で tty を開く行をコメントアウトしてから起動する必用があります

/etc/inittab
#Spawn a getty on Raspberry Pi serial line
# T1:23:respawn:/sbin/getty -L ttyUSB0 115200 vt100 ※これをコメントアウト

jessie の補足

※2016.07.08 補足
この辺りが jessie で変わっていて、inittab で止めておかなくても systemctl で tty を止めたり再開したり出来るようになってました

sudo systemctl stop serial-getty@ttyAMA0.service
sudo systemctl start serial-getty@ttyAMA0.service

RaspberryPi 3 の補足

※2016.11.24 補足
Raspberry Pi 3 だと 下記2点変更が必要です

  • デフォルトで UART が無効(SoC が2個持ってる内の簡単な方が BT に map?)になっているので、raspi-config で UART を enable にするか、/boot/config.txtenable_uart=1 を追加するかして UART を有効にする スクリーンショット 2016-11-24 10.06.40.png スクリーンショット 2016-11-24 10.07.07.png スクリーンショット 2016-11-24 10.07.20.png

またはこんな感じ↓

スクリーンショット 2016-11-24 10.29.15.png

  • tty が ttyAMA0 じゃなくて ttyS0 になっているので、下記のように tty を開け閉めをし、
sudo systemctl stop serial-getty@ttyS0.service
sudo systemctl start serial-getty@ttyS0.service

/dev/ttyAMA0 ではなく /dev/ttyS0 に読み書きする

def mh_z19():
#    ser = serial.Serial('/dev/ttyAMA0',
    serial_dev = '/dev/ttyS0'
    ser = serial.Serial(serial_dev,
                        baudrate=9600,
                        bytesize=serial.EIGHTBITS,
                        parity=serial.PARITY_NONE,
                        stopbits=serial.STOPBITS_ONE,
                        timeout=1.0)

コード

そして Gas consentration reading のコマンドを投げます。Return Value の Byte2 * 256 + Byte3 が CO2 濃度になるとのことなので、下記のようにシリアルを開いてコマンドなげて結果を読むだけの簡単なコードであっさり動きました。マジックナンバーだらけのコードでどうもすみません ^^;;;

mh_z19.py
# http://eleparts.co.kr/data/design/product_file/SENSOR/gas/MH-Z19_CO2%20Manual%20V2.pdf
import serial
import time

def mh_z19():
  ser = serial.Serial('/dev/ttyAMA0',
                      baudrate=9600,
                      bytesize=serial.EIGHTBITS,
                      parity=serial.PARITY_NONE,
                      stopbits=serial.STOPBITS_ONE,
                      timeout=1.0)
  while 1:
    result=ser.write("\xff\x01\x86\x00\x00\x00\x00\x00\x79")
    s=ser.read(9)
    if s[0] == "\xff" and s[1] == "\x86":
      return {'co2': ord(s[2])*256 + ord(s[3])}
    break

if __name__ == '__main__':
  value = mh_z19()
  print "co2=", value["co2"]

※2016.2.12 遅ればせながらこちらにgistを御用意いたしました
※2018.9.13 pre-require モジュールのインストール、設定、MONITOR™への送信など、必要なものをまとめてこちらに用意しました
これまで用意してなくて大変申し訳ありませんでした
※2018.11.06 遅ればせながらパッケージを pypi にご用意いたしました。本当に必要なのはこれだと気がつくのに3年も掛かってしまい我ながら情けないです ^^;;;

jessie の補足

※2016.07.08 補足
上の補足の通り,jessie だと systemctl コマンドで tty を開け閉めできるので

import subprocess

stop_getty = 'sudo systemctl stop serial-getty@ttyAMA0.service'
start_getty = 'sudo systemctl start serial-getty@ttyAMA0.service'


if __name__ == '__main__':
  subprocess.call(stop_getty, stdout=subprocess.PIPE, shell=True)
  value = mh_z19()
  subprocess.call(start_getty, stdout=subprocess.PIPE, shell=True)

みたいに、UART 読む時だけ tty を閉めてしまうのでもいいのかもしれません

RaspberryPi 3 の補足

※2016.11.24 補足
起動時に RPi3 かどうかチェックして、使う tty を切り替える処理を入れたバージョンをgithubに用意いたしました
中で import してる RPi のモデルチェックモジュール getpimodel.py もgithubに用意してあります
これはこれで他にも使い所がありそうなので、別途 package を作ろうとおもってます(futur works)

getrpimodel は、他にもいろいろ使い所がありそうでしたので大変僭越ではございますがpypi のパッケージにさせていだだきました。pip でインストールしていただければ恐縮でございます

pip install getrpimodel

パッケージのソースはご参考までにこちらにご用意させていただきました

表示

測ったデータはサーバに POST して(mqttが本手なんでしょうけど 1883通してくれないネットワークが結構あるんですよね) Chart.js でグラフにすると(websocket が本手なんでしょうけど 9000通してくれないネットワークが沢山あるのでポーリングで更新)見やすくて便利です。
スクリーンショット 2015-12-22 17.53.21.png

ついでに温湿度も測って飽差も計算してつけてしまうと会議室だけじゃなくてビニールハウスのトマト栽培のCO2施肥管理でもつかえそうです

※2018.09.04 補足
こちらも、MONITORとしてサービスを公開しております
使い方などのご紹介をこちらのブログ(English version is also available here)にご用意いたしましたので、もしよろしければお時間のある時にでも御覧いただけますことが叶えば至福の至りに存じます

こんな感じのサービスです
ss.2018-11-20.11.25.43.png

使っていただけたりしようものならもう大感謝で言葉もないです!

※2020.04.26
Ken Matsui様、Raspberry Pi 3B+でCO2濃度を計測してグラフ表示 で Monitor をご紹介いただきまして誠にありがとうございました。設定方法とか私のドキュメントよりもわかりやすくて脱帽いたしました。

謝辞

Qiita の Raspberry Pi アドベント、ぼーっとしてたら速攻で埋まってしまって登録できず、立て逃げみたいな事になってしまいまして誠に申し訳ありませんでした
登録された方の書かれてた記事がとても参考になり、ありがたく勉強させて頂きました事をこの場を借りてお礼もうしあげさせていただきます

future works

私の所に届いた個体はちょっと高めに出ている気がします。校正が必用みたいです
※2016.02.18 屋外で400ppmで校正しました。こちらもコマンド一発なので簡単でした
あと、時定数というか応答時間というかこれが結構長いです

※2018.09.05 訂正
応答時間が長いんじゃなくて、プレヒート中は正確な値がとれない、ですね。馬鹿な事をもうしまして申し訳ありませんでした。訂正させていただければ幸いです。訂正が遅れましたことも申し訳ありませんでした。

references

  • 会議中の眠気は二酸化炭素濃度が上がっていることが原因かも?! 高い給料の人が集まって寝ててもしかたないですので、きれいな空気にいれかえましょう

  • 室内CO2濃度と眠気・集中力の関係 伊那北高校の生徒の方々によるリサーチ。NDIR の解説がわかりやすいです。教室のCO2濃度と寝ている人の数を計測して回帰直線を計算されているのが興味深かったです

  • MH-Z19 開発元のサイトです

  • MH-Z19のドキュメント 私はこれ以外のドキュメントを見つけられていません

  • AliExpressのショップ ちなみにいろんな人がいろんな値段で出品してます。eBay にもありました

  • 必要なインストールや設定を行うスクリプトを含めて、MH-Z19 を Raspberry Pi で使うソフトウェア一式はこちらに、単に読み取りを行うだけのモジュールはこちらです

  • (※2019.01.23 追加) David さんから教えていただいたRevSpace。全てのコマンドをためしてみた記録が秀逸。range 設定が DataSheet の記載と違う、とか

  • (※2020.12.14 追加) nincube8 さんに教えていただいたんですけどケーブリングに問題なく UARTのドライバの準備も問題なさそうなのに値がとれない場合は1-5kΩぐらいの抵抗でプルアップすると読めることがそうです。私は出会ったことがないのですが信号のレベルが足りてないデバイスがあるみたいですね

  • (※2021.4.4 追加) 申し遅れましたがPWMサポート を追加してます。UART 準備するのめんどくさい 接点インタフェースなので生のGPIOでOK デュポンケーブル4本も用意するのは嫌だ 3本で済みます なんかしらんけどエラーになる TTL レベルに届いてなくてもなんでコレだと読めるのか不思議なのですが とかいう場合の 2nd chance にご検討いただければ幸いです

376
340
25

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
376
340