Club robotique de Sophia-Antipolis

Accueil > POBOTpedia > Electronique > Montages électroniques > Asservissement d’un moteur à courant continu

Asservissement d’un moteur à courant continu

Ou comment dompter un moteur sauvage et intrépide.

mercredi 8 octobre 2014, par Benoit T.

Préambule

  • Pourquoi l’asservissement en position d’un moteur à courant continu quand on dispose d’un servomoteur ? Mais parce que le moteur DC ne connait pas de limite d’angle ! Cela peut être par exemple utile pour imposer précisément une position à un bras mobile, une roue, un robot...
  • Et pourquoi l’asservir en vitesse ? Et pourquoi pas, c’est toujours utile de savoir créer un asservissement en vitesse. Par exemple pour faire avancer droit un robot qui possède deux moteurs de récupération différents (à condition d’avoir les datasheets des deux moteurs) !

Matériel et définition du problème

Voici le matériel dont je me suis servi :
- Une carte Arduino
- Un pont en H L293D
- Un moteur à courant continu 12V (de rapport de réduction 1/19) équipe d’une roue codeuse , dont on peut trouver les infos et la datasheet :en cliquant sur ce lien.
- Une pile de 9V pour alimenter le moteur

Plusieurs prérequis sont nécessaires pour aborder l’asservissement. Je les reprends un par un dans la suite. Mais avant, et pour comprendre à quelle fin j’ai fait tout cela, rappelons quel est le problème majeur :

Le moteur DC fonctionne quand on lui envoie un courant. Le rotor va donc tourner plus ou moins vite selon celui-ci, puis s’arrêter dès lors qu’il n’est plus alimenté. Cependant, on ne connait ni la distance angulaire parcourue, ni la vitesse de rotation. Aussi, si l’on veut réaliser un asservissement en vitesse ou en position, il faut transformer la consigne pour envoyer un courant pendant le temps nécessaire pour atteindre l’objectif. Il faut pouvoir mesurer ce qu’il se passe pendant que le moteur est en marche, calculer une position ou une vitesse, en déduire une erreur, puis la corriger pour atteindre la consigne de sortie. Il faut donc se servir de codeurs incrémentaux, acquérir les données, faire les calculs et commander le moteur en même temps. Comment réaliser tout cela ?

__1__

__1__

1. Interruptions de programmes

L’interruption est une sorte de programme parallèle qui s’effectue en même temps que la tâche principale. C’est le seul moyen que je connaisse qui permette de faire du multitâche sur l’Arduino (il y a aussi DuinOs, mais je n’ai pas creusé cette voie). Cependant, on aurait bien besoin de pouvoir être capable de compter le nombre de tour pendant que le moteur tourne ! L’interruption que l’on cherche à implanter va donc se déclencher à chaque transition de l’encodeur et viendra simplement incrémenter un compteur. Dans notre cas, l’encodeur est intégré et constitué de deux capteurs hall (équivalents magnétique des capteurs optique) qui nous permettent de lire ces interruptions sous forme de front montants et descendants. Deux capteurs, deux fonctions d’interruptions.

L’objet de cet article étant l’asservissement, je me permet d’aller vite. Je me suis aidé de l’excellent article suivant, que je vous invite à aller voir. Je vous invite aussi à reproduire les exemples si les interruptions ne sont encore pour vous qu’une vague notion.

  • Exemple du montage pour réaliser une interruption :

__1__

2.Acquisition des impulsions de la roue codeuse

Les roues codeuses sont essentielles à l’asservissement du moteur. Elles permettent à terme de connaitre le sens ainsi que la vitesse de rotation du moteur. Un disque magnétique passe devant deux capteurs qui le détectent tour à tour. A chaque passage de l’aimant, une impulsion, aussi appelée tick, est envoyé à la carte Arduino. Il y a un front montant et un front descendant pour chaque capteur, soit quatre positions différentes possible (HH,BB,HB,BH). Sur une période, il est donc possible de passer par quatre positions équidistantes de 90° chacune, 360° équivalent à une période. C’est pour cela que l’on parle de décalage en quadrature du signal. De plus, selon l’enchaînement des fronts, il est facile de déterminer le sens de rotation. Par exemple si on avait enregistré HH et qu’ensuite HB provient, on sait que le moteur tourne dans le sens horaire. Si au contraire BH provient, c’est l’inverse.

