M5StackとTVOC/eCO2 ガスセンサユニットで部屋の二酸化炭素濃度をはかり、高かったらBeep音をならして換気を促す



伊藤と申します。

会社員で、週４回ペースでリモートワークしております。
12月半ばになって急に寒くなり、窓を開けると寒いので、なかなか換気ができません。しかし二酸化炭素濃度が上がってくると眠くなるといいますし、空気が悪いと頭痛になったりしますので、CO2センサーで測ってアラートを上げる事にしました。




#1.機材

- [M5Stack](https://www.switch-science.com/catalog/3647/)
- [TVOC/eCO2センサー](https://www.switch-science.com/catalog/6619/)

 - TVOC = 総揮発性有機化合物。常温常圧で大気中に容易に揮発する有機化学物質の総称。シックハウス症候群の原因とも。
 - eCO2 = 二酸化炭素相当量。「eCO2はH2濃度に基づいて計算されるので、研究所で使用されるレベルのCO2センサと完全に置き換えることはできません。」との説明。

- [Arduino IDE](https://www.arduino.cc/en/software) 1.8.10 ※最新版の方がいいと思います。
- Mac Book Air 11' High Sierra
 
M1 Mac Book Proで試したのですが、USBSerialポートに M5Stackを検出できなかったので、古いMBAを引っ張り出して使いました。

 
#2.手順

## 初期設定

自分が当初お世話になった神記事
→@hmmrjn さんの[MacでM5stackをはじめる](https://qiita.com/hmmrjn/items/2b2da09eecffcbdbad85)

## TVOC/eCO2センサーの公式サンプルを試す


 - M5StackとTVOC/eCO2センサーをHY2.0ケーブルで繋ぐ

 - M5Stack付属の短いUSBケーブルでMacとM5Stackを繋ぐ

Arduino IDEで作業

 - File > examples > M5Stack > Unit > TVOC_SGP30を開く

 - tools を設定
   -  board: M5Stack-Core-ESP32
   -  Port: /dev/cu.***USBほにゃらら


何も編集せずに 心を静かに「Upload」を押すと、以下のようにTVOCとeCO2の値が表示されました。

![eCO2sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173392/77aa76cb-3459-be72-a315-af4de38c53c1.png)

やったー。まずはセンサーが動く事がわかって安心(^p^)


## 二酸化炭素濃度が閾値を超えたらBeep音を鳴らす


新しいスケッチを作ります。

- File > New 

さっきのサンプルにBeep音を鳴らす処理を付け加えてみます。
eCO2の値、つまり二酸化炭素濃度が1000ppmを超えたら、M5Stackの内蔵スピーカーを使って、コツン、コツン、というbeep音を鳴らすように、コードを書き加えました。



```
#include <M5Stack.h>
#include "Adafruit_SGP30.h"


//for beep
#define GPIO_PIN 25
uint32_t beep_last_time = 0;
uint8_t beep_volume = 50; //min 1, max 255
uint32_t beep_total_time = 0;
uint16_t eco2_threshhold = 1000;

Adafruit_SGP30 sgp;
int i = 15;
long last_millis = 0;
void header(const char *string, uint16_t color)
{
    M5.Lcd.fillScreen(color);
    M5.Lcd.setTextSize(1);
    M5.Lcd.setTextColor(TFT_WHITE, TFT_BLACK);
    M5.Lcd.fillRect(0, 0, 320, 30, TFT_BLACK);
    M5.Lcd.setTextDatum(TC_DATUM);
    M5.Lcd.drawString(string, 160, 3, 4); 
}

void setup() {
  M5.begin(true, false, true, true);
  header("SGP30 TEST",TFT_BLACK);
  Serial.begin(115200);
  Serial.println("SGP30 test");
  if (! sgp.begin()){
    Serial.println("Sensor not found :(");
    while (1);
  }

  beep_total_time = millis();
  
  M5.Lcd.drawString("TVOC:", 50, 40, 4);
  M5.Lcd.drawString("eCO2:", 50, 80, 4);
  Serial.print("Found SGP30 serial #");
  Serial.print(sgp.serialnumber[0], HEX);
  Serial.print(sgp.serialnumber[1], HEX);
  Serial.println(sgp.serialnumber[2], HEX);
  M5.Lcd.drawString("Initialization...", 140, 120, 4);
}

void loop() {
  while(i > 0) {    
    if(millis()- last_millis > 1000) {
      last_millis = millis();
      i--;
      M5.Lcd.fillRect(198, 120, 40, 20, TFT_BLACK);
      M5.Lcd.drawNumber(i, 20, 120, 4);
    }
  }
  M5.Lcd.fillRect(0, 120, 300, 30, TFT_BLACK);

  if (! sgp.IAQmeasure()) {
    Serial.println("Measurement failed");
    return;
  }
  M5.Lcd.fillRect(100, 40, 220, 90, TFT_BLACK);
  M5.Lcd.drawNumber(sgp.TVOC, 120, 40 , 4);
  M5.Lcd.drawString("ppb", 200, 40, 4);
  M5.Lcd.drawNumber(sgp.eCO2, 120, 80, 4);
  M5.Lcd.drawString("ppm", 200, 80, 4);
  Serial.print("TVOC "); Serial.print(sgp.TVOC); Serial.print(" ppb\t");
  Serial.print("eCO2 "); Serial.print(sgp.eCO2); Serial.println(" ppm");

 if (sgp.eCO2 > eco2_threshhold){
  M5.Lcd.drawString("over1000", 200, 100, 4);
  Serial.print("over500");   
  dacWrite(GPIO_PIN, 0);
  delay(1); //約500Hz
  dacWrite(GPIO_PIN, beep_volume); 
  delay(1); //約500Hz
 } 

  delay(1000);
}

```
※ M5Stackの内蔵スピーカーでBeepを鳴らすやり方は、
mgo_tecさんの「M5Stack の内蔵スピーカーから Beep 音（電子音）を出す実験」を参考にさせていただきました！
https://www.mgo-tec.com/blog-entry-beep-sound-speaker-m5stack.html



Verifyをクリックし、保存場所を聞かれたら適当に保存します。

また、先ほどのサンプルに入っていた、Adafruitの2つのファイル(以下のスクショの2個目と3個目のタブ)をコピーしてきます。

![Adafruit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173392/28708023-3ade-bfb1-a73b-f24703232b69.png)

Arduinoのインストールディレクトリが「/Users/ユーザー名/Documents/Arduino/」の場合、コピー元とコピー先は以下となります。


- FROM : /Users/ユーザー名/Documents/Arduino/libraries/M5Stack/examples/Unit/TVOC_SGP30/
- TO : /Users/ユーザー名/Documents/Arduino/sketch_スケッチ名/

![Adafruit3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173392/6a7fc55a-48a3-eb3f-171c-a579941f356b.png)

 - スケッチをUpload後、TVOC/eCO2センサーユニットに向かって息をふきかけて二酸化炭素濃度を上げると、1000ppmを超えているい間は、1秒毎に、タン、タン、という控えめなBeep音が鳴ります。息は拡散して薄まるので、数秒後にはBeepはとまります。

https://www.youtube.com/watch?v=JmfcTXhLIT0
<a href="https://www.youtube.com/watch?v=JmfcTXhLIT0
"><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173392/37ff7c51-17a8-2e6a-f16f-93810dac6450.png"></a>

## 補足

### 二酸化炭素濃度の閾値について

1000ppmで良いのか？ですが、東京都地球温暖化防止活動推進センター（愛称：クール・ネット東京）という組織が書いてる説明によると、[「外気はおおよそ400ppm、室内はおおよそ1,000ppmがCO2濃度の目安」](https://www.tokyo-co2down.jp/2016/06/24/30472/index.html#:~:text=%E5%8A%B4%E5%83%8D%E5%AE%89%E5%85%A8%E8%A1%9B%E7%94%9F%E6%B3%95%E3%81%AE,%E3%81%A8%E6%9B%B8%E3%81%8B%E3%82%8C%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%80%82)だそうですので、参考にさせていただきました。




## 課題 

部屋を締め切って1時間くらいたったらBeepが鳴ったのですが、その後さらに1時間たったら、eCO2は"400ppm"で止まってしまいました。
息をふきかけるとちゃんと1000ppm以上に上がってBeepが鳴るものの、その後またすぐ"400ppm"に戻ってしまいます。
精度は特に良くはないとの事なのですが、検出が止まるというのはちょっと意味が違うような。。
TVOC(総揮発性有機化合物)のほうは値が動いているので、eCO2の方だけの問題のようです。
　
*(→12/26 追記)*
[「2020年忘年会！アドベントカレンダー振り返りラジオ - IoTLT オンライン vol5」](https://iotlt.connpass.com/event/199665/)にて、偉い方からアドバイスをいただきました！

- __表示される最低値が400ppmであり、実際はそれ以下の値でも400ppmが表示される仕様。__
- __正常に動かすにはベースラインをとってキャリブレーションすることが必要__
(サンプルコードがAdafruitのSGP30のサイトで公開されてるらしい）
→おそらくここのp.12　https://cdn-learn.adafruit.com/downloads/pdf/adafruit-sgp30-gas-tvoc-eco2-mox-sensor.pdf 後でやってみます(^p^)

# 3. まとめ



## 野望リスト

- どこかにアップしてグラフ化するといいやも
- 家では限界があるため、会社のオフィスに勝手に設置して測ってみようかな
- Raspberry Pi用にMH-Z14Aも買ってみたので、M5Stack + TVOC/eCO2センサーと比較してみたい
- 当初Apple SiliconのMac Book Proを使って作業を始めたのだが、USBSerial port接続でM5Stackを認識せず。いずれ情報を仕入れて再チャレンジするぞい


## 感想
室内に人が多く換気が悪く澱んでいる状態だと、二酸化炭素濃度が高くなるなら、コロナ対策にも役立つやも。



以上でぃす! (^p^)