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 edu.wpi.first.wpilibj.interfaces.Potentiometer; 011import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable; 012import edu.wpi.first.wpilibj.tables.ITable; 013 014/** 015 * Class for reading analog potentiometers. Analog potentiometers read in an analog voltage that 016 * corresponds to a position. The position is in whichever units you choose, by way of the scaling 017 * and offset constants passed to the constructor. 018 */ 019public class AnalogPotentiometer implements Potentiometer, LiveWindowSendable { 020 private AnalogInput m_analogInput; 021 private boolean m_initAnalogInput; 022 private double m_fullRange; 023 private double m_offset; 024 protected PIDSourceType m_pidSource = PIDSourceType.kDisplacement; 025 026 /** 027 * AnalogPotentiometer constructor. 028 * 029 * <p>Use the fullRange and offset values so that the output produces meaningful values. I.E: you 030 * have a 270 degree potentiometer and you want the output to be degrees with the halfway point as 031 * 0 degrees. The fullRange value is 270.0(degrees) and the offset is -135.0 since the halfway 032 * point after scaling is 135 degrees. This will calculate the result from the fullRange times 033 * the fraction of the supply voltage, plus the offset. 034 * 035 * @param channel The analog channel this potentiometer is plugged into. 036 * @param fullRange The scaling to multiply the fraction by to get a meaningful unit. 037 * @param offset The offset to add to the scaled value for controlling the zero value 038 */ 039 public AnalogPotentiometer(final int channel, double fullRange, double offset) { 040 this(new AnalogInput(channel), fullRange, offset); 041 m_initAnalogInput = true; 042 } 043 044 /** 045 * AnalogPotentiometer constructor. 046 * 047 * <p>Use the fullRange and offset values so that the output produces meaningful values. I.E: you 048 * have a 270 degree potentiometer and you want the output to be degrees with the halfway point as 049 * 0 degrees. The fullRange value is 270.0(degrees) and the offset is -135.0 since the halfway 050 * point after scaling is 135 degrees. This will calculate the result from the fullRange times 051 * the fraction of the supply voltage, plus the offset. 052 * 053 * @param input The {@link AnalogInput} this potentiometer is plugged into. 054 * @param fullRange The scaling to multiply the fraction by to get a meaningful unit. 055 * @param offset The offset to add to the scaled value for controlling the zero value 056 */ 057 public AnalogPotentiometer(final AnalogInput input, double fullRange, double offset) { 058 m_analogInput = input; 059 m_initAnalogInput = false; 060 061 m_fullRange = fullRange; 062 m_offset = offset; 063 } 064 065 /** 066 * AnalogPotentiometer constructor. 067 * 068 * <p>Use the fullRange and offset values so that the output produces meaningful values. I.E: you 069 * have a 270 degree potentiometer and you want the output to be degrees with the halfway point as 070 * 0 degrees. The fullRange value is 270.0(degrees) and the offset is -135.0 since the halfway 071 * point after scaling is 135 degrees. 072 * 073 * @param channel The analog channel this potentiometer is plugged into. 074 * @param scale The scaling to multiply the voltage by to get a meaningful unit. 075 */ 076 public AnalogPotentiometer(final int channel, double scale) { 077 this(channel, scale, 0); 078 } 079 080 /** 081 * AnalogPotentiometer constructor. 082 * 083 * <p>Use the fullRange and offset values so that the output produces meaningful values. I.E: you 084 * have a 270 degree potentiometer and you want the output to be degrees with the halfway point as 085 * 0 degrees. The fullRange value is 270.0(degrees) and the offset is -135.0 since the halfway 086 * point after scaling is 135 degrees. 087 * 088 * @param input The {@link AnalogInput} this potentiometer is plugged into. 089 * @param scale The scaling to multiply the voltage by to get a meaningful unit. 090 */ 091 public AnalogPotentiometer(final AnalogInput input, double scale) { 092 this(input, scale, 0); 093 } 094 095 /** 096 * AnalogPotentiometer constructor. 097 * 098 * @param channel The analog channel this potentiometer is plugged into. 099 */ 100 public AnalogPotentiometer(final int channel) { 101 this(channel, 1, 0); 102 } 103 104 /** 105 * AnalogPotentiometer constructor. 106 * 107 * @param input The {@link AnalogInput} this potentiometer is plugged into. 108 */ 109 public AnalogPotentiometer(final AnalogInput input) { 110 this(input, 1, 0); 111 } 112 113 /** 114 * Get the current reading of the potentiometer. 115 * 116 * @return The current position of the potentiometer. 117 */ 118 @Override 119 public double get() { 120 return (m_analogInput.getVoltage() / ControllerPower.getVoltage5V()) * m_fullRange + m_offset; 121 } 122 123 @Override 124 public void setPIDSourceType(PIDSourceType pidSource) { 125 if (!pidSource.equals(PIDSourceType.kDisplacement)) { 126 throw new IllegalArgumentException("Only displacement PID is allowed for potentiometers."); 127 } 128 m_pidSource = pidSource; 129 } 130 131 @Override 132 public PIDSourceType getPIDSourceType() { 133 return m_pidSource; 134 } 135 136 /** 137 * Implement the PIDSource interface. 138 * 139 * @return The current reading. 140 */ 141 @Override 142 public double pidGet() { 143 return get(); 144 } 145 146 147 /** 148 * Live Window code, only does anything if live window is activated. 149 */ 150 @Override 151 public String getSmartDashboardType() { 152 return "Analog Input"; 153 } 154 155 private ITable m_table; 156 157 @Override 158 public void initTable(ITable subtable) { 159 m_table = subtable; 160 updateTable(); 161 } 162 163 @Override 164 public void updateTable() { 165 if (m_table != null) { 166 m_table.putNumber("Value", get()); 167 } 168 } 169 170 @Override 171 public ITable getTable() { 172 return m_table; 173 } 174 175 /** 176 * Frees this resource. 177 */ 178 public void free() { 179 if (m_initAnalogInput) { 180 m_analogInput.free(); 181 m_analogInput = null; 182 m_initAnalogInput = false; 183 } 184 } 185 186 /** 187 * Analog Channels don't have to do anything special when entering the LiveWindow. {@inheritDoc} 188 */ 189 @Override 190 public void startLiveWindowMode() { 191 } 192 193 /** 194 * Analog Channels don't have to do anything special when exiting the LiveWindow. {@inheritDoc} 195 */ 196 @Override 197 public void stopLiveWindowMode() { 198 } 199}