0
1

More than 1 year has passed since last update.

Raspberry pi で BME280 を使用する (Golang)

Last updated at Posted at 2022-10-09

はじめに

Raspberry pi にて、
温度、湿度、気圧を測定できる環境を構築することを目的とする。
BME280の基本部分のみを使用する。

追記:2022/10/10
Appソースの一部を修正

使用機材

raspi : raspberry pi 4 (4GB)
sensor : bme280 (GYBMEP)

$ cat /etc/debian_version
> 10.13

$ go version
> go version go1.11.6 linux/arm

i2c 準備

i2c 系ライブラリのインストール

sudo apt install i2c-tools

raspberry pi 側の i2c の Enabe

sudo raspi-config

3 Interface Option
P5 I2C
Yes
OK
Finish
の順

再起動(不要かも)

sudo reboot

i2c 確認

sudo i2cdetect -l
>i2c-1 i2c bcm2835 (i2c@7e804000) I2C adapter

センサの接続

raspberry pi を正面に見て左上6ピンを図のように接続する
スクリーンショット 2022-10-09 12.26.48.png

センサ取り付け後の確認

sudo i2cdetect -y 1

スクリーンショット 2022-10-09 12.07.30.png

Chip ID 読み

sudo i2cget -y 1 0x76 0xD0
> 0x60

BME280は0xD0アドレスに0x60のChipIDが記載されている
(ので上記のコマンドは成功している)

Golang app

main.go
package main

import (
	"os/exec"
	"time"
	"strconv"
	"fmt"
)

func sread(adr string) int8 {
	res, _ :=exec.Command("i2cget", "-y", "1", "0x76", adr).Output()
	val, _ := strconv.ParseInt(string(res)[:4], 0, 16)
//	fmt.Printf("Adr%s:0x%02x\n", adr, val)

	return int8(val)
}

func uread(adr string) uint8 {
	return uint8(sread(adr))
}

func write(adr, val string) {
	exec.Command("i2cset", "-y", "1", "0x76", adr, val).Run()
}

func main() {

	//Check Chip ID
	if (uread("0xD0") != 0x60) {
		fmt.Printf("Chip ID Error\n")
		return
	}

	//Reset
	write("0xE0", "0xB6")
	uread("0xF4")

	//ForceMode (once)
	write("0xF2", "0x01")
	write("0xF4", "0x25")
	uread("0xF4")
	time.Sleep(time.Millisecond)
	uread("0xF4")

	t_fine, tmp := getTemp()
	fmt.Printf("TEMP  : %7.2f [Deg]\n", float32(tmp) /100.0)

	hum := getHum(t_fine)
	fmt.Printf("HUM   : %7.2f [%%RH]\n", float32(hum) /1024.0)

	press := getPress(t_fine)
	fmt.Printf("PRESS : %7.2f [hPa]\n", float32(press) /25600.0)
}

func getPress(t_fine int) int {
	//GetData
	press_msb := uread("0xF7")
	press_lsb := uread("0xF8")
	press := int64(press_msb) << 12 | int64(press_lsb) << 4

	//digP1
	dig_p1_msb := uread("0x8F")
	dig_p1_lsb := uread("0x8E")
	dig_p1 := int64(dig_p1_msb) << 8 | int64(dig_p1_lsb)

	//digP2
	dig_p2_msb := sread("0x91")
	dig_p2_lsb := uread("0x90")
	dig_p2 := int64(dig_p2_msb) << 8 | int64(dig_p2_lsb)

	//digP3
	dig_p3_msb := sread("0x93")
	dig_p3_lsb := uread("0x92")
	dig_p3 := int64(dig_p3_msb) << 8 | int64(dig_p3_lsb)

	//digP4
	dig_p4_msb := sread("0x95")
	dig_p4_lsb := uread("0x94")
	dig_p4 := int64(dig_p4_msb) << 8 | int64(dig_p4_lsb)

	//digP5
	dig_p5_msb := sread("0x97")
	dig_p5_lsb := uread("0x96")
	dig_p5 := int64(dig_p5_msb) << 8 | int64(dig_p5_lsb)

	//digP6
	dig_p6_msb := sread("0x99")
	dig_p6_lsb := uread("0x98")
	dig_p6 := int64(dig_p6_msb) << 8 | int64(dig_p6_lsb)

	//digP7
	dig_p7_msb := sread("0x9B")
	dig_p7_lsb := uread("0x9A")
	dig_p7 := int64(dig_p7_msb) << 8 | int64(dig_p7_lsb)

	//digP8
	dig_p8_msb := sread("0x9D")
	dig_p8_lsb := uread("0x9C")
	dig_p8 := int64(dig_p8_msb) << 8 | int64(dig_p8_lsb)

	//digP9
	dig_p9_msb := sread("0x9F")
	dig_p9_lsb := uread("0x9E")
	dig_p9 := int64(dig_p9_msb) << 8 | int64(dig_p9_lsb)

	var1 := int64(t_fine) - int64(128000)
	var2 := var1 * var1 * dig_p6
	var2 = var2 + ((var1 * dig_p5) << 17)
	var2 = var2 + (dig_p4<<35)
	var1 = ((var1 * var1 * dig_p3) >>8) + ((var1 * dig_p2) <<12)
	var1 = (((int64(1)<<47) + var1)) * dig_p1 >> 33;
	if (var1 == 0) {
		return 0;
	}
	p := int64(1048576) - press
	p = (((p<<31) - var2) * 3125) / var1
	var1 = (dig_p9 * (p>>13) * (p>>13)) >> 25
	var2 = (dig_p8 * p) >> 19
	p = ((p + var1 + var2) >> 8) + (dig_p7 << 4)

	return int(p)
}

