mirror of
https://github.com/hybridgroup/gobot.git
synced 2025-05-02 22:17:12 +08:00
i2c: add bmp280 driver, then encapsulate it with bme280 and add Humidity
Signed-off-by: deadprogram <ron@hybridgroup.com>
This commit is contained in:
parent
8940824ff0
commit
c9b992aaa5
@ -3,29 +3,11 @@ package i2c
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
|
||||
"gobot.io/x/gobot"
|
||||
)
|
||||
|
||||
const bme280RegisterHumidityMSB = 0xFD
|
||||
const bme280RegisterCalibDigH1 = 0xa1
|
||||
const bme280RegisterCalibDigH2LSB = 0xe1
|
||||
const bmp280RegisterCalib00 = 0x88
|
||||
|
||||
type bmp280CalibrationCoefficients struct {
|
||||
t1 uint16
|
||||
t2 int16
|
||||
t3 int16
|
||||
p1 uint16
|
||||
p2 int16
|
||||
p3 int16
|
||||
p4 int16
|
||||
p5 int16
|
||||
p6 int16
|
||||
p7 int16
|
||||
p8 int16
|
||||
p9 int16
|
||||
}
|
||||
|
||||
type bmeHumidityCalibrationCoefficients struct {
|
||||
h1 uint8
|
||||
@ -38,13 +20,8 @@ type bmeHumidityCalibrationCoefficients struct {
|
||||
|
||||
// BME280Driver is a driver for the BME280 temperature/humidity sensor
|
||||
type BME280Driver struct {
|
||||
name string
|
||||
connector Connector
|
||||
connection Connection
|
||||
Config
|
||||
|
||||
tpc *bmp280CalibrationCoefficients
|
||||
hc *bmeHumidityCalibrationCoefficients
|
||||
*BMP280Driver
|
||||
hc *bmeHumidityCalibrationCoefficients
|
||||
}
|
||||
|
||||
// NewBME280Driver creates a new driver with specified i2c interface.
|
||||
@ -57,11 +34,8 @@ type BME280Driver struct {
|
||||
//
|
||||
func NewBME280Driver(c Connector, options ...func(Config)) *BME280Driver {
|
||||
b := &BME280Driver{
|
||||
name: gobot.DefaultName("BME280"),
|
||||
connector: c,
|
||||
Config: NewConfig(),
|
||||
tpc: &bmp280CalibrationCoefficients{},
|
||||
hc: &bmeHumidityCalibrationCoefficients{},
|
||||
BMP280Driver: NewBMP280Driver(c),
|
||||
hc: &bmeHumidityCalibrationCoefficients{},
|
||||
}
|
||||
|
||||
for _, option := range options {
|
||||
@ -72,21 +46,6 @@ func NewBME280Driver(c Connector, options ...func(Config)) *BME280Driver {
|
||||
return b
|
||||
}
|
||||
|
||||
// Name returns the name of the device.
|
||||
func (d *BME280Driver) Name() string {
|
||||
return d.name
|
||||
}
|
||||
|
||||
// SetName sets the name of the device.
|
||||
func (d *BME280Driver) SetName(n string) {
|
||||
d.name = n
|
||||
}
|
||||
|
||||
// Connection returns the connection of the device.
|
||||
func (d *BME280Driver) Connection() gobot.Connection {
|
||||
return d.connector.(gobot.Connection)
|
||||
}
|
||||
|
||||
// Start initializes the BME280 and loads the calibration coefficients.
|
||||
func (d *BME280Driver) Start() (err error) {
|
||||
bus := d.GetBusOrDefault(d.connector.GetDefaultBus())
|
||||
@ -96,68 +55,23 @@ func (d *BME280Driver) Start() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: set sleep mode here...
|
||||
|
||||
if err := d.initialization(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := d.initHumidity(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: set usage mode here...
|
||||
|
||||
// TODO: set default sea level here
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Halt halts the device.
|
||||
func (d *BME280Driver) Halt() (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Temperature returns the current temperature, in celsius degrees.
|
||||
func (d *BME280Driver) Temperature() (temp float32, err error) {
|
||||
// TODO: implement this
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// Pressure returns the current barometric pressure, in Pa
|
||||
func (d *BME280Driver) Pressure() (press float32, err error) {
|
||||
// TODO: implement this
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// Humidity returns the current humidity in percentage of relative humidity
|
||||
func (d *BME280Driver) Humidity() (humidity float32, err error) {
|
||||
// TODO: implement this
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// initialization reads the calibration coefficients.
|
||||
func (d *BME280Driver) initialization() (err error) {
|
||||
var coefficients []byte
|
||||
if coefficients, err = d.read(bmp280RegisterCalib00, 26); err != nil {
|
||||
return err
|
||||
}
|
||||
buf := bytes.NewBuffer(coefficients)
|
||||
binary.Read(buf, binary.LittleEndian, &d.tpc.t1)
|
||||
binary.Read(buf, binary.LittleEndian, &d.tpc.t2)
|
||||
binary.Read(buf, binary.LittleEndian, &d.tpc.t3)
|
||||
binary.Read(buf, binary.LittleEndian, &d.tpc.p1)
|
||||
binary.Read(buf, binary.LittleEndian, &d.tpc.p2)
|
||||
binary.Read(buf, binary.LittleEndian, &d.tpc.p3)
|
||||
binary.Read(buf, binary.LittleEndian, &d.tpc.p4)
|
||||
binary.Read(buf, binary.LittleEndian, &d.tpc.p5)
|
||||
binary.Read(buf, binary.LittleEndian, &d.tpc.p6)
|
||||
binary.Read(buf, binary.LittleEndian, &d.tpc.p7)
|
||||
binary.Read(buf, binary.LittleEndian, &d.tpc.p8)
|
||||
binary.Read(buf, binary.LittleEndian, &d.tpc.p9)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// read the humidity calibration coefficients.
|
||||
func (d *BME280Driver) initHumidity() (err error) {
|
||||
var coefficients []byte
|
||||
@ -190,21 +104,6 @@ func (d *BME280Driver) initHumidity() (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: implement
|
||||
func (d *BME280Driver) rawTempPress() (temp int16, press int16, err error) {
|
||||
return 0, 0, nil
|
||||
}
|
||||
|
||||
// TODO: implement
|
||||
func (d *BME280Driver) calculateTemp(rawTemp int16) float32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// TODO: implement
|
||||
func (d *BME280Driver) calculatePress(rawPress int16) float32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (d *BME280Driver) rawHumidity() (int16, error) {
|
||||
ret, err := d.read(bme280RegisterHumidityMSB, 2)
|
||||
if err != nil {
|
||||
@ -247,15 +146,3 @@ func (d *BME280Driver) calculateHumidity(rawH int16) float32 {
|
||||
|
||||
return h * y
|
||||
}
|
||||
|
||||
func (d *BME280Driver) read(address byte, n int) ([]byte, error) {
|
||||
if _, err := d.connection.Write([]byte{address}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buf := make([]byte, n)
|
||||
bytesRead, err := d.connection.Read(buf)
|
||||
if bytesRead != n || err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf, nil
|
||||
}
|
||||
|
168
drivers/i2c/bmp280_driver.go
Normal file
168
drivers/i2c/bmp280_driver.go
Normal file
@ -0,0 +1,168 @@
|
||||
package i2c
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
|
||||
"gobot.io/x/gobot"
|
||||
)
|
||||
|
||||
const bmp280RegisterCalib00 = 0x88
|
||||
|
||||
type bmp280CalibrationCoefficients struct {
|
||||
t1 uint16
|
||||
t2 int16
|
||||
t3 int16
|
||||
p1 uint16
|
||||
p2 int16
|
||||
p3 int16
|
||||
p4 int16
|
||||
p5 int16
|
||||
p6 int16
|
||||
p7 int16
|
||||
p8 int16
|
||||
p9 int16
|
||||
}
|
||||
|
||||
// BMP280Driver is a driver for the BMP280 temperature/pressure sensor
|
||||
type BMP280Driver struct {
|
||||
name string
|
||||
connector Connector
|
||||
connection Connection
|
||||
Config
|
||||
|
||||
tpc *bmp280CalibrationCoefficients
|
||||
}
|
||||
|
||||
// NewBMP280Driver creates a new driver with specified i2c interface.
|
||||
// Params:
|
||||
// conn Connector - the Adaptor to use with this Driver
|
||||
//
|
||||
// Optional params:
|
||||
// i2c.WithBus(int): bus to use with this driver
|
||||
// i2c.WithAddress(int): address to use with this driver
|
||||
//
|
||||
func NewBMP280Driver(c Connector, options ...func(Config)) *BMP280Driver {
|
||||
b := &BMP280Driver{
|
||||
name: gobot.DefaultName("BMP280"),
|
||||
connector: c,
|
||||
Config: NewConfig(),
|
||||
tpc: &bmp280CalibrationCoefficients{},
|
||||
}
|
||||
|
||||
for _, option := range options {
|
||||
option(b)
|
||||
}
|
||||
|
||||
// TODO: expose commands to API
|
||||
return b
|
||||
}
|
||||
|
||||
// Name returns the name of the device.
|
||||
func (d *BMP280Driver) Name() string {
|
||||
return d.name
|
||||
}
|
||||
|
||||
// SetName sets the name of the device.
|
||||
func (d *BMP280Driver) SetName(n string) {
|
||||
d.name = n
|
||||
}
|
||||
|
||||
// Connection returns the connection of the device.
|
||||
func (d *BMP280Driver) Connection() gobot.Connection {
|
||||
return d.connector.(gobot.Connection)
|
||||
}
|
||||
|
||||
// Start initializes the BMP280 and loads the calibration coefficients.
|
||||
func (d *BMP280Driver) Start() (err error) {
|
||||
bus := d.GetBusOrDefault(d.connector.GetDefaultBus())
|
||||
address := d.GetAddressOrDefault(bmp180Address)
|
||||
|
||||
if d.connection, err = d.connector.GetConnection(address, bus); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: set sleep mode here...
|
||||
|
||||
if err := d.initialization(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: set usage mode here...
|
||||
|
||||
// TODO: set default sea level here
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Halt halts the device.
|
||||
func (d *BMP280Driver) Halt() (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Temperature returns the current temperature, in celsius degrees.
|
||||
func (d *BMP280Driver) Temperature() (temp float32, err error) {
|
||||
// TODO: implement this
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// Pressure returns the current barometric pressure, in Pa
|
||||
func (d *BMP280Driver) Pressure() (press float32, err error) {
|
||||
// TODO: implement this
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// initialization reads the calibration coefficients.
|
||||
func (d *BMP280Driver) initialization() (err error) {
|
||||
// TODO: set sleep mode here...
|
||||
|
||||
var coefficients []byte
|
||||
if coefficients, err = d.read(bmp280RegisterCalib00, 26); err != nil {
|
||||
return err
|
||||
}
|
||||
buf := bytes.NewBuffer(coefficients)
|
||||
binary.Read(buf, binary.LittleEndian, &d.tpc.t1)
|
||||
binary.Read(buf, binary.LittleEndian, &d.tpc.t2)
|
||||
binary.Read(buf, binary.LittleEndian, &d.tpc.t3)
|
||||
binary.Read(buf, binary.LittleEndian, &d.tpc.p1)
|
||||
binary.Read(buf, binary.LittleEndian, &d.tpc.p2)
|
||||
binary.Read(buf, binary.LittleEndian, &d.tpc.p3)
|
||||
binary.Read(buf, binary.LittleEndian, &d.tpc.p4)
|
||||
binary.Read(buf, binary.LittleEndian, &d.tpc.p5)
|
||||
binary.Read(buf, binary.LittleEndian, &d.tpc.p6)
|
||||
binary.Read(buf, binary.LittleEndian, &d.tpc.p7)
|
||||
binary.Read(buf, binary.LittleEndian, &d.tpc.p8)
|
||||
binary.Read(buf, binary.LittleEndian, &d.tpc.p9)
|
||||
|
||||
// TODO: set usage mode here...
|
||||
// TODO: set default sea level here
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: implement
|
||||
func (d *BMP280Driver) rawTempPress() (temp int16, press int16, err error) {
|
||||
return 0, 0, nil
|
||||
}
|
||||
|
||||
// TODO: implement
|
||||
func (d *BMP280Driver) calculateTemp(rawTemp int16) float32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// TODO: implement
|
||||
func (d *BMP280Driver) calculatePress(rawPress int16) float32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (d *BMP280Driver) read(address byte, n int) ([]byte, error) {
|
||||
if _, err := d.connection.Write([]byte{address}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buf := make([]byte, n)
|
||||
bytesRead, err := d.connection.Read(buf)
|
||||
if bytesRead != n || err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf, nil
|
||||
}
|
64
drivers/i2c/bmp280_driver_test.go
Normal file
64
drivers/i2c/bmp280_driver_test.go
Normal file
@ -0,0 +1,64 @@
|
||||
package i2c
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gobot.io/x/gobot"
|
||||
"gobot.io/x/gobot/gobottest"
|
||||
)
|
||||
|
||||
var _ gobot.Driver = (*BMP280Driver)(nil)
|
||||
|
||||
// --------- HELPERS
|
||||
func initTestBMP280Driver() (driver *BMP280Driver) {
|
||||
driver, _ = initTestBMP280DriverWithStubbedAdaptor()
|
||||
return
|
||||
}
|
||||
|
||||
func initTestBMP280DriverWithStubbedAdaptor() (*BMP280Driver, *i2cTestAdaptor) {
|
||||
adaptor := newI2cTestAdaptor()
|
||||
return NewBMP280Driver(adaptor), adaptor
|
||||
}
|
||||
|
||||
// --------- TESTS
|
||||
|
||||
func TestNewBMP280Driver(t *testing.T) {
|
||||
// Does it return a pointer to an instance of BME280Driver?
|
||||
var bmp280 interface{} = NewBMP280Driver(newI2cTestAdaptor())
|
||||
_, ok := bmp280.(*BMP280Driver)
|
||||
if !ok {
|
||||
t.Errorf("NewBMP280Driver() should have returned a *BMP280Driver")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBMP280Driver(t *testing.T) {
|
||||
bmp280 := initTestBMP280Driver()
|
||||
gobottest.Refute(t, bmp280.Connection(), nil)
|
||||
}
|
||||
|
||||
func TestBMP280DriverStart(t *testing.T) {
|
||||
bmp280, _ := initTestBMP280DriverWithStubbedAdaptor()
|
||||
gobottest.Assert(t, bmp280.Start(), nil)
|
||||
}
|
||||
|
||||
func TestBMP280DriverHalt(t *testing.T) {
|
||||
bmp280 := initTestBMP280Driver()
|
||||
|
||||
gobottest.Assert(t, bmp280.Halt(), nil)
|
||||
}
|
||||
|
||||
// TODO: implement test
|
||||
func TestBMP280DriverMeasurements(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestBMP280DriverSetName(t *testing.T) {
|
||||
b := initTestBMP280Driver()
|
||||
b.SetName("TESTME")
|
||||
gobottest.Assert(t, b.Name(), "TESTME")
|
||||
}
|
||||
|
||||
func TestBMP280DriverOptions(t *testing.T) {
|
||||
b := NewBMP280Driver(newI2cTestAdaptor(), WithBus(2))
|
||||
gobottest.Assert(t, b.GetBusOrDefault(1), 2)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user