91 lines
No EOL
3.9 KiB
C#
91 lines
No EOL
3.9 KiB
C#
using System;
|
|
using GrovePi.I2CDevices.Configuration;
|
|
using Windows.Devices.I2c;
|
|
|
|
namespace GrovePi.I2CDevices
|
|
{
|
|
|
|
public interface IThreeAxisAccelerometerADXL345
|
|
{
|
|
IThreeAxisAccelerometerADXL345 Initialize();
|
|
double[] GetAcclXYZ();
|
|
}
|
|
|
|
internal sealed class ThreeAxisAccelerometerADXL345 : IThreeAxisAccelerometerADXL345
|
|
{
|
|
struct Acceleration
|
|
{
|
|
public double X;
|
|
public double Y;
|
|
public double Z;
|
|
};
|
|
|
|
private const byte ACCEL_I2C_ADDR = 0x53; /* 7-bit I2C address of the ADXL345 with SDO pulled low */
|
|
private const byte ACCEL_REG_POWER_CONTROL = 0x2D; /* Address of the Power Control register */
|
|
private const byte ACCEL_REG_DATA_FORMAT = 0x31; /* Address of the Data Format register */
|
|
private const byte ACCEL_REG_X = 0x32; /* Address of the X Axis data register */
|
|
private const byte ACCEL_REG_Y = 0x34; /* Address of the Y Axis data register */
|
|
private const byte ACCEL_REG_Z = 0x36; /* Address of the Z Axis data register */
|
|
|
|
internal I2cDevice DirectAccess { get; }
|
|
|
|
internal ThreeAxisAccelerometerADXL345(I2cDevice Device)
|
|
{
|
|
if (Device == null) throw new ArgumentNullException(nameof(Device));
|
|
|
|
DirectAccess = Device;
|
|
}
|
|
|
|
public IThreeAxisAccelerometerADXL345 Initialize()
|
|
{
|
|
/*
|
|
* Initialize the accelerometer:
|
|
*
|
|
* For this device, we create 2-byte write buffers:
|
|
* The first byte is the register address we want to write to.
|
|
* The second byte is the contents that we want to write to the register.
|
|
*/
|
|
byte[] WriteBuf_DataFormat = new byte[] { ACCEL_REG_DATA_FORMAT, 0x01 }; /* 0x01 sets range to +- 4Gs */
|
|
byte[] WriteBuf_PowerControl = new byte[] { ACCEL_REG_POWER_CONTROL, 0x08 }; /* 0x08 puts the accelerometer into measurement mode */
|
|
|
|
/* Write the register settings */
|
|
DirectAccess.Write(WriteBuf_DataFormat);
|
|
DirectAccess.Write(WriteBuf_PowerControl);
|
|
|
|
return this;
|
|
}
|
|
|
|
public double[] GetAcclXYZ()
|
|
{
|
|
const int ACCEL_RES = 1024; /* The ADXL345 has 10 bit resolution giving 1024 unique values */
|
|
const int ACCEL_DYN_RANGE_G = 8; /* The ADXL345 had a total dynamic range of 8G, since we're configuring it to +-4G */
|
|
const int UNITS_PER_G = ACCEL_RES / ACCEL_DYN_RANGE_G; /* Ratio of raw int values to G units */
|
|
|
|
byte[] RegAddrBuf = new byte[] { ACCEL_REG_X }; /* Register address we want to read from */
|
|
byte[] ReadBuf = new byte[6]; /* We read 6 bytes sequentially to get all 3 two-byte axes registers in one read */
|
|
|
|
/*
|
|
* Read from the accelerometer
|
|
* We call WriteRead() so we first write the address of the X-Axis I2C register, then read all 3 axes
|
|
*/
|
|
DirectAccess.WriteRead(RegAddrBuf, ReadBuf);
|
|
|
|
/*
|
|
* In order to get the raw 16-bit data values, we need to concatenate two 8-bit bytes from the I2C read for each axis.
|
|
* We accomplish this by using the BitConverter class.
|
|
*/
|
|
short AccelerationRawX = BitConverter.ToInt16(ReadBuf, 0);
|
|
short AccelerationRawY = BitConverter.ToInt16(ReadBuf, 2);
|
|
short AccelerationRawZ = BitConverter.ToInt16(ReadBuf, 4);
|
|
|
|
/* Convert raw values to G's */
|
|
double[] accel = new double[3];
|
|
accel[0] = (double)AccelerationRawX / UNITS_PER_G;
|
|
accel[1] = (double)AccelerationRawY / UNITS_PER_G;
|
|
accel[2] = (double)AccelerationRawZ / UNITS_PER_G;
|
|
|
|
return accel;
|
|
}
|
|
|
|
}
|
|
} |