ESP32(M5Stack)で作る、安価なCO2モニタ【秋月でCO2センサ取扱開始 記念】

# この記事について
CO<sub>2</sub>センサである MH-Z19 と M5Stack を使用して、安価にCO<sub>2</sub>を可視化してみよう、という、シンプルな試みです。

# CO<sub>2</sub>センサ MH-Z19 について
MH-Z19 という二酸化炭素センサがあります。このような2x3cmくらいの金色の箱の形をしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169018/d4461c0f-7c4c-1dd3-71fa-a9805db37dbb.png)

このセンサですが、海外では2016年くらいから流通していたのですが、日本では Aliexpress/eBayで中国から個人輸入するかamazonで中華業者から少し割高な値段で買うか、という2択の状態が長らく続いており、微妙に入手がめんどくさい状況でした。
ところが、先日よりのMH-Z19C（おそらく従来品のマイナーチェンジ版）が[秋月電子で取り扱いが始まり](https://akizukidenshi.com/catalog/g/gM-16142/)、日本でも簡単に入手できるようになりました。

## MH-Z19 ESP32用ライブラリについて
2016-7年当時、私はAliexpressでMH-Z19を輸入したのですが、当時はめぼしいライブラリが無かったので、データシートとにらめっこしながら自前で以下のライブラリを書いて公開しておりました。
https://github.com/nara256/mhz19_uart

今回、秋月で取り扱いが始まったということで、改めてライブラリの確認などをしていたのですが、まーソースコードが汚いしw、マイナーチェンジ版のMH-Z19Cだと動かない部分もあったりで、今回実装内容を少し内容を見直しました。

# M5Stack と MH-Z19 で CO<sub>2</sub> 値を取得する
ということで、やっと本題です
## 使用する機器
- M5Stack (ESP32であれば何でも良いのですが、今回はM5Stackを使ってみます)
- MH-Z19C (秋月電子で購入したもの)

## 配線
### M5Stack と MH-Z19C を接続する
以下の通りワイヤーで接続します。

- M5Stackの "G" → MH-Z19C の "GND"
- M5Stackの "5V" → MH-Z19C の "Vin"
- M5Stackの "R2" → MH-Z19C の "Tx"
- M5Stackの "T2" → MH-Z19C の "Rx"
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169018/48697682-387c-4f68-1210-384d4f9a31f0.png)

## 実装
### ライブラリのインポート
1. 次のページより、黄緑の"Code"のボタンを押し、続いて "Download ZIP" を選択し、ファイルをダウンロードします。  
 https://github.com/nara256/mhz19_uart
2. Arduino IDE を起動し、メニューの スケッチ → ライブラリをインクルード → .ZIP形式のライブラリをインストール を選択し、ダウンロードしたzipファイルを選択します。

これでライブラリのインポートが完了です。

### とりあえず動かす

- M5Stack を PC に接続します。
- Arduino IDE のファイル→スケッチ例 から、 `MHZ19_uart` → `MHZ19_getco2` を選択すると、サンプルのソースコードが表示されます。

```cpp:MHZ19_getco2.ino
/*----------------------------------------------------------
    MH-Z19 CO2 sensor  SAMPLE
  ----------------------------------------------------------*/

#include <MHZ19_uart.h>

const int rx_pin = 16; //Serial rx pin no
const int tx_pin = 17; //Serial tx pin no

MHZ19_uart mhz19;

/*----------------------------------------------------------
    MH-Z19 CO2 sensor  setup
  ----------------------------------------------------------*/
void setup()
{
  Serial.begin(9600);
  mhz19.begin(rx_pin, tx_pin);
  mhz19.setAutoCalibration(false);

  Serial.println("MH-Z19 is warming up now.");
  delay(10 * 1000); //
}

/*----------------------------------------------------------
    MH-Z19 CO2 sensor  loop
  ----------------------------------------------------------*/
void loop()
{
  int co2ppm = mhz19.getCO2PPM();
  int temp = mhz19.getTemperature();

  Serial.print("co2: ");
  Serial.println(co2ppm);
  Serial.print("temp: ");
  Serial.println(temp);

  delay(5000);
}
```
</details>

- ビルドして M5Stack に書き込みます。
- シリアルモニタを開くと、二酸化炭素濃度（とおまけの温度）が表示されます。  

```
co2: 1234
temp: 17
```

簡単に動かせました。

### M5Stackのディスプレイに表示する
シリアルモニタに表示させるだけだとアレなので、今回はM5StackのLCDに表示してみます。

サンプルのソースコードに以下を追加します。

- M5Stackのライブラリをインクルードする

```cpp:MHZ19_getco2.ino
#include <M5Stack.h>
```

- `setup()`関数内で、LCDを初期化する

```cpp:MHZ19_getco2.ino
void setup() {
  : 
  前略
  :
  M5.begin();
  M5.Lcd.setBrightness(200);
  M5.Lcd.fillScreen(BLACK);

  M5.Lcd.setCursor(0, 0);
  M5.Lcd.setTextColor(WHITE, BLACK);
  M5.Lcd.setTextSize(5);
  M5.Lcd.print("CO2");
```

- `loop()`関数内で、二酸化炭素濃度をLCDに表示する

```cpp:MHZ19_getco2.ino
void loop() {
  : 
  前略
  :
  M5.Lcd.setCursor(48, 48);
  M5.Lcd.setTextColor(co2ppm<1000 ? WHITE : (co2ppm>=2000 ? RED : YELLOW), BLACK);
  M5.Lcd.print(String(co2ppm) + "ppm");
  : 
  後略
  :
}
```

これで、LCDに表示されるようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169018/c717cce1-566f-3468-2573-8e9a8ebd8fd6.png)

なお、一般的に二酸化炭素濃度が 1,000ppm 以下が無難、1,000ppm 以上だと集中力が薄れる、2,000ppm 以上だと頭痛がしてくる、らしいので、それに合わせて文字色を変えてみました。

### 更に便利に可視化させるために
今回は省略しますが、取得したデータを [IIJ Machinist](https://machinist.iij.jp/) などに送信するとより便利に可視化できるようになるかと思います。
Machinistへのデータ送信については以下の記事をご参照ください。
[Spresense+LTE拡張ボード で IIJ Machinist を使用する](https://qiita.com/nara256/items/ae906b5ae3d3ea0aa5fe)
[ESP-WROOM-02/32 で IIJ Machinist を使用する](https://qiita.com/nara256/items/3b9c40f59ab742222d62)


## その他 MH-Z19 の機能
MH-Z19 は、大気（要は屋外）で「ゼロキャリブレーション」をしたり、屋内(1,000-2,000ppmくらいの場所)で「スパンキャリブレーション」などをすると、数値の精度が高められる機能があります。
詳細は [README](https://github.com/nara256/mhz19_uart/blob/master/README_jp.md) を確認しつつ、スケッチ例の `MHZ19_zerocarib` や `MHZ19_spancarib` のソースを確認してみてください。

# まとめ
昨今のコロナ禍で、店舗内などの二酸化炭素濃度の計測が重要視されているようです。そんな中で、安価すぎる二酸化炭素計測器を買うとデタラメな数字しか出てこないような例もあるようです。少しお高めのまともな計測器を買う方法が確実ではありますが、今回のような組み合わせでも比較的信頼度が高い計測ができるのではないかと思います。