虎の穴開発室ブログ

虎の穴ラボ株式会社所属のエンジニアが書く技術ブログです

MENU

オフィスのCO2濃度を測定してみたい

こんにちは、今年最後の虎の穴開発室ブログ執筆者の虎の穴ラボのH.Yです。

今回は、CO2の濃度を安めのCO2センサーとRaspberry Piを使って測ってみたという内容です。

昼過ぎに眠くなるのは一体。

お昼過ぎに何故か眠くなるので、はじめは常に高い血糖値がさらに高くなって云々で眠くなると考えていたのですが、
同僚からSlackでこんな記事を紹介されました。

ch.nicovideo.jp

全く同じ事象がTeamLabさんでも起きていたということ。
記事を見ると、CO2濃度が眠気の原因で、換気したらよくなったという

とりあえず、現状を把握するために、Raspberry Piを使ってCO2濃度測定器を作ることに。

ハードウェア部分

必要なものは2つ
・CO2センサー(MH-Z19B)

f:id:toranoana-lab:20191224193835p:plain Amazon CAPTCHA
比較的安めで、UARTでデータが取れます。

・Raspberry Pi(Raspberry Pi 3 Model B)

f:id:toranoana-lab:20191224194306p:plain https://www.yodobashi.com/product/100000001004207792/
最近Raspberry Pi4が出てるけど、作ったときは日本未発売だったので、3Bを使用。

CO2センサーとRaspberry PiをUARTで接続します。

ソフトウェア部分

今回のアプリでは、以下2点の機能を作りました。
・CO2濃度を測定すること
・DBにデータを蓄積すること

まず、Raspberry PiでUARTを有効にする設定を行います。

vi /boot/config.txt

以下の内容を追記

enable_uart=1

追記したら再起動して設定を反映にします。

シリアル通信部分の実装はよくわからなかったので↓の記事を参考にしました。
Raspberry Pi 3 で CO2濃度を測る - Qiita
(じつは諸々書いてあります)
ついでに、何かで使うかもしれないので、SQLiteにデータを挿入していきます。(申し訳程度のオリジナル要素)

今回使用するpythonのバージョンは3.7.3を使用します。 使用するライブラリを追加します。

pip install pyserial
pip install redis
pip install sqlalchemy
pip install getrpimodel

co2_measure.py(ここの部分を実行することで、CO2濃度の出力とDBに挿入を行います。)

import serial
import getrpimodel
import subprocess

from insert_record import insert_co2

#Raspberry Piのモデルごとの初期設定
if getrpimodel.model() == "3 Model B":
  serial_dev = '/dev/ttyS0'
  stop_getty = 'sudo systemctl stop serial-getty@ttyS0.service'
  start_getty = 'sudo systemctl start serial-getty@ttyS0.service'
else:
  serial_dev = '/dev/ttyAMA0'
  stop_getty = 'sudo systemctl stop serial-getty@ttyAMA0.service'
  start_getty = 'sudo systemctl start serial-getty@ttyAMA0.service'

#CO2センサーからデータを取得するところ
def read():
    try:
        ser = serial.Serial(serial_dev,
                          baudrate=9600,
                          bytesize=serial.EIGHTBITS,
                          parity=serial.PARITY_NONE,
                          stopbits=serial.STOPBITS_ONE,
                          timeout=1.0)

        #CO2濃度を取得するコマンド送信
        result=ser.write(b'\xff\x01\x86\x00\x00\x00\x00\x00\x79')
        s=ser.read(9)

        #取得した形式が正しければCO2濃度を10進法に変換してretrun
        if len(s) >= 4 and s[0] == int('ff',16) and s[1] == int('86',16):
            return s[2]*256 + s[3]

    except IOError:
          print('IOエラー')
    except:
          print('その他エラー')

p = subprocess.call(stop_getty, stdout=subprocess.PIPE, shell=True)
co2_concentration = read()
p = subprocess.call(start_getty, stdout=subprocess.PIPE, shell=True)
if co2_concentration is not None:
    #CO2濃度が取得できていればCO2濃度の標準出力
    print('CO2濃度:',co2_concentration,'ppm', flush=True)
    #CO2濃度をDBに挿入
    insert_co2( co2_concentration )

insert_record.py(CO2を挿入する部分)

from models.co2_records import Base, Co2Records
from database.database import session,engine
from datetime import datetime

#現在日付とCO2濃度を記録するメソッド
def insert_co2( co2_concentration ):
    Base.metadata.create_all(engine)
    dt_now = datetime.now()
    record = Co2Records(dt_now, co2_concentration)
    session.add(record)
    session.commit()
    session.close()

database.py

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine

#SQLite用の接続設定
engine = create_engine('sqlite:///data.sqlite')
Session = sessionmaker(bind=engine)
session = Session()

co2_records.py

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, DateTime
import datetime

Base = declarative_base()

#DBのCO2濃度のモデルクラス
class Co2Records(Base):

    __tablename__ = 'co2_records'
 
    create_datetime = Column(DateTime, primary_key=True)
    co2_concentration = Column(Integer)

    def __init__(self, create_datetime, co2_concentration):
        self.create_datetime = create_datetime
        self.co2_concentration = co2_concentration

    def __repr__(self):
        return "<Co2_record(create_datetime='%s', co2_concentration='%s')>" % (
            self.create_datetime, self.co2_concentration)

このソースを使い、CO2濃度を表示していくには、

watch -n 1 python co2_measure.py

で行います(ゴリ押し)

Raspberry Piの設置場所が、割と目立つところがあるので、結構確認しやすいので、これでよし!
f:id:toranoana-lab:20191223190312p:plain

運用してみると、Slackで通知するよりも常に表示したほうが直感的にCO2濃度が高いとわかります。
若干適当な感じがしますが、一旦このまま運用しています。

昼過ぎぐらいに1000ppmを超えることがあったので、
f:id:toranoana-lab:20191223191604p:plain
上のように濃度関係なしに、定期的に換気促すようにbotを動かしました。

5分ぐらい換気すると、問題なさそうなぐらいまで下がりました。
f:id:toranoana-lab:20191224194709j:plain

あとがき

こころなしか、昼過ぎでもスッキリしたような感じがします(プラシーボかも・・・
大体毎秒、DBにCO2濃度を書き込んでいるので、1日のグラフとかを作ってみたい気がします。
続きは、技術同人誌を書くことがあれば、そこに書いてみたいと思います。

P.S.

虎の穴では一緒に働く仲間を絶賛募集中です! 興味のある方は是非採用サイトを御覧ください! yumenosora.co.jp