RobotC Gyro & Encoder issue

We are attempting to change our auton from time-based to sensor-based. We recently added a quad encoder to each side and a gyro and now we are attempting to implement the coding but are having a few issues. This is the first time we’ve tried using those sensors in competition, and our main goal is to have the sensor-based codes work as well as the time-based codes but with less sensitivity to variations in field conditions and battery levels.

  1. Individually tested, the voids for GTurnRight, GTurnLeft, EncForward, & EncBackward work as expected and are within reasonable accuracy limits.

  2. When added together, the first steps work correctly - but when it gets to the GTurnLeft it doesn’t ever move past it to the EncForward (no matter what we’ve played with, the robot goes until it does that turn and then sits there).

  3. The quad encoders don’t appear to be re-setting to 0 after each movement in the debugger window, even though that is at the beginning of the void.

  4. We know the Gyro has to initially sit for 2 secs in pre-auton. Afterwards, though, when you are running code with multiple turns - can you reset it quickly to 0 (without resting) just to make selecting degrees easier? For instance, can you say “GTurnRight 90 degrees”, reset to 0 on the move, do other things, then “GTurnRight 90 degrees” again?

  5. Also on the Gyro - shouldn’t we be able to say degrees*10 so that what we enter as “int degrees” is 90 instead of having to put 900? We tried that and it didn’t seem to work correctly, but it seems like it should…

  6. Anything else major missing or that ought to be incorporated (either immediately - for basic performance or eventually - for better performance later)?

We’re cutting down the code here, as we have an LCD and all codes together so it gets bulky.

(Note - we plan to eventually incorporate PID [or at least P] for straighter driving and perhaps tweak things like scaling and error some for even great accuracy, but we only have a few days to get things working well enough for an upcoming competition. We will then have much more time available to fine tune things!)


#pragma config(Sensor, in1,    POT,            sensorPotentiometer)
#pragma config(Sensor, in2,    Gyro,           sensorGyro)
#pragma config(Sensor, dgtl1,  rightEncoder,   sensorQuadEncoder)
#pragma config(Sensor, dgtl3,  leftEncoder,    sensorQuadEncoder)
#pragma config(Sensor, dgtl5,  limitswitch,    sensorTouch)
#pragma config(Motor,  port1,           rightMotorB,   tmotorVex393HighSpeed_HBridge, openLoop, reversed, driveRight)
#pragma config(Motor,  port2,           rightMotorF,   tmotorVex393HighSpeed_MC29, openLoop, reversed, driveRight)
#pragma config(Motor,  port3,           ArmMotor,      tmotorVex393_MC29, openLoop)
#pragma config(Motor,  port4,           Intake1,       tmotorVex393_MC29, openLoop)
#pragma config(Motor,  port5,           Intake2,       tmotorVex393_MC29, openLoop)
#pragma config(Motor,  port6,           Angler,        tmotorVex393_MC29, openLoop)
#pragma config(Motor,  port7,           Puncher2,      tmotorVex393_MC29, openLoop)
#pragma config(Motor,  port8,           Puncher1,      tmotorVex393_MC29, openLoop, reversed)
#pragma config(Motor,  port9,           leftMotorF,    tmotorVex393HighSpeed_MC29, openLoop, driveLeft)
#pragma config(Motor,  port10,          leftMotorB,    tmotorVex393HighSpeed_HBridge, openLoop, driveLeft)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//

/*---------------------------------------------------------------------------*/
/*                                                                    Y       */
/*        Description: Competition template for VEX EDR                      */
/*                                                                           */
/*---------------------------------------------------------------------------*/

// This code is for the VEX cortex platform
#pragma platform(VEX2)

// Select Download method as "competition"
#pragma competitionControl(Competition)

int count = 0;  //Define

//Main competition background code...do not modify!
#include "Vex_Competition_Includes.c"

const short leftButton = 1;
const short centerButton = 2;
const short rightButton = 4;
//Wait for Press--------------------------------------------------
void waitForPress()
{
while(nLCDButtons == 0){}
wait1Msec(5);
}
//----------------------------------------------------------------

//Wait for Release------------------------------------------------
void waitForRelease()
{
while(nLCDButtons != 0){}
wait1Msec(5);
}
//----------------------------------------------------------------

/*---------------------------------------------------------------------------*/
/*                          Pre-Autonomous Functions                         */
/*                                                                           */
/*  You may want to perform some actions before the competition starts.      */
/*  Do them in the following function.  You must return from this function   */
/*  or the autonomous and usercontrole tasks will not be started.  This       */
/*  function is only called once after the cortex has been powered on and    */
/*  not every time that the robot is disabled.                               */
/*---------------------------------------------------------------------------*/

