mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-13 11:23:40 +00:00
lis2mdl: add LIS2MDL magnetometer (#187)
Signed-off-by: deadprogram <ron@hybridgroup.com>
This commit is contained in:
@@ -151,5 +151,7 @@ smoke-test:
|
|||||||
@md5sum ./build/test.hex
|
@md5sum ./build/test.hex
|
||||||
tinygo build -size short -o ./build/test.hex -target=hifive1b ./examples/ssd1351/main.go
|
tinygo build -size short -o ./build/test.hex -target=hifive1b ./examples/ssd1351/main.go
|
||||||
@md5sum ./build/test.hex
|
@md5sum ./build/test.hex
|
||||||
|
tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/lis2mdl/main.go
|
||||||
|
@md5sum ./build/test.hex
|
||||||
|
|
||||||
test: clean fmt-check smoke-test
|
test: clean fmt-check smoke-test
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ func main() {
|
|||||||
|
|
||||||
## Currently supported devices
|
## Currently supported devices
|
||||||
|
|
||||||
The following 51 devices are supported.
|
The following 52 devices are supported.
|
||||||
|
|
||||||
| Device Name | Interface Type |
|
| Device Name | Interface Type |
|
||||||
|----------|-------------|
|
|----------|-------------|
|
||||||
@@ -80,6 +80,7 @@ The following 51 devices are supported.
|
|||||||
| [ILI9341 TFT color display](https://cdn-shop.adafruit.com/datasheets/ILI9341.pdf) | SPI |
|
| [ILI9341 TFT color display](https://cdn-shop.adafruit.com/datasheets/ILI9341.pdf) | SPI |
|
||||||
| [L293x motor driver](https://www.ti.com/lit/ds/symlink/l293d.pdf) | GPIO/PWM |
|
| [L293x motor driver](https://www.ti.com/lit/ds/symlink/l293d.pdf) | GPIO/PWM |
|
||||||
| [L9110x motor driver](https://www.elecrow.com/download/datasheet-l9110.pdf) | GPIO/PWM |
|
| [L9110x motor driver](https://www.elecrow.com/download/datasheet-l9110.pdf) | GPIO/PWM |
|
||||||
|
| [LIS2MDL magnetometer](https://www.st.com/resource/en/datasheet/lis2mdl.pdf) | I2C |
|
||||||
| [LIS3DH accelerometer](https://www.st.com/resource/en/datasheet/lis3dh.pdf) | I2C |
|
| [LIS3DH accelerometer](https://www.st.com/resource/en/datasheet/lis3dh.pdf) | I2C |
|
||||||
| [LSM6DS3 accelerometer](https://www.st.com/resource/en/datasheet/lsm6ds3.pdf) | I2C |
|
| [LSM6DS3 accelerometer](https://www.st.com/resource/en/datasheet/lsm6ds3.pdf) | I2C |
|
||||||
| [MAG3110 magnetometer](https://www.nxp.com/docs/en/data-sheet/MAG3110.pdf) | I2C |
|
| [MAG3110 magnetometer](https://www.nxp.com/docs/en/data-sheet/MAG3110.pdf) | I2C |
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"machine"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"tinygo.org/x/drivers/lis2mdl"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
machine.I2C0.Configure(machine.I2CConfig{})
|
||||||
|
compass := lis2mdl.New(machine.I2C0)
|
||||||
|
|
||||||
|
if !compass.Connected() {
|
||||||
|
for {
|
||||||
|
println("LIS2MDL not connected!")
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compass.Configure(lis2mdl.Configuration{}) //default settings
|
||||||
|
|
||||||
|
for {
|
||||||
|
heading := compass.ReadCompass()
|
||||||
|
println("Heading:", heading)
|
||||||
|
|
||||||
|
time.Sleep(time.Millisecond * 100)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
// Package lis2mdl implements a driver for the LIS2MDL,
|
||||||
|
// a magnetic sensor which is included on BBC micro:bit v1.5.
|
||||||
|
//
|
||||||
|
// Datasheet: https://www.st.com/resource/en/datasheet/lsm303agr.pdf
|
||||||
|
//
|
||||||
|
package lis2mdl // import "tinygo.org/x/drivers/lis2mdl"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"machine"
|
||||||
|
"math"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Device wraps an I2C connection to a LIS2MDL device.
|
||||||
|
type Device struct {
|
||||||
|
bus machine.I2C
|
||||||
|
Address uint8
|
||||||
|
PowerMode uint8
|
||||||
|
SystemMode uint8
|
||||||
|
DataRate uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configuration for LIS2MDL device.
|
||||||
|
type Configuration struct {
|
||||||
|
PowerMode uint8
|
||||||
|
SystemMode uint8
|
||||||
|
DataRate uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new LIS2MDL connection. The I2C bus must already be
|
||||||
|
// configured.
|
||||||
|
//
|
||||||
|
// This function only creates the Device object, it does not touch the device.
|
||||||
|
func New(bus machine.I2C) Device {
|
||||||
|
return Device{bus: bus, Address: MAG_ADDRESS}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connected returns whether LIS2MDL sensor has been found.
|
||||||
|
func (d *Device) Connected() bool {
|
||||||
|
data := []byte{0}
|
||||||
|
d.bus.ReadRegister(uint8(d.Address), MAG_WHO_AM_I, data)
|
||||||
|
return data[0] == 0x40
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure sets up the LIS2MDL device for communication.
|
||||||
|
func (d *Device) Configure(cfg Configuration) {
|
||||||
|
if cfg.PowerMode != 0 {
|
||||||
|
d.PowerMode = cfg.PowerMode
|
||||||
|
} else {
|
||||||
|
d.PowerMode = MAG_POWER_NORMAL
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.DataRate != 0 {
|
||||||
|
d.DataRate = cfg.DataRate
|
||||||
|
} else {
|
||||||
|
d.DataRate = MAG_DATARATE_100HZ
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.SystemMode != 0 {
|
||||||
|
d.SystemMode = cfg.SystemMode
|
||||||
|
} else {
|
||||||
|
d.SystemMode = MAG_SYSTEM_CONTINUOUS
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := []byte{0}
|
||||||
|
|
||||||
|
// reset
|
||||||
|
cmd[0] = byte(1 << 5)
|
||||||
|
d.bus.WriteRegister(uint8(d.Address), MAG_MR_CFG_REG_A, cmd)
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
|
||||||
|
// reboot
|
||||||
|
cmd[0] = byte(1 << 6)
|
||||||
|
d.bus.WriteRegister(uint8(d.Address), MAG_MR_CFG_REG_A, cmd)
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
|
||||||
|
// bdu
|
||||||
|
cmd[0] = byte(1 << 4)
|
||||||
|
d.bus.WriteRegister(uint8(d.Address), MAG_MR_CFG_REG_C, cmd)
|
||||||
|
|
||||||
|
// Temperature compensation is on for magnetic sensor (0x80)
|
||||||
|
cmd[0] = byte(0x80)
|
||||||
|
d.bus.WriteRegister(uint8(d.Address), MAG_MR_CFG_REG_A, cmd)
|
||||||
|
|
||||||
|
// speed
|
||||||
|
cmd[0] = byte(0x80 | d.DataRate)
|
||||||
|
d.bus.WriteRegister(uint8(d.Address), MAG_MR_CFG_REG_A, cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadMagneticField reads the current magnetic field from the device and returns
|
||||||
|
// it in mG (milligauss). 1 mG = 0.1 µT (microtesla).
|
||||||
|
func (d *Device) ReadMagneticField() (x int32, y int32, z int32) {
|
||||||
|
data := make([]byte, 6)
|
||||||
|
d.bus.ReadRegister(uint8(d.Address), MAG_OUT_X_L_M, data)
|
||||||
|
|
||||||
|
x = int32(int16((uint16(data[0]) << 8) | uint16(data[1])))
|
||||||
|
y = int32(int16((uint16(data[2]) << 8) | uint16(data[3])))
|
||||||
|
z = int32(int16((uint16(data[4]) << 8) | uint16(data[5])))
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadCompass reads the current compass heading from the device and returns
|
||||||
|
// it in degrees. When the z axis is pointing straight to Earth and
|
||||||
|
// the y axis is pointing to North, the heading would be zero.
|
||||||
|
//
|
||||||
|
// However, the heading may be off due to electronic compasses would be effected
|
||||||
|
// by strong magnetic fields and require constant calibration.
|
||||||
|
func (d *Device) ReadCompass() (h int32) {
|
||||||
|
x, y, _ := d.ReadMagneticField()
|
||||||
|
xf, yf := float64(x)*0.15, float64(y)*0.15
|
||||||
|
|
||||||
|
rh := (math.Atan2(yf, xf) * 180) / math.Pi
|
||||||
|
if rh < 0 {
|
||||||
|
rh = 360 + rh
|
||||||
|
}
|
||||||
|
|
||||||
|
return int32(rh)
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package lis2mdl
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Constants/addresses used for I2C.
|
||||||
|
MAG_ADDRESS = 0x1E
|
||||||
|
|
||||||
|
// magnetic sensor registers.
|
||||||
|
MAG_WHO_AM_I = 0x4F
|
||||||
|
MAG_MR_CFG_REG_A = 0x60
|
||||||
|
MAG_MR_CFG_REG_B = 0x61
|
||||||
|
MAG_MR_CFG_REG_C = 0x62
|
||||||
|
MAG_OUT_X_L_M = 0x68
|
||||||
|
MAG_OUT_X_H_M = 0x69
|
||||||
|
MAG_OUT_Y_L_M = 0x6A
|
||||||
|
MAG_OUT_Y_H_M = 0x6B
|
||||||
|
MAG_OUT_Z_L_M = 0x6C
|
||||||
|
MAG_OUT_Z_H_M = 0x6D
|
||||||
|
|
||||||
|
// magnetic sensor power mode.
|
||||||
|
MAG_POWER_NORMAL = 0x00 // default
|
||||||
|
MAG_POWER_LOW = 0x01
|
||||||
|
|
||||||
|
// magnetic sensor operate mode.
|
||||||
|
MAG_SYSTEM_CONTINUOUS = 0x00 // default
|
||||||
|
MAG_SYSTEM_SINGLE = 0x01
|
||||||
|
|
||||||
|
// magnetic sensor data rate
|
||||||
|
MAG_DATARATE_10HZ = 0x00 // default
|
||||||
|
MAG_DATARATE_20HZ = 0x01
|
||||||
|
MAG_DATARATE_50HZ = 0x02
|
||||||
|
MAG_DATARATE_100HZ = 0x03
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user