How do I use the blocks's encoder features?

I’m making a program. It first needs to set the zero point at zero degrees, and then rotate the motor from zero degrees to ninety degrees using the blocks’ encoder feature. How do I do this? All these encoder things are super confusing, too. Thanks

No worries, we all start somewhere, just some of us probably started a long, long time ago in a galaxy far, far away. Haha.

So let’s focus specifically on your question, how to make a motor move 90 degrees in Blocks. First, we have to assume you have a motor plugged into Motor Port 0 on the Control Hub, and you have your encoder cable plugged into the associated Encoder Port 0 located “just below” the motor power port. It’s important to plug the encoder cable into the power port’s encoder input, the two of them are “paired” together. In your Robot Configuration, I also hope you have your motor configured properly as the type of the motor.

In my case, I’m going to use a Core Hex motor plugged into Motor Port 0. Here is what my motor config looks like:

Let’s start with the base sample program, the BasicOpMode. It looks like this:

image

Okay, now that we have a baseline to start with, let’s add the code to do what we want to do. I personally like initializing my motors to zero at the start of my program, which is the INIT stage of the software (when you press INIT for the OpMode on the Driver Hub - basically everything before the call to “call waitForStart”). Not everyone does it this way, but I certainly do.

The way the FTC software controls motors is it “counts” the internal encoder ticks made as the motor turns, and it uses an internal algorithm to control the motor based on those ticks. When the motor rotates in the “forward” direction the encoder ticks “up” (positive), and when the motor rotates in the “backwards” direction the encoder ticks “down” (negative). Each tick is counted by an accumulator/counter.

So first we have to reset the encoder accumulator/counter. We do this by putting the motor into the STOP_AND_RESET_ENCODER mode, by adding the following block and changing the mode to STOP_AND_RESET_ENCODER:

The thing we have to understand is that each motor has a different encoder “tick rate”. Generally we think of rotation as the rotation of the output shaft, but that is highly dependent on the gearing of the transmission being used. For example, the REV Core Hex motor ticks 4 times per rotation of the internal motor, but it has a 72:1 transmission, which means it will tick 288 times (4 x 72 = 288) per rotation of the output shaft. By comparison, the REV HD Hex motor ticks 28 times per rotation of the internal motor; with a 40:1 spur gearbox you’d get 1120 ticks per revolution of the output shaft (28 x 40 = 1120) and with a 20:1 ultraplanetary gearbox stack you’d get 560 ticks per revolution of the output shaft (28 x 20 = 560).

Okay, now we’re at the point where we want to rotate the motor. Let’s set up a gamepad button situation so we can see what it looks like when we want to set multiple different “rotations”.

What I did here was set up a couple different situations:

  1. Press Button A on Gamepad 1
    • Motor moves to 90 degrees (one-fourth of a rotation) from Zero.
    • Because I also allow moving the motor using the “else” statement, you have to HOLD THE BUTTON DOWN. If you let go, the “else” statement will change modes and cancel moving to the target position.
  2. Press Button B on Gamepad 1
    • Motor moves to Three Rotations from Zero.
    • Because I also allow moving the motor using the “else” statement, you have to HOLD THE BUTTON DOWN. If you let go, the “else” statement will change modes and cancel moving to the target position.
  3. Press Button X on Gamepad 1
    • Motor moves back to origin position (zero tick counts).
    • Because I also allow moving the motor using the “else” statement, you have to HOLD THE BUTTON DOWN. If you let go, the “else” statement will change modes and cancel moving to the target position.
  4. Press Left Bumper button on Gamepad 1
    • Zero motor encoder from the current position.
  5. Move the Left Analog Stick in the Y axis
    • Control motor power using stick.
    • Only works if you’re not currently pressing one of the buttons that automatically moves the motors. If the “else” portion of this “if” block wasn’t here, there wouldn’t be a case where the mode would be changed, and you wouldn’t have had to hold down the buttons to automatically move the motor to specific positions.

What’s fun here is the Telemetry is being fed the current encoder count value, so you can see what the encoder counts are doing. If you press Button X, it will rotate the motor back to the zero count no matter where it is.

