Codificadores - Software

Nota

Esta sección cubre codificadores en software. Para obtener una guía de hardware para codificadores, consulte Codificadores - Hardware.

Encoders are devices used to measure motion (usually, the rotation of a shaft).

Importante

The classes in this document are only used for encoders that are plugged directly into the roboRIO! Please reference the appropriate vendors” documentation for using encoders plugged into motor controllers.

Quadrature Encoders - The Encoder Class

WPILib proporciona soporte para codificadores cuadráticos a través de la clase :code:`Encoder`(`Java <https://github.wpilib.org/allwpilib/docs/release/java/edu/wpi/first/wpilibj/Encoder.html>`__, C++). Esta clase proporciona una API simple para configurar y leer datos de los encoders.

Quadrature Encoders determine direction by observing which pulse channel (A or B) receives a pulse first.

These encoders produce square-wave signals on two channels that are a quarter-period out-of-phase (hence the term, «quadrature»). The pulses are used to measure the rotation, and the direction of motion can be determined from which channel «leads» the other.

A Quadrature Decoder analyzing the A, B, and Index signals.

The FPGA handles quadrature encoders either through a counter module or an encoder module, depending on the decoding type - the choice is handled automatically by WPILib. The FPGA contains 8 encoder modules.

Examples of quadrature encoders:

Initializing a Quadrature Encoder

A quadrature encoder can be instantiated as follows:

  // Initializes an encoder on DIO pins 0 and 1
  // Defaults to 4X decoding and non-inverted
  Encoder m_encoder = new Encoder(0, 1);
  // Initializes an encoder on DIO pins 0 and 1
  // Defaults to 4X decoding and non-inverted
  frc::Encoder m_encoder{0, 1};

Decoding Type

La clase WPILib Encoder puede decodificar señales de codificador en tres modos diferentes:

  • Decodificación 1X: aumenta la distancia por cada período completo de la señal del codificador (una vez cada cuatro bordes).

  • Decodificación 2X: Incrementa la distancia por cada medio período de la señal del codificador (una vez por dos bordes).

  • Decodificación 4X: aumenta la distancia para cada borde de la señal del codificador (cuatro veces por período).

La decodificación 4X ofrece la mayor precisión, pero a costa de un aumento de la «fluctuación» en las mediciones de velocidad. Para usar un tipo de decodificación diferente, use el siguiente constructor:

  // Initializes an encoder on DIO pins 0 and 1
  // 2X encoding and non-inverted
  Encoder m_encoder2x = new Encoder(0, 1, false, Encoder.EncodingType.k2X);
  // Initializes an encoder on DIO pins 0 and 1
  // 2X encoding and non-inverted
  frc::Encoder m_encoder2x{0, 1, false, frc::Encoder::EncodingType::k2X};

Configuring Quadrature Encoder Parameters

Nota

La clase Encoder no hace ninguna suposición sobre las unidades de distancia; devolverá valores en las unidades que se hayan utilizado para calcular el valor de distancia por pulso. De este modo, los usuarios tienen un control completo sobre las unidades de distancia utilizadas. Sin embargo, las unidades de tiempo son siempre en segundos.

Nota

The number of pulses used in the distance-per-pulse calculation does not depend on the decoding type - each «pulse» should always be considered to be a full cycle (four edges).

La clase Encoder ofrece varios métodos de configuración:

    // Configures the encoder to return a distance of 4 for every 256 pulses
    // Also changes the units of getRate
    m_encoder.setDistancePerPulse(4.0 / 256.0);
    // Configures the encoder to consider itself stopped after .1 seconds
    m_encoder.setMaxPeriod(0.1);
    // Configures the encoder to consider itself stopped when its rate is below 10
    m_encoder.setMinRate(10);
    // Reverses the direction of the encoder
    m_encoder.setReverseDirection(true);
    // Configures an encoder to average its period measurement over 5 samples
    // Can be between 1 and 127 samples
    m_encoder.setSamplesToAverage(5);
    // Configures the encoder to return a distance of 4 for every 256 pulses
    // Also changes the units of getRate
    m_encoder.SetDistancePerPulse(4.0 / 256.0);
    // Configures the encoder to consider itself stopped after .1 seconds
    m_encoder.SetMaxPeriod(0.1_s);
    // Configures the encoder to consider itself stopped when its rate is below
    // 10
    m_encoder.SetMinRate(10);
    // Reverses the direction of the encoder
    m_encoder.SetReverseDirection(true);
    // Configures an encoder to average its period measurement over 5 samples
    // Can be between 1 and 127 samples
    m_encoder.SetSamplesToAverage(5);

