Set command to run for a certain amount of time

I need a motor to run for a short duration when I click a button. I already have it working to run continuously when I hit the button but im not sure how to get it to only run for like half a second or something.

I’m sure this is a simple fix I’m just a rookie programmer so could anyone walk me through this?

FYI, I’m using the command based template from WPI.

Here is a command that uses a timer. When you create an instance of the command you pass in the time (seconds) you want it to run.

package edu.rhhs.frc.commands;

/**

  • @author rhhs
    */
    public class ConveyorTimed extends CommandBase {

    private double m_timeout;

    public ConveyorTimed(double timeout) {
    m_timeout = timeout;
    requires(m_conveyor);
    }

    protected void initialize() {
    setTimeout(m_timeout);
    m_conveyor.start();
    }

    protected void execute() {
    }

    protected boolean isFinished() {
    return isTimedOut();
    }

    protected void end() {
    m_conveyor.stop();
    }

    protected void interrupted() {
    m_conveyor.stop();
    }
    }

If you don’t want something big and fancy like ^ that guy suggested :), I would use the FPGA time method in the Utility class.

long millisecondsToRun = 1000; // This should run 1000ms = 1 s.
long initTime = Utility.getFPGATime();
while (Utility.getFPGATime() - initTime <= millisecondsToRun){
    // Place your code here.
}

What this does is:
Utility.getFPGATime() gives you a time in milliseconds, say 123400 ms. Now, you want to run your code for a continuous 2 seconds. You would then set the while loop to run your code UNTIL 2 seconds or 2000 ms has passed. So, the loop would be to run until the FPGA time is equals or greater than 125400 ms. And then, it stops running because the conditional is no longer true.

this is called “busy waiting” or “spinning” and it chews up CPU time.

not the best way to do things.

http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.54.6453&rep=rep1&type=pdf
*
*

Eh. I did say it was not big and fancy right? :wink:

Well, he could put that in its own thread implementation, but they are first year programmers after all…

Also if you don’t need interrupts it may be helpful to have a timed command class:

This class is designed for commands that don’t have interrupts and have static motor speeds.

If you wanted dynamic motor speeds you wouldn’t want to override execute.

public abstract class TimedCommand extends Command{
    
    public TimedCommand(double time){
        super(time);
    }
    
    @Override
    protected void execute() {
        //do nothing
    }

    @Override
    protected boolean isFinished() {
        return isTimedOut();
    }


    @Override
    protected void interrupted() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    
}

public class RunMotor extends TimedCommand{
    
    private static double time = 1.0;
    
    public RunMotor(){
        super(time);
    }

    @Override
    protected void initialize() {
        motor.set(1);
    }

    @Override
    protected void end() {
        motor.set(0);
    }
}

It still chews up CPU time even if it’s in its own thread.
*
*

Or you could try this:

The nice thing about this, for all of your timed commands you only have to define what its doing when its running.

public abstract class Mechanism extends Subsystem{
    
    public abstract void stop();
    
}

public abstract class TimedCommand extends Command{
    
    private Mechanism mechanism;
    
    public TimedCommand(Mechanism mechanism, double time){
        super(time);
        this.mechanism = mechanism;
        requires(mechanism);
    }
    
    @Override
    protected void execute() {
        //do nothing
    }

    @Override
    protected boolean isFinished() {
        return isTimedOut();
    }


    @Override
    protected void interrupted() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    
    @Override
    protected void end() {
        mechanism.stop();
    }
    
}
public class RunMotor extends TimedCommand{
    
    private static double time = 1.0;
    
    public RunMotor(){
        super(RobotMap.SHOOTER, time);
    }

    @Override
    protected void initialize() {
        RobotMap.SHOOTER.shoot();
    }
}

You could try this. This worked for me when I had your EXACT problem.


public void autonomous()
{
    Timer.start() //starts a timer at 0 seconds
    while(isAutonomous() && isEnabled()) //run when autonomous is Clive and you are enabled
    {
        if(Timer.get() < time) //time is a double in terms of seconds
        {
            driveVariable.drive(speed, curve); //move robot at this speed with/without curve
        }
        Timer.delay(0.005); //does nothing for 5 seconds but helps refresh motors in loop
    }
    Timer.stop() //stops timer
}

Good luck and happy competition!