Non, non, il n’y a aucune faute d’orthographe dans ce titre...
La manip d’aujourd’hui montre comment il est possible de piloter un ou plusieurs servo-moteurs depuis notre ATmega8, et ainsi être en mesure d’actionner des éléments méacaniques. Il s’agit d’un grand classique dans le monde de la robotique et des micro-contrôleurs.
Pour ceux qui ignorent ce qu’est un servo-moteur (ou servo pour les intimes), tout d’abord je tiens à leur dire qu’il n’y a pas lieu d’en avoir honte. Ensuite, je vais aller assez vite, car beaucoup d’auteurs de par le vaste Web ont pris la peine d’écrire des pages très claires sur le sujet. Par exemple, nos amis de Fribotte.
Ce qu’il faut en retenir en deux mots :
Une petite précision qui aura son importance tout à l’heure : l’intervalle de temps entre les fronts montants de 2 impulsions consécutives ne doit pas dépasser 20ms en principe.
Et pour mettre un visage sur la chose, en voici un qu’on peut acheter pour un prix très modique :
(Il est ici relié mécaniquement à un antique rhéostat pour le contrôle de la vitesse d’un moteur électrique de bateau radio-commandé)
Et bien non, pas de schéma. Pour la simple raison qu’on va tout simplement reprendre celui du chenillards à LEDs, en connectant nos servos en lieu et place des LEDs et de leur résistance. J’avoue avoir eu la flemme de refaire un nouveau schéma pour si peu, et puis vous pouvez bien bosser un peu de votre côté aussi :-)
Connecter les servos... Et comment ? Ben avec leurs fils, banane !!!
Un peu de sérieux. Un servo se connecte au moyen de trois fils, rassemblés sur un connecteur femelle à 3 points. Ces 3 fils sont :
Et c’est pareil quelle que soit la marque de l’engin. La seule chose qui change est la couleur du fil de commande, qui est tantôt blanc, tantôt jaune selon le fabriquant (non, non, cela n’a rien à voir avec le fait que le servo soit de marque allemande ou nipponne). Les deux autres seront toujours noir et rouge, selon la convention habituelle. Pas bien difficile de savoir qui est qui au bout du compte.
Pour relier ce connecteur femelle à notre plaque d’expérimentation, il suffit de fabriquer un petit adaptateur comme celui-ci :
Le connecteur 3 broches mâles est tout simplement un morceau de barrette sécable. Les 3 pins à l’autre bout proviennent des mêmes types de barrettes (il suffit de tirer dessus avec une pince pour les sortir de l’isolant). Un peu de gaine thermo-rétractable autour du tout pour faire propre et éviter les court-circuits possibles. J’ai d’ailleurs équipé de cette manière tous les fils volants appelés à être connectés sur la plaquette d’expérimentation. Ainsi on a des broches bien rigides et donc faciles à enficher, et qui de plus offrent de très bons maintien et contact électrique avec les lyres de la plaquette.
On peut également voir ci-dessus le connecteur femelle monté sur le fil du servo, ici noir-rouge-blanc.
Remarque importante : vu qu’il n’y a aucune forme de détrompeur sur ce type de connecteurs, le repérage du sens de branchement se basera sur les couleurs de fils. Soyez donc attentif...
Un gros plan sur la connexion du servo au montage maintenant :
Notez au passage que je n’ai même pas pris la peine d’enlever les LEDs. Ca m’a permis de vérifier qu’il y avait bien un signal sur les sorties, et ce sans brancher de servo. De plus, l’intensité d’allumage des LEDs est fonction de la largeur de l’impulsion, ce qui donne une vérification visuelle simple du fonctionnement.
Quelques images de l’oscillo pour illustrer les signaux obtenus, prélevés directement sur les sorties de l’ATmega :

On peut voir ici les signaux de 2 servos, réglés sur leur position mini. La base de temps ayant été calibrée de telle sorte qu’un carreau représente 1ms en abscisse, on peut constater que les impulsions durent exactement 1ms (au parallaxe près avec les graduations, car l’appareil photo n’était pas pile-poil dans l’axe).

