tinygo.org/x/drivers@v0.27.1-0.20240509133757-7dbca2a54349/lsm6dsox/lsm6dsox.go (about) 1 // Package lsm6dsox implements a driver for the LSM6DSOX 2 // a 6 axis Inertial Measurement Unit (IMU) 3 // 4 // Datasheet: https://www.st.com/resource/en/datasheet/lsm6dsox.pdf 5 package lsm6dsox // import "tinygo.org/x/drivers/lsm6dsox" 6 7 import ( 8 "errors" 9 10 "tinygo.org/x/drivers" 11 "tinygo.org/x/drivers/internal/legacy" 12 ) 13 14 type AccelRange uint8 15 type AccelSampleRate uint8 16 17 type GyroRange uint8 18 type GyroSampleRate uint8 19 20 // Device wraps an I2C connection to a LSM6DSOX device. 21 type Device struct { 22 bus drivers.I2C 23 Address uint16 24 accelMultiplier int32 25 gyroMultiplier int32 26 buf [6]uint8 27 } 28 29 // Configuration for LSM6DSOX device. 30 type Configuration struct { 31 AccelRange AccelRange 32 AccelSampleRate AccelSampleRate 33 GyroRange GyroRange 34 GyroSampleRate GyroSampleRate 35 } 36 37 var errNotConnected = errors.New("lsm6dsox: failed to communicate with acel/gyro sensor") 38 39 // New creates a new LSM6DSOX connection. The I2C bus must already be configured. 40 // 41 // This function only creates the Device object, it does not touch the device. 42 func New(bus drivers.I2C) *Device { 43 return &Device{ 44 bus: bus, 45 Address: Address, 46 } 47 } 48 49 // Configure sets up the device for communication. 50 func (d *Device) Configure(cfg Configuration) (err error) { 51 52 // Verify unit communication 53 if !d.Connected() { 54 return errNotConnected 55 } 56 57 // Multipliers come from "Table 2. Mechanical characteristics" of the datasheet * 1000 58 switch cfg.AccelRange { 59 case ACCEL_2G: 60 d.accelMultiplier = 61 61 case ACCEL_4G: 62 d.accelMultiplier = 122 63 case ACCEL_8G: 64 d.accelMultiplier = 244 65 case ACCEL_16G: 66 d.accelMultiplier = 488 67 } 68 switch cfg.GyroRange { 69 case GYRO_250DPS: 70 d.gyroMultiplier = 8750 71 case GYRO_500DPS: 72 d.gyroMultiplier = 17500 73 case GYRO_1000DPS: 74 d.gyroMultiplier = 35000 75 case GYRO_2000DPS: 76 d.gyroMultiplier = 70000 77 } 78 79 data := d.buf[:1] 80 // Configure accelerometer 81 data[0] = uint8(cfg.AccelRange) | uint8(cfg.AccelSampleRate) 82 err = legacy.WriteRegister(d.bus, uint8(d.Address), CTRL1_XL, data) 83 if err != nil { 84 return 85 } 86 // Configure gyroscope 87 data[0] = uint8(cfg.GyroRange) | uint8(cfg.GyroSampleRate) 88 err = legacy.WriteRegister(d.bus, uint8(d.Address), CTRL2_G, data) 89 if err != nil { 90 return 91 } 92 93 return nil 94 } 95 96 // Connected returns whether a LSM6DSOX has been found. 97 // It does a "who am I" request and checks the response. 98 func (d *Device) Connected() bool { 99 data := d.buf[:1] 100 legacy.ReadRegister(d.bus, uint8(d.Address), WHO_AM_I, data) 101 return data[0] == 0x6C 102 } 103 104 // ReadAcceleration reads the current acceleration from the device and returns 105 // it in µg (micro-gravity). When one of the axes is pointing straight to Earth 106 // and the sensor is not moving the returned value will be around 1000000 or 107 // -1000000. 108 func (d *Device) ReadAcceleration() (x, y, z int32, err error) { 109 data := d.buf[:6] 110 err = legacy.ReadRegister(d.bus, uint8(d.Address), OUTX_L_A, data) 111 if err != nil { 112 return 113 } 114 x = int32(int16((uint16(data[1])<<8)|uint16(data[0]))) * d.accelMultiplier 115 y = int32(int16((uint16(data[3])<<8)|uint16(data[2]))) * d.accelMultiplier 116 z = int32(int16((uint16(data[5])<<8)|uint16(data[4]))) * d.accelMultiplier 117 return 118 } 119 120 // ReadRotation reads the current rotation from the device and returns it in 121 // µ°/s (micro-degrees/sec). This means that if you were to do a complete 122 // rotation along one axis and while doing so integrate all values over time, 123 // you would get a value close to 360000000. 124 func (d *Device) ReadRotation() (x, y, z int32, err error) { 125 data := d.buf[:6] 126 err = legacy.ReadRegister(d.bus, uint8(d.Address), OUTX_L_G, data) 127 if err != nil { 128 return 129 } 130 x = int32(int16((uint16(data[1])<<8)|uint16(data[0]))) * d.gyroMultiplier 131 y = int32(int16((uint16(data[3])<<8)|uint16(data[2]))) * d.gyroMultiplier 132 z = int32(int16((uint16(data[5])<<8)|uint16(data[4]))) * d.gyroMultiplier 133 return 134 } 135 136 // ReadTemperature returns the temperature in celsius milli degrees (°C/1000) 137 func (d *Device) ReadTemperature() (t int32, err error) { 138 data := d.buf[:2] 139 err = legacy.ReadRegister(d.bus, uint8(d.Address), OUT_TEMP_L, data) 140 if err != nil { 141 return 142 } 143 // From "Table 4. Temperature sensor characteristics" 144 // temp = value/256 + 25 145 t = 25000 + (int32(int16((int16(data[1])<<8)|int16(data[0])))*125)/32 146 return 147 }