ラズパイで部屋の環境(温度湿度気圧CO2)をモニタリングするIoTデバイスを作る① ～センサーデータをPythonで取得する～

## はじめに
皆さんはご家庭に眠らせたままのラズパイやCO2センサ(MH-Z19C)、温湿度気圧センサ(BME280)はありませんか？
私はあります。

過去に市中製品でCO2濃度を取得できる良さげなIoTデバイスがなく自作しようと部品だけ集めて満足していたのですが、いつの間にかSwitchBotからCO2センサーが出てしまいました😇

このまま家のガラクタでいてもらうのも悲しいので、重い腰を上げ真っ当なIoTデバイスとして部屋の環境モニタリングで活躍してもらうことにします💪

## 使用するラズパイの情報
<table>
  <tr>
    <th> モデル </th> <td>Raspberry Pi 3 Model B+</td>
  </tr>
  <tr>
    <th> OS </th> <td>Raspberry Pi OS 12 (bookworm)</td>
  </tr>
  <tr>
    <th> Kernel </th> <td>6.6.47</td>
  </tr>
  <tr>
    <th> Python </th> <td>3.11.2</td>
  </tr>
</table>

※OSインストール方法等については触れませんので他の記事をご覧ください。

## シリアル通信とI2Cの有効化
今回利用するCO2センサ(MH-Z19C)はシリアル通信で、温湿度気圧センサ(BME280)はI2C通信でデータを取得します。
そのためこれらの通信を有効化する必要があります。
### シリアル通信の有効化
1. 設定画面を開く
    ```shell-session
    $ sudo raspi-config
    ```
1. 「3 Interface Options」を選択

    ![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870591/5471c5ad-7646-af9c-7913-07a19549c7e4.png)

1. 「I6 Serial Port」を選択

    ![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870591/b6b1fac3-da44-c496-ddbd-661cf1d2ff6e.png)

1. 「Would you like a login shell to be accessible over serial?」は「いいえ」

    ![003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870591/f924c40e-bc29-7155-3b8d-9613160e8a72.png)

1. 「Would you like the serial port hardware to be enabled?」は「はい」

    ![004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870591/e9bec011-8686-8e62-4967-a1d2408099a5.png)

1. 設定結果が表示されるので「了解」

    ![005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870591/8d546767-f20d-2358-62ed-e104b6071abe.png)

### I2C通信の有効化
1. 「3 Interface Options」を選択

    ![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870591/5471c5ad-7646-af9c-7913-07a19549c7e4.png)

1. 「I5 I2C」を選択

    ![006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870591/cd1e7bf5-3903-5134-da0a-989825d49c1c.png)

1. 「Would you like the ARM I2C interface to be enabled?」は「はい」

    ![007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870591/10d03f55-5bf2-36fe-e400-2c5ccdc865f0.png)

1. 設定結果が表示されるので「了解」

    ![008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870591/b178bf51-3cd5-035e-0b13-b77e41b707a9.png)

1. 「Finish」を選択して完了

    ![009.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870591/ca7918fd-c851-7815-e047-1f762f16f680.png)

### 再起動
設定が完了したら再起動しておきます。
```shell-session
$ sudo reboot
```

## ラズパイと各種センサーの接続
ラズパイと各種センサーはこのように配線しました。
※今回使用しているBME280は3.3V駆動なので注意

![配線図_ブレッドボード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870591/f6159c9a-c994-b733-e9fc-5d91c9cc308b.png)

## Pythonの仮想環境作成
ラブパイのPythonにはデフォルトで様々なライブラリが入っています。
環境を分けるためvenvを使用して仮想環境を作成し、そこに必要なライブラリをインストールします。
1. 仮想環境の作成とアクティベート
    「EnvDataCollector」という名前で仮想環境を作成し、仮想環境をアクティベートします。
    ```shell-session
    $ python -m venv EnvDataCollector
    $ cd EnvDataCollector/
    $ source bin/activate
    (EnvDataCollector) $
    ```

1. 温湿度気圧センサ(BME280)用ライブラリのインストールと動作確認
    仮想環境に[cgsensorライブラリ](https://github.com/IndoorCorgi/cgsensor)をインストールします。
    ```shell-session
    (EnvDataCollector) $ pip install cgsensor
    ～省略～
    Successfully installed cgsensor-1.1 docopt-0.6.2 smbus2-0.5.0
    ```

    センサーを接続していればコマンドで動作確認できます。
    ```shell-session
    (EnvDataCollector) $ cgsensor bme280
    BME280 測定
      温度[°C]:  25.4
      湿度[%]:   55.5
      気圧[hPa]: 1019.5
    ```

1. CO2センサ(MH-Z19C)用ライブラリのインストール
    仮想環境に[mh-z19ライブラリ](https://github.com/UedaTakeyuki/mh-z19)をインストールします。
    ```shell-session
    (EnvDataCollector) $ pip install mh-z19
    ～省略～
    Successfully installed RPi.GPIO-0.7.1 argparse-1.4.0 certifi-2024.8.30 charset-normalizer-3.4.0 colorzero-2.0 getrpimodel-0.1.26 gpiozero-2.0.1 idna-3.10 lgpio-0.2.2.0 mh-z19-3.1.6 pyserial-3.5 requests-2.32.3 urllib3-2.2.3
    ```

    センサーを接続していればコマンドで動作確認できますが、root権限が必要なため仮想環境から抜けてから実施します。
    ```shell-session
    (EnvDataCollector) $ deactivate
    $ sudo bin/python -m mh_z19
    {"co2": 1846}
    ```
    (高いですね...通りで眠いわけだ😴)
## Pythonでのセンサーデータの取得
次のコードで各種センサーの値を取得します。
```python:main.py
import mh_z19
from cgsensor import BME280

class EnvDataCollector:
    def __init__(self) -> None:
        self._bme280: BME280 = BME280()

    def _get_data_from_mh_z19c(self) -> int:
        return mh_z19.read()["co2"]

    def _get_data_from_bme280(self) -> tuple[float, float, float]:
        self._bme280.forced()
        return self._bme280.temperature, self._bme280.humidity, self._bme280.pressure

    def execute(self) -> bool:
        is_succeeded: bool = True

        try:
            concentration: int = self._get_data_from_mh_z19c()
            print(f"{concentration=}")
        except Exception as e:
            print(f"{e=}")
            is_succeeded = False

        temperature: float
        humidity: float
        pressure: float
        try:
            temperature, humidity, pressure = self._get_data_from_bme280()
            print(f"{temperature=}")
            print(f"{humidity=}")
            print(f"{pressure=}")
        except Exception as e:
            print(f"{e=}")
            is_succeeded = False

        return is_succeeded

if __name__ == "__main__":
    print(f"result: {EnvDataCollector().execute()}")

```

root権限で実行し各種センサー値をプログラムで取得できていることが確認できます。
※MH-Z19Cからのデータ取得にroot権限が必要です。
```shell-session
$ sudo bin/python main.py
concentration=1161
temperature=25.6
humidity=45.2
pressure=1018.7
result: True
```

## さいごに
センサーからデータ取得できるようになりましたが、このままではシェル上にしかデータを表示できないのでIoTデバイスとは呼べません。
次の記事ではIoTデバイスたらしめるため、AWS IoTCoreに接続しデータを送信できるようにしていきます。

https://qiita.com/h0uk1st4r/items/42ce9ede4a54e05d9955