Après quelques essais voici ce que me rapporte mon pote Mad (with desire !) :

Asservissement d’un Servo Moteur en vitesse et en position

Introduction

Le but est de pouvoir, par exemple, faire lever le bras d’Eugène à différentes vitesses.

Le positionnement du moteur est toujours donné par le potentiomètre, mais l'idée c'est de faire en sorte que ce soit la carte Arduino qui le reçoive et non plus le servo moteur.

Mis à part le fait de pouvoir effectuer un mouvement à différentes vitesses cela permettrait aussi de connaître la position du servo dans la Arduino.
On peut alors tout à fait imaginer de faire bouger manuellement les bras et la main et d'enregistrer la séquence (capture du mouvement par cinématique inverse - Inverse Kinematic Motion Capture).
Il faudrait toutefois auparavant retirer les vis sans fin dans les réducteurs afin que le mouvement devienne réversible.

Modification d'un servo

La première chose à faire est de modifier le servo moteur :

  1. Ouvrir le servo (HS-805BB) en retirant les 6 vis qui se trouvent au dos
  2. Supprimer la butée plastique ce qui va permettre au servo de tourner en continu (voir photo ci-dessous)Mad
  3. Déssouder le potentiomètre (voir photo ci-dessous - cliquer pour l'agrandir)
    Mad
  4. Souder de nouveaux fils à la place (j’utilise des fils de la même couleur afin de pouvoir facilement retrouver les branchements plus tard)
  5. Découper une fente dans le capot du servo afin d'y faire passer vos fils
  6. Refermer le servo

Câblage

Voici le câblage à réaliser afin de pouvoir procéder au test :

Mad
Cliquer pour agrandir

Les deux résistances de 2490 Ohm remplacent le potentiomètre du servo.
Cela a pour effet de créer un pont diviseur équilibré. C’est comme si l’on mettait le potentiomètre du servo pile au milieu de sa course.

Une fois le potentiomètre modifié comme expliqué plus haut, le servo va désormais réagir de la façon suivante :
  • si on envoit la position 90°, le servo ne bouge pas. C’est pratique car dans cette position il ne ronronne pas (ceux qui se sont fabriqué un Inmoov comprendront...)
  • si on envoit une position entre 0° et 89°, le servo tourne à droite
  • si on envoit une position entre 91° et 180° le servo tourne à gauche

Résultat et mesures

J’ai effectué des mesures de vitesse pour différentes positions demandées (vitesse en tour par minute en sortie du réducteur du servo et ce pour une tension de 5V) :

Mad
Cliquer le tableau pour l'agrandir

Cela fonctionne aussi dans l’autre sens mais on va alors de 90° a 180°.

De l'angle 56° jusqu'à l'angle 0° je ne note aucun changement de vitesse.
Idem de l'angle 124° jusqu'à 180° : le servo ne change plus de vitesse.

Voici ci-dessous la courbe des vitesses en fonction de la position (angle) :

Mad
Cliquer pour agrandir

Programmation Arduino

Et voici le programme que j'ai utilisé pour la Arduino :

/*======================================
Programme pour asservir un servomoteur en vitesse et en position.

La vitesse varie de 0 à 34 (34 correspondant à la vitesse maximum).
La position varie de 0 à 1023 (1023 correspondant à un angle de180°).
Les commandes à envoyer via le moniteur série sont par exemple :

5v 875p g (vitesse=5 / position=875 / g pour "Go")
5v = 14.5 tour/minute
875p correspond a 153°


17v 120p g (vitesse=17 / position=120 / g pour "Go")
17v = 46 tour/minute
120p correspond a 21°
*/======================================

#include <Servo.h>
Servo servo_h;  // création du servo h
Servo servo_i;  // création du servo i

long Long_val;
int vitesse_h = 0;
int position_demande_h = 500;
int position_h = 500;
int limite_basse_vitesse_h = 90;
int limite_haute_vitesse_h = 90;

int sensorPin_A0 = A0;    // select the input pin for the potentiometer
int sensorValue_h = 0;  // variable to store the value coming from the sensor

void setup()
{
   // initialisation de la communication série
   Serial.begin(115200);
  // initialisation des sorties servo
    servo_h.attach(9);
    servo_i.attach(10);
}

void loop() {
 
  static int v = 0;

  if ( Serial.available()) {
    char ch = Serial.read();

    switch(ch) {
      case '0'...'9':
        v = v * 10 + ch - '0';
        break;
      case 'v':
        vitesse_h = v;
        v = 0;
        break;
      case 'p':
        position_h = v;
        v = 0;
        break;
      case 'g':
        position_demande_h = position_h ;
        limite_haute_vitesse_h = (90+vitesse_h);
        limite_basse_vitesse_h = (90-vitesse_h);
        Serial.println("ok");
        break;
    }
  }

// Boucle d'asservisement du servo h
   // read the value from the sensor:
   sensorValue_h = analogRead(sensorPin_A0);
   // Calcul de l'écart entre le sensor et la position demandée
   Long_val = (position_demande_h-sensorValue_h+22);
   Long_val = (Long_val*90)/1001;
   Long_val = (Long_val+90);
   // Bornage de la vitesse
   if (Long_val < limite_basse_vitesse_h) Long_val=limite_basse_vitesse_h;
   if (Long_val > limite_haute_vitesse_h) Long_val=limite_haute_vitesse_h;
   // écriture dans le servo
   servo_h.write(Long_val);
}

Conclusion

Après avoir réalisé des tests "à blanc", j’ai effectué un essai avec l’épaule d’Eugène et je dois dire que ça fonctionne plutôt bien.

Sur la vidéo ci-dessous, j’effectue un aller à faible vitesse et demande la vitesse maximum sur le retour (test effectué en 5V) :

Il faudrait maintenant améliorer la boucle d’asservissement car en fin de course le moteur tourne trop au ralenti et mets trop de temps à terminer son mouvement.
Mais ces tests sont plutôt encourageants !

A suivre donc…. So stay tuned !

Lien

Afin de mener à bien cette expérience Mad a trouvé des informations sur le site suivant et tient donc à ce que ce soit précisé :
Fribotte : base de données technique pour tout comprendre de l’électronique et de la robotique.

Voilà qui est chose faite...