hogehoge, world.

米国カリフォルニアのソフトウェアエンジニアがIT・自転車・音楽・天体写真・語学などについて書く予定。

SGP30/SCD30によるCO2濃度測定

閉じた空間のCO2濃度というのは結構簡単に上がるものらしい。現在在宅勤務100%となり、狭い部屋で仕事や電話会議をすることも増え、知らない間にCO2濃度が上がり頭の働きが悪くなるなんてこともあるかもしれない。となれば当然測ってみたくなる。

CO2濃度が測れる廉価なセンサーとしてはSGP30がある。電圧レギュレーター内蔵のAdafruitのモジュールが$20で入手でき、手軽に試すことができる。

しかし、SGP30で測れるのは実際のCO2濃度ではなく近似値であり、実のところまったく満足いくものではなかったので、結局ちゃんとCO2濃度を測る光学式のセンサーも使ってみることにした。この手のセンサーは基本的に業務指向で高価なものが多いのだが、その中でもSCD30は比較的廉価で、例えばMouserで$50程度で入手できる。

今回はこれら両センサーの使い方と測定結果をシェアしてみようと思う。使い方に興味がない人、早く測定結果を見たい人は下の目次から最後のセクションまで飛ばしてもらって構わない。f:id:tomoto335:20200713160118j:plain

目次

CO2濃度に関する基礎知識

空気中のCO2の濃度はppm (百万分率, 1ppm = 0.0001%)で表されることが多く、外気のCO2濃度がおよそ400ppmらしい。1000ppmになると明らかに空気が悪いと感じ、それを越えると眠くなったりするそうだ。厚生労働省の建築物環境衛生管理基準には「換気設備のある建物ではCO2濃度は1000ppm以下に抑えよ」と書かれている。 

SGP30の特徴と使い方

基本情報

上のドキュメントを見るとわかるように、正式にはCO2センサーではなくVOC(Volatile Organic Compounds, 揮発性有機化合物)センサー、つまり臭いなども含めた空気の悪さを測るものである。CO2濃度の近似値であるeCO2(Equivalent co2)値と、TVOC(Total Volatile Organic Compound)値を得ることができる。

eCO2というのは、H2の濃度から見積もったCO2濃度らしい。なぜH2からCO2の濃度が見積もれるかはよくわからないが、人体から出るCO2の見積もりにはよい近似になると何かに書いてあった。値はppmで、400から取れる。

TVOCは空気中のエタノールの濃度をもとに算出されるそうだ。こちらはppb (ppmより0三つ分だけ小さい単位)で取れる。

接続方法

いつもの通り、ArduinoボードやParticleボードにI2Cで接続し、Adafruitのライブラリを使って呼び出す。不慣れな人もAdafruitのチュートリアルを追えば配線して動かすまで簡単にいけるだろう。チップ自体は1.8V駆動だが、上のAdafruitのモジュールは3.3Vや5Vのボードに直接接続できるので使い易い。

湿度補正

H2濃度計測は湿度による影響を受けるので、別途計測した湿度を与えて補正できるようになっている。私はそのためBME280を隣に載せることにした。

使うのは相対湿度(%)ではなく絶対湿度(g/m3)である。相対湿度から絶対湿度の近似計算方法はデータシートやライブラリのサンプルコードに載っている。

自動ベースライニング

センサーは継続的な補正が必要で、そのために「自動ベースライニング」という機能を備えている。コンセプトの説明はこれ The Senseair ABC-algorithm | Senseair が解りやすい。センサー稼働中に値が一番低かった場所を発見し、それをベースラインとして更新していくというもの。そのためセンサーは継続的に稼働させ、一日一回10分程度きれいな空気に当てる必要があるらしい。 

Adafruitのドキュメントにベースラインの扱い方について説明されているが少々わかりにくい。つまりはこういうことだ:

  • SGP30は不揮発性メモリを積んでいないので、一旦電源を切るとせっかく調整したベースラインを忘れてしまう。そこでアプリケーションは定期的に(一時間に一回ほど)ベースライン値をセンサーから読み取ってどこか失われない場所に書き込んでおき、次に電源を投入してアプリケーションを起動するときにはそれをセンサーに書き戻すこと。
  • 初回はベースラインが不明なので、黙って12時間稼働させて、ベースライン値を保存するのはその後にすること。
  • 7日前より古いベースライン値は使わない(再び12時間稼働させてベースラインを再計算させる)こと。

私はベースライン値をSPIFFSに保存し、あと推移を見るためにネットワークサーバにも送ることにした。 

ベースライン値は通常は0x8000~9000台のはずである。私はこれが急に0xFF00越えまでジャンプアップし、計測値もおかしくなる現象に出会ったが、原因は単にブレッドボードの組み方が悪くて電源電圧が不安定になっていただけだった。

SCD30の特徴と使い方

基本情報

こちらはNDIR方式と呼ばれ、赤外線の吸収率でCO2濃度を測るセンサー。MOX式のSGP30より正確なはず。値は同じくppmで取れる。

接続方法

これもI2CでArduino等に接続可能。ライブラリはSparkFunから出ているものが使える。

電源は3.3-5.5Vだが、3.3Vだとギリギリっぽかったので私はUSBのVBUSから取った5Vを使っている。SCD30は電源電圧に関わらずI2C信号の電圧は3Vなので、電源電圧を引き上げても3.3Vのボードと直接接続できるので都合がよい。逆に5Vのボードとの接続時には注意が必要である。

