001/*----------------------------------------------------------------------------*/
002/* Copyright (c) 2016-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.CompressorJNI;
011import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
012import edu.wpi.first.wpilibj.hal.HAL;
013import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
014
015/**
016 * Class for operating a compressor connected to a PCM (Pneumatic Control Module). The PCM will
017 * automatically run in closed loop mode by default whenever a {@link Solenoid} object is created.
018 * For most cases, a Compressor object does not need to be instantiated or used in a robot program.
019 * This class is only required in cases where the robot program needs a more detailed status of the
020 * compressor or to enable/disable closed loop control.
021 *
022 * <p>Note: you cannot operate the compressor directly from this class as doing so would circumvent
023 * the safety provided by using the pressure switch and closed loop control. You can only turn off
024 * closed loop control, thereby stopping the compressor from operating.
025 */
026public class Compressor extends SendableBase implements Sendable {
027  private int m_compressorHandle;
028  private byte m_module;
029
030  /**
031   * Makes a new instance of the compressor using the provided CAN device ID.  Use this constructor
032   * when you have more than one PCM.
033   *
034   * @param module The PCM CAN device ID (0 - 62 inclusive)
035   */
036  public Compressor(int module) {
037    m_module = (byte) module;
038
039    m_compressorHandle = CompressorJNI.initializeCompressor((byte) module);
040
041    HAL.report(tResourceType.kResourceType_Compressor, module);
042    setName("Compressor", module);
043  }
044
045  /**
046   * Makes a new instance of the compressor using the default PCM ID of 0.
047   *
048   * <p>Additional modules can be supported by making a new instance and {@link #Compressor(int)
049   * specifying the CAN ID.}
050   */
051  public Compressor() {
052    this(SensorBase.getDefaultSolenoidModule());
053  }
054
055  /**
056   * Start the compressor running in closed loop control mode.
057   *
058   * <p>Use the method in cases where you would like to manually stop and start the compressor for
059   * applications such as conserving battery or making sure that the compressor motor doesn't start
060   * during critical operations.
061   */
062  public void start() {
063    setClosedLoopControl(true);
064  }
065
066  /**
067   * Stop the compressor from running in closed loop control mode.
068   *
069   * <p>Use the method in cases where you would like to manually stop and start the compressor for
070   * applications such as conserving battery or making sure that the compressor motor doesn't start
071   * during critical operations.
072   */
073  public void stop() {
074    setClosedLoopControl(false);
075  }
076
077  /**
078   * Get the status of the compressor.
079   *
080   * @return true if the compressor is on
081   */
082  public boolean enabled() {
083    return CompressorJNI.getCompressor(m_compressorHandle);
084  }
085
086  /**
087   * Get the pressure switch value.
088   *
089   * @return true if the pressure is low
090   */
091  public boolean getPressureSwitchValue() {
092    return CompressorJNI.getCompressorPressureSwitch(m_compressorHandle);
093  }
094
095  /**
096   * Get the current being used by the compressor.
097   *
098   * @return current consumed by the compressor in amps
099   */
100  public double getCompressorCurrent() {
101    return CompressorJNI.getCompressorCurrent(m_compressorHandle);
102  }
103
104  /**
105   * Set the PCM in closed loop control mode.
106   *
107   * @param on if true sets the compressor to be in closed loop control mode (default)
108   */
109  public void setClosedLoopControl(boolean on) {
110    CompressorJNI.setCompressorClosedLoopControl(m_compressorHandle, on);
111  }
112
113  /**
114   * Gets the current operating mode of the PCM.
115   *
116   * @return true if compressor is operating on closed-loop mode
117   */
118  public boolean getClosedLoopControl() {
119    return CompressorJNI.getCompressorClosedLoopControl(m_compressorHandle);
120  }
121
122  /**
123   * If PCM is in fault state : Compressor Drive is disabled due to compressor current being too
124   * high.
125   *
126   * @return true if PCM is in fault state.
127   */
128  public boolean getCompressorCurrentTooHighFault() {
129    return CompressorJNI.getCompressorCurrentTooHighFault(m_compressorHandle);
130  }
131
132  /**
133   * If PCM sticky fault is set : Compressor is disabled due to compressor current being too
134   * high.
135   *
136   * @return true if PCM sticky fault is set.
137   */
138  public boolean getCompressorCurrentTooHighStickyFault() {
139    return CompressorJNI.getCompressorCurrentTooHighStickyFault(m_compressorHandle);
140  }
141
142  /**
143   * If PCM sticky fault is set : Compressor output appears to be shorted.
144   *
145   * @return true if PCM sticky fault is set.
146   */
147  public boolean getCompressorShortedStickyFault() {
148    return CompressorJNI.getCompressorShortedStickyFault(m_compressorHandle);
149  }
150
151  /**
152   * If PCM is in fault state : Compressor output appears to be shorted.
153   *
154   * @return true if PCM is in fault state.
155   */
156  public boolean getCompressorShortedFault() {
157    return CompressorJNI.getCompressorShortedFault(m_compressorHandle);
158  }
159
160  /**
161   * If PCM sticky fault is set : Compressor does not appear to be wired, i.e. compressor is not
162   * drawing enough current.
163   *
164   * @return true if PCM sticky fault is set.
165   */
166  public boolean getCompressorNotConnectedStickyFault() {
167    return CompressorJNI.getCompressorNotConnectedStickyFault(m_compressorHandle);
168  }
169
170  /**
171   * If PCM is in fault state : Compressor does not appear to be wired, i.e. compressor is not
172   * drawing enough current.
173   *
174   * @return true if PCM is in fault state.
175   */
176  public boolean getCompressorNotConnectedFault() {
177    return CompressorJNI.getCompressorNotConnectedFault(m_compressorHandle);
178  }
179
180  /**
181   * Clear ALL sticky faults inside PCM that Compressor is wired to.
182   *
183   * <p>If a sticky fault is set, then it will be persistently cleared. The compressor might
184   * momentarily disable while the flags are being cleared. Doo not call this method too
185   * frequently, otherwise normal compressor functionality may be prevented.
186   *
187   * <p>If no sticky faults are set then this call will have no effect.
188   */
189  public void clearAllPCMStickyFaults() {
190    CompressorJNI.clearAllPCMStickyFaults(m_module);
191  }
192
193  @Override
194  public void initSendable(SendableBuilder builder) {
195    builder.setSmartDashboardType("Compressor");
196    builder.addBooleanProperty("Enabled", this::enabled, (value) -> {
197      if (value) {
198        start();
199      } else {
200        stop();
201      }
202    });
203    builder.addBooleanProperty("Pressure switch", this::getPressureSwitchValue, null);
204  }
205}