001/*----------------------------------------------------------------------------*/ 002/* Copyright (c) 2008-2018 FIRST. 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 edu.wpi.first.wpilibj.hal.AnalogJNI; 011import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType; 012import edu.wpi.first.wpilibj.hal.HAL; 013import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder; 014import edu.wpi.first.wpilibj.util.AllocationException; 015 016/** 017 * Analog channel class. 018 * 019 * <p>Each analog channel is read from hardware as a 12-bit number representing 0V to 5V. 020 * 021 * <p>Connected to each analog channel is an averaging and oversampling engine. This engine 022 * accumulates the specified ( by setAverageBits() and setOversampleBits() ) number of samples 023 * before returning a new value. This is not a sliding window average. The only difference between 024 * the oversampled samples and the averaged samples is that the oversampled samples are simply 025 * accumulated effectively increasing the resolution, while the averaged samples are divided by the 026 * number of samples to retain the resolution, but get more stable values. 027 */ 028public class AnalogInput extends SensorBase implements PIDSource, Sendable { 029 private static final int kAccumulatorSlot = 1; 030 int m_port; // explicit no modifier, private and package accessible. 031 private int m_channel; 032 private static final int[] kAccumulatorChannels = {0, 1}; 033 private long m_accumulatorOffset; 034 protected PIDSourceType m_pidSource = PIDSourceType.kDisplacement; 035 036 /** 037 * Construct an analog channel. 038 * 039 * @param channel The channel number to represent. 0-3 are on-board 4-7 are on the MXP port. 040 */ 041 public AnalogInput(final int channel) { 042 checkAnalogInputChannel(channel); 043 m_channel = channel; 044 045 final int portHandle = AnalogJNI.getPort((byte) channel); 046 m_port = AnalogJNI.initializeAnalogInputPort(portHandle); 047 048 HAL.report(tResourceType.kResourceType_AnalogChannel, channel); 049 setName("AnalogInput", channel); 050 } 051 052 /** 053 * Channel destructor. 054 */ 055 @Override 056 public void free() { 057 super.free(); 058 AnalogJNI.freeAnalogInputPort(m_port); 059 m_port = 0; 060 m_channel = 0; 061 m_accumulatorOffset = 0; 062 } 063 064 /** 065 * Get a sample straight from this channel. The sample is a 12-bit value representing the 0V to 5V 066 * range of the A/D converter. The units are in A/D converter codes. Use GetVoltage() to get the 067 * analog value in calibrated units. 068 * 069 * @return A sample straight from this channel. 070 */ 071 public int getValue() { 072 return AnalogJNI.getAnalogValue(m_port); 073 } 074 075 /** 076 * Get a sample from the output of the oversample and average engine for this channel. The sample 077 * is 12-bit + the bits configured in SetOversampleBits(). The value configured in 078 * setAverageBits() will cause this value to be averaged 2^bits number of samples. This is not a 079 * sliding window. The sample will not change until 2^(OversampleBits + AverageBits) samples have 080 * been acquired from this channel. Use getAverageVoltage() to get the analog value in calibrated 081 * units. 082 * 083 * @return A sample from the oversample and average engine for this channel. 084 */ 085 public int getAverageValue() { 086 return AnalogJNI.getAnalogAverageValue(m_port); 087 } 088 089 /** 090 * Get a scaled sample straight from this channel. The value is scaled to units of Volts using the 091 * calibrated scaling data from getLSBWeight() and getOffset(). 092 * 093 * @return A scaled sample straight from this channel. 094 */ 095 public double getVoltage() { 096 return AnalogJNI.getAnalogVoltage(m_port); 097 } 098 099 /** 100 * Get a scaled sample from the output of the oversample and average engine for this channel. The 101 * value is scaled to units of Volts using the calibrated scaling data from getLSBWeight() and 102 * getOffset(). Using oversampling will cause this value to be higher resolution, but it will 103 * update more slowly. Using averaging will cause this value to be more stable, but it will update 104 * more slowly. 105 * 106 * @return A scaled sample from the output of the oversample and average engine for this channel. 107 */ 108 public double getAverageVoltage() { 109 return AnalogJNI.getAnalogAverageVoltage(m_port); 110 } 111 112 /** 113 * Get the factory scaling least significant bit weight constant. The least significant bit weight 114 * constant for the channel that was calibrated in manufacturing and stored in an eeprom. 115 * 116 * <p>Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9) 117 * 118 * @return Least significant bit weight. 119 */ 120 public long getLSBWeight() { 121 return AnalogJNI.getAnalogLSBWeight(m_port); 122 } 123 124 /** 125 * Get the factory scaling offset constant. The offset constant for the channel that was 126 * calibrated in manufacturing and stored in an eeprom. 127 * 128 * <p>Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9) 129 * 130 * @return Offset constant. 131 */ 132 public int getOffset() { 133 return AnalogJNI.getAnalogOffset(m_port); 134 } 135 136 /** 137 * Get the channel number. 138 * 139 * @return The channel number. 140 */ 141 public int getChannel() { 142 return m_channel; 143 } 144 145 /** 146 * Set the number of averaging bits. This sets the number of averaging bits. The actual number of 147 * averaged samples is 2^bits. The averaging is done automatically in the FPGA. 148 * 149 * @param bits The number of averaging bits. 150 */ 151 public void setAverageBits(final int bits) { 152 AnalogJNI.setAnalogAverageBits(m_port, bits); 153 } 154 155 /** 156 * Get the number of averaging bits. This gets the number of averaging bits from the FPGA. The 157 * actual number of averaged samples is 2^bits. The averaging is done automatically in the FPGA. 158 * 159 * @return The number of averaging bits. 160 */ 161 public int getAverageBits() { 162 return AnalogJNI.getAnalogAverageBits(m_port); 163 } 164 165 /** 166 * Set the number of oversample bits. This sets the number of oversample bits. The actual number 167 * of oversampled values is 2^bits. The oversampling is done automatically in the FPGA. 168 * 169 * @param bits The number of oversample bits. 170 */ 171 public void setOversampleBits(final int bits) { 172 AnalogJNI.setAnalogOversampleBits(m_port, bits); 173 } 174 175 /** 176 * Get the number of oversample bits. This gets the number of oversample bits from the FPGA. The 177 * actual number of oversampled values is 2^bits. The oversampling is done automatically in the 178 * FPGA. 179 * 180 * @return The number of oversample bits. 181 */ 182 public int getOversampleBits() { 183 return AnalogJNI.getAnalogOversampleBits(m_port); 184 } 185 186 /** 187 * Initialize the accumulator. 188 */ 189 public void initAccumulator() { 190 if (!isAccumulatorChannel()) { 191 throw new AllocationException("Accumulators are only available on slot " + kAccumulatorSlot 192 + " on channels " + kAccumulatorChannels[0] + ", " + kAccumulatorChannels[1]); 193 } 194 m_accumulatorOffset = 0; 195 AnalogJNI.initAccumulator(m_port); 196 } 197 198 /** 199 * Set an initial value for the accumulator. 200 * 201 * <p>This will be added to all values returned to the user. 202 * 203 * @param initialValue The value that the accumulator should start from when reset. 204 */ 205 public void setAccumulatorInitialValue(long initialValue) { 206 m_accumulatorOffset = initialValue; 207 } 208 209 /** 210 * Resets the accumulator to the initial value. 211 */ 212 public void resetAccumulator() { 213 AnalogJNI.resetAccumulator(m_port); 214 215 // Wait until the next sample, so the next call to getAccumulator*() 216 // won't have old values. 217 final double sampleTime = 1.0 / getGlobalSampleRate(); 218 final double overSamples = 1 << getOversampleBits(); 219 final double averageSamples = 1 << getAverageBits(); 220 Timer.delay(sampleTime * overSamples * averageSamples); 221 222 } 223 224 /** 225 * Set the center value of the accumulator. 226 * 227 * <p>The center value is subtracted from each A/D value before it is added to the accumulator. 228 * This is used for the center value of devices like gyros and accelerometers to take the device 229 * offset into account when integrating. 230 * 231 * <p>This center value is based on the output of the oversampled and averaged source the 232 * accumulator channel. Because of this, any non-zero oversample bits will affect the size of the 233 * value for this field. 234 */ 235 public void setAccumulatorCenter(int center) { 236 AnalogJNI.setAccumulatorCenter(m_port, center); 237 } 238 239 /** 240 * Set the accumulator's deadband. 241 * 242 * @param deadband The deadband size in ADC codes (12-bit value) 243 */ 244 public void setAccumulatorDeadband(int deadband) { 245 AnalogJNI.setAccumulatorDeadband(m_port, deadband); 246 } 247 248 /** 249 * Read the accumulated value. 250 * 251 * <p>Read the value that has been accumulating. The accumulator is attached after the oversample 252 * and average engine. 253 * 254 * @return The 64-bit value accumulated since the last Reset(). 255 */ 256 public long getAccumulatorValue() { 257 return AnalogJNI.getAccumulatorValue(m_port) + m_accumulatorOffset; 258 } 259 260 /** 261 * Read the number of accumulated values. 262 * 263 * <p>Read the count of the accumulated values since the accumulator was last Reset(). 264 * 265 * @return The number of times samples from the channel were accumulated. 266 */ 267 public long getAccumulatorCount() { 268 return AnalogJNI.getAccumulatorCount(m_port); 269 } 270 271 /** 272 * Read the accumulated value and the number of accumulated values atomically. 273 * 274 * <p>This function reads the value and count from the FPGA atomically. This can be used for 275 * averaging. 276 * 277 * @param result AccumulatorResult object to store the results in. 278 */ 279 public void getAccumulatorOutput(AccumulatorResult result) { 280 if (result == null) { 281 throw new IllegalArgumentException("Null parameter `result'"); 282 } 283 if (!isAccumulatorChannel()) { 284 throw new IllegalArgumentException( 285 "Channel " + m_channel + " is not an accumulator channel."); 286 } 287 AnalogJNI.getAccumulatorOutput(m_port, result); 288 result.value += m_accumulatorOffset; 289 } 290 291 /** 292 * Is the channel attached to an accumulator. 293 * 294 * @return The analog channel is attached to an accumulator. 295 */ 296 public boolean isAccumulatorChannel() { 297 for (int channel : kAccumulatorChannels) { 298 if (m_channel == channel) { 299 return true; 300 } 301 } 302 return false; 303 } 304 305 /** 306 * Set the sample rate per channel. 307 * 308 * <p>This is a global setting for all channels. The maximum rate is 500kS/s divided by the number 309 * of channels in use. This is 62500 samples/s per channel if all 8 channels are used. 310 * 311 * @param samplesPerSecond The number of samples per second. 312 */ 313 public static void setGlobalSampleRate(final double samplesPerSecond) { 314 AnalogJNI.setAnalogSampleRate(samplesPerSecond); 315 } 316 317 /** 318 * Get the current sample rate. 319 * 320 * <p>This assumes one entry in the scan list. This is a global setting for all channels. 321 * 322 * @return Sample rate. 323 */ 324 public static double getGlobalSampleRate() { 325 return AnalogJNI.getAnalogSampleRate(); 326 } 327 328 @Override 329 public void setPIDSourceType(PIDSourceType pidSource) { 330 m_pidSource = pidSource; 331 } 332 333 @Override 334 public PIDSourceType getPIDSourceType() { 335 return m_pidSource; 336 } 337 338 /** 339 * Get the average voltage for use with PIDController. 340 * 341 * @return the average voltage 342 */ 343 @Override 344 public double pidGet() { 345 return getAverageVoltage(); 346 } 347 348 @Override 349 public void initSendable(SendableBuilder builder) { 350 builder.setSmartDashboardType("Analog Input"); 351 builder.addDoubleProperty("Value", this::getAverageVoltage, null); 352 } 353}