Le codeur magnétique est moins précis qu’un codeur optique. En effet, il utilise des aimants à la place des traditionnels traits noirs, et ceux-ci doivent éviter d’être trop proches pour ne pas créer d’interférences. Cependant, fixé à l’arbre moteur, le nombre d’impulsions par tour de l’arbre de sortie est multiplié par 19 et est donc largement suffisant dans mon cas. L’image ci-dessous montre le fonctionnement d’un codeur optique, mais il suffit de remplacer virtuellement les points blancs par des aimants et vous obtenez un codeur magnétique.

Tirer des informations du codeur incrémental revient donc simplement à créer une fonction compteur un peu plus développée. On enregistre une valeur que l’on vient incrémenter ou décrémenter selon l’ordre des impulsions de la quadrature. Cela dit, il est possible de connaitre la vitesse de rotation à l’aide d’un seul capteur. Mais le fait d’utiliser deux capteurs permet de plus d’en déterminer le sens.

On trouve une grande diversité de codes pour les codeurs sur la page arduino :dédiée aux encodeurs
Dans l’ensemble, tous marchent. Je les ai tous testés, et ai finalement opté pour celui intitulé :«  Interrupt Example (the Encoder interrupts the processor). Uses both Interrupt pins »

__1__

3.Commande et alimentation du moteur

Afini de commander le moteur dans les deux sens, j’ai opté pour un pont en H intégré très courant, le L293D. Le pont en H est un système composé de quatre transistors qui permet de contrôler électroniquement le sens du courant ou de la tension.

Pour l’explication du pont en H :c’est par là

Pour trouver le code de base utilisé : c’est par ici

  • Quoiqu’il en soit, voici un rappel du montage électronique du pont en H (pour un seul moteur, voir internet pour le brochage de l’autre moteur, ou me demander) :
  • Et voici l’allure du montage pour illustrer :

__1__

4.Echantillonnage

L’échantillonnage est une technique utilisée pour le traitement du signal et permet de dire à l’Arduino de faire des calculs tous les intervalles donnés afin de ne pas saturer la puce de calculs inutiles. Ainsi, au lieu de faire des mesures continues et de ralentir le microprocesseur, celui-ci effectuera ses calculs par exemple toutes les 50ms.
C’est vraiment la base de l’asservissement.En effet, toutes les 50ms, l’Arduino refera les calculs et nous dira si oui ou non on s’est éloigné de la consigne d’entrée. Cela nous permettra alors de corriger la sortie.

Comme vous pouvez le constater, j’ai eu recours à une bibliothèque externe pour créer la commande d’échantillonnage. Celle-ci n’existe pas en propre sur le langage arduino de base et il m’a donc fallu l’importer. Je pense que l’on peut trouver plusieurs bibliothèques qui fonctionnent correctement. J’ai trouvé la mienne sur le site d’arduino avec des codes d’exemple permettant de comprendre ce que l’on fait. Ainsi, l’Arduino met en mémoire les ticks de la roue codeuse en continu dans les interruptions, mais ne procédera à l’asservissement que toutes les 50ms.

__1__

5.Asservissement

Nous voilà donc enfin au cœur du sujet. Voilà à quoi ressemble l’asservissement dans la modélisation courante : une entrée, une sortie, et une correction intermédiaire.

Pour aller vite dans la théorie,j’ai utilisé un correcteur PID, c’est à dire à effets proportionnel, intégral, et dérivé. Cet asservissement peut être modélisé par la formule ci-dessous, où V est la consigne à envoyer au moteur, et Ki, Kd, Kp des coefficients à modifier à la main jusqu’à trouver les coefficients les plus satisfaisants :

