04 - Encoders

Introduction to Encoders

One of the first sensors you will learn in RobotC is the use of Encoders. They are designed to measure the rotation of the wheel in degrees. This is a very useful tool to understand as you can use them to further increase the accuracy of how your robot moves. Using encoders, you can write code for the robot to travel a specified distance and then perform a turn rather than relying on guessing a time and dealing with different motor speeds/powers. Encoders can also help your robot move straight forward more precisely with the ability of line straightening, regardless of the different motor speeds/times on the left and right sides.

Here is image of the encoder. They are placed on the shaft of the robot's wheel.

These encoders are optical. There is a disc in the encoder with slits, and light to used to measured the how many slits have past. To understand how encoders work in detail, lets navigate to following resource.

Overall Reason for Using Encoders

The two main reasons for using the wheel encoders are:

    1. Dealing with the fact that real-world products are not perfect. In other words, no real motor operates exactly as expected and no two motors act exactly alike. To deal with these inevitable imperfections, we can use encoders to do things like:

      • Driving in an accurate, straight line

      • Turning an accurate number of degrees

    2. Measuring actual distance traveled. In other words, instead of guessing and checking how much time the robot should move forward and at what power, you can tell it to move forward a set distance. Instead of spending the time guessing and checking, you can take out a measuring tape and see that your robot needs to travel 260 cm, then tell it to move forward until it has traveled that distance. This is much more time efficient and accurate.

How to Check Sensor Values

Encoders measure the number of degrees the wheel has rotated. We can view this data in the Sensor Debugger Window.

In this scenario we will the use RVW Level Builder with the Clawbot.

In the Virtual World you can see the encoder values by looking at the Sensors Debugger Window.

When you run your robot in the Virtual World, you can see the values coming from the rotation of the wheel in this window.

Writing a Loop that Drives Based on Encoder Values

Now that we know how the encoder works, let's write code for the robot to travel a specified distance using the encoder.

With one full rotation, the wheel will rotate 360 degrees, and the robot will travel a distance equal to one circumference of the wheel.

Given that the radius of the wheel our clawbot is using is 4.7cm, lets calculate the circumference of the wheel.

Circumference = 2 * pi * radius.

Circumference = 2 * pi * 4.7 = 29.53097... cm. approximately

We can say that one full rotation of the wheel (360 degrees) will move the robot about 29.53 cm.

Going even further, by dividing 29.53097... by 360 degrees, we can see that for for each degree the wheel rotates the robot travels about 0.08203 cm.

Code

The following code programs the robot to travel 360 degrees (which is about 29.53 cm). Lets see how that works by going over the comments.

#pragma config(StandardModel, "RVW CLAWBOT")

task main()

{

// Set encoders to 0 at the beginning

// You will do this each time you want to measure a distance starting from a new point

SensorValue[leftEncoder] = 0;

SensorValue[rightEncoder] = 0;


/********************************************************************************************************************************

* This loop runs the motor until the left-wheel encoder reaches 360. The loop then breaks and the motors are set to zero.

* We use "abs", which is the absolute value, because a forward turn of the wheel may add positive numbers to the encoder or

* negative numbers to the encoder depending on which way the encoders are attached to the robot.

* To begin, we will just check one of the two encoders (the left one below). Later on we will be watching both encoders closely.

*********************************************************************************************************************************/

while( abs(SensorValue[leftEncoder]) < 360 )

{

motor[leftMotor] = 30;

motor[rightMotor] = 30; //Notice we are moving on low power for better accuracy - less slipping when starting/stopping

}


// The loop breaks when the encoder is equal to 360 or greater, and then the motors are set to 0.

motor[leftMotor] = 0;

motor[rightMotor] = 0;

// Because the loop runs one last time at an encoder value of 359, and because the robot will slide a little when it stops,

// the actual ending value after the loop finishes and the robot stops will be around 361-367

}

How to Measure a Distance in a RobotC Virtual World

There are two main ways in which we will measure distance in a RobotC Virtual World:

  1. In Curriculum Companion 4.2.7 you can use laser markers to calculate precise distances

  2. In RVW Level Builder, where we will be loading custom teacher-created maps, we will count squares to approximate distances.

Measuring Distance - Option #1 - Using Laser Markers in Curriculum Companion 4.2.7

When using Curriculum Companion 4.2.7, you can use the built-in measuring tool. Here is how:

    1. Before starting to use this tool, selecting the camera view #2 which is the bird's eye view.

    2. To start using the measuring tool, click on the "SHOW" button at the right of your screen. You must do this once to be able to use the measuring tool. When the tool is ready to use, you will see a red laser coming from the front of your robot.

    3. Now click on the "ADD" button and select a place directly in front of your robot. This will measure the distance from the Sonar Sensor on your robot to the marked spot on the map.

    4. Now click on a new spot on the map.

    5. You may only place 3 markers at a time. When there are three on the board, you will not be able to place a new marker until you click the "CLEAR" button. When ready, clear your past markers and begin placing new markers.

Each time a new point is dropped, you are given two pieces of information:

    1. The distance in meters from your robot to the first marker, or between subsequent markers.

    2. The angle the robot needs to turn clockwise by (in degrees) to be pointed at the marker. A negative angle simply means a counter-clockwise turn.

Distance - Option #2 - Counting Squares in RVW Level Builder

Every starting board in the RVW Level Builder is a twelve-foot by twelve-foot square (12'x12'). The board has a 12x12 grid of thick lines representing tiles measuring 1'x1'. Each of these smaller 1-foot squares is made of a 3x3 grid of 4"x4" squares. The image below shows this.

How to Move a Set Distance

Given the information above, we can calculate the number of degrees needed for any distance to travel using ratios and proportions.

