diff --git a/eclipse-plugins/edu.wpi.first.wpilib.plugins.cpp/resources/templates/examples/CANTalon/src/Robot.cpp b/eclipse-plugins/edu.wpi.first.wpilib.plugins.cpp/resources/templates/examples/CANTalon/src/Robot.cpp index e175af4460..2794e7beef 100644 --- a/eclipse-plugins/edu.wpi.first.wpilib.plugins.cpp/resources/templates/examples/CANTalon/src/Robot.cpp +++ b/eclipse-plugins/edu.wpi.first.wpilib.plugins.cpp/resources/templates/examples/CANTalon/src/Robot.cpp @@ -1,35 +1,37 @@ #include "WPILib.h" /** - * This is a quick sample program to show how to use the new Talon SRX over CAN. - * As of the time of this writing (11/20/14), the only mode supported on the SRX is the - * straight-up throttle (status info, such as current and temperature should work). + * This sample shows how to use the new CANTalon to just run a motor in a basic + * throttle mode, in the same manner as you might control a traditional PWM + * controlled motor. * */ class Robot : public SampleRobot { CANTalon m_motor; - // update every 0.005 seconds/5 milliseconds. - double kUpdatePeriod = 0.005; + Joystick m_stick; + + // update every 0.01 seconds/10 milliseconds. + // The talon only receives control packets every 10ms. + double kUpdatePeriod = 0.010; public: Robot() - : m_motor(1) // Initialize the Talon as device 1. Use the roboRIO web + : m_motor(1), // Initialize the Talon as device 1. Use the roboRIO web // interface to change the device number on the talons. + m_stick(0) {} /** * Runs the motor from the output of a Joystick. */ void OperatorControl() { - m_motor.EnableControl(); while (IsOperatorControl() && IsEnabled()) { // Takes a number from -1.0 (full reverse) to +1.0 (full forwards). - m_motor.Set(0.5); + m_motor.Set(m_stick.GetY()); - Wait(kUpdatePeriod); // Wait 5ms for the next update. + Wait(kUpdatePeriod); // Wait a bit so that the loop doesn't lock everything up. } - m_motor.Set(0.0); } }; diff --git a/eclipse-plugins/edu.wpi.first.wpilib.plugins.cpp/resources/templates/examples/CANTalonPID/src/Robot.cpp b/eclipse-plugins/edu.wpi.first.wpilib.plugins.cpp/resources/templates/examples/CANTalonPID/src/Robot.cpp new file mode 100644 index 0000000000..837f392764 --- /dev/null +++ b/eclipse-plugins/edu.wpi.first.wpilib.plugins.cpp/resources/templates/examples/CANTalonPID/src/Robot.cpp @@ -0,0 +1,63 @@ +#include "WPILib.h" + +/** + * This is a quick sample program to show how to use the new Talon SRX over CAN. + * This particular sample demonstrates running a basic PID control loop with an + * analog potentiometer. + * + */ +class Robot : public SampleRobot { + CANTalon m_motor; + +public: + Robot() + : m_motor(1) // Initialize the Talon as device 1. Use the roboRIO web + // interface to change the device number on the m_motors. + { + // This sets the mode of the m_motor. The options are: + // kPercentVbus: basic throttle; no closed-loop. + // kCurrent: Runs the motor with the specified current if possible. + // kSpeed: Runs a PID control loop to keep the motor going at a constant + // speed using the specified sensor. + // kPosition: Runs a PID control loop to move the motor to a specified move + // the motor to a specified sensor position. + // kVoltage: Runs the m_motor at a constant voltage, if possible. + // kFollower: The m_motor will run at the same throttle as the specified other talon. + m_motor.SetControlMode(CANSpeedController::kPosition); + // This command allows you to specify which feedback device to use when doing + // closed-loop control. The options are: + // AnalogPot: Basic analog potentiometer + // QuadEncoder: Quadrature Encoder + // AnalogEncoder: Analog Encoder + // EncRising: Counts the rising edges of the QuadA pin (allows use of a + // non-quadrature encoder) + // EncFalling: Same as EncRising, but counts on falling edges. + m_motor.SetFeedbackDevice(CANTalon::AnalogPot); + // This sets the basic P, I , and D values (F, Izone, and rampRate can also + // be set, but are ignored here). + // These must all be positive floating point numbers (SetSensorDirection will + // multiply the sensor values by negative one in case your sensor is flipped + // relative to your motor). + // These values are in units of throttle / sensor_units where throttle ranges + // from -1023 to +1023 and sensor units are from 0 - 1023 for analog + // potentiometers, encoder ticks for encoders, and position / 10ms for + // speeds. + m_motor.SetPID(1.0, 0.0, 0.0); + } + + /** + * Runs the motor from the output of a Joystick. + */ + void OperatorControl() { + while (IsOperatorControl() && IsEnabled()) { + // In closed loop mode, this sets the goal in the units mentioned above. + // Since we are using an analog potentiometer, this will try to go to + // the middle of the potentiometer range. + m_motor.Set(512); + + Wait(5.0); + } + } +}; + +START_ROBOT_CLASS(Robot); diff --git a/eclipse-plugins/edu.wpi.first.wpilib.plugins.cpp/resources/templates/examples/examples.xml b/eclipse-plugins/edu.wpi.first.wpilib.plugins.cpp/resources/templates/examples/examples.xml index dc2cface62..61b8c8b1b7 100644 --- a/eclipse-plugins/edu.wpi.first.wpilib.plugins.cpp/resources/templates/examples/examples.xml +++ b/eclipse-plugins/edu.wpi.first.wpilib.plugins.cpp/resources/templates/examples/examples.xml @@ -145,6 +145,23 @@ + + CAN Talon SRX PID + Quick demo of running the SRX with a PID loop. + + Robot and Motor + Digital + Actuators + Complete List + + + src + + + + + + Relay Demonstrate controlling a Relay from Joystick buttons. diff --git a/eclipse-plugins/edu.wpi.first.wpilib.plugins.java/resources/templates/examples/CANTalon/src/org/usfirst/frc/team190/robot/Robot.java b/eclipse-plugins/edu.wpi.first.wpilib.plugins.java/resources/templates/examples/CANTalon/src/org/usfirst/frc/team190/robot/Robot.java index 48af9802d1..3d4dbb1145 100755 --- a/eclipse-plugins/edu.wpi.first.wpilib.plugins.java/resources/templates/examples/CANTalon/src/org/usfirst/frc/team190/robot/Robot.java +++ b/eclipse-plugins/edu.wpi.first.wpilib.plugins.java/resources/templates/examples/CANTalon/src/org/usfirst/frc/team190/robot/Robot.java @@ -8,31 +8,29 @@ import edu.wpi.first.wpilibj.Timer; /** * This is a short sample program demonstrating how to use the basic throttle - * mode of the new CAN Talon. As of when this was made, the basic throttle mode - * is all that is supported. + * mode of the new CAN Talon. */ public class Robot extends SampleRobot { CANTalon motor; - private final double k_updatePeriod = 0.005; // update every 0.005 seconds/5 milliseconds (200Hz) - public Robot() { motor = new CANTalon(1); // Initialize the CanTalonSRX on device 1. } /** - * Runs the motor from a joystick. + * Runs the motor. */ public void operatorControl() { - motor.enableControl(); while (isOperatorControl() && isEnabled()) { // Set the motor's output to half power. // This takes a number from -1 (100% speed in reverse) to +1 (100% speed // going forward) motor.set(0.5); - Timer.delay(k_updatePeriod); // wait 5ms to the next update + Timer.delay(0.01); // Note that the CANTalon only receives updates every + // 10ms, so updating more quickly would not gain you + // anything. } motor.disable(); } diff --git a/eclipse-plugins/edu.wpi.first.wpilib.plugins.java/resources/templates/examples/CANTalonPID/src/org/usfirst/frc/team190/robot/Robot.java b/eclipse-plugins/edu.wpi.first.wpilib.plugins.java/resources/templates/examples/CANTalonPID/src/org/usfirst/frc/team190/robot/Robot.java new file mode 100755 index 0000000000..090e1d8226 --- /dev/null +++ b/eclipse-plugins/edu.wpi.first.wpilib.plugins.java/resources/templates/examples/CANTalonPID/src/org/usfirst/frc/team190/robot/Robot.java @@ -0,0 +1,62 @@ +package $package; + + +import edu.wpi.first.wpilibj.SpeedController; +import edu.wpi.first.wpilibj.CANTalon; +import edu.wpi.first.wpilibj.SampleRobot; +import edu.wpi.first.wpilibj.Timer; + +/** + * This is a short sample program demonstrating how to use the Talon SRX over + * CAN to run a closed-loop PID controller with an analog potentiometer. + */ +public class Robot extends SampleRobot { + + CANTalon motor; + + public Robot() { + motor = new CANTalon(1); // Initialize the CanTalonSRX on device 1. + + // This sets the mode of the m_motor. The options are: + // PercentVbus: basic throttle; no closed-loop. + // Current: Runs the motor with the specified current if possible. + // Speed: Runs a PID control loop to keep the motor going at a constant + // speed using the specified sensor. + // Position: Runs a PID control loop to move the motor to a specified move + // the motor to a specified sensor position. + // Voltage: Runs the m_motor at a constant voltage, if possible. + // Follower: The m_motor will run at the same throttle as the specified + // other talon. + motor.changeControlMode(CANTalon.ControlMode.Position); + // This command allows you to specify which feedback device to use when doing + // closed-loop control. The options are: + // AnalogPot: Basic analog potentiometer + // QuadEncoder: Quadrature Encoder + // AnalogEncoder: Analog Encoder + // EncRising: Counts the rising edges of the QuadA pin (allows use of a + // non-quadrature encoder) + // EncFalling: Same as EncRising, but counts on falling edges. + motor.setFeedbackDevice(CANTalon.FeedbackDevice.AnalogPot); + // This sets the basic P, I , and D values (F, Izone, and rampRate can also + // be set, but are ignored here). + // These must all be positive floating point numbers (reverseSensor will + // multiply the sensor values by negative one in case your sensor is flipped + // relative to your motor). + // These values are in units of throttle / sensor_units where throttle ranges + // from -1023 to +1023 and sensor units are from 0 - 1023 for analog + // potentiometers, encoder ticks for encoders, and position / 10ms for + // speeds. + motor.setPID(1.0, 0.0, 0.0); + } + + public void operatorControl() { + while (isOperatorControl() && isEnabled()) { + // In closed loop mode, this sets the goal in the units mentioned above. + // Since we are using an analog potentiometer, this will try to go to + // the middle of the potentiometer range. + motor.set(512); + + Timer.delay(5.0); + } + } +} diff --git a/eclipse-plugins/edu.wpi.first.wpilib.plugins.java/resources/templates/examples/examples.xml b/eclipse-plugins/edu.wpi.first.wpilib.plugins.java/resources/templates/examples/examples.xml index b0bd47120b..483fa383b0 100755 --- a/eclipse-plugins/edu.wpi.first.wpilib.plugins.java/resources/templates/examples/examples.xml +++ b/eclipse-plugins/edu.wpi.first.wpilib.plugins.java/resources/templates/examples/examples.xml @@ -171,6 +171,23 @@ + + CAN Talon SRX PID + Demonstrate running a Talon SRX with PID Closed Loop control. + + Actuators + Complete List + Robot and Motor + + + src/$package-dir + + + + + + CommandBased Robot diff --git a/wpilibj/wpilibJavaDevices/src/main/java/edu/wpi/first/wpilibj/CANTalon.java b/wpilibj/wpilibJavaDevices/src/main/java/edu/wpi/first/wpilibj/CANTalon.java index 6fb46ad2b5..d67588ce0e 100644 --- a/wpilibj/wpilibJavaDevices/src/main/java/edu/wpi/first/wpilibj/CANTalon.java +++ b/wpilibj/wpilibJavaDevices/src/main/java/edu/wpi/first/wpilibj/CANTalon.java @@ -75,7 +75,8 @@ public class CANTalon implements MotorSafety, PIDOutput, SpeedController { } @Override - public void pidWrite(double output) { + public void pidWrite(double output) + { if (getControlMode() == ControlMode.PercentVbus) { set(output); } @@ -342,6 +343,12 @@ public class CANTalon implements MotorSafety, PIDOutput, SpeedController { m_controlEnabled = false; } + /** + * Get the current proportional constant. + * + * @returns double proportional constant for current profile. + * @throws IllegalStateException if not in Position of Speed mode. + */ public double getP() { if(!(m_controlMode.equals(ControlMode.Position) || m_controlMode.equals(ControlMode.Speed))) { throw new IllegalStateException("PID mode only applies in Position and Speed modes."); @@ -353,6 +360,9 @@ public class CANTalon implements MotorSafety, PIDOutput, SpeedController { else m_impl.RequestParam(CanTalonSRX.param_t.eProfileParamSlot1_P); + // Briefly wait for new values from the Talon. + Timer.delay(1); + long pp = CanTalonJNI.new_doublep(); m_impl.GetPgain(m_profile, new SWIGTYPE_p_double(pp, true)); return CanTalonJNI.doublep_value(pp); @@ -369,6 +379,9 @@ public class CANTalon implements MotorSafety, PIDOutput, SpeedController { else m_impl.RequestParam(CanTalonSRX.param_t.eProfileParamSlot1_I); + // Briefly wait for new values from the Talon. + Timer.delay(1); + long ip = CanTalonJNI.new_doublep(); m_impl.GetIgain(m_profile, new SWIGTYPE_p_double(ip, true)); return CanTalonJNI.doublep_value(ip); @@ -385,6 +398,9 @@ public class CANTalon implements MotorSafety, PIDOutput, SpeedController { else m_impl.RequestParam(CanTalonSRX.param_t.eProfileParamSlot1_D); + // Briefly wait for new values from the Talon. + Timer.delay(1); + long dp = CanTalonJNI.new_doublep(); m_impl.GetDgain(m_profile, new SWIGTYPE_p_double(dp, true)); return CanTalonJNI.doublep_value(dp); @@ -401,6 +417,9 @@ public class CANTalon implements MotorSafety, PIDOutput, SpeedController { else m_impl.RequestParam(CanTalonSRX.param_t.eProfileParamSlot1_F); + // Briefly wait for new values from the Talon. + Timer.delay(1); + long fp = CanTalonJNI.new_doublep(); m_impl.GetFgain(m_profile, new SWIGTYPE_p_double(fp, true)); return CanTalonJNI.doublep_value(fp); @@ -417,6 +436,9 @@ public class CANTalon implements MotorSafety, PIDOutput, SpeedController { else m_impl.RequestParam(CanTalonSRX.param_t.eProfileParamSlot1_IZone); + // Briefly wait for new values from the Talon. + Timer.delay(1); + long fp = CanTalonJNI.new_intp(); m_impl.GetIzone(m_profile, new SWIGTYPE_p_int(fp, true)); return CanTalonJNI.intp_value(fp); @@ -433,34 +455,97 @@ public class CANTalon implements MotorSafety, PIDOutput, SpeedController { else m_impl.RequestParam(CanTalonSRX.param_t.eProfileParamSlot1_CloseLoopRampRate); + // Briefly wait for new values from the Talon. + Timer.delay(1); + long fp = CanTalonJNI.new_intp(); m_impl.GetCloseLoopRampRate(m_profile, new SWIGTYPE_p_int(fp, true)); return CanTalonJNI.intp_value(fp); } + /** + * Set the proportional value of the currently selected profile. + * + * @param p Proportional constant for the currently selected PID profile. + * @see setProfile For selecting a certain profile. + */ public void setP(double p) { m_impl.SetPgain(m_profile, p); } + /** + * Set the integration constant of the currently selected profile. + * + * @param i Integration constant for the currently selected PID profile. + * @see setProfile For selecting a certain profile. + */ public void setI(double i) { m_impl.SetIgain(m_profile, i); } + /** + * Set the derivative constant of the currently selected profile. + * + * @param d Derivative constant for the currently selected PID profile. + * @see setProfile For selecting a certain profile. + */ public void setD(double d) { m_impl.SetDgain(m_profile, d); } + /** + * Set the feedforward value of the currently selected profile. + * + * @param f Feedforward constant for the currently selected PID profile. + * @see setProfile For selecting a certain profile. + */ public void setF(double f) { m_impl.SetFgain(m_profile, f); } + /** + * Set the integration zone of the current Closed Loop profile. + * + * Whenever the error is larger than the izone value, the accumulated + * integration error is cleared so that high errors aren't racked up when at + * high errors. + * An izone value of 0 means no difference from a standard PIDF loop. + * + * @param izone Width of the integration zone. + * @see setProfile For selecting a certain profile. + */ public void setIZone(int izone) { m_impl.SetIzone(m_profile, izone); } - public void setRampRate(int rampRate) { - m_impl.SetCloseLoopRampRate(m_profile, rampRate); + /** + * Set the closed loop ramp rate for the current profile. + * + * Limits the rate at which the throttle will change. + * Only affects position and speed closed loop modes. + * + * @param rampRate Maximum change in voltage, in volts / sec. + * @see setProfile For selecting a certain profile. + */ + public void setCloseLoopRampRate(double rampRate) { + // CanTalonSRX takes units of Throttle (0 - 1023) / 10ms. + int rate = (int) (rampRate * 1023.0 / 12.0 * 100.0); + m_impl.SetCloseLoopRampRate(m_profile, rate); + } + + /** + * Set the voltage ramp rate for the current profile. + * + * Limits the rate at which the throttle will change. + * Affects all modes. + * + * @param rampRate Maximum change in voltage, in volts / sec. + */ + public void setVoltageRampRate(double rampRate) { + // CanTalonSRX takes units of Throttle (0 - 1023) / 10ms. + int rate = (int) (rampRate * 1023.0 / 12.0 * 100.0); + m_impl.SetRampThrottle(rate); } /** @@ -479,7 +564,8 @@ public class CANTalon implements MotorSafety, PIDOutput, SpeedController { * on hand in the talon. In order to switch profiles without recalling setPID, * you must call setProfile(). */ - public void setPID(double p, double i, double d, double f, int izone, int ramprate, int profile) { + public void setPID(double p, double i, double d, double f, int izone, int ramprate, int profile) + { if (profile != 0 && profile != 1) throw new IllegalArgumentException("Talon PID profile must be 0 or 1."); m_profile = profile; @@ -489,7 +575,7 @@ public class CANTalon implements MotorSafety, PIDOutput, SpeedController { setD(d); setF(f); setIZone(izone); - setRampRate(ramprate); + setCloseLoopRampRate(ramprate); } public void setPID(double p, double i, double d) { setPID(p, i, d, 0, 0, 0, m_profile); @@ -499,7 +585,8 @@ public class CANTalon implements MotorSafety, PIDOutput, SpeedController { * Select which closed loop profile to use, and uses whatever PIDF gains and * the such that are already there. */ - public void setProfile(int profile) { + public void setProfile(int profile) + { if (profile != 0 && profile != 1) throw new IllegalArgumentException("Talon PID profile must be 0 or 1."); m_profile = profile;