Often times, like in the program created during Part 2: Robot Control, we use the block to set the drivetrain motors to a set power or power based on a joystick's inputs. The combined power going to both motors help to determine the direction the robot moves or turns.
However, in RUN_TO_POSITION
mode the encoder counts are used instead of to dictate directionality of the motor.
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:
The rightTarget
has been changed to be a negative target position. Assuming that the encoder starts at zero due to STOP_AND_RESET_ENCODER
this causes the robot to turn to the right.
Notice the velocity is the same for both motors. If you try running this code, you can see that the robot pivots along its center of rotation.
To get a wider turn, try 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.
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.
For this tutorial, our OpMode is named HelloRobot_Encoder!
Before diving in too far, recall that for certain drivetrains, like the Class Bot V2, one of the motors needs to be reversed as the motors are mirrored. In our example, we are adding the block under the .
As introduced in Using Encoders, using RUN_TO_POSITION
mode requires a three step process.
If we want our robot to travel a specific distance we will need to do a bit of math beforehand to calculate the TargetPosition. But for now let's start simple by setting the target position to 1000 ticks.
Order matters! The TargetPosition block must come before RUN_TO_POSITION mode is set or it will result in an error.
As mentioned, normally there would be more math involved to help determine how fast the motors should move to reach the desired position. But for testing purposes, we are going to start by keeping it simple!
Save your OpMode and give it a test. What happens once you press play? What happens if you stop the program then start it again?
For our demo code we will want to request our motors reset their encoders during the initialization process of the program.
Let's say we want our program to run only for however long it takes for the motors to reach designated position. Or maybe we intend for the robot to do something else after reaching the destination. For this we will need to edit our whileLoop block!
Even though we are ending a new exit case for our loop, we must always have our call to check opModeIsActive or our program will instantly timeout!
Save your OpMode and give it a try!
As soon as the motors hit the desired position the program will end instead of continuously run in the event they do not perfectly hit the position.
In the previous section, the basic structure needed to use RUN_TO_POSITION
was created. The placement ofwithin the code, set the target position to 1000 ticks.
But how far is a tick and how can we use them to help our robot navigate an area? We could attempt to estimate the distance the robot moves per tick or we can convert the amount of ticks per revolution of the encoder into a unit like millimeters or inches! 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.
This process will take a bit of math to achieve so let's break it down.
When using encoders built into motors, converting from ticks per revolution to ticks per unit of measure moved requires the following information:
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.
Visit the manufacturers website for your motor or encoders for more information on encoder counts. For HD Hex Motors or Core Hex Motors visit the Motor documentation.
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.
The UltraPlanetary Cartridges use the nominal gear ratio as a descriptor. The actual gear ratios can be found in the UltraPlanetary Users Manual's Cartridge Details.
Using the compound gearing formula for the Class Bot V2 the total gear reduction is:
Unlike 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:
Ticks per revolution
28 ticks
Total gear reduction
30.21
Circumference of the wheel
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:
COUNTS_PER_MOTOR_REV
DRIVE_GEAR_REDUCTION
WHEEL_CIRCUMFERENCE_MM
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.
We'll add the variables to the initialization section of the OpMode:
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 multiply COUNTS_PER_MOTOR_REV
by DRIVE_GEAR_REDUCTION
Use the following formula:
Where:
Once the COUNTS_PER_WHEEL_REV
is calculated, it can be used to calculate the counts per mm that the wheel moves. To do this divide the COUNTS_PER_WHEEL_REV
by the WHEEL_CIRCUMFERENCE_MM
. Use the following formula.
Where,
COUNTS_PER_WHEEL_REV
will be created as a separate variable from COUNTS_PER_MM
as it is used in calculating a target velocity.
Once COUNTS_PER_WHEEL_MM
is set, this completes the conversion process, and all constant variables are set.
Make sure to save your OpMode here to prevent any progress being lost in the event of a disconnect!
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_MM
will give you the amount of counts (or ticks) needed to reach that distance!
Let's create two more variables called leftTarget
and rightTarget
. Add the and blocks within the if/then statement that will run once Play is selected.
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.
Next, multiply 610 millimeters by the COUNTS_PER_MM
variable 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 leftTarget
and rightTarget
, to be equal to 610 * COUNTS_PER_MM
Velocity is a closed loop control within the that uses the encoder counts to determine the approximate power/speed the motors need to go in order to meet the set velocity.
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!
Since RPM is the amount of revolutions per minute, a conversion needs to be made from RPM to ticks per second (TPS). To do this, divide the RPM by 60 to get the amount of rotations per second.
Rotations per second can then 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 beginning of the if/then statement above the target variables.
With the velocity set, let's give our program a test run after saving!
The first step is setting target position. To do so, grab the block and add it to under the comment. For this example, we are setting our position after pressing Initialize, but before we hit Play on the Driver Hub.
The next step is to set both motors to the RUN_TO_POSITION
mode. Place the block beneath the block.
Add the block beneath the block. Let's go ahead and change the duty cycle (or power) of both motors to 0.8, instead of 1.
Grab an 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.
Embed the in another block. Place the on the right side of the block. Our call for the OpMode will go in the lefthand side slot.
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 such as:
Once the variables are created and added to the OpMode, use the blocks to set the variables to the respective values.
For WHEEL_CIRCUMFERENCE_MM
a combination of the , , and blocks will be used to get the circumference of the wheel.
= COUNTS_PER_MOTOR_REV
= DRIVE_GEAR_REDUCTION
= COUNTS_PER_WHEEL_REV
Again math blocks need to be used to define these variables. Lets start with the COUNTS_PER_WHEEL_REV
variable. Add a to the block. Add the and blocks to either side of the block.
= COUNTS_PER_MOTOR_REV
= DRIVE_GEAR_REDUCTION
= WHEEL_CIRCUMFERENCE_MM
= COUNTS_PER_WHEEL_REV
= COUNTS_PER_MM
Since COUNTS_PER_WHEEL_REV
has been calculated it can be used to calculate COUNTS_PER_MM
add the to the . On the left side of the add the block. On the right side of the add the .
Lastly, we need to change the so that both motors are set to the appropriate target position. To do this add the and blocks to their respective motor.
Add a block to the block. On the right side of the block add the . One the left side of the add the block.
Add the chosen RPM (175 in this example) 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.