mirror of
https://github.com/hybridgroup/gobot.git
synced 2025-04-24 13:48:49 +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
|
||||
- Grove RGB LCD
|
||||
- HMC6352 Compass
|
||||
- HMC8553L 3-Axis Digital Compass
|
||||
- INA3221 Voltage Monitor
|
||||
- JHD1313M1 LCD Display w/RGB Backlight
|
||||
- L3GD20H 3-Axis Gyroscope
|
||||
|
@ -36,7 +36,6 @@ https://github.com/hybridgroup/gobot/issues
|
||||
|
||||
- ensure that SMBUS operations are working as expected.
|
||||
- add support for the following i2c devices:
|
||||
- HMC5883L
|
||||
- LSM303DLHC
|
||||
- MAG3110
|
||||
- MMA8452
|
||||
|
@ -27,6 +27,7 @@ Gobot has a extensible system for connecting to hardware devices. The following
|
||||
- GrovePi Expansion Board
|
||||
- Grove RGB LCD
|
||||
- HMC6352 Compass
|
||||
- HMC8553L 3-Axis Digital Compass
|
||||
- INA3221 Voltage Monitor
|
||||
- JHD1313M1 LCD Display w/RGB Backlight
|
||||
- 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