Motors running in Initialize() immediately stop


#1

When creating a command for our hatch extender which is controlled by a limit switch, I’m following the WPI documentation and putting the method in the initialize() command to make the motor drive. However, the motor only briefly pulses and then stops, even though the isFinished() criteria isn’t being completed. The motor safety is off as well. I’m probably missing something obvious.

This is the command for the mechanism

public class FourBarLinkageCommand extends Command 
{
  boolean linkageDeployed = false;

  public FourBarLinkageCommand() 
  {
    linkageDeployed = false;
    requires(Robot.fourBarLinkage);
    System.out.println("Four Bar Linkage has been created");
    // Use requires() here to declare subsystem dependencies
    // eg. requires(chassis);
  }

  // Called just before this Command runs the first time
  @Override
  protected void initialize() 
  {
    System.out.println("linkage initialized");
    Robot.fourBarLinkage.initializeCounter();
    Robot.fourBarLinkage.hatchForward();
    System.out.println("Initialized At " + java.lang.System.currentTimeMillis());

  }

  // Called repeatedly when this Command is scheduled to run
  @Override
  protected void execute() 
  {
    System.out.println("TIMESTAMP: " + java.lang.System.currentTimeMillis());
  }

  // Make this return true when this Command no longer needs to run execute()
  @Override
  protected boolean isFinished() 
  {
    System.out.println(Robot.fourBarLinkage.isFrontSwitchSet() || Robot.fourBarLinkage.isRearSwitchSet());
    return Robot.fourBarLinkage.isFrontSwitchSet() || Robot.fourBarLinkage.isRearSwitchSet(); // finishes when the limit switch is activated, shouldn't be an issue due to how slowly it goes
  }

  // Called once after isFinished returns true
  @Override
  protected void end() 
  {
    Robot.fourBarLinkage.stopLinkage();
    System.out.println("linkage finished at: " + java.lang.System.currentTimeMillis());
  }

  // Called when another command which requires one or more of the same
  // subsystems is scheduled to run
  @Override
  protected void interrupted() 
  {

  }
}

This is the subsystem for the mechanism

public class FourBarLinkageForHatch extends Subsystem 
{
  // Put methods for controlling this subsystem
  // here. Call these from Commands.
  WPI_TalonSRX fourBarLinkageTalon = RobotMap.fourBarLinkageTalon;
  DigitalInput hatchArmSwitchFront = new DigitalInput(RobotMap.HATCH_ARM_SWITCH_ID_FRONT); 
  DigitalInput hatchArmSwitchBack = new DigitalInput(RobotMap.HATCH_ARM_SWITCH_ID_BACK); 
  Counter counterFront = new Counter(hatchArmSwitchFront);
  Counter counterRear = new Counter(hatchArmSwitchBack);

  @Override
  public void initDefaultCommand() 
  {
    // Set the default command for a subsystem here.
    // setDefaultCommand(new MySpecialCommand());
  }

  public void hatchForward()
  {
    fourBarLinkageTalon.set(ControlMode.PercentOutput, 0.8);
  }

  public void hatchBack()
  {
    fourBarLinkageTalon.set(ControlMode.PercentOutput, -0.8);
  }

  public void stopLinkage()
  {
    fourBarLinkageTalon.set(ControlMode.PercentOutput, 0);
  }

  public boolean isFrontSwitchSet(){
    return counterFront.get() > 0; // increments when the limit switch is activated
  }

  public boolean isRearSwitchSet(){
    return counterRear.get() > 0;
  }

  public void initializeCounter(){
    counterFront.reset();
    counterRear.reset();
  }
}

#2

Is there any other code running concurrently that could be setting the motor back to zero?

Are you sure the command isn’t exiting? I see you have print statements, but it doesn’t hurt to ask.

What are the talon status lights doing when the motor stops?


#3

The command isn’t exiting, the execute timestamp continues to run and the switches continue to return false. The talon status lights flash green briefly so they are running, at least for a pulse, and then stay solid orange. No other code is using the talon either.


#4

Do you have your code on github, so that I can look at the rest of it? By far the most likely scenario is that there is other code that is setting the motor back to zero.


#5

Yeah, I’ll PM you the link.


#6

Additionally, you really shouldn’t have your motors be global variables, for precisely this reason. You should also be initializing your subsystem’s fields inside of a constructor.


#7

Ok, I was just following the example from here and it seems that’s what they did.


#8

Your execute() method needs to call hatchForward() as well.


#9

Okay, I can’t find any place in your code where you’re explicitly using the motor elsewhere, but it worries me that you’ve instantiated your cargomotor with a device ID of 9999999, and in general it’s hard to check every piece of code that could be touching the motor.

Try making the motor a private field in the relevant subsystem, and set the cargomotor to a CAN ID that is actually in the valid range.

It does not; the motor controller should continue at the value it was last set to until it is told to do something else.


#10

I instantiated it with the high ID as a placeholder because I’m not sure which talon I’m using yet. I’ll try making it private in the subsystem.


#11

For most processors, this would be true. As I understand it, the FRC RIO firmware requires that the motor speed be refreshed every hundred milliseconds or so. This “watchdog” function is also why robots stop when user code has a wait() or a long while loop in it.


#12

MotorSafety does what you describe (stops the motors if they aren’t driven periodically), but it’s only enabled by default in drivetrains (although maybe some of the vendor motor controllers enable it by default)? The watchdog feature added this year is used solely to warn about loop overruns / long delays, it doesn’t actually turn off the motors.


#13

@Oblarg is correct. For example, in position control, we’ll often set the position using the subsystem’s methods in the command’s initialize(). The system runs, and then in isFinished(), we’ll check with the subsystem if we’re onTarget(). If we are, then we stop.


#14

We had this issue a few days ago as well.

Check:

  • Is anything else using the subsystem at that time?
  • Is the default command being called?
  • Make sure isFinished() is returning what you think. I spent way too long chasing down a ! (caused the command to end immediately) in one of our subsystems.

#15

Every FRC-legal motor controller requires regular signals so that the e-stop and end-of-match will shut motors down. The question is whether the controlling computer (RIO) requires a refreshed signal. If you and @oblarg are correct, I’ve been party to a bunch of superfluous code.


#16

This is a good example:

Check out the subsystem https://github.com/rkalnins/twist-robot/blob/master/src/main/java/frc/team2767/twistrobot/subsystem/DriveSubsystem.java to see how isFinished() works with the subsystem.


#17

This is, indeed, the case.


#18

I don’t see that in the code you posted.


#19

So I tried declaring the motor controller private in the subsystem that it’s being used in, and it still didn’t work. As a workaround I’m just using it in execute().