V = Kp x Erreur + Kd x ∆ Erreur + KI x ∫ Erreur
avec
Erreur = Consigne(Tr/s par ex.) – Nombre Tour roue par seconde mesuré
∆ Erreur = Erreur – Erreur précédente
∫ Erreur = ∑ erreurs

Pour réussir à atteindre mon but, je me suis aussi servi des résultats que d’autres ont mis à disposition sur la toile.
Je cite mes sources, dont je tire mon propre code (et c’est bien l’intérêt de l’Arduino) :

Pour l’asservissement en vitesse :
http://www.ferdinandpiette.com/blog...

L’asservissement en position :
http://abigmagnet.blogspot.fr/2008/...

Le reste n’est plus que logique, conversions d’unités, et bricolage de différents codes.
Même si vous n’avez pas étudié les correcteurs en classe, le correcteur PID est relativement courant et assez simple à comprendre. La seule chose à retenir est que l’on rentre une consigne en entrée qui va impliquer une action (corrigée) en sortie. Le but est évidemment que les deux correspondent au maximum.

__1__

5.a .Asservissement en vitesse

Avant de donner le code complet, je voudrais détailler la fonction « asservissement », appelée par la fonction d’échantillonnage :

C’est la partie mathématique du code. Elle a cela de compliqué qu’elle consiste en grande partie en conversions. Si l’on se trompe ici, l’asservissement sera raté et les informations reçues seront fausses. En donnée brute, on obtient un nombre de ticks par période d’échantillonnage. Il n’y a en fait qu’à convertir cette donnée dans l’unité de la consigne et d’en faire la différence pour trouver l’erreur.
Ici, la consigne est en tours/s. Je n’utilise qu’un des deux capteurs hall, soit 32 impulsions par tour et la réduction est d’1/19eme. Associée à une roue, on peut même obtenir des m/s ou des km/h à partir du diamètre.

Enfin, je joins le code complet en format .ino ci dessous. Il est long, mais pas compliqué dans sa structure. Bien entendu, n’hésitez pas à poser vos questions pour les points qui vous paraissent obscurs. Je possède encore tous les codes séparés pour ceux qui voudraient voir le code fractionné.

  • Asservissement en vitesse.ino

__1__

5.b .Asservissement en position

L’asservissement en position est un peu plus compliqué à mettre en place. Une chose importante est d’effectuer tous les calculs en nombres entiers pour ne pas perdre d’informations. L’Arduino est le roi de la troncature. Si vous divisez 1 par 19, il est capable de dire que la réponse est 0, à moins que vous ne maîtrisiez les float,int, long et autres code de stockage, ce qui n’est pas spécialement mon cas. C’est pourquoi ici la fonction « asservissement » pourra paraître plus simple. Toute les conversions sont effectuées à l’extérieur. De plus, plus on se rapproche de l’objectif, moins la vitesse du moteur est élevée. On peut bien sur jouer avec les constantes du PID, pour trouver l’optimum entre vitesse, dépassement et temps de réaction.

Pour les nombres relatifs présents, ils sont encore une fois le fruit de conversions logiques. S’il vous chante de donner un ordre à vote moteur en nombre de ticks, tout va bien, mais c’est quand même pratique d’avoir une unité compréhensible par tous. Votre intellect permettra d’effectuer ces conversions.

Par exemple, une commande de 10 degré en sortie équivaut à :
= 190 degrés en entrée (R=19)
= 0,52 tours d’arbre moteur (/365°)
=33,28 ticks (64 ticks par tour)

Et pour citer les autres données calculées : 5,23 est pour moi le nombre de cm qu’effectue un tour de la roue fixée au moteur. 68,8 est le nombres de degré qui permet de faire avancer la roue d’un cm (rapport calculé entre l’angle de consigne et la distance parcourue mesurée à la règle).

  • Pour être plus ludique, et faire comprendre l’asservissement à des non initiés, j’ai fixé le moteur à un camion Meccano :

