mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-07-26 10:38:41 +00:00
lis3dh: implement accelerometer functionality
Signed-off-by: Ron Evans <ron@hybridgroup.com>
This commit is contained in:
@@ -21,6 +21,7 @@ jobs:
|
||||
- run: tinygo build -size short -o test.elf -target=itsybitsy-m0 ./examples/ds3231/main.go
|
||||
- run: tinygo build -size short -o test.elf -target=microbit ./examples/easystepper/main.go
|
||||
- run: tinygo build -size short -o test.elf -target=itsybitsy-m0 ./examples/espat/esphub/main.go
|
||||
- run: tinygo build -size short -o test.elf -target=circuitplay-express ./examples/lis3dh/main.go
|
||||
- run: tinygo build -size short -o test.elf -target=itsybitsy-m0 ./examples/mag3110/main.go
|
||||
- run: tinygo build -size short -o test.elf -target=itsybitsy-m0 ./examples/mma8653/main.go
|
||||
- run: tinygo build -size short -o test.elf -target=itsybitsy-m0 ./examples/mpu6050/main.go
|
||||
|
||||
@@ -62,6 +62,7 @@ func main() {
|
||||
| [DS3231 real time clock](https://datasheets.maximintegrated.com/en/ds/DS3231.pdf) | I2C |
|
||||
| ["Easystepper" stepper motor controller](https://en.wikipedia.org/wiki/Stepper_motor) | GPIO |
|
||||
| [ESP8266/ESP32 AT Command set for WiFi/TCP/UDP](https://github.com/espressif/esp32-at) | UART |
|
||||
| [LIS3DH accelerometer](https://www.st.com/resource/en/datasheet/lis3dh.pdf) | I2C |
|
||||
| [MAG3110 magnetometer](https://www.nxp.com/docs/en/data-sheet/MAG3110.pdf) | I2C |
|
||||
| [MMA8653 accelerometer](https://www.nxp.com/docs/en/data-sheet/MMA8653FC.pdf) | I2C |
|
||||
| [MPU6050 accelerometer/gyroscope](https://store.invensense.com/datasheets/invensense/MPU-6050_DataSheet_V3%204.pdf) | I2C |
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
// Connects to a LIS3DH I2C accelerometer on the Adafruit Circuit Playground Express.
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"github.com/tinygo-org/drivers/lis3dh"
|
||||
)
|
||||
|
||||
var i2c = machine.I2C1
|
||||
|
||||
func main() {
|
||||
i2c.Configure(machine.I2CConfig{})
|
||||
|
||||
accel := lis3dh.New(i2c)
|
||||
accel.Address = lis3dh.Address1 // address on the Circuit Playground Express
|
||||
accel.Configure()
|
||||
accel.SetRange(lis3dh.RANGE_2_G)
|
||||
|
||||
println(accel.Connected())
|
||||
|
||||
for {
|
||||
x, y, z, _ := accel.ReadAcceleration()
|
||||
println("X:", x, "Y:", y, "Z:", z)
|
||||
|
||||
rx, ry, rz := accel.ReadRawAcceleration()
|
||||
println("X (raw):", rx, "Y (raw):", ry, "Z (raw):", rz)
|
||||
|
||||
time.Sleep(time.Millisecond * 100)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
// Package lis3dh provides a driver for the LIS3DH digital accelerometer.
|
||||
//
|
||||
// Datasheet: https://www.st.com/resource/en/datasheet/lis3dh.pdf
|
||||
package lis3dh
|
||||
|
||||
import (
|
||||
"machine"
|
||||
)
|
||||
|
||||
// Device wraps an I2C connection to a LIS3DH device.
|
||||
type Device struct {
|
||||
bus machine.I2C
|
||||
Address uint16
|
||||
r Range
|
||||
}
|
||||
|
||||
// New creates a new LIS3DH 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: Address0}
|
||||
}
|
||||
|
||||
// Configure sets up the device for communication
|
||||
func (d *Device) Configure() {
|
||||
// enable all axes, normal mode
|
||||
d.bus.WriteRegister(uint8(d.Address), REG_CTRL1, []byte{0x07})
|
||||
|
||||
// 400Hz rate
|
||||
d.SetDataRate(DATARATE_400_HZ)
|
||||
|
||||
// High res & BDU enabled
|
||||
d.bus.WriteRegister(uint8(d.Address), REG_CTRL4, []byte{0x88})
|
||||
|
||||
// get current range
|
||||
d.r = d.ReadRange()
|
||||
}
|
||||
|
||||
// Connected returns whether a LIS3DH has been found.
|
||||
// It does a "who am I" request and checks the response.
|
||||
func (d *Device) Connected() bool {
|
||||
data := []byte{0}
|
||||
err := d.bus.ReadRegister(uint8(d.Address), WHO_AM_I, data)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return data[0] == 0x33
|
||||
}
|
||||
|
||||
// SetDataRate sets the speed of data collected by the LIS3DH.
|
||||
func (d *Device) SetDataRate(rate DataRate) {
|
||||
ctl1 := []byte{0}
|
||||
err := d.bus.ReadRegister(uint8(d.Address), REG_CTRL1, ctl1)
|
||||
if err != nil {
|
||||
println(err.Error())
|
||||
}
|
||||
// mask off bits
|
||||
ctl1[0] &^= 0xf0
|
||||
ctl1[0] |= (byte(rate) << 4)
|
||||
d.bus.WriteRegister(uint8(d.Address), REG_CTRL1, ctl1)
|
||||
}
|
||||
|
||||
// SetRange sets the G range for LIS3DH.
|
||||
func (d *Device) SetRange(r Range) {
|
||||
ctl := []byte{0}
|
||||
err := d.bus.ReadRegister(uint8(d.Address), REG_CTRL4, ctl)
|
||||
if err != nil {
|
||||
println(err.Error())
|
||||
}
|
||||
// mask off bits
|
||||
ctl[0] &^= 0x30
|
||||
ctl[0] |= (byte(r) << 4)
|
||||
d.bus.WriteRegister(uint8(d.Address), REG_CTRL4, ctl)
|
||||
|
||||
// store the new range
|
||||
d.r = r
|
||||
}
|
||||
|
||||
// ReadRange returns the current G range for LIS3DH.
|
||||
func (d *Device) ReadRange() (r Range) {
|
||||
ctl := []byte{0}
|
||||
err := d.bus.ReadRegister(uint8(d.Address), REG_CTRL4, ctl)
|
||||
if err != nil {
|
||||
println(err.Error())
|
||||
}
|
||||
// mask off bits
|
||||
r = Range(ctl[0] >> 4)
|
||||
r &= 0x03
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
// ReadAcceleration reads the current acceleration from the device and returns
|
||||
// it in µg (micro-gravity). When one of the axes is pointing straight to Earth
|
||||
// and the sensor is not moving the returned value will be around 1000000 or
|
||||
// -1000000.
|
||||
func (d *Device) ReadAcceleration() (int32, int32, int32, error) {
|
||||
x, y, z := d.ReadRawAcceleration()
|
||||
divider := float32(1)
|
||||
switch d.r {
|
||||
case RANGE_16_G:
|
||||
divider = 1365
|
||||
case RANGE_8_G:
|
||||
divider = 4096
|
||||
case RANGE_4_G:
|
||||
divider = 8190
|
||||
case RANGE_2_G:
|
||||
divider = 16380
|
||||
}
|
||||
|
||||
return int32(float32(x) / divider * 1000000), int32(float32(y) / divider * 1000000), int32(float32(z) / divider * 1000000), nil
|
||||
}
|
||||
|
||||
// ReadRawAcceleration returns the raw x, y and z axis from the LIS3DH
|
||||
func (d *Device) ReadRawAcceleration() (x int16, y int16, z int16) {
|
||||
d.bus.WriteRegister(uint8(d.Address), REG_OUT_X_L|0x80, nil)
|
||||
|
||||
data := []byte{0, 0, 0, 0, 0, 0}
|
||||
d.bus.Tx(d.Address, nil, data)
|
||||
|
||||
x = int16((uint16(data[1]) << 8) | uint16(data[0]))
|
||||
y = int16((uint16(data[3]) << 8) | uint16(data[2]))
|
||||
z = int16((uint16(data[5]) << 8) | uint16(data[4]))
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package lis3dh
|
||||
|
||||
// Constants/addresses used for I2C.
|
||||
|
||||
// The I2C addresses which this device listens to.
|
||||
const (
|
||||
Address0 = 0x18 // SA0 is low
|
||||
Address1 = 0x19 // SA0 is high
|
||||
)
|
||||
|
||||
// Registers. Names, addresses and comments copied from the datasheet.
|
||||
const (
|
||||
WHO_AM_I = 0x0F
|
||||
REG_STATUS1 = 0x07
|
||||
REG_OUTADC1_L = 0x08
|
||||
REG_OUTADC1_H = 0x09
|
||||
REG_OUTADC2_L = 0x0A
|
||||
REG_OUTADC2_H = 0x0B
|
||||
REG_OUTADC3_L = 0x0C
|
||||
REG_OUTADC3_H = 0x0D
|
||||
REG_INTCOUNT = 0x0E
|
||||
REG_WHOAMI = 0x0F
|
||||
REG_TEMPCFG = 0x1F
|
||||
REG_CTRL1 = 0x20
|
||||
REG_CTRL2 = 0x21
|
||||
REG_CTRL3 = 0x22
|
||||
REG_CTRL4 = 0x23
|
||||
REG_CTRL5 = 0x24
|
||||
REG_CTRL6 = 0x25
|
||||
REG_REFERENCE = 0x26
|
||||
REG_STATUS2 = 0x27
|
||||
REG_OUT_X_L = 0x28
|
||||
REG_OUT_X_H = 0x29
|
||||
REG_OUT_Y_L = 0x2A
|
||||
REG_OUT_Y_H = 0x2B
|
||||
REG_OUT_Z_L = 0x2C
|
||||
REG_OUT_Z_H = 0x2D
|
||||
REG_FIFOCTRL = 0x2E
|
||||
REG_FIFOSRC = 0x2F
|
||||
REG_INT1CFG = 0x30
|
||||
REG_INT1SRC = 0x31
|
||||
REG_INT1THS = 0x32
|
||||
REG_INT1DUR = 0x33
|
||||
REG_CLICKCFG = 0x38
|
||||
REG_CLICKSRC = 0x39
|
||||
REG_CLICKTHS = 0x3A
|
||||
REG_TIMELIMIT = 0x3B
|
||||
REG_TIMELATEN = 0x3C
|
||||
REG_TIMEWINDO = 0x3D
|
||||
REG_ACTTHS = 0x3E
|
||||
REG_ACTDUR = 0x3F
|
||||
)
|
||||
|
||||
type Range uint8
|
||||
|
||||
const (
|
||||
RANGE_16_G Range = 3 // +/- 16g
|
||||
RANGE_8_G = 2 // +/- 8g
|
||||
RANGE_4_G = 1 // +/- 4g
|
||||
RANGE_2_G = 0 // +/- 2g (default value)
|
||||
)
|
||||
|
||||
type DataRate uint8
|
||||
|
||||
// Data rate constants.
|
||||
const (
|
||||
DATARATE_400_HZ DataRate = 7 // 400Hz
|
||||
DATARATE_200_HZ = 6 // 200Hz
|
||||
DATARATE_100_HZ = 5 // 100Hz
|
||||
DATARATE_50_HZ = 4 // 50Hz
|
||||
DATARATE_25_HZ = 3 // 25Hz
|
||||
DATARATE_10_HZ = 2 // 10 Hz
|
||||
DATARATE_1_HZ = 1 // 1 Hz
|
||||
DATARATE_POWERDOWN = 0
|
||||
DATARATE_LOWPOWER_1K6HZ = 8
|
||||
DATARATE_LOWPOWER_5KHZ = 9
|
||||
)
|
||||
Reference in New Issue
Block a user