Made for FRC Team 972: Iron Claw, in Los Gatos High School, CA.
Authored by @whackamadoodle3000, @me1234q , TsarF
Guides
Motors
Joysticks
Encoders
Built-in Accelerometer
NavX
Solenoids
Double Solenoids
Compressors
Limit Switches
Start Programming On Your Computer
Examples
Make Motor Spin Based on Joystick Input
Arcade Drive
Tank Drive
PID Example Snippet
Toggling Double Solenoids
Motors are one of the most common actuators and provide rotational motion. When given power, the motor will spin with speed proportional to the voltage and torque proportional to the current. They are controlled with a talon.
- To import
- To import TalonSRX
import com.ctre.phoenix.motorcontrol.can.*;
- To import control modes
import com.ctre.phoenix.motorcontrol.ControlMode;
- To import TalonSRX
- To initialize
- To initialize motor
WPI_TalonSRX Motor = new WPI_TalonSRX(6);
- To initialize automatic deadband
Motor.enableDeadbandElimination(true);
- To initialize motor
- To use (with various control modes)
- Set motor absolute power
Motor.set(ControlMode.PercentOutput, value);
with value as double between -1 and 1 - Set motor to follow another
Motor.set(ControlMode.Follower, value);
with value as the id of the other talon
- Set motor absolute power
- Documentation: http://www.ctr-electronics.com/downloads/api/java/html/classcom_1_1ctre_1_1phoenix_1_1motorcontrol_1_1can_1_1_w_p_i___talon_s_r_x.html
- To import
- To import SparkMAX
import com.revrobotics.CANSparkMax;
- To import motor Types
import com.revrobotics.CANSparkMaxLowLevel.MotorType;
- To import SparkMAX
- To initialize
- To intialize SparkMAX controller
CANSparkMax <name> = new CANSparkMax(<MotorID (setup with REV Robotics SparkMAX client)>, <MotorType.kBrushless OR MotorType.kBrushed>);
- There are multiple control modes for different motors because some motors are BRUSHED and some are BRUSHLESS you can tell if it is brushed or brushless by counting the wires going into the motor from the controller
- 3 wires: Brushless
- 2 wires: Brushed
- NOTE Some motors, like NEO motors, have 3 wires AND what may look like a 4th wire, which is actually the encoder wire, inside the protective sleeve, there are 6 more wires. DO NOT BE CONFUSED BY THAT.
- There are multiple control modes for different motors because some motors are BRUSHED and some are BRUSHLESS you can tell if it is brushed or brushless by counting the wires going into the motor from the controller
- To intialize SparkMAX controller
- To use
- To RUN the motor
CANSparkMax.set(<speed 0.0 - 1.0>);
- Set Follower
CANSparkMax.follow(<motor to follow>)
orCANSparkMax.follow(<motor to follow>, <inverted? true:false>);
- Encoder
CANSparkMax.getEncoder();
- Get velocity
CANSparkMax.getEncoder().getVelocity();
- Get position
CANSparkMax.getEncoder().getPosotion();
- SET position
CANSparkMax.getEncoder().setPosition(<position (double)>); //used for aeroid out the encoders, and resetting field position
- Get velocity
- To RUN the motor
Joysticks are (misleadingly) an umbrella term for all user input devices, including gamepads, joysticks, etc. Joystick objects can receive joystick and button input.
- To import
import edu.wpi.first.wpilibj.Joystick;
- To initialize
Joystick Joy = new Joystick(0);
- To use
- To get axis values
Joy.getRawAxis(0);
with value between -1 and 1 - To get button values
Joy.getRawButton(0);
with boolean output - To get angle in radians
Math.atan2(xAxis, -yAxis)
- To get angle in degrees
Math.atan2(xAxis, -yAxis) * 180 / Math.PI
- To get angle in degrees
- To get magnitude
Math.sqrt(xAxis*xAxis + yAxis*yAxis);
- To get axis values
- Documentation: http://first.wpi.edu/FRC/roborio/release/docs/java/edu/wpi/first/wpilibj/Joystick.html
Encoders are used for measuring rotation. This is done through counting the number of "clicks", which increments or decrements with every slight rotation.
- To import
import edu.wpi.first.wpilibj.Encoder
- To initialize
Encoder sampleEncoder = new Encoder(0, 1, false, Encoder.EncodingType.k4X);
- To set max period (secs) without clicks before it is considered at rest
sampleEncoder.setMaxPeriod(.1);
- Minimum rate (rotation/time) before device is stopped
sampleEncoder.setMinRate(10);
- How much distance is traveled every encoder pulse
sampleEncoder.setDistancePerPulse(5);
- Reverse the direction encoder counts
sampleEncoder.setReverseDirection(true);
- How many samples to take (1-127) when determining the period
sampleEncoder.setSamplesToAverage(7);
- To set max period (secs) without clicks before it is considered at rest
- To use
- To get count of clicks
int count = sampleEncoder.get();
- To get distance
double distance = sampleEncoder.getDistance();
- To get period between clicks
double period = sampleEncoder.getPeriod();
- To get speed
double rate = sampleEncoder.getRate();
- To get current direction
boolean direction = sampleEncoder.getDirection();
- To see if the encoder is stopped turning
boolean stopped = sampleEncoder.getStopped();
- To get count of clicks
- Documentation: http://first.wpi.edu/FRC/roborio/release/docs/java/edu/wpi/first/wpilibj/Encoder.html
- More info: https://wpilib.screenstepslive.com/s/currentCS/m/java/l/599717-encoders-measuring-rotation-of-a-wheel-or-other-shaft
These encoders function the same as external encoders, but are connected to the talon's encoder port and thus can be directly accessed from the talon object.
- To import
import com.ctre.phoenix.motorcontrol.FeedbackDevice;
- To initialize
talon.configSelectedFeedbackSensor(FeedbackDevice.CTRE_MagEncoder_Relative, 0, 100);
- To use
talon.getSensorCollection().getQuadraturePosition();
talon.getSensorCollection().getQuadratureVelocity();
- Documentation: http://www.ctr-electronics.com/downloads/api/java/html/classcom_1_1ctre_1_1phoenix_1_1motorcontrol_1_1_sensor_collection.html
This is the RoboRio's built-in accelerometer. It allows you to get the acceleration in the x, y, and z directions.
- To import
import edu.wpi.first.wpilibj.BuiltInAccelerometer;
- To initialize
BuiltInAccelerometer accel = new BuiltInAccelerometer();
- To use
- Get x acceleration
accel.getX()
- Get y acceleration
accel.getY()
- Get z acceleration
accel.getZ()
- Get x acceleration
- Documentation: http://first.wpi.edu/FRC/roborio/release/docs/java/edu/wpi/first/wpilibj/BuiltInAccelerometer.html
The NavX gives a variety of information on the robot state, including orientation, velocity, acceleration, position, and more.
- To import
import com.kauailabs.navx.frc.AHRS;
import edu.wpi.first.wpilibj.SPI;
or I2C
- To initialize
- If mounted on RoboRIO
AHRS ahrs = new AHRS(SPI.Port.kMXP);
- If mounted elsewhere
AHRS ahrs = new AHRS(I2C.Port.kMXP);
- If mounted on RoboRIO
- To use
- Orientation Data
- To get heading
ahrs.getAngle()
- To get yaw
ahrs.getYaw()
(-180 to 180 degrees) - To get pitch
ahrs.getPitch()
(-180 to 180 degrees) - To get roll
ahrs.getRoll()
- To get compass data
ahrs.getCompassHeading()
(0 to 360)
- To get heading
- Velocity Data in Meters/Sec
- Velocity in x direction
ahrs.getVelocityX()
- Velocity in y direction
ahrs.getVelocityY()
- Velocity in z direction
ahrs.getVelocityZ()
- Rate of yaw (turning)
ahrs.getRate()
- Velocity in x direction
- Acceleration Data in g-force
- Acceleration in x direction
ahrs.getWorldLinearAccelX()
- Acceleration in y direction
ahrs.getWorldLinearAccelY()
- Acceleration in z direction
ahrs.getWorldLinearAccelZ()
- Acceleration in x direction
- Distance/Displacement Data in meters
- Displacement x
ahrs.getDisplacementX()
- Displacement y
ahrs.getDisplacementY()
- Displacement z
ahrs.getDisplacementZ()
- Displacement x
- Pressure and Temperature data
- Barometric Pressure in millibars
ahrs.getBarometricPressure()
- Temperature in Celsius
ahrs.getTempC()
- Barometric Pressure in millibars
- Boolean Motion Data
- To see if it is rotating
ahrs.isRotating()
- To see if it is moving
ahrs.isMoving()
- To see if it is rotating
- Reset
- To reset measurements for the yaw gyro
ahrs.reset()
- To zero yaw gyro
ahrs.zeroYaw()
(tell it what forward mean) - To reset displatement distances
ahrs.resetDisplacement()
- To reset measurements for the yaw gyro
- Board Info
- To get update rate
ahrs.getActualUpdateRate()
- Check if it is connected
ahrs.isConnected()
- To get update rate
- Orientation Data
- Documentation: https://www.kauailabs.com/public_files/navx-mxp/apidocs/java/com/kauailabs/navx/frc/AHRS.html
Solenoids are the most often used actuator for linear motion. Single acting Solenoids extend by increasing the air pressure inside a piston. Double Solenoids are recommended, as their have two channels, allowing them to more easily switch between extended and retracted position.
- To import
import edu.wpi.first.wpilibj.Solenoid;
- To initialize
Solenoid solenoid = new Solenoid(1)
- To use
- To turn on
solenoid.set(true)
- To turn off
solenoid.set(false)
- To get solenoid state in boolean
solenoid.get()
- To turn on
- Documentation: http://first.wpi.edu/FRC/roborio/release/docs/java/edu/wpi/first/wpilibj/Solenoid.html
These are similar to single acting solenoids, but have a second channel allowing them to revert to their original position without the need of an external force.
- To import
import edu.wpi.first.wpilibj.DoubleSolenoid;
- To initialize
DoubleSolenoid doubleSolenoid = new DoubleSolenoid(forwardchannel, reversechannel);
- To use
- To block all pressure
doubleSolenoid.set(DoubleSolenoid.Value.kOff);
- To put pressure in forward channel
doubleSolenoid.set(DoubleSolenoid.Value.kForward);
- To put pressure in reverse channel
doubleSolenoid.set(DoubleSolenoid.Value.kReverse);
- To block all pressure
- Documentation: http://first.wpi.edu/FRC/roborio/release/docs/java/edu/wpi/first/wpilibj/DoubleSolenoid.html
Compressors are used for compressing air. They are need for any pneumatics, as they need air at a high pressure to function.
- To import
import edu.wpi.first.wpilibj.Compressor;
- To initialize
Compressor c = new Compressor(40);
- To control
- To toggle closed loop control (goes up until maximum PSI)
c.setClosedLoopControl(boolean);
- To turn on
c.start();
- To turn off
c.stop();
- To toggle closed loop control (goes up until maximum PSI)
- Getting information
- To get if the pressure is low in boolean
c.getPressureSwitchValue()
- To get the current being consumed in amps in double
c.getCompressorCurrent()
- To check if closed loop control is on
c.getClosedLoopControl()
- To get if the pressure is low in boolean
- Getting fault/error information
- Check if compressor is disabled because current is too high
c.getCompressorCurrentTooHighFault()
- Check if the compressor is disabled because output is shorted
c.getCompressorShortedFault()
- Check if compressor is is not connected/not drawing enough current
c.getCompressorNotConnectedFault()
- Check if compressor is disabled because current is too high
- Documentation: http://first.wpi.edu/FRC/roborio/beta/docs/java/edu/wpi/first/wpilibj/Compressor.html
Limit switches are devices that mechanically prevent an actuator from extending a certain predetermined position.
- To import
import edu.wpi.first.wpilibj.DigitalInput;
- To initialize
DigitalInput limitSwitch = new DigitalInput(1);
- To get value
limitSwitch.get()
(boolean) - Documentation: http://first.wpi.edu/FRC/roborio/beta/docs/java/edu/wpi/first/wpilibj/DigitalInput.html
Here you can Install Git Desktop or Git Bash, whichever one you prefer.
- Download link: link
- Run the installer
- Make sure
Add to PATH
option is selected
- Download the installer from this link
- Run the installer, make sure
Add to PATH
option is selected - Thats it
Python is usually used for computer vision stuff, it is very useful for automatic allignment
- Download Python 3 from here: link
- Run the Installer
- Ensure the
Add to PATH
option is selected, otherwise it will not work - Ensure everything is installed correctly by running
python
orpython3
in the command line - If an interactive python inveronment opens, you are good to go
Installing OpenCV package for python
- Open the command line once again and run
python -m pip install
if that fails, then runpy -m pip install
- Wait for it to install, accept any warning/messages
This IDE is different from the others as it has integrated WPI lib and vendor library manage for easier installation of new libraries for new devices.
- You want to download the installer: link
- Extract the files to any folder of you choise and run the installer file (.msi or .exe)
- In the installer, make sure it is installing a NEW version of VS CODE
- wait for the installation to finish
- Configure your settings as you wish
- Configure the team number to 972
This toolsuite is often used for configuring Driver Station dashboards, testing camera feed and configuring CAN devices
- Get the installer zip file from here: link
- Run the installer, it will install the following: Phoenix Tuner, Smart Dashboard
This one comes with the Driver Station and RoboRIO Imaging Tool
- Go to the following link
- Click on the download link to download the latest update suite
- Run the installers, login with the email:
[email protected]
and password:garyk
This application is used for configuring SparkMAX motor controllers, updating their firmware and running motors for testing
- Go to the download link
- Run the installer
Used for controlling the SparkMAX motors
- In FRC VS CODE press
ctrl + shift + p
to open the terminal - Type in
Manage Vendor Libraries
- Give it this link: https://www.revrobotics.com/content/sw/max/sdk/REVRobotics.json
- Press enter
- Recompile to ensure library was installed correctly
NOTE: SOME OF THE INSTALLERS ARE DOWNLOADED AS .zip
FILES WHICH YOU NEED TO EXTRACT TO INSTALL PROPERLY
package org.usfirst.frc.team972.robot;
import com.ctre.phoenix.motorcontrol.can.*;
import edu.wpi.first.wpilibj.IterativeRobot;
import edu.wpi.first.wpilibj.Joystick;
public class Robot extends IterativeRobot {
WPI_TalonSRX motor = new WPI_TalonSRX(6); //initialize motor
Joystick joy = new Joystick(0); //initialize joystick (to find number, check driver station)
double powerMultiplier = 0.7; //scales down motor power
public void robotInit() {
//This function is run when the robot is first started up
}
public void teleopPeriodic() {
//This function is called periodically during teleoperated control
double joystickValue = joy.getRawAxis(1); //find axis number in driver station
System.out.println("Joy: " + joystickValue);
Motor.set(joystickValue*powerMultiplier); //scale down by powerMultiplier
}
}
package org.usfirst.frc.team972.robot;
import com.ctre.phoenix.motorcontrol.can.*;
import edu.wpi.first.wpilibj.IterativeRobot;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.drive.DifferentialDrive;
public class Robot extends IterativeRobot {
/* talons for arcade drive */
WPI_TalonSRX _frontLeftMotor = new WPI_TalonSRX(6);
WPI_TalonSRX _frontRightMotor = new WPI_TalonSRX(2);
/* extra talons and victors for six motor drives */
WPI_TalonSRX _leftSlave1 = new WPI_TalonSRX(5);
WPI_VictorSPX _rightSlave1 = new WPI_VictorSPX(7);
WPI_TalonSRX _leftSlave2 = new WPI_TalonSRX(4);
WPI_VictorSPX _rightSlave2 = new WPI_VictorSPX(17);
DifferentialDrive _drive = new DifferentialDrive(_frontLeftMotor, _frontRightMotor);
Joystick _joy = new Joystick(0);
/**
* This function is run when the robot is first started up and should be
* used for any initialization code.
*/
public void robotInit() {
/*
* take our extra talons and just have them follow the Talons updated in
* arcadeDrive
*/
_leftSlave1.follow(_frontLeftMotor);
_leftSlave2.follow(_frontLeftMotor);
_rightSlave1.follow(_frontRightMotor);
_rightSlave2.follow(_frontRightMotor);
/* drive robot forward and make sure all
* motors spin the correct way.
* Toggle booleans accordingly.... */
_frontLeftMotor.setInverted(false);
_leftSlave1.setInverted(false);
_leftSlave2.setInverted(false);
_frontRightMotor.setInverted(false);
_rightSlave1.setInverted(false);
_rightSlave2.setInverted(false);
}
/**
* This function is called periodically during operator control
*/
public void teleopPeriodic() {
double forward = -1.0 * _joy.getY();
/* sign this so right is positive. */
double turn = +1.0 * _joy.getZ();
/* deadband */
if (Math.abs(forward) < 0.10) {
/* within 10% joystick, make it zero */
forward = 0;
}
if (Math.abs(turn) < 0.10) {
/* within 10% joystick, make it zero */
turn = 0;
}
/* print the joystick values to sign them, comment
* out this line after checking the joystick directions. */
System.out.println("JoyY:" + forward + " turn:" + turn );
/* drive the robot, when driving forward one side will be red.
* This is because DifferentialDrive assumes
* one side must be negative */
_drive.tankDrive(forward, turn);
}
}
package org.usfirst.frc.team972.robot;
import com.ctre.phoenix.motorcontrol.can.*;
import edu.wpi.first.wpilibj.IterativeRobot;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.drive.DifferentialDrive;
public class Robot extends IterativeRobot {
/* talons for arcade drive */
WPI_TalonSRX _frontLeftMotor = new WPI_TalonSRX(6);
WPI_TalonSRX _frontRightMotor = new WPI_TalonSRX(2);
/* extra talons and victors for six motor drives */
WPI_TalonSRX _leftSlave1 = new WPI_TalonSRX(5);
WPI_VictorSPX _rightSlave1 = new WPI_VictorSPX(7);
WPI_TalonSRX _leftSlave2 = new WPI_TalonSRX(4);
WPI_VictorSPX _rightSlave2 = new WPI_VictorSPX(17);
DifferentialDrive _drive = new DifferentialDrive(_frontLeftMotor, _frontRightMotor);
Joystick leftJoy = new Joystick(0);
Joystick rightJoy = new Joystick(1);
//This function is run when the robot is first started up and should be used for any initialization code.
public void robotInit() {
//take our extra talons and just have them follow the Talons updated in
_leftSlave1.follow(_frontLeftMotor);
_leftSlave2.follow(_frontLeftMotor);
_rightSlave1.follow(_frontRightMotor);
_rightSlave2.follow(_frontRightMotor);
/* drive robot forward and make sure all
* motors spin the correct way.
* Toggle booleans accordingly.... */
_frontLeftMotor.setInverted(false);
_leftSlave1.setInverted(false);
_leftSlave2.setInverted(false);
_frontRightMotor.setInverted(false);
_rightSlave1.setInverted(false);
_rightSlave2.setInverted(false);
}
/**
* This function is called periodically during operator control
*/
public void teleopPeriodic() {
double right = rightJoy.getY();
double left = leftjoy.getY();
/* deadband */
if (Math.abs(left) < 0.10) {
/* within 10% joystick, make it zero */
left = 0;
}
if (Math.abs(right) < 0.10) {
/* within 10% joystick, make it zero */
right = 0;
}
/* print the joystick values to sign them, comment
* out this line after checking the joystick directions. */
System.out.println("Left: " + left + " Right:" + right );
_drive.tankDrive(left, right);
}
}
//At top:
double proportionFactor = 0.2; //These values should be tuned to be the most efficient.
double integralFactor = 0.2;
double derivativeFactor = 0.2;
double marginOfError = 0.01;
double actual = 1; //Change based on situation
double desired = 10;
double priorActual = actual;
double integral = 0;
double error = desired - actual;
Repeated loop (like slow or fast periodic) {
priorActual = actual;
actual = <get sensor data>;
error = desired - actual;
if (Math.abs(desired-actual) < marginOfError){
<End of PID, Position Achieved>
} else {
integral = integral + current - desired;
}
return proportionFactor*error + integralFactor*integral + derivativeFactor*(actual-priorActual);
}
package org.usfirst.frc.team972.robot;
import edu.wpi.first.wpilibj.IterativeRobot;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.*;
public class Robot extends IterativeRobot {
Compressor com = new Compressor(40);
DoubleSolenoid sol = new Double Solenoid(1, 2);
Joystick joy = new Joystick(1);
//This function is run when the robot is first started up and should be used for any initialization code.
public void robotInit() {
//set up compressors
com.setClosedLoopControl(true);
com.start();
}
public void teleopPeriodic() {
// Called when the button was released since last check
if(joystick.getRawButtonReleased(0)) {
if(frontSolenoid.get().equals(kForward)) {
frontSolenoid.set(kReverse);
} else if(frontSolenoid.get().equals(kReverse)) {
frontSolenoid.set(kForward);
}
}
}
}
Last Edit on January 26, 2019