Reading information from Quadrature Encoders

La clase Encoder proporciona una gran cantidad de información al usuario sobre el movimiento del codificador.

Distancia

Nota

Quadrature encoders measure relative distance, not absolute; the distance value returned will depend on the position of the encoder when the robot was turned on or the encoder value was last reset.

Los usuarios pueden obtener la distancia total recorrida por el codificador con el método getDistance():

    // Gets the distance traveled
    m_encoder.getDistance();
    // Gets the distance traveled
    m_encoder.GetDistance();

Velocidad

Nota

Las unidades de tiempo para la clase Encoder son siempre en segundos.

Los usuarios pueden obtener la tasa actual de cambio del codificador con el método getRate():

    // Gets the current rate of the encoder
    m_encoder.getRate();
    // Gets the current rate of the encoder
    m_encoder.GetRate();

Detenido

Los usuarios pueden obtener si el codificador está estacionario con el método getStopped():

    // Gets whether the encoder is stopped
    m_encoder.getStopped();
    // Gets whether the encoder is stopped
    m_encoder.GetStopped();

Dirección

Los usuarios pueden obtener la dirección en la que el codificador se movió por última vez con el método getDirection():

    // Gets the last direction in which the encoder moved
    m_encoder.getDirection();
    // Gets the last direction in which the encoder moved
    m_encoder.GetDirection();

Período

Los usuarios pueden obtener el período de los pulsos del codificador (en segundos) con el método getPeriod():

    // Gets the current period of the encoder
    m_encoder.getPeriod();
    // Gets the current period of the encoder
    m_encoder.GetPeriod();

Resetting a Quadrature Encoder

To reset a quadrature encoder to a distance reading of zero, call the reset() method. This is useful for ensuring that the measured distance corresponds to the actual desired physical measurement, and is often called during a homing routine:

    // Resets the encoder to read a distance of zero
    m_encoder.reset();
    // Resets the encoder to read a distance of zero
    m_encoder.Reset();

Duty Cycle Encoders - The DutyCycleEncoder class

WPILib provides support for duty cycle (also marketed as PWM) encoders through the DutyCycleEncoder class (Java, C++). This class provides a simple API for configuring and reading data from duty cycle encoders.

The roboRIO’s FPGA handles duty cycle encoders automatically.

Advertencia

In 2025 the API changed to remove rollover detection as rollover detection did not work. The get() method returns the value within a rotation where the maximum value in a rotation is defined in the constructor (default 1).

Examples of duty cycle encoders:

Initializing a Duty Cycle Encoder

A duty cycle encoder can be instantiated as follows:

  // Initializes a duty cycle encoder on DIO pins 0
  DutyCycleEncoder m_encoder = new DutyCycleEncoder(0);
  // Initializes a duty cycle encoder on DIO pins 0
  frc::DutyCycleEncoder m_encoder{0};

Configuring Duty Cycle Encoder Range and Zero

Nota

The DutyCycleEncoder class does not assume specific units of rotation. It returns values in the same units used to calculate the full range of rotation, giving users complete control over the rotation units.

The DutyCycleEncoder class provides an alternate constructor that allows control over the full range and the zero position of the encoder.

