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 }