Accueil > La technologie > Arduino > Manœuvre des aiguilles avec des servo-moteurs > Réglage des butées des servomoteurs

Manœuvre des aiguilles en analogique avec des servo-moteurs

Réglage des butées des servomoteurs

dimanche 1er décembre 2013, par Jean-Luc

Nous voici enfin à l’avant dernière étape de développement de notre système. Dans « Sélection d’un servomoteur pour le réglage des butées », nous avons vu la mise en œuvre d’un codeur pour désigner le servomoteur à régler, dans « Clavier de réglage des butées », nous avons vu l’ajout d’un second clavier analogique destiné à permettre le réglage des butées et, comme nous avions déjà un clavier analogique, la généralisation de la gestion de ce type de clavier par le biais d’une classe C++.

Nous allons maintenant voir comment intégrer cette fonction de réglage au programme de pilotage des 8 servos. Mais tout d’abord quelques éclaircissement sur la fonction désirée.

Le fonctionnement du réglage

Lorsqu’un des servo est désigné au moyen du codeur, le mouvement des servos restent actif. En effet, le réglage ne porte que sur la butée actuelle du servo désigné.

Si le servo est en butée dans le sens horaire, une pression sur le poussoir de droite doit déplacer la butée horaire un peu plus dans le sens horaire. Une pression sur le poussoir de gauche déplace la butée un peu moins. De même, si le servo est en butée dans le sens trigonométrique, une pression sur le poussoir de gauche déplace un peu plus la butée dans le sens trigonométrique et une pression sur le poussoir de droite un peu moins.

Pour passer du réglage d’une butée au réglage de l’autre butée, il suffit de presser le poussoir commandant le mouvement du servomoteur.

Une tentative de réglage alors que le servo est en mouvement est ignorée.

Le réglage en lui même va donc augmenter ou diminuer les angles minimum et maximum. Si on veut un réglage précis, il faut régler de pas en pas [1]. Mais régler de pas en pas risque d’être long. On veut donc pouvoir décider de combien de pas la butée est augmentée ou diminuée lors d’une pression sur un des poussoirs de réglage. Voici donc le rôle des 2 boutons supplémentaires du clavier de réglage, ils servent à augmenter et diminuer le nombre de pas de réglage.

Par défaut, lorsqu’on désigne un servo à régler, le nombre de pas sera de 8. Une pression sur le poussoir d’augmentation du pas le multipliera par 2 avec un maximum de 32. Une pression sur le poussoir de diminution du pas le divisera par 2 avec un minimum de 1. Le fait de désigner un nouveau servo réinitialisera le pas de réglage à 8.

Modification de la classe DescripteurServo

La première modification est évidente. Auparavant, les butées étaient déterminées globalement pour les 8 servomoteurs. Maintenant que l’on veut régler les butées de chaque servomoteur individuellement, il faut que le DescripteurServo comporte deux données membres angleMin et angleMax comme ceci :

class DescripteurServo {
    Servo objetServo; /* Objet issu de la bibliothèque Servo de l'Arduino */
    int vitesse;      /* La vitesse de déplacement du servomoteur */
    int angle;        /* L'angle du servo-moteur */
    int angleMin;     /* Angle minimum du servo */
    int angleMax;     /* Angle maximum du servo */
    int pin;          /* La broche sur laquelle il est connecté */ 
    byte etatServo;   /* son état : SERVO_A_ANGLE_MIN, SERVO_A_ANGLE_MAX
                         SERVO_EN_MOUVEMENT_VERS_ANGLE_MAX ou
                         SERVO_EN_MOUVEMENT_VERS_ANGLE_MIN    */
    ...

On va bien entendu conserver des constantes minimum et maximum absolues afin de limiter le réglage :

const int ANGLE_MIN = 1000;
const int ANGLE_MAX = 2000;

Ces constantes vont être employées dans le constructeur de DescripteurServo pour initialiser les données membres angleMin et angleMax.

La fonction de réglage

Ensuite, il faut écrire une fonction membre de réglage. Cette fonction est appelée de loop() lorsque le codeur désigne le servo concerné. Cette fonction doit

