C++ Compressor Problem

Guys, new to programming the code for pneumatic and based on the documentation that I’m reading the below should get the compressor to turn on but it is not even though we can manually make things work.

#include "Robot.h"

#include <iostream>

#include <math.h>

#include <ctre/Phoenix.h>

#include <frc/WPILib.h>

#include <frc/Compressor.h>

#include <frc/Solenoid.h>

#include <frc/smartdashboard/SmartDashboard.h>

frc::Compressor *m_compressor;

frc::Joystick js1{0}; // Driver’s Controller

void Robot::RobotInit() {

m_chooser.SetDefaultOption(kAutoNameDefault, kAutoNameDefault);

m_chooser.AddOption(kAutoNameCustom, kAutoNameCustom);

frc::SmartDashboard::PutData(“Auto Modes”, &m_chooser);

m_compressor = new frc::Compressor(1);

m_compressor->Start();

}

void Robot::RobotPeriodic() {}

void Robot::AutonomousInit() {

m_autoSelected = m_chooser.GetSelected();

// m_autoSelected = SmartDashboard::GetString(“Auto Selector”,

// kAutoNameDefault);

std::cout << "Auto selected: " << m_autoSelected << std::endl;

if (m_autoSelected == kAutoNameCustom) {

// Custom Auto goes here

} else {

// Default Auto goes here

}

}

void Robot::AutonomousPeriodic() {

if (m_autoSelected == kAutoNameCustom) {

// Custom Auto goes here

} else {

// Default Auto goes here

}

}

void Robot::TeleopInit() {

}

void Robot::TeleopPeriodic() {

if (js1.GetRawButton(1))

{

m_compressor->SetClosedLoopControl(true);

bool enabled = m_compressor->Enabled();

bool pressureSwitch = m_compressor->GetPressureSwitchValue();

double current = m_compressor->GetCompressorCurrent();

std::cout << "Compressor Current: " << current << std::endl;

std::cout << "Pressure Switch: " << pressureSwitch << std::endl;

std::cout << "Starting Compressor " << std::endl;

}

else

{

m_compressor->Stop();

m_compressor->SetClosedLoopControl(false);

std::cout << "Stopping Compressor " << std::endl;

}

}

void Robot::TestPeriodic() {}

#ifndef RUNNING_FRC_TESTS

int main() { return frc::StartRobot<Robot>(); }

#endif

What do the current, pressure switch and enabled outputs say?

