Help with Test Robot program (NetBeans)

I am running a test program on my team’s test robot and the victors keep blinking even when the robot is enabled. As far as I know, the victors are not receiving information but according to my program they should. I’ve been working to solve this problem for a very long time now so I’ve changed the victors, PWM and wires but still no luck. I don’t think there is a problem with program but here it is:

package edu.wpi.first.wpilibj.templates;

import edu.wpi.first.wpilibj.RobotDrive;
import edu.wpi.first.wpilibj.GenericHID;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.Victor;
//import edu.wpi.first.wpilibj.PWM;
import edu.wpi.first.wpilibj.RobotBase;
import edu.wpi.first.wpilibj.SpeedController;
import edu.wpi.first.wpilibj.Timer;

/**

  • The VM is configured to automatically run this class, and to call the

  • functions corresponding to each mode, as described in the IterativeRobot

  • 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.
    */
    public class TestRobot extends RobotBase {
    private static RobotDrive driveTrain;
    private static GenericHID leftJoystick;
    private static GenericHID rightJoystick;
    private SpeedController leftVictor;
    private SpeedController rightVictor;
    //private static PWM rightPWM;
    //private static PWM leftPWM;
    private boolean m_robotMainOverridden;

    /**

    • This function is run when the robot is first started up and should be
    • used for any initialization code.
      */
      public void robotInit() {
      driveTrain = new RobotDrive(2,1);
      leftJoystick = new Joystick(2);
      leftVictor = new Victor (1);
      //leftPWM = new PWM (2);
      rightJoystick = new Joystick(1);
      rightVictor = new Victor (1);
      //rightPWM = new PWM (1);
      }

    /**

    • This function is called periodically during autonomous
      */
      public void autonomousPeriodic() {

    }

    /**

    • This function is called periodically during operator control
      */
      public void teleopPeriodic() {
      getWatchdog().setEnabled(true);
      getWatchdog().setExpiration(0.2);
      while (isOperatorControl() && isEnabled()) {
      //driveTrain.arcadeDrive(rightJoystick);
      driveTrain.tankDrive(leftJoystick, rightJoystick);

       if(leftJoystick.getTrigger()) 
       {
           leftVictor.set(0.7);
       } 
       else 
       {
           leftVictor.set(0.0);
       }
       if(rightJoystick.getTrigger()) 
       {
           rightVictor.set(0.7);
       }
       else 
       {
           rightVictor.set(0.0);
       }
      

      }
      getWatchdog().feed();
      }

    public void robotMain() { // supplied default robotMain
    System.out.println(“Information: No user-supplied robotMain()”);
    m_robotMainOverridden = false;
    }

    public void autonomous() { // supplied default autonomous()
    System.out.println(“Provided Autonomous() method running”);
    }

     public void operatorControl() { // suppled default operatorControl() 
     System.out.println("Provided OperatorControl() method running"); 
     } 
    

    public void startCompetition() {
    robotMain();
    if (!m_robotMainOverridden) {
    while(true) {
    // Wait for robot to be enabled
    while (isDisabled()) {
    Timer.delay(.01);
    }
    // Now enabled - check if we should run Autonomous code
    if (isAutonomous()) {
    autonomous();
    while (isAutonomous() && !isDisabled()) {
    Timer.delay(.01);
    }
    } else {
    operatorControl(); // run the operator control method
    while (isOperatorControl() && !isDisabled()) {
    Timer.delay(.01);
    }
    }
    }
    }
    }
    }

please give me any advice that you can come up with thank you!

  • Team 2064
    Captain/Programmer

Your class extends RobotBase, which isn’t a problem, except for that you’ve written your auto and teleop code inside of methods which are never called. If you take a look at the linnked javadoc for RobotBase, you will see that it has no notion of robotInit, autonomousPeriodic, or teleopPeriodic methods.

If you wanted to continue to extend RobotBase, you need to call these methods appropriately from your startCompetition method.

However, I would suggest you take a look at the IterativeRobot class. If your TestRobot class extended IterativeRobot, then you should be able to get rid of the startCompetition method in your code. robotInit, and the auto/teleopPeriodic metyhods would be called as described in the javadoc. Currently though you have while loops inside your teleopPeriodic method. If you use the iterative robot project, the auto and teleopPeriod methods are already going to be called periodically (50 times per second per javadoc), so you want them to complete quickly. If there are loops in these methods you want to be sure they won’t take longer than 20ms to complete.