Et enfin, voilà le code. Étonnamment, vous noterez qu’une simple correction proportionnelle a été très suffisante dans mon cas. Sauf erreur, j’ai utilisé ici un autre code pour l’encodeur. Mais vous le retrouverez facilement sur la page arduino que j’ai cité précédemment.

  • Asservissement en position.ino

__1__

6. précisions et montage final

  • Voilà tout d’abord un rappel des correspondances entre couleurs et rôles des différents câbles du moteur CC que j’ai utilisé.
  • Puis voilà un schéma du montage final. Comme les motoréducteurs n’existent pas sur Fritzing, je les ai modélisés par des résistances variables.

Et pour finir en beauté, voilà ce qui m’a finalement permis d’illustrer l’asservissement. En asser de position, je demandais une distance au hasard entre 10 cm et 10M, et mon camion suivait une règle jusqu’à s’arrêter au bon endroit. Bien sur, pour 10M j’avais quand même quelques cm d’erreur (constantes pas assez précises, pertes d’adhérence...). La prochaine étape est de rajouter un deuxième moteur et de pouvoir commander le camion en direction !


Post-Scriptum :
Etudiant à l’EIGSI La Rochelle, ma spécialité n’est pas exactement l’automatique. Cependant, une vocation est née grâce à l’aide des membres de Pobot qui m’ont aidé à démarrer en électronique. D’autres ont surement fait mieux ou différemment, mais moi aussi j’apprend. En plus d’ajouter ma pierre à l’édifice, j’espère que cet article pourra être utile à d’autres !

Portfolio

