001/*----------------------------------------------------------------------------*/ 002/* Copyright (c) FIRST 2008-2017. 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 008package edu.wpi.first.wpilibj; 009 010import java.nio.ByteBuffer; 011import java.nio.ByteOrder; 012 013import edu.wpi.first.wpilibj.hal.FRCNetComm.tInstances; 014import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType; 015import edu.wpi.first.wpilibj.hal.HAL; 016import edu.wpi.first.wpilibj.interfaces.Accelerometer; 017import edu.wpi.first.wpilibj.livewindow.LiveWindow; 018import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable; 019import edu.wpi.first.wpilibj.tables.ITable; 020 021/** 022 * ADXL345 I2C Accelerometer. 023 */ 024@SuppressWarnings({"TypeName", "PMD.UnusedPrivateField"}) 025public class ADXL345_I2C extends SensorBase implements Accelerometer, LiveWindowSendable { 026 027 private static final byte kAddress = 0x1D; 028 private static final byte kPowerCtlRegister = 0x2D; 029 private static final byte kDataFormatRegister = 0x31; 030 private static final byte kDataRegister = 0x32; 031 private static final double kGsPerLSB = 0.00390625; 032 private static final byte kPowerCtl_Link = 0x20; 033 private static final byte kPowerCtl_AutoSleep = 0x10; 034 private static final byte kPowerCtl_Measure = 0x08; 035 private static final byte kPowerCtl_Sleep = 0x04; 036 037 private static final byte kDataFormat_SelfTest = (byte) 0x80; 038 private static final byte kDataFormat_SPI = 0x40; 039 private static final byte kDataFormat_IntInvert = 0x20; 040 private static final byte kDataFormat_FullRes = 0x08; 041 private static final byte kDataFormat_Justify = 0x04; 042 043 public enum Axes { 044 kX((byte) 0x00), 045 kY((byte) 0x02), 046 kZ((byte) 0x04); 047 048 /** 049 * The integer value representing this enumeration. 050 */ 051 @SuppressWarnings("MemberName") 052 public final byte value; 053 054 private Axes(byte value) { 055 this.value = value; 056 } 057 } 058 059 @SuppressWarnings("MemberName") 060 public static class AllAxes { 061 062 public double XAxis; 063 public double YAxis; 064 public double ZAxis; 065 } 066 067 protected I2C m_i2c; 068 069 /** 070 * Constructs the ADXL345 Accelerometer with I2C address 0x1D. 071 * 072 * @param port The I2C port the accelerometer is attached to 073 * @param range The range (+ or -) that the accelerometer will measure. 074 */ 075 public ADXL345_I2C(I2C.Port port, Range range) { 076 this(port, range, kAddress); 077 } 078 079 /** 080 * Constructs the ADXL345 Accelerometer over I2C. 081 * 082 * @param port The I2C port the accelerometer is attached to 083 * @param range The range (+ or -) that the accelerometer will measure. 084 * @param deviceAddress I2C address of the accelerometer (0x1D or 0x53) 085 */ 086 public ADXL345_I2C(I2C.Port port, Range range, int deviceAddress) { 087 m_i2c = new I2C(port, deviceAddress); 088 089 // Turn on the measurements 090 m_i2c.write(kPowerCtlRegister, kPowerCtl_Measure); 091 092 setRange(range); 093 094 HAL.report(tResourceType.kResourceType_ADXL345, tInstances.kADXL345_I2C); 095 LiveWindow.addSensor("ADXL345_I2C", port.value, this); 096 } 097 098 099 @Override 100 public void setRange(Range range) { 101 final byte value; 102 103 switch (range) { 104 case k2G: 105 value = 0; 106 break; 107 case k4G: 108 value = 1; 109 break; 110 case k8G: 111 value = 2; 112 break; 113 case k16G: 114 value = 3; 115 break; 116 default: 117 throw new IllegalArgumentException(range + " unsupported range type"); 118 } 119 120 // Specify the data format to read 121 m_i2c.write(kDataFormatRegister, kDataFormat_FullRes | value); 122 } 123 124 @Override 125 public double getX() { 126 return getAcceleration(Axes.kX); 127 } 128 129 @Override 130 public double getY() { 131 return getAcceleration(Axes.kY); 132 } 133 134 @Override 135 public double getZ() { 136 return getAcceleration(Axes.kZ); 137 } 138 139 /** 140 * Get the acceleration of one axis in Gs. 141 * 142 * @param axis The axis to read from. 143 * @return Acceleration of the ADXL345 in Gs. 144 */ 145 public double getAcceleration(Axes axis) { 146 ByteBuffer rawAccel = ByteBuffer.allocateDirect(2); 147 m_i2c.read(kDataRegister + axis.value, 2, rawAccel); 148 149 // Sensor is little endian... swap bytes 150 rawAccel.order(ByteOrder.LITTLE_ENDIAN); 151 return rawAccel.getShort(0) * kGsPerLSB; 152 } 153 154 /** 155 * Get the acceleration of all axes in Gs. 156 * 157 * @return An object containing the acceleration measured on each axis of the ADXL345 in Gs. 158 */ 159 public AllAxes getAccelerations() { 160 AllAxes data = new AllAxes(); 161 ByteBuffer rawData = ByteBuffer.allocateDirect(6); 162 m_i2c.read(kDataRegister, 6, rawData); 163 164 // Sensor is little endian... swap bytes 165 rawData.order(ByteOrder.LITTLE_ENDIAN); 166 data.XAxis = rawData.getShort(0) * kGsPerLSB; 167 data.YAxis = rawData.getShort(2) * kGsPerLSB; 168 data.ZAxis = rawData.getShort(4) * kGsPerLSB; 169 return data; 170 } 171 172 @Override 173 public String getSmartDashboardType() { 174 return "3AxisAccelerometer"; 175 } 176 177 private ITable m_table; 178 179 @Override 180 public void initTable(ITable subtable) { 181 m_table = subtable; 182 updateTable(); 183 } 184 185 @Override 186 public void updateTable() { 187 if (m_table != null) { 188 m_table.putNumber("X", getX()); 189 m_table.putNumber("Y", getY()); 190 m_table.putNumber("Z", getZ()); 191 } 192 } 193 194 @Override 195 public ITable getTable() { 196 return m_table; 197 } 198 199 @Override 200 public void startLiveWindowMode() { 201 } 202 203 @Override 204 public void stopLiveWindowMode() { 205 } 206}