I am currently trying to code using the ROBOTC for VEX Robotics 4.X program. I assembled a vehicle with VEX parts; a VEX EDR cortex, and VEXNet 2.0 key, VEXNet remote, touch sensor, two VEX motors and two VEX encoders. Using the program, my goal is to get the vehicle to start and stop a given distance by altering the revolutions within the code. To program I have the remote paired with the cortex through the two keys- I download the program directly from laptop to cortex via USB, then turn on the cortex and remote paired by keys and press the touch sensor. As of now, the code I have written runs the motors in the same direction as intended, however it only starts when I manually click the start button on the laptop, when the cortex is still connected via USB, and it does not stop until I manually click off. Please help fix my code this is what I have so far:
task main()
{
while(SensorValue(TouchSensor) == 0)
//Forward with Encoder function
//Parameters: p for power, ticks for encoder
void forwardWithEncodesr(int p, int ticks) {
//Step 0: Set encoders to 0
SensorValue[encoderRight] = 0;
SensorValue[encoderLeft] = 0;
//Step 1: Turn on Motors
motor[right] = -p;
motor[left] = p;
//Step2:Wait for condition
//Check power
if (p < 0) {
while (SensorValue[encoderLeft] < ticks) {
//run the motors
} // end while
} // end if
if (p > 0) {
ticks = ticks * -1;
while (SensorValue[encoderLeft] > ticks) {
// run the motors
}
}// end if
// Step 3: Turn off the motors
motor[right] = 0;
motor[left] = 0;
You mentioned pairing the controller and the Cortex. Did you pair them by connecting the orange USB cable between the controller and the Cortex?
Many overlook this step and it is required so that multiple robots and controllers don’t interfere with each other. It only needs to be done once and then you can use the wireless keys.
The code is close but not quite right. Your function should be written prior to task (main) and called from task main. Your check for the touch sensor is a while with no brackets, which would lead to a compiler error. I think it would belong inside the function as an emergency stop - but I am not certain of your intention with the button. You need to either run the motors within the while loops checking for encoder value, or put waits in those loops.
All together, those tweaks would look like this:
//Forward with Encoder function
//Parameters: p for power, ticks for encoder
void forwardWithEncoder(int p, int ticks) {
//Step 0: Set encoders to 0
SensorValue[encoderRight] = 0;
SensorValue[encoderLeft] = 0;
while(SensorValue(TouchSensor) == 0)
{
//Step 1: Turn on Motors
motor[right] = -p;
motor[left] = p;
//Step2:Wait for condition
//Check power
if (p < 0)
{
while (SensorValue[encoderLeft] < ticks)
{
//run the motors
wait1Msec(50);
} // end while
} // end if
if (p > 0)
{
ticks = ticks * -1;
while (SensorValue[encoderLeft] > ticks)
{
// run the motors
wait1Msec(50);
}
}// end if
} // end while
// Step 3: Turn off the motors
motor[right] = 0;
motor[left] = 0;
}//end forwardWithEncoder
task main()
{
forwardWithEncoder ( 90, 1800);
}
For what it is worth, you can reverse the right motor with a checkbox in motor and sensor setup. You can also check for the absolute value of the sensor with abs(SensorValue[encoderLeft]) and avoid the if checks for direction. The touch sensor can be tested in the same while loop. That would look like this:
//Forward with Encoder function
//Parameters: p for power, ticks for encoder
void forwardWithEncoder(int p, int ticks) {
// Set encoders to 0
SensorValue[encoderRight] = 0;
SensorValue[encoderLeft] = 0;
while (abs(SensorValue[encoderLeft]) < ticks && SensorValue(TouchSensor) == 0)
{
//run the motors
motor[right] = motor[left] = p;
} // end while
// Turn off the motors
motor[right] = motor[left] = 0;
}//end forwardWithEncoder
task main()
{
forwardWithEncoder ( 90, 1800);
}
@Doug Moyers You seem very well versed in this coding. If you don’t mind helping out a bit more I would be so grateful as I have never coded before. Yes, the controller and the cortex are paired. The touch sensor I mentioned I think is actually called a bump sensor or bumper switch; the intention is that once the program is downloaded to cortex, we will turn on cortex and controller with keys in each and by pressing the bumper switch, the vehicle will then begin to move a given distance based on the rotations we write in the code. We don’t want it to be a function of time (I think that is what you have written in the above code with the waits) we would rather like to input different rotations for the encoder and have the vehicle stop itself after given rotations.
I sort of hijacked what Doug wrote, merged it with your programming and below is what I came up with. I am not sure what ports you used so I assumed the following:
Motor ports 1 and 10 for the motors.
Touch button in digital 1
Left encoder in digital 2 & 3
Right encoder in digital 4 & 5
#pragma config(Sensor, dgtl1, touch1, sensorTouch)
#pragma config(Sensor, dgtl2, encoderLeft, sensorQuadEncoder)
#pragma config(Sensor, dgtl4, encoderRight, sensorQuadEncoder)
#pragma config(Motor, port1, left, tmotorVex393_HBridge, openLoop)
#pragma config(Motor, port10, right, tmotorVex393_HBridge, openLoop)
//*!!Code automatically generated by 'ROBOTC' configuration wizard !!*//
//Forward with Encoder function
//Parameters: p for power, ticks for encoder
void forwardWithEncoder(int p, long ticks) {
// Set encoders to 0
SensorValue[encoderRight] = 0;
SensorValue[encoderLeft] = 0;
//while encoderLeft and encoderRight are less than tick
//note: encoders count backward when the wires are reversed. Using abs() to prevent issue.
while (abs(SensorValue[encoderLeft]) < ticks && abs(SensorValue[encoderRight]) < ticks)
{
//run the motors
motor[left] = p; //clockwise
motor[right] = -p; //counter-clockwise (optionally can be set in the config)
} // end while
// Turn off the motors
motor[right] = 0;
motor[left] = 0;
}
//end forwardWithEncoder
task main()
{
while(1)
{
//wait until bump button or 8 Down on joystick is pressed.
if(SensorValue[touch1] || getJoystickValue(Btn8D)){
//move forward at speed 60 for 3 rotations
//aka pi(d)*4 or 3.14 x 4" wheel x 3 revolutions ~ 38"
forwardWithEncoder(60, 360 * 3);
}
}
}
@Pete The code you provided works! Thank you so so much. One question I have is what does each value in the parenthesis of the end of your code mean. The 60, 360, and 3 in “forwardWithEncoder(60, 360 * 3);”
function is asking for two parameters - speed and distance.
What I passed to the function
forwardWithEncoder(60, 360 * 3)
tells the motors to run at a speed of 60 for 1,080 ticks (or 360 * 3)
Encoders tick 360 times per rotation (much like 360 degrees in a circle). I simply added a math formula inside of the function telling it to travel 3 rotations.
As I noted in the comments of the program you could also have the robot travel a specific distance. If you are using 4" wheels and you multiply that by pi you end up with ~12.5 inches per rotation. Divide that into 360 ticks and you end up with 28.8 ticks per inch. So if you wanted the robot to travel 12" you would enter 346 ticks.
You could also add that as another function in your code.
@Pete The code is working it seems to be curving to the right a lot though. Do you know why that would be? We actually need it to curve left for our event.
Well no two motors are identical. There also could be more friction on one side compared to the other.
The quick fix would be to make the left motor run a little bit slower than the right by subtracting 5 from its p value. As you change that number you should see the robot turning arc change.
If( abs(SensorValue[encoderLeft]) < ticks && abs(SensorValue[encoderRight]) < ticks)
{
//run the motors
motor[left] = p-5; //subtract 5 to make the left motor slower
motor[right] = -p;
} // end while
More advanced techniques would be to compare the values of the left and right encoders and have them adjust the motor speed.