tinygo.org/x/drivers@v0.27.1-0.20240509133757-7dbca2a54349/adxl345/adxl345.go (about) 1 // Package adxl345 provides a driver for the ADXL345 digital accelerometer. 2 // 3 // Datasheet EN: http://www.analog.com/media/en/technical-documentation/data-sheets/ADXL345.pdf 4 // 5 // Datasheet JP: http://www.analog.com/media/jp/technical-documentation/data-sheets/ADXL345_jp.pdf 6 package adxl345 // import "tinygo.org/x/drivers/adxl345" 7 8 import ( 9 "tinygo.org/x/drivers" 10 "tinygo.org/x/drivers/internal/legacy" 11 ) 12 13 type Range uint8 14 type Rate uint8 15 16 // Internal structure for the power configuration 17 type powerCtl struct { 18 link uint8 19 autoSleep uint8 20 measure uint8 21 sleep uint8 22 wakeUp uint8 23 } 24 25 // Internal structure for the sensor's data format configuration 26 type dataFormat struct { 27 selfTest uint8 28 spi uint8 29 intInvert uint8 30 fullRes uint8 31 justify uint8 32 sensorRange Range 33 } 34 35 // Internal structure for the sampling rate configuration 36 type bwRate struct { 37 lowPower uint8 38 rate Rate 39 } 40 41 // Device wraps an I2C connection to a ADXL345 device. 42 type Device struct { 43 bus drivers.I2C 44 Address uint16 45 powerCtl powerCtl 46 dataFormat dataFormat 47 bwRate bwRate 48 } 49 50 // New creates a new ADXL345 connection. The I2C bus must already be 51 // configured. 52 // 53 // This function only creates the Device object, it does not init the device. 54 // To do that you must call the Configure() method on the Device before using it. 55 func New(bus drivers.I2C) Device { 56 return Device{ 57 bus: bus, 58 powerCtl: powerCtl{ 59 measure: 1, 60 }, 61 dataFormat: dataFormat{ 62 sensorRange: RANGE_2G, 63 }, 64 bwRate: bwRate{ 65 lowPower: 1, 66 rate: RATE_100HZ, 67 }, 68 Address: AddressLow, 69 } 70 } 71 72 // Configure sets up the device for communication 73 func (d *Device) Configure() { 74 legacy.WriteRegister(d.bus, uint8(d.Address), REG_BW_RATE, []byte{d.bwRate.toByte()}) 75 legacy.WriteRegister(d.bus, uint8(d.Address), REG_POWER_CTL, []byte{d.powerCtl.toByte()}) 76 legacy.WriteRegister(d.bus, uint8(d.Address), REG_DATA_FORMAT, []byte{d.dataFormat.toByte()}) 77 } 78 79 // Halt stops the sensor, values will not updated 80 func (d *Device) Halt() { 81 d.powerCtl.measure = 0 82 legacy.WriteRegister(d.bus, uint8(d.Address), REG_POWER_CTL, []byte{d.powerCtl.toByte()}) 83 } 84 85 // Restart makes reading the sensor working again after a halt 86 func (d *Device) Restart() { 87 d.powerCtl.measure = 1 88 legacy.WriteRegister(d.bus, uint8(d.Address), REG_POWER_CTL, []byte{d.powerCtl.toByte()}) 89 } 90 91 // ReadAcceleration reads the current acceleration from the device and returns 92 // it in µg (micro-gravity). When one of the axes is pointing straight to Earth 93 // and the sensor is not moving the returned value will be around 1000000 or 94 // -1000000. 95 func (d *Device) ReadAcceleration() (x int32, y int32, z int32, err error) { 96 rx, ry, rz := d.ReadRawAcceleration() 97 98 x = int32(d.dataFormat.convertToIS(rx)) 99 y = int32(d.dataFormat.convertToIS(ry)) 100 z = int32(d.dataFormat.convertToIS(rz)) 101 102 return 103 } 104 105 // ReadRawAcceleration reads the sensor values and returns the raw x, y and z axis 106 // from the adxl345. 107 func (d *Device) ReadRawAcceleration() (x int16, y int16, z int16) { 108 data := []byte{0, 0, 0, 0, 0, 0} 109 legacy.ReadRegister(d.bus, uint8(d.Address), REG_DATAX0, data) 110 111 x = readIntLE(data[0], data[1]) 112 y = readIntLE(data[2], data[3]) 113 z = readIntLE(data[4], data[5]) 114 115 return 116 } 117 118 // UseLowPower sets the ADXL345 to use the low power mode. 119 func (d *Device) UseLowPower(power bool) { 120 if power { 121 d.bwRate.lowPower = 1 122 } else { 123 d.bwRate.lowPower = 0 124 } 125 legacy.WriteRegister(d.bus, uint8(d.Address), REG_BW_RATE, []byte{d.bwRate.toByte()}) 126 } 127 128 // SetRate change the current rate of the sensor 129 func (d *Device) SetRate(rate Rate) bool { 130 d.bwRate.rate = rate & 0x0F 131 legacy.WriteRegister(d.bus, uint8(d.Address), REG_BW_RATE, []byte{d.bwRate.toByte()}) 132 return true 133 } 134 135 // SetRange change the current range of the sensor 136 func (d *Device) SetRange(sensorRange Range) bool { 137 d.dataFormat.sensorRange = sensorRange & 0x03 138 legacy.WriteRegister(d.bus, uint8(d.Address), REG_DATA_FORMAT, []byte{d.dataFormat.toByte()}) 139 return true 140 } 141 142 // convertToIS adjusts the raw values from the adxl345 with the range configuration 143 func (d *dataFormat) convertToIS(rawValue int16) int16 { 144 switch d.sensorRange { 145 case RANGE_2G: 146 return rawValue * 4 // rawValue * 2 * 1000 / 512 147 case RANGE_4G: 148 return rawValue * 8 // rawValue * 4 * 1000 / 512 149 case RANGE_8G: 150 return rawValue * 16 // rawValue * 8 * 1000 / 512 151 case RANGE_16G: 152 return rawValue * 32 // rawValue * 16 * 1000 / 512 153 default: 154 return 0 155 } 156 } 157 158 // toByte returns a byte from the powerCtl configuration 159 func (p *powerCtl) toByte() (bits uint8) { 160 bits = 0x00 161 bits = bits | (p.link << 5) 162 bits = bits | (p.autoSleep << 4) 163 bits = bits | (p.measure << 3) 164 bits = bits | (p.sleep << 2) 165 bits = bits | p.wakeUp 166 167 return bits 168 } 169 170 // toByte returns a byte from the dataFormat configuration 171 func (d *dataFormat) toByte() (bits uint8) { 172 bits = 0x00 173 bits = bits | (d.selfTest << 7) 174 bits = bits | (d.spi << 6) 175 bits = bits | (d.intInvert << 5) 176 bits = bits | (d.fullRes << 3) 177 bits = bits | (d.justify << 2) 178 bits = bits | uint8(d.sensorRange) 179 180 return bits 181 } 182 183 // toByte returns a byte from the bwRate configuration 184 func (b *bwRate) toByte() (bits uint8) { 185 bits = 0x00 186 bits = bits | (b.lowPower << 4) 187 bits = bits | uint8(b.rate) 188 189 return bits 190 } 191 192 // readInt converts two bytes to int16 193 func readIntLE(msb byte, lsb byte) int16 { 194 return int16(uint16(msb) | uint16(lsb)<<8) 195 }