Gyroscope drive straight

I am trying to create a drive straight program with a gyroscope instead of encoders because we do not have the space for them(i know there are solutions to that but this is also just learning for the gyro) but am running into the problem that this
while(SensorValue[gyro] < degree) earns an error. the solution so far is to change it to a while(abs(SensorValue[gyro]) < degree) and while this works for turns it does not help for driving straight. sample code would be appreciated!

I’m on my phone so I can’t provide any sample code, but what I do is just have my regular driving code add the value of the gyroscope to the left side motors and subtract the value from the right side motors. So, when the drive starts to veer off to the left, the gyroscope value is positive, and the left side motors increase in value and the right side motors decrease, veering it back to where it was before. Same thing applies vice versa. Basically,

motor[leftSide] = (whatever code you have) + SensorValue[gyro] * C;
motor[rightSide] = (whatever code you have) - SensorValue[gyro] * C;

C is a constant that multiplies the value of the gyroscope. That you will have to adjust based on how your drive oscillates, but I’ve tried it anywhere from 0.1 to 1 and it’s done me good.

Are you using the gyroscope to keep your robot straight while driving forward, or are you trying to use the gyroscope to measure the distance you traveled? The latter is impossible (you need encoders to measure the distance you drive forward. @Mystellianne 's answer is sufficient for the first usage, however.

If you have nowhere to put encoders on your drive, consider using a passive tracking wheel with an encoder on it. This can go in the middle of your chassis, on the back of your robot that does not go over the bar of the 10-point zone.

Just curious, what do you do to keep the movement perfectly linear? This was one of the few times I’ve just whipped up my own custom solution instead of researching other ones, and I never bothered to look for other solutions because this has worked to near-perfect success (consistent 84 point skills without using the fence to reposition at all).

I have my turning PID constantly running and adding its values to the drive PID. Then, some arithmetic is done if the resultant value is over 127 to make the larger value of the left and right side 127, with the other the proper amount slower. (So a difference of 30 would remain a difference of 30.) I don’t know how you can do that long of a programming skills without recalibrating; we have three gyros, and even the best one drifts too much for that. If anyone has any tips on keeping gyros from drifting, that would be great. I get some weird issues with mine.

While I don’t take the time to align myself on the fence, I do align myself on the ten point bar every single time I put down a mobile goal. Whenever you back out of scoring in the 20 pt zone, you can be assured you are at a 45* angle relative to the rest of the field. In addition, every time I place one in the 10 pt zone, I drive forwards slightly (maybe a power of like 20) so that my drive fully aligned itself with the bar, while not going fast enough to actually drive over it. Also, is your drive chained? Mine isn’t, but my routine would be a whole lot more accurate if it was.

Also, I only use one gyro. I reset it before every turn and just use what i mentioned above as my assurance for absolute positioning.

Have a look at my gyro filtering code here . You can use it to calibrate each gyro and get more responsive measurements with less drift than the standard ROBOTC (or PROS) filtering. My functions only return the angular rate measured from the gyro, you have to sum it over time yourself like this (assuming gyro is plugged in to analog port 1 on cortex):


#include "NERD_Gyro.c"

Gyro gyro;
gyroInit(gyro, in1, false);
float gyroAngle = 0;

long time = nPgmTime;

task pollGyro() {
  while (1) {
    float deltaTime = (nPgmTime - time) / 1000.0;

    if (deltaTime != 0) {
      gyroAngle += gyroGetRate(gyro) * deltaTime;
    }

    delay(1);
  }
}

task main() {
  startTask(pollGyro);

  while (1) {
    //use gyro or do other things
  }
}


I measured the difference between my code and ROBOTC’s filtering for gyros, and I actually found that ROBOTC’s won’t drift at all if the robot sat still, but would tend to have a less accurate angle measurement after a turn or move, whereas mine would drift something like +/-0.2 degrees over a few minutes but gave great results for turns or other moves.

My Programming Skills run realigns with the bar as well, and my drive is chained together.

One other thing that a lot of teams don’t do is run their programming routines at a lower motor power. This increases accuracy by a lot. All of my driving is done at a power of 84, and my turning at 64. Granted this is still pretty fast considering my robot is on a 6 motor turbo drive, but running at a reduced speed made it a loooot more accurate.

Now that I’m going for 94 instead of 84, I wouldn’t even bump up the power, but instead I want to incorporate more swing turns to save a lot of driving distance. My 3 cone autons already do this but it will be a little harder to implement on such a long routine.

This is actually very easy to accomplish.

First, start by establishing a “speed” value that you get from whatever you’re using to reach your target. Either use PID, or use bang bang (if current encoder value < target --> motors 127) and set the end speed to the ‘speed’ variable.
Then, use a secondary PID Loop for correcting based on the gyro. This is done like so:


SensorValue[gyro] = 0;
int error = 0 - SensorValue[gyro];
float kP = 0.2; // random-ish starter value, tune this. The higher this value is, the greater affect the gyro correction have on your robot, the lower it is the lower the affect.

motor[left] = speed - (error * kP);
motor[right] = speed + (error * kP);

1 Like

@jmmckinney I was talking to one of my mentors the other day about measuring velocity with encoders or angular velocity with the gyro, somewhat similar to your code, and he said the speed of the clock varies with battery voltage, so it doesn’t actually return consistent values for time. Do you know anything about this?

@ZProgrammer The short answer is that this is incorrect, the CPU voltage should never vary in a properly functioning cortex.

Long answer:
Your mentor has the right idea, that the clock speed of a CPU will increase if you increase the voltage, but from my understanding the ARM cortex M3 chip in the VEX Cortex Microcontroller is a 3.3v CPU. The 7.2v batteries we use have their voltage lowered by a voltage regulator circuit to a constant 3.3v (minus a tiny bit of electrical noise). The lower CPU voltage should be independent of the battery voltage because of this.

Actually, if you check the Cortex internals, you’ll find a little metal can next to the chips. That is a crystal, a time reference. While slightly influenced by temperature, these things are precise at least to 50ppm (50 parts per million, that is, deviate from the nominal frequency by less than 0.005%). Compare that to the jitter in the OS timing (when will the RobotC virtual machine actually schedule your sampling or integration task) and, most of all, the actual quantization and precision of the A/D converter (quantization - one lsb step: 1/4096 or 0.025%, precision - multiples of lsb).

What he said. It didn’t even occur to me that there would be a crystal oscillator in there. My head’s too deep in the software engineering world sometimes.

thank you thank you thank you that works so much better than just straight motors and i could not figure out how to program it without using the abs