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.
Cypher Max Specs (Click to Open)
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
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.
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)
Therefor we can conclude that the distancePerTick for the Maverick using a 100mm omni wheel is 0.218881455mm.
Application
The last formula needed is:
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
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
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}
Header
1#include <studica/TitanQuad.h>
2#include <studica/TitanQuadEncoder.h>
3
4#include <cmath>
5
6class Subsystem : public frc2::SubsystemBase
7{
8 public:
9 Subsystem();
10
11 double GetEncoderDistance (void);
12
13 private:
14 /**
15 * Motor Constants
16 */
17 #define TITAN_ID 42
18 #define MOTOR_N 2
19
20 /**
21 * Encoder Constants
22 */
23
24 //Radius of drive wheel in mm
25 #define wheelRadius 51
26
27 //Encoder pulses per rotation of motor shaft
28 #define pulsePerRotation 1464
29
30 //Gear ratio between motor shaft and output shaft
31 #define gearRatio 1/1
32
33 //Pulse per rotation combined with gear ratio
34 #define encoderPulseRatio pulsePerRotation * gearRatio
35
36 //Distance per tick
37 #define distancePerTick (M_PI * 2 * wheelRadius) / encoderPulseRatio
38
39 /**
40 * Objects
41 */
42 studica::TitanQuad motor{TITAN_ID, MOTOR_N};
43 studica::TitanQuadEncoder encoder{motor, MOTOR_N, distancePerTick};
44};
Source
1#include "subsystems/Subsystem.h"
2
3Subsystem::Subsystem(){};
4
5/**
6 * Gets the distance traveled of the motor
7 * <p>
8 * @return the distance traveled
9 */
10double Subsystem::GetEncoderDistance (void)
11{
12 return encoder.GetEncoderDistance();
13}