Encodeurs - Partie logicielle

Note

Cette section couvre le logiciel associé aux encodeurs. Pour un guide sur le branchement électrique des encodeurs, voir Encodeurs.

Les encodeurs sont des composants utilisés pour mesurer le mouvement (généralement la rotation d’un arbre).

Important

Les classe dans ce document ne sont utilisées que pour les encodeurs qui sont branchés directement sur le roboRIO ! Veuillez consulter la documentation appropriée des fournisseurs pour l’utilisation d’encodeurs branchés sur des contrôleurs de moteur.

Encodeurs en quadrature - la classe Encoder

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

Les encodeurs en quadrature déterminent la direction en observant quel canal d’impulsion (A ou B) reçoit une impulsion en premier.

Ces encodeurs produisent des signaux rectangulaires sur deux canaux qui sont déphasés d’un quart de période (d’où le terme « quadrature »). Les impulsions sont utilisées pour mesurer la rotation, et la direction du mouvement peut être déterminée à partir de quel canal « est en avance » par rapport à l’autre.

Un décodeur en quadrature analysant les signaux A, B et Index.

Le FPGA gère les encodeurs en quadrature via un module compteur ou un module encodeur, selon le decoding type - le choix est géré automatiquement par WPILib . Le FPGA contient 8 modules encodeurs.

Exemples d’encodeurs en quadrature:

Initialisation d’un encodeur en quadrature

Un encodeur en quadrature peut être instancié comme suit:

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

Type de décodage

La classe WPILib Encoder peut décoder les signaux d’encodeur dans trois modes différents:

  • Décodage 1X: Augmente la distance pour chaque période complète du signal de l’encodeur (une fois par quatre fronts).

  • Décodage 2X: Augmente la distance pour chaque demi-période du signal de l’encodeur (une fois par deux fronts).

  • Décodage 4X: Incrémente la distance pour chaque front du signal de l’encodeur (quatre fois par période).

Le décodage 4X offre la plus grande précision, mais au prix potentiel de « fluctuations » (jitter) accrue dans les mesures de débit. Pour utiliser un type de décodage différent, utilisez le constructeur suivant:

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

Configuration des paramètres de l’encodeur en quadrature

Note

La classe Encoder ne fait aucune hypothèse sur les unités de distance; comme elle compte seulement les impulsions, elle retournera les valeurs dans le système d’unités utilisées pour calculer la distance. Les utilisateurs ont ainsi un contrôle total sur les unités de distance utilisées. Cependant, les unités de temps sont toujours en secondes.

Note

Le nombre d’impulsions utilisées dans le calcul de la distance par impulsion ne dépend pas du type de décodage - chaque « impulsion » doit toujours être considéré comme un cycle complet (quatre fronts).

La classe Encoder propose plusieurs méthodes de configuration:

// Configures the encoder to return a distance of 4 for every 256 pulses
// Also changes the units of getRate
encoder.setDistancePerPulse(4.0/256.0);

// Configures the encoder to consider itself stopped after .1 seconds
encoder.setMaxPeriod(0.1);

// Configures the encoder to consider itself stopped when its rate is below 10
encoder.setMinRate(10);

// Reverses the direction of the encoder
encoder.setReverseDirection(true);

// Configures an encoder to average its period measurement over 5 samples
// Can be between 1 and 127 samples
encoder.setSamplesToAverage(5);
// Configures the encoder to return a distance of 4 for every 256 pulses
// Also changes the units of getRate
encoder.SetDistancePerPulse(4.0/256.0);

// Configures the encoder to consider itself stopped after .1 seconds
encoder.SetMaxPeriod(0.1);

// Configures the encoder to consider itself stopped when its rate is below 10
encoder.SetMinRate(10);

// Reverses the direction of the encoder
encoder.SetReverseDirection(true);

// Configures an encoder to average its period measurement over 5 samples
// Can be between 1 and 127 samples
encoder.SetSamplesToAverage(5);

Lecture des informations des encodeurs en quadrature

La classe Encoder fournit une multitude d’informations à l’utilisateur sur le mouvement de l’encodeur.

La distance

Note

Les encodeurs en quadrature mesurent la distance relative, pas absolue; la valeur de distance renvoyée dépendra de la position de l’encodeur lorsque le robot a été allumé ou la dernière valeur de l’encodeur reset.

Les utilisateurs peuvent obtenir la distance totale parcourue par l’encodeur avec la méthode getDistance():

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

Le taux

Note

Les unités de temps pour la classe Encoder sont toujours en secondes.

Les utilisateurs peuvent obtenir le taux de changement actuel de l’encodeur avec la méthode getRate():

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

Mode stationnaire

Les utilisateurs peuvent savoir si l’encodeur est stationnaire avec la méthode getStopped():

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

La direction

Les utilisateurs peuvent obtenir la direction dans laquelle l’encodeur s’est déplacé pour la dernière fois avec la méthode getDirection():

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

