Programming Using A Toggle Function

Is there a way to make a function on the robot to be able to toggle? I have tried things like

int variable = 0;

if (buttonPressed && variable%2 == 0) {
//do something
variable += 1;
} else if (otherButtonPressed && variable%2 == 1) {
//do the other thing
variable += 1;
}

But I am having problems with this as the program is constantly switching between the two when I press the button. If I hold down the button, the variable will switch from 1 to 0 and then from 0 to 1 infinitely until I stop holding the button down. So if I just tap the button, it probably switches like 5 times or 6 or maybe 4 because every tap can’t be exactly the same. It is not accurate and fails a lot. Am I just a noob or is this a common problem?

My solution to this is set a variable when button is pressed and reset it when it is not. If the button is being pressed but the variable is still set, it doesn’t run

2 Likes

Your program is looping many times a second. So by the time you’ve released the button, the program has looped like 5 times. We can counteract this by not only checking to see if the button is currently pressed, but also checking if the button was not pressed in the last run.

int variable = 0;
bool last = false;

if (buttonPressed && !last && variable%2 == 0) {
//do something
last = true;
variable += 1;
} else if (buttonPressed && !last && variable%2 == 1) {
//do the other thing
last = true;
variable += 1;
}
else if (!buttonPressed) {
last = false;
}

Also, if you have a boolean in C++, you can make the boolean equal to its opposite state using ! (the not operator). We can use this to simplify your code a bit. So if you wanted to toggle a variable called state, you would do state = !state; So the code would look a bit more like

bool state = false;
bool last = false;

while(true) {
   if(button && !last) {
      state = !state;
      last = true;
   } else if(!button) {
      last = false;
   }

   if(state) {
      //Do thing 1
   } else {
      //Do thing 2
   }
}
7 Likes

I am glad that there are good people out there willing to help one another out. I have been on forums before where I will ask a question, and people, even though they probably have the answer, don’t reply. Thank you all!

1 Like

I’m having an issue with this piece of code. The toggle does work, but it stops all other code from running. I suspect this is because the code is in a while (true) { } loop, and when I take the while (true) out of the code my other code works but the toggle function breaks and I have to hold the button. I can upload my full code if needed.

Uploading your code will be needed. You don’t need to upload your full code, but just the part that contains the button press. My guess without looking at your code is that you are either:

  1. Not running your code in a task
    or
  2. You don’t have a delay in your while loop

Here is the code with the while (true) loop. The toggle works fine but nothing else works:

while (true) {
if (MainController.ButtonDown.pressing () == true && !ConveyerLast) {
ConveyerState = !ConveyerState;
ConveyerLast = true;
}

else if (!MainController.ButtonDown.pressing () == true) {
  ConveyerLast = false;
}

if (MainController.ButtonRight.pressing () == true) {
  ConveyerMotor.spin (directionType::rev, 100, velocityUnits::pct);
}

else if (ConveyerState) {
  ConveyerMotor.spin (directionType::fwd, 100, velocityUnits::pct);
}

else {
  ConveyerMotor.stop ();
}

}

Copy Paste ruins indentation

You’re good, I have had problems with that in the past your code is still readable.

So you are going to need to put your code in a task. Tasks allow you to do multiple drive functions at once without blocking everything else from running. Since your code runs your conveyor:

int toggleLift() {
    while(true) {
        if (MainController.ButtonDown.pressing () == true && !ConveyerLast) {

        ConveyerState = !ConveyerState;
        ConveyerLast = true;

        } else if (!MainController.ButtonDown.pressing () == true) {

        ConveyerLast = false;

        }

        if (MainController.ButtonRight.pressing () == true) {

           ConveyerMotor.spin (directionType::rev, 100, velocityUnits::pct);

        } else if (ConveyerState) {

          ConveyerMotor.spin (directionType::fwd, 100, velocityUnits::pct);

        } else {

          ConveyerMotor.stop ();

        }
    task::sleep(50); //This is the delay that is needed at the end
    }
return 1; //Tasks must return 1 for some reason.
}

This is an example of a task. Tasks have to be of type int, they have to have a delay at the end of the while loop, and the task has to return 1. You may have to modify the body of the task (inside the while loop) to fit your robot’s needs. Once the task is created, you can run it in usercontrol like so:

task toggleLiftTask(toggleLift);

I advise that you do this for all of your drive functions (the drive movements, ring conveyor, any bar lifts, etc.). Hope this helps!

2 Likes

Thank you so much for coming back and replying to this thread after 2 years. I will implement this into my code. I really appreciate the quick and thorough response!