When using the code, keep this in mind:

  • When asking the motor to go to a target position, always do the tasks IN ORDER.
    • Step 1 - Set the Target Position.
    • Step 2 - Set the Mode to RUN_TO_POSITION
    • Step 3 - Set the power of the motor (to tell the system how fast to get there).
    • NEVER do these out of order. The behavior can be indeterminant, or if you set the target position while the motor is running you might upset the SDK and the code will crash.
    • Fun fact - the power value is ALWAYS between 0 and 1 when using RUN_TO_POSITION. Because you set the motor type in the robot configuration, the robot knows which direction to spin the motor to make it go FORWARD and which way to go BACKWARD, so all you’re providing in the Set Power block is the absolute speed (not direction - direction was implicit in the target position value).

If you have questions, please ask.

One note, however, the purple “isBusy” block could have been used to only allow moving the motor with the joystick (which would prevented you from having to hold the button down) ONLY if the system wasn’t automatically moving the motor - isBusy returns “true” if the motor is being automatically moved to a position by using the RUN_TO_POSITION mode. However, I hate that, because you then can’t interrupt the action without using one of the other buttons. I personally like being able to manually move the motor if I want to, and interrupt the action by just releasing the button, and using buttons as “get me in the general vicinity without me having to think about it.”

Using the “isBusy” block to keep the mode from being changed while automatically moving to the target position was being executed would have looked like this:

-Danny

THANKS so much! Im using a Rev HD Hex 40:1 motor but aren’t sure of the model name.Would that be the 40:1 gearbox? So what would the number of ticks be for 90 degrees?

What’s the telemetry block?

Do I need the isBusy block?

I also have a specific point the motor needs to start at - that’s considered the zero positon, right, and how do I start that?

Planning to use this as an autonomous program, what will I need to change?

Thanks again

Im using a Rev HD Hex 40:1 motor but aren’t sure of the model name.Would that be the 40:1 gearbox? So what would the number of ticks be for 90 degrees?

The “REV HD Hex 40:1 motor” is a REV HD Hex motor with a 40:1 spur gearbox - yup, it’s as easy as the name suggests. The REV encoder specifications for the 40:1 motor is exactly as I described in the previous post - the motor provides 1120 ticks per revolution of the output shaft. 90 degrees is one-fourth of a rotation, so that’s one-fourth of 1120, or 280 ticks.

What’s the telemetry block?

Telemetry is a way to send messages from the Robot to the Driver Station, so we can use the Driver Station App as a “screen” for text from the robot. It’s exactly like the robot sending back messages to the user. In this case, we’re adding data to the messages that get sent back to the user about the encoder value. So with the purple telemetry blocks, we can monitor the value of the motor encoder. Here is a really good YouTube video that shows how to do Telemetry. The video is a little dated, but all the concepts are exactly the same.

Do I need the isBusy block?

I don’t think you want the isBusy Block for this specific use-case, but the isBusy block is really useful - especially in autonomous - to know when the motion has completed. You can tell the robot to do a RUN_TO_POSITION motion, but it doesn’t happen instantly - you have to wait for it to be done. In our example above we didn’t wait for it to be done, we just knew it would be done eventually. But depending on how far you moved the motor using the analog stick, it could take a while to bring the motor back to zero (or to any of the other presets). The only way you’d know when it was done would be by waiting until isBusy returns false.

I also have a specific point the motor needs to start at - that’s considered the zero positon, right, and how do I start that?

Oh, that’s a harder case. See, the encoders aren’t absolute encoders, meaning they can’t tell you exactly where they are without more information. When the robot powers off, the counter gets reset, so you can’t maintain knowing your “position” through a power down and power up. So usually teams mount a REV touch sensor at the lowest point where a robot arm (for example) can go down to, and when they touch the sensor you can know “aha, here’s where the arm is.” Then you can zero the encoder and know you’re at a known mechanical position. Sometimes that can also be the floor, if the mechanism can’t go any farther down then it’s at a known lowest position. You kinda have to decide how you want to manage it.

Planning to use this as an autonomous program, what will I need to change?

It’s important to understand that there’s fundamentally no difference between a TELEOP OpMode and an AUTO OpMode, except that an AUTO OpMode generally doesn’t use gamepad data (since you can’t use the gamepads during AUTO) and an AUTO OpMode doesn’t have a “repeat while” loop. Usually an AUTO OpMode (especially for a beginner team) just has a list of sequential commands you want to perform, and when you’re done the program simply quits.

I highly recommend reading this ftc-docs article on auto-loading OpModes, it explains a few things about OpModes. This article on My first autonomous program is also a really good article that walks you through creating a Blocks auto OpMode.

Again, if you have more questions just ask!
-Danny