Raspberry Pi PicoでCO2を計測・表示してみる

Raspberry Pi Picoでの開発の練習として、[以前ESP32で作成した](https://qiita.com/mine820/items/205fdc83dbb2731b84db)のと同じように、CO2を計測・表示してみました。

ほかの方も同じようなことをしているようですが、おそらく一番シンプルな方法で実現してます。

# 準備
- ハードウェア
    - Raspberry Pi Pico
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/be72e3dc-626e-9523-3aca-c0a8b6e98d49.png)
    - MH-Z19C（CO2センサー）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/54be6203-1014-ba5e-3a6f-86e3a403c472.png)
    - SSD1306（OLEDディスプレイ）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/22c6719a-4bce-bdf7-8ed8-aa93ee8c3079.png)
    - その他（ケーブルやらブレッドボードなど）
- ソフトウェア
    - MicroPython（Thonnyで開発）

# SSD1306用ライブラリの取得
自分で全部書くのはめんどくさかったので、先人の知恵をお借りすることにしました。
githubの[こちら](https://github.com/micropython/micropython/blob/master/drivers/display/ssd1306.py)からファイルをダウンロードし、Raspberry Pi Picoに入れました。

具体的には、githubのページでraw表示し、Thonnyの新規ファイルにコピペして、ファイル名「ssd1306.py」をつけてRaspberry Pi Picoに保存しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/69feaec1-6e23-d8d0-96c2-029b7f8d7d5c.png)

# 配線
CO2センサー、OLEDディスプレイの配線は以下のようになっています。

〇CO2センサー（UARTで通信）
|  | pico側 | CO2側 |
|:---:|:---:|:---:|
| 電源（5V） | VBUS（40番ピン） | Vin power in（3番ピン） |
| アース | GND（23番ピン） | GND（3番ピン） |
|  | UART1 TX（GP4、6番ピン） | UART(RXD)（5番ピン） |
|  | UART1 RX（GP5、７番ピン） | UART(TXD)（6番ピン） |

〇OLEDディスプレイ（I2Cで通信）
|  | pico側 | OLED側 |
|:---:|:---:|:---:|
| 電源（3.3V） | 3V3(OUT)（36番ピン） | VCC |
| アース | GND（23番ピン） | GND |
| SDA | I2C0 SDA（GP0、1番ピン） | SDA |
| SCL | I2C0 SCL（GP1、2番ピン） | SCL |

![DSC_0002.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/b1cf2522-e1c4-2010-5faf-9cc48223f298.jpeg)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/47ce994d-4c4d-1d5b-2bef-190ac6bb1b73.png)

# プログラミング
## CO2センサーからのデータの取得
まず、CO2センサーからデータを取得します。
```main.py
from machine import Pin, UART
import utime

mhz19c = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5))

while True:
    data = bytearray([0xff, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79])
    mhz19c.write(data)
    mhz19c.readinto(data,len(data))
    co2 = data[2] * 256 + data[3]
    temp = data[4] - 48
    print('CO2 (ppm):'+str(co2))
    print('Temperature (C):'+str(temp))

    utime.sleep(1)
```
なお、CO2の値だけでなく、温度も取得できるので、一緒に表示しています。

また、ファイル名は「main.py」にしておきます。
（起動時に自動で実行させたいので）

実行すると、Thonnyのコンソールに1秒間隔で取得したデータが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/ada41a0e-9fe0-5bc1-ff19-9ce562d2b914.png)

## OLEDディスプレイへの表示
次に、取得したデータをOLEDディスプレイに表示するようにします。
```main.py
from machine import Pin, UART, I2C
import ssd1306
import utime

mhz19c = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5))
i2c = I2C(0, sda=Pin(0), scl=Pin(1))
display = ssd1306.SSD1306_I2C(128, 32, i2c)

while True:
    data = bytearray([0xff, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79])
    mhz19c.write(data)
    mhz19c.readinto(data,len(data))
    co2 = data[2] * 256 + data[3]
    temp = data[4] - 48
    print('CO2 (ppm):'+str(co2))
    print('Temperature (C):'+str(temp))

    display.fill(0)
    display.text(str(co2)+' ppm', 0, 0, 1)
    display.text(str(temp)+' degree', 0, 10, 1)
    display.show()

    utime.sleep(1)
```

コンソールにも表示されますが、OLEDディスプレイにも取得したデータが表示されます。
（省略形で表示しています）
![DSC_0003.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/75ca3736-cbe8-57a3-f41e-8a29307cb09e.jpeg)

### 余談
USBケーブルが違うと、取得される値が異なるのが気になる．．．
供給電圧が低いのかな？
→キャリブレーションされたら（しばらくほっといたら）正しくなりました

## Raspberry Pi Picoの中身
ちなみに、Raspberry Pi Picoには以下の2つのファイルが置かれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/d6157b3b-4819-ccf0-2082-22531901e0d3.png)

できれば、モジュールのインストール（「pip intall 〇〇」）ができればいいんだけど、その辺りはまだよくわかりませんでした。
Raspberry Pi Picoに入れるMicroPythonを作り直せばいいのかな？

# まとめ
非常に簡単にCO2を計測・表示できました。