Wheel Encoders – V3

So far we have been controlling the motors by setting their power. Unfortunately, this is not ideal because the power only indirectly controls the speed, which is what we are really interested in. As we have already seen, our robot does not exactly drive straight when we apply the same power to both wheels. This is because differences in the motors and the way they are mounted cause them to run at slightly different speeds when the same power is applied.

What we need is some way to tell how far the wheels have turned and how fast. Each of the wheels on this robot have an encoder which will do just that. We will use the encoder to control the distance the robot moves as well as it’s speed.

For our first exercise, we are going to create a new command, similar to our DriveForTimeCommand, that will drive the robot forward a fixed distance, rather than a fixed time. Before that, a word on encoders and how we use them in software.

The encoders that we are using are handled by the Encoder class. We will need to create a separate instance of this class for the left and right motors. The DriveMechanism will eventually need the encoders so we will be adding these to that class. Consulting the Encoder class documentation, we see that the constructor take a encoder type and two integer parameters which specifies the Microcontroller pins to which they are connected. Once again these values are provided via the Minibot class. Using these values we can create our encoder declarations as follows:

When you import the Encoder class be sure to select the one from RobotCore.

Encoder Import

The way the encoders are wired, the left encoder works as expected – when the left wheel moves forward (e.g., moves the robot forward), the encoder counts up. BUT, the right encoder counts down when the wheel moves forward. Rather than having to deal with this throughout the code, we can tell the encoder that it is “inverted” by adding the following to the DriveSubsystem constructor:

The call to setInverted(true) tells the encoder to report the reverse of its direction, so it becomes “positive means forward”, like the left encoder.

Your DriveMechanism.java file should now look like:

Now it is time to create our new command which we will call DriveForDistance command. As you did before create a new function in DriveMechanism.java called driveForDistance() function that takes a power and distance as arguments and returns a new Command() and fill in all the missing functions as before, leaving the run() function to fix. Your driveForDistance() function should look like:

Now we need to do the following in the run() function:

  • Reset the encoder to zero by calling the encoder’s reset() function
  • Turn the motors on by calling setPower()
  • Loop until the current encoder value obtained by a call the encoder’s get() function reaches the distance.
  • Turn the motors off by calling stop()

Take a shot of creating this code yourself. When you are done, your run() function should look something like:

Don’t forget the yeild() in your loop!

We now need configure joystick button 2 (index 1) so when it is pressed we will run the DriveForDistance command. Add one line to TeleopOpMode constructor:

Note that the distance that we are passing in are in somewhat arbitrary units. The Encoder counts are somewhat arbitrary as they depend on the particular motor/encoder and the size of the wheel. We have chosen 2000 here just to test this command. Later we will perform a conversion which will allow us to use real world units such as inches.

Now run your program and click the B2 button. You should find that your robot will drive a short distance and then stop. Also note that since we are now using distance rather than time, we can change the speed and the robot should still move the same distance. Try it out and see.

Next: Speed Control