  • lire un événement sur le clavier de réglage ;
  • si l’événement est un changement de pas de réglage, la variable de pas est multipliée par 2 ou divisée par 2 ;
  • si l’événement est un réglage :
    • si l’état du servo est SERVO_A_ANGLE_MIN, l’angle minimum est ajusté, la vitesse du servo est mise à 1 ou -1 selon le changement pour que le servo vienne de recaler sur l’angle minimum ;
    • si l’état du servo est SERVO_A_ANGLE_MAX, l’angle maximum est ajusté, la vitesse du servo est mise à 1 ou -1 selon le changement pour que le servo vienne de recaler sur l’angle maximum.

Afin de séparer clairement les différents cas, nous allons utiliser des switch ... case.

void regleServo()
{
    int numPoussoir;
    
    if (clavierReglage.lireEvenement(&numPoussoir) == EVENEMENT_PRESSE) {
        switch(numPoussoir) {
          
          case 0: /* déplacement de la butée dans le sens trigo */
            switch(etatServo) {
              case SERVO_A_ANGLE_MIN:
                if (angleMin < angleMax)
                  angleMin += min(pasDeReglage, angleMax - angleMin);
                objetServo.attach(pin);
                vitesse = 1;
                 break;
              case SERVO_A_ANGLE_MAX:
                if (angleMax < ANGLE_MAX)
                  angleMax += min(pasDeReglage, ANGLE_MAX - angleMax);
                objetServo.attach(pin);
                vitesse = 1;
                break;
            }
            break;
            
          case 1: /* déplacement de la butée dans le sens horaire */
            switch(etatServo) {
              case SERVO_A_ANGLE_MIN:
                if (angleMin > ANGLE_MIN)
                  angleMin -= min(pasDeReglage, angleMin - ANGLE_MIN);
                objetServo.attach(pin);
                vitesse = -1;
                break;
              case SERVO_A_ANGLE_MAX:
                if (angleMax > angleMin)
                  angleMax -= min(pasDeReglage, angleMax - angleMin);
                objetServo.attach(pin);
                vitesse = -1;
                break;
            }
            break;
            
          case 2: /* diminution du pas de réglage */
            if (pasDeReglage > 1) pasDeReglage /= 2;
            break;
            
          case 3: /* augmentation du pas de réglage */
            if (pasDeReglage < 32) pasDeReglage *= 2;
            break;
        }
    }
}

La gestion du mouvement

Le réglage est un cas particulier, l’angle du servo peut être en dehors de la fourchette angleMin et angleMax. Or la fonction gereServo() suppose que l’angle est dans la fourchette. Il ne va donc pas fonctionner correctement pour le réglage. Il faut donc l’adapter.

Tout d’abord, il nous faut une variable booléenne qui va indiquer si un réglage est en cours ou non. Cette variable sera modifiée dans loop en fonction de la valeur renvoyée par lireReglage(), la fonction qui renvoie l’état du codeur.

Si il n’y a aucun réglage en cours ou si le servo est dans l’une des états SERVO_EN_MOUVEMENT_VERS_ANGLE_MAX ou SERVO_EN_MOUVEMENT_ VERS_ANGLE_MIN, il s’agit d’un mouvement normal du servo et le code existant fonctionne. Dans l’autre cas, il faut un code spécifique pour gérer le mouvement vers la nouvelle butée. Selon la butée où le servo est et selon le signe de la vitesse, on détermine quand le mouvement doit être arrêté :

if (etatServo == SERVO_A_ANGLE_MIN) {
    if (vitesse > 0 && angle >= angleMin) {
        angle = angleMin;
        vitesse = 0;         
        objetServo.detach();
    }
    else if (vitesse < 0 && angle <= angleMin) {
        angle = angleMin;
        vitesse = 0;
        objetServo.detach();
    }
}
else if (etatServo == SERVO_A_ANGLE_MAX) {
    if (vitesse > 0 && angle >= angleMax) {
        angle = angleMax;
        vitesse = 0;         
        objetServo.detach();
    }
    else if (vitesse < 0 && angle <= angleMax) {
        angle = angleMax;
        vitesse = 0;
        objetServo.detach();
    }
}

Le fait de tester l’angle par rapport aux angles minimum et maximum avec des >= et <= est une sécurité. En effet, en testant avec une égalité == et si pour une raison indéterminée l’angle dépassait l’angle min ou max, le servo continuerait sont mouvement et irait en butée mécanique, ce qui pourrait l’endommager.

Modification de loop()

loop() est modifié pour prendre en compte la fonction de réglage.

void loop()
{
    int numServo;
  
    /* gestion du mouvement des servos */
    for (numServo = 0; numServo < 8; numServo++)
        servoMoteur[numServo].gereServo();
 
    /* lecture d'un ordre de mouvement */
    byte evenement = clavierOrdreServo.lireEvenement(&numServo);
  
    /* exécution de l'ordre de mouvement */
    if (evenement == EVENEMENT_PRESSE)
        servoMoteur[numServo].evenementServo();
    
    /* lecture du codeur qui désigne le servo à régler */
    int servoARegler = lireReglage();
    /* si positif ou nul, il y a un servo à régler */
    reglageEnCours = (servoARegler >= 0);
    /* si on a changé de servo à régler, le pas est remis à 8 */
    if (servoARegler != ancienServoARegler) {
      ancienServoARegler = servoARegler;
      pasDeReglage = 8;
    }
    /* exécution de réglage */
    if (reglageEnCours)
        servoMoteur[servoARegler].regleServo();
  
    delay(5);
}

Voici le code complet du sketch à télécharger.

Sketch Arduino de l’application avec réglage des butées

Et une vidéo de la mise en œuvre.

Test de l’application avec le réglage des butées

Comme expliqué dans la vidéo, il reste une paire de détails à régler. Nous verrons cela dans le prochain article mais on commence à voir le bout du tunnel !


[1Un pas vaut 1µs puisqu’on utilise la fonction writeMicroseconds(...) pour piloter les servos

Messages

Un message, un commentaire ?

Qui êtes-vous ?
Votre message

Pour créer des paragraphes, laissez simplement des lignes vides.

Lien hypertexte

(Si votre message se réfère à un article publié sur le Web, ou à une page fournissant plus d’informations, vous pouvez indiquer ci-après le titre de la page et son adresse.)