So I saw this thread last night one button as two-state switch? I saw that all these examples are not in VCS C++ and tried to make it into VCS.
void (BallIntakeToggle)
{
bool Toggle = false;
bool Pressed = false;
if (Controller1.ButtonL2.pressing)
{
if (Controller1.ButtonL2.released)
{
Toggle = !Toggle;
}
}
if (Toggle = true)
{
BallIntake.spin(directionType::fwd);
}
else
{
BallIntake.stop();
}
}
int main()
{
while (1)
{
Controller1.ButtonL2.pressed(BallIntakeToggle)();
}
}
I came up with a quite a bit of errors and didn’t know how to fix it, any help would be appreciated.
Here are the errors I came across by the way
18:20:04 -- error -- In file included from cxx_entry.cpp:16:
./main.cpp:2:7: error: variable has incomplete type 'void'
void (BallIntakeToggle)
^
./main.cpp:4:10:
18:20:04 -- error -- error: expected '(' for function-style cast or type construction
bool Toggle = false;
~~~~ ^
./main.cpp:24:2:
18:20:04 -- error -- error: expected ';' after top level declarator
}
^
You aren’t declaring the function properly it should be
void BallIntakeToggle()
Also when you check if the button is pressed you are checking if it’s released right after(You would need superhuman speed for that to work)
And the bools are declared inside the function so every time you call it they will be reset to false, you can fix that by making them global.
And i think setting the function for when the button is pressed down would cause some problems
This should fix everything:
bool Toggle = false;
bool Pressed = false;
void BallIntakeToggle()
{
if (Controller1.ButtonL2.pressing())
{
if (!Pressed){
Toggle = !Toggle;
Pressed = true;
}
}
else {
Pressed = false;
}
if (Toggle)
{
BallIntake.spin(directionType::fwd);
}
else
{
BallIntake.stop();
}
}
int main()
{
while (1)
{
BallIntakeToggle();
}
}
ok, lots of issues in original and some in the revised version posted by @eggplant.
Controller1.ButtonL2.pressed(BallIntakeToggle);
should not be in a loop.
no need for this test
if (Controller1.ButtonL2.pressing()
you can only enter BallIntakeToggle on the pressed event so no need to test for pressing, it has to be true unless the event was blocked from running for a pretty long time.
Here is revised version.
void BallIntakeToggle()
{
static bool Toggle = false;
Toggle = !Toggle;
if (Toggle == true)
{
//BallIntake.spin(directionType::fwd);
Brain.Screen.printAt( 10, 30, "spin");
}
else
{
//BallIntake.stop();
Brain.Screen.printAt( 10, 30, "stop");
}
}
int main()
{
Controller1.ButtonL2.pressed(BallIntakeToggle);
while (1)
{
this_thread::sleep_for(10);
}
}
( I have no motor connected so I just tested with Brain.Screen.print)
@jpearman @eggplant Thanks for the help it’s working now 
The ‘static’ keyword that James added is really important: static tells the variable to stick around. Normally any variables you declare inside a function/method are discarded when the function ends. This makes it work similarly to how a global variable works, in that its value is persistent, but also prevents anything outside of the function/method from changing it.
This does mean, though, that with just this toggle function you can’t affect the toggle state from anywhere else. The full Monty in an object oriented language for handling the ball intake’s state would be to create a Ball_Intake class, with a private member variable to hold the toggle state:
public class Ball_Intake
{
private bool ToggledOnState = false;
private vex::motor mMotor;
public Ball_Intake(vex::motor init_motor)
{
mMotor = init_motor;
}
public Ball_Intake(int portIndex, vex::gearSetting gsetting)
{
mMotor = vex::motor(portIndex, gsetting);
}
public void toggle()
{
ToggledOnState = !ToggledOnState;
//rest of the method body
}
public void stop()
{
ToggledOnState = false;
mMotor.stop();
}
public void start()
{
ToggledOnState = true;
mMotor.spin(vex::directionType::fwd);
}
//other methods and members
};
int main()
{
intake = Ball_Intake(INTAKE_PORT, INTAKE_GEAR_RATIO);
intake.start();
intake.toggle();
intake.stop();
//etc.
}
The VCS and RMS motor APIs include an “isSpinning” method for the vex::motor class, but rather than refer to if the motor wants to be spinning or not it refers to whether a rotateFor or rotateTo command is in progress and doesn’t change state when given an ongoing command such as motor::spin, so we have to have some wrapper instead. Also important is to include something like this in a thread somewhere:
while(true)
{
if (!mCompetition.isEnabled())
{
intake.stop();
//other things that need to be notified that the robot was disabled
}
this_thread::sleep_for(10);
}
or the wrapper class won’t know that VEXos stopped the motor when the robot was disabled.