We recently had to debug our pneumatics and found out that we both had bad wiring to our presume switch (causing it to believe it was at pressure) and a sticky PCM fault (compressor was un-plugged while robot was on.

To fix the PCM sticky faults you can do m_compressor->ClearAllPCMStickyFaults(); in RobotInit().

Another note, your code has the compressor plugged into a PCM with ID 1, while they by default are imaged to ID 0.

Thank you for the reply, I will try the clear option when I get to the building in a few hours.

I was told the compressor is in pcm 2
The readout is 0 for both pressure and current.

Also within documentation it found I should be doing m_compressor = new frc::Compressor(1,1); but it only build with one number

Note that you do not need to create a Compressor object in order to use pneumatics. The compressor will automatically run if you create Solenoid objects. Creating a Compressor object is only required if you wish to programmatically force the PCM to stop running the compressor.

1 Like

Where did you read that? That would need to be fixed if it actually says that anywhere.

Saw it on screensteps but arguably it may have been an older page.

So if we have solenoids hooked up it will start the compressor and the compressor stops on it’s own?

The two argument constructor is for the cRIO, which still has instructions on the 2014 section of screensteps. It’s important to keep track of that.

Why are you stopping the compressor in autonomous init?

Honestly I’m not sure…

This is not our robot code but a small timed robot test to get the compressor and solenoid working.

so still having issues :frowning:

/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017-2018 FIRST. All Rights Reserved.                        */
/* Open Source Software - may be modified and shared by FRC teams. The code   */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project.                                                               */
/*----------------------------------------------------------------------------*/
#include "Robot.h"
#include 
#include 
#include 
#include 
#include 

frc::Solenoid *openGate;
frc::Solenoid *closeGate;
frc::Compressor *compressor;

frc::Joystick js1{0}; // Driver's Controller

void Robot::RobotInit() {
  m_chooser.SetDefaultOption(kAutoNameDefault, kAutoNameDefault);
  m_chooser.AddOption(kAutoNameCustom, kAutoNameCustom);
  frc::SmartDashboard::PutData("Auto Modes", &m_chooser);

  openGate = new frc::Solenoid(1);
  closeGate = new frc::Solenoid(2);
  compressor = new frc::Compressor(0);

  compressor->ClearAllPCMStickyFaults();
}

void Robot::RobotPeriodic() {}

void Robot::AutonomousInit() {
  m_autoSelected = m_chooser.GetSelected();
  // m_autoSelected = SmartDashboard::GetString("Auto Selector",
  //     kAutoNameDefault);
  std::cout << "Auto selected: " << m_autoSelected <Set(false);
  closeGate->Set(true);
}

void Robot::TeleopPeriodic() {
  if (js1.GetRawButton(1))
  {
        openGate->Set(true);
    closeGate->Set(false);

    bool enabled = compressor->Enabled();
    bool pressureSwitch = compressor->GetPressureSwitchValue();
    double current = compressor->GetCompressorCurrent();

    std::cout << "Compressor Current: " << current << std::endl;
    std::cout << "Pressure Switch: " << pressureSwitch << std::endl;
    std::cout << "Starting Compressor " <Set(false);
    closeGate->Set(true);
  }
}

void Robot::TestPeriodic() {}

#ifndef RUNNING_FRC_TESTS
int main() { return frc::StartRobot(); }
#endif

Getting 0 for both readouts

Yep, you don’t have to declare the Compressor. Please see FRC C++ Programming, p130 if you download the complete PDF doc, and specifically the last sentence:

The Pneumatics Control Module from Cross the Road Electronics allows for integrated closed loop control of a compressor. Creating any instance of a Solenoid or Double Solenoid object will enable the Compressor control on the corresponding PCM. The Compressor object is only needed if you want to have greater control over the compressor or query compressor status.

You can check the electrical operation of the pressure switch: Disconnect it from the PCM, and check the resistance across the two terminals of the switch (and polarity of the meter’s probes doesn’t matter in this case) with your multimeter, set to its resistance (ohms) scale. It should read zero ohms when there’s no pressure in the system, and infinite ohms when there’s full pressure, ~120 PSI.

Remember also there’s an LED on the PCM that shows when the PCM is sending power to the compressor: http://www.ctr-electronics.com/downloads/pdf/PCM%20User’s%20Guide.pdf

Did you change the CAN address of the PCM to 0?

Correct, but atleast on my team we do it anyways to make things easier to debug on the field (we do the same with the PDP too).

As to the specific issue, if the pressure switch returns zero then it sounds like it is working (ours had a connection issue and always returned 1). I’d advise downloading the Pheonix Tuner and seeing which CAN ID the PCM is set to, as you previously said it was on ID 1, but now are coding for ID 0.

Anyone having issues with the example for the solenoids not working?

I did get the compressor working, it turned out to be a bad PCM … hours of programming trials for nothing

Updated the code, it will turn on the compressor but the solenoid tests don’t seem to work

/*----------------------------------------------------------------------------*/

/* Copyright (c) 2017-2018 FIRST. All Rights Reserved. */

/* Open Source Software - may be modified and shared by FRC teams. The code */

/* must be accompanied by the FIRST BSD license file in the root directory of */

/* the project. */

/*----------------------------------------------------------------------------*/

#include "Robot.h"

#include <iostream>

#include <frc/smartdashboard/SmartDashboard.h>

#include <frc/Joystick.h>

#include <frc/TimedRobot.h>

#include <ctre/Phoenix.h>

#include <frc/Solenoid.h>

#include <frc/SolenoidBase.h>

#include <frc/DoubleSolenoid.h>

#include <frc/WPILib.h>

// Compressor Definitions - Start

frc::Compressor *compressor;

frc::Solenoid *solenoid0;

frc::Solenoid *solenoid1;

frc::DoubleSolenoid *doublesolenoid;

// Compressor Definitions - Stop

// Joystick Definitions - Start

frc::Joystick js1{0}; // Driver's Controller

frc::Joystick js2{1}; // Operator's Controller

// Joystick Definitions - Stop

// Logitech Gamepad F310 Controller Layout

int btnX = 1;

int btnA = 2;

int btnB = 3;

int btnY = 4;

int btnLB = 5;

int btnRB = 6;

int btnLT = 7;

int btnRT = 8;

int btnBack = 9;

int btnStart = 10;

int btnLToggle = 11;

int btnRToggle = 12;

void Robot::RobotInit() {

m_chooser.SetDefaultOption(kAutoNameDefault, kAutoNameDefault);

m_chooser.AddOption(kAutoNameCustom, kAutoNameCustom);

frc::SmartDashboard::PutData("Auto Modes", &m_chooser);

solenoid0 = new frc::Solenoid(0);

solenoid1 = new frc::Solenoid(1);

compressor = new frc::Compressor(2);

// DoubleSolenoid corresponds to a double solenoid.

doublesolenoid = new frc::DoubleSolenoid{1, 2};

compressor->ClearAllPCMStickyFaults();

compressor->SetClosedLoopControl(true);

}

/**

* This function is called every robot packet, no matter the mode. Use

* this for items like diagnostics that you want ran during disabled,

* autonomous, teleoperated and test.

*

* <p> This runs after the mode specific periodic functions, but before

* LiveWindow and SmartDashboard integrated updating.

*/

void Robot::RobotPeriodic() {}

/**

* This autonomous (along with the chooser code above) shows how to select

* between different autonomous modes using the dashboard. The sendable chooser

* code works with the Java SmartDashboard. If you prefer the LabVIEW Dashboard,

* remove all of the chooser code and uncomment the GetString line to get the

* auto name from the text box below the Gyro.

*

* You can add additional auto modes by adding additional comparisons to the

* if-else structure below with additional strings. If using the SendableChooser

* make sure to add them to the chooser code above as well.

*/

void Robot::AutonomousInit() {

m_autoSelected = m_chooser.GetSelected();

// m_autoSelected = SmartDashboard::GetString("Auto Selector",

// kAutoNameDefault);

std::cout << "Auto selected: " << m_autoSelected << std::endl;

if (m_autoSelected == kAutoNameCustom) {

// Custom Auto goes here

} else {

// Default Auto goes here

}

}

void Robot::AutonomousPeriodic() {

if (m_autoSelected == kAutoNameCustom) {

// Custom Auto goes here

} else {

// Default Auto goes here

}

}

void Robot::TeleopInit() {

compressor->SetClosedLoopControl(true);

}

void Robot::TeleopPeriodic() {

// Compressor Stats

bool enabled = compressor->Enabled();

bool pressureSwitch = compressor->GetPressureSwitchValue();

double current = compressor->GetCompressorCurrent();

std::cout << "Compressor Current: " << current << std::endl;

std::cout << "Pressure Switch: " << pressureSwitch << std::endl;

#pragma region Solenoid Test 1

if (js1.GetRawButton(btnLB))

{

solenoid0->Set(true);

solenoid1->Set(false);

// std::cout << "Solenoid 0 - Open" << std::endl;

std::cout << "Solenoid 0: " << solenoid0->Get() << std::endl;

std::cout << "Solenoid 1: " << solenoid1->Get() << std::endl;

}

else

{

solenoid0->Set(false);

solenoid1->Set(false);

// std::cout << "Solenoid 0 - Closed" << std::endl;

std::cout << "Solenoid 0: " << solenoid0->Get() << std::endl;

std::cout << "Solenoid 1: " << solenoid1->Get() << std::endl;

}

if (js1.GetRawButton(btnRB))

{

solenoid1->Set(true);

solenoid0->Set(false);

// std::cout << "Solenoid 1 - Open" << std::endl;

std::cout << "Solenoid 0: " << solenoid0->Get() << std::endl;

std::cout << "Solenoid 1: " << solenoid1->Get() << std::endl;

}

else

{

solenoid1->Set(false);

solenoid0->Set(false);

// std::cout << "Solenoid 1 - Closed" << std::endl;

std::cout << "Solenoid 0: " << solenoid0->Get() << std::endl;

std::cout << "Solenoid 1: " << solenoid1->Get() << std::endl;

}

#pragma endregion Solenoid Test 1

#pragma region Solenoid Test 2

solenoid0->Set(js1.GetRawButton(btnX));

std::cout << "Solenoid 0: " << solenoid0->Get() << std::endl;

/* 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 (js1.GetRawButton(btnA))

{

doublesolenoid->Set(frc::DoubleSolenoid::kForward);

std::cout << "Double Solenoid: " << doublesolenoid->Get() << std::endl;

}

else if (js1.GetRawButton(btnB))

{

doublesolenoid->Set(frc::DoubleSolenoid::kReverse);

std::cout << "Double Solenoid: " << doublesolenoid->Get() << std::endl;

}

else

{

doublesolenoid->Set(frc::DoubleSolenoid::kOff);

std::cout << "Double Solenoid: " << doublesolenoid->Get() << std::endl;

}

#pragma endregion Solenoid Test 2

}

void Robot::TestPeriodic() {}

#ifndef RUNNING_FRC_TESTS

int main() { return frc::StartRobot<Robot>(); }

#endif

Nevermind, changed the PCM controller for a second time and now we are working.