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.hal.FRCNetComm.tResourceType;
008import edu.wpi.first.hal.HAL;
009import edu.wpi.first.hal.util.AllocationException;
010import edu.wpi.first.util.sendable.Sendable;
011import edu.wpi.first.util.sendable.SendableBuilder;
012import edu.wpi.first.util.sendable.SendableRegistry;
013
014/**
015 * Class for operating a compressor connected to a pneumatics module. The module will automatically
016 * run in closed loop mode by default whenever a {@link Solenoid} object is created. For most cases,
017 * a Compressor object does not need to be instantiated or used in a robot program. This class is
018 * only required in cases where the robot program needs a more detailed status of the compressor or
019 * to enable/disable closed loop control.
020 *
021 * <p>Note: you cannot operate the compressor directly from this class as doing so would circumvent
022 * the safety provided by using the pressure switch and closed loop control. You can only turn off
023 * closed loop control, thereby stopping the compressor from operating.
024 */
025public class Compressor implements Sendable, AutoCloseable {
026  private PneumaticsBase m_module;
027
028  /**
029   * Constructs a compressor for a specified module and type.
030   *
031   * @param module The module ID to use.
032   * @param moduleType The module type to use.
033   */
034  @SuppressWarnings("this-escape")
035  public Compressor(int module, PneumaticsModuleType moduleType) {
036    m_module = PneumaticsBase.getForType(module, moduleType);
037
038    if (!m_module.reserveCompressor()) {
039      m_module.close();
040      throw new AllocationException("Compressor already allocated");
041    }
042
043    m_module.enableCompressorDigital();
044
045    HAL.report(tResourceType.kResourceType_Compressor, module + 1);
046    SendableRegistry.addLW(this, "Compressor", module);
047  }
048
049  /**
050   * Constructs a compressor for a default module and specified type.
051   *
052   * @param moduleType The module type to use.
053   */
054  public Compressor(PneumaticsModuleType moduleType) {
055    this(PneumaticsBase.getDefaultForType(moduleType), moduleType);
056  }
057
058  @Override
059  public void close() {
060    SendableRegistry.remove(this);
061    m_module.unreserveCompressor();
062    m_module.close();
063    m_module = null;
064  }
065
066  /**
067   * Returns whether the compressor is active or not.
068   *
069   * @return true if the compressor is on - otherwise false.
070   */
071  public boolean isEnabled() {
072    return m_module.getCompressor();
073  }
074
075  /**
076   * Returns the state of the pressure switch.
077   *
078   * @return True if pressure switch indicates that the system is not full, otherwise false.
079   */
080  public boolean getPressureSwitchValue() {
081    return m_module.getPressureSwitch();
082  }
083
084  /**
085   * Get the current drawn by the compressor.
086   *
087   * @return Current drawn by the compressor in amps.
088   */
089  public double getCurrent() {
090    return m_module.getCompressorCurrent();
091  }
092
093  /**
094   * If supported by the device, returns the analog input voltage (on channel 0).
095   *
096   * <p>This function is only supported by the REV PH. On CTRE PCM, this will return 0.
097   *
098   * @return The analog input voltage, in volts.
099   */
100  public double getAnalogVoltage() {
101    return m_module.getAnalogVoltage(0);
102  }
103
104  /**
105   * If supported by the device, returns the pressure (in PSI) read by the analog pressure sensor
106   * (on channel 0).
107   *
108   * <p>This function is only supported by the REV PH with the REV Analog Pressure Sensor. On CTRE
109   * PCM, this will return 0.
110   *
111   * @return The pressure (in PSI) read by the analog pressure sensor.
112   */
113  public double getPressure() {
114    return m_module.getPressure(0);
115  }
116
117  /** Disable the compressor. */
118  public void disable() {
119    m_module.disableCompressor();
120  }
121
122  /**
123   * Enables the compressor in digital mode using the digital pressure switch. The compressor will
124   * turn on when the pressure switch indicates that the system is not full, and will turn off when
125   * the pressure switch indicates that the system is full.
126   */
127  public void enableDigital() {
128    m_module.enableCompressorDigital();
129  }
130
131  /**
132   * If supported by the device, enables the compressor in analog mode. This mode uses an analog
133   * pressure sensor connected to analog channel 0 to cycle the compressor. The compressor will turn
134   * on when the pressure drops below {@code minPressure} and will turn off when the pressure
135   * reaches {@code maxPressure}. This mode is only supported by the REV PH with the REV Analog
136   * Pressure Sensor connected to analog channel 0.
137   *
138   * <p>On CTRE PCM, this will enable digital control.
139   *
140   * @param minPressure The minimum pressure in PSI. The compressor will turn on when the pressure
141   *     drops below this value.
142   * @param maxPressure The maximum pressure in PSI. The compressor will turn off when the pressure
143   *     reaches this value.
144   */
145  public void enableAnalog(double minPressure, double maxPressure) {
146    m_module.enableCompressorAnalog(minPressure, maxPressure);
147  }
148
149  /**
150   * If supported by the device, enables the compressor in hybrid mode. This mode uses both a
151   * digital pressure switch and an analog pressure sensor connected to analog channel 0 to cycle
152   * the compressor. This mode is only supported by the REV PH with the REV Analog Pressure Sensor
153   * connected to analog channel 0.
154   *
155   * <p>The compressor will turn on when <i>both</i>:
156   *
157   * <ul>
158   *   <li>The digital pressure switch indicates the system is not full AND
159   *   <li>The analog pressure sensor indicates that the pressure in the system is below the
160   *       specified minimum pressure.
161   * </ul>
162   *
163   * <p>The compressor will turn off when <i>either</i>:
164   *
165   * <ul>
166   *   <li>The digital pressure switch is disconnected or indicates that the system is full OR
167   *   <li>The pressure detected by the analog sensor is greater than the specified maximum
168   *       pressure.
169   * </ul>
170   *
171   * <p>On CTRE PCM, this will enable digital control.
172   *
173   * @param minPressure The minimum pressure in PSI. The compressor will turn on when the pressure
174   *     drops below this value and the pressure switch indicates that the system is not full.
175   * @param maxPressure The maximum pressure in PSI. The compressor will turn off when the pressure
176   *     reaches this value or the pressure switch is disconnected or indicates that the system is
177   *     full.
178   */
179  public void enableHybrid(double minPressure, double maxPressure) {
180    m_module.enableCompressorHybrid(minPressure, maxPressure);
181  }
182
183  /**
184   * Returns the active compressor configuration.
185   *
186   * @return The active compressor configuration.
187   */
188  public CompressorConfigType getConfigType() {
189    return m_module.getCompressorConfigType();
190  }
191
192  @Override
193  public void initSendable(SendableBuilder builder) {
194    builder.setSmartDashboardType("Compressor");
195    builder.addBooleanProperty("Enabled", this::isEnabled, null);
196    builder.addBooleanProperty("Pressure switch", this::getPressureSwitchValue, null);
197  }
198}