Encodeurs - Partie logicielle

Note

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

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

Les encodeurs sont des dispositifs utilisés pour mesurer le mouvement (généralement, la rotation d’un arbre). Les encodeurs utilisés dans FRC | reg | sont connus sous le nom «d’encodeurs en quadrature». Ces encodeurs produisent des signaux carrés sur deux canaux 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 « mène » l’autre.

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

Le FPGA du roboRIO gère les encodeurs via un module compteur ou un module encodeur, selon le type de décodage - le choix est géré automatiquement par WPILib. Le FPGA contient 8 modules « encodeur ».

La classe Encoder

WPILib prend en charge les encodeurs via la classe Encoder (Java, C++). Cette classe fournit une API simple pour configurer et lire les données des encodeurs.

Important

La classe Encoder n’est utilisée 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.

Initialisation d’un encodeur

Un encodeur 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);

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

Configuration des paramètres de l’encodeur

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é dans le calcul de la distance par impulsion ne dépend pas du type de décodage - chaque « impulsion » doit toujours être considérée être 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./256.);

// Configures the encoder to consider itself stopped after .1 seconds
encoder.setMaxPeriod(.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

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

La distance

Note

Les codeurs en quadrature mesurent la distance relative, non absolue; la valeur de distance renvoyée dépendra de la position de l’encodeur lors de la mise sous tension du robot ou de 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();

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();

Mode arrêt

Les utilisateurs peuvent savoir si l’encodeur est stationnaire avec la méthode 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();

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();

La réinitialisation d’un encodeur

Pour réinitialiser un encodeur à une distance de lecture de zéro, appelez la méthode: code: 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();

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 quelques exemples de base sont fournis ci-dessous:

Parcourir une certaine distance

Les encodeurs peuvent être utilisés sur un lecteur de robot pour créer une routine simple de «conduite afin de parcourir une distance spécifique». Ceci est très utile pour générer le code du robot pour la période « autonome » du jeu:

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

// Initialize motor controllers and drive
Spark left1 new Spark(0);
Spark left2 = new Spark(1);

Spark right1 = new Spark(2);
Spark right2 = new Spark(3);

SpeedControllerGroup leftMotors = new SpeedControllerGroup(left1, left2);
SpeedControllerGroup rightMotors = new SpeedControllerGroup(right1, right2);

DifferentialDrive drive = new DifferentialDrive(leftMotors, rightMotors);

@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.);
}

@Override
public void autonomousPeriodic() {
    // Drives forward at half speed until the robot has moved 5 feet, then stops:
    if(encoder.getDistance() < 5) {
        drive.tankDrive(.5, .5);
    } else {
        drive.tankDrive(0, 0);
    }
}

Gestion du Cap de stabilisation

Avertissement

Comme pour toutes les boucles de contrôle à rétroaction, les utilisateurs doivent veiller à ce que le cap du robot (mesuré par la différence de lecture entre l’encodeur de gauche et celui de droite) et la direction de rotation (contôleurs de moteurs) soient cohérents. Si ce n’est pas le cas, la boucle de rétroaction sera instable et le robot tournera autour de son axe central d’une manière incontrôlable.

Les encodeurs peuvent être utilisés pour s’assurer qu’un robot roule en ligne droite d’une manière assez similaire à comment cela se fait avec un gyroscope. Une implémentation simple avec une boucle P est donnée ci-dessous:

// The encoders for the drive
Encoder leftEncoder = new Encoder(0,1);
Encoder rightEncoder = new Encoder(2,3);

// The gain for a simple P loop
double kP = 1;

// Initialize motor controllers and drive
Spark left1 = new Spark(0);
Spark left2 = new Spark(1);

Spark right1 = new Spark(2);
Spark right2 = new Spark(3);

SpeedControllerGroup leftMotors = new SpeedControllerGroup(left1, left2);
SpeedControllerGroup rightMotors = new SpeedControllerGroup(right1, right2);

DifferentialDrive drive = new DifferentialDrive(leftMotors, rightMotors);

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

@Override
public void autonomousPeriodic() {
    // Assuming no wheel slip, the difference in encoder distances is proportional to the heading error
    double error = leftEncoder.getDistance() - rightEncoder.getDistance();

    // Drives forward continuously at half speed, using the encoders to stabilize the heading
    drive.tankDrive(.5 + kP * error, .5 - kP * error);
}

Les implémentations plus avancées peuvent utiliser des boucles de contrôle plus compliquées. La rétroaction basée sur la différence entre deux encodeurs est à peu près équivalente à celle qui mise sur l’erreur de cap (comme un gyroscope), et dans les deux cas, les boucles PD sont particulièrement efficaces.

Contrôle PID

Les encodeurs sont particulièrement utiles comme entrées pour les contrôleurs PID (l’exemple de stabilisation de cap ci-dessus est une simple boucle P).

Mise à zéro d’un mécanisme

Comme les encodeurs 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:

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(-.5);
    } else {
        spark.set(0);
        encoder.reset();
    }
}