you’re welcome! I hope this helps your team out a lot!

I spent quite a while trying to implement your tips into my code. Here is my full code. If there are any obvious issues please let me know. I appreciate all your help so far. Full Code Upload (indentation is messed up by copy paste):

//Vex Start
#include "vex.h"
#include "cmath"

using namespace vex;

//Define Devices
competition Competition;
controller MainController = controller();
controller SecondaryController = controller();
motor DriveRFront = motor(PORT8, ratio18_1, true);
motor DriveRBack = motor(PORT7, ratio18_1, true);
motor DriveLFront = motor(PORT9, ratio18_1, false);
motor DriveLBack = motor(PORT6, ratio18_1, false);
motor MainLift = motor(PORT18, ratio18_1, false);
motor GoalLift = motor(PORT14, ratio36_1, true);
motor ConveyerMotor = motor(PORT17, ratio18_1, false);
motor ClampMotor = motor(PORT15, ratio36_1, true);

//Pre Auton Code (Configuration)
void pre_auton(void) {
  
  vexcodeInit();

//General Motor Config

  //Main Lift Config
  MainLift.setMaxTorque (100, percent);
  MainLift.setVelocity(100, percent);
  MainLift.setStopping (hold);

  //Goal Lift Config
  GoalLift.setMaxTorque (100, percent);
  GoalLift.setVelocity (100, percent);
  GoalLift.setStopping (brake);

  //Conveyer Config (ADJUST VELOCITY)
  ConveyerMotor.setMaxTorque (100, percent);
  ConveyerMotor.setVelocity (90, percent);
  ConveyerMotor.setStopping (brake);

  //Goal Clamp Config
  ClampMotor.setMaxTorque (100, percent);
  ClampMotor.setVelocity (100, percent);
  ClampMotor.setStopping (hold);

  //Drive Base Config
  
    //Torque Config
    DriveRFront.setMaxTorque (100, percent);
    DriveRBack.setMaxTorque (100, percent);
    DriveLFront.setMaxTorque (100, percent);
    DriveLBack.setMaxTorque (100, percent);
    
    //Velocity Config
    DriveRFront.setVelocity (100, percent);
    DriveRBack.setVelocity (100, percent);
    DriveLFront.setVelocity (100, percent);
    DriveLBack.setVelocity (100, percent);
    
    //Stopping Mode Config
    DriveRFront.setStopping (brake);
    DriveRBack.setStopping (brake);
    DriveLFront.setStopping (brake);
    DriveLBack.setStopping (brake);

}

//Autonomous Function Define

  //Drivebase Forward
  void drivefwd (int autonspeed, int duration) {
    DriveRFront.spin(directionType::fwd, autonspeed, velocityUnits::pct);
    DriveRBack.spin(directionType::fwd, autonspeed, velocityUnits::pct);
    DriveLFront.spin(directionType::fwd, autonspeed, velocityUnits::pct);
    DriveLBack.spin(directionType::fwd, autonspeed, velocityUnits::pct);
    task::sleep(duration);
    DriveRFront.stop();
    DriveRBack.stop();
    DriveLFront.stop();
    DriveLBack.stop();

  } 
  
  //Drivebase Reverse
  void driverev (int autonspeed, int duration) {
    DriveRFront.spin(directionType::rev, autonspeed, velocityUnits::pct);
    DriveRBack.spin(directionType::rev, autonspeed, velocityUnits::pct);
    DriveLFront.spin(directionType::rev, autonspeed, velocityUnits::pct);
    DriveLBack.spin(directionType::rev, autonspeed, velocityUnits::pct);
    task::sleep(duration);
    DriveRFront.stop();
    DriveRBack.stop();
    DriveLFront.stop();
    DriveLBack.stop();
  } 

