diff --git a/drivers/i2c/bme280_driver.go b/drivers/i2c/bme280_driver.go index 40200188..8ccc303a 100644 --- a/drivers/i2c/bme280_driver.go +++ b/drivers/i2c/bme280_driver.go @@ -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 -} diff --git a/drivers/i2c/bmp280_driver.go b/drivers/i2c/bmp280_driver.go new file mode 100644 index 00000000..779b3ea1 --- /dev/null +++ b/drivers/i2c/bmp280_driver.go @@ -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 +} diff --git a/drivers/i2c/bmp280_driver_test.go b/drivers/i2c/bmp280_driver_test.go new file mode 100644 index 00000000..eb735a6c --- /dev/null +++ b/drivers/i2c/bmp280_driver_test.go @@ -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) +}