センサーのデータをinfluxdbへ送る

python版

参考URL(ラズパイ+BME280で温度・湿度・気圧を計測(BMP280は湿度なし)

次のpythonコードをcronで定期的(例えば3分毎)に実行し、influxdbのホストへ送信する。

#coding: utf-8
#encoding: utf-8

from influxdb import InfluxDBClient
client = InfluxDBClient(host='xxx.xxx.xxx.xxx', port=8086, username='****', password='****', database='iot01')
measurement = 'air5'
tags = {'place': 'leaf-bme280','host': 'RockPi4'}

from smbus2 import SMBus
import time

bus_number  = 7 # RockPi4の場合。 Raspiでは 1
i2c_address = 0x76

bus = SMBus(bus_number)

digT = []
digP = []
digH = []

t_fine = 0.0

def writeReg(reg_address, data):
        bus.write_byte_data(i2c_address,reg_address,data)

def get_calib_param():
        calib = []

        for i in range (0x88,0x88+24):
                calib.append(bus.read_byte_data(i2c_address,i))
        calib.append(bus.read_byte_data(i2c_address,0xA1))
        for i in range (0xE1,0xE1+7):
                calib.append(bus.read_byte_data(i2c_address,i))

        digT.append((calib[1] << 8) | calib[0])
        digT.append((calib[3] << 8) | calib[2])
        digT.append((calib[5] << 8) | calib[4])
        digP.append((calib[7] << 8) | calib[6])
        digP.append((calib[9] << 8) | calib[8])
        digP.append((calib[11]<< 8) | calib[10])
        digP.append((calib[13]<< 8) | calib[12])
        digP.append((calib[15]<< 8) | calib[14])
        digP.append((calib[17]<< 8) | calib[16])
        digP.append((calib[19]<< 8) | calib[18])
        digP.append((calib[21]<< 8) | calib[20])
        digP.append((calib[23]<< 8) | calib[22])
        digH.append( calib[24] )
        digH.append((calib[26]<< 8) | calib[25])
        digH.append( calib[27] )
        digH.append((calib[28]<< 4) | (0x0F & calib[29]))
        digH.append((calib[30]<< 4) | ((calib[29] >> 4) & 0x0F))
        digH.append( calib[31] )

        for i in range(1,2):
                if digT[i] & 0x8000:
                        digT[i] = (-digT[i] ^ 0xFFFF) + 1

        for i in range(1,8):
                if digP[i] & 0x8000:
                        digP[i] = (-digP[i] ^ 0xFFFF) + 1

        for i in range(0,6):
                if digH[i] & 0x8000:
                        digH[i] = (-digH[i] ^ 0xFFFF) + 1

def readData():
        data = []
        for i in range (0xF7, 0xF7+8):
                data.append(bus.read_byte_data(i2c_address,i))
        pres_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4)
        temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4)
        hum_raw  = (data[6] << 8)  |  data[7]

        temp = compensate_T(temp_raw)
        pres = compensate_P(pres_raw)
        humi = compensate_H(hum_raw)
        print (round(temp,2))
        print (round(pres,2))
        print (round(humi,2))
        json_body = [
                {
                        'measurement': measurement,
                        'tags': tags,
                        'fields': {'temp': round(temp,2) , 'humi': round(humi,2) , 'hpa': round(pres,2)}
                }
        ]
        client.write_points(json_body)
        print(json_body)