La période

Les utilisateurs peuvent obtenir la période des impulsions du codeur (en secondes) avec la méthode getPeriod():

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

Réinitialisation d’un encodeur en quadrature

Pour réinitialiser un encodeur en quadrature à une lecture de distance de zéro, appelez la méthode reset(). Ceci est utile pour s’assurer que la distance mesurée correspond à la mesure physique réelle souhaitée, et est souvent appelée lors d’une routine de mise à zéro :

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

Encodeurs de rapport cyclique - La classe DutyCycleEncoder

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.

Le FPGA du roboRIO gère automatiquement les encodeurs de rapport cyclique.

Exemples d’encodeurs de rapport cyclique:

Initialisation d’un encodeur de rapport cyclique

Un encodeur de rapport cyclique («duty cycle») peut être instancié comme suit:

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

Configuration des paramètres de l’encodeur de rapport cyclique

Note

La classe DutyCycleEncoder ne fait aucune hypothèse sur les unités de distance; comme elle compte seulement les rotations, elle retournera les valeurs dans le système d’unités utilisées pour calculer la distance. Les utilisateurs ont ainsi un contrôle total sur les unités de distance utilisées.

La classe DutyCycleEncoder propose plusieurs méthodes de configuration:

// Configures the encoder to return a distance of 4 for every rotation
encoder.setDistancePerRotation(4.0);
// Configures the encoder to return a distance of 4 for every rotation
encoder.SetDistancePerRotation(4.0);

Lire une distance avec un encodeur de rapport cyclique

Note

L’encodeur de rapport cyclique mesure une distance absolue. Celle-ci ne dépend pas de la position de départ de l’encodeur.

Les utilisateurs peuvent obtenir la distance mesurée par l’encodeur avec la méthode getDistance():

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

Détecter si un encodeur de rapport cyclique est connecté

Comme un encodeur de rapport cyclique génère un ensemble continu d’impulsions, il est possible de détecter qu’un encodeur a été débranché.

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

Réinitialisation d’un encodeur de rapport cyclique

Pour réinitialiser un encodeur afin que la distance actuelle soit de 0, appelez la méthode reset(). Ceci est utile pour garantir que la distance mesurée correspond à la mesure physique réelle souhaitée. Contrairement aux encodeurs en quadrature, les encodeurs de rapport cyclique n’ont pas besoin de retour au repos (homing). Cependant, après la réinitialisation, le décalage de position peut être stocké pour être défini au démarrage du programme afin d’éviter une nouvelle réinitialisation. La Preferences class 1 fournit une méthode pour enregistrer et récupérer les valeurs sur le roboRIO.

// Resets the encoder to read a distance of zero at the current position
encoder.reset();

// get the position offset from when the encoder was reset
encoder.getPositionOffset();

// set the position offset to half a rotation
encoder.setPositionOffset(0.5);
// Resets the encoder to read a distance of zero at the current position
encoder.Reset();

// get the position offset from when the encoder was reset
encoder.GetPositionOffset();

// set the position offset to half a rotation
encoder.SetPositionOffset(0.5);

Encodeurs analogiques - la classe AnalogEncoder

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 duty cycle encoders.

Exemples d’encodeurs analogiques:

Initialisation d’un encodeur analogique

Un encodeur analogique peut être instancié comme suit:

// Initializes a duty cycle encoder on Analog Input pins 0
AnalogEncoder encoder = new AnalogEncoder(0);
// Initializes a duty cycle encoder on DIO pins 0
frc::AnalogEncoder encoder{0};

Configuration des paramètres de l’encodeur analogique

Note

La classe AnalogEncoder ne fait aucune hypothèse sur les unités de distance; comme elle compte seulement les rotations, elle retournera les valeurs dans le système d’unités utilisées pour calculer la distance. Les utilisateurs ont ainsi un contrôle total sur les unités de distance utilisées.

La classe AnalogEncoder propose plusieurs méthodes de configuration:

// Configures the encoder to return a distance of 4 for every rotation
encoder.setDistancePerRotation(4.0);
// Configures the encoder to return a distance of 4 for every rotation
encoder.SetDistancePerRotation(4.0);

Lire une distance avec un encodeur analogique

Note

L’encodeur analogique mesure une distance absolue. Celle-ci ne dépend pas de la position de départ de l’encodeur.

Les utilisateurs peuvent obtenir la distance mesurée par l’encodeur avec la méthode getDistance():

// Gets the distance measured
encoder.getDistance();
// Gets the distance measured
encoder.GetDistance();

Réinitialisation d’un encodeur analogique

