001 /*----------------------------------------------------------------------------*/
002 /* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
003 /* Open Source Software - may be modified and shared by FRC teams. The code */
004 /* must be accompanied by the FIRST BSD license file in the root directory of */
005 /* the project. */
006 /*----------------------------------------------------------------------------*/
007 package edu.wpi.first.wpilibj;
008
009 import edu.wpi.first.wpilibj.communication.UsageReporting;
010
011 /**
012 *
013 * @author dtjones
014 */
015 public class ADXL345_I2C extends SensorBase {
016
017 private static final byte kAddress = 0x3A;
018 private static final byte kPowerCtlRegister = 0x2D;
019 private static final byte kDataFormatRegister = 0x31;
020 private static final byte kDataRegister = 0x32;
021 private static final double kGsPerLSB = 0.00390625;
022 private static final byte kPowerCtl_Link = 0x20, kPowerCtl_AutoSleep = 0x10, kPowerCtl_Measure = 0x08, kPowerCtl_Sleep = 0x04;
023 private static final byte kDataFormat_SelfTest = (byte) 0x80, kDataFormat_SPI = 0x40, kDataFormat_IntInvert = 0x20, kDataFormat_FullRes = 0x08, kDataFormat_Justify = 0x04;
024
025 public static class DataFormat_Range {
026
027 /**
028 * The integer value representing this enumeration
029 */
030 public final byte value;
031 static final byte k2G_val = 0x00;
032 static final byte k4G_val = 0x01;
033 static final byte k8G_val = 0x02;
034 static final byte k16G_val = 0x03;
035 public static final DataFormat_Range k2G = new DataFormat_Range(k2G_val);
036 public static final DataFormat_Range k4G = new DataFormat_Range(k4G_val);
037 public static final DataFormat_Range k8G = new DataFormat_Range(k8G_val);
038 public static final DataFormat_Range k16G = new DataFormat_Range(k16G_val);
039
040 private DataFormat_Range(byte value) {
041 this.value = value;
042 }
043 }
044
045 public static class Axes {
046
047 /**
048 * The integer value representing this enumeration
049 */
050 public final byte value;
051 static final byte kX_val = 0x00;
052 static final byte kY_val = 0x02;
053 static final byte kZ_val = 0x04;
054 public static final Axes kX = new Axes(kX_val);
055 public static final Axes kY = new Axes(kY_val);
056 public static final Axes kZ = new Axes(kZ_val);
057
058 private Axes(byte value) {
059 this.value = value;
060 }
061 }
062
063 public static class AllAxes {
064
065 public double XAxis;
066 public double YAxis;
067 public double ZAxis;
068 }
069 private I2C m_i2c;
070
071 /**
072 * Constructor.
073 *
074 * @param module The slot of the digital module that the sensor is plugged into.
075 * @param range The range (+ or -) that the accelerometer will measure.
076 */
077 public ADXL345_I2C(int moduleNumber, DataFormat_Range range) {
078 DigitalModule module = DigitalModule.getInstance(moduleNumber);
079 m_i2c = module.getI2C(kAddress);
080
081 // Turn on the measurements
082 m_i2c.write(kPowerCtlRegister, kPowerCtl_Measure);
083 // Specify the data format to read
084 m_i2c.write(kDataFormatRegister, kDataFormat_FullRes | range.value);
085
086 UsageReporting.report(UsageReporting.kResourceType_ADXL345, UsageReporting.kADXL345_I2C, moduleNumber-1);
087 }
088
089 /**
090 * Get the acceleration of one axis in Gs.
091 *
092 * @param axis The axis to read from.
093 * @return Acceleration of the ADXL345 in Gs.
094 */
095 public double getAcceleration(Axes axis) {
096 byte[] rawAccel = new byte[2];
097 m_i2c.read(kDataRegister + axis.value, rawAccel.length, rawAccel);
098
099 // Sensor is little endian... swap bytes
100 return accelFromBytes(rawAccel[0], rawAccel[1]);
101 }
102
103 private double accelFromBytes(byte first, byte second) {
104 short tempLow = (short) (first & 0xff);
105 short tempHigh = (short) ((second << 8) & 0xff00);
106 return (tempLow | tempHigh) * kGsPerLSB;
107 }
108
109 /**
110 * Get the acceleration of all axes in Gs.
111 *
112 * @return Acceleration measured on all axes of the ADXL345 in Gs.
113 */
114 public AllAxes getAccelerations() {
115 AllAxes data = new AllAxes();
116 byte[] rawData = new byte[6];
117 m_i2c.read(kDataRegister, rawData.length, rawData);
118
119 // Sensor is little endian... swap bytes
120 data.XAxis = accelFromBytes(rawData[0], rawData[1]);
121 data.YAxis = accelFromBytes(rawData[2], rawData[3]);
122 data.ZAxis = accelFromBytes(rawData[4], rawData[5]);
123 return data;
124 }
125
126 // TODO: Support LiveWindow
127 }