Raspberry Pi と Senseair Sunrise で CO2 濃度計測編

Raspberry Pi と Senseair Sunrise を使って CO2 濃度を測ります

このブログは、N 高等学校と VRChat の世界からやってきた株式会社 Armoris アルバイトの Shadero が書いています。
あるもりすぶろぐの内容は個人の意見です。

なぜ CO2 濃度なのか

厚労省からコロナ対策の一環として、良好な換気状態を示すCO2 濃度の基準値が提示されています。
これを参考に社内でも対策の一環として適切な換気状態の維持を目的として CO2 濃度の計測を行います。

Senseair Sunrise ってなに?

Senseair Sunriseとは2018 年に旭化成のグループ会社になった Senseair 社が開発する CO2 センサーのこと。

今回このセンサーを使用するのは、Winsen 社の MH-Z19 など他の CO2 センサーと比べて消費電力が比較的少ないこと、400 ~ 5000ppm まで CO2 濃度を計測可能で、誤差も ±30ppm で一般的な用途としては十分な計測範囲と精度を持っているためです。

(センサーは Digikey から 6500 円くらいで購入可能です)

環境

Type Name
PC Raspberry Pi 3 Model B+
OS Raspbian 10 buster
CO2 sensor Senseair Sunrise

CO2 センサーを繋ぐ PC は、先日の記事で温度・湿度・気圧をグラフ化した際に使用したラズパイを使用しています。

また、Senseair Sunrise は I2C と UART の 2 つの通信手段で通信が可能ですが、今回は UART を使用して通信を行います。
(UARTはアドレスを意識しなくて済むので少しだけ楽)

シリアル通信を有効にする

早速ラズパイと Senseair Sunrise を繋ぐ…!といきたい所ですが、ラズパイと Senseair Sunrise 間で使用するシリアル通信が、ラズパイのデフォルト設定では無効になっているためraspi-configから有効にします。

  1. $ sudo raspi-config
  2. Interface Options と書かれた項目を選択 f:id:Armoris:20210513164925p:plain
  3. Serial Port と書かれた項目を選択 f:id:Armoris:20210513165139p:plain
  4. シリアル通信経由でシェルにログインするか聞いてくるので No を選択 f:id:Armoris:20210513165331p:plain
  5. シリアル通信を有効にするため Yes を選択 f:id:Armoris:20210513165450p:plain

ラズパイと Senseair Sunrise を繋いでみる

シリアル通信が有効になったら、いよいよラズパイと Senseair Sunrise を繋ぎます。

Senseair Sunrise の統合ガイドを参照して今回は各ピンを以下のように接続しています。

Senseair Sunrise Raspberry Pi 3 Model B+
VDD 3V3Power P17
EN 3V3Power P17
VDDIO 3V3Power P17
DVCC 接続しない
RXD/SDA GPIO 14(TXD) P8
TXD/SCL GPIO 15(RXD) P10
nRDY 接続しない
COMSEL 接続しない
GND Ground P25

CO2 濃度を取得してみる

Senseair Sunrise のデータシートを参照しながら Golang を使って CO2 濃度を取得するコードを書きます。

package main

import (
    "log"
    "time"

    "github.com/tarm/serial"
)

func main() {
    // どのポートを使うのか、どの速度で通信するのか、何ミリ秒でタイムアウトするのかを設定してポートを開く。
    c := &serial.Config{
        Name:        "/dev/serial0",
        Baud:        9600,
        ReadTimeout: time.Millisecond * 180}
    ser, err := serial.OpenPort(c)
    if err != nil {
        log.Fatal(err)
        return
    }
    defer ser.Close()

    // CO2濃度を取得するためのメッセージを用意してセンサーに送信する。
    // (詳細はセンサーのデータシートとModbusプロトコルの仕様を参照してくれると幸いです。)
    co2Read := []byte{0xfe, 0x04, 0x00, 0x03, 0x00, 0x01, 0xd5, 0xc5}
    if _, err = ser.Write(co2Read); err != nil {
        log.Fatal(err)
        return
    }

    // センサーからラズパイ側に値が送られるまで待つ
    time.Sleep(time.Millisecond * 50)

    // センサーから送られてきた値を保存する。
    buf := make([]byte, 128)
    _, err = ser.Read(buf)
    if err != nil {
        log.Fatal(err)
        return
    }

    // センサーから送られてきた値を人間が読めるように変換してログに表示する。
    co2 := (int(buf[3]) << 8) | int(buf[4])
    log.Printf("%vppm\n", co2)
}

  1. Golangのコードをラズパイ向けに設定してビルドします。

    $ GOOS=linux && GOARCH=arm && GOARM=6`
    $ go build ./GetCO2
    

  2. 実行ファイルに実行権限を付与して実行します。

    $ chmod 744 ./GetCO2
    $ ./GetCO2
    

結果

上記のコードをビルドして実行すると CO2 濃度がシェルに表示されます! f:id:Armoris:20210513175721p:plain

やってみて

Senseair Sunrise のデータシートを見ながら動かしていったのですが、筆者の経験不足から「これ動くのかな…。」と思いながらずっと作業していました...。
とりあえずセンサーを壊さずに動かせたのでよかったです!
(画像は Senseair Sunrise をユニバーサル基板の上に配置して動かしたときの画像) f:id:Armoris:20210513184151j:plain

Senseair Sunrise に関する文献が少ないのと、筆者の知識不足が相まって情報に誤りや不足があるかもしれません。お気づきの方はコメントを頂けると幸いです…!

ご覧いただきありがとうございました!