The zero position is useful for ensuring that the measured rotation corresponds to the desired physical measurement. Unlike quadrature encoders, duty cycle encoders don’t need to be homed. The desired rotation can be read and stored to be set when the program starts. The Preferences class provides methods to save and retrieve these values on the roboRIO.

  // Initializes a duty cycle encoder on DIO pins 0 to return a value of 4 for
  // a full rotation, with the encoder reporting 0 half way through rotation (2
  // out of 4)
  DutyCycleEncoder m_encoderFR = new DutyCycleEncoder(0, 4.0, 2.0);
  // Initializes a duty cycle encoder on DIO pins 0 to return a value of 4 for
  // a full rotation, with the encoder reporting 0 half way through rotation (2
  // out of 4)
  frc::DutyCycleEncoder m_encoderFR{0, 4.0, 2.0};

Reading Rotation from Duty Cycle Encoders

Nota

Duty Cycle encoders measure absolute rotation. It does not depend on the starting position of the encoder.

Users can obtain the rotation measured by the encoder with the get() method:

    // Gets the rotation
    m_encoder.get();
    // Gets the rotation
    m_encoder.Get();

Detecting a Duty Cycle Encoder is Connected

As duty cycle encoders output a continuous set of pulses, it is possible to detect that the encoder has been unplugged.

    // Gets if the encoder is connected
    m_encoder.isConnected();
    // Gets if the encoder is connected
    m_encoder.IsConnected();

Analog Encoders - The AnalogEncoder Class

WPILib provides support for analog absolute encoders through the AnalogEncoder class (Java, C++). This class provides a simple API for configuring and reading data from analog encoders.

Examples of analog encoders:

Initializing an Analog Encoder

An analog encoder can be instantiated as follows:

  // Initializes an analog encoder on Analog Input pin 0
  AnalogEncoder m_encoder = new AnalogEncoder(0);
  // Initializes an analog encoder on Analog Input pin 0
  frc::AnalogEncoder m_encoder{0};

Configuring Analog Encoder Range and Zero

Nota

The AnalogEncoder class makes no assumptions about rotation units, returning values in the same units used to calculate the full range. This gives users complete control over the choice of rotation units.

The AnalogEncoder class offers an alternate constructor that offers control over the full range of rotation and zero position of the encoder.

The zero position is useful for ensuring that the measured rotation corresponds to the desired physical measurement. Unlike quadrature encoders, analog encoders don’t need to be homed. The desired rotation can be read and stored to be set when the program starts. The Preferences class provides methods to save and retrieve these values on the roboRIO.

  // Initializes an analog encoder on DIO pins 0 to return a value of 4 for
  // a full rotation, with the encoder reporting 0 half way through rotation (2
  // out of 4)
  AnalogEncoder m_encoderFR = new AnalogEncoder(0, 4.0, 2.0);
  // Initializes an analog encoder on DIO pins 0 to return a value of 4 for
  // a full rotation, with the encoder reporting 0 half way through rotation (2
  // out of 4)
  frc::AnalogEncoder m_encoderFR{0, 4.0, 2.0};

Reading Rotation from Analog Encoders

Nota

Analog encoders measure absolute rotation. It does not depend on the starting position of the encoder.

Users can obtain the rotation measured by the encoder with the get() method:

    // Gets the rotation
    m_encoder.get();
    // Gets the rotation
    m_encoder.Get();

Using Encoders in Code

Encoders are some of the most useful sensors in FRC®; they are very nearly a requirement to make a robot capable of nontrivially-automated actuations and movement. The potential applications of encoders in robot code are too numerous to summarize fully here, but an example is provided below:

Driving to a Distance

Encoders can be used on a robot drive to create a simple «drive to distance» routine. This is useful in autonomous mode, but has the disadvantage that the robot’s momentum will cause it to overshoot the intended distance. Better methods include using a PID Controller or using Path Planning

Nota

