mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-07-26 10:38:41 +00:00
128 lines
3.4 KiB
Go
128 lines
3.4 KiB
Go
// Package lis3dh provides a driver for the LIS3DH digital accelerometer.
|
|
//
|
|
// Datasheet: https://www.st.com/resource/en/datasheet/lis3dh.pdf
|
|
package lis3dh // import "tinygo.org/x/drivers/lis3dh"
|
|
|
|
import (
|
|
"tinygo.org/x/drivers"
|
|
"tinygo.org/x/drivers/internal/legacy"
|
|
)
|
|
|
|
// Device wraps an I2C connection to a LIS3DH device.
|
|
type Device struct {
|
|
bus drivers.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 drivers.I2C) Device {
|
|
return Device{bus: bus, Address: Address0}
|
|
}
|
|
|
|
// Configure sets up the device for communication
|
|
func (d *Device) Configure() {
|
|
// enable all axes, normal mode
|
|
legacy.WriteRegister(d.bus, uint8(d.Address), REG_CTRL1, []byte{0x07})
|
|
|
|
// 400Hz rate
|
|
d.SetDataRate(DATARATE_400_HZ)
|
|
|
|
// High res & BDU enabled
|
|
legacy.WriteRegister(d.bus, 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 := legacy.ReadRegister(d.bus, 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 := legacy.ReadRegister(d.bus, uint8(d.Address), REG_CTRL1, ctl1)
|
|
if err != nil {
|
|
println(err.Error())
|
|
}
|
|
// mask off bits
|
|
ctl1[0] &^= 0xf0
|
|
ctl1[0] |= (byte(rate) << 4)
|
|
legacy.WriteRegister(d.bus, uint8(d.Address), REG_CTRL1, ctl1)
|
|
}
|
|
|
|
// SetRange sets the G range for LIS3DH.
|
|
func (d *Device) SetRange(r Range) {
|
|
ctl := []byte{0}
|
|
err := legacy.ReadRegister(d.bus, uint8(d.Address), REG_CTRL4, ctl)
|
|
if err != nil {
|
|
println(err.Error())
|
|
}
|
|
// mask off bits
|
|
ctl[0] &^= 0x30
|
|
ctl[0] |= (byte(r) << 4)
|
|
legacy.WriteRegister(d.bus, 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 := legacy.ReadRegister(d.bus, 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) {
|
|
legacy.WriteRegister(d.bus, 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
|
|
}
|