Sur cette photo, le signal du bas correspond à la position maxi du servo, et l’impulsion y fait 2ms.
Quant à l’interface côté HyperTerminal, en voici une illustration :

Le numéro du servo concerné est donné par un chiffre entre 0 et 7. La position est donnée en 1/10e de débattement, la valeur étant saisie par un chiffre entre 0 et 9, et par la lettre A (pour obtenir les 11 positions correspondant aux 10 intervalles).
Avant de recevoir 3 zillions de mails pour me dire, "ouais l’ôt bouffon, ta solution elle pue, moi j’fé kom sa" [1], je tiens à préciser qu’il n’y a pas qu’une seule solution bien entendu, et que celle-ci ne prétend être ni la meilleure, ni la plus belle, ni la plus [complétez par la caractéristique de votre choix]....
Elle a cependant les avantages suivants :
Sur notre ATmega8, nous disposons de 3 compteurs/timers :
C’est ce dernier que nous allons regarder de plus près. La fonctionnalité qui nous intéresse ici est le fait qu’il dispose de deux comparateurs (A et B), capables de déclencher une interruption lorsque le compteur atteint la valeur à laquelle ils ont été configurés. De plus, avec la configuration appropriée du compteur, le comparateur A peut provoquer une remise à 0 automatique du comptage lorsque sa valeur est atteinte. Bien entendu une interruption peut également être déclenchée sur cet événement.
Comme toujours, RTFM. Traduisez par : “fortement, le datasheet à étudier vous êtes invités” (la version intégrale de 300 pages bien entendu, par le résumé de quelques feuilles. Soyons un peu sérieux).
Nous avons maintenant tout pour générer nos impulsions de commande. Le principe retenu est le suivant :
Avant de faire tout cela, il faut également définir le prescale du compteur (comme pour les LEDs). Notre quartz étant à 8MHz, si on prescale l’horloge à 8, on va donc obtenir un pas de comptage toutes les micro-secondes, ce qui nous donne une résolution de 1/1000ème sur l’excursion de durée (rappel : entre 1ms et 2ms). Ce prescale est de plus éminemment pratique, puisqu’alors le réglage de nos comparateurs se fait en y chargeant les délais souhaités exprimés en micro-secondes (pas de division scabreuse pour traduire une durée en nombre de clocks).
Voilà, tout est dit. Il n’y a plus qu’à coder tout cela
Comme pour les articles précédents, je ne vais pas faire de la redite ici, et je vous invite donc à lire le source et ses (abondants) commentaires. En cas de doute, n’hésitez pas à m’envoyer vos questions par mail (eric at pobot.org)
Ce que je trouve assez agréable dans l’utilisation qui est faite ici du compteur et de ses comparateurs est que tout tient dans les quelques lignes des deux interrupt handlers des comparateurs, et sans logique complexe. Le seul test qui y est fait est dû à la distribution des sorties sur deux ports, à cause de l’attribution des sorties PD0 et PD1 aux signaux Rx et Tx de l’USART. Si nous avions utilisé un autre moyen de communication comme l’I2C (pardon : le TWI), les 8 servos auraient pu rester groupés sur le seul port D.
Le timer/compteur 1 de l’ATmega offre également la possibilité de générer directement les impulsions sur les sorties associées aux deux comparateurs. Avec la configuration adéquate de son mode de fonctionnement, nous arions pu obtenir les impulsions directement sur ces sorties, sans en passer par les ports d’I/O. Mais dans ce cas, nous n’aurions pu contrôler que deux servos.
La solution proposée ici permet d’en piloter jusqu’à 10 en théorie. Dans la pratique, il vaut mieux se limiter à 9 pour être tranquille, car avec la durée cumulée de toutes les impulsions pour 10 servos, on serait trop à la limite des 20ms maximales entre deux impulsions d’un même servo.
A vous d’essayer maintenant d’autres approches, avec les autres timers/compteurs, etc, etc...
[1] vous avez vu, moi aussi je sais causer d’jeuns