2021年2月28日日曜日

HDC1080 と RaspberryPI と Golang で温度湿度を読み取る

  タイトルの通りなんですが、Amazonで購入した HDC1080 という温度と湿度を測るチップをRaspberry PI4 とGO言語を使ってI2Cバスから読み取ってみました


HDC1080のデータシートはここから手に入れました

# i2cdetect -y 1

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f

00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 

10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 

20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 

30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 

40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 

50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 


似たような温度湿度センサーSi7021と同じアドレスだ

Pythonは嫌だ

 なんだってまたGo言語を使うのかというと、HDC1080の読み取りでググるとほとんどがPythonで書かれているんですよね
 で、PythonはPython2とPython3で互換性がなく、パッとソースみただけじゃどっちかわかんない書き方をしているものが多いです

 pipコマンドでライブラリを入れるんですが、pip3だとpip2だのいろいろバージョンがでてくる

 しかも pip serch 欲しいライブラリすると...

pip3 search test

ERROR: XMLRPC request failed [code: -32500]

RuntimeError: PyPI's XMLRPC API has been temporarily disabled due to unmanageable load and will be deprecated in the near future. See https://status.python.org/ for more information.

 ううーん、pip3 install ホゲホゲ はできるのに、サーチできない。

 pip3をアップデートしろ、という書き込みをみたのでアップデートしたらpip(Python2のほう)がぶっ壊れたww

 真の原因は、どうやら現在searchする為のサーバーが攻撃だかリクエスト有りすぎだかでダウンしていて、回復する見込みはないという絶望的な状態とのこと(2021/02現在)

 意味わからんのでPythonは金輪際使いたくない。

 昔インフラの仕事もしてたから、破壊的バージョンアップを平気でするスクリプト系は嫌いなんだよ。Dockerとかこのあたりを解決したかったんじゃないかとも思える 

 Rubyは2.0系にAppleが開発に加わって破壊的なのが激減したから許す

Raspberry PI on Go Lang

Go言語はクロスコンパイルがめっちゃ楽なので、本当はmacで実行ファイル作ってRaspberry PIに転送してたんだけど、Raspberry PI単体でも当然コンパイルできます

 でもSDカードの寿命をうんとこ縮めるので、実機コンパイルするならSSDやHDDで起動したラズパイにしましょう

$ sudo apt install golang

...

$ go version

go version go1.11.6 linux/arm64

インストール終了。1.11はちょっと古いけどまぁいいか。環境変数 $GOPATHの取り扱いがどこかのバージョンで変更されているので気をつけたいけど、今回のようなちっさいプログラムだとあんま関係ない

さらにi2cのライブラリを入れるんだけど、gobotという無敵ライブラリはあまりにでっかいので、100行くらいの小さいライブラリをgithubからみつけたのでこれを入れる

go get github.com/davecheney/i2c

これでライブラリがgithubから読み込まれて、ソースコードから読み出せるようになった

で、Go言語はフォルダ名とかソース名にとても意味があるので注意しよう

$ mkdir hd1080

$ cd hd1080

ソースを書く(main.goにする事)

 $ vi main.go


package main


import (

  "fmt"

  "time"

  "github.com/davecheney/i2c"  // go get github.com/davecheney/i2c

  "encoding/binary"

)


const (

    wait = 100 * time.Millisecond

)


func write(dev *i2c.I2C, s string) {

  chars := []byte(s)

  dev.Write(append([]byte{0x40}, chars...))

  time.Sleep(wait)

}


func main() {

  if len(os.Args) < 2 {

    fmt.Println( "exp: hdc1080 0 or 1 (0=Ondo 1=Shitudo")

    os.Exit(-1)

  }

  var b = []byte{0, 0}

  var c float32


  if os.Args[1] == "0" {

    // 0x40 is I2C address , 4 is /dev/i2c-4

    dev, _ := i2c.New(0x40, 4)


    dev.Write([]byte{0x00})

    time.Sleep(wait)

    dev.Read(b)


    c = float32(binary.BigEndian.Uint16(b))/65536.*165. - 40.

    time.Sleep(wait)

    fmt.Printf("%.2f\n",c)

  } else {

    dev, _ := i2c.New(0x40, 4)


    dev.Write([]byte{0x01})

    time.Sleep(wait)

    dev.Read(b)


    c = float32(binary.BigEndian.Uint16(b)) / 65536. * 100.

    time.Sleep(wait)

    fmt.Printf("%.2f\n",c)

  }

}

自分のラズパイ4は i2c の4番を使っているので 

  dev,_ := i2c.New(0x40,4)

となっているが、普通は

  dev,_ := i2c.New(0x40,1)

として、/dev/i2c-1 を使うようにしよう

 

I2Cの追加方法はこちら

コンパイル前に go.mod ファイルを作っておく
一度きりでOK

go mod init hdc1080


ソースを変更したらビルドして実行ファイルを作る

GOOS=linux GOARCH=arm go build 

または

$ GOOS=linux GOARCH=arm64 go build 

main.go というファイル名だと勝手にうまいことコンパイルして、ディレクトリ名の実行ファイルができる

$ ls

hdc1080  main.go


$ ./hdc1080 

18.7127685546875

45.574951171875

部屋の温度は18.7度で、湿度が45%くらいとの事

懐かしい寒暖計もだいたいそのくらいを指しているので信じる事とする

あとはこの値をzabbixなどに食わせればグラフ化できたりする。


追加

I2Cをsudoしなくても読めるようにする

これはグラフツールのzabbixが読めるようにする設定
ユーザー名がpiの人は zabbix を pi にするとよさそう

# sudo usermod -aG i2c zabbix


end

0 件のコメント:

コメントを投稿