The following example uses the Encoder class, but is similar if other DutyCycleEncoder or AnalogEncoder is used. However, quadrature encoders are typically better suited for drivetrains since they roll over many times and don’t have an absolute position.

  // Creates an encoder on DIO ports 0 and 1
  Encoder m_encoder = new Encoder(0, 1);
  // Initialize motor controllers and drive
  Spark m_leftLeader = new Spark(0);
  Spark m_leftFollower = new Spark(1);
  Spark m_rightLeader = new Spark(2);
  Spark m_rightFollower = new Spark(3);
  DifferentialDrive m_drive = new DifferentialDrive(m_leftLeader::set, m_rightLeader::set);

  /** Called once at the beginning of the robot program. */
  public Robot() {
    // Configures the encoder's distance-per-pulse
    // The robot moves forward 1 foot per encoder rotation
    // There are 256 pulses per encoder rotation
    m_encoder.setDistancePerPulse(1.0 / 256.0);
    // Invert the right side of the drivetrain. You might have to invert the other side
    m_rightLeader.setInverted(true);
    // Configure the followers to follow the leaders
    m_leftLeader.addFollower(m_leftFollower);
    m_rightLeader.addFollower(m_rightFollower);
  }

  /** Drives forward at half speed until the robot has moved 5 feet, then stops. */
  @Override
  public void autonomousPeriodic() {
    if (m_encoder.getDistance() < 5.0) {
      m_drive.tankDrive(0.5, 0.5);
    } else {
      m_drive.tankDrive(0.0, 0.0);
    }
  }
  // Creates an encoder on DIO ports 0 and 1.
  frc::Encoder m_encoder{0, 1};
  // Initialize motor controllers and drive
  frc::Spark leftLeader{0};
  frc::Spark leftFollower{1};
  frc::Spark rightLeader{2};
  frc::Spark rightFollower{3};
  frc::DifferentialDrive drive{[&](double output) { leftLeader.Set(output); },
                               [&](double output) { rightLeader.Set(output); }};
  Robot() {
    // Configures the encoder's distance-per-pulse
    // The robot moves forward 1 foot per encoder rotation
    // There are 256 pulses per encoder rotation
    m_encoder.SetDistancePerPulse(1.0 / 256.0);
    // Invert the right side of the drivetrain. You might have to invert the
    // other side
    rightLeader.SetInverted(true);
    // Configure the followers to follow the leaders
    leftLeader.AddFollower(leftFollower);
    rightLeader.AddFollower(rightFollower);
  }
  void AutonomousPeriodic() override {
    // Drives forward at half speed until the robot has moved 5 feet, then
    // stops:
    if (m_encoder.GetDistance() < 5) {
      drive.TankDrive(0.5, 0.5);
    } else {
      drive.TankDrive(0, 0);
    }
  }

Homing a Mechanism

Since quadrature encoders measure relative distance, it is often important to ensure that their «zero-point» is in the right place. A typical way to do this is a «homing routine,» in which a mechanism is moved until it hits a known position (usually accomplished with a limit switch), or «home,» and then the encoder is reset. The following code provides a basic example:

Nota

Homing is not necessary for absolute encoders like duty cycle encoders and analog encoders.

  Encoder m_encoder = new Encoder(0, 1);
  Spark m_spark = new Spark(0);
  // Limit switch on DIO 2
  DigitalInput m_limit = new DigitalInput(2);

  /**
   * Runs the motor backwards at half speed until the limit switch is pressed then turn off the
   * motor and reset the encoder.
   */
  @Override
  public void autonomousPeriodic() {
    if (!m_limit.get()) {
      m_spark.set(-0.5);
    } else {
      m_spark.set(0.0);
      m_encoder.reset();
    }
  }
  frc::Encoder m_encoder{0, 1};
  frc::Spark m_spark{0};
  // Limit switch on DIO 2
  frc::DigitalInput m_limit{2};
  void AutonomousPeriodic() override {
    // Runs the motor backwards at half speed until the limit switch is pressed
    // then turn off the motor and reset the encoder
    if (!m_limit.Get()) {
      m_spark.Set(-0.5);
    } else {
      m_spark.Set(0);
      m_encoder.Reset();
    }
  }