def compensate_P(adc_P):
        global  t_fine
        pressure = 0.0

        v1 = (t_fine / 2.0) - 64000.0
        v2 = (((v1 / 4.0) * (v1 / 4.0)) / 2048) * digP[5]
        v2 = v2 + ((v1 * digP[4]) * 2.0)
        v2 = (v2 / 4.0) + (digP[3] * 65536.0)
        v1 = (((digP[2] * (((v1 / 4.0) * (v1 / 4.0)) / 8192)) / 8)  + ((digP[1] * v1) / 2.0)) / 262144
        v1 = ((32768 + v1) * digP[0]) / 32768

        if v1 == 0:
                return 0
        pressure = ((1048576 - adc_P) - (v2 / 4096)) * 3125
        if pressure < 0x80000000:
                pressure = (pressure * 2.0) / v1
        else:
                pressure = (pressure / v1) * 2
        v1 = (digP[8] * (((pressure / 8.0) * (pressure / 8.0)) / 8192.0)) / 4096
        v2 = ((pressure / 4.0) * digP[7]) / 8192.0
        pressure = pressure + ((v1 + v2 + digP[6]) / 16.0)

        return (pressure/100)
        #print "pressure : %7.2f hPa" % (pressure/100)

def compensate_T(adc_T):
        global t_fine
        v1 = (adc_T / 16384.0 - digT[0] / 1024.0) * digT[1]
        v2 = (adc_T / 131072.0 - digT[0] / 8192.0) * (adc_T / 131072.0 - digT[0] / 8192.0) * digT[2]
        t_fine = v1 + v2
        temperature = t_fine / 5120.0

        return temperature
        #print "temp : %-6.2f ℃" % (temperature)

def compensate_H(adc_H):
        global t_fine
        var_h = t_fine - 76800.0
        if var_h != 0:
                var_h = (adc_H - (digH[3] * 64.0 + digH[4]/16384.0 * var_h)) * (digH[1] / 65536.0 * (1.0 + digH[5] / 67108864.0 * var_h * (1.0 + digH[2] / 67108864.0 * var_h)))
        else:
                return 0
        var_h = var_h * (1.0 - digH[0] * var_h / 524288.0)
        if var_h > 100.0:
                var_h = 100.0
        elif var_h < 0.0:
                var_h = 0.0

        return var_h
        #print "hum : %6.2f %" % (var_h)

def setup():
        osrs_t = 1                      #Temperature oversampling x 1
        osrs_p = 1                      #Pressure oversampling x 1
        osrs_h = 1                      #Humidity oversampling x 1
        mode   = 3                      #Normal mode
        t_sb   = 5                      #Tstandby 1000ms
        filter = 0                      #Filter off
        spi3w_en = 0                    #3-wire SPI Disable

        ctrl_meas_reg = (osrs_t << 5) | (osrs_p << 2) | mode
        config_reg    = (t_sb << 5) | (filter << 2) | spi3w_en
        ctrl_hum_reg  = osrs_h

        writeReg(0xF2,ctrl_hum_reg)
        writeReg(0xF4,ctrl_meas_reg)
        writeReg(0xF5,config_reg)

setup()
get_calib_param()

if __name__ == '__main__':
        try:
                readData()
        except KeyboardInterrupt:
                pass

Golang版

参考URL Armoris日記 ラズパイと BME280 で温度・湿度・気圧を測って グラフ化して表示する

Raspberry Pi4B 32biOSの場合

$ uname -a
Linux ps2 5.10.63-v7l+ #1457 SMP Tue Sep 28 11:26:14 BST 2021 armv7l GNU/Linux

コンパイル時に次を設定

$ GOOS=linux && GOARCH=arm && GOARM=6

const recordIntervalSec = 180で、データを投げる周期を指定します。(自分の環境では $HOME/influx/配下に配置)

package main

import (
    "context"
    "fmt"
    "time"

    influxdb2 "github.com/influxdata/influxdb-client-go/v2"
    "github.com/influxdata/influxdb-client-go/v2/api"
    "github.com/quhar/bme280"
    "golang.org/x/exp/io/i2c"
)

func initBme280() (*bme280.BME280, error) {
    d, err := i2c.Open(&i2c.Devfs{Dev: "/dev/i2c-1"}, 0x76) // 0x76は今回使用す るBME280のI2Cアドレス
    if err != nil {
        return nil, err
    }

    b := bme280.New(d)
    err = b.Init()
    return b, err
}