void pre_auton()
{
   SensorType[in5] = sensorNone;
 	 wait1Msec(100);
   SensorType[in5] = sensorGyro;
   wait1Msec(2000);

bStopTasksBetweenModes = true;


//------------- Beginning of LCD Selection Code ---------------
//Clear LCD
clearLCDLine(0);
clearLCDLine(1);

//Battery voltage information
bLCDBacklight = true;	//Enable/disable lcd backlight.
string mainBattery, powerexpander;

clearLCDLine(0);   //Clear lcd lines.
clearLCDLine(1);

//Display the Primary Robot battery voltage
displayLCDString(0, 0, "Primary: ");
sprintf(mainBattery, "%1.2f%c", nImmediateBatteryLevel/1000,'V'); //Build the value to be displayed
displayNextLCDString(mainBattery);

//Display the Power Expander's voltage
sprintf (powerexpander, "%1.2f%c",SensorValue[in1] /4/45.6, 'v');
displayLCDString(1, 0, "Backup: ");
displayNextLCDString(powerexpander);

//How long to display voltage in milliseconds
wait1Msec(1000);
//Battery voltage information



//While loop until center button for selection
while(nLCDButtons != centerButton)
{
//Selecting Autonomous
switch(count){
case 0:
//Display first choice
displayLCDCenteredString(0, "B-F HF LF P");													//Rename "Code 1" etc. to name codes based on what they do.
displayLCDCenteredString(1, "<        Enter       >");
waitForPress();
//Increment or decrement "count" based on button press
//If left button is pressed switch to last code
if(nLCDButtons == leftButton)
{
waitForRelease();
count = 19;
}
else if(nLCDButtons == rightButton)
{
waitForRelease();
count++;
}

//
break;

__________________________________


Continued (too long)


//VOIDS FOR AUTONOMOUS
                                                        //Voids for autonomous.
void GTurnLeft ( int degrees, int speed )
{
int	scale = 1.025;
	while(abs(SensorValue[in5]) < degrees*scale - 100)
 {
 motor[rightMotorB] = speed;
 motor[rightMotorF] = speed;
 motor[leftMotorB] = -speed;
 motor[leftMotorF] = -speed;
 }

 motor[rightMotorB] = -10;
 motor[rightMotorF] = -10;
 motor[leftMotorB] = 10;
 motor[leftMotorF] = 10;
 wait1Msec(250);

  while(abs(SensorValue[in5]) > degrees*scale + 5 || abs(SensorValue[in5]) < degrees*scale - 5)
{

  if(abs(SensorValue[in5]) > degrees*scale)
 {
 motor[rightMotorB] = -30;
 motor[rightMotorF] = -30;
 motor[leftMotorB] = 30;
 motor[leftMotorF] = 30;
 }
else 
 {
 motor[rightMotorB] = 30;
 motor[rightMotorF] = 30;
 motor[leftMotorB] = -30;
 motor[leftMotorF] = -30;
}
 motor[rightMotorB] = 0;
 motor[rightMotorF] = 0;
 motor[leftMotorB] = 0;
 motor[leftMotorF] = 0;
 wait1Msec(250);
}
}

void GTurnRight ( int degrees, int speed)
{
int	scale = 1.025;
	while(abs(SensorValue[in5]) < degrees*scale - 100)
 {
 motor[rightMotorB] = -speed;
 motor[rightMotorF] = -speed;
 motor[leftMotorB] = speed;
 motor[leftMotorF] = speed;
 }

 motor[rightMotorB] = 10;
 motor[rightMotorF] = 10;
 motor[leftMotorB] = -10;
 motor[leftMotorF] = -10;
 wait1Msec(250);

  while(abs(SensorValue[in5]) > degrees*scale + 5 || abs(SensorValue[in5]) < degrees*scale - 5)
{

  if(abs(SensorValue[in5]) > degrees*scale)
 {
 motor[rightMotorB] = 30;
 motor[rightMotorF] = 30;
 motor[leftMotorB] = -30;
 motor[leftMotorF] = -30;
 }
else 
 {
 motor[rightMotorB] = -30;
 motor[rightMotorF] = -30;
 motor[leftMotorB] = 30;
 motor[leftMotorF] = 30;
}
 motor[rightMotorB] = 0;
 motor[rightMotorF] = 0;
 motor[leftMotorB] = 0;
 motor[leftMotorF] = 0;
 wait1Msec(250);
}
}

void EncForward ( int inches, int driveSpeed)
{
float distance = 27*inches;

SensorValue[rightEncoder] = 0;
SensorValue[leftEncoder] = 0;

while(SensorValue[rightEncoder] < distance)
{
 motor[rightMotorB] = driveSpeed;
 motor[rightMotorF] = driveSpeed;
 motor[leftMotorB] = driveSpeed;
 motor[leftMotorF] = driveSpeed;	
}
 motor[rightMotorB] = 0;
 motor[rightMotorF] = 0;
 motor[leftMotorB] = 0;
 motor[leftMotorF] = 0;
}

void EncBackward ( int inches, int driveSpeed)
{
float distance = 27*inches;

SensorValue[rightEncoder] = 0;
SensorValue[leftEncoder] = 0;

while(SensorValue[rightEncoder] > -distance)
{
 motor[rightMotorB] = -driveSpeed;
 motor[rightMotorF] = -driveSpeed;
 motor[leftMotorB] = -driveSpeed;
 motor[leftMotorF] = -driveSpeed;	
}
 motor[rightMotorB] = 0;
 motor[rightMotorF] = 0;
 motor[leftMotorB] = 0;
 motor[leftMotorF] = 0;
}

void forwarddrive(int driveSpeed, int driveTime)
{
motor[leftMotorF]  = driveSpeed;
motor[leftMotorB]  = driveSpeed;
motor[rightMotorF]  = driveSpeed;
motor[rightMotorB]  = driveSpeed;
wait1Msec(driveTime);
stopMotor(leftMotorF);
stopMotor(leftMotorB);
stopMotor(rightMotorF);
stopMotor(rightMotorB);
}
void backwarddrive(int driveSpeed, int driveTime)
{
motor[leftMotorF]  = -driveSpeed;
motor[leftMotorB]  = -driveSpeed;
motor[rightMotorF]  = -driveSpeed;
motor[rightMotorB]  = -driveSpeed;
wait1Msec(driveTime);
stopMotor(leftMotorF);
stopMotor(leftMotorB);
stopMotor(rightMotorF);
stopMotor(rightMotorB);
}
void leftturn(int leftwheels, int rightwheels, int driveTime)
{
motor[leftMotorF]  = -leftwheels;
motor[leftMotorB]  = -leftwheels;
motor[rightMotorF]  = rightwheels;
motor[rightMotorB]  = rightwheels;
wait1Msec(driveTime);
stopMotor(leftMotorF);
stopMotor(leftMotorB);
stopMotor(rightMotorF);
stopMotor(rightMotorB);
}
void rightturn(int leftwheels, int rightwheels, int driveTime)
{
motor[leftMotorF]  = leftwheels;
motor[leftMotorB]  = leftwheels;
motor[rightMotorF]  = -rightwheels;
motor[rightMotorB]  = -rightwheels;
wait1Msec(driveTime);
stopMotor(leftMotorF);
stopMotor(leftMotorB);
stopMotor(rightMotorF);
stopMotor(rightMotorB);
}
void punchershoot(int shootTime)
{
motor[Puncher1] = 127;
motor[Puncher2] = 127;
wait1Msec(shootTime);
stopMotor(Puncher1);
stopMotor(Puncher2);
}


//VOIDS FOR AUTONOMOUS
_________________________________________________
task autonomous()
{
clearLCDLine(0);
clearLCDLine(1);
//Switch Case that actually runs the user choice
switch(count){
case 0:
//If count = 0, run the code correspoinding with choice 1
displayLCDCenteredString(0, "B-F HF LF P");
displayLCDCenteredString(1, "is selected");
wait1Msec(1);
//Autonomous code here
  //The blue-front - right high flag, right low flag, low park
punchershoot(1600);
motor[Intake1] = 127;
rightturn(40, 40, 265);
EncForward(48, 127);
EncBackward(60, 127);
GTurnLeft(800, 127);
EncForward(30, 127);

//Autonomous code above
break;

@jpearman
@The Electrobotz
@nleighton11

Any insight as to what might be going wrong? We’re going to be working on things this afternoon to prepare for the competition, so we’re hoping to get past at least the hurdle of the robot not moving past the gyro turn code line. We assume it is somehow blocking the next line, or maybe the quad encoders are not resetting? Any assistance on things to try would be much appreciated!

Every time I try to use quad encoders they don’t work, so I recommend switching to integrated encoders; those have worked for me with flying colors. That’s just my first take on it, I will look more into the issue, but we did use a gyro last year so I should be able to help there!

It kind of looks like you need to move a paren:

Instead of this:
while(abs(SensorValue[in5]) > degreesscale + 5 || abs(SensorValue[in5]) < degreesscale - 5)
{

if(abs(SensorValue[in5]) > degrees*scale)
{
motor[rightMotorB] = -30;
motor[rightMotorF] = -30;
motor[leftMotorB] = 30;
motor[leftMotorF] = 30;
}
else
{
motor[rightMotorB] = 30;
motor[rightMotorF] = 30;
motor[leftMotorB] = -30;
motor[leftMotorF] = -30;
}
motor[rightMotorB] = 0;
motor[rightMotorF] = 0;
motor[leftMotorB] = 0;
motor[leftMotorF] = 0;
wait1Msec(250);
}
}

Try this:
while(abs(SensorValue[in5]) > degreesscale + 5 || abs(SensorValue[in5]) < degreesscale - 5)
{

if(abs(SensorValue[in5]) > degrees*scale)
{
motor[rightMotorB] = -30;
motor[rightMotorF] = -30;
motor[leftMotorB] = 30;
motor[leftMotorF] = 30;
}
else
{
motor[rightMotorB] = 30;
motor[rightMotorF] = 30;
motor[leftMotorB] = -30;
motor[leftMotorF] = -30;
}
}
motor[rightMotorB] = 0;
motor[rightMotorF] = 0;
motor[leftMotorB] = 0;
motor[leftMotorF] = 0;
wait1Msec(250);
}

Because it kind of looks like it might get to the part where the motors shut off and get stuck. You only want them to shut off after you’ve finished your correction turn.

When your program hangs up are the batteries at zero power? That might be a sign that the paren is in the wrong place.

OTOH, if when the program hangs up, the motors are at 30, it may be that there is not enough power to move the robot and the program is hanging up because of it.

1 Like

Thank you both!
@Gear Geeks - we’ll run some tests with changing that and checking on those thing this pm.

So when I used the gyro last year, we tried to keep the function as simple as we could, so this is what we came up with and it worked very well.

void turn(int speed, int degree){
Reset_Gyrosensor();
if(degree < 0){ //turn left
int rotation = degree*-10;
while(SensorValue[Gyro] < rotation){
motor[leftWheels] = -speed;
motor[rightWheels] = speed;}
motor[leftWheels] = 0; motor[rightWheels] = 0;}
if(degree > 0){ //turn right
int rotation = degree*-10;
while(SensorValue[Gyro] > rotation){
motor[leftWheels] = speed;
motor[rightWheels] = -speed;}
motor[leftWheels] = 0; motor[rightWheels] = 0;}}

@Gear Geeks - moving the } totally worked! Yay!
@nleighton11 - thanks for the sample - we’ll definitely check it out moving forward as we fine-tune!

After moving the }, the only issue we had with the auton was that we had done a float distance calc to be able just to enter # of inches and have it go that far but apparently the calc is wrong (it went only about 30 inches when we wanted 45). We tweaked it until the float took it as far as we wanted, but it definitely is different from expected! 4" omni wheels.

Hmmm - 2 additional strange issues have come up that we weren’t able to completely resolve.

  1. When going onto the low platform, code runs as expected (forward some, then stop when on platform). When doing Skills and going onto the center platform running the same initial code but with a longer forward, the robot goes up onto the center then backs up at the end and comes off. There is no back up in the code, and none of the other void EncForward calls throw this “back up” in at the end.

  2. On the gyro turns, on one code since we don’t have it reset to 0 the code doesn’t correctly do the 2nd turn (it’s gone to 900 then needs to go right to 200, however since it is already over it assumes it doesn’t need to move). We tried in the code itself (not the void, since others were running correctly) putting a “SensorValue[gyro] = 0” right before that turn but it didn’t seem to do any good. (Reset_Gyrosensor() threw an error.) We may try not having 2 different but doing + - degrees as shown above.

Time ran out for working today, so we’ll have to play with things again tmo. If you have any ideas on things that could be causing these issues, though, we’d love to hear them!

Note to help others who may encounter similar issues:

  • Issue 1 (doing additional movements after code has run) - turned out the “break;” at the end of those segments of LCD code were accidentally removed. When added back, code works as expected.
  • Issue 2 (resetting Gyro not working) - the motor/sensor setup showed “Gyro” as 2, however it was actually plugged into 5. This didn’t affect normal operation, since the first part of the code reset to 5 and used it as 5 - however when calling the it by name “Gyro” later to try and reset to 0, it referenced the one in 2 instead (as set up in motor/sensors). Referencing 5 fixed the issue.