🐱
Go言語によるRaspberry PiとMH-Z19Bを利用したCO2濃度検出
はじめに
Raspberry Pi4-BとMH-Z19Bを使って部屋のCO2濃度を計測して遊んでいたのですが、これ計測結果をDBにためたり、濃度が一定値を超えるとメールしたりしたいなぁと感じました。普通はPythonでやるのでしょうが、Python嫌い苦手なので大好きなGoで書きました。
環境設定
Goのインストール
$ wget https://go.dev/dl/go1.23.4.linux-arm64.tar.gz
$ sudo tar -C /usr/local -xzf go1.23.4.linux-arm64.tar.gz
$ rm go1.23.4.linux-arm64.tar.gz
シリアル通信用のライブラリ取得(go mod initはよしなに)
$ go get go.bug.st/serial
Rapsberry Pi4-Bのシリアルポート設定
/dev/serial0がBluetoothに割り当てられている場合、ソフトウェアシリアルポートが適用されてCPU負荷の影響を受けてREADの際に先頭バイト(0xff)を取りこぼすケースがあったのでシリアルポートの設定を行った。
- /boot/firmware/config.txtの確認
- 以下の行によりbluetoothが無効になっていることを確認
dtoverlay=disable-bt
- raspi-configで以下を設定
プログラムソース
package main
import (
"fmt"
"log"
"os"
"go.bug.st/serial"
)
func main() {
mode := &serial.Mode{
BaudRate: 9600,
DataBits: 8,
Parity: serial.NoParity,
StopBits: serial.OneStopBit,
}
port, err := serial.Open("/dev/serial0", mode)
if err != nil {
log.Println("serial port open error:",err)
os.Exit(1)
}
defer port.Close()
buf := make([]byte, 128)
readCmd := []byte{0xff, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}
_, errW := port.Write(readCmd)
if errW != nil {
log.Println("serial port write error:",err)
os.Exit(2)
}
nRead, errRead := port.Read(buf)
if errRead != nil {
log.Println("serial port read error:",err)
os.Exit(3)
}
if nRead!=9 {
log.Println("serial port does't work. data size::",nRead)
os.Exit(4)
}
co2conc := int(buf[2])*256 + int(buf[3])
fmt.Println("CO2:", co2conc, "ppm")
}
プログラム説明
- シリアル通信のモード設定
- ポートは"dev/serial0"を使用
- MH-Z19Bの読み込みコマンドを送信する(データシート参照)
- 9バイトの計測結果からCO2濃度を取得(データシート参照)
- 結果を焼くなり、煮るなり好きなように
実行結果
$ go build main.go
$ sudo ./main
CO2: 1294 ppm
最後に
「なんでPythonでやらないの?馬鹿なの」という声が聞こえてきそうですが、Goが好きなんです。Rob PikeとRuss CoxがMy Heroなんです。
実はBME280という温度/湿度を取得できるセンサも所持しているので、これもなんとかRaspiにつないで温度/湿度/CO2濃度を記録できるようにしたいと思っています。
Discussion