Alternatively, if you want to have while loops in your teleop or auto methods, take a look at the SimpleRobot class.

Also, I would recommend not using the watchdog, at least not until you get everything up and running. It’s just one more thing that could go wrong and confuse the issue. For example, it’s currently not being fed inside your while loop in the teleopPeriodic method, so the robot should stop working after 0.2 sec. per your code.

Hopefully that gets you moving in the right direction. In the future use the "

" tags around your code so it's easier for people to read.

One thing I noticed that might affect your PWM outputs is that you are using the wrong constructor for RobotDrive. When you pass the RobotDrive constructor port numbers as the parameters, it creates internal instances of the Jaguar class for the speed controllers. Your code then creates Victors using the same PWM ports as the Jaguars that RobotDrive created:


driveTrain = new RobotDrive(2, 1);
leftVictor = new Victor(2);
rightVictor = new Victor(1);

Instead, you should create your Victors first, and then pass them to the RobotDrive constructor:


leftVictor = new Victor(2);
rightVictor = new Victor(1);
driveTrain = new RobotDrive(leftVictor, rightVictor);

Also, as opposed to using the watchdog, you may want to use the MotorSafety methods provided by the RobotDrive class.The RobotDrive#setSafetyEnabled() and RobotDrive#setExpiration() methods should provide similar functionality without using the global watchdog.

Thank you both for your help but it still doesn’t work and at this point I do not know if it is a electrical or programming issue. Any other advice?

It would help to post your modified code.

Updated code:

package edu.wpi.first.wpilibj.templates;

import edu.wpi.first.wpilibj.RobotDrive;
import edu.wpi.first.wpilibj.GenericHID;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.Victor;
//import edu.wpi.first.wpilibj.PWM;
import edu.wpi.first.wpilibj.IterativeRobot;
import edu.wpi.first.wpilibj.SpeedController;
import edu.wpi.first.wpilibj.Timer;

/**
 * The VM is configured to automatically run this class, and to call the
 * functions corresponding to each mode, as described in the IterativeRobot
 * 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.
 */
public class TestRobot extends IterativeRobot {
    private static RobotDrive driveTrain;
    private static GenericHID leftJoystick;
    private static GenericHID rightJoystick;
    private SpeedController leftVictor;
    private SpeedController rightVictor;
    //private static PWM rightPWM;
    //private static PWM leftPWM;
    private boolean m_robotMainOverridden;
    
    /**
     * This function is run when the robot is first started up and should be
     * used for any initialization code.
     */
    public void robotInit() {
        leftJoystick = new Joystick(2);
        leftVictor = new Victor (1);
        //leftPWM = new PWM (2);
        rightJoystick = new Joystick(1);
        rightVictor = new Victor (1);
        //rightPWM = new PWM (1);
        driveTrain = new RobotDrive(leftVictor, rightVictor);
    }

    /**
     * This function is called periodically during autonomous
     */
    public void autonomousPeriodic() {

    }

    /**
     * This function is called periodically during operator control
     */
    public void teleopPeriodic() {
        getWatchdog().setEnabled(true);
        getWatchdog().setExpiration(0.2);
        while (isOperatorControl() && isEnabled()) {
            //driveTrain.arcadeDrive(rightJoystick);
            driveTrain.tankDrive(leftJoystick, rightJoystick);
            
            if(leftJoystick.getTrigger()) 
            {
                leftVictor.set(0.7);
            } 
            else 
            {
                leftVictor.set(0.0);
            }
            if(rightJoystick.getTrigger()) 
            {
                rightVictor.set(0.7);
            }
            else 
            {
                rightVictor.set(0.0);
            }
        }
         getWatchdog().feed();  
    }
    
     public void robotMain() { // supplied default robotMain 
        System.out.println("Information: No user-supplied robotMain()"); 
        m_robotMainOverridden = false; 
        }
     
     public void autonomous() { // supplied default autonomous() 
        System.out.println("Provided Autonomous() method running"); 
        } 

        public void operatorControl() { // suppled default operatorControl() 
        System.out.println("Provided OperatorControl() method running"); 
        } 
      
