Les servomoteurs sont très utilisés en robotique. Nous leur avons consacré un grand nombre d’articles. Ce sont des modèles courants en modélisme, et ils se pilotent habituellement avec une radio-commande, donc le signal de contrôle est universel et il est possible de le reproduire avec une puce programmable, comme Eric l’a présenté dans un excellent article : Bouge ton servo
Ici nous expliquons comment ne pas recourir à la programmation : on peut utiliser quelques composants électroniques simples et courants pour obtenir la commande en position d’un servomoteur.
L’objectif est le suivant : ne pas implémenter dans un micro-contrôleur le signal particulier nécessaire à un servomoteur mais utiliser une carte auxiliaire prenant en entrée un niveau logique binaire (0 ou 1) pour obtenir un changement de la position du servomoteur.
Les raisons sont les suivantes, au choix :
– les ressources de calcul du contrôleur principal sont limitées
– pas de contrôleur du tout (le cas des cartes I/O type Phidget ou K8055)
Solution 1 : le NE555
On va commencer par un circuit intégré très connu, le NE555 qui existe depuis plus de 35 ans et rend toujours de très bons services. Vous trouverez un très bon article de présentation ici :
Tutoriel Robotix.fr sur le NE555
Il suffit d’ajouter une résistance et un condensateur et on obtient un signal carré "monostable" qu’on peut déclencher une fois. Le but est de reproduire le signal nécessaire à un servomoteur :
– niveau bas pendant environ 20 millisecondes
– niveau haut entre 1 et 2 ms selon la position souhaitée
Bien sûr le NE555 devra reproduire ce signal régulièrement, on va donc utiliser le NE555 en "astable" (voir le site de robotix.fr cité au début de cet article).
Pour celà, on va alterner la charge et la décharge en utilisant des valeurs de résistances et de condensateurs bien précises permettant d’obtenir les temps souhaités.
Utilisation d’un montage proposé
Un montage sensé atteindre le but fixé est proposé sur le Wikibot de Planète-Sciences" : NE555 pour contrôler un servo mais trop insuffisant à mon goût, donc on va reprendre point par point.
Voici la liste du matériel utilisé :
– 1 circuit intégré NE555 (temporisateur monostable ou astable)
– 1 transistor PNP BC558 (TO92)
– 1 diode 1N4148
– 1 résistance 150 kOhms
– 1 résistance 200 kOhms
– 1 condensateur 100 nF ou 10 nF
– 1 condensateur 220 nF
– 1 potentiomètre / résistance variable ( 20 kOhms)
– 1 potentiomètre / résistance variable ( 10 kOhms)
Le transistor permet d’avoir deux positions : selon qu’on ouvre ou ferme le circuit grâce à une entrée numérique sur la base, on ajoute la valeur de la résistance, faisant passer la constante de temps de l’autre côté de la valeur médiane (en gros de 1 à 2 ms si on prend les extrêmes).
Pour comprendre le fonctionnement d’un transistor, regardez cette animation sur le site de l’Université du Mans : théorie du transistor
Circuit schématique et implantation des composants
On peut choisir de réaliser le circuit avec un logiciel de CAO électronique comme Eagle ou utiliser un petit outil pour simuler le placement des composants sur une plaque d’essai à bandes ("veroboard" ou "stripboard" en anglais).
Premier test : tel quel
On implante tous les composants selon ce circuit sur une plaque d’essai. C’est assez facile, ce n’est pas encore le montage définitif donc on prend de la place, surtout pour pouvoir laisser passer les différents fils qu’on va ensuite connecter : alimentation 5v, ligne de commande et retour vers le servo, plus toutes les connexions de test, par exemple les grippe-fils pour l’analyseur logique Saleae Logic.
On va d’abord faire des tests juste avec l’alimentation et regarder le signal obtenu en sortie du montage (à la place du servomoteur)
On connecte ensuite l’Arduino et un servomoteur :
Les points rouge et noir sont le 5V et la masse (en provenance de l’Arduino ou de la carte microcontrôleur et à destination du servo)
Le point vert est l’entrée HIGH ou LOW pilotée par le microcontrôleur et le point bleu est la sortie de commande du servomoteur. Tel que le schéma de principe l’indique, c’est ici qu’il faudrait se connecter, ce qu’on fait pour notre premier test.
Et là c’est le drame : le servo se bloque et fait un méchant bruit. On regarde à l’analyseur, le créneau dépasse les 3 millisecondes dès qu’on connecte le servo, alors qu’il reste sagement entre 1 et 2 millisecondes (signal typique souhaité) quand le servo est déconnecté —> le montage proposé est calamiteux, théorique et ne peut pas marcher tel quel. En tout cas c’est ma conclusion et j’aimerais bien que les auteurs m’expliquent comment ils l’ont fait fonctionner (c’est bien les wiki pour l’anonymat).
Second test : un étage supplémentaire
On va donc protéger le circuit pour empêcher le servomoteur de parasiter le signal. Pour cela j’ai pris ce que j’avais sous la main, une diode (et pas une led) et une résistance. Voici le schéma.
Et maintenant ça va mieux : on a bien nos deux créneaux à 1,1 ms et 1,8 ms réglables avec les potentiomètres :
Il y aurait certainement des améliorations à faire : regarder à l’oscilloscope (que je n’ai pas) d’où venait les parasites et mieux choisir le filtre diode/résistance.
Solution 2 : un microcontrôleur
Et oui, on peut décharger la gestion du micro-contrôleur principal en utilisant un µC secondaire qui va écouter sur 1 entrée numérique le choix et gérer le servo comme on le fait habituellement. Il y a donc un programme, mais externe.
Par exemple, avec un simple petit ATtiny13 à 8 pattes ou dans mon cas un ATtiny2313 qui fait tout de même 20 pattes, on va implémenter un programme très simple qui écoute sur une ligne d’entrée la commande et va piloter le servomoteur sur une ligne en sortie. Ok il y a du code à exécuter, mais c’est simplement déporté dans une puce auxiliaire et les ressources du contrôleur principal sont toujours préservées !
Code source
En utilisant WinAVR et la bibliothèque "delay" de AVR-libc pour attendre un nombre de millisecondes précis.
int main(void)
{
// port en sortie (servo)
sbi(DDRB,0);
// port en sortie (led de contrôle)
sbi(DDRD,1);
cbi(PORTD,1);
// port en entrée (commande position 0 ou 1)
cbi(DDRD,0);
cbi(PORTD,0); // pull-down
while (1) {
sbi(PORTB,0);
if (inb(PIND) & 0x01) {
cbi(PORTD,1);
_delay_ms(1.3);
} else {
sbi(PORTD,1);
_delay_ms(1.8);
}
cbi(PORTB,0);
_delay_ms(20);
}
return 0;
}
C’est vrai que ça fait un peu "grosse cavalerie" et je ne regrette pas d’avoir tenté avec le NE555, mais quand même on aurait eu moins de composants sur la carte et une plus grande précision dans la gestion des créneaux.
Avec la version NE555, je n’ai pas réussi à avoir les limites du servo et il ne tournait que de 90° et encore !