屋内環境を手軽にモニタリングする～④MH-Z19BからCO2濃度をJavaで取得する(シリアル通信 / jSerialComm)～

## はじめに
CO2濃度を測定するセンサーとして、安価な[MH-Z19B](https://www.winsen-sensor.com/d/files/infrared-gas-sensor/mh-z19b-co2-ver1_0.pdf)を使用します。これはシリアル通信でデータを取得することができます。本記事では、Javaによるシリアル通信モジュールの[jSerialComm](https://github.com/Fazecast/jSerialComm)を使用して、MH-Z19BからCO2濃度を取得するために作成したJavaライブラリ[mh-z19b-driver](https://github.com/s5uishida/mh-z19b-driver)の概要を紹介します。といっても、Githubの内容そのままです。実装の詳細や使い方のサンプルは、[Githubのコード](https://github.com/s5uishida/mh-z19b-driver/blob/master/src/io/github/s5uishida/iot/device/mhz19b/driver/MHZ19BDriver.java)を参照して下さい。

## MH-Z19BとRaspberry Pi 3Bの接続
5V、GND、Tx、Rxを以下の通り接続します。**なお、相互にTx⇔Rxで接続して下さい。**

- `6. Pins` of [MH-Z19B](https://www.winsen-sensor.com/d/files/infrared-gas-sensor/mh-z19b-co2-ver1_0.pdf)
  - Vin
  - GND
  - Tx
  - Rx
- [GPIO of Raspberry Pi 3B](https://www.raspberrypi.org/documentation/usage/gpio/README.md)
  - Vin --> (2) or (4)
  - GND --> (6), (9), (14), (20), (25), (30), (34) or (39)
  - Tx --> (8) GPIO14
  - Rx --> (10) GPIO15
 
なお、Raspberry Pi 3BのGPIO端子の代わりに、USB接続のシリアル通信アダプタ([SH-U09C](https://www.amazon.co.jp/dp/B07BBPX8B8))をRaspberry Pi 3Bに挿して、これとMH-Z19Bを接続して使用することもできます。その場合、シリアル通信のポート名は、`/dev/ttyUSB0`になると思います。

## OSの設定
Bluetoothとシリアル通信(UART)を同時に使えるようにするために、Raspbian Buster Lite OSを以下のように設定します。

- /boot/cmdline.txt

```
console=serial0,115200 --> 削除します。
```

- /boot/config.txt  
以下の通りに追記します。

```
@@ -45,7 +45,7 @@
 # Uncomment some or all of these to enable the optional hardware interfaces
 #dtparam=i2c_arm=on
 #dtparam=i2s=on
-#dtparam=spi=on
+dtparam=spi=on
 
 # Uncomment this to enable the lirc-rpi module
 #dtoverlay=lirc-rpi
@@ -55,6 +55,10 @@
 # Enable audio (loads snd_bcm2835)
 dtparam=audio=on
 
+enable_uart=1
+dtoverlay=pi3-miniuart-bt
+core_freq=250
+
 [pi4]
 # Enable DRM VC4 V3D driver on top of the dispmanx display stack
 dtoverlay=vc4-fkms-v3d
```

## サンプルコード
mh-z19b-driverの使い方のサンプルは以下の通りです。**注意点として、初回読み出しのセンサーデータは、変な値が返りますが、二回目以降は適切な値が返ります。**

```Java
import io.github.s5uishida.iot.device.mhz19b.driver.MHZ19BDriver;

public class MyMHZ19B {
    private static final Logger LOG = LoggerFactory.getLogger(MyMHZ19B.class);
    
    public static void main(String[] args) throws IOException {
        MHZ19BDriver mhz19b = null;
        try {
            mhz19b = MHZ19BDriver.getInstance("/dev/ttyAMA0");
            mhz19b.open();
            mhz19b.setDetectionRange5000();
            
            while (true) {
                int value = mhz19b.getGasConcentration();
                LOG.info("co2:" + value);
                
                Thread.sleep(10000);
            }
        } catch (InterruptedException e) {
            LOG.warn("caught - {}", e.toString());
        } catch (IOException e) {
            LOG.warn("caught - {}", e.toString());
        } finally {
            if (mhz19b != null) {
                mhz19b.close();
            }
        }
    }
}
```

## 一連の記事
このシリーズは、以下の記事から構成されます。
1. [動機とコンセプト](https://qiita.com/items/9c31e6fd9b6eb0fa9c96)
2. [Bluetooth LEアドバタイズ信号をJavaでキャッチする(Bluetooth LE / bluez-dbus)](https://qiita.com/items/a4543c9e7fb13b4c7c6e)
　関連するGithubは[こちら](https://github.com/s5uishida/bluetooth-scanner)。
3. [TI SensorTag CC2650から温度/湿度/照度などをJavaで取得する(Bluetooth LE / bluez-dbus)](https://qiita.com/items/79a2de6a7026ef230e9b)
　関連するGithubは[こちら](https://github.com/s5uishida/cc2650-driver)。
4. **MH-Z19BからCO2濃度をJavaで取得する(シリアル通信 / jSerialComm)(今回)**
　関連するGithubは[こちら](https://github.com/s5uishida/mh-z19b-driver)。
5. [PPD42NSからPM2.5濃度をJavaで取得する(GPIO / Pi4J)](https://qiita.com/items/4ae7784aeaf50df1e3d3)
　関連するGithubは[こちら](https://github.com/s5uishida/ppd42ns-driver)。
6. [産業オートメーション機器の稼動情報をJavaで取得する(OPC-UA / Eclipse Milo)](https://qiita.com/items/60954d356a3ea1048c61)
　関連するGithubは[こちら](https://github.com/s5uishida/rainy-opcua)。
7. [簡易ツールにまとめる](https://qiita.com/s5uishida/items/c56f1444c6856656b128)
　関連するGithubは[こちら](https://github.com/s5uishida/rainy)。
8. [後記](https://qiita.com/s5uishida/items/d2a888eb2d68e72f32ae)

## 追記
[2019.11.16]
簡易ツールの最新情報は、[こちら](https://github.com/s5uishida/rainy)をご参照下さい。