Hey Guys. Our team is wanting to use encoders but we don’t know how to use them and the WPILib explination is a bit confusing for me. We’re putting them on both sides of our robot.
BTW, I have a ‘okay’ understanding of FRC Java. If anyone can explain the encoders in a simple way for us to understand, that would be great. Some sample code would be help too.
Thanks.
Are your encoders encoders that connect to the DIO or into the talon?
We are planning on using the DIO ports.
You’ll typically want to use encoders as feedback to a PID controller, which will then control your motors. This is a simple program to experiment with PID and encoders. Just run this program and use the SmartDashboard to enter a “setpoint” which is how far you want the motor to go. Then adjust the P value (for starters) to get it there quickly and completely. Then try chaning the setpoint and see how the motor responds. To start with, try using setpoints in the thousands (e.g. 5000). And it’s a good idea to test this with the robot on blocks so it doesn’t take off across the room.
Once you have something like this in your real program, you can tell your robot to drive a certain distance just by giving the PID controller a setpoint for that distance.
import edu.wpi.first.wpilibj.Encoder;
import edu.wpi.first.wpilibj.IterativeRobot;
import edu.wpi.first.wpilibj.PIDController;
import edu.wpi.first.wpilibj.PIDSourceType;
import edu.wpi.first.wpilibj.Victor;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
public class Robot extends IterativeRobot {
Victor myMotor;
Encoder myEncoder;
PIDController myPID;
double allowableError = 10;
public void robotInit() {
myMotor = new Victor(0); // motor controller on port 0
myEncoder = new Encoder(0, 1, true, Encoder.EncodingType.k4X); // encoder plugged into digital ports 0 and 1 : k4x gives high precision on lower speeds
myPID = new PIDController(0, 0, 0, myEncoder, myMotor); // setup a PID controller with an encoder source and motor output
myEncoder.setPIDSourceType(PIDSourceType.kDisplacement); // tell the encoder to report its overall change to the PID controller
// myEncoder.setDistancePerPulse(0.1); // use this to convert encoder ticks to a useful measurement (e.g. inches) - your number will be different.
myPID.setOutputRange(-1, 1);
myEncoder.reset();
SmartDashboard.putNumber("P", .01);
SmartDashboard.putNumber("I", 0);
SmartDashboard.putNumber("D", 0);
SmartDashboard.putNumber("Distance Setpoint",0);
SmartDashboard.putNumber("Allowable Error: ", allowableError);
myPID.setSetpoint(0);
myPID.enable();
}
public void teleopPeriodic() {
// read the PID values from the SmartDashboard and update the PID controller
myPID.setPID(SmartDashboard.getNumber("P", 0), SmartDashboard.getNumber("I", 0), SmartDashboard.getNumber("D", 0));
// update setpoint to whatever has been entered on smartdashboard
myPID.setSetpoint(SmartDashboard.getNumber("Distance Setpoint", 0));
// update the allowable error from the SmartDashboard
allowableError = SmartDashboard.getNumber("Allowable Error: ", 0);
SmartDashboard.putNumber("Encoder Get: ", myEncoder.get()); // show encoder reading on the dashboard
// We know we are on target when the difference in our setpoint and
// encoder value are less than our determined allowable error
SmartDashboard.putBoolean("On Target: ", Math.abs(myPID.getSetpoint() - myEncoder.get()) < allowableError);
}
public void teleopInit() {
myEncoder.reset();
}
}
OK then.
Here’s a code that sends to the SmartDashboard the rate of the encoders and the distance they’ve passed.
package org.usfirst.frc.team5951.robot;
import edu.wpi.first.wpilibj.Encoder;
import edu.wpi.first.wpilibj.SampleRobot;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
/**
* This is a demo program showing the use of the RobotDrive class. The
* SampleRobot class is the base of a robot application that will automatically
* call your Autonomous and OperatorControl methods at the right time as
* controlled by the switches on the driver station or the field controls.
*
* The VM is configured to automatically run this class, and to call the
* functions corresponding to each mode, as described in the SampleRobot
* documentation. If you change the name of this class or the package after
* creating this project, you must also update the manifest file in the resource
* directory.
*
* WARNING: While it may look like a good choice to use for your code if you're
* inexperienced, don't. Unless you know what you are doing, complex code will
* be much more difficult under this system. Use IterativeRobot or Command-Based
* instead if you're new.
*/
public class Robot extends SampleRobot {
// Encoder is a built in class in the wpilib.
Encoder encoder;
@Override
public void robotInit() {
// Constructor takes 2 arguments that are the 2 ports in the dio (the
// one where the blue cable is and the one where the yellow cable is).
encoder = new Encoder(0, 1);
// To reset the encoder use:
encoder.reset();
}
@Override
public void operatorControl() {
//To find the amount of pulses the encoder has passed and send it to the smart dashboard use:
SmartDashboard.putNumber("Encoder pulses: ", encoder.get());
//To find the rate (pulse per second) and send it to the SmartDashboard, use:
SmartDashboard.putNumber("Encoder rate: ", encoder.getRate());
//If you want to use rotations instead of pulses, use the get method to find out how many pulses are in a rotation
//Or check the instructions of the encoder and use: (Example, there are 1028 pulses in rotations)
encoder.setDistancePerPulse(1 / 1028);
}
}
BTW, When I say pulse, I mean every position the encoder knows.