Using Encoders to Turn


#1

Does anyone know how to use the V5 motor encoder values to turn? I wanted to modify my previous time-based turn function to incorporate encoders, but I’m not really sure how. Here’s my old turn function:


void timeTurn (int direction, int time, int percentage = 100)
{
    // If the percentage is not specified, it defaults to 100%
    if (direction == LEFT)
    {
        setLeftDrive (vex::directionType::rev, percentage);
        setRightDrive (vex::directionType::fwd, percentage);
        // When turning left, the left motors go in reverse and the right motors go forwards
        vex::task::sleep (time);
        stopLeftDrive (vex::brakeType::brake);
        stopRightDrive (vex::brakeType::brake);
    }
    if (direction == RIGHT)
    {
        setLeftDrive (vex::directionType::fwd, percentage);
        setRightDrive (vex::directionType::rev, percentage);
        // When turning right, the right motors go in reverse and the left motors go forwards
        vex::task::sleep (time);
        stopLeftDrive (vex::brakeType::brake);
        stopRightDrive (vex::brakeType::brake);
    }
}


#2

Mathematically, the tough thing is making sure you know around what point the robot rotates, where the wheels are in relation to that spot, and what their orientation is. It’s probably easier to set some specific values for the encoders to hit and see just how far the robot gets in its rotation.

As for the actual code, I have three comments. First, that doesn’t look like working code unless you’ve defined a whole bunch of other functions you haven’t shown us. I would expect code like leftDrive.spin(vex::directionType::fwd, percentage,vex::velocityUnits::pct); instead. Second, you could pull the sleep and brake commands outside of the if statements. Third, if you want to switch over, you could use motor.startRotateTo instead of the motor commands you’re using. I would take an input angle and calculate the needed rotation of the motors inside of the function based on that. That way from the outside you just give it an angle for the robot to rotate.


#3

Yes, there are some other functions which I didn’t include to save space. Here is an example of the setLeftDrive and stopLeftDrive functions for reference:

void setLeftDrive (vex::directionType type, int percentage)
{
    LeftFront.spin (type, percentage, vex::velocityUnits::pct);
    LeftBack.spin (type, percentage, vex::velocityUnits::pct);
}
void stopLeftDrive (vex::brakeType type = vex::brakeType::coast)
    // If the brakeType is not specified, it defaults to coast
{
    LeftFront.stop (type);
    LeftBack.stop (type);
}

I didn’t realize that when I made the function, but that makes sense now.

So, are you suggesting I modify the previous setLeftDrive function to this:

void setLeftDrive (int degrees, int percentage)
{
    LeftFront.startRotateTo (degrees,vex::rotationUnits::deg, percentage,vex::velocityUnits::pct);
    LeftBack.startRotateTo (degrees,vex::rotationUnits::deg, percentage,vex::velocityUnits::pct);
}

Also, what is the difference between the motor.startRotateTo and the motor.rotateTo functions? And how are these functions different from the motor.rotateFor and motor.startRotateFor functions?


#4

Maybe, maybe not. It depends on if you plan to use setLeftDrive for anything else, such as when using the joystick.

There are two different angles involved. There is how much you want the robot to rotate, and there is how much the motors need to rotate to accomplish that rotation. Let’s say you find out the motors must rotate 405 degrees to get the robot to rotate 90 degrees, a ratio of 4.5:1. Then your code would look more like this with your new setLeftDrive

void angleTurn (int direction, int angle, int percentage = 100)
{
    int wheelAngle = angle * 4.5;
    if (direction == LEFT)
    {
        // make sure left side is running backward
        setLeftDrive (wheelAngle, percentage);
        setRightDrive (wheelAngle, percentage);
    }
    if (direction == RIGHT)
    {
        // make sure right side is running backward
        setLeftDrive (wheelAngle, percentage);
        setRightDrive (wheelAngle, percentage);
    }
    stopLeftDrive (vex::brakeType::brake);
    stopRightDrive (vex::brakeType::brake);
}

I’m not sure what LEFT and RIGHT are. If they’re ±1, then you could use them to switch signs. If they’re true and false, you could stick them directly into motor.setReversed. So you might not even need the if statement here at all, just sticking those values in the appropriate spot. But not knowing, I left the structure of your if statement.

They are the same if you include the optional boolean as false in motor.rotateFor. The default behavior is that motor.rotateFor finishes before the code advances, with the boolean assumed to be true. If you set it to false, it will behave exactly as motor.startRotateTo does.


#5

What would be the best way to find out how many degrees (or any other unit for that matter) the motors need to rotate for the robot to rotate a given number of degrees? I plan to just my previous time-based turn function with the motor encoder values being shown on the controller to find the number of degrees.

Also, for the turning function you wrote, wouldn’t setLeftDrive have to use a motor.startRotateFor rather than motor.startRotateTo? I’m basing this on the assumption that the encoders aren’t cleared when the function is started, resulting in a starting reading that is not 0. Therefore if you need to turn 405 degrees for a 90-degree turn, you are turning to an exact angle with RotateTo, rather than a relative angle with RotateFor. I haven’t tried this with an actual robot yet so my conclusions about motor.startRotateFor and motor.startRotateTo may be incorrect.


#6

I would do it empirically. Choose some amount and measure how far the robot actually rotated. Do it a few times. Choose other amounts and do it again. It shouldn’t take long to get an accurate ratio.

Yes, startRotateFor if you’re not clearing the encoders.


#7

This is what I’ve done and it works quite well for us, whenever we program a new turn we just put it through the ratio and now exactly how much the motors need to spin


#8

Thank you @callen and @JuiceBox for your advice!