mirror of
https://github.com/hybridgroup/gobot.git
synced 2025-04-29 13:49:14 +08:00
Adding support for hmc8553l compass
This commit is contained in:
parent
97d23a5aec
commit
979379d765
@ -275,6 +275,7 @@ drivers provided using the `gobot/drivers/i2c` package:
|
|||||||
- GrovePi Expansion Board
|
- GrovePi Expansion Board
|
||||||
- Grove RGB LCD
|
- Grove RGB LCD
|
||||||
- HMC6352 Compass
|
- HMC6352 Compass
|
||||||
|
- HMC8553L 3-Axis Digital Compass
|
||||||
- INA3221 Voltage Monitor
|
- INA3221 Voltage Monitor
|
||||||
- JHD1313M1 LCD Display w/RGB Backlight
|
- JHD1313M1 LCD Display w/RGB Backlight
|
||||||
- L3GD20H 3-Axis Gyroscope
|
- L3GD20H 3-Axis Gyroscope
|
||||||
|
@ -36,7 +36,6 @@ https://github.com/hybridgroup/gobot/issues
|
|||||||
|
|
||||||
- ensure that SMBUS operations are working as expected.
|
- ensure that SMBUS operations are working as expected.
|
||||||
- add support for the following i2c devices:
|
- add support for the following i2c devices:
|
||||||
- HMC5883L
|
|
||||||
- LSM303DLHC
|
- LSM303DLHC
|
||||||
- MAG3110
|
- MAG3110
|
||||||
- MMA8452
|
- MMA8452
|
||||||
|
@ -27,6 +27,7 @@ Gobot has a extensible system for connecting to hardware devices. The following
|
|||||||
- GrovePi Expansion Board
|
- GrovePi Expansion Board
|
||||||
- Grove RGB LCD
|
- Grove RGB LCD
|
||||||
- HMC6352 Compass
|
- HMC6352 Compass
|
||||||
|
- HMC8553L 3-Axis Digital Compass
|
||||||
- INA3221 Voltage Monitor
|
- INA3221 Voltage Monitor
|
||||||
- JHD1313M1 LCD Display w/RGB Backlight
|
- JHD1313M1 LCD Display w/RGB Backlight
|
||||||
- L3GD20H 3-Axis Gyroscope
|
- L3GD20H 3-Axis Gyroscope
|
||||||
|
120
drivers/i2c/hmc8553l_driver.go
Normal file
120
drivers/i2c/hmc8553l_driver.go
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
package i2c
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
|
||||||
|
"gobot.io/x/gobot"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultAddress = 0x1e // default I2C Address
|
||||||
|
registerA = 0x0 // Address of Configuration register A
|
||||||
|
registerB = 0x01 // Address of Configuration register B
|
||||||
|
registerMode = 0x02 // Address of node register
|
||||||
|
xAxisH = 0x03 // Address of X-axis MSB data register
|
||||||
|
zAxisH = 0x05 // Address of Z-axis MSB data register
|
||||||
|
yAxisH = 0x07 // Address of Y-axis MSB data register
|
||||||
|
)
|
||||||
|
|
||||||
|
// HMC8553LDriver is a Driver for a HMC6352 digital compass
|
||||||
|
type HMC8553LDriver struct {
|
||||||
|
name string
|
||||||
|
connector Connector
|
||||||
|
connection Connection
|
||||||
|
Config
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewHMC8553LDriver 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 NewHMC8553LDriver(a Connector, options ...func(Config)) *HMC8553LDriver {
|
||||||
|
hmc := &HMC8553LDriver{
|
||||||
|
name: gobot.DefaultName("HMC8553L"),
|
||||||
|
connector: a,
|
||||||
|
Config: NewConfig(),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, option := range options {
|
||||||
|
option(hmc)
|
||||||
|
}
|
||||||
|
|
||||||
|
return hmc
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns the name for this Driver
|
||||||
|
func (h *HMC8553LDriver) Name() string { return h.name }
|
||||||
|
|
||||||
|
// SetName sets the name for this Driver
|
||||||
|
func (h *HMC8553LDriver) SetName(n string) { h.name = n }
|
||||||
|
|
||||||
|
// Connection returns the connection for this Driver
|
||||||
|
func (h *HMC8553LDriver) Connection() gobot.Connection { return h.connector.(gobot.Connection) }
|
||||||
|
|
||||||
|
// Start initializes the HMC8553L
|
||||||
|
func (h *HMC8553LDriver) Start() (err error) {
|
||||||
|
bus := h.GetBusOrDefault(h.connector.GetDefaultBus())
|
||||||
|
address := h.GetAddressOrDefault(defaultAddress)
|
||||||
|
h.connection, err = h.connector.GetConnection(address, bus)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := h.connection.WriteByteData(registerA, 0x70); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := h.connection.WriteByteData(registerB, 0xa0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := h.connection.WriteByteData(registerMode, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Halt returns true if devices is halted successfully
|
||||||
|
func (h *HMC8553LDriver) Halt() (err error) { return }
|
||||||
|
|
||||||
|
// ReadRawData reads the raw values from the X, Y, and Z registers
|
||||||
|
func (h *HMC8553LDriver) ReadRawData() (x int16, y int16, z int16, err error) {
|
||||||
|
unsignedX, err := h.connection.ReadWordData(xAxisH)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
unsignedY, err := h.connection.ReadWordData(yAxisH)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
unsignedZ, err := h.connection.ReadWordData(zAxisH)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return unsignedToSigned(unsignedX), unsignedToSigned(unsignedY), unsignedToSigned(unsignedZ), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Heading returns the current heading in radians
|
||||||
|
func (h *HMC8553LDriver) Heading() (heading float64, err error) {
|
||||||
|
var x, y int16
|
||||||
|
x, y, _, err = h.ReadRawData()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
heading = math.Atan2(float64(y), float64(x))
|
||||||
|
if heading > 2*math.Pi {
|
||||||
|
heading -= 2 * math.Pi
|
||||||
|
}
|
||||||
|
if heading < 0 {
|
||||||
|
heading += 2 * math.Pi
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func unsignedToSigned(unsignedValue uint16) int16 {
|
||||||
|
if unsignedValue > 32768 {
|
||||||
|
return int16(unsignedValue) - ^int16(0) - ^int16(0) - 2
|
||||||
|
}
|
||||||
|
return int16(unsignedValue)
|
||||||
|
}
|
72
drivers/i2c/hmc8553l_driver_test.go
Normal file
72
drivers/i2c/hmc8553l_driver_test.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package i2c
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"gobot.io/x/gobot"
|
||||||
|
"gobot.io/x/gobot/gobottest"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ gobot.Driver = (*HMC8553LDriver)(nil)
|
||||||
|
|
||||||
|
// --------- HELPERS
|
||||||
|
func initTestHMC8553LDriver() (driver *HMC8553LDriver) {
|
||||||
|
driver, _ = initTestHMC8553LDriverWithStubbedAdaptor()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func initTestHMC8553LDriverWithStubbedAdaptor() (*HMC8553LDriver, *i2cTestAdaptor) {
|
||||||
|
adaptor := newI2cTestAdaptor()
|
||||||
|
return NewHMC8553LDriver(adaptor), adaptor
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------- TESTS
|
||||||
|
|
||||||
|
func TestNewHMC8553LDriver(t *testing.T) {
|
||||||
|
// Does it return a pointer to an instance of HMC8553LDriver?
|
||||||
|
var bm interface{} = NewHMC8553LDriver(newI2cTestAdaptor())
|
||||||
|
_, ok := bm.(*HMC8553LDriver)
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("NewHMC8553LDriver() should have returned a *HMC8553LDriver")
|
||||||
|
}
|
||||||
|
|
||||||
|
b := NewHMC8553LDriver(newI2cTestAdaptor())
|
||||||
|
gobottest.Refute(t, b.Connection(), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
func TestHMC8553LDriverStart(t *testing.T) {
|
||||||
|
hmc, adaptor := initTestHMC8553LDriverWithStubbedAdaptor()
|
||||||
|
|
||||||
|
gobottest.Assert(t, hmc.Start(), nil)
|
||||||
|
|
||||||
|
adaptor.i2cWriteImpl = func([]byte) (int, error) {
|
||||||
|
return 0, errors.New("write error")
|
||||||
|
}
|
||||||
|
err := hmc.Start()
|
||||||
|
gobottest.Assert(t, err, errors.New("write error"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test8553LStartConnectError(t *testing.T) {
|
||||||
|
d, adaptor := initTestHMC8553LDriverWithStubbedAdaptor()
|
||||||
|
adaptor.Testi2cConnectErr(true)
|
||||||
|
gobottest.Assert(t, d.Start(), errors.New("Invalid i2c connection"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHMC8553LDriverHalt(t *testing.T) {
|
||||||
|
hmc := initTestHMC8553LDriver()
|
||||||
|
|
||||||
|
gobottest.Assert(t, hmc.Halt(), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHMC8553LDriverSetName(t *testing.T) {
|
||||||
|
d := initTestHMC8553LDriver()
|
||||||
|
d.SetName("TESTME")
|
||||||
|
gobottest.Assert(t, d.Name(), "TESTME")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHMC8553LDriverOptions(t *testing.T) {
|
||||||
|
d := NewHMC8553LDriver(newI2cTestAdaptor(), WithBus(2))
|
||||||
|
gobottest.Assert(t, d.GetBusOrDefault(1), 2)
|
||||||
|
}
|
46
examples/raspi_hmc8553l.go
Normal file
46
examples/raspi_hmc8553l.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// +build example
|
||||||
|
//
|
||||||
|
// Do not build by default.
|
||||||
|
|
||||||
|
/*
|
||||||
|
How to run
|
||||||
|
|
||||||
|
go run examples/firmata_hmc8553l.go
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gobot.io/x/gobot"
|
||||||
|
"gobot.io/x/gobot/drivers/i2c"
|
||||||
|
"gobot.io/x/gobot/platforms/raspi"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
raspi := raspi.NewAdaptor()
|
||||||
|
hmc8553l := i2c.NewHMC8553LDriver(raspi)
|
||||||
|
|
||||||
|
work := func() {
|
||||||
|
gobot.Every(200*time.Millisecond, func() {
|
||||||
|
|
||||||
|
// get heading in radians, to convert to degrees multiply by 180/math.Pi
|
||||||
|
heading, _ := hmc8553l.Heading()
|
||||||
|
fmt.Println("Heading", heading)
|
||||||
|
|
||||||
|
// read the raw data from the device, this is useful for calibration
|
||||||
|
x, y, z, _ := hmc8553l.ReadRawData()
|
||||||
|
fmt.Println(x, y, z)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
robot := gobot.NewRobot("hmc8553LBot",
|
||||||
|
[]gobot.Connection{raspi},
|
||||||
|
[]gobot.Device{hmc8553l},
|
||||||
|
work,
|
||||||
|
)
|
||||||
|
|
||||||
|
robot.Start()
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user