Raspberry Pi 3B+ と MH-Z19C (2024/bookwarm)
とりあえずRaspberry Pi OSをSDカードに焼いてあるものとします。
- Raspberry Pi 3B+
- Raspbery Pi OS Lite (64bit)
raspi-config
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
- Would you like a login shell to be accessible over serial ?
Finish
- 再起動する?と聞いてくるのでYes
UARTを有効化
BluetoothをPL0116からminiUARTへ切り替える
- RPi3Bに搭載されているUART機能はPL0116(H/W)とminiUART(S/W)の2つ
- フル機能が使えるのはPL0116の方
- どちらかをBluetoothに割り当てる場合は以下の通り
- そもそもBluetoothを使わない方法もあるけど今回はめんどいので省略
sudo nano /boot/firmware/config.txt
以下の内容を書き込む
# UART config
dtparam=krnbt=off
dtoverlay=miniuart-bt
core_freq=250
再起動して設定を反映する
sudo reboot
serial*の設定を確認
serialのどれかがPL0116(ttyAMA)になっているはず
ls -al /dev | grep serial
lrwxrwxrwx 1 root root 7 May 19 23:51 serial0 -> ttyAMA0
serial0(UART0)がttyAMA0として設定されている
GPIO/UARTの対応を確認
pinctrl get 14-15
14: a0 -- | lo // GPIO14 = TXD0
15: a0 -- | hi // GPIO15 = RXD0
UART0(TXD0/RXD0)がGPIO14/15に割り当てられている
UARTの読み書きができるようにユーザーに権限を付与
sudo usermod -aG dialout pi
Pythonでスクリプトを書いて読み込む
PIPをインストール
sudo apt-get install python3-pip
pySerialをインストール
sudo pip3 install pyserial --break-system-packages
スクリプトを作成
touch uart.py
chmod 755 uart.py
nano uart.py
以下のコードを書き込む
#!/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の電源を切る
sudo poweroff
センサーを接続する
センサーがVIN 5.0V±ちょいというシビアな環境なのでNJM7805で5.0Vを作成
スペックシートは以下リンク先
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の電源を入れる
配線がショートしていないか確認しつつ電源を入れる
スクリプトを動かしてみる
./uart.py
こんな感じで値が返ってくる
(Byte4とByte6にノイズが乗ってるけど使わないからとりあえず影響はない)
---[Co2 Value]---
754
---[Debug]---
255
134
2
242
66
0
2
0
66
はまりどころ
- UARTを使うときはGNDのレベルを合わせないと通信できない
- RPiのレガシーOSは設定/boot/になっているけれど新型では/boot/firmaware/に移動している
- dtoverlay=miniuart-bt は=の左右にスペースを入れると反映されない