Raspberry Pi 3 で CO2濃度を測る

2020/03/30 update:
[Raspberry Pi 3 で CO2濃度を測る (Raspbian OS)](https://qiita.com/revsystem/items/76ab1e21d386c5977892) に、手順をアップデートしたものを記載しました。

## はじめに
社内で、この記事をきっかけに「社内のCO2濃度を測ってみたいね」「計測器を買ったり借りたりすると高いから、Raspberry Piでなんとかならないの?」という話になったので、さっそく試してみました。
すでに実績のある手順が公開されているので、参考にしました。

[なぜ、カフェだと仕事がはかどるのか、を実験してみた。](http://chibiblog.hatenablog.com/entry/2017/08/01/084041)
> 端的にいうと、仕事場でいちばん生産性に影響を及ぼす因子は、気温とCO2濃度。その気温とCO2濃度がもっとも低く、生産性を高める環境というのが、自宅でも、オフィスでもなく、カフェなんだとか。


## 参考情報
 - http://qiita.com/UedaTakeyuki/items/c5226960a7328155635f
 - https://www.open-homeautomation.com/tag/raspberry-pi/
 - https://lowreal.net/2016/12/15/3
 - http://eleparts.co.kr/EPXF8W34
 - http://eleparts.co.kr/data/design/product_file/SENSOR/gas/MH-Z19_CO2%20Manual%20V2.pdf

## 前提条件
 - "[RaspberryPi 3 model B に CentOS7をインストール](http://qiita.com/revsystem/items/9989a18116e554c133b6)" でCentOS7をインストールしていること。
 - rootユーザのほかに一般ユーザが存在し sudo コマンドが実行可能であること。
 
## 準備する物
- [アイ・オー・データ機器 UD-RP3BP Raspberry Pi メインボード（Bluetooth、Wi-Fi対応モデル） Raspberry Pi 3 Model B+](https://www.amazon.co.jp/dp/B07SDFCDYQ/)
- [MH-Z19 0-5000PPM CO2室内空気質モニタ用赤外線CO2センサUART / PWM](https://www.amazon.co.jp/dp/B07JF4YTTB/)
- [uxcell ブレッドボードキット 830ポイント 無はんだブレッドボード 65個ジャンパー線付き プロトシールド分配接続ブロック用 1セット](https://www.amazon.co.jp/dp/B09H5RPTTB/)
 
## OSのセットアップ
/boot/config.txt に enable_uart=1 を追加して UART を有効にします。

```
$ sudo vi /boot/config.txt
```

差分

```diff
diff --git 1/tmp/confifg.old 2/tmp/confifg.new
index 671312c..8cfe831 100644
--- 1/tmp/confifg.old
+++ 2/tmp/confifg.new
@@ -10,3 +10,4 @@ disable_overscan=0
 core_freq=250
 sdram_freq=400
 over_voltage=0
+enable_uart=1
```



変更後、OS を再起動します。

```
$ sudo reboot
```
## MH-Z19 の動作環境のセットアップ
### プログラム動作環境のセットアップ

制御プログラムを動かすために、python-pip と pyserial をインストールします。

```
$ cd /tmp
$ sudo curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py"
$ sudo python get-pip.py
$ sudo pip install pyserial
$ sudo pip install redis
```

制御プログラムを取得するために、git をインストールします。

```
$ sudo yum install git -y
```

制御プログラムを git clone で取得します。あわせて制御プログラムから呼び出しているモジュールをインストールします。

```
$ cd
$ git clone https://github.com/UedaTakeyuki/slider.git
$ sudo pip install getrpimodel
```

### ジャンパーワイヤを結線する。
"[窓を開けて新鮮な空気をいれよう！Raspberry Pi でCO2 濃度を測ろう](http://qiita.com/UedaTakeyuki/items/c5226960a7328155635f#%E6%8E%A5%E7%B6%9A)" の接続図を参考にしました。

![IMG_20170822_021845.jpg](https://qiita-image-store.s3.amazonaws.com/0/61809/c8e5204c-f86c-c20c-d729-49bc0f7f5517.jpeg)


### 制御プログラムを実行する。

git clone で取得した制御プログラムを実行します。
出力された値の単位は ppm。この場合は、 453ppm。
[User's Manual](http://eleparts.co.kr/data/design/product_file/SENSOR/gas/MH-Z19_CO2%20Manual%20V2.pdf) よると ±(50ppm + 5%)の誤差があり、外気は約400ppmだそうなので、およそ正しそう。

```
$ cd slider
$ sudo mkdir -p /home/pi/LOG/
$ sudo python ./mh_z19.py
co2= 453
```

### 補正(キャリブレーション)
値が正しくなさそうな場合は、[User's Manual](http://eleparts.co.kr/data/design/product_file/SENSOR/gas/MH-Z19_CO2%20Manual%20V2.pdf) 8ページ目に記載されている `Calibrate zero point` のコマンドを送信する。
`Calibrate zero point` のコマンドは、mh_z19.pyのコードを参考に、以下のように実装。
戻り値はないので、実行のみ。

- calibrate.py

```
# -*- coding: utf-8 -*-
# refer http://eleparts.co.kr/data/design/product_file/SENSOR/gas/MH-Z19_CO2%20Manual%20V2.pdf
#
# <C2><A9> Takeyuki UEDA 2015 -

import serial
import time
import subprocess
import slider_utils as slider
import getrpimodel

if getrpimodel.model() == "3 Model B":
  serial_dev = '/dev/ttyS0'
  stop_getty = 'sudo systemctl stop serial-getty@ttyS0.service'
  start_getty = 'sudo systemctl start serial-getty@ttyS0.service'
else:
  serial_dev = '/dev/ttyAMA0'
  stop_getty = 'sudo systemctl stop serial-getty@ttyAMA0.service'
  start_getty = 'sudo systemctl start serial-getty@ttyAMA0.service'


def calibrateZeroPoing():
  try:
    ser = serial.Serial(serial_dev,
                        baudrate=9600,
                        bytesize=serial.EIGHTBITS,
                        parity=serial.PARITY_NONE,
                        stopbits=serial.STOPBITS_ONE,
                        timeout=1.0)
    while 1:
      result=ser.write("\xff\x01\x87\x00\x00\x00\x00\x00\x78")
      break
  except IOError:
    slider.io_error_report()
  except:
    slider.unknown_error_report()

if __name__ == '__main__':
  calibrateZeroPoing()
  print "caribration zero point done."
```

実行します。

```
$ sudo python ./calibrate.py
caribration zero point done.
```

再度、mh_z19.py を実行し値を確認します。

### cron 実行と値の記録
cron で 10 分毎に実行し、ファイルに出力する例。
(もしくは、mh_z19.py でファイル出力を実装する。)

```
*/10 * * * * sudo python /PATH/TO/slider/mh_z19.py >> /tmp/co2.txt
```

## モノクロOLEDモジュールにCO2濃度を表示
"[Raspberry Pi 3 Model Bに Adafruit PiOLED を接続](http://qiita.com/revsystem/items/e6aa7a5c875f0c5a6fe9)" に、関連記事を書きました。


## 今後
- MH-Z19 に単一列端子ピン ヘッダーをつけて結線を見直す。
- [Chart.js](http://www.chartjs.org/)などでグラフ化する。
- 閾値を設けて、超えたら換気を促すTypetalk botをつくる。