diff --git a/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/cpp/RapidReactCommandBot.cpp b/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/cpp/RapidReactCommandBot.cpp index c25f0e820b..1b46affa21 100644 --- a/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/cpp/RapidReactCommandBot.cpp +++ b/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/cpp/RapidReactCommandBot.cpp @@ -40,6 +40,10 @@ void RapidReactCommandBot::ConfigureBindings() { m_storage.RunCommand()) // Since we composed this inline we should give it a name .WithName("Shoot")); + + // Toggle compressor with the Start button + m_driverController.Start().ToggleOnTrue( + m_pneumatics.DisableCompressorCommand()); } frc2::CommandPtr RapidReactCommandBot::GetAutonomousCommand() { diff --git a/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/cpp/subsystems/Pneumatics.cpp b/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/cpp/subsystems/Pneumatics.cpp new file mode 100644 index 0000000000..e19040a0c3 --- /dev/null +++ b/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/cpp/subsystems/Pneumatics.cpp @@ -0,0 +1,27 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#include "subsystems/Pneumatics.h" + +Pneumatics::Pneumatics() {} + +frc2::CommandPtr Pneumatics::DisableCompressorCommand() { + return StartEnd( + [&] { + // Disable closed-loop mode on the compressor. + m_compressor.Disable(); + }, + [&] { + // Enable closed-loop mode based on the digital pressure switch + // connected to the PCM/PH. The switch is open when the pressure is over + // ~120 PSI. + m_compressor.EnableDigital(); + }); +} + +units::pounds_per_square_inch_t Pneumatics::GetPressure() { + // Get the pressure (in PSI) from an analog pressure sensor connected to + // the RIO. + return units::pounds_per_square_inch_t{m_pressureTransducer.Get()}; +} diff --git a/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/include/RapidReactCommandBot.h b/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/include/RapidReactCommandBot.h index 4f733b7b49..0071a83b65 100644 --- a/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/include/RapidReactCommandBot.h +++ b/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/include/RapidReactCommandBot.h @@ -10,6 +10,7 @@ #include "Constants.h" #include "subsystems/Drive.h" #include "subsystems/Intake.h" +#include "subsystems/Pneumatics.h" #include "subsystems/Shooter.h" #include "subsystems/Storage.h" @@ -45,6 +46,7 @@ class RapidReactCommandBot { Intake m_intake; Shooter m_shooter; Storage m_storage; + Pneumatics m_pneumatics; // The driver's controller frc2::CommandXboxController m_driverController{ diff --git a/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/include/subsystems/Intake.h b/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/include/subsystems/Intake.h index 72093205ab..111353a0f5 100644 --- a/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/include/subsystems/Intake.h +++ b/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/include/subsystems/Intake.h @@ -28,7 +28,9 @@ class Intake : public frc2::SubsystemBase { private: frc::PWMSparkMax m_motor{IntakeConstants::kMotorPort}; - frc::DoubleSolenoid m_piston{frc::PneumaticsModuleType::REVPH, + + // Double solenoid connected to two channels of a PCM with the default CAN ID + frc::DoubleSolenoid m_piston{frc::PneumaticsModuleType::CTREPCM, IntakeConstants::kSolenoidPorts[0], IntakeConstants::kSolenoidPorts[1]}; }; diff --git a/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/include/subsystems/Pneumatics.h b/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/include/subsystems/Pneumatics.h new file mode 100644 index 0000000000..bd4f2d8d4e --- /dev/null +++ b/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/include/subsystems/Pneumatics.h @@ -0,0 +1,43 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "Constants.h" + +class Pneumatics : frc2::SubsystemBase { + public: + Pneumatics(); + /** Returns a command that disables the compressor indefinitely. */ + [[nodiscard]] frc2::CommandPtr DisableCompressorCommand(); + + /** + * Query the analog pressure sensor. + * + * @return the measured pressure, in PSI + */ + units::pounds_per_square_inch_t GetPressure(); + + private: + // External analog pressure sensor + // product-specific voltage->pressure conversion, see product manual + // in this case, 250(V/5)-25 + // the scale parameter in the AnalogPotentiometer constructor is scaled from + // 1 instead of 5, so if r is the raw AnalogPotentiometer output, the + // pressure is 250r-25 + static constexpr double kScale = 250; + static constexpr double kOffset = -25; + frc::AnalogPotentiometer m_pressureTransducer{/* the AnalogIn port*/ 2, + kScale, kOffset}; + + // Compressor connected to a PH with a default CAN ID + frc::Compressor m_compressor{frc::PneumaticsModuleType::CTREPCM}; +}; diff --git a/wpilibcExamples/src/main/cpp/examples/Solenoid/cpp/Robot.cpp b/wpilibcExamples/src/main/cpp/examples/Solenoid/cpp/Robot.cpp index 82e481bffa..88a2dbf242 100644 --- a/wpilibcExamples/src/main/cpp/examples/Solenoid/cpp/Robot.cpp +++ b/wpilibcExamples/src/main/cpp/examples/Solenoid/cpp/Robot.cpp @@ -2,69 +2,96 @@ // Open Source Software; you can modify and/or share it under the terms of // the WPILib BSD license file in the root directory of this project. -#include -#include -#include -#include -#include +#include "Robot.h" -/** - * This is a sample program showing the use of the solenoid classes during - * operator control. - * - * Three buttons from a joystick will be used to control two solenoids: One - * button to control the position of a single solenoid and the other two buttons - * to control a double solenoid. - * - * Single solenoids can either be on or off, such that the air diverted through - * them goes through either one channel or the other. - * - * Double solenoids have three states: Off, Forward, and Reverse. Forward and - * Reverse divert the air through the two channels and correspond to the on and - * off of a single solenoid, but a double solenoid can also be "off", where both - * channels are diverted to exhaust such that there is no pressure in either - * channel. - * - * Additionally, double solenoids take up two channels on your PCM whereas - * single solenoids only take a single channel. - */ -class Robot : public frc::TimedRobot { - public: - void TeleopPeriodic() override { - /* The output of GetRawButton is true/false depending on whether the button - * is pressed; Set takes a boolean for for whether to use the default - * (false) channel or the other (true). - */ - m_solenoid.Set(m_stick.GetRawButton(kSolenoidButton)); +#include +#include - /* In order to set the double solenoid, we will say that if neither button - * is pressed, it is off, if just one button is pressed, set the solenoid to - * correspond to that button, and if both are pressed, set the solenoid to - * Forwards. - */ - if (m_stick.GetRawButton(kDoubleSolenoidForward)) { - m_doubleSolenoid.Set(frc::DoubleSolenoid::kForward); - } else if (m_stick.GetRawButton(kDoubleSolenoidReverse)) { - m_doubleSolenoid.Set(frc::DoubleSolenoid::kReverse); - } else { - m_doubleSolenoid.Set(frc::DoubleSolenoid::kOff); - } +void Robot::RobotInit() { + // Publish elements to shuffleboard. + frc::ShuffleboardTab& tab = frc::Shuffleboard::GetTab("Pneumatics"); + tab.Add("Single Solenoid", m_solenoid); + tab.Add("Double Solenoid", m_doubleSolenoid); + tab.Add("Compressor", m_compressor); + + // Also publish some raw data + tab.AddDouble("PH Pressure [PSI]", [&] { + // Get the pressure (in PSI) from the analog sensor connected to the PH. + // This function is supported only on the PH! + // On a PCM, this function will return 0. + units::pounds_per_square_inch_t pressure = m_compressor.GetPressure(); + return pressure.value(); + }); + tab.AddDouble("Compressor Current", [&] { + // Get compressor current draw. + units::ampere_t compressorCurrent = m_compressor.GetCurrent(); + return compressorCurrent.value(); + }); + tab.AddBoolean("Compressor Active", [&] { + // Get whether the compressor is active. + return m_compressor.IsEnabled(); + }); + tab.AddBoolean("Pressure Switch", [&] { + // Get the digital pressure switch connected to the PCM/PH. + // The switch is open when the pressure is over ~120 PSI. + return m_compressor.GetPressureSwitchValue(); + }); +} + +void Robot::TeleopPeriodic() { + /* + * The output of GetRawButton is true/false depending on whether + * the button is pressed; Set takes a boolean for whether + * to retract the solenoid (false) or extend it (true). + */ + m_solenoid.Set(m_stick.GetRawButton(kSolenoidButton)); + + /* + * GetRawButtonPressed will only return true once per press. + * If a button is pressed, set the solenoid to the respective channel. + */ + if (m_stick.GetRawButtonPressed(kDoubleSolenoidForward)) { + m_doubleSolenoid.Set(frc::DoubleSolenoid::kForward); + } else if (m_stick.GetRawButtonPressed(kDoubleSolenoidReverse)) { + m_doubleSolenoid.Set(frc::DoubleSolenoid::kReverse); } - private: - frc::Joystick m_stick{0}; - - // Solenoid corresponds to a single solenoid. - frc::Solenoid m_solenoid{frc::PneumaticsModuleType::CTREPCM, 0}; - - // DoubleSolenoid corresponds to a double solenoid. - frc::DoubleSolenoid m_doubleSolenoid{frc::PneumaticsModuleType::CTREPCM, 1, - 2}; - - static constexpr int kSolenoidButton = 1; - static constexpr int kDoubleSolenoidForward = 2; - static constexpr int kDoubleSolenoidReverse = 3; -}; + // On button press, toggle the compressor with the mode selected from the + // dashboard. + if (m_stick.GetRawButtonPressed(kCompressorButton)) { + // Check whether the compressor is currently enabled. + bool isCompressorEnabled = m_compressor.IsEnabled(); + if (isCompressorEnabled) { + // Disable closed-loop mode on the compressor. + m_compressor.Disable(); + } else { + // Change the if directives to select the closed-loop mode you want to + // use: +#if 0 + // Enable closed-loop mode based on the digital pressure switch + // connected to the PCM/PH. + m_compressor.EnableDigital(); +#endif +#if 1 + // Enable closed-loop mode based on the analog pressure sensor connected + // to the PH. The compressor will run while the pressure reported by the + // sensor is in the specified range ([70 PSI, 120 PSI] in this example). + // Analog mode exists only on the PH! On the PCM, this enables digital + // control. + m_compressor.EnableAnalog(70_psi, 120_psi); +#endif +#if 0 + // Enable closed-loop mode based on both the digital pressure switch AND the analog + // pressure sensor connected to the PH. + // The compressor will run while the pressure reported by the analog sensor is in the + // specified range ([70 PSI, 120 PSI] in this example) AND the digital switch reports + // that the system is not full. + // Hybrid mode exists only on the PH! On the PCM, this enables digital control. + m_compressor.EnableHybrid(70_psi, 120_psi); +#endif + } + } +} #ifndef RUNNING_FRC_TESTS int main() { diff --git a/wpilibcExamples/src/main/cpp/examples/Solenoid/include/Robot.h b/wpilibcExamples/src/main/cpp/examples/Solenoid/include/Robot.h new file mode 100644 index 0000000000..550e949994 --- /dev/null +++ b/wpilibcExamples/src/main/cpp/examples/Solenoid/include/Robot.h @@ -0,0 +1,61 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +/** + * This is a sample program showing the use of the solenoid classes during + * operator control. + * + * Three buttons from a joystick will be used to control two solenoids: One + * button to control the position of a single solenoid and the other two buttons + * to control a double solenoid. + * + * Single solenoids can either be on or off, such that the air diverted through + * them goes through either one channel or the other. + * + * Double solenoids have three states: Off, Forward, and Reverse. Forward and + * Reverse divert the air through the two channels and correspond to the on and + * off of a single solenoid, but a double solenoid can also be "off", where both + * channels are diverted to exhaust such that there is no pressure in either + * channel. + * + * Additionally, double solenoids take up two channels on your PCM whereas + * single solenoids only take a single channel. + */ + +class Robot : public frc::TimedRobot { + public: + void RobotInit() override; + void TeleopPeriodic() override; + + private: + frc::Joystick m_stick{0}; + + // Solenoid corresponds to a single solenoid. + // In this case, it's connected to channel 0 of a PH with the default CAN + // ID. + frc::Solenoid m_solenoid{frc::PneumaticsModuleType::REVPH, 0}; + + // DoubleSolenoid corresponds to a double solenoid. + // In this case, it's connected to channels 1 and 2 of a PH with the default + // CAN ID. + frc::DoubleSolenoid m_doubleSolenoid{frc::PneumaticsModuleType::REVPH, 1, 2}; + + // Compressor connected to a PH with a default CAN ID + frc::Compressor m_compressor{frc::PneumaticsModuleType::REVPH}; + + static constexpr int kSolenoidButton = 1; + static constexpr int kDoubleSolenoidForward = 2; + static constexpr int kDoubleSolenoidReverse = 3; + static constexpr int kCompressorButton = 4; +}; diff --git a/wpilibcExamples/src/main/cpp/examples/examples.json b/wpilibcExamples/src/main/cpp/examples/examples.json index 4b96642647..a472716d11 100644 --- a/wpilibcExamples/src/main/cpp/examples/examples.json +++ b/wpilibcExamples/src/main/cpp/examples/examples.json @@ -58,6 +58,7 @@ "tags": [ "Hardware", "Joystick", + "Shuffleboard", "Pneumatics" ], "foldername": "Solenoid", diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/examples.json b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/examples.json index 3910ad30a7..a04ec9902a 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/examples.json +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/examples.json @@ -68,6 +68,7 @@ "tags": [ "Hardware", "Joystick", + "Shuffleboard", "Pneumatics" ], "foldername": "solenoid", diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/Constants.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/Constants.java index 6ee700c2f3..5809616cf7 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/Constants.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/Constants.java @@ -63,7 +63,7 @@ public final class Constants { public static final class IntakeConstants { public static final int kMotorPort = 6; - public static final int[] kSolenoidPorts = {0, 1}; + public static final int[] kSolenoidPorts = {2, 3}; } public static final class StorageConstants { diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/RapidReactCommandBot.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/RapidReactCommandBot.java index 879f2c227f..de0e93a271 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/RapidReactCommandBot.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/RapidReactCommandBot.java @@ -11,6 +11,7 @@ import edu.wpi.first.wpilibj.examples.rapidreactcommandbot.Constants.OIConstants import edu.wpi.first.wpilibj.examples.rapidreactcommandbot.Constants.ShooterConstants; import edu.wpi.first.wpilibj.examples.rapidreactcommandbot.subsystems.Drive; import edu.wpi.first.wpilibj.examples.rapidreactcommandbot.subsystems.Intake; +import edu.wpi.first.wpilibj.examples.rapidreactcommandbot.subsystems.Pneumatics; import edu.wpi.first.wpilibj.examples.rapidreactcommandbot.subsystems.Shooter; import edu.wpi.first.wpilibj.examples.rapidreactcommandbot.subsystems.Storage; import edu.wpi.first.wpilibj2.command.CommandBase; @@ -29,6 +30,7 @@ public class RapidReactCommandBot { private final Intake m_intake = new Intake(); private final Storage m_storage = new Storage(); private final Shooter m_shooter = new Shooter(); + private final Pneumatics m_pneumatics = new Pneumatics(); // The driver's controller CommandXboxController m_driverController = @@ -69,6 +71,9 @@ public class RapidReactCommandBot { m_storage.runCommand()) // Since we composed this inline we should give it a name .withName("Shoot")); + + // Toggle compressor with the Start button + m_driverController.start().toggleOnTrue(m_pneumatics.disableCompressorCommand()); } /** diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/subsystems/Intake.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/subsystems/Intake.java index 533f596fca..c8dcc215e1 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/subsystems/Intake.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/subsystems/Intake.java @@ -14,9 +14,11 @@ import edu.wpi.first.wpilibj2.command.SubsystemBase; public class Intake extends SubsystemBase { private final PWMSparkMax m_motor = new PWMSparkMax(IntakeConstants.kMotorPort); + + // Double solenoid connected to two channels of a PCM with the default CAN ID private final DoubleSolenoid m_pistons = new DoubleSolenoid( - PneumaticsModuleType.REVPH, + PneumaticsModuleType.CTREPCM, IntakeConstants.kSolenoidPorts[0], IntakeConstants.kSolenoidPorts[1]); diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/subsystems/Pneumatics.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/subsystems/Pneumatics.java new file mode 100644 index 0000000000..e98c8a70f7 --- /dev/null +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/subsystems/Pneumatics.java @@ -0,0 +1,65 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package edu.wpi.first.wpilibj.examples.rapidreactcommandbot.subsystems; + +import edu.wpi.first.wpilibj.AnalogPotentiometer; +import edu.wpi.first.wpilibj.Compressor; +import edu.wpi.first.wpilibj.PneumaticsModuleType; +import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard; +import edu.wpi.first.wpilibj2.command.CommandBase; +import edu.wpi.first.wpilibj2.command.SubsystemBase; + +/** Subsystem for managing the compressor, pressure sensor, etc. */ +public class Pneumatics extends SubsystemBase { + // External analog pressure sensor + // product-specific voltage->pressure conversion, see product manual + // in this case, 250(V/5)-25 + // the scale parameter in the AnalogPotentiometer constructor is scaled from 1 instead of 5, + // so if r is the raw AnalogPotentiometer output, the pressure is 250r-25 + static final double kScale = 250; + static final double kOffset = -25; + private final AnalogPotentiometer m_pressureTransducer = + new AnalogPotentiometer(/* the AnalogIn port*/ 2, kScale, kOffset); + + // Compressor connected to a PCM with a default CAN ID (0) + private final Compressor m_compressor = new Compressor(PneumaticsModuleType.CTREPCM); + + public Pneumatics() { + var tab = Shuffleboard.getTab("Pneumatics"); + tab.addDouble("External Pressure [PSI]", this::getPressure); + } + + /** + * Query the analog pressure sensor. + * + * @return the measured pressure, in PSI + */ + private double getPressure() { + // Get the pressure (in PSI) from an analog pressure sensor connected to the RIO. + return m_pressureTransducer.get(); + } + + /** + * Disable the compressor closed-loop for as long as the command runs. + * + *