const float TurnMultiplier = 0.35;

  //Drivebase Turn Left
  void driveleft (int Velocity, int turnangle) {
    DriveRFront.resetPosition();

      while (std::abs (DriveRFront.rotation(rotationUnits::deg) * TurnMultiplier) < turnangle) {
        DriveRFront.spin(directionType::fwd, Velocity, velocityUnits::pct);
        DriveRBack.spin(directionType::fwd, Velocity, velocityUnits::pct);
        DriveLFront.spin(directionType::fwd, -Velocity, velocityUnits::pct);
        DriveLBack.spin(directionType::fwd, -Velocity, velocityUnits::pct);
      }

    DriveRFront.stop();
    DriveRBack.stop();
    DriveLFront.stop();
    DriveLBack.stop();
  }

  //Drivebase Turn Right
  void driveright (int Velocity, int turnangle) {
    DriveRFront.resetPosition();

      while (std::abs (DriveRFront.rotation(rotationUnits::deg) * TurnMultiplier) < turnangle) {
        DriveRFront.spin(directionType::fwd, -Velocity, velocityUnits::pct);
        DriveRBack.spin(directionType::fwd, -Velocity, velocityUnits::pct);
        DriveLFront.spin(directionType::fwd, Velocity, velocityUnits::pct);
        DriveLBack.spin(directionType::fwd, Velocity, velocityUnits::pct);
      }

    DriveRFront.stop();
    DriveRBack.stop();
    DriveLFront.stop();
    DriveLBack.stop();
  }

    //Drivebase Stop
  void drivestop () {
    DriveRFront.stop ();
    DriveRBack.stop ();
    DriveLFront.stop ();
    DriveLBack.stop ();
  }

  //Drivebase Set Stop Hold
  void drivehold () {
    DriveRFront.setStopping(hold);
    DriveRBack.setStopping(hold);
    DriveLFront.setStopping(hold);
    DriveLBack.setStopping(hold);
  }

  //Drivebase Set Stop Brake
  void drivebrake () {
    DriveRFront.setStopping(brake);
    DriveRBack.setStopping(brake);
    DriveLBack.setStopping(brake);
    DriveLFront.setStopping(brake);
  }

  //Drivebase Set Stop Brake
  void drivecoastduration (int duration) {
    DriveRFront.stop();
    DriveRBack.stop();
    DriveLFront.stop();
    DriveLBack.stop();
    DriveRFront.setStopping(coast);
    DriveRBack.setStopping(coast);
    DriveLFront.setStopping(coast);
    DriveLBack.setStopping(coast);
    task::sleep(duration);
    DriveRFront.stop();
    DriveRBack.stop();
    DriveLFront.stop();
    DriveLBack.stop();
  }

  void drivecoast () {
    DriveRFront.stop();
    DriveRBack.stop();
    DriveLFront.stop();
    DriveLBack.stop();
    DriveRFront.setStopping(coast);
    DriveRBack.setStopping(coast);
    DriveLFront.setStopping(coast);
    DriveLBack.setStopping(coast);
  }

  //Main Lift Up
  void mainliftup (int autonspeed, int duration) {
    MainLift.spin(directionType::fwd, autonspeed, velocityUnits::pct);
    task::sleep(duration);
    MainLift.stop();
  }
  
  //Main Lift Down
  void mainliftdown (int autonspeed, int duration) {
    MainLift.spin(directionType::rev, autonspeed, velocityUnits::pct);
    task::sleep(duration);
    MainLift.stop();
  }

  //Main Lift Stop
  void mainliftstop () {
    MainLift.stop();
  }

  //Min Lift Set Stop Hold
  void mainlifthold () {
    MainLift.setStopping(hold);
  }

  //Main Lift Set Stop Brake
  void mainliftbrake () {
    MainLift.setStopping(brake);
  }

  //Main Lift Set Stop Coast
  void mainliftcoast () {
    MainLift.setStopping(coast);
  }

  void clampdown () {
    ClampMotor.spin(directionType::fwd);
  }

  void clampup () {
    ClampMotor.spinTo (double (100), deg);
  }

  //Goal Lift Up
  void goalliftup (int autonspeed, int duration) {
    GoalLift.spin(directionType::fwd, autonspeed, velocityUnits::pct);
    task::sleep(duration);
    GoalLift.stop();
  }

  //Goal Lift Down
  void goalliftdown (int autonspeed, int duration) {
    GoalLift.spin(directionType::rev, autonspeed, velocityUnits::pct);
    task::sleep(duration);
    GoalLift.stop();
  }

  //Goal Lift Stop
  void goalliftstop () {
    GoalLift.stop();
  }

  //Goal Lift Set Stop Hold
  void goallifthold () {
    GoalLift.setStopping(hold);
  }

  //Goal Lift Set Stop Brake
  void goalliftbrake () {
    GoalLift.setStopping(brake);
  }

  //Goal Lift Set Stop Coast
  void goalliftcoast () {
    GoalLift.setStopping(coast);
  }

  //Spins Conveyer Belt Forwards
  void conveyerfwd () {
    ConveyerMotor.spin(directionType::fwd);
  }

  //Spins Conveyer Belt Backwards
  void conveyerrev () {
    ConveyerMotor.spin(directionType::rev);
  }

