Encoders

Encoders are a sensor placed normally on a shaft to provide feedback to a controller. This feedback allows for the detection of position, speed and direction of motion control system. There are two types of encoders absolute and incremental. Absolute encoders report back a location specific position and will remember the position through a power cycle. Incremental encoders only indicate that there has been a change in position and what that change was. In robotics both types of encoders are used. There are also advanced encoders that offer the function of both absolute and incremental.

Studica offers both types of encoders. The Maverick motor has an incremental encoder attached to the back of the motor. There is also the Cypher Max which is an advanced encoder that offers absolute and incremental outputs.

../../_images/encoder-1.svg

Cypher Max Specs (Click to Open)
Cypher Max Specs

Function

Value

Counts Per Revolution

512

Absolute Interface

PWM

Incremental Interface

ABI

Programming Interface

SPI

Voltage

3.3V or 5V

Temperature Range

-40℃ to 125℃

Default Hub

3/8” Hex

Included with each Cypher Max:

  • PWM Cable

  • ABI Cable

  • FTC Control Hub Cable

  • Breakout Cable

  • 5mm Hex Insert

  • 6mm D-Shaft Insert

  • 7mm Hex Insert

Note

With a CPR of 512 and a quadrature output the total pulses per revolution will be 2048.

Maverick Encoder Specs
Maverick Encoder Specs

Function

Value

Counts Per Revolution

6

Current

6mA

Voltage

4V - 5V

Note

With a CPR of 6, gear ratio of 61:1 and a quadrature output the total pulses per revolution will be \(\begin{equation}6*61*4 = 1464\end{equation}\).

Calculating Distance

There are few formulas required to calculate distance traveled using incremental encoders.

\[\begin{equation} {distancePerTick} = \frac{2 \pi r}{ticksPerRev * gearRatio} \end{equation}\]

Where:

  • r = wheel or pulley radius.

  • ticksPerRev = ammount of pulses of the encoder for one complete rotation.

  • gearRatio = an external gear ratio used. Mostly will be 1:1 unless the encoder is not connected to output wheel or pulley directly.

Example

Let’s look at an example using the Maverick and a 100mm omni wheel attached directly on the shaft of the motor.

  • r = 51mm (actual measured radius of omni wheel)

  • ticksPerRev = 1464

  • gearRatio = 1:1 (no external gearbox)

\[\begin{equation} {distancePerTick} = \frac{2 \pi r}{ticksPerRev * gearRatio} = \frac{2 \pi 51}{1464 * 1} = \frac{102 \pi}{1464} = 0.218881455mm \end{equation}\]

Therefor we can conclude that the distancePerTick for the Maverick using a 100mm omni wheel is 0.218881455mm.

Application

The last formula needed is:

\[distance = {distancePerTick} * {encoderCount}\]

Where:

  • distancePerTick = is calculated from the formula above.

  • encoderCount = the incremental count from the encoder.

Let’s look at a real work example.

One Wheel Roation

  • encoderCount = 1464

  • distancePerTick = 0.218881455mm

\[distance = {0.218881455} * {1464} = 320.44 mm\]

Note

The distance measured is in mm as the radius was specficed in mm.

With one wheel rotation there is a total travel of 320.4mm.

120 Wheel Rotations

  • encoderCount = 175680

  • distancePerTick = 0.218881455mm

\[distance = {0.218881455} * {175680} = 38453.09401 mm\]

With 120 wheel roations there is a total travel of 38.45m.

Code

Now that the math is known behind calculating distance with an incremental encoder. How can that be programmed.

Constants

 1/**
 2 * Motor Constants
 3 */
 4public static final int TITAN_ID                = 42;
 5public static final int MOTOR                   = 2;
 6
 7/**
 8 * Encoder Constants
 9 */
10
11//Radius of drive wheel in mm
12public static final int wheelRadius             = 51;
13
14//Encoder pulses per rotation of motor shaft
15public static final int pulsePerRotation        = 1464;
16
17//Gear ratio between motor shaft and output shaft
18public static final double gearRatio            = 1/1;
19
20//Pulse per rotation combined with gear ratio
21public static final double encoderPulseRatio    = pulsePerRotation * gearRatio;
22
23//Distance per tick
24public static final double distancePerTick      = (Math.PI * 2 * wheelRadius) / encoderPulseRatio;

Subsystem

 1import com.studica.frc.TitanQuad;
 2import com.studica.frc.TitanQuadEncoder;
 3
 4public class Subsystem
 5{
 6    /**
 7     * Motors
 8     */
 9    private TitanQuad motor;
10
11    /**
12     * Sensors
13     */
14    private TitanQuadEncoder encoder;
15
16    public Subsystem()
17    {
18        //Motors
19        motor = new TitanQuad(Constants.TITAN_ID, Constants.MOTOR);
20
21        //Sensors
22        encoder = new TitanQuadEncoder(motor, Constants.MOTOR, Constants.distancePerTick);
23    }
24
25    /**
26     * Gets the distance traveled of the motor
27     * <p>
28     * @return the distance traveled
29     */
30    public double getEncoderDistance()
31    {
32        return encoder.getEncoderDistance();
33    }
34}