mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-03 06:27:47 +00:00
Driver for ADXL345 3-axis digital accelerometer (#33)
* Driver for ADXL345 3-axis digital accelerometer
This commit is contained in:
committed by
Ron Evans
parent
f6bdc9734f
commit
ed2d334d55
@@ -53,6 +53,7 @@ func main() {
|
||||
|
||||
| Device Name | Interface Type |
|
||||
|----------|-------------|
|
||||
| [ADXL345 accelerometer](http://www.analog.com/media/en/technical-documentation/data-sheets/ADXL345.pdf) | I2C |
|
||||
| [APA102 RGB LED](https://cdn-shop.adafruit.com/product-files/2343/APA102C.pdf) | SPI |
|
||||
| [BH1750 ambient light sensor](https://www.mouser.com/ds/2/348/bh1750fvi-e-186247.pdf) | I2C |
|
||||
| [BlinkM RGB LED](http://thingm.com/fileadmin/thingm/downloads/BlinkM_datasheet.pdf) | I2C |
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
// Package provides a driver for the digital accelerometer ADXL345
|
||||
//
|
||||
// Datasheet EN: http://www.analog.com/media/en/technical-documentation/data-sheets/ADXL345.pdf
|
||||
// Datasheet JP: http://www.analog.com/media/jp/technical-documentation/data-sheets/ADXL345_jp.pdf
|
||||
package adxl345
|
||||
|
||||
import (
|
||||
"machine"
|
||||
)
|
||||
|
||||
type Range uint8
|
||||
type Rate uint8
|
||||
|
||||
// Internal structure for the power configuration
|
||||
type powerCtl struct {
|
||||
link uint8
|
||||
autoSleep uint8
|
||||
measure uint8
|
||||
sleep uint8
|
||||
wakeUp uint8
|
||||
}
|
||||
|
||||
// Internal structure for the sensor's data format configuration
|
||||
type dataFormat struct {
|
||||
selfTest uint8
|
||||
spi uint8
|
||||
intInvert uint8
|
||||
fullRes uint8
|
||||
justify uint8
|
||||
sensorRange Range
|
||||
}
|
||||
|
||||
// Internal structure for the sampling rate configuration
|
||||
type bwRate struct {
|
||||
lowPower uint8
|
||||
rate Rate
|
||||
}
|
||||
|
||||
// Device wraps an I2C connection to a BMP180 device.
|
||||
type Device struct {
|
||||
bus machine.I2C
|
||||
Address uint16
|
||||
powerCtl powerCtl
|
||||
dataFormat dataFormat
|
||||
bwRate bwRate
|
||||
x, y, z int32
|
||||
rawX, rawY, rawZ int32
|
||||
}
|
||||
|
||||
// New creates a new BMP180 connection. The I2C bus must already be
|
||||
// configured.
|
||||
//
|
||||
// This function only creates the Device object, it does not touch the device.
|
||||
func New(bus machine.I2C) Device {
|
||||
return Device{
|
||||
bus: bus,
|
||||
powerCtl: powerCtl{
|
||||
measure: 1,
|
||||
},
|
||||
dataFormat: dataFormat{
|
||||
sensorRange: RANGE_2G,
|
||||
},
|
||||
bwRate: bwRate{
|
||||
lowPower: 1,
|
||||
rate: RATE_100HZ,
|
||||
},
|
||||
Address: AddressLow,
|
||||
}
|
||||
}
|
||||
|
||||
// Configure sets up the device for communication
|
||||
func (d *Device) Configure() {
|
||||
d.bus.WriteRegister(uint8(d.Address), REG_BW_RATE, []byte{d.bwRate.toByte()})
|
||||
d.bus.WriteRegister(uint8(d.Address), REG_POWER_CTL, []byte{d.powerCtl.toByte()})
|
||||
d.bus.WriteRegister(uint8(d.Address), REG_DATA_FORMAT, []byte{d.dataFormat.toByte()})
|
||||
}
|
||||
|
||||
// Halt stops the sensor, values will not updated
|
||||
func (d *Device) Halt() {
|
||||
d.powerCtl.measure = 0
|
||||
d.bus.WriteRegister(uint8(d.Address), REG_POWER_CTL, []byte{d.powerCtl.toByte()})
|
||||
}
|
||||
|
||||
// Restart makes reading the sensor working again after a halt
|
||||
func (d *Device) Restart() {
|
||||
d.powerCtl.measure = 1
|
||||
d.bus.WriteRegister(uint8(d.Address), REG_POWER_CTL, []byte{d.powerCtl.toByte()})
|
||||
}
|
||||
|
||||
// Acceleration returns the adjusted x, y and z axis in µG
|
||||
func (d *Device) Acceleration() (x int32, y int32, z int32) {
|
||||
return d.x, d.y, d.z
|
||||
}
|
||||
|
||||
// XYZ returns the raw x, y and z axis from the adxl345
|
||||
func (d *Device) RawXYZ() (x int32, y int32, z int32) {
|
||||
return d.rawX, d.rawY, d.rawZ
|
||||
}
|
||||
|
||||
// Update reads the sensor values and stores them in a buffer
|
||||
func (d *Device) Update() {
|
||||
data := []byte{0, 0, 0, 0, 0, 0}
|
||||
d.bus.ReadRegister(uint8(d.Address), REG_DATAX0, data)
|
||||
|
||||
d.rawX = readIntLE(data[0], data[1])
|
||||
d.rawY = readIntLE(data[2], data[3])
|
||||
d.rawZ = readIntLE(data[4], data[5])
|
||||
|
||||
d.x = d.dataFormat.convertToIS(d.rawX)
|
||||
d.y = d.dataFormat.convertToIS(d.rawY)
|
||||
d.z = d.dataFormat.convertToIS(d.rawZ)
|
||||
}
|
||||
|
||||
// SetRate change the current rate of the sensor
|
||||
func (d *Device) UseLowPower(power bool) {
|
||||
if power {
|
||||
d.bwRate.lowPower = 1
|
||||
} else {
|
||||
d.bwRate.lowPower = 0
|
||||
}
|
||||
d.bus.WriteRegister(uint8(d.Address), REG_BW_RATE, []byte{d.bwRate.toByte()})
|
||||
}
|
||||
|
||||
// SetRate change the current rate of the sensor
|
||||
func (d *Device) SetRate(rate Rate) bool {
|
||||
d.bwRate.rate = rate & 0x0F
|
||||
d.bus.WriteRegister(uint8(d.Address), REG_BW_RATE, []byte{d.bwRate.toByte()})
|
||||
return true
|
||||
}
|
||||
|
||||
// SetRange change the current range of the sensor
|
||||
func (d *Device) SetRange(sensorRange Range) bool {
|
||||
d.dataFormat.sensorRange = sensorRange & 0x03
|
||||
d.bus.WriteRegister(uint8(d.Address), REG_DATA_FORMAT, []byte{d.dataFormat.toByte()})
|
||||
return true
|
||||
}
|
||||
|
||||
// convertToIS adjusts the raw values from the adxl345 with the range configuration
|
||||
func (d *dataFormat) convertToIS(rawValue int32) int32 {
|
||||
switch d.sensorRange {
|
||||
case RANGE_2G:
|
||||
return rawValue * 4 // rawValue * 2 * 1000 / 512
|
||||
case RANGE_4G:
|
||||
return rawValue * 8 // rawValue * 4 * 1000 / 512
|
||||
case RANGE_8G:
|
||||
return rawValue * 16 // rawValue * 8 * 1000 / 512
|
||||
case RANGE_16G:
|
||||
return rawValue * 32 // rawValue * 16 * 1000 / 512
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
// toByte returns a byte from the powerCtl configuration
|
||||
func (p *powerCtl) toByte() (bits uint8) {
|
||||
bits = 0x00
|
||||
bits = bits | (p.link << 5)
|
||||
bits = bits | (p.autoSleep << 4)
|
||||
bits = bits | (p.measure << 3)
|
||||
bits = bits | (p.sleep << 2)
|
||||
bits = bits | p.wakeUp
|
||||
|
||||
return bits
|
||||
}
|
||||
|
||||
// toByte returns a byte from the dataFormat configuration
|
||||
func (d *dataFormat) toByte() (bits uint8) {
|
||||
bits = 0x00
|
||||
bits = bits | (d.selfTest << 7)
|
||||
bits = bits | (d.spi << 6)
|
||||
bits = bits | (d.intInvert << 5)
|
||||
bits = bits | (d.fullRes << 3)
|
||||
bits = bits | (d.justify << 2)
|
||||
bits = bits | uint8(d.sensorRange)
|
||||
|
||||
return bits
|
||||
}
|
||||
|
||||
// toByte returns a byte from the bwRate configuration
|
||||
func (b *bwRate) toByte() (bits uint8) {
|
||||
bits = 0x00
|
||||
bits = bits | (b.lowPower << 4)
|
||||
bits = bits | uint8(b.rate)
|
||||
|
||||
return bits
|
||||
}
|
||||
|
||||
// readInt converts two bytes to int16
|
||||
func readIntLE(msb byte, lsb byte) int32 {
|
||||
return int32(uint16(msb) | uint16(lsb)<<8)
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package adxl345
|
||||
|
||||
const AddressLow = 0x53
|
||||
const AddressHigh = 0x1D
|
||||
|
||||
const (
|
||||
// Data rate
|
||||
RATE_3200HZ Rate = 0x0F // 3200 Hz
|
||||
RATE_1600HZ Rate = 0x0E // 1600 Hz
|
||||
RATE_800HZ Rate = 0x0D // 800 Hz
|
||||
RATE_400HZ Rate = 0x0C // 400 Hz
|
||||
RATE_200HZ Rate = 0x0B // 200 Hz
|
||||
RATE_100HZ Rate = 0x0A // 100 Hz
|
||||
RATE_50HZ Rate = 0x09 // 50 Hz
|
||||
RATE_25HZ Rate = 0x08 // 25 Hz
|
||||
RATE_12_5HZ Rate = 0x07 // 12.5 Hz
|
||||
RATE_6_25HZ Rate = 0x06 // 6.25 Hz
|
||||
RATE_3_13HZ Rate = 0x05 // 3.13 Hz
|
||||
RATE_1_56HZ Rate = 0x04 // 1.56 Hz
|
||||
RATE_0_78HZ Rate = 0x03 // 0.78 Hz
|
||||
RATE_0_39HZ Rate = 0x02 // 0.39 Hz
|
||||
RATE_0_20HZ Rate = 0x01 // 0.20 Hz
|
||||
RATE_0_10HZ Rate = 0x00 // 0.10 Hz
|
||||
|
||||
// Data range
|
||||
RANGE_2G Range = 0x00 // +-2 g
|
||||
RANGE_4G Range = 0x01 // +-4 g
|
||||
RANGE_8G Range = 0x02 // +-8 g
|
||||
RANGE_16G Range = 0x03 // +-16 g)
|
||||
|
||||
REG_DEVID = 0x00 // R, 11100101, Device ID
|
||||
REG_THRESH_TAP = 0x1D // R/W, 00000000, Tap threshold
|
||||
REG_OFSX = 0x1E // R/W, 00000000, X-axis offset
|
||||
REG_OFSY = 0x1F // R/W, 00000000, Y-axis offset
|
||||
REG_OFSZ = 0x20 // R/W, 00000000, Z-axis offset
|
||||
REG_DUR = 0x21 // R/W, 00000000, Tap duration
|
||||
REG_LATENT = 0x22 // R/W, 00000000, Tap latency
|
||||
REG_WINDOW = 0x23 // R/W, 00000000, Tap window
|
||||
REG_THRESH_ACT = 0x24 // R/W, 00000000, Activity threshold
|
||||
REG_THRESH_INACT = 0x25 // R/W, 00000000, Inactivity threshold
|
||||
REG_TIME_INACT = 0x26 // R/W, 00000000, Inactivity time
|
||||
REG_ACT_INACT_CTL = 0x27 // R/W, 00000000, Axis enable control for activity and inactiv ity detection
|
||||
REG_THRESH_FF = 0x28 // R/W, 00000000, Free-fall threshold
|
||||
REG_TIME_FF = 0x29 // R/W, 00000000, Free-fall time
|
||||
REG_TAP_AXES = 0x2A // R/W, 00000000, Axis control for single tap/double tap
|
||||
REG_ACT_TAP_STATUS = 0x2B // R, 00000000, Source of single tap/double tap
|
||||
REG_BW_RATE = 0x2C // R/W, 00001010, Data rate and power mode control
|
||||
REG_POWER_CTL = 0x2D // R/W, 00000000, Power-saving features control
|
||||
REG_INT_ENABLE = 0x2E // R/W, 00000000, Interrupt enable control
|
||||
REG_INT_MAP = 0x2F // R/W, 00000000, Interrupt mapping control
|
||||
REG_INT_SOUCE = 0x30 // R, 00000010, Source of interrupts
|
||||
REG_DATA_FORMAT = 0x31 // R/W, 00000000, Data format control
|
||||
REG_DATAX0 = 0x32 // R, 00000000, X-Axis Data 0
|
||||
REG_DATAX1 = 0x33 // R, 00000000, X-Axis Data 1
|
||||
REG_DATAY0 = 0x34 // R, 00000000, Y-Axis Data 0
|
||||
REG_DATAY1 = 0x35 // R, 00000000, Y-Axis Data 1
|
||||
REG_DATAZ0 = 0x36 // R, 00000000, Z-Axis Data 0
|
||||
REG_DATAZ1 = 0x37 // R, 00000000, Z-Axis Data 1
|
||||
REG_FIFO_CTL = 0x38 // R/W, 00000000, FIFO control
|
||||
REG_FIFO_STATUS = 0x39 // R, 00000000, FIFO status
|
||||
)
|
||||
@@ -0,0 +1,26 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"github.com/tinygo-org/drivers/adxl345"
|
||||
)
|
||||
|
||||
func main() {
|
||||
machine.I2C0.Configure(machine.I2CConfig{})
|
||||
sensor := adxl345.New(machine.I2C0)
|
||||
sensor.Configure()
|
||||
|
||||
println("ADXL345 starts")
|
||||
for {
|
||||
sensor.Update()
|
||||
x, y, z := sensor.Acceleration()
|
||||
println("X:", x, "Y:", y, "Z:", z)
|
||||
|
||||
rx, ry, rz := sensor.RawXYZ()
|
||||
println("X (raw):", rx, "Y (raw):", ry, "Z (raw):", rz)
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user