Pour réinitialiser un encodeur analogique afin que la distance actuelle soit de 0, appelez la méthode reset(). Ceci est utile pour garantir que la distance mesurée correspond à la mesure physique réelle souhaitée. Contrairement aux encodeurs en quadrature, les encodeurs de rapport cyclique («duty cycle») n’ont pas besoin de retour au repos (homing). Cependant, après la réinitialisation, le décalage de position peut être stocké pour être défini au démarrage du programme afin d’éviter une nouvelle réinitialisation. La Preferences class 1 fournit une méthode pour enregistrer et récupérer les valeurs sur le roboRIO.

// Resets the encoder to read a distance of zero at the current position
encoder.reset();

// get the position offset from when the encoder was reset
encoder.getPositionOffset();

// set the position offset to half a rotation
encoder.setPositionOffset(0.5);
// Resets the encoder to read a distance of zero at the current position
encoder.Reset();

// get the position offset from when the encoder was reset
encoder.GetPositionOffset();

// set the position offset to half a rotation
encoder.SetPositionOffset(0.5);

Utilisation des encodeurs dans le code

Les encodeurs sont parmi les capteurs les plus utiles de FRC; ils sont essentiels pour automatiser un mouvement de robot qui nécessite une certaine complexité. Les applications potentielles des encodeurs dans le code robot sont trop nombreuses pour être toutes énumérées ici, mais un exemple est fourni ci-dessous:

Parcourir une certaine distance

Les encodeurs peuvent être utilisés pour créer une routine simple de type « parcourir une certaine distance ». Ceci est utile en mode autonome, mais présente l’inconvénient que l’élan du robot l’amènera au-delà de la distance prévue. Les meilleures méthodes incluent l’utilisation d’un PID Controller 1 ou l’utilisation de Path Planning 2

Note

L’exemple suivant utilise la classe Encoder, mais est similaire si un autre type (DutyCycleEncoder ou AnalogEncoder) est utilisé. Cependant, les encodeurs en quadrature sont généralement mieux adaptés aux transmissions car ils retournent à zéro (roll over) plusieurs fois et n’ont pas de position absolue.

// Creates an encoder on DIO ports 0 and 1
Encoder encoder = new Encoder(0, 1);

// Initialize motor controllers and drive
Spark leftLeader = new Spark(0);
Spark leftFollower = new Spark(1);

Spark rightLeader = new Spark(2);
Spark rightFollower = new Spark(3);

DifferentialDrive drive = new DifferentialDrive(leftLeader::set, rightLeader::set);

@Override
public void robotInit() {
    // Configures the encoder's distance-per-pulse
    // The robot moves forward 1 foot per encoder rotation
    // There are 256 pulses per encoder rotation
    encoder.setDistancePerPulse(1./256.);

    // 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);
}

@Override
public void autonomousPeriodic() {
    // Drives forward at half speed until the robot has moved 5 feet, then stops:
    if(encoder.getDistance() < 5) {
        drive.tankDrive(0.5, 0.5);
    } else {
        drive.tankDrive(0, 0);
    }
}
 // Creates an encoder on DIO ports 0 and 1.
frc::Encoder 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); }};

void Robot::RobotInit() {
    // Configures the encoder's distance-per-pulse
    // The robot moves forward 1 foot per encoder rotation
    // There are 256 pulses per encoder rotation
    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 Robot::AutonomousPeriodic() {
    // Drives forward at half speed until the robot has moved 5 feet, then stops:
    if(encoder.GetDistance() < 5) {
        drive.TankDrive(0.5, 0.5);
    } else {
        drive.TankDrive(0, 0);
    }
}

La mise à zéro d’un mécanisme

Comme les encodeurs en quadrature mesurent la distance relative, il est souvent important de s’assurer que leur « point zéro » est au bon endroit. Une façon typique de le faire est une « routine de référencement », dans laquelle un mécanisme est déplacé jusqu’à ce qu’il atteigne une position connue (généralement accomplie avec un interrupteur de fin de course), ou « point zéro », puis l’encodeur est réinitialisé. Le code suivant fournit un exemple de base:

Note

La mise à zéro n’est pas nécessaire pour les encodeurs absolus comme les encodeurs de rapport cyclique et les encodeurs analogiques.

Encoder encoder = new Encoder(0, 1);

Spark spark = new Spark(0);

// Limit switch on DIO 2
DigitalInput limit = new DigitalInput(2);

public void autonomousPeriodic() {
    // Runs the motor backwards at half speed until the limit switch is pressed
    // then turn off the motor and reset the encoder
    if(!limit.get()) {
        spark.set(-0.5);
    } else {
        spark.set(0);
        encoder.reset();
    }
}
frc::Encoder encoder{0,1};

frc::Spark spark{0};

// Limit switch on DIO 2
frc::DigitalInput limit{2};

void AutonomousPeriodic() {
    // Runs the motor backwards at half speed until the limit switch is pressed
    // then turn off the motor and reset the encoder
    if(!limit.Get()) {
        spark.Set(-0.5);
    } else {
        spark.Set(0);
        encoder.Reset();
    }
}