Raspberry Pi 3B+ と MH-Z19C (2024/bookwarm)

# Raspberry Pi 3B+ と MH-Z19C (2024/bookwarm)

とりあえずRaspberry Pi OSをSDカードに焼いてあるものとします。

- Raspberry Pi 3B+
- Raspbery Pi OS Lite (64bit)

## raspi-config

```bash
sudo raspi-config
```

### 3.Interface Options

- I5 Serial Port
  - Would you like a login shell to be accessible over serial ?
    - NO
  - Would you like the serial port hardware to be enables ?
    - YES
  - OK

### Finish

- 再起動する？と聞いてくるのでYes

## UARTを有効化

### BluetoothをPL0116からminiUARTへ切り替える

- RPi3Bに搭載されているUART機能はPL0116(H/W)とminiUART(S/W)の2つ
  - フル機能が使えるのはPL0116の方
  - どちらかをBluetoothに割り当てる場合は以下の通り
    - そもそもBluetoothを使わない方法もあるけど今回はめんどいので省略

```bash
sudo nano /boot/firmware/config.txt
```

以下の内容を書き込む

```bash
# UART config
dtparam=krnbt=off
dtoverlay=miniuart-bt
core_freq=250
```

再起動して設定を反映する

```bash
sudo reboot
```

### serial*の設定を確認

serialのどれかがPL0116(ttyAMA)になっているはず

```bash
ls -al /dev | grep serial

lrwxrwxrwx  1 root root           7 May 19 23:51 serial0 -> ttyAMA0
```

serial0(UART0)がttyAMA0として設定されている

### GPIO/UARTの対応を確認

```bash
pinctrl get 14-15

14: a0    -- | lo // GPIO14 = TXD0
15: a0    -- | hi // GPIO15 = RXD0
```

UART0(TXD0/RXD0)がGPIO14/15に割り当てられている

### UARTの読み書きができるようにユーザーに権限を付与

```bash
sudo usermod -aG dialout pi
```

## Pythonでスクリプトを書いて読み込む

### PIPをインストール

```bash
sudo apt-get install python3-pip
```

### pySerialをインストール

```bash
sudo pip3 install pyserial --break-system-packages
```

### スクリプトを作成

```bash
touch uart.py
chmod 755 uart.py
nano uart.py
```

以下のコードを書き込む

```python
#!/usr/bin/python3

import serial
import time

if __name__=="__main__":
    read_command = bytes.fromhex('ff 01 86 00 00 00 00 00 79')
    startbyte = 0xff
    command = 0x86
    co2_value = 0
    while 1:
        try:
            uart = serial.Serial(port='/dev/ttyAMA0',
                                 baudrate=9600,
                                 bytesize=serial.EIGHTBITS,
                                 parity=serial.PARITY_NONE,
                                 stopbits=serial.STOPBITS_ONE,
                                 timeout=1.0)
            uart.flush()
            result = uart.write(read_command)
            time.sleep(0.1)
            value_array = uart.read(9)
            if len(value_array) >= 9:
                print("---[Co2 Value]---")
                if value_array[0] == startbyte and value_array[1] == command:
                    co2_value = value_array[2]*256 + value_array[3]
                    print(co2_value)
                print("---[Debug]---")
                print(value_array[0])
                print(value_array[1])
                print(value_array[2])
                print(value_array[3])
                print(value_array[4])
                print(value_array[5])
                print(value_array[6])
                print(value_array[7])
                print(value_array[8])
            else:
                print(len(value_array))
            time.sleep(1)
        except Exception as e:
            print(e)
```

## センサーを接続する

### RPiの電源を切る

```bash
sudo poweroff
```

### センサーを接続する

センサーがVIN 5.0V±ちょいというシビアな環境なのでNJM7805で5.0Vを作成
スペックシートは以下リンク先
[https://www.nisshinbo-microdevices.co.jp/ja/products/ldo-linear-regulator/spec/?product=njm7800](https://www.nisshinbo-microdevices.co.jp/ja/products/ldo-linear-regulator/spec/?product=njm7800)

|RPi|<--->|MH-Z19C|<--->|NJM7805FA|
|-----|-----|-----|-----|-----|
|(06) GND|<--->|<--->|<--->|Pin 2|
|||GND|<--->|Pin 2|
|||VIN|<--->|Pin 3|
|(08) GPIO14|<--->|RX|||
|(10) GPIO15|<--->|TX|||

## 値を読んでみる

### Rpiの電源を入れる

配線がショートしていないか確認しつつ電源を入れる

### スクリプトを動かしてみる

```bash
./uart.py
```

こんな感じで値が返ってくる
(Byte4とByte6にノイズが乗ってるけど使わないからとりあえず影響はない)

```bash
---[Co2 Value]---
754
---[Debug]---
255
134
2
242
66
0
2
0
66
```

## はまりどころ

- UARTを使うときはGNDのレベルを合わせないと通信できない
- RPiのレガシーOSは設定/boot/になっているけれど新型では/boot/firmaware/に移動している
- *dtoverlay=miniuart-bt* は=の左右にスペースを入れると反映されない