//Auton Code
void autonomous(void) {

  drivebrake();
  goallifthold();
  mainlifthold();
  goalliftdown (100,2000);
  drivefwd (30, 700);
  goalliftup (100, 2500);
  driverev (30, 700);
  driveleft (50, 90);
  mainliftup (100, 500);
  drivefwd (60, 700);
  driveleft (50, 90);
  drivefwd (30, 2000);
  goalliftdown (100, 2000);
}

int toggleConveyer () {

  bool ConveyerState = false;
  bool ConveyerLast = false;

    while (true) {

      if (MainController.ButtonDown.pressing () == true && !ConveyerLast) {
        ConveyerState = !ConveyerState;
        ConveyerLast = true;
      }

      else if (!MainController.ButtonDown.pressing () == true) {
        ConveyerLast = false;
      }

      if (ConveyerState) {
        ConveyerMotor.spin (directionType::fwd, 100, velocityUnits::pct);
      }

      else {
        ConveyerMotor.stop ();
      }
    task::sleep (50);
  }
return 1;
}

int toggleClamp () {

    bool GoalClampState = false;
    bool GoalClampLast = false;

    while (true) {
      if (MainController.ButtonB.pressing () == true && !GoalClampLast) {
        GoalClampState = !GoalClampState;
        GoalClampLast = true;
      }

      else if (!MainController.ButtonB.pressing () == true) {
        GoalClampLast = false;
      }

      if (GoalClampState) {
        ClampMotor.spin (directionType::fwd, 100, velocityUnits::pct);
      }

      else {
        ConveyerMotor.spinTo (double (90), rotationUnits::deg);
      }

    task::sleep (50);
    }
return 1;
}

int runMainLift () {
    //Main Lift Up 
  if (MainController.ButtonR1.pressing () == true) { 
    MainLift.spin (directionType::fwd, 100, velocityUnits::pct);
  }
  
  //Main Lift Down
  else if (MainController.ButtonR2.pressing () == true) {
    MainLift.spin (directionType::rev, 100, velocityUnits::pct);
  }

  //Stop Main Lift Motors
  else {
    MainLift.stop();
    MainLift.setStopping(hold);
  }

return 1;
}

int runGoalLift () {
  //Goal Lift Code

  //Goal Lift Up
  if (MainController.ButtonL1.pressing () == true) {
    GoalLift.spin (directionType::fwd, 100, velocityUnits::pct);
  }

  //Goal Lift Down
  else if (MainController.ButtonL2.pressing () == true) {
    GoalLift.spin (directionType::rev, 100, velocityUnits::pct);
  }
  
  //Stop Goal Lift Motor
  else {
    GoalLift.stop();
    GoalLift.setStopping(hold);
  }

return 1;
}

int runMainDrive () {
  //Drivetrain Axis Config
  int axis3original = MainController.Axis3.position(percentUnits::pct);
  int axis3mapped = 0.00008 * pow(axis3original, 3) + 0.2 * axis3original;
  int axis4original = MainController.Axis4.position(percentUnits::pct);
  int axis4mapped = 0.00008 * pow(axis4original, 3) + 0.2 * axis4original;;

  //Drivetrain Motor Control
  DriveRFront.spin(directionType::fwd, axis3mapped - axis4mapped, velocityUnits::pct);
  DriveRBack.spin(directionType::fwd, axis3mapped - axis4mapped, velocityUnits::pct);
  DriveLFront.spin(directionType::fwd, axis3mapped + axis4mapped, velocityUnits::pct);
  DriveLBack.spin(directionType::fwd, axis3mapped + axis4mapped, velocityUnits::pct);

return 1;
}

//Driver Control Code
void usercontrol(void) {
    
  while (1) {

task runMainDriveTask (runMainDrive);

task runMainLiftTask (runMainLift);

task runGoalLiftTask (runGoalLift);

task toggleConveyerTask (toggleConveyer);

task toggleClampTask (toggleClamp);

  //Vex Wait
  wait (20, msec); 
  }
}

//Vex Loop
int main() {

  Competition.autonomous(autonomous);
  Competition.drivercontrol(usercontrol);

  pre_auton();

  while (true) {
    wait(100, msec);
  }
}

edit by mods: code tags added, please try and remember to use them.

Don’t create tasks in a while loop, this will constantly keep recreating them.

//Driver Control Code
void usercontrol(void) {
    
  while (1) {

task runMainDriveTask (runMainDrive);

task runMainLiftTask (runMainLift);

task runGoalLiftTask (runGoalLift);

task toggleConveyerTask (toggleConveyer);

task toggleClampTask (toggleClamp);

  //Vex Wait
  wait (20, msec); 
  }
}

also, have a read through this for some advice on task management when using competition control.

6 Likes