Structured this way as the compressor is enabled by default. + * + * @return command + */ + public CommandBase disableCompressorCommand() { + return startEnd( + () -> { + // Disable closed-loop mode on the compressor. + m_compressor.disable(); + }, + () -> { + // Enable closed-loop mode based on the digital pressure switch connected to the + // PCM/PH. + // The switch is open when the pressure is over ~120 PSI. + m_compressor.enableDigital(); + }) + .withName("Compressor Disabled"); + } +} diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/solenoid/Robot.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/solenoid/Robot.java index 98fb3b6afc..d6ae048711 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/solenoid/Robot.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/solenoid/Robot.java @@ -4,11 +4,14 @@ package edu.wpi.first.wpilibj.examples.solenoid; +import edu.wpi.first.wpilibj.Compressor; import edu.wpi.first.wpilibj.DoubleSolenoid; import edu.wpi.first.wpilibj.Joystick; import edu.wpi.first.wpilibj.PneumaticsModuleType; import edu.wpi.first.wpilibj.Solenoid; import edu.wpi.first.wpilibj.TimedRobot; +import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard; +import edu.wpi.first.wpilibj.shuffleboard.ShuffleboardTab; /** * This is a sample program showing the use of the solenoid classes during operator control. Three @@ -25,34 +28,111 @@ public class Robot extends TimedRobot { private final Joystick m_stick = new Joystick(0); // Solenoid corresponds to a single solenoid. - private final Solenoid m_solenoid = new Solenoid(PneumaticsModuleType.CTREPCM, 0); + // In this case, it's connected to channel 0 of a PH with the default CAN ID. + private final Solenoid m_solenoid = new Solenoid(PneumaticsModuleType.REVPH, 0); // DoubleSolenoid corresponds to a double solenoid. + // In this case, it's connected to channels 1 and 2 of a PH with the default CAN ID. private final DoubleSolenoid m_doubleSolenoid = - new DoubleSolenoid(PneumaticsModuleType.CTREPCM, 1, 2); + new DoubleSolenoid(PneumaticsModuleType.REVPH, 1, 2); - private static final int kSolenoidButton = 1; - private static final int kDoubleSolenoidForward = 2; - private static final int kDoubleSolenoidReverse = 3; + // Compressor connected to a PH with a default CAN ID (1) + private final Compressor m_compressor = new Compressor(PneumaticsModuleType.REVPH); + static final int kSolenoidButton = 1; + static final int kDoubleSolenoidForwardButton = 2; + static final int kDoubleSolenoidReverseButton = 3; + static final int kCompressorButton = 4; + + @Override + public void robotInit() { + // Publish elements to shuffleboard. + ShuffleboardTab tab = Shuffleboard.getTab("Pneumatics"); + tab.add("Single Solenoid", m_solenoid); + tab.add("Double Solenoid", m_doubleSolenoid); + tab.add("Compressor", m_compressor); + + // Also publish some raw data + tab.addDouble( + "PH Pressure [PSI]", + () -> { + // Get the pressure (in PSI) from the analog sensor connected to the PH. + // This function is supported only on the PH! + // On a PCM, this function will return 0. + return m_compressor.getPressure(); + }); + tab.addDouble( + "Compressor Current", + () -> { + // Get compressor current draw. + return m_compressor.getCurrent(); + }); + tab.addBoolean( + "Compressor Active", + () -> { + // Get whether the compressor is active. + return m_compressor.isEnabled(); + }); + tab.addBoolean( + "Pressure Switch", + () -> { + // Get the digital pressure switch connected to the PCM/PH. + // The switch is open when the pressure is over ~120 PSI. + return m_compressor.getPressureSwitchValue(); + }); + } + + @SuppressWarnings("PMD.UnconditionalIfStatement") @Override public void teleopPeriodic() { /* * The output of GetRawButton is true/false depending on whether * the button is pressed; Set takes a boolean for whether - * to use the default (false) channel or the other (true). + * to retract the solenoid (false) or extend it (true). */ m_solenoid.set(m_stick.getRawButton(kSolenoidButton)); /* - * In order to set the double solenoid, if just one button - * is pressed, set the solenoid to correspond to that button. - * If both are pressed, set the solenoid will be set to Forwards. + * GetRawButtonPressed will only return true once per press. + * If a button is pressed, set the solenoid to the respective channel. */ - if (m_stick.getRawButton(kDoubleSolenoidForward)) { + if (m_stick.getRawButtonPressed(kDoubleSolenoidForwardButton)) { m_doubleSolenoid.set(DoubleSolenoid.Value.kForward); - } else if (m_stick.getRawButton(kDoubleSolenoidReverse)) { + } else if (m_stick.getRawButtonPressed(kDoubleSolenoidReverseButton)) { m_doubleSolenoid.set(DoubleSolenoid.Value.kReverse); } + + // On button press, toggle the compressor. + if (m_stick.getRawButtonPressed(kCompressorButton)) { + // Check whether the compressor is currently enabled. + boolean isCompressorEnabled = m_compressor.isEnabled(); + if (isCompressorEnabled) { + // Disable closed-loop mode on the compressor. + m_compressor.disable(); + } else { + // Change the if statements to select the closed-loop you want to use: + if (false) { + // Enable closed-loop mode based on the digital pressure switch connected to the PCM/PH. + // The switch is open when the pressure is over ~120 PSI. + m_compressor.enableDigital(); + } + if (true) { + // Enable closed-loop mode based on the analog pressure sensor connected to the PH. + // The compressor will run while the pressure reported by the sensor is in the + // specified range ([70 PSI, 120 PSI] in this example). + // Analog mode exists only on the PH! On the PCM, this enables digital control. + m_compressor.enableAnalog(70, 120); + } + if (false) { + // Enable closed-loop mode based on both the digital pressure switch AND the analog + // pressure sensor connected to the PH. + // The compressor will run while the pressure reported by the analog sensor is in the + // specified range ([70 PSI, 120 PSI] in this example) AND the digital switch reports + // that the system is not full. + // Hybrid mode exists only on the PH! On the PCM, this enables digital control. + m_compressor.enableHybrid(70, 120); + } + } + } } }