SCD41でCO₂濃度を測ってみた話（Raspberry Pi + Ubuntu 24.04）

# きっかけ
新しい仕事が始まり、最初は出社ベースで研修を受けていますが、慣れてくればリモートワークと併用になる予定です。
そうなると自然と、自宅の作業環境を整えたいという気持ちが強くなってきました。

「このタイミングしかないな」と思い立ち、仕事用のデスク周りを見直したり、空調や照明の自動化、センサーによる環境モニタリングなど、いろいろなアイデアを試してみています。

特に気になったのが部屋の空気の質です。
以前から「集中力が切れるときって、CO₂濃度が高いときなんじゃ？」と感じていたので、放置していたSCD41を引っ張り出して、ようやく実験を開始しました。

ちょうど、I²Cに触れる良い機会でもあったので、センサーの読み取りからグラフ表示まで一通りやってみようと、いろいろ試しながら開発を進めています。

この流れで、今後も自宅環境の改善に役立ちそうなツールやアプリを自作していくつもりです。

[前回記事](https://qiita.com/jyukipann/items/41394c56e66dddf4fc97)に引き続きIoT関連の記事です。

# 使用したもの

- [SCD41](https://sensirion.com/jp/products/catalog/SCD41)（Sensirion製のCO₂センサー）
- Raspberry Pi 4 ( Ubuntu 24.04 LTS )
- はんだごて（部品で買ったので自分ではんだ付け）

# 配線について
SCD41は3.3Vで動作させました。5vでも動くようです。
Raspberry Pi 4とはI²Cで接続しました。

| SCD41ピン | Raspberry Piピン |
|-----------|------------------|
| VDD       | 3.3V             |
| GND       | GND              |
| SDA       | SDA (GPIO2)      |
| SCL       | SCL (GPIO3)      |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200387/63cac824-11bb-4ea8-b9b1-744c2244a5c2.png)
配線がないものを買ったため、自分ではんだしました。逆側はピンソケットにしたため、ラズパイのGPIOに直接接続できます。

# 環境構築
Ubuntuにインストール済みのPython環境をいじるのは良くないので、venvで環境構築します。
```bash
python -m vnev scd41
```
以下のようにI²CのツールやPythonパッケージをインストールしました。
```bash
sudo apt update
sudo apt install -y i2c-tools
source scd41/bin/activate
pip install sensirion-i2c-driver sensirion-i2c-scd
```
I²Cを有効にしていない場合は、`raspi-config`や`/boot/firmware/config.txt`で設定が必要です。

## 接続確認
```bash
i2cdetect -y 1
```
このように`0x62`に接続されていることが確認できました。
```
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- 62 -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --                  
```


# テストコード
以下に、センサーから値を取得してコンソールに表示するだけの簡単なスクリプトを紹介します。
ChatGPTの協力に感謝。
```python
import time
from sensirion_i2c_driver import I2cConnection
from sensirion_i2c_driver.linux_i2c_transceiver import LinuxI2cTransceiver
from sensirion_i2c_scd.scd4x.device import Scd4xI2cDevice

# I2C バス番号（通常は1）
i2c_bus_number = 1

# LinuxI2cTransceiver を使用
i2c_transceiver = LinuxI2cTransceiver(f'/dev/i2c-{i2c_bus_number}')
i2c_conn = I2cConnection(i2c_transceiver)
scd4x = Scd4xI2cDevice(i2c_conn)

# 測定開始
try:
    scd4x.stop_periodic_measurement() # まずは測定を停止(前回の測定が残っている場合)
except Exception as e:
    pass

scd4x.start_periodic_measurement()
print("SCD41がウォームアップ中... 5秒待機")
# time.sleep(5)

try:
    while True:
        time.sleep(5)
        measurement = scd4x.read_measurement()
        # print(measurement)
        co2, temp, humid = measurement
        print(co2, temp, humid)

except KeyboardInterrupt:
    scd4x.stop_periodic_measurement()
    print("終了します")
```

# 実行結果
実行すると、こんな感じで表示されます。
```
SCD41がウォームアップ中... 5秒待機
857 ppm 25.1 °C 68.5 %RH
828 ppm 24.9 °C 69.8 %RH
832 ppm 24.8 °C 70.8 %RH
856 ppm 24.7 °C 71.8 %RH
^C終了します
```
キャリブレーションなどは特にしていないため、正確性には疑義があります。

# まとめ
- 準備
- 接続
- 環境構築
- サンプルコード実行

本稿でサンプルコード実行までできました。

# 今後の展望
API化して、Grafanaとかと組み合わせてダッシュボードを作ってみるのも面白そうです。