Single button Pneumatic toggle not working but two button does

Our team wants to use a single controller button to raise a pneumatic, and then pressing it again to lower it. He was able to use one Vuitton to raise and a different to lower by using the following:


pros::ADIDigitalOut wingMech('G');

void opcontrol() {
    while (true) {
        // if else for each controller button
        if(…){
        } else if(controller.get_digital(pros::E_CONTROLLER_DIGITAL_L2)){
            wingMech.set_value(LOW);

        } else if(controller.get_digital(pros::E_CONTROLLER_DIGITAL_L1)){
            wingMech.set_value(HIGH);

        } else {
            \\ turn off drive and intake motors
        }

We tried to use this, but the mech just stayed in the up position:

pros::ADIDigitalOut wingMech('G');

void opcontrol() {
    bool position = false;
    while (true) {
        if(){
        } else if(controller.get_digital(pros::E_CONTROLLER_DIGITAL_L2)){
            position = !position;
            wingMech.set_value(position);

Any hints on how to get this to work? Do I need a separate task to send this to, and monitor when the button is actually released, only toggling the position when the button first changes from “not pressed” to “pressed”. Anyone have example code?

I’m not a professional so you don’t have to listen but I use a variable and changing it is easier for me. cant explain it so I’ll just give you what I have until you find a better alternative.
if (Controller1.ButtonX.pressing() && !(Rx == 1.0)) {
DigitalOutB.set(false);
Rx = 1.0;
waitUntil((!Controller1.ButtonX.pressing()));
}
else {
if (Controller1.ButtonX.pressing() && Rx == 1.0) {
DigitalOutB.set(true);
Rx = 0.0;
waitUntil((!Controller1.ButtonX.pressing()));
}

My team has the same problem, too. We tried to change it instead to a hold code where the driver just holds down a button for the wing to go up and let go to make it go down but that didn’t work. We will let you know when we find a solution. Sorry that we weren’t that much help.

For this you don’t actually need a variable because you can just use the value of the digital out like this:

if(Controller1.ButtonX.pressing()&&DigitalOutB.value()) {
     DigitalOutB.set(false); 
     waitUntil((!Controller1.ButtonX.pressing()));
}else if(Controller1.ButtonX.pressing()&&!DigitalOutB.value()) {
     DigitalOutB.set(true);
     waitUntil((!Controller1.ButtonX.pressing()));
}

You could simply use an event.

digital_out DigitalOutB = digital_out(Brain.ThreeWirePort.B);

bool IsExt = false;  //variable to maintain state

void MovePneumatic2() {
  IsExt = !IsExt;  //alternates in/out
  DigitalOutB.set(IsExt);
}


int main() {
  vexcodeInit();

  //Register event to button press
  Controller1.ButtonX.pressed(MovePneumatic2);

  wait(15, msec);
  whenStarted1();
}

A clean way to get a toggle without having any waits is to use a callback function.

Create callbacks in

int Main{

// callback functions
  Controller1.ButtonA.pressed(toggle_loader);

  Controller1.ButtonB.pressed(toggle_hook);
}

Then set global Booleans to hold the state of the digital out and invert it on button press.

// callback functions
bool loader_position = true; // initiate a global to hold the loader position
void toggle_loader(){ // callback function initiated in int main
  loader_position = !loader_position; // set position to not position
  air_loader_A.set(loader_position);
}

bool hook_position = true; // initiate a global to hold the hook position
void toggle_hook(){ // callback function initiated in int main
  hook_position = !hook_position; // set position to not position
  air_hook_B.set(hook_position);
}

I just noticed that EZtemplate has a piston object that might do everything we need. I’ll compare these answers with that to see what looks like it’ll work the best.

OP was using PROS, however.

It can be even simpler, there are overloaded operators for digital_out (and pneumatics which is sub class of digital_out), so you can do this.

// A global instance of vex::brain used for printing to the EXP brain screen
vex::brain       Brain;

// define your global instances of motors and other devices here
vex::digital_out   dig(Brain.ThreeWirePort.A);

void
toggle_dig() {
    dig = !dig;
}

int main() {
    Brain.buttonCheck.pressed(toggle_dig);

    while(1) {       
        // Allow other tasks to run
        this_thread::sleep_for(10);
    }
}

(that’s for EXP, but V5 is the same using a controller button)

or as 1 line

    Brain.buttonCheck.pressed( []() { dig = !dig; } );

so we were wondering if it would be possible to do this with block code. right now we have this:


but we dont have access to our robot right now, so we were wondering if it would work,thanks!

This won’t work. Both if statements will only run once and then never again. Add a forever loop around each if statement to fix it.