Robot for the 2025 Reefscape FRC Competition
Pneumatic systems operated on the power of compressed air. By channeling this compressed air through pipes it can be used to act on (i.e. push) and object. This compressed air can be used in conjuction with Pistons - basic cylinders which can be extended using this air.
Pistons have 2 basic states: open and close. To open them, air must be pushed through the bottom of the piston, which then pushes the piston up (and open). To close them, air must be pushed through the top of the piston, whih pushes it back down and closes it.
The top and bottom holes are connected via pipes to a double electronic valve (double solenoid). When switched to Forward the valve opens one part to air flow which pushes the piston open. When switched to Reverse the valve opens the other part to air flow whih pushes the piston close. When switched to Off the valve is completly closed and air does not flow to the piston.
The solenoids are connected to the Pneumatics Hub which can be controlled from the RobotRIO. It can instruct the solenoids open or close as we request. This is how we control the pistons.
Compressed air is held in Air Tanks (filled before each game) and also generated by a Compressor placed on the robot.
Controlling Pneumatics involves mostly controlling the Solenoids. Each solenoid can be controlled via the DoubleSolenoid
class. It has 2 identifiers (numbers indicaing the connection ports on the PH), the forwardIdentifier
indicates port for opening the valve into Forward mode and reverseIdentifier
indicates port for opening the valve into Reverse mode. Each double solenoid operates a single piston.
public class Robot extends TimedRobot {
private DoubleSolenoid solenoid;
@Override
public void robotInit() {
solenoid = new DoubleSolenoid(PneumaticsModuleType.REVPH, RobotMap.PISTON_FORWARD_CHANNEL, RobotMap.PISTON_REVERSE_CHANNEL);
}
@Override
public void teleopInit() {
// opens into Forward mode. Use kBackward for backward mode and kOff for closed.
solenoid.set(DoubleSolenoid.Value.kForward);
}
}
Limit switches are basic electronic switches that open or close electronic circuits based on outside information. We can use them to detect a boolean state, but what they detect exactly is not specific, as they can be used in many ways, but as the name suggests, they are generally used to provide a limit to a system, for example, we can use them to limit the motion of a motor: if the switch is closed, we stop the motor, if it is open we rotate the motor.
Generally, because switches are either open or closed, we can detect their state by connecting them into a circuit which connects to a digital input signal pin on the RoboRIO.
When the switch is closed, the circuit is closed and thus the voltage on the line is LOW. When it is open, the voltage on the line is HIGH (due to the pull-up resistor on the pin). So we can read this state using the DigitalInput class.
Switches have 2 kinds of configurations:
- Normally Open: in normally open mode, when the switch is not pressed, the circuit is open. And due to the pull-up resistor, the voltage will be HIGH on the pin. When it is pressed, the circuit is closed with resistance and thus the voltage level becomes LOW.
- Normally Closed: in normally closed mode, when the switch is not pressed, the circuit is closed with resistance so the voltage is LOW. When it is pressed, the circuit is open and voltage becomes high.
public class Robot extends TimedRobot {
private DigitalInput input;
@Override
public void robotInit() {
input = new DigitalInput(1);
}
...
@Override
public void teleopPeriodic() {
boolean isHigh = input.get();
if (isHigh) {
// the voltage level is HIGH on the pin
// so in normally-open, this means the switch isn't pressed
} else {
// the voltage level is LOW on the pin
// so in normally-open, this means the switch is pressed.
}
}
...
}
Example Code for initializing with factory reset
public class Robot extends TimedRobot {
private SparkMax motor;
@Override
public void robotInit() {
motor = new SparkMax(RobotMap.MOTOR_IDENTIFIER, SparkLowLevel.MotorType.kBrushless);
SparkMaxConfig config = new SparkMaxConfig();
motor.configure(config, SparkBase.ResetMode.kNoResetSafeParameters, SparkBase.PersistMode.kNoPersistParameters);
}
}
The robot is divided into 3 large parts: the drive system, components for collecting and placing Coral and components for collecting and placing Alge. These can be further subdivided into more specific parts.
SHALEV DO ME
SHALEV DO ME
SHALEV DO ME
In this phase we'll be implementing the basic subsystems of the robot. This is the base of the robot from which we can do the rest. For each subsystem, please read the description and specs of the subsystems to understand how it works.
The CoralElevator
operates the elevator for extending the Coral components for higher reach. It is a basic Pneumatic system operated by 2 pistons which are in turn. Opening both pistons extends
the elevator up, retracting them lowers the elevator. These are operated each by a DoubleSolenoid
with 2 limits switches indicating if the elevator is raised or lowered (one for raised one for lowered).
- Create the subsystem
- Create and initialize the 2 solenoids
- Create and initialize the 2 limit switches
- Implement
public boolean isRaised()
method- returns
true
if the upper limit switch indicates the elevator is raised,false
otherwise - query the limit switch with
.get
- remember that the limit switch is normally open and so
get
returnstrue
when not pressed
- returns
- Implement
public boolean isLowered()
method- returns
true
if the lower limit switch indicates the elevator is lowered,false
otherwise - query the limit switch with
.get
- remember that the limit switch is normally open and so
get
returnstrue
when not pressed
- returns
- Implement
public void raise()
method- extends both pistons
- use
set(DoubleSolenoid.Value.kForward)
on both solenoids
- Implement
public void lower()
method- retracts both pistons
- use
set(DoubleSolenoid.Value.kReverse)
on both solenoids
- Implement
public void stop()
method- close both valves
- use
set(DoubleSolenoid.Value.kOff)
on both solenoids
- Add
periodic
method which prints the values fromisRaised
isLowered
Implement Basic Operational Commands for the subsystem:
RaiseCoralElevator
- runs on
CoralElevator
subsystem - on
initialize
callraise
to start raising system - on
execute
do nothing - on
isFinished
returntrue
ifisRaised
istrue
,false
otherwise - on
end
do nothing
- runs on
LowerCoralElevator
- runs on
LowerElevator
subsystem - on
initialize
calllower
to start lowering system - on
execute
do nothing - on
isFinished
returntrue
ifisLowered
istrue
,false
otherwise - on
end
do nothing
- runs on
The CoralArm
operates a two-phased arm on top of the CoralElevator
. This arm mounts the Coral gripper and as such manouvers it around. It is operated by 2 Pistons and has two positions. The pistons are operated each by a DoubleSolenoid
with 2 limits switches indicating if the position of this arm.
- Create the subsystem
- Create and initialize the 2 solenoids
- Create and initialize the 2 limit switches
- Implement
public boolean isExtended()
method- returns
true
if the limit switch on the extended position indicates the arm is extended,false
otherwise - query the limit switch with
.get
- remember that the limit switch is normally open and so
get
returnstrue
when not pressed
- returns
- Implement
public boolean isRetracted()
method- returns
true
if the limit switch on the retracted position indicates the arm is retracted,false
otherwise - query the limit switch with
.get
- remember that the limit switch is normally open and so
get
returnstrue
when not pressed
- returns
- Implement
public void extend()
method- extends both pistons
- use
set(DoubleSolenoid.Value.kForward)
on both solenoids
- Implement
public void retract()
method- retracts both pistons
- use
set(DoubleSolenoid.Value.kReverse)
on both solenoids
- Implement
public void stop()
method- close both valves
- use
set(DoubleSolenoid.Value.kOff)
on both solenoids
- Add
periodic
method which prints the values fromisExtended
isRetracted
Implement Basic Operational Commands for the subsystem:
ExtendedCoralArm
- runs on
CoralArm
subsystem - on
initialize
callextend
to start extending system - on
execute
do nothing - on
isFinished
returntrue
ifisExtended
istrue
,false
otherwise - on
end
do nothing
- runs on
RetractCoralArm
- runs on
CoralArm
subsystem - on
initialize
callretract
to start retracting system - on
execute
do nothing - on
isFinished
returntrue
ifisRetracted
istrue
,false
otherwise - on
end
do nothing
- runs on
The CoralGripper
sits on top of the CoralArm
and is used to collect and hold the Coral pieces. The gripper uses two wheels to grip onto the Coral, collect it and hold it in place. A single NEO 550 and SparkMax motor controller operate this system. A limit switch is placed on the system to indicate if a Coral is present.
- Create the subsystem
- Create and initialize the SparkMax motor controller
- make sure to reset the motor controller settings
- Create and initialize the limit switch
- Implement
public boolean hasCoral()
method- returns
true
if the limit switch indicates a Coral is in the system,false
otherwise - query the limit switch with
.get
- remember that the limit switch is normally open and so
get
returnstrue
when not pressed
- returns
- Implement
public void rotateCollect()
method- rotate the motor at a constant speed for collecting a Coral
- use the speed value
0.8
- Implement
public void rotateRelease()
method- rotate the motor at a constant speed for release a Coral
- use the speed value
-0.5
- Implement
public void rotateHold()
method- rotate the motor at a constant speed for holding a collected Coral in place
- use the speed value
0.2
- Implement
public void stop()
method- stops the motor
- Add
periodic
method which prints the values fromhasCoral
Implement Basic Operational Commands for the subsystem:
CollectCoral
- runs on
CoralGripper
subsystem - on
initialize
callrotateCollect
to start rotating - on
execute
do nothing - on
isFinished
returntrue
ifhasCoral
istrue
,false
otherwise - on
end
do nothing
- runs on
ReleaseCoral
- runs on
CoralGripper
subsystem - on
initialize
callrotateRelease
to start rotating - on
execute
do nothing - on
isFinished
returntrue
ifhasCoral
isfalse
,false
otherwise - on
end
do nothing
- runs on
HoldCoral
- runs on
CoralGripper
subsystem - on
initialize
callrotateHold
to start retracting system - on
execute
do nothing - on
isFinished
returnfalse
- on
end
do nothing
- runs on
The AlgaeArm
operates a two-phased arm on top of the chassis. This arm mounts the Algae gripper and as such manouvers it around. It is operated by 2 Pistons and has two positions. The pistons are operated each by a DoubleSolenoid
with 2 limits switches indicating if the position of this arm.
- Create the subsystem
- Create and initialize the 2 solenoids
- Create and initialize the 2 limit switches
- Implement
public boolean isExtended()
method- returns
true
if the limit switch on the extended position indicates the arm is extended,false
otherwise - query the limit switch with
.get
- remember that the limit switch is normally open and so
get
returnstrue
when not pressed
- returns
- Implement
public boolean isRetracted()
method- returns
true
if the limit switch on the retracted position indicates the arm is retracted,false
otherwise - query the limit switch with
.get
- remember that the limit switch is normally open and so
get
returnstrue
when not pressed
- returns
- Implement
public void extend()
method- extends both pistons
- use
set(DoubleSolenoid.Value.kForward)
on both solenoids
- Implement
public void retract()
method- retracts both pistons
- use
set(DoubleSolenoid.Value.kReverse)
on both solenoids
- Implement
public void stop()
method- close both valves
- use
set(DoubleSolenoid.Value.kOff)
on both solenoids
- Add
periodic
method which prints the values fromisExtended
isRetracted
Implement Basic Operational Commands for the subsystem:
ExtendedAlgaeArm
- runs on
AlgaeArm
subsystem - on
initialize
callextend
to start extending system - on
execute
do nothing - on
isFinished
returntrue
ifisExtended
istrue
,false
otherwise - on
end
do nothing
- runs on
RetractAlgaeArm
- runs on
AlgaeArm
subsystem - on
initialize
callretract
to start retracting system - on
execute
do nothing - on
isFinished
returntrue
ifisRetracted
istrue
,false
otherwise - on
end
do nothing
- runs on
The AlgaeGripper
sits on top of the AlgaeArm
and is used to collect and hold the Algae pieces. The gripper uses two wheels to grip onto the Algae, collect it and hold it in place. A single NEO 550 and SparkMax motor controller operate this system. A limit switch is placed on the system to indicate if a Algae is present.
- Create the subsystem
- Create and initialize the SparkMax motor controller
- make sure to reset the motor controller settings
- Create and initialize the limit switch
- Implement
public boolean hasAlgae()
method- returns
true
if the limit switch indicates a Algae is in the system,false
otherwise - query the limit switch with
.get
- remember that the limit switch is normally open and so
get
returnstrue
when not pressed
- returns
- Implement
public void rotateCollect()
method- rotate the motor at a constant speed for collecting a Algae
- use the speed value
0.8
- Implement
public void rotateRelease()
method- rotate the motor at a constant speed for release a Algae
- use the speed value
-0.5
- Implement
public void rotateHold()
method- rotate the motor at a constant speed for holding a collected Algae in place
- use the speed value
0.2
- Implement
public void stop()
method- stops the motor
- Add
periodic
method which prints the values fromhasAlgae
Implement Basic Operational Commands for the subsystem:
CollectAlgae
- runs on
AlgaeGripper
subsystem - on
initialize
callrotateCollect
to start rotating - on
execute
do nothing - on
isFinished
returntrue
ifhasAlgae
istrue
,false
otherwise - on
end
do nothing
- runs on
ReleaseAlgae
- runs on
AlgaeGripper
subsystem - on
initialize
callrotateRelease
to start rotating - on
execute
do nothing - on
isFinished
returntrue
ifhasAlgae
isfalse
,false
otherwise - on
end
do nothing
- runs on
HoldAlgae
- runs on
AlgaeGripper
subsystem - on
initialize
callrotateHold
to start rotating - on
execute
do nothing - on
isFinished
returnfalse
- on
end
do nothing
- runs on
The project has several pre-made run configurations for your convenience. These configurations will be loaded automatically when you open the project.
To use a run configuration, select it from the configurations drop down box and click on run
Select the Robot Deploy
run configuration and click on run. This will build and deploy the code to the robot.
Select the Robot Deploy Debug
run configuration to deploy the code with debugger enabled.
To attach a debugger, after a successful deployment (i.e. wait for the deployment to finish successfully), select and run the RoboRIO Debugger
(run with debug, the bug button, not the run button).
Select the Simulate
run configuration and click on run. This will build and run the code in the simulator.
Select the Simulate Debug
run configuration and click on run. This will run the simulation with debugger enabled.
Once the console prints Listening for transport dt_socket at address
select and run the Simulation Debugger
run configuration (run with debug, the bug button, not the run button).
Note that doing all these will run two configuration simultaneously. This is fine, but when you wish to stop the simulation you will need to stop both the simulation and the debugger.