i2c: functional bmp180 temperature/pressure and bme280 humidity
Signed-off-by: deadprogram <ron@hybridgroup.com>
This commit is contained in:
parent
c573ba99ac
commit
bdb24109af
|
@ -3,8 +3,10 @@ package i2c
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
)
|
||||
|
||||
const bme280RegisterControlHumidity = 0xF2
|
||||
const bme280RegisterHumidityMSB = 0xFD
|
||||
const bme280RegisterCalibDigH1 = 0xa1
|
||||
const bme280RegisterCalibDigH2LSB = 0xe1
|
||||
|
@ -68,7 +70,7 @@ func (d *BME280Driver) Start() (err error) {
|
|||
|
||||
// Humidity returns the current humidity in percentage of relative humidity
|
||||
func (d *BME280Driver) Humidity() (humidity float32, err error) {
|
||||
var rawH int32
|
||||
var rawH uint32
|
||||
if rawH, err = d.rawHumidity(); err != nil {
|
||||
return 0.0, err
|
||||
}
|
||||
|
@ -105,46 +107,52 @@ func (d *BME280Driver) initHumidity() (err error) {
|
|||
d.hc.h4 = 0 + (int16(addrE4) << 4) | (int16(addrE5 & 0x0F))
|
||||
d.hc.h5 = 0 + (int16(addrE6) << 4) | (int16(addrE5) >> 4)
|
||||
|
||||
d.connection.WriteByteData(bme280RegisterControlHumidity, 0x3F)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *BME280Driver) rawHumidity() (int32, error) {
|
||||
func (d *BME280Driver) rawHumidity() (uint32, error) {
|
||||
ret, err := d.read(bme280RegisterHumidityMSB, 2)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if ret[0] == 0x80 && ret[1] == 0x00 {
|
||||
return 0, errors.New("Humidity disabled")
|
||||
}
|
||||
buf := bytes.NewBuffer(ret)
|
||||
var rawH int32
|
||||
var rawH uint16
|
||||
binary.Read(buf, binary.BigEndian, &rawH)
|
||||
return rawH, nil
|
||||
return uint32(rawH), nil
|
||||
}
|
||||
|
||||
// Adapted from https://github.com/BoschSensortec/BME280_driver/blob/master/bme280.c
|
||||
// function bme280_compensate_humidity_double(s32 v_uncom_humidity_s32)
|
||||
func (d *BME280Driver) calculateHumidity(rawH int32) float32 {
|
||||
func (d *BME280Driver) calculateHumidity(rawH uint32) float32 {
|
||||
var rawT int32
|
||||
var err error
|
||||
var h float32
|
||||
|
||||
rawT, _, err = d.rawTempPress()
|
||||
rawT, err = d.rawTemp()
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
_, tFine := d.calculateTemp(rawT)
|
||||
h = float32(tFine - 76800)
|
||||
h = float32(tFine) - 76800
|
||||
|
||||
if h == 0 {
|
||||
return 0 // TODO err is 'invalid data' from Bosch - include errors or not?
|
||||
}
|
||||
|
||||
h = (float32(rawH) - (float32(d.hc.h4) * 64.0) + // H4 double * 64.0 double
|
||||
(float32(d.hc.h5) / 16384.0 * h)) // H5 double / 16384.0 * var_h
|
||||
x := float32(rawH) - (float32(d.hc.h4)*64.0 +
|
||||
(float32(d.hc.h5) / 16384.0 * h))
|
||||
|
||||
y :=
|
||||
(float32(d.hc.h2) / 65536.0) * // H2 double / 65536.0
|
||||
(1.0 + float32(d.hc.h6)/67108864.0*h) * // 1.0 + (H6 double / 67108664.0 * var_h
|
||||
(1.0 + float32(d.hc.h3)/67108864.0*h) // 1.0 + H3 double / 67108864.0 * var_h
|
||||
y := float32(d.hc.h2) / 65536.0 *
|
||||
(1.0 + float32(d.hc.h6)/67108864.0*h*
|
||||
(1.0+float32(d.hc.h3)/67108864.0*h))
|
||||
|
||||
return h * y
|
||||
h = x * y
|
||||
h = h * (1 - float32(d.hc.h1)*h/524288)
|
||||
return h
|
||||
}
|
||||
|
|
|
@ -7,8 +7,14 @@ import (
|
|||
"gobot.io/x/gobot"
|
||||
)
|
||||
|
||||
const (
|
||||
bmp280RegisterControl = 0xf4
|
||||
bmp280RegisterConfig = 0xf5
|
||||
bmp280RegisterPressureData = 0xf7
|
||||
bmp280RegisterTempData = 0xfa
|
||||
)
|
||||
|
||||
const bmp280RegisterCalib00 = 0x88
|
||||
const bme280RegisterPressureMSB = 0xf7
|
||||
|
||||
type bmp280CalibrationCoefficients struct {
|
||||
t1 uint16
|
||||
|
@ -98,7 +104,7 @@ func (d *BMP280Driver) Halt() (err error) {
|
|||
// Temperature returns the current temperature, in celsius degrees.
|
||||
func (d *BMP280Driver) Temperature() (temp float32, err error) {
|
||||
var rawT int32
|
||||
if rawT, _, err = d.rawTempPress(); err != nil {
|
||||
if rawT, err = d.rawTemp(); err != nil {
|
||||
return 0.0, err
|
||||
}
|
||||
temp, _ = d.calculateTemp(rawT)
|
||||
|
@ -108,7 +114,11 @@ func (d *BMP280Driver) Temperature() (temp float32, err error) {
|
|||
// Pressure returns the current barometric pressure, in Pa
|
||||
func (d *BMP280Driver) Pressure() (press float32, err error) {
|
||||
var rawT, rawP int32
|
||||
if rawT, rawP, err = d.rawTempPress(); err != nil {
|
||||
if rawT, err = d.rawTemp(); err != nil {
|
||||
return 0.0, err
|
||||
}
|
||||
|
||||
if rawP, err = d.rawPressure(); err != nil {
|
||||
return 0.0, err
|
||||
}
|
||||
_, tFine := d.calculateTemp(rawT)
|
||||
|
@ -120,7 +130,7 @@ func (d *BMP280Driver) initialization() (err error) {
|
|||
// TODO: set sleep mode here...
|
||||
|
||||
var coefficients []byte
|
||||
if coefficients, err = d.read(bmp280RegisterCalib00, 26); err != nil {
|
||||
if coefficients, err = d.read(bmp280RegisterCalib00, 24); err != nil {
|
||||
return err
|
||||
}
|
||||
buf := bytes.NewBuffer(coefficients)
|
||||
|
@ -137,28 +147,43 @@ func (d *BMP280Driver) initialization() (err error) {
|
|||
binary.Read(buf, binary.LittleEndian, &d.tpc.p8)
|
||||
binary.Read(buf, binary.LittleEndian, &d.tpc.p9)
|
||||
|
||||
d.connection.WriteByteData(bmp280RegisterControl, 0x3F)
|
||||
|
||||
// TODO: set usage mode here...
|
||||
// TODO: set default sea level here
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *BMP280Driver) rawTempPress() (temp int32, press int32, err error) {
|
||||
func (d *BMP280Driver) rawTemp() (temp int32, err error) {
|
||||
var data []byte
|
||||
var tp0, tp1, tp2, tp3, tp4, tp5 byte
|
||||
var tp0, tp1, tp2 byte
|
||||
|
||||
if data, err = d.read(bme280RegisterPressureMSB, 6); err != nil {
|
||||
return 0, 0, err
|
||||
if data, err = d.read(bmp280RegisterTempData, 3); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
buf := bytes.NewBuffer(data)
|
||||
binary.Read(buf, binary.LittleEndian, &tp0)
|
||||
binary.Read(buf, binary.LittleEndian, &tp1)
|
||||
binary.Read(buf, binary.LittleEndian, &tp2)
|
||||
|
||||
temp = ((int32(tp2) >> 4) | (int32(tp1) << 4) | (int32(tp0) << 12))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (d *BMP280Driver) rawPressure() (press int32, err error) {
|
||||
var data []byte
|
||||
var tp0, tp1, tp2 byte
|
||||
|
||||
if data, err = d.read(bmp280RegisterPressureData, 3); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
buf := bytes.NewBuffer(data)
|
||||
binary.Read(buf, binary.LittleEndian, &tp0)
|
||||
binary.Read(buf, binary.LittleEndian, &tp1)
|
||||
binary.Read(buf, binary.LittleEndian, &tp2)
|
||||
binary.Read(buf, binary.LittleEndian, &tp3)
|
||||
binary.Read(buf, binary.LittleEndian, &tp4)
|
||||
binary.Read(buf, binary.LittleEndian, &tp5)
|
||||
|
||||
temp = ((int32(tp5) >> 4) | (int32(tp4) << 4) | (int32(tp3) << 12))
|
||||
press = ((int32(tp2) >> 4) | (int32(tp1) << 4) | (int32(tp0) << 12))
|
||||
|
||||
return
|
||||
|
@ -174,22 +199,26 @@ func (d *BMP280Driver) calculateTemp(rawTemp int32) (float32, int32) {
|
|||
}
|
||||
|
||||
func (d *BMP280Driver) calculatePress(rawPress int32, tFine int32) float32 {
|
||||
pcvar1 := (float32(tFine) / 2.0) - 64000.0
|
||||
pcvar2 := pcvar1 * pcvar1 * (float32(d.tpc.p6)) / 32768.0
|
||||
pcvar2 = pcvar2 + pcvar1*(float32(d.tpc.p5))*2.0
|
||||
pcvar2 = (pcvar2 / 4.0) + (float32(d.tpc.p4) * 65536.0)
|
||||
pcvar1 = (float32(d.tpc.p3)*pcvar1*pcvar1/524288.0 + float32(d.tpc.p2)*pcvar1) / 524288.0
|
||||
pcvar1 = (1.0 + pcvar1/32768.0) * (float32(d.tpc.p1))
|
||||
if pcvar1 == 0.0 { // avoid divide by zero
|
||||
return 0.0
|
||||
}
|
||||
pressureComp := 1048576.0 - float32(rawPress)
|
||||
pressureComp = (pressureComp - (pcvar2 / 4096.0)) * (6250.0 / pcvar1)
|
||||
pcvar1 = float32(d.tpc.p9) * pressureComp * pressureComp / 2147483648.0
|
||||
pcvar2 = pressureComp * float32(d.tpc.p8) / 32768.0
|
||||
pressureComp = pressureComp + (pcvar1+pcvar2+float32(d.tpc.p7))/16.0
|
||||
var var1, var2, p int64
|
||||
|
||||
return pressureComp
|
||||
var1 = int64(tFine) - 128000
|
||||
var2 = var1 * var1 * int64(d.tpc.p6)
|
||||
var2 = var2 + ((var1 * int64(d.tpc.p5)) << 17)
|
||||
var2 = var2 + (int64(d.tpc.p4) << 35)
|
||||
var1 = (var1 * var1 * int64(d.tpc.p3) >> 8) +
|
||||
((var1 * int64(d.tpc.p2)) << 12)
|
||||
var1 = ((int64(1) << 47) + var1) * (int64(d.tpc.p1)) >> 33
|
||||
|
||||
if var1 == 0 {
|
||||
return 0 // avoid exception caused by division by zero
|
||||
}
|
||||
p = 1048576 - int64(rawPress)
|
||||
p = (((p << 31) - var2) * 3125) / var1
|
||||
var1 = (int64(d.tpc.p9) * (p >> 13) * (p >> 13)) >> 25
|
||||
var2 = (int64(d.tpc.p8) * p) >> 19
|
||||
|
||||
p = ((p + var1 + var2) >> 8) + (int64(d.tpc.p7) << 4)
|
||||
return float32(p) / 256
|
||||
}
|
||||
|
||||
func (d *BMP280Driver) read(address byte, n int) ([]byte, error) {
|
||||
|
|
Loading…
Reference in New Issue