tinygo.org/x/drivers@v0.27.1-0.20240509133757-7dbca2a54349/lis3dh/lis3dh.go (about)

     1  // Package lis3dh provides a driver for the LIS3DH digital accelerometer.
     2  //
     3  // Datasheet: https://www.st.com/resource/en/datasheet/lis3dh.pdf
     4  package lis3dh // import "tinygo.org/x/drivers/lis3dh"
     5  
     6  import (
     7  	"tinygo.org/x/drivers"
     8  	"tinygo.org/x/drivers/internal/legacy"
     9  )
    10  
    11  // Device wraps an I2C connection to a LIS3DH device.
    12  type Device struct {
    13  	bus     drivers.I2C
    14  	Address uint16
    15  	r       Range
    16  }
    17  
    18  // New creates a new LIS3DH connection. The I2C bus must already be configured.
    19  //
    20  // This function only creates the Device object, it does not touch the device.
    21  func New(bus drivers.I2C) Device {
    22  	return Device{bus: bus, Address: Address0}
    23  }
    24  
    25  // Configure sets up the device for communication
    26  func (d *Device) Configure() {
    27  	// enable all axes, normal mode
    28  	legacy.WriteRegister(d.bus, uint8(d.Address), REG_CTRL1, []byte{0x07})
    29  
    30  	// 400Hz rate
    31  	d.SetDataRate(DATARATE_400_HZ)
    32  
    33  	// High res & BDU enabled
    34  	legacy.WriteRegister(d.bus, uint8(d.Address), REG_CTRL4, []byte{0x88})
    35  
    36  	// get current range
    37  	d.r = d.ReadRange()
    38  }
    39  
    40  // Connected returns whether a LIS3DH has been found.
    41  // It does a "who am I" request and checks the response.
    42  func (d *Device) Connected() bool {
    43  	data := []byte{0}
    44  	err := legacy.ReadRegister(d.bus, uint8(d.Address), WHO_AM_I, data)
    45  	if err != nil {
    46  		return false
    47  	}
    48  	return data[0] == 0x33
    49  }
    50  
    51  // SetDataRate sets the speed of data collected by the LIS3DH.
    52  func (d *Device) SetDataRate(rate DataRate) {
    53  	ctl1 := []byte{0}
    54  	err := legacy.ReadRegister(d.bus, uint8(d.Address), REG_CTRL1, ctl1)
    55  	if err != nil {
    56  		println(err.Error())
    57  	}
    58  	// mask off bits
    59  	ctl1[0] &^= 0xf0
    60  	ctl1[0] |= (byte(rate) << 4)
    61  	legacy.WriteRegister(d.bus, uint8(d.Address), REG_CTRL1, ctl1)
    62  }
    63  
    64  // SetRange sets the G range for LIS3DH.
    65  func (d *Device) SetRange(r Range) {
    66  	ctl := []byte{0}
    67  	err := legacy.ReadRegister(d.bus, uint8(d.Address), REG_CTRL4, ctl)
    68  	if err != nil {
    69  		println(err.Error())
    70  	}
    71  	// mask off bits
    72  	ctl[0] &^= 0x30
    73  	ctl[0] |= (byte(r) << 4)
    74  	legacy.WriteRegister(d.bus, uint8(d.Address), REG_CTRL4, ctl)
    75  
    76  	// store the new range
    77  	d.r = r
    78  }
    79  
    80  // ReadRange returns the current G range for LIS3DH.
    81  func (d *Device) ReadRange() (r Range) {
    82  	ctl := []byte{0}
    83  	err := legacy.ReadRegister(d.bus, uint8(d.Address), REG_CTRL4, ctl)
    84  	if err != nil {
    85  		println(err.Error())
    86  	}
    87  	// mask off bits
    88  	r = Range(ctl[0] >> 4)
    89  	r &= 0x03
    90  
    91  	return r
    92  }
    93  
    94  // ReadAcceleration reads the current acceleration from the device and returns
    95  // it in µg (micro-gravity). When one of the axes is pointing straight to Earth
    96  // and the sensor is not moving the returned value will be around 1000000 or
    97  // -1000000.
    98  func (d *Device) ReadAcceleration() (int32, int32, int32, error) {
    99  	x, y, z := d.ReadRawAcceleration()
   100  	divider := float32(1)
   101  	switch d.r {
   102  	case RANGE_16_G:
   103  		divider = 1365
   104  	case RANGE_8_G:
   105  		divider = 4096
   106  	case RANGE_4_G:
   107  		divider = 8190
   108  	case RANGE_2_G:
   109  		divider = 16380
   110  	}
   111  
   112  	return int32(float32(x) / divider * 1000000), int32(float32(y) / divider * 1000000), int32(float32(z) / divider * 1000000), nil
   113  }
   114  
   115  // ReadRawAcceleration returns the raw x, y and z axis from the LIS3DH
   116  func (d *Device) ReadRawAcceleration() (x int16, y int16, z int16) {
   117  	legacy.WriteRegister(d.bus, uint8(d.Address), REG_OUT_X_L|0x80, nil)
   118  
   119  	data := []byte{0, 0, 0, 0, 0, 0}
   120  	d.bus.Tx(d.Address, nil, data)
   121  
   122  	x = int16((uint16(data[1]) << 8) | uint16(data[0]))
   123  	y = int16((uint16(data[3]) << 8) | uint16(data[2]))
   124  	z = int16((uint16(data[5]) << 8) | uint16(data[4]))
   125  
   126  	return
   127  }