Running something while a button is pressed

We have a condition where the girls want to run a section of code while a button is pressed, and if the button is released, they want the code to stop immediately - breaking out of the loop. Its been a while since I’ve programmed much, but I don’t believe the “while” statement will do that, as it only checks the condition at the start of the loop and will continue to loop again if the input condition is still true. I was trying to think of a way to program this to explain control structures further, bu I can’t think of how to do this, other than a messy sequence of constantly checking the button being pressed during the section of code.

Is there a way to do this?

by the way… we are still on cortex.

are you using vex code v5?

if (condition) {
your code
} else {
stop your code
}

“if” statement should work in your case.

1 Like

while(true){
if(Controller1.ButtonA.pressing() )
Moter1.spin}
else{
Motor1.stop()}

that should work,

WE have a large portion of code that is desired to execute, sort of a sub program to trigger a longer(time-wise) action on the field. If it was a single line of code or a couple lines, yes, the if statement woiuld work. The only way I can think of doing it is to have multlipe if statements in the larger program repeatedly. But that seems a less than elegant solution.

it does not matter if you have one line of code or a thousand lines of code. The rational is still the same. You should be able to use if or while statement. If you can post your code along with what you want to achieve, you will get more solid solution.

One way to do this in ROBOTC would be to spin off a couple of tasks:

  • Task A runs the “sub-program”, and is started when the button is pressed.
  • Task B is also started when the button is pressed, but continually checks to see if the button has been released. When that happens, it stops task A, then stops itself.

You could probably also implement the functionality of task B within the main task.

6 Likes

The if and while loops won’t do it as they only check the conditions of the button at the start. Once the items in the loop start they won’t be interrupted, they will only be restricted from starting again

Oohhh… I think I like this… something was telling me that it would involve task management.

2 Likes

I don’t have the robot here, but I’ve drafted some stuff to explain this method to the girls so they can code it the next meeting.

I guess I am a little puzzled, My first thought is this is a perfect example of a while loop. It will continue to check to see if the button it pressed and if it is it will continue running whatever is inside the loop. It doesn’t interrupt what is happening as it goes to check. If the button is no longer pressed, the program will jump out of the while loop. As for running this little piece of code at many different places in your program, I recommend setting it up as a function that you merely need to call when needed. I would write your button code roughly as follows, you can fill in the details.
while (button A is pressed)
{
setMotor ( motor port,speed);
If (button A not pressed)
{
stop Motor(motor port)
}
}

It has been a while since I have coded in Robot C, but the above if the logic I would use.

The problem with that approach in this case is that the condition is only checked at the beginning of each iteration of the while loop. @sabarrett328 wants to be able to stop the code in the middle of the contents of the loop, so just a while loop is not the solution here.

1 Like

You could Do While

   do {
      //something
   } while ( Controller1.ButtonA.pressing() );

@holbrook do you know if a wait time has to be put in the while loop within Task B?

During the summer camp building and programming the teleop on the robots, some of the kids wanted to use the buttons to move the arm up and down. When they put in something like this, the arm would jerk as it tries to move up (and very slow at it).

while(true)
{
  if(getJoystickValue(BtnRUp) == 1)
    {
       setMotorSpeed(arm, 100);
    }
   else
   {
      setMotorSpeed(arm, 0);
   }
}

What was speculated was that the brain’s cycles in were faster than the communication from the controller to the brain. So, while the first pass on the button press initiated the condition check, the next cycle by the brain didn’t detect a press from the controller.

When a wait time was put in the arm went up smoothly.

 if(getJoystickValue(BtnRUp) == 1)
    {
       setMotorSpeed(arm, 100);
       wait1Msec(100);
    }

With any constantly running while loop you would want to put a small wait at the end (10ms or so) to make sure it doesn’t eat up all of the processor. This is especially important with concurrently running while loops (tasks). I don’t know exactly why your arm was acting like that though.

I dont know how exactly robotc does it, but in java, we would use the break command to exit a loop. If robotc has anything similar, you can have an if statement in the while loop that breaks out of the while loop under a condition

c/c++ has the break keyword too, the problem with that approach is that you’d have to have a bunch of checks to see if the button has been released (and breaking out of the loop if so), one at every possible point where you might want to break out. I guess this would sort of work but it would be much more elegant to have a separate thread continually checking to see if the button has been released.

2 Likes

It’s not required, but is considered good practice, to have a short delay (10-20 ms) at the end of each iteration of an infinite loop, to provide the scheduler with an opportunity to service another task.


That seems unlikely to me.

It’s difficult to say exactly what caused the behavior you described without seeing the whole program in question. However, a common cause of behavior like that is to architect the code like this:

if (button a pressed){
    //spin motor forwards
}
else{
    //stop motor
}

if (button b pressed){
    //spin motor backwards
}
else{
    //stop motor
}

The problem with this code is that if (for example) you press button A, then the first if/else statement spins the motor forward, and the second if/else statement stops the motor. Put the whole thing in an infinite loop and hold down button A, and you have the motor being intermittently told to spin and stop at a fast interval, which can result in the motor “jerking”.

The solution is to structure the code like this instead:

if (button a pressed){
    //spin motor forwards
}
else if (button b pressed){
    //spin motor backwards
}
else{
    //stop motor
}
2 Likes

When I get a chance and the girls code this on the bot, I’ll report back. Right now I’m sketching up notes to explain more of tasking and how to watch the conditions of the buttons in tasks. Two tasks. One will run the macro when the button is pressed, the other will stop the macro task if the button is released.

My understanding of a while loop is that the input condition is checked at the start of the loop, and if true, executes the loop fully before it checks the input condition again. If it’s true again, it executes the loop fully again. If not, it bypasses the loop and continues the program. What they want to do is break out of the loop mid cycle And go do something else if the button is released.

1 Like