    public void startCompetition() { 
        robotMain(); 
        if (!m_robotMainOverridden) { 
        while(true) { 
        // Wait for robot to be enabled 
        while (isDisabled()) { 
        Timer.delay(.01); 
        } 
        // Now enabled - check if we should run Autonomous code 
        if (isAutonomous()) { 
        autonomous(); 
       while (isAutonomous() && !isDisabled()) { 
        Timer.delay(.01); 
        } 
        } else { 
        operatorControl(); // run the operator control method 
        while (isOperatorControl() && !isDisabled()) { 
        Timer.delay(.01); 
        } 
       } 
      } 
     } 
    } 
   }

After looking over the updated code, I have come up with some more points for you to consider:

  • When subclassing IterativeRobot, there is no need to override the robotMain(), autonomous(), operatorControl(), or startCompetition() methods. operatorControl() and autonomous() are used by the SimpleRobot class, and robotMain() and startCompetition() have already been setup in the IterativeRobot class

  • IterativeRobot is an iterative style of programming as the name implies. The teleopPeriodic() method will be automatically called at a fixed interval (about 20 ms). This means that the method needs to return quickly, so you shouldn’t place any loops inside of it.

  • Since the periodic methods are called repeatedly, any setup code should be placed in an init method. The IterativeRobot framework provides a robotInit() method that is called once at the start of the program as well as an init method called at the start of each game period (autonomousInit(), teleopInit(), disabledInit(), testInit()).

  • Some of the variables for your robot class were prefaced with the ‘static’ keyword and thus class variables. While this shouldn’t break your code, you will usually want to use instance variables instead of class variables for the main robot class.

  • You are still using the watchdog. While I don’t have documentation to back me up, I believe most would agree that it is usually better to avoid using the watchdog these days. The RobotDrive method has built in methods for handling safety/timeouts. See the code example at the end of my post.

  • Inside your teleopPeriodic() method there seems to be a conflict with controlling the motors. You start by calling driveTrain.tankDrive() which sets the left and right motors. But then underneath you have a series of if statements that sets both motors to one of two values:


public void teleopPeriodic() {
    driveTrain.tankDrive(leftJoystick, rightJoystick);

    if(leftJoystick.getTrigger()) {
        leftVictor.set(0.7);
    } else {
        leftVictor.set(0.0);
    }

    if(rightJoystick.getTrigger()) {
        rightVictor.set(0.7);
    } else {
        rightVictor.set(0.0);
    }
}

Every time this runs, you end up setting both motors to either 0.7 or 0.0, overriding the tank drive. Removing the else statements should fix this problem, allowing the motors to default to the joystick values when their respective buttons are not pressed.

Below is a modified version of your code with these changes made. One other thing I changed was moving the constructors to the variable declarations to save space.


package edu.wpi.first.wpilibj.templates;

import edu.wpi.first.wpilibj.RobotDrive;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.Victor;
import edu.wpi.first.wpilibj.IterativeRobot;
import edu.wpi.first.wpilibj.SpeedController;

/**
* The VM is configured to automatically run this class, and to call the
* functions corresponding to each mode, as described in the IterativeRobot
* 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.
*/
public class TestRobot extends IterativeRobot {
    private Joystick leftJoystick = new Joystick(2);
    private Joystick rightJoystick = new Joystick(1);
    private SpeedController leftVictor = new Victor(2);
    private SpeedController rightVictor = new Victor(1);
    private RobotDrive driveTrain = new RobotDrive(leftVictor, rightVictor);

    /**
     * This function is run when the robot is first started up and should be
     * used for any initialization code.
     */
    public void robotInit() {
        driveTrain.setSafetyEnabled(true);
        driveTrain.setExpiration(0.2);
    }

    /**
     * This function is called periodically during operator control
     */
    public void teleopPeriodic() {
        driveTrain.tankDrive(leftJoystick, rightJoystick);

        if(leftJoystick.getTrigger()) {
            leftVictor.set(0.7);
        }

        if(rightJoystick.getTrigger()) {
            rightVictor.set(0.7);
        }
    }
}

Phew, that was more than I thought it would be when I started writing this post. :yikes: Sorry for the wall of text. One last thing: when using the code tags, make sure the second tag has a slash after the opening bracket like this "

".

Thank you so much for you help! It worked perfectly and everything makes much more sense now :slight_smile: