3.3Vで稼働するCO2センサー "S-300L-3V" を Wio LTE で動かして SORACOM Harvest Data に蓄積する

サンタさん来訪に備え、室内のCO2濃度を快適にしておきたいと思っている [松下(ニックネーム: Max)](https://twitter.com/ma2shita) です。

[多すぎる二酸化炭素は脳の敵](https://studyhacker.net/columns/kanki-performance-up) と言われており、オフィスのIoTネタでもよく話題になるCO2の計測。センサーは探すとあるのですが、いかんせん5V駆動のものばかりで、 Wio LTE のような 3.3V マイコンで動かすには...

* 3.3V -> 5V DCDC 昇圧回路を挟む
* 3.3V で駆動するセンサーを探す

という選択肢となります。ちなみに、動作電圧3.3Vか5Vというのはプロトコルのようなものです。3.3V/5Vの両方に対応しているセンサーもありますし、電圧を「変換」することで動きます。

作るのは好きですが、目的を見失うので3.3Vで動くCO2センサーを探してみると...あるものですね！

[S-300L-3V CO₂センサモジュール](https://www.switch-science.com/catalog/3685/)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22754/2b527250-ce9a-aaca-304c-c67a60bdab48.png)

1万円となかなかいいお値段ですが、昇圧回路を作って5Vのものを動かすくらいなら、既製品を使えばお金はかかるかもしれませんが、時間※が節約できるので、今回はこれを使ってみようと思います。

※時間 = 昇圧回路を作るだけじゃなくて、その回路が正常に動いているかチェックしたり、、、面倒なのはお金で解決したい派です。

## S-300L にピンヘッダをはんだ付け

本当は Grove コネクタがついてくれていれば最強だったのですが、残念。
仕方ないのでピンヘッダをハンダで取り付けます。まあ、このくらいは作業するか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22754/f87f177d-e3fc-17e5-4128-de4524e1733c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22754/c52e6044-78f6-0ba7-df67-7ed9ffa6820a.png)

下手なのはわかってます。突っ込まないで。

## ブレッドボードで検証

S-300Lのピンヘッダは直接ブレッドボードに挿せます(2.54mmピッチ)。これは便利。
あとは [Groveのジャンパーピン変換ケーブル](https://www.sengoku.co.jp/mod/sgk_cart/detail.php?code=EEHD-4K34#)を使って Wio LTE の UART と接続します。
ケーブルと S-300L の接続は以下の通り。

| Grove | S-300L |
|-------|--------|
|  黒   |  GND   |
|  赤   |  VCC   |
|  白   |  Rx    |
|  黄   |  Tx    |

こんな感じになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22754/c5692f88-b118-7806-f18e-7b1a2ab0426f.png)

### コード

この時点ではまだセンサーとマイコン(Wio LTE)間の接続を確認してみます。
S-300L から UART で[出力されるデータフォーマットは公開されています](http://doc.switch-science.com/datasheets/ELT/User+Guide+for+U-ART+command+for+Low-Power+ver160719+cdg.pdf)ので、それを見ながら以下のようにします。

* S-300L <=> Wio LTE のスピードは 38400 bps
* 3秒毎に計測されるので UART バッファ内を待つ
* 区切り文字に LF (0x0A = \n)

```c++:measurement_co2.ino
#include <WioLTEforArduino.h>
WioLTE Wio;

uint16_t CO2ppm() {
  while (!SerialUART.available()); /* wait max 3 seconds by spec (TODO: Timeout) */
  String buf = SerialUART.readStringUntil('\n'); /* separete char by spec */
  int pos = buf.lastIndexOf(" ppm"); /* Avoiding garbage in buffer */
  String v = buf.substring(pos - 6, pos);
  return v.toInt();
}

void setup() {
  delay(200);
  Wio.Init();
  SerialUSB.begin(115200);
  Wio.PowerSupplyGrove(true);
  delay(500);
  SerialUART.begin(38400);
  SerialUSB.println("Ready");
}

void loop() {
  uint16_t ppm = CO2ppm();
  SerialUSB.println(ppm);
  delay(5000);
}
```

ppm が表示され始めたら成功です。
誰もいない部屋なら800 ~ 1000 くらいの間だと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22754/7f84cf92-ddcf-d600-4973-4c10435e09d3.png)

※思いっきりテキストで `   960 ppm` とかコンソールに出力されてくるのは(´Д｀)ってな感じ。

## SORACOM Harvest Data へ

Wio LTE は LTE Cat.1 モジュールと SIM 、そしてアンテナがあるので Wi-Fi 等が無くても単体でクラウドへデータを送ることができます。
今回は SORACOM の IoT データ収集・蓄積サービス「[SORACOM Harvest Data](https://soracom.jp/services/harvest/)」で以下のように計測したデータを蓄積します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22754/6abeab82-6616-cf37-3f24-8a75a7961d6c.png)

### コード

前回のコードに以下の内容をつけ足しました。

* `setup()`
    * セルラーモデム ON
    * セルラーネットワーク(SORACOM) への接続
* `loop()`
    * SORACOM Harvest Data への送信

```c++:measurement_co2_with_soracom_harvest_data.ino
#include <WioLTEforArduino.h>
WioLTE Wio;

uint16_t CO2ppm() {
  while (!SerialUART.available()); /* wait max 3 seconds by spec (TODO: Timeout) */
  String buf = SerialUART.readStringUntil('\n'); /* separete char by spec */
  int pos = buf.lastIndexOf(" ppm"); /* Avoiding garbage in buffer */
  String v = buf.substring(pos - 6, pos);
  return v.toInt();
}

void setup() {
  delay(200);
  Wio.Init();
  SerialUSB.begin(115200);
  Wio.PowerSupplyGrove(true);
  delay(500);
  SerialUART.begin(38400);
  Wio.PowerSupplyLTE(true);
  delay(500);
  if (!Wio.TurnOnOrReset()) {
    SerialUSB.println("failed TurnOnOrReset()");
    return;
  }
  if (!Wio.Activate("soracom.io", "sora", "sora")) {
    SerialUSB.println("failed Activate()");
    return;
  }
  SerialUSB.println("Ready");
}

void loop() {
  uint16_t ppm = CO2ppm();
  SerialUSB.println(ppm);
  char payload[1024];
  sprintf(payload, "{\"co2_ppm\":%lu}", ppm);
  int status_code;
  if (!Wio.HttpPost("http://uni.soracom.io", payload, &status_code)) {
    SerialUSB.println("failed HttpPost()");
    goto err;
  }
  SerialUSB.print("Status code:");
  SerialUSB.println(status_code);
err:
  SerialUSB.println("Waiting for next loop");
  delay(5000);
}
```

前回とのdiffはこんな感じで21行加えています。

```diff

@@ -16,11 +16,33 @@
   Wio.PowerSupplyGrove(true);
   delay(500);
   SerialUART.begin(38400);
+  Wio.PowerSupplyLTE(true);
+  delay(500);
+  if (!Wio.TurnOnOrReset()) {
+    SerialUSB.println("failed TurnOnOrReset()");
+    return;
+  }
+  if (!Wio.Activate("soracom.io", "sora", "sora")) {
+    SerialUSB.println("failed Activate()");
+    return;
+  }
   SerialUSB.println("Ready");
 }

 void loop() {
   uint16_t ppm = CO2ppm();
   SerialUSB.println(ppm);
+  char payload[1024];
+  sprintf(payload, "{\"co2_ppm\":%lu}", ppm);
+  int status_code;
+  if (!Wio.HttpPost("http://uni.soracom.io", payload, &status_code)) {
+    SerialUSB.println("failed HttpPost()");
+    goto err;
+  }
+  SerialUSB.print("Status code:");
+  SerialUSB.println(status_code);
+err:
+  SerialUSB.println("Waiting for next loop");
   delay(5000);
 }
```

### SORACOM 側の設定

SORACOM Harvest Data を有効にするには [SORACOM Harvest Data でデバイスのデータをクラウドで収集・取得・可視化する](https://dev.soracom.io/jp/start/harvest/#post) を参考に進めてください。スクリーンショット付きです。

## 今回使った機材の費用

ざくっと計算すると、このくらいでした。

* 初期: 約 21,700円
* ランニング: 16円/日/SIM

※金額は税抜きです。

### 初期

| 役割 | 機材 | 金額 |
|-----|-----|-----:|
| マイコン＆モデムボード| [Wio LTE JP Version](https://soracom.jp/products/module/wio_lte/) | 9800円 |
| CO2 センサー | [S-300L-3V](https://www.switch-science.com/catalog/3685/) | 9930円 |
| ブレッドボード | どこのやつだったかな？ | 300~500円くらい |
| ケーブル | [Grove ジャンパーピン変換ケーブル (5本入り)](https://www.sengoku.co.jp/mod/sgk_cart/detail.php?code=EEHD-4K34#) | 500円くらい |
| SIM | [SORACOM 特定地域向け IoT SIM (plan-D)](https://soracom.jp/products/sim/plan-d/) | 895円 |

### ランニング (1日分)

| 役割 | 機材 | 金額 |
|-----|-----|-----:|
| データ通信 / 基本料 | [SORACOM 特定地域向け IoT SIM (plan-D)](https://soracom.jp/products/sim/plan-d/) | 10円/日/SIM |
| データ通信 / 通信料※ | [SORACOM 特定地域向け IoT SIM (plan-D)](https://soracom.jp/products/sim/plan-d/) | 1円/日/SIM |
| データ収集・蓄積 | [SORACOM Harvest Data](https://soracom.jp/services/harvest/) | 5円/日/SIM |

※ 1回500B、10分に1回で約720KBの通信を想定

## まとめ

できる限り既製品を使う事で、思い立ってから1日で完成できたのは大きかった。
（揃うまでに3日くらいかかったけど）

動くことは確認できたので、あとはケースや電源を考えることにします。
とはいえ、ここも作るのが面倒なので [既製品のケースやネジ](https://qiita.com/ma2shita/items/3846b9ec9c27babaab86#%E3%83%8F%E3%83%BC%E3%83%89%E3%82%A6%E3%82%A7%E3%82%A2%E7%B7%A8) で何とかしようと思います。

**Grove 5V 出力昇圧 DCDC コンバーターがあると嬉しいのだけど！**

EoT