Encoder Navigation - Blocks
In the previous section you learned about how to use Elapsed Time to allow your robot to navigate the world around it autonomously. When starting out many of the robot actions can be accomplished by turning on a motor for a specific amount of time. Eventually, these time-based actions may not be accurate or repeatable enough. Environmental factors, such as the state of battery charge during operation and mechanisms wearing in through use, can all affect time-based actions. Fortunately, there is a way to give feedback to the robot about how it is operating by using sensors; devices that are used to collect information about the robot and the environment around it.
With Elapsed Time, in order to get the robot to move to a specific distance, you had to estimate the amount of time and the percentage of duty cycle needed to get from point a to point b. However, the REV motors come with built in encoders, which provide feedback in the form of ticks ( or counts) per revolution of the motor. The information provided by the encoders can be used to move the motor to a target position, or a target distance.
Moving the motors to a specific position, using the encoders, removes any potential inaccuracies or inconsistencies from using Elapsed Time. The focus of this section is to move the robot to a target position using encoders.
There are two articles in that go through the basics of Encoders. Using Encoders goes through the basics of the different types of motor modes, as well as a few application examples of using these modes in code. In this section we will focus on using
It is recommended that you review both articles before moving on with this guide.
Start by creating a basic op mode called HelloRobot_EncoderAuton.
When creating an op mode a decision needs to be made on whether or not to set it to autonomous mode. For applications under 30 seconds, typically required for competitive game play changing the op mode type to autonomous is recommended. For applications over 30 seconds, setting the code to the autonomous op mode type will limit your autonomous code to 30 seconds of run time. If you plan on exceeding the 30 seconds built into the SDK, keeping the code as a teleoperated op mode type is recommended.
block to the op mode under the
.This will change the direction of the rotation of the right motor to be the same direction as the left motor.
Recall from Using Encoders that using
RUN_TO_POSITIONmode requires a three step process. The first step is setting target position. To set target position, grab the
block and add it to the op mode under the
comment. To get a target position that equates to a target distance requires so calculations, which will be covered later. For now, set target position to 1000 ticks.
When there are multiple of the same type of variable (such as multiple Dc Motor variables) the variable specific blocks will choose a default variable based on alphabetical order. For this example Op Mode Dc Motor blocks will default to the arm variable. Click the arrow next to the motor name to change the arm motor variable to the rightmotor variable. Use the variable drop down menu on the block to change from arm to rightmotor.
The next step is to set both motors to the
RUN_TO_POSITIONmode. Place the
block beneath the
The main focus of the three step process is to set a target, tell the robot to move to that target, and at what speed (or velocity) the robot should get to that target. Normally, the recommended next step is to calculate velocity and set a target velocity based on ticks. However, this requires quite a bit of math to find the appropriate velocity. For testing purposes, its more important to make sure that the main part of the code is working before getting too deep into the creation of the code. Since the
function was covered in previous sections and will communicate to the system what relative speed (or in this case duty cycle) is needed to get to the target, this can be used in the place of velocity for now.
block to the op mode beneath the
block. Change the duty cycle (or power) of both motors to 0.8, instead of 1.
Now that all three
RUN_TO_POSITIONsteps have been added to the code the code can be tested. However, if you want to wait for the motor to reach its target position before continuing in your program, you can use a while loop that checks if the motor is busy (not yet at its target). For this program lets edit the
Recall that, within a linear op mode, a while loop must always have the
Boolean as a condition. This condition ensures that the while loop will terminate when the stop button is pressed.
block from the logic menu and add it to the while loop. On the left side of the
block add the
block. On the right side add the
block. Place the
on the right side of the
block. On the left side add the
Right now the while loop is waiting for the right and left motors to reach their respective targets. There may be occasions when you want to wait for both motors to reach their target position, in this case the
can be used.
Save and run the op mode two times in a row. Does the robot move as expected the second time?
Try turning the Control Hub off and then back on. How does the robot move?
In the Basic Encoder Concepts section, it is clarified that ell encoder ports start at 0 ticks when the Control Hub is turned on. Since you did not turn off the Control Hub in between runs, the second time you ran the op mode the motors were already at, or around, the target position. When you run a code, you want to ensure that certain variables start in a known state. For the encoder ticks, this can be achieved by setting the mode to
. Add this block to the op mode in the initialization section. Each time the op mode is initialized, the encoder ticks will be reset to zero.
In the previous section, the basic structure needed to use
RUN_TO_POSITIONwas created. The placement of
within the code, set the target position to 1000 ticks. What is the distance from the starting point of the robot and the point the robot moves to after running this code?
Rather than attempt to measure, or estimate, the distance the robot moves, the encoder ticks can be converted from amount of ticks per revolution of the encoder to how many encoder ticks it takes to move the robot a unit of distance, like a millimeter or inch. Knowing the amount of ticks per a unit of measure allows you to set a specific distance. For instance, if you work through the conversion process and find out that a drivetrain takes 700 ticks to move an inch, this can be used to find the total number of ticks need to move the robot 24 inches.
Reminder that the basis for this guide is the Class Bot V2. The REV DUO Build System is a metric system. Since part of the conversion process references the diameter of the wheels, this section will convert to ticks per mm.
When using encoders built into motors, converting from ticks per revolution to ticks per unit of measure moved requires the following information:
- Ticks per revolution of the encoder shaft
- Total gear reduction on the motor
- Including gearboxes and motion transmission components like gears, sprockets and chain, or belts and pulleys
- Circumference of the driven wheels
The amount of ticks per revolution of the encoder shaft is dependent on the motor and encoder. Manufacturers of motors with built-in encoders will have information on the amount of ticks per revolution. For HD Hex Motors the encoder counts 28 ticks per revolution of the motor shaft.
Since ticks per revolution of the encoder shaft is before any gear reduction calculating the total gear reduction is needed. This includes the gearbox and any addition reduction from motion transmission components. To find the total gear reduction use the Compound Gearing formula.
For the Class Bot V2 there are two UltraPlanetary Cartridges, 4:1 and 5:1, and an additional gear reduction from the UltraPlanetary Output to the wheels, 72T:45T ratio.
Using the compound gearing formula for the Class Bot V2 the total gear reduction is:
Unlike the the spur gears used to transfer motion to the wheels, the UltraPlanetary Gearbox Cartridges are planetary gear systems. To make calculations easier the gear ratios for the Cartridges are already reduced.
The Class Bot V2 uses the 90mm Traction Wheels. 90mm is the diameter of the wheel. To get the appropriate circumference use the following formula
You can calculate this by hand, but for the purpose of this guide, this can be calculated within the code.
Due to wear and manufacturing tolerances, the diameter of some wheels may be nominally different. For the most accurate results consider measuring your wheel to confirm that the diameter is accurate.
To summarize, for the Class Bot V2 the following information is true:
Each of these pieces of information will be used to find the number of encoder ticks (or counts) per mm that the wheel moves. Rather than worry about calculating this information by hand, these values can be added to the code as constant variables. To do this create three variables:
The common naming convention for constant variables is known as CONSTANT_CASE, where the variable name is in all caps and words are separated by and underscore.
Add the variables to the initialization section of the op mode.
Once the variables are created and added to the op mode, use the
blocks to set the variables to the respective values. For
WHEEL_CIRCUMFERENCE_MMa combination of the
blocks to get the circumference of the wheel. The
Now that these three variables have been defined, we can use them to calculate two other variables: the amount of encoder counts per rotation of the wheel and the number of counts per mm that the wheel moves.
To calculate counts per wheel revolution multiple
DRIVE_GEAR_REDUCTIONUse the following formula:
COUNTS_PER_WHEEL_REVis calculated, use it to calculate the counts per mm that the wheel moves. To do this divide the
WHEEL_CIRCUMFERENCE_MM. Use the following formula.
COUNTS_PER_WHEEL_REVwill be created as a separate variable from
COUNTS_PER_MMas it is used in calculating a target velocity.
Create these variables in Blocks and add then to the op mode under the other constant variables.
Again math blocks need to be used to define these variables. Lets start with the
COUNTS_PER_WHEEL_REVvariable. Add a
block. Add the
blocks to either side of the
COUNTS_PER_WHEEL_REVhas been calculated it can be used to calculate
. On the left side of the
block. On the right side of the
COUNTS_PER_WHEEL_MMis set, this completes the conversion process, and all constant variables are set.
Now that you have created the constant variables needed to calculate the amount of ticks per mm moved, you can use this to set a target distance. For instance, if you would like to have the robot move forward two feet, converting from feet to millimeters and multiplying by the
COUNTS_PER_MMwill give you the amount of counts (or ticks) needed to reach that distance.
Create two more variables called
rightTarget. Add the
blocks to the op mode above the
Right now the main distance factor is
COUNTS_PER_MM, however you may want to go a distance that is in the imperial system, such as 2 feet (or 24 inches). The target distance in this case will need to be converted to mm. To convert from feet to millimeters use the following formula:
If you convert 2 feet to millimeters, it comes out the be 609.6 millimeters. For the purpose of this guide, lets go ahead an round this to be 610 millimeters. Multiply 610 millimeters by the
COUNTS_PER_MMvariable to get the number of ticks needed to move the robot 2 feet. Since the intent is to have the robot move in a straight line, set both the
rightTarget, to be equal to 610 *
so that both motors are set to the appropriate target position. To do this add the
blocks to their respective motor.
Velocity is a closed loop control within the SDK that uses the encoder counts to determine the approximate power/speed the motors need to go in order to meet the set velocity. When working with encoder setting a velocity is recommended over setting a power level, as it offers a higher level of control.
To set a velocity, its important to understand the maximum velocity in RPM your motor is capable of. For the Class Bot V2 the motors are capable of a maximum RPM of 300. With a drivetrain, you are likely to get better control by setting velocity lower than the maximum. In this case, lets set the velocity to 175 RPM
setVelocityis measure in ticks per second.
Since RPM is the amount of revolutions per minute a conversion needs to be made from RPM to ticks per second. To do this divide the RPM by 60, to get the amount of rotations per second. Rotations per second can the be multiplied by
COUNTS_PER_WHEEL_REV, to get the amount of ticks per second.
Create a new variable called TPS. Add the
to the op mode under the
block to the
block. On the right side of the
block add the
. One the left side of the
block. Add the chosen RPM to the left side of the
block and 60 to the right side.
Now that the target ticks per second has been set, swap the
block for a
block. Add the
to both motors.
With the velocity set, this is the final thing needed to complete the objective of driving in a straight line. Consider adding telemetry and other hardware components as you begin fleshing out your full autonomous code.
In the Robot Navigation - Blocks section, the mechanism of
dictates what direction and speed a motor moves in. On a drivetrain the combined direction and speed of the motors dictates whether the robot moves in forward, backwards, or turns.
RUN_TO_POSITIONmode the encoder counts are used instead
of to dictate directionality of the motor. If a target position value is greater than the current position of the encoder, the motor moves forward. If the target position value is less than the current position of the encoder, the motor moves backwards
Since speed an directionality impacts how a robot turns, target position and velocity need to be edited to get the robot to turn. Consider the following code:
rightTargethas been changed to be a negative target position. Assuming that the encoder starts at zero due to
STOP_AND_RESET_ENCODERthis causes the robot to turn to the right. Velocity is the same for both motors. If you try running this code, you may notice that the robot pivots along its center of rotation. To get a wider turn changing the velocity so that the right motor is running at a lower velocity than the left motor. Adjust the velocity and target position as needed to get the turn you need.