001// Copyright (c) FIRST and other WPILib contributors. 002// Open Source Software; you can modify and/or share it under the terms of 003// the WPILib BSD license file in the root directory of this project. 004 005package edu.wpi.first.wpilibj; 006 007import edu.wpi.first.util.sendable.Sendable; 008import edu.wpi.first.util.sendable.SendableBuilder; 009import edu.wpi.first.util.sendable.SendableRegistry; 010 011/** 012 * Class for reading analog potentiometers. Analog potentiometers read in an analog voltage that 013 * corresponds to a position. The position is in whichever units you choose, by way of the scaling 014 * and offset constants passed to the constructor. 015 */ 016public class AnalogPotentiometer implements Sendable, AutoCloseable { 017 private AnalogInput m_analogInput; 018 private boolean m_initAnalogInput; 019 private double m_fullRange; 020 private double m_offset; 021 022 /** 023 * AnalogPotentiometer constructor. 024 * 025 * <p>Use the fullRange and offset values so that the output produces meaningful values. I.E: you 026 * have a 270 degree potentiometer, and you want the output to be degrees with the halfway point 027 * as 0 degrees. The fullRange value is 270.0(degrees) and the offset is -135.0 since the halfway 028 * point after scaling is 135 degrees. This will calculate the result from the fullRange times the 029 * fraction of the supply voltage, plus the offset. 030 * 031 * @param channel The analog input channel this potentiometer is plugged into. 0-3 are on-board 032 * and 4-7 are on the MXP port. 033 * @param fullRange The scaling to multiply the fraction by to get a meaningful unit. 034 * @param offset The offset to add to the scaled value for controlling the zero value 035 */ 036 public AnalogPotentiometer(final int channel, double fullRange, double offset) { 037 this(new AnalogInput(channel), fullRange, offset); 038 m_initAnalogInput = true; 039 SendableRegistry.addChild(this, m_analogInput); 040 } 041 042 /** 043 * AnalogPotentiometer constructor. 044 * 045 * <p>Use the fullRange and offset values so that the output produces meaningful values. I.E: you 046 * have a 270 degree potentiometer, and you want the output to be degrees with the halfway point 047 * as 0 degrees. The fullRange value is 270.0(degrees) and the offset is -135.0 since the halfway 048 * point after scaling is 135 degrees. This will calculate the result from the fullRange times the 049 * fraction of the supply voltage, plus the offset. 050 * 051 * @param input The {@link AnalogInput} this potentiometer is plugged into. 052 * @param fullRange The angular value (in desired units) representing the full 0-5V range of the 053 * input. 054 * @param offset The angular value (in desired units) representing the angular output at 0V. 055 */ 056 public AnalogPotentiometer(final AnalogInput input, double fullRange, double offset) { 057 SendableRegistry.addLW(this, "AnalogPotentiometer", input.getChannel()); 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 scale value so that the output produces meaningful values. I.E: you have a 270 069 * degree potentiometer, and you want the output to be degrees with the starting point as 0 070 * degrees. The scale value is 270.0(degrees). 071 * 072 * @param channel The analog input channel this potentiometer is plugged into. 0-3 are on-board 073 * and 4-7 are on the MXP port. 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 starting point 085 * as 0 degrees. The scale value is 270.0(degrees). 086 * 087 * @param input The {@link AnalogInput} this potentiometer is plugged into. 088 * @param scale The scaling to multiply the voltage by to get a meaningful unit. 089 */ 090 public AnalogPotentiometer(final AnalogInput input, double scale) { 091 this(input, scale, 0); 092 } 093 094 /** 095 * AnalogPotentiometer constructor. 096 * 097 * <p>The potentiometer will return a value between 0 and 1.0. 098 * 099 * @param channel The analog input channel this potentiometer is plugged into. 0-3 are on-board 100 * and 4-7 are on the MXP port. 101 */ 102 public AnalogPotentiometer(final int channel) { 103 this(channel, 1, 0); 104 } 105 106 /** 107 * AnalogPotentiometer constructor. 108 * 109 * <p>The potentiometer will return a value between 0 and 1.0. 110 * 111 * @param input The {@link AnalogInput} this potentiometer is plugged into. 112 */ 113 public AnalogPotentiometer(final AnalogInput input) { 114 this(input, 1, 0); 115 } 116 117 /** 118 * Get the current reading of the potentiometer. 119 * 120 * @return The current position of the potentiometer. 121 */ 122 public double get() { 123 if (m_analogInput == null) { 124 return m_offset; 125 } 126 return (m_analogInput.getAverageVoltage() / RobotController.getVoltage5V()) * m_fullRange 127 + m_offset; 128 } 129 130 @Override 131 public void initSendable(SendableBuilder builder) { 132 if (m_analogInput != null) { 133 builder.setSmartDashboardType("Analog Input"); 134 builder.addDoubleProperty("Value", this::get, null); 135 } 136 } 137 138 @Override 139 public void close() { 140 SendableRegistry.remove(this); 141 if (m_initAnalogInput) { 142 m_analogInput.close(); 143 m_analogInput = null; 144 m_initAnalogInput = false; 145 } 146 } 147}