toggleWhenPressed and whileHeld methods fail to properly turn off motors once initiated

Hi all, we’re attempting to create a command that toggles a motor for a conveyor system using a TalonSRX controller. Here’s an example command bound to the A button with the toggleWhenPressed method in the OI.

When toggled on, the motor starts, but upon attempting to toggle it off, the command passes through both the interrupted and end methods as expected, but then begins initiation of the execute method right after. I am assuming it has something to do with how the isFinished method is handled or I am completely misunderstanding how toggleWhenPressed works, but I am currently at a loss on how to fix this, so any input would be appreciated.

What kind of controller are you using? You may need some sort of debouncing.

We’re currently using CTRE TalonSRXs for a 775 motor.

Sorry - I mean, when you say “A button”, are you using an Xbox Controller, or a Logitech controller, or some kind of joystick, etc…

We’re currently using Xbox 360 controllers, but we’ve tested with Logitech F310 Gamepads as well just in case the issue involved the controller itself, but it did not happen to resolve the issue. We will look into implementing debouncing as we had not considered that may be the case before.

All those controller types are usually pretty good at avoiding this issue, so this is indeed puzzling.

What is the behavior when you press the button? Do the motors continue move without stopping or don’t appear to move at all? Or do they only slightly move?

This is the output I receive when using toggleWhenPressed and attempting to toggle off after the motor was turned on

The motor momentarily stalls, but starts moving again in this case

Alternatively, I tried whileHeld to see if the behavior was different, and the results were a very mixed bag

Attempting to toggle on or off results in the motor momentarily fidgeting, but it almost instantly shuts off afterwards.

Not sure if this has any relation to the issue at hand, but using setTimeout and allowing isFinished to return isTimedOut properly shuts down the motor after the specified time. Our current work around is using two separate commands to turn the motor on and off and setting the on method to whenPressed() and the off method to whenReleased(). As far as file structure and organization though, I feel this is a suboptimal workaround.

Can you share your OI code as well? Maybe there’s something in the way the button is being mapped to the command.

I think what’s happening is that when you toggle it it turns off, but since its bound to the same button, it immediately turns on again. I would do something in your execute() function like so:
if(motor.get() != 0)
motor.set(0.25)
else
motor.set(0)

and then remove the Robot.cv.stop() in the end() function.

This is our OI class

Would this not make the motor endlessly vacillate between the off and on state? From what I’ve read execute runs about 50 times a second so this would just turn the motor off and on without any way to end it still unless I am mistaken

Yeah. So to modify this you could probably declare a static boolean at the top that flips value in your initialize instead, so something like this:

public class ToggleMotors extends Command {
static boolean toggle = false;

public ToggleMotors () {
}

// Called just before this Command runs the first time
@Override
protected void initialize() {
    toggle = !toggle;
}

// Called repeatedly when this Command is scheduled to run
@Override
protected void execute() {
    if(toggle)
        Motor.set(0.25);
    else
       Motor.set(0);
}

// Called once after isFinished returns true
@Override
protected void end() {
}

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

}

Or you can use an instant command like so

public class ToggleMotors extends InstantCommand {
static boolean toggle = false;

public ToggleMotors () {
}

// Called just before this Command runs the first time
@Override
protected void initialize() {
    toggle = !toggle;
    if(toggle)
        Motor.set(0.25);
    else
       Motor.set(0);
}

// Called once after isFinished returns true
@Override
protected void end() {
}

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

}

The boolean toggle approach seems to work great. I was under the assumption that booleans for toggles would be ineffective in commands since whenPressed or whenTogglePressed would create an entirely new instance of the command with reset boolean values, but it seems I was mistaken. I was initially rather vexed since open source code from steamworks projects had toggle commands did not need any toggle booleans to function properly, but thank you very much for the help regarding this issue!

So a static variable in Java initializes only a single variable for that class that can be accessed by all other variables of the same class. By setting the boolean to static, we can ensure we know what state it is whenever a new class is created when pressing the button.

So it should be true that you shouldn’t need a boolean toggle to make this work in a toggleWhenPressed(), since this code would work the same way in a whenPresssed() since the logic is contained within the command itself. So I’m not exactly sure why it doesn’t work as intended.

Do you have a default Command set for your subsystem? If you have this same command set as the subsystem default. When no other command is running on that subsystem, the default command would start back up.

I second the default command theory.

We currently have the default command set to null in our subsystem. Would deleting setDefaultCommand(null) make any difference?

That should be fine then. Commenting it out wouldn’t hurt, but I doubt it would fix it either.

Any chance you could post the entirety of your code? Preferably on GitHub, but here works too. It can help if this is some really minute issue, or an issue resulting from somewhere else in the code.

We’re currently in the process of including additional subsystems and commands, so this was a post haste commit, but this is the repo we’re currently working with minus our current static boolean toggle fix for the conveyor.