func getHum(t_fine int) int {
	//GetData
	hum_msb := uread("0xFD")
	hum_lsb := uread("0xFE")
	hum := int(hum_msb) << 8 | int(hum_lsb)

	//digH1
	dig_h1 := int(uread("0xA1"))

	//digH2
	dig_h2_msb := sread("0xE2")
	dig_h2_lsb := uread("0xE1")
	dig_h2 := int(dig_h2_msb) << 8 | int(dig_h2_lsb)

	//digH3
	dig_h3 := int(uread("0xE3"))

	//digH4
	dig_h4_msb := sread("0xE4")
	dig_h4_lsb := uread("0xE5") & 0x0F
	dig_h4 := int(dig_h4_msb) << 4 | int(dig_h4_lsb)

	//digH5
	dig_h5_msb := sread("0xE6")
	dig_h5_lsb := uread("0xE5") & 0xFF
	dig_h5 := int(dig_h5_msb) << 4 | int(dig_h5_lsb)

	//digH6
	dig_h6 := int(sread("0xE7"))

	v_x1_u32r := t_fine - 76800
	v_x1_u32r = (((((hum<<14) - (dig_h4<<20) - (dig_h5*v_x1_u32r)) + 16384) >>15) *
		(( (( (( (v_x1_u32r*dig_h6) >>10) * (((v_x1_u32r *
		dig_h3) >>11) + 32768)) >>10) + 2097152) * dig_h2 + 8191) >>14))
	v_x1_u32r = v_x1_u32r - (( (( (v_x1_u32r>>15) * (v_x1_u32r>>15)) >>7) * dig_h1) >> 4)
	if (v_x1_u32r < 0) {
		v_x1_u32r = 0
	} else if (419430400 < v_x1_u32r) {
		v_x1_u32r = 419430400
	}
	vhum := v_x1_u32r >> 12

	return vhum
}

func getTemp() (int, int) {
	//GetData
	temp_msb := uread("0xFA")
	temp_lsb := uread("0xFB")
	temp := int(temp_msb) << 12 | int(temp_lsb) << 4

	//digT1
	dig_t1_msb := sread("0x89")
	dig_t1_lsb := uread("0x88")
	dig_t1 := int(dig_t1_msb) << 8 | int(dig_t1_lsb)

	//digT2
	dig_t2_msb := uread("0x8B")
	dig_t2_lsb := uread("0x8A")
	dig_t2 := int(dig_t2_msb) << 8 | int(dig_t2_lsb)

	//digT3
	dig_t3_msb := uread("0x8D")
	dig_t3_lsb := uread("0x8C")
	dig_t3 := int(dig_t3_msb) << 8 | int(dig_t3_lsb)

	var1 := ((temp>>3 - dig_t1<<1) * dig_t2) >>11
	var2 := ((((temp>>4 - dig_t1) * (temp>>4 - dig_t1)) >> 12) * (dig_t3)) >>14

	t_fine := var1 + var2
	t := (t_fine * 5 + 128) >> 8

	return t_fine, t
}
sudo go run main.go
> TEMP  :   22.10 [Deg]
> HUM   :   59.70 [%RH]
> PRESS : 1010.45 [hPa]
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1