😺
Go言語によるRaspberry, MH-Z19B, DHT22を利用した環境測定
はじめに
前回の記事ではCO2濃度だけだったのですが、手持ちのセンサーを追加して気温と湿度も測定できるよう拡張しました。
環境設定
- 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 get go.bug.st/serial
- DHT22用ライブラリ
$ go get github.com/MichaelS11/go-dht
機器の接続
※図ではRasberry Pi3となっていますが、実際にテストしたのはPi4です。
プログラム説明
- main()
- mainで1分おきにループしてCO2測定処理、温度・湿度測定処理を呼出し、結果をログ出力します
- getMH_Z19B()
- シリアル通信でCO2濃度を取得しています
- 本来readできるデータのサイズは9バイトなのですが、結構なタイミングで先頭部分が欠落します。欲しいデータは3バイト目と4バイト目なので、ここが欠落した場合は5回リトライして、だめならあきらめます
- getDHT22()
- DHT22との通信は専用の単線式デジタル通信なので、すべてモジュールにおまかせです。
プログラム
package main
import (
"errors"
"log"
"time"
"go.bug.st/serial"
"github.com/MichaelS11/go-dht"
)
func main() {
for range time.Tick(time.Minute*1) {
co2Conc, err1 := getMH_Z19B()
if err1!=nil {
log.Println("getDHT22 error:",err1)
}
temperatur, humidity, err2 := getDHT22()
if err2!=nil {
log.Println("getDHT22 error:",err2)
}
log.Printf("Tmp:%4.1f, Hum:%.1f %%, CO2:%4d ppm", temperatur, humidity, co2Conc)
}
}
func getMH_Z19B() (int, error) {
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("Z19B serial port open error:",err)
return 0,err
}
defer port.Close()
buf := make([]byte, 128)
readCmd := []byte{0xff, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}
for i:=0; i<5; i++ {
_, errW := port.Write(readCmd)
if errW != nil {
log.Println("Z19B serial port write error:",err)
continue
}
nRead, errRead := port.Read(buf)
if errRead != nil {
log.Println("Z19B serial port read error:",err)
continue
}
if nRead>=7 {
co2conc := int(buf[nRead-7])*256 + int(buf[nRead-6])
return co2conc,nil
} else {
//log.Println("Z19B serial port read size error:",nRead)
continue
}
}
return 0,errors.New("MH_Z19B error")
}
func getDHT22() (float64,float64,error) {
err := dht.HostInit()
if err != nil {
log.Println("HosiInit error:", err)
return 0.0,0.0,err
}
dht, err := dht.NewDHT("GPIO18", dht.Celsius, "")
if err != nil {
log.Println("NewDHT error:", err)
return 0.0,0.0,err
}
humidity, temperature, err := dht.ReadRetry(11)
if err != nil {
log.Println("Read error:", err)
return 0.0,0.0,err
}
return temperature, humidity, nil
}
最後に
- 持っていた温度・湿度センサーはBME280だと思っていたのですが、安いDHT22でした。
- DHT22も精度は高く、手持ちの気温計と0.1℃程度のズレしかありませんでした。
- 私はほぼなにもしていなくて、全てモジュールなどを提供してくれた方々のおかげです。以下順不同で感謝したいと思います。
- (DHT22モジュール)[https://github.com/MichaelS11/go-dht]
- (シリアル通信モジュール)[https://github.com/bugst/go-serial]
- (fritzing無料版)[https://github.com/fritzing/fritzing-app/releases]
- (fritzing部品)[https://github.com/TD-er/fritzing-parts/blob/master/MH-Z19_CO2/MH-Z19 CO2 sensor.fzpz]
- (fritzing部品)[https://github.com/HuangYuTse/DHT22-module-fritzing-part/blob/master/DHT22 module.fzpz]
Discussion