Raspberry PiでCO2センサーモジュール(MH-Z14A)を使って室内のCO2濃度測定

# きっかけ
・大学の研究室にて部屋の人口密度が高く、室内環境(CO2濃度等)が気になっていた　
　後輩「CO2の濃度が測れる何かがあるといいっすね！」
・ラズパイのGPIOを使って何かを作ったことが今まであまり無かった
　僕「勉強になるからやってみるか」

# 使ったもの

・Raspberry Pi 3 model B+
・CO2センサーモジュール(MH-Z14A)
・ジャンパワイヤ(オス-メス)　
・ピンソケット(メス、2.54 mm)


CO2センサー(MH-Z14A)はこんな感じのやつ。通電させると中央の白い四角の四隅が赤く点滅する。
おそらくこの部分からCO2を取り込んでCO2濃度を測定していると思われる。
測定原理はNDIR方式というものらしい(CO2の赤外吸収を利用して測定？)

<img width="600" alt="IMG_3082.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513034/de67ae8c-ad6e-8c53-4531-4f22c67ce44e.jpeg">

マニュアルによると5000 ppmまで測れるらしい

マニュアルのリンク↓
https://www.openhacks.com/uploadsproductos/mh-z14_co2.pdf



# 手順

## Raspbianをインストール

これはまあ適当に

## CO2センサーとラズパイを接続
### CO2センサー側

MHZ-14AはCO2の値をUART、PWM、アナログ電圧等色々な方法で取得できるらしい
→今回はUART方式で

UARTでは16-19ピンを使うようなのでで4本分のジャンパワイヤ＆ピンソケットがあれば良いね

マニュアルから抜粋↓

<img width="600" alt="MHZ-14A.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513034/7cbc04c1-b73f-9f63-ab65-a2e914f8fff6.png">


実際に接続するとこんな感じ

| ピン | 割当て |ジャンパワイヤの色|
|:-:|:-:|:-:|
|  17 |  Vin(5 V) |赤|
|  16 |  GND |黒|
|  18 |  UART(RXD) |青|
|  19 |  UART(TXD) |黄|


<img width="400" alt="IMG_3085.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513034/468bb426-29db-5c28-266b-cc01415cef2f.jpeg">


### ラズパイ側

ラズパイ側はこんな感じで接続する

<img width="400" alt="MHz-14a.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513034/d88df523-72d6-aa11-0e24-40ba29f65c34.jpeg">


## ラズパイ側の設定

###UARTの有効化


まず、ラズパイ(Bluetooth搭載モデル)でのUARTでは以下の特徴があるようである
・ラズパイの場合、UARTのポートが二種類あり、初期設定ではメインのものはBluetoothに、サブの物はシリアル通信(GPIO)に割り当てられているらしい
・また、サブの方は送受信のデータ長に制限がある、クロックがラズパイCPUに依存しているためボーレートもそれに合わせて変化してしまう

そこでメインのポートをシリアル通信側に割り当てる設定を行う
<br/>
lsで/dev/serial*を参照すると以下の通りになっている

```
root@raspberrypi:/home/pi# ls -l /dev/serial*
lrwxrwxrwx 1 root root 7 10月  4 18:28 /dev/serial0 -> ttyS0
lrwxrwxrwx 1 root root 5 10月  4 18:28 /dev/serial1 -> ttyAMA0
```

<br/>
メインのポート(serial0)はコンソール(ttyS0)に割り当てられているのでシリアル通信(ttyAMA0)に割り当てられるように設定する


```
root@raspberrypi:/home/pi# vi /boot/cmdline.txt
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を削除する

<br/>
次にBluetoothの無効化を行う

```
root@raspberrypi:/home/pi# vi /boot/config.txt
     ・
　　　・
　　　・
dtoverlay=pi3-disable-bt　←追記する

```
<br/>
Bluetoothの設定を初期化するサービスを無効化する

```
root@raspberrypi:/home/pi# systemctl disable hciuart
Removed /etc/systemd/system/multi-user.target.wants/hciuart.service.
```

<br/>
ここで再起動

```
root@raspberrypi:/home/pi# reboot
```
<br/>

この時点で/dev/serial*を参照するとserial0とserial1の割り当てが逆になっている

```
root@raspberrypi:/home/pi# ls -l /dev/serial*
lrwxrwxrwx 1 root root 7 10月  4 18:28 /dev/serial0 -> ttyAMA0
lrwxrwxrwx 1 root root 5 10月  4 18:28 /dev/serial1 -> ttyS0
```


<br/>


##Pythonによるセンサーの制御

PythonでUART制御が行えるようにライブラリをインストールする

```
root@raspberrypi:/home/pi# apt　install python-serial
```
<br/>

実際にセンサーに値を取得させるコマンドを送り、値を取得するプログラムを作成する

```co2.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import serial
import time
import datetime
   
s = None
def setup():
	global s
	s = serial.Serial('/dev/ttyAMA0',baudrate=9600,bytesize=serial.EIGHTBITS,       parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,timeout=1.0)
    print ("start setup")
	time.sleep(60)
    print ("end setup")
	

def readdata():
	now = datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S")
    print ("send")
	b = bytearray([0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79])
	s.write(b)
	time.sleep(5)
	result = s.read(9)
	checksum = (0xFF - ((ord(result[1])+ord(result[2])+ord(result[3])+ord(result[4])+ord(result[5])+ord(result[6])+ord(result[7]))% 256))+ 0x01
	checksumok = 'FAIL'
	if checksum == ord(result[8]):
		checksumok = 'PASS'
	data = now + "," + str((ord(result[2])*256)+ord(result[3]))+ "," + checksumok+"\n"
	filename = datetime.datetime.now().strftime("%Y%m") + 'CO2data.txt'
	file_data = open(filename , "a" )
	file_data.write(data)
	print (data)
	file_data.close()
   
if __name__ == '__main__':
	setup()
	while True:
		readdata()
        print ("read")
```

<br/>
実際にプログラムを実行すると以下の通りになる

```
root@raspberrypi:/home/pi/mh-z14a# python co2.py 
start setup
end setup
send
2019/10/13 00:44:27,620,PASS
```
CO2濃度が620 ppmとして取得された

追記:
こちらに取得したCO2濃度によって光らせるLEDの色を変えてみた記事を書きました
[CO2濃度センサーで取得した値に応じて光らせるLEDの色を変える](https://qiita.com/_shin_/items/f4037a58f63c65bb3048)


#参考にしたサイト
・UART有効化
https://www.ingenious.jp/raspberry-pi/2019/03/gpio-uart/
<br/>
・センサー・ラズパイ間の接続、プログラム
https://www.ishikawa-lab.com/RasPi_CO2_MHZ19.html
https://qiita.com/watiko/items/5cfa2aedd5a67619add0

有用な情報ありがとうございました