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.interfaces.Potentiometer; 011import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder; 012 013/** 014 * Class for reading analog potentiometers. Analog potentiometers read in an analog voltage that 015 * corresponds to a position. The position is in whichever units you choose, by way of the scaling 016 * and offset constants passed to the constructor. 017 */ 018public class AnalogPotentiometer extends SensorBase implements Potentiometer, Sendable { 019 private AnalogInput m_analogInput; 020 private boolean m_initAnalogInput; 021 private double m_fullRange; 022 private double m_offset; 023 protected PIDSourceType m_pidSource = PIDSourceType.kDisplacement; 024 025 /** 026 * AnalogPotentiometer constructor. 027 * 028 * <p>Use the fullRange and offset values so that the output produces meaningful values. I.E: you 029 * have a 270 degree potentiometer and you want the output to be degrees with the halfway point as 030 * 0 degrees. The fullRange value is 270.0(degrees) and the offset is -135.0 since the halfway 031 * point after scaling is 135 degrees. This will calculate the result from the fullRange times 032 * the fraction of the supply voltage, plus the offset. 033 * 034 * @param channel The analog channel this potentiometer is plugged into. 035 * @param fullRange The scaling to multiply the fraction by to get a meaningful unit. 036 * @param offset The offset to add to the scaled value for controlling the zero value 037 */ 038 public AnalogPotentiometer(final int channel, double fullRange, double offset) { 039 this(new AnalogInput(channel), fullRange, offset); 040 m_initAnalogInput = true; 041 addChild(m_analogInput); 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 setName("AnalogPotentiometer", input.getChannel()); 059 m_analogInput = input; 060 m_initAnalogInput = false; 061 062 m_fullRange = fullRange; 063 m_offset = offset; 064 } 065 066 /** 067 * AnalogPotentiometer constructor. 068 * 069 * <p>Use the fullRange and offset values so that the output produces meaningful values. I.E: you 070 * have a 270 degree potentiometer and you want the output to be degrees with the halfway point as 071 * 0 degrees. The fullRange value is 270.0(degrees) and the offset is -135.0 since the halfway 072 * point after scaling is 135 degrees. 073 * 074 * @param channel The analog channel this potentiometer is plugged into. 075 * @param scale The scaling to multiply the voltage by to get a meaningful unit. 076 */ 077 public AnalogPotentiometer(final int channel, double scale) { 078 this(channel, scale, 0); 079 } 080 081 /** 082 * AnalogPotentiometer constructor. 083 * 084 * <p>Use the fullRange and offset values so that the output produces meaningful values. I.E: you 085 * have a 270 degree potentiometer and you want the output to be degrees with the halfway point as 086 * 0 degrees. The fullRange value is 270.0(degrees) and the offset is -135.0 since the halfway 087 * point after scaling is 135 degrees. 088 * 089 * @param input The {@link AnalogInput} this potentiometer is plugged into. 090 * @param scale The scaling to multiply the voltage by to get a meaningful unit. 091 */ 092 public AnalogPotentiometer(final AnalogInput input, double scale) { 093 this(input, scale, 0); 094 } 095 096 /** 097 * AnalogPotentiometer constructor. 098 * 099 * @param channel The analog channel this potentiometer is plugged into. 100 */ 101 public AnalogPotentiometer(final int channel) { 102 this(channel, 1, 0); 103 } 104 105 /** 106 * AnalogPotentiometer constructor. 107 * 108 * @param input The {@link AnalogInput} this potentiometer is plugged into. 109 */ 110 public AnalogPotentiometer(final AnalogInput input) { 111 this(input, 1, 0); 112 } 113 114 /** 115 * Get the current reading of the potentiometer. 116 * 117 * @return The current position of the potentiometer. 118 */ 119 @Override 120 public double get() { 121 if (m_analogInput == null) { 122 return m_offset; 123 } 124 return (m_analogInput.getVoltage() / RobotController.getVoltage5V()) * m_fullRange + m_offset; 125 } 126 127 @Override 128 public void setPIDSourceType(PIDSourceType pidSource) { 129 if (!pidSource.equals(PIDSourceType.kDisplacement)) { 130 throw new IllegalArgumentException("Only displacement PID is allowed for potentiometers."); 131 } 132 m_pidSource = pidSource; 133 } 134 135 @Override 136 public PIDSourceType getPIDSourceType() { 137 return m_pidSource; 138 } 139 140 /** 141 * Implement the PIDSource interface. 142 * 143 * @return The current reading. 144 */ 145 @Override 146 public double pidGet() { 147 return get(); 148 } 149 150 @Override 151 public void initSendable(SendableBuilder builder) { 152 if (m_analogInput != null) { 153 m_analogInput.initSendable(builder); 154 } 155 } 156 157 /** 158 * Frees this resource. 159 */ 160 @Override 161 public void free() { 162 super.free(); 163 if (m_initAnalogInput) { 164 m_analogInput.free(); 165 m_analogInput = null; 166 m_initAnalogInput = false; 167 } 168 } 169}