Vos commentaires

  • Le 2 juin 2016 à 11:29, par Thibaut B En réponse à : Asservissement d’un moteur à courant continu

    Bonjour
    Tout d’abord merci pour ce programme d’exemple.
    J’aimerais connaître la façon de calculer l’angle de sortie j’aimerais fixé une consigne moteur a 30 ou 60 ° et cela ne marche pas du tout avec ce programme Merci. :)

    Répondre à ce message

  • Le 28 août 2016 à 02:48, par frederic En réponse à : Asservissement d’un moteur à courant continu

    bonjour après avoir lut votre post je me suis aperçu que c’est ce qui me faudrait comme programme
    n’etant pas du tout dans la partie je m’i lance depuis quelque semaine je voudrais faire une antenne parabolique pilote par arduino mega
    j’ai plein de chose encore pas livré ma question est la suivant, elle vous paraitras peut être un peu bête
    cette antenne est équipé de deux moteurs a codeur hall ic :il me faudrait quelqu’un qui puisse me dire comment je doit brancher ces moteur sur l’arduino sans le faire fumer je vous joint le datasheet :
    Design Data Performance data
    Commutation Brushed Rated voltage [V] U
    Series GMPS
    Motor type 404 846
    12
    Direction of rotation Bi-directional Nominal torque [Nm] M
    1.50
    Bearing type A:Sleeve - B:Sleeve
    No-load speed [min
     1
    ]
    n
    N
    N
    180.0
    Nominal power [W] P
    0
    21.3
    Nominal current [A] I
    N
    9.0
    Nominal force [kN] F
    N
    2.00
    Duty cycle s3
    N
    Sensor data
    Pulses 29
    Output channels 1
    Other data
    Gear ratio 29/1
    Gear wheel material plastic
    Suppression components 5,5µH, 47nF, (0,47µF)
    Enclosure class IP 40
    Weight [kg] 0.880
    Remarks : L = 116mm, 1 start worm
    Motor picture Characteristic curves

    Répondre à ce message

  • Le 28 août 2016 à 02:49, par frederic En réponse à : Asservissement d’un moteur à courant continu

    le deuxieme schema

    Répondre à ce message

  • Le 24 février 2016 à 10:38, par Oumaima En réponse à : Asservissement d’un moteur à courant continu

    Bonjour
    Mon projet est commander un bras manipulateur a 5 moteurs a courant continue mais Notre problem est commant fait un controle angulaire et commant choisir le nombre de replacement ? Est Notre espace de travail est cerculaire

    Répondre à ce message

  • Le 24 novembre 2015 à 11:36, par yoyo En réponse à : Asservissement d’un moteur à courant continu

    j’ai un sujet de projet dans le cadre de ma terminale S si, je dois faire l’asservissement d’un moteur AC à l’aide d’un capteur de position angulaire,
    en gros je dois adapter en fonction de la position de l’assiette en statique (c’est a dire que je dois juste modifier la position des phares quand des gens entrent dans la voiture)
    comment pourrais-je faire SVP
    Merci d’avance :)

    • Le 25 novembre 2015 à 15:34, par Julien H. En réponse à : Asservissement d’un moteur à courant continu

      Bonjour.
      Nous invitons désormais les professeurs de lycée à nous contacter pour définir le cadre de l’aide que nous apportons aux élèves. Merci de lui transmettre nos coordonnées.
      Cordialement et bonne continuation.

    Répondre à ce message

  • Le 22 août 2015 à 17:01, par Stephan En réponse à : Asservissement d’un moteur à courant continu

    Bonjour,
    Merci beaucoup pour ce tuto qui permet de démarrer même quand on ne connait rien du tout à l’asservissement. :) Je fais aussi quelques bricolages en meccano...
    Bonne journée
    Stephan

    Répondre à ce message

  • Le 1er juin 2015 à 23:53, par Augustin En réponse à : Asservissement d’un moteur à courant continu

    Bonjour,
    tout d’abord merci beaucoup pour cet article d’une très grande précision et très enrichissant.
    Je me posais la question de la stabilité de ce sytème, j’ai réalisé l’asservissement en position d’un MCC grace à votre code, mais je n’arrive pas a obtenir un asservissement vraiment stable, j’ai toujours des oscillations, et une erreur de position énorme et aléatoire. Je me demande comment résoudre ce problème... J’ai essayé en tâtonnant de jouer sur les gains du PID mais sans résultat significatif. Merci d’avance de votre aide.

    Répondre à ce message

  • Le 27 novembre 2014 à 23:50, par Benoit T. En réponse à : Asservissement d’un moteur à courant continu

    Salut Franck,
    J’ai proposé une solution, non pas la seule, mais une compréhensive pour les gens tentés par reproduire un tel asservissement avec l’arduino. L’asser proportionnel est pour moi le plus simple, mais il correspond en fait à un PID avec kd=0 et ki=o. Mais quel que soit l’asser choisi, tu auras quand même besoin des interruptions, de codeuses, d’échantillonnage, de fournir un code... Et donc de reproduire plus ou moins quelque chose similaire à ma démarche et à mon projet. Cependant, je ne propose qu’une solution pour l’asservissement, pas la direction ou la position 2D !
    idée arduino : si le but c’est d’aller tout droit sans obtenir d’infos, tu peux aussi utiliser les broches PWM de l’arduino pour réduire le courant.
    idée DIY : tu peux aussi tenter manuellement d’insérer une petite résistance à une borne d’un moteur pour tenter de réduire le courant, et donc la vitesse. Plus aléatoire, mais plus rapide si le but est ailleurs...
    J’espère avoir répondu à ta question !
    Benoît

    Répondre à ce message

  • Le 16 octobre 2014 à 13:05, par Franck En réponse à : Asservissement d’un moteur à courant continu

    Bonjour,
    Je commence sur la base d’un Robot roulant avec deux moteur à courant continu et l’ors de ces
    déplacement le Robot d’écrit une courbe plutôt qu’une ligne droite.
    Avant de poursuivre avec des capteur, etc... je vais déjà commencer à le faire avancer droit. Quelle
    est le type d’asservissement que je doit mettre en place ?
    Avez vous quelques chose de simple à me proposer pour me faire la main pour commancer ??
    Merci

    Répondre à ce message

Un message, un commentaire ?

modération a priori

Attention, votre message n’apparaîtra qu’après avoir été relu et approuvé.

Qui êtes-vous ?

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.