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  }