wait1Msec doesn’t return a value since it’s a built-in void function
As Sunny mentioned, use a timer that returns a value
RobotC syntax is ClearTimer(T1); then time1[T1] to retrieve the value, if I remember correctly
You can also use time100[T1] and wait for 30 tenths of a second, since your value doesn’t seem to require high precision
OK so now the timer works, BUT the bumper is not working. I tested the bumper without the wait statement together, so the bumper is working. What is the problem this time? This is my current code:
If that is your whole program, unless you are holding the bumper in when you start the bot it is just going to exit. You need to put the whole thing inside another while (true) { } loop to keep it going and going. Additionally, I think the bump sensor is only going to do anything while it is pressed. And since the timer starts at the beginning, I think it will keep moving at the beginning via the timer and not the bumper.
So if this is your entire bot, you should be fairly safe… but I personally don’t like using while loops because then you get stuck in a bit of code and can’t respond to anything else. For a 1 motor, 1 sensor bot this may not be a big deal. Instead, you can make use of the time still but not use a while loop.
The below code is a bit over complicated for the simple task above (and it probably doesn’t work right because I only compiled it, I didn’t test it), but should be easier to expand and allow you to do other things at the same time. The main benefit (to me) is it gives you better information about the buttons. The SensorValue[bump] reads that value instantly, so putting it inside an if or while statement means it will only run when the button is physically held down. By watching for the button state and storing a few values, you can instead see when the button is down (held down), that it was pressed and then released and keep track of how many times it was pressed. And by using if statements with timers (or something else) that finish immediately instead of getting stuck inside a loop, you can continue to act on other things.
I also use this sort of code to use the 4 back buttons on the controller as buttons, which can be useful for a variety of things
#pragma config(Sensor, in2, bump, sensorDigitalIn)
// A struct to store button press details
typedef struct {
int Counter;
bool Down;
bool Pressed;
}button;
button bumper;
void initButtons();
task main ()
{
bVexAutonomousMode = false;
initButtons();
// Clear timer the first time to get started
ClearTimer(T1);
motor[port1] = 0;
while (true)
{
// Detect a press of bumper
if (SensorValue[bump])
{
bumper.Down = true;
}
// Detect a release of bumper
if (bumper.Down && !SensorValue[bump])
{
bumper.Pressed = true;
bumper.Counter +=1;
bumper.Down = false;
}
// A button press and release was detected
if (bumper.Pressed)
{
motor[port1] = 127;
// We've dealt with the button being pressed, so unpress it
bumper.Pressed = false;
}
// The timer has expired
if (time100[T1] < 500)
{
motor[port1] = 127;
}
}
}
void initButtons()
{
bumper.Counter = 0;
bumper.Down = false;
bumper.Pressed = false;
}
I tried both of your programs and neither seemed to give me any help. The first program responded in the same way that my other program did, by running until the 50 seconds were up without doing anything when the button was pressed.
The second program just didn’t respond at all and didn’t do anything. Was there something I was supposed to add to it?
Thanks for the help so far!
Sorry, I didn’t mean to imply that either of them would actually work
If it were me, I’d fiddle around. You can’t break anything, so feel free to poke around. I’d run it with the device hooked up (RobotC right?) and see what values the different variables have and what they are doing. Try stepping through the program one line at a time, see where it does what you expect and where it doesn’t.
For me to get this working like you want, I’d have to set up my vex doodads and tinker around. I’d work on getting the first one to behave as you want since it is far, far simpler. If you are feeling adventurous, you can probably use what you learn to make the second style work too.
Edit: Also, I always forget what motor values are valid in RobotC. Is it -127 to 127? Or is it 0 to 255? I think the first, but am not sure
Also, what happens if you hold down the bumper button after the 50s are up with the first program?
I know in easyC there is a command to retrieve the sensor value, is there something like that in robotC that I have just completely looked over? The code I posted was actually just a shortened code of my whole test program to test using two different conditions and “or” inside a while loop. I want to use this type of code in an autonomous mode for competition. My entire test code is:
Blech, a ton of my comments are wrong because I thought ‘sensorRotation’ was the potentimeter, but I just realized it is obviously the rotation encoder
If you read the below, ignore those parts. Sorry, I might have a look at this later when I can.
#pragma config(Sensor, in1, coder, sensorRotation)
#pragma config(Sensor, in2, bump, sensorDigitalIn)
//*!!Code automatically generated by 'ROBOTC' configuration wizard !!*//
// You aren't looping inside of main, so this program will run once then exit
task main ()
{
// This will only run *while* the sensor 'bump' is pressed down *OR* when
// the sensor 'coder' is lower than 900
// Having to hold the button in is very unlikely to be what you want to do.
while(SensorValue[bump] < 1 || SensorValue(coder) < 900)
{
motor[port1] = -127;
}
// Immediately after the above conditions are done being met (you twist the
// know past 900 or let go of the button). Your motor on port1 will stop.
// If the knob was *already* past 900 when you started *or* you were
// not holding the button when the robot was turned on, you'll just get
// here and nothing will have happened.
motor[port1] = 0;
wait1Msec(1000);
// Now you are trying to set a sensor to a value, which I don't think is valid.
SensorValue[coder] = 0;
ClearTimer(T1);
// Again, this will *ONLY* fire when the sensor 'bump' is held down *OR* it
// is less than 500 what evers since you cleared the timer.
// And since your program only runs once *and* you clear the timer
// immediately before... the bump sensor will actually have no effect at all.
while (SensorValue[bump] < 1 || time100[T1] < 500)
{
motor[port1] = 127;
}
// The above should have run for ~500 what evers, but this will of course stop it.
motor[port1] = 0;
// Setting a value on a sensor again, I don't think that is valid.
SensorValue[coder] = 0;
ClearTimer(T2);
// This should run for 600 what evers, since your program only runs once
// I don't think the bump will have any effect
while (time100[T2] < 600 || SensorValue[bump] < 1)
{
motor[port2] = 127;
}
motor[port2] = 0;
}
Yeah sorry I didn’t format my code, I know it can be very difficult without it
#pragma config(Sensor, in1, coder, sensorRotation)
#pragma config(Sensor, in2, bump, sensorDigitalIn)
//*!!Code automatically generated by 'ROBOTC' configuration wizard !!*//
//yes I just want it to run once
task main ()
{
//I had meant for the program to stop when I either pressed the button OR the motor
//caused the rotation encoder(coder) to rotate 900 ticks.
while(SensorValue[bump] > 0 || SensorValue(coder) < 900)
{
motor[port1] = -127;
}
//then I would like the motor to stop once either of those happens.
motor[port1] = 0;
//wait a second just to let me see what is happening easier
wait1Msec(1000);
//I have had trouble figuring out how to reset a rotation encoder back to 0.
// from what I was able to find, this is what I am supposed to do, but it has
// not seemed to work well, even though it doesn't matter in this program because
//I never use the encoder again in the program. but if you do know a way to reset an
//encoder that would be helpful.
SensorValue[coder] = 0;
//then I clear the timer so it starts counting from 1
ClearTimer(T1);
//for this part I hope that it would drive the motor until the timer is no longer
//less than 50 seconds OR I press the button. Is this the correct way to write it?...
while (SensorValue[bump] > 0 || time100[T1] < 500)
{
motor[port1] = 127;
}
//then the motor stops
motor[port1] = 0;
//clear a second timer
ClearTimer(T2);
//and finally, it runs for 60 seconds OR stops when I press the button. but, from what
//you said it sounds like it does not re-check the value of the button over and over
//while running the loop. Is there a "check motor value" command that I could put
//inside the loop to continuously check the motor?
(time100[T2] < 600 || SensorValue[bump] > 0)
{
motor[port2] = 127;
}
motor[port2] = 0;
}
So my main problems are resetting the encoder(coder) back to zero and getting the program to recheck the bumper value(bump) over and over within the while loop.
Thanks for the continued help!
This is the program I am using to test what you want.
bump1 advances to the next test
bump2 is used inside a test for various purposes
Between each test it will zero out everything (timers, button presses/counters, rotation encoder)
There are no while loops (well, except the main one to keep it going) so it doesn’t get stuck anywhere and you can always do anything you want.
Test 0: Just sits there, waits for you to press button 1
Test 1: If you press and hold button 2, it will run the motor
Test 2: The motor runs until you press button 2 then does nothing
Test 3: The motor runs until either you press button 2 OR the encoder ticks 900 forward or back (assumes the motor is connected to the encoder of course)
Test 4: The motor runs until either you press button 2 OR 10 seconds elapses on the timer
#pragma config(Sensor, in1, pot1, sensorPotentiometer)
#pragma config(Sensor, in3, rot1, sensorQuadEncoder, int3)
#pragma config(Sensor, in15, bump2, sensorTouch)
#pragma config(Sensor, in16, bump1, sensorTouch)
#pragma config(Motor, port1, motor1, tmotorNormal, openLoop)
//*!!Code automatically generated by 'ROBOTC' configuration wizard !!*//
// A simple struct I use to make buttons more powerful
typedef struct {
int Counter;
bool Held;
bool Pressed;
}button;
// Will use bump1/bumper1 to advance through the tests
button bumper1;
// Will use bump2/bumper2 to do actions inside a test
button bumper2;
// Start all the buttons with the right values
void initButtons();
task main()
{
// Initialize all button values
initButtons();
// TestSection controls where we are in testing, default is 0
int TestSection = 0;
// Lets go forever
while(true)
{
// bumper1
if (SensorValue[bump1])
{
bumper1.Held = true;
}
if (bumper1.Held && !SensorValue[bump1])
{
bumper1.Pressed = true;
bumper1.Counter +=1;
bumper1.Held = false;
}
// bumper2
if (SensorValue[bump2])
{
bumper2.Held = true;
}
if (bumper2.Held && !SensorValue[bump2])
{
bumper2.Pressed = true;
bumper2.Counter +=1;
bumper2.Held = false;
}
// Catch button 1 press to advance test section
if (bumper1.Pressed)
{
TestSection+=1;
// We want to clear button state every time we advance.
initButtons();
// And stop the motor;
motor[motor1] = 0;
// And reset the rotation sensor
SensorValue[rot1] = 0;
// And reset the timer
ClearTimer(T1);
}
// Right now there are only 2 sections, so after 1 we wrap to 0
if (TestSection > 4)
{
TestSection = 0;
}
switch (TestSection)
{
case 0:
wait10Msec(1);
break;
case 1:
// If bumper2 is held in, run the motor otherwise stop it
if (bumper2.Held)
{
motor[motor1] = 15;
} else {
motor[motor1] = 0;
}
break;
case 2:
// Run the motor until bumper2 is pressed.
if (bumper2.Pressed)
{
motor[motor1] = 0;
} else {
motor[motor1] = 15;
}
break;
case 3:
// Run the motor until bumper2 is pressed *or* encoder hits 900 ticks
if (bumper2.Pressed || abs(SensorValue[rot1]) > 900)
{
motor[motor1] = 0;
} else {
motor[motor1] = -15;
}
break;
case 4:
// Run the motor until bumper2 is pressed *or* 10 seconds has passed
if (bumper2.Pressed || time100[T1] > 100)
{
motor[motor1] = 0;
} else {
motor[motor1] = 15;
}
break;
}
// Wait a little to save cpu
wait1Msec(10);
}
}
void initButtons()
{
bumper1.Counter = 0;
bumper1.Held = false;
bumper1.Pressed = false;
bumper2.Counter = 0;
bumper2.Held = false;
bumper2.Pressed = false;
}