func recordSensorValues(b *bme280.BME280, w api.WriteAPIBlocking, measurement string) (err error) {
    t, p, h, err := b.EnvData()
    if err != nil {
        return
    }
    point := influxdb2.NewPoint(
        measurement,
        map[string]string{},
        map[string]interface{}{
            "temperature": t,
            "humidity":    h,
            "pressure":    p,
        },
        time.Now(),
    )
    err = w.WritePoint(context.Background(), point)
    if err != nil {
        return
    }
    fmt.Printf("Temp: %.2fC, Hum: %.2f%%, Press: %.2fhpa\n", t, h, p)
    return
}

func main() {
    const influxURL = "http://xxx.xxx.xxx.xxx:8086"      // InfluxDB APIのURL
    const userName = "*****"                      // influxDBのUser名
    const password = "*****"                       // influxDBのUserのPassword
    const db = "iot01"                             // influxDBのDatabase
    const measurement = "sensors"                  // influxDBのMeasurement(存在しない場合は実行時に生成される)
    const recordIntervalSec = 180                  // 値を書き込む間隔(秒)

    b, err := initBme280()
    if err != nil {
        panic(err)
    }
    c := influxdb2.NewClient(influxURL, fmt.Sprintf("%s:%s", userName, password))
    w := c.WriteAPIBlocking("", db+"/autogen")

    ticker := time.NewTicker(recordIntervalSec * time.Second)
    defer ticker.Stop()
    for {
        select {
        case <-ticker.C:
            err = recordSensorValues(b, w, measurement)
            if err != nil {
                panic(err)
            }
        }
    }
}

RockPi4で64bit OSの場合

$ uname -a
Linux rock 4.4.154-110-rockchip-gcef30e88a9f5 #1 SMP Mon Jun 22 07:37:10 UTC 2020 aarch64 aarch64 aarch64 GNU/Linux

aptでインストールしたgolangのバージョンが古いので、新しいバージョンを取得

$ GOOS=linux && GOARCH=arm64 && GOARM=6 でコンパイルはできるが、実行時にエラーとなる。(chip IDが違うよ! というエラー)

mars@rock:~/influx$ ~/go/bin/go build iot-sensor-logger.go
go: downloading github.com/influxdata/influxdb-client-go/v2 v2.5.1
go: downloading golang.org/x/net v0.0.0-20210119194325-5f4716e94777
go: downloading github.com/deepmap/oapi-codegen v1.8.2
go: downloading github.com/pkg/errors v0.9.1
go: downloading gopkg.in/yaml.v2 v2.3.0
go: downloading github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839

$ ./iot-sensor-logger
panic: chip ID is different than expected, want(60), got(58)

goroutine 1 [running]:
main.main()
        /home/mars/influx/iot-sensor-logger.go:58 +0x1bc

自分の環境では、実行時にエラーとなってデータを取得できない。 GOARM=7も試してみたがNG。コンパイルで生成されたコードの情報は、問題なさそうなので、参照しているライブラリーに問題があるのか???

$ file iot-sensor-logger
iot-sensor-logger: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, not stripped

ちなみに、【Golang】がサポートしている GOOS と GOARCH の一覧

$ go tool dist list
aix/ppc64
android/386
android/amd64
android/arm
android/arm64
darwin/amd64
darwin/arm64
dragonfly/amd64
freebsd/386
freebsd/amd64
freebsd/arm
freebsd/arm64
illumos/amd64
ios/amd64
ios/arm64
js/wasm
linux/386
linux/amd64
linux/arm
linux/arm64
linux/mips
linux/mips64
linux/mips64le
linux/mipsle
linux/ppc64
linux/ppc64le
linux/riscv64
linux/s390x
netbsd/386
netbsd/amd64
netbsd/arm
netbsd/arm64
openbsd/386
openbsd/amd64
openbsd/arm
openbsd/arm64
openbsd/mips64
plan9/386
plan9/amd64
plan9/arm
solaris/amd64
windows/386
windows/amd64
windows/arm
windows/arm64

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です