We know that 360 Degrees = 29.53 cm

For 100cm, about how many degrees is that?

360 degrees ? degrees

------------------ = -----------------

29.53 cm 100 cm

When we solve this proportion (cross multiply and then divide), we get about 1219.1 degrees after rounding. The code for the robot to move

100cm would be as follows.

#pragma config(StandardModel, "RVW CLAWBOT")

task main()

{

//Set encoders to 0

SensorValue[leftEncoder] = 0;

SensorValue[rightEncoder] = 0;


//Run the motor until one of the encoders reaches 1219.1 degrees (around 100cm)

while( abs(SensorValue[leftEncoder]) < 1219.1 )

{

motor[leftMotor] = 30;

motor[rightMotor] = 30;

}


//After the loop breaks (at 1219.1 degrees), the motors are set to 0 to stop the robot.

motor[leftMotor] = 0;

motor[rightMotor] = 0;

}

Activity 1

    • Write code to move the robot 10 cm.

    • Write code to move the robot 50 cm.

    • Write code to move the robot 200 cm or 2 meters.

Activity 2

    • Write a function that takes in a float number of degrees, and have the robot move forward that amount of degrees then stop.

    • Call it void moveForwardDegrees(float degrees). Test it by calling it in the main and passing in 1500 degrees as the input.

  • Write a function that takes in a float value in centimeters, and have the robot move forward that distance then stop.

  • Call it void moveFowardDistance(float distance). Test it by calling it in the main and passing in 800 cm as the input.

  • Note: In RobotC, you must use float. There can be some issues with float calculation using integers.

  • To convert the cm to degrees for the radius of the wheel use of the following formula.

  • float degree = (360.0 / circumference of wheel) * distance to travel;

Making (more) Precise Turns

You can use the encoder to make turns. This is similar to moving forward, but the wheels will be moving in different directions.

Big Picture - Wheel encoders aren't the best method for measuring turns, but it is more precise than wait times (which can fluctuate greatly depending on what the CPU is doing when running the code). In future lessons, we will use different sensors to measure how much the robot has turned. The reason encoders aren't the best to measure turns is that to turn a wheel, it must slip on the ground. Calculating this slippage is a wonderful friction/physics/calculus problem.

At the moment, we will guess-and-check wheel encoder values to see about how many wheel rotations make the robot turn about 90 degrees. This will again be more precise than using wait times, but the small errors will accumulate as we navigate through mazes.

The following code turns the robot about 90 degrees to the right. In this case, the left wheels will rotate forward while the right wheels will rotate backwards. The wheels will rotate until the left encoder goes past 269 degrees of rotation.

#pragma config(StandardModel, "RVW CLAWBOT")

task main()

{

// Set encoders to 0

SensorValue[leftEncoder] = 0;

SensorValue[rightEncoder] = 0;


// Run the motor until the left encoder reaches 270 degrees

// Note that this means 270 degrees of wheel rotation, which is different from a 270 degree turn.

// Through trial and error you will have to figure out in what ratio the wheel rotation degrees relate to the turning degrees

while( abs(SensorValue[leftEncoder]) < 270 )

{

motor[leftMotor] = 30;

motor[rightMotor] = -30;

}

}

Activity 3

Again, note that you will have to use trial and error to figure out how many degrees the wheels should rotate to make the below turns.

    • Write code for the robot to turn 90 degrees to the left.

    • Write code for the robot to turn 180 degrees (left or right is the same).

    • Write code for the robot to turn 360 degrees (left or right is the same).

Activity 4

    • Write a function called void turnLeft (int degrees) that will turn the robot left a specified degree angle. An input of 90 degrees should make the robot turn 90 degrees. Test it with an 80 degree turn.

    • Write a function called void turnRight (int degrees) that will turn the robot right a specified degree angle. Test it with 270 degrees.

Line Straightening - Correcting for Imbalanced Motors

One really helpful usage of encoders is line straightening. This technique allows for the robot to straightening itself out when moving forward. The idea behind this is that one wheel will adjust its speed if the other wheel encoder degrees are not in sync with its own encoder degrees. Lets look at the following code to see how this works.

#pragma config(StandardModel, "RVW CLAWBOT")

task main()

{

// Set both wheel encoders to 0

SensorValue[leftEncoder] = 0;

SensorValue[rightEncoder] = 0;


// Travel 1000 degrees in a straight line

while( abs( SensorValue[leftEncoder] ) < 1000 )

{

// If left encoder is less than right, increase the left motor's power level a bit

if( abs( SensorValue[leftEncoder] ) < abs( SensorValue[rightEncoder] ) )

{

motor[leftMotor] = 80;

motor[rightMotor] = 60;

}

// Else if left encoder is greater than right, increase the right motor's power level a bit

else if( abs( SensorValue[leftEncoder] ) > abs( SensorValue[rightEncoder] ) )

{

motor[leftMotor] = 60;

motor[rightMotor] = 80;

}

// Else, they must be equal encoder values. In this case, keep the power levels the same for both.

else

{

motor[leftMotor] = 60;

motor[rightMotor] = 60;

}

}

}

Activity 5

    • Write code to move the robot 2000 degrees using line straightening.

    • Write code to move the robot 50 cm using line straightening.

    • Write code to move the robot 2 meters using line straightening.

Activity 6

    • Write a function that takes in a float number of degrees, and has the robot move forward that amount of degrees using line straightening.

    • Call it void moveStraightForwardDegrees (float degrees). Test it with 1000 degrees.

  • Write a function that takes in a float number of centimeters, and has the robot move forward that amount of distance using line straightening.

  • Call it void moveStraightForwardDistance (float cm). Test it with 500 cm.