hi i am making a robot for vex cortex that is a race car for my senior project in high school.
i am trying to make a toggle switch program that enables me to switch between autonomous and driver controlled to convey the concept. in essence the car just follows a wall while in autonomous.
but i cant switch it from driver controlled to autonomous. any suggestions?
#pragma config(Sensor, dgtl9, sideSonar, sensorSONAR_inch)
#pragma config(Sensor, dgtl11, frontSonar, sensorSONAR_inch)
#pragma config(Motor, port2, servoMotor, tmotorServoStandard, openLoop)
#pragma config(Motor, port3, leftMotor, tmotorServoContinuousRotation, openLoop)
#pragma config(Motor, port4, rightMotor, tmotorServoContinuousRotation, openLoop, reversed)
task main()
{
int buttonPressed=0;
int buttonState=0;
while(1==1){
if(vexRT[Btn6U]==1){
if(buttonState==0){
buttonState=buttonState+1;}
if(buttonState==1){
buttonState=buttonState-1;}
}
if(buttonState==0){
motor[rightMotor] = vexRT[Ch3];
motor[leftMotor] = vexRT[Ch3];
motor[servoMotor] = vexRT[Ch4]+30;}
if(buttonState==1){
if(SensorValue(sideSonar))
motor[servoMotor]=30+6.5*(-5+ SensorValue(sideSonar)); //if robot is more than 5in from wall then turn towards wall
motor[leftMotor]=127; //set left motor to full power
motor[rightMotor]=127; //set right motor to full power}
}
}
}
When you (the user) press Button 6U, it runs all the code in the outer if block in the quote.
Suppose buttonState was 0. It would then set buttonState to 1 in the first nested if block, which would then make the second nested if block’s condition true, resulting in buttonState being set back to 0 again.
RobotC actually has a built in competition switch. When you download the program to the robot and brings up the debugger, go to: robot --> debugger windows --> competition control and click it. Then it brings up a little competition control that you can use. You still have to start the program however but after you do so you may use the competition control to switch to disabled, user control, or autonomous modes.
This way, buttonState is always incremented by 1 when you press the button. If buttonState is 0, driver control runs. If buttonState is 1, autonomous runs. If buttonState is 2, it gets reset to 0 and runs driver.
The addition of the pressed variable prevents the code from being unintentionally executed multiple times when you press the button once (since the infinite loop iterates multiple times in the time it takes a human to press and release a button). Basically, when you press the button, it sets pressed to 1, preventing the first if block from running. When you release the button, though, the third if block runs, thereby ‘unlocking’ the first if block to be run again.
Note that you will have to declare the pressed variable and set it to 0 earlier in the code for this to work.
Note to those experienced in C: I know this code can be condensed quite a bit. I’m not doing that here for ease of understanding.
thank you it works like a charm. now i am just changing how hard it turns during autonomous and etc.
but if we were to simplify the code would the code be run more often and therefor be run more smoothly and turns would be less jerky for autonomous.
Switching a variable back and fourth between 0 and 1 is a common problem in programming. It can be achieved with a series of “if” statements but it gets a bit more complicated. A simple approach is to find a function, f(x), such that f(0)=1 and f(1)=0 and feed your variable into it each time the button is pressed. The simplest such function I can think of is f(x)=1-x
The problem is your program will keep looping and will switch back and fourth as long as the button is held down. To fix this add a while loop that suspends the flow as long as the button is down.
This will also suspend the flow of your main loop and will lock up your robot as long as the button is held down. To fix that you can put this toggle code in a separate task.
Here is another technique we use that I have modified for his purpose.
2 global variables, or at lease outside of your Main while loop.
boolean runAton = false;
int btnAton = 0;
Then this code as the start of your main loop:
if(vexRT(Btn6U) != btnAton){ //See if 6U is different from our last known reading
btnAton = vexRT(Btn6U);
if(vexRT(Btn6U) == 1){ // If 6U is different, see if it is pressed
//So 6U was pressed, changed our aton state
if(runAton == true)
runAton = false;
else
runAton = true;
}
}
Then after this for the main loop, you have a main fork for the if statement that checks our runAton variable.
if(runAton == true) {
//our simulated Autonomous code goes here
}
else {
//our normal driver code goes here
}
The great thing about programming is there are always more than one way to do anything, I just hate using wait1Msec() commands inside the Main loop. I’m used to programming on an arduino and checking against millis() to do time delays so as to not lock up the rest of the program.
I can write some full code tonight for an example, but it’s kind of a debounce. So it just checks if the state of the button has changed, and if it had changed, see if it was a press of the button. If we had pressed the button, then change the boolean. So you can keep the button held down and it won’t keep flip flopping the boolean. I guess you could change it to start an aton task and end a “user” task, and the opposite instead of flipping a boolean, but I try to use as few tasks as possbile unless necessary.