電源を入れていると約2秒に1回自動的に計測が行われる。計測時には橙色のLEDが点灯する(ちなみにこのLEDが付いているのは何故か基盤の裏側である)。計測頻度を下げて消費電力を下げられるが、代わりに変化に対するレスポンスが遅れるらしいので、私はデフォルトの最高頻度(2秒)のままで使っている。2秒ごとにLEDがみょ~んみょ~んと光るのはとにかくかっこいい。

youtu.be

高度補正と気圧補正

NDIR方式の計測は高度と気圧の影響を受けるらしく、別途計測した高度と気圧を与えて補正することができる。私は測定場所のおよその高度を決め打ちで設定し、SGP30のときと同じくBME280を付けて気圧を測定&設定することにした。

設定値は不揮発性メモリに保存されるので、電源を切っても保持される。

おまけの温時計・湿度計機能

CO2計測補正用と思われる温度計と湿度計の値を取ることができる。温度には自己発熱が含まれ(BME280と同じ)、正しい環境温度からのオフセットがわかっていれば、それを設定し温度・湿度の値を補正することができる。

精度はスペック的にも実測した感覚からもBME280と同等のようだ。私は気圧測定用にBME280を既に付けているので残念ながら使う理由がない。

自動ベースライニング

SCD30にもSGP30と同原理の自動ベースライニング機能がある。ベースラインはセンサー自身の不揮発性メモリに保存されるので、SGP30のようにアプリケーションで保存処理を書かなくてもよく、結局ほぼ意識しなくてよいので楽である。

ドキュメントによれば、初回のベースライン決定には7日間かかるので、その間電源を入れっぱなしにし、一日一時間ほど新鮮な空気に当てる必要があるとのこと。

(後日談: 2台買ったSCD30のうち1台の出力値がやけに低くなってしまった。現象的にはベースラインが変な値に固定されてしまったような感じである。思い付く手段をいくら試しても解消せず、結局過去データともう1台のSCD30からオフセットを適当に見積もってプログラムの側で補正することにした。)

電力消費と電源の取り方

光学式の電力消費ってどのくらいだろうか、電源は耐えられるだろうか、と測ってみたところ、ほぼドキュメント通りだった。

計測にときどき間が空いているが、気圧補正や温度補正の設定操作のタイミングでこうなることがあるようだ。最初計測ごと(数秒ごと)に補正データを更新していたらLEDの点滅周期がかなりばらばらになったので、やりすぎない方がよさそうである。

消費電流の実測値:

f:id:tomoto335:20200713180858p:plain

ドキュメントに書かれた消費電流:

f:id:tomoto335:20200704075016p:plain

私は電源を最初ESP32ボードの3.3Vレギュレーターから取っていた(レギュレーターの仕様上電流には余裕がある)のだが、ときどき計測がぱったりと止まってしまうことがあり、電源電圧を測ってみると電流ピーク時に仕様の下限である3.3Vを下回っていた。そこでUSBのVBUSから5Vを取るようにしたのは先述の通りだが、これで問題は解消したように見える。3.3V以上の電源を安定して確保するよう気を付けた方がよさそうだ。

計測結果

計測結果を下のグラフに示す。青がSGP30、赤がSCD30の値のCO2値で、灰色はSGP30から取れるTVOC値を参考情報として示したものである。

なおSCD30は7日間のベースライニング期間が終わっていないので、オフセットが仕様より大きく出ている可能性がある。

f:id:tomoto335:20200715055639p:plain

SCD30の測定値は、閉め切った部屋で仕事をしていればほぼ線形に上がるし、窓を全開にして換気すれば即座に下がる。体がセンサーの方を向いていればそれにも敏感に反応する。絶対値の正しさは確かめようがないが、増減の仕方とその範囲からして、測りたいものをちゃんと測ってくれている感じがする。

一方SGP30は、何を測っているのか正直わからない。人がいてもいなくても突然1000やひどいときには数1000まで上がったりする。また、部屋を空けて食事に出るとSCD30は期待通り下がるのに対しSGP30は上がることが何度かあり、外から入ってくる食事のにおいに反応しているようにも見える。実際TVOC値と並べてみると強い相関があり(自分のプログラムの誤りで同じ値を使ってしまっているのではないかと疑うほど)、結局のところあまり役に立つ指標ではなかった、という感想である。

まとめ

SGP30は廉価でガスセンシングの入門にはなる(見えないものを測る面白さには触れられる)が、結局何を測っているのかわからないのですぐに飽きると思う。CO2を測りたいのなら、少々高いが最初からSCD30を買う方がいいだろう。

SCD30を使うなら、気圧補正のためBME280かBMP280を一緒に使うことをお勧めする。また、湿度計機能も使いたいなら、温度補正用に別の温度センサーが欲しくなると思う。私は個人的にはDS18B20+をお勧めするが、こちらの記事も参考にしてもらいたい。

私は結局、温度/湿度/気圧/CO2濃度を測るのにDS18B20+/BME280/SCD30の3センサーを載せたボードを組むことになった。贅沢で無駄が多い構成だとは思うが、趣味でデータ取ってニヤニヤするにはまあこんなものだろう。