I tried running the tasks in driver/user control without the while (1) {} loop if that’s what you meant and nothing was ran. no driving or motor action at all. if you could clarify exactly where the loop to remove is or provide an example that would be great. I also tried removing the while (true) {} loop inside the task for the toggles and that didn’t help anything either. (not sure if I should use tags on this post)

Just move the tasks outside of the while loop and keep everything else in. Otherwise, the whole driver control code will only run once at the start for less than a millisecond, and you won’t be able to do anything.

1 Like

Everything works correctly except for the clamp. I’m not sure what the error is here since the code for the clamp is basically identical to the conveyer. The goal for the clamp is to press a button, have it spin forward in order to clamp onto a goal, and then press the button again for the clamp to spin backwards to a set degree and stay there. I can clarify if needed. Also I cannot figure out how to add tags for the life of me.

int toggleConveyer () {

bool ConveyerState = false;
bool ConveyerLast = false;

while (true) {

  if (MainController.ButtonDown.pressing () == true && !ConveyerLast) {
    ConveyerState = !ConveyerState;
    ConveyerLast = true;
  }

  else if (!MainController.ButtonDown.pressing () == true) {
    ConveyerLast = false;
  }

  if (ConveyerState) {
    ConveyerMotor.spin (directionType::fwd, 100, velocityUnits::pct);
  }

  else {
    ConveyerMotor.stop ();
  }
task::sleep (50);
}

return 1;
}

int toggleClamp () {

bool GoalClampState = false;
bool GoalClampLast = false;

while (true) {
  
  if (MainController.ButtonB.pressing () == true && !GoalClampLast) {
    GoalClampState = !GoalClampState;
    GoalClampLast = true;
  }

  else if (!MainController.ButtonB.pressing () == true) {
    GoalClampLast = false;
  }

  if (GoalClampState) {
    ClampMotor.spin (directionType::fwd, 100, velocityUnits::pct);
  }

  else {
    ConveyerMotor.spinTo (double (90), rotationUnits::deg);
  }
task::sleep (50);
}

return 1;
}

//Auton Code
void autonomous(void) {

drivebrake();
goallifthold();
mainlifthold();
goalliftdown (100,2000);
drivefwd (30, 700);
goalliftup (100, 2500);
driverev (30, 700);
driveleft (50, 90);
mainliftup (100, 500);
drivefwd (60, 700);
driveleft (50, 90);
drivefwd (30, 2000);
goalliftdown (100, 2000);
}

//Driver Control Code
void usercontrol(void) {

task toggleConveyerTask (toggleConveyer);

task toggleClampTask (toggleClamp);

while (1) {

//Drive Base Code

//Drivetrain Axis Config
int axis3original = MainController.Axis3.position(percentUnits::pct);
int axis3mapped = 0.00008 * pow(axis3original, 3) + 0.2 * axis3original;
int axis4original = MainController.Axis4.position(percentUnits::pct);
int axis4mapped = 0.00008 * pow(axis4original, 3) + 0.2 * axis4original;;

//Drivetrain Motor Control
DriveRFront.spin(directionType::fwd, axis3mapped - axis4mapped, velocityUnits::pct);
DriveRBack.spin(directionType::fwd, axis3mapped - axis4mapped, velocityUnits::pct);
DriveLFront.spin(directionType::fwd, axis3mapped + axis4mapped, velocityUnits::pct);
DriveLBack.spin(directionType::fwd, axis3mapped + axis4mapped, velocityUnits::pct);

if (MainController.ButtonR1.pressing () == true) { 
  MainLift.spin (directionType::fwd, 100, velocityUnits::pct);
}

//Main Lift Code

//Main Lift Down
else if (MainController.ButtonR2.pressing () == true) {
  MainLift.spin (directionType::rev, 100, velocityUnits::pct);
}

//Stop Main Lift Motors
else {
  MainLift.stop();
  MainLift.setStopping(hold);
}

//Goal Lift Code

//Goal Lift Up
if (MainController.ButtonL1.pressing () == true) {
  GoalLift.spin (directionType::fwd, 100, velocityUnits::pct);
}

//Goal Lift Down
else if (MainController.ButtonL2.pressing () == true) {
  GoalLift.spin (directionType::rev, 100, velocityUnits::pct);
}

//Stop Goal Lift Motor
else {
  GoalLift.stop();
  GoalLift.setStopping(hold);
}

}

//Vex Wait
wait (20, msec);
}

You are spinning the conveyor motor instead of the clamp motor.

I am an absolute baffoon, Thank you so much for pointing out my error. Happy New Year!

Happens to all of us. Happy New Year!