Peut-être avez-vous noté que nous avons retiré le Yocto-Motor-DC de notre assortiment. Certains composants n’étaient plus disponibles, et comme nous n’en avons que très peu vendu, le remplacement par un module exactement équivalent ne se justifiait pas. Mais comme nous allons vous le montrer ci-dessous, cela ne veut pas dire qu’on ne puisse plus piloter un moteur DC à l’aide de modules Yoctopuce.
Ce projet a été réalisé par Ariel, un stagiaire chez Yoctopuce à qui nous avions confié la tâche de vérifier si il était facile de piloter un moteur DC avec les modules actuellement disponible. Le but était de réaliser un système d’asservissement simple pour un chariot motorisé se déplaçant sur un rail. Le chariot est entraîné par un moteur DC réducté, en prise directe sur une tige filletée. Pour ce système d’asservissement, nous utiliserons:
- Un variateur de modélisme pour piloter le moteur
- Un Yocto-Servo pour piloter le variateur
- Un Yocto-PWM-Rx pour mesurer la position du chariot
- Un Yocto-PowerRelay-V3 pour la gestion des arrêts d’urgence
Et pour le panneau de contrôle avec des touches physiques:
Rail motorisé
Nous avons pris comme base pour ce projet un rail motorisé de Open Builds:
Rail motorisé acheté il y a quelques années chez Open Builds
Le rail a un moteur qui entraîne une tige filetée dans l’axe central du chariot, ce qui permet le déplacement sur toute la longueur. Nous avons remplacé le moteur pas-à-pas prévu d’origine par un moteur DC avec réduction d’un facteur 34:1, qui inclut un capteur à effet Hall qui offre une mesure précise des mouvements par encodage en quadrature.
Montage du moteur DC réducté avec encodeur en quadrature
Contrôle du moteur
Le moteur est contrôlé par un variateur de modélisme de chez Hobbywing. Nous pilotons le variateur avec l’un des cinq canaux du Yocto-Servo. Il faut prendre garde à une particularité des variateurs de modélisme : ils incluent en général une sécurité pour éviter de casser la mécanique par un passage brutal d’un sens à l’autre. Une fois une direction engagée, le variateur exige un passage par l’arrêt avant d’engager la direction inverse. Mais on trouve en général dans la documentation du variateur comment désactiver cette sécurité pour garantir un contrôle direct sur le moteur par le Yocto-Servo.
Le variateur de modélisme utilisé pour piloter le moteur
Le capteur à effet Hall incorporé au moteur produit un signal en quadrature que le Yocto-PWM-Rx peut décoder automatiquement pour fournir une mesure précise de la distance parcourue par le chariot.
Alimentation électrique
Le moteur que nous avons choisi a une tension de fonctionnement conseillée de 6V, mais supporte aussi des tensions plus haute, au risque d’une usure accélérée. Le variateur exigeant 7.2V, nous avons donc choisi une alimentation unique de 7.2V pour tout le système, y compris l’alimentation du capteur à effet Hall sur le moteur.
Le moteur est une charge inductive et peut générer des pointes de tension importantes sur notre alimentation. Voici une mesure de la perturbation observée à la commutation du moteur:
Nous avons donc pris la précaution de mettre en place un filtre RC sur l’alimentation du capteur à effet Hall afin d’éviter toute perturbation sur les mesures de la position du chariot.
Panneau de contrôle
Pour l’interface utilisateur, nous avons choisi de réutiliser un panneau de contrôle existant de 6 boutons de fonctions et 2 joysticks, connecté à un Yocto-MaxiKnob.
Panneau de contrôle avec touches physiques, connecté par un Yocto-MaxiKnob
Gestion des fins de course
Afin de protéger le système mécanique et le moteur, nous avons intégré au rail des interrupteurs de fin de course. Les deux boutons sont fixés à chaque extrémité du rail à l’aide de petites plaques en PMMA. Les boutons sont alignés sur le côté du corps du chariot afin que celui-ci puisse correctement les enfoncer en cas de fin de course.
Nous avons utilisé des interrupteurs avec sortie double, permettant une déconnection matérielle immédiate du moteur et une signalisation de l’événement au logiciel de contrôle via le Yocto-MaxiKnob. Une fois la situation de coupure détectée par le logiciel, celui-ci est capable de désactiver la sécurité matérielle (fonction override) à l’aide d’un Yocto-PowerRelay-V3.
Montage des interrupteurs de fin de course
Après une petite séance de câblage sur l’ensemble des périphériques, voici le schéma complet du projet:
Logiciel
Le logiciel de contrôle est écrit en C#. Pour une réactivité maximale, tous les capteurs sont lus par des fonctions de callback de changement de valeur. Le contrôle du système est géré par une machine à états.
Comme le rail n’est pas doté d’un encodeur absolu mais uniquement d’une mesure de la distance parcourue, il faut effectuer une recherche de l’origine au démarrage du système.
La première commande envoie le chariot raisonnablement vite en direction du capteur de fin de course de départ. Une fois arrivé, la commande suivante arrête le moteur et le sort lentement de la butée. À ce moment-là, le logiciel réinitialise le compteur de position du module Yocto-PWM-Rx à l’aide de la commande.set_currentValue(). Une distance de 500 est utilisée à l’origine pour éviter que les mouvements jusqu’à la position zéro ne plaquent le chariot contre l’interrupteur de fin de course.
{
Console.Clear();
Console.SetCursorPosition(0, 0);
Console.WriteLine("CALIBRATING, PLEASE WAIT...");
relay.set_state(YRelay.STATE_B);
motorMove.move(-666, 10);
do
{
YAPI.Sleep(2, ref errmsg);
} while (dangerStart == false);
motorMove.move(0, 0);
YAPI.Sleep(100, ref errmsg);
Console.WriteLine("End of course found");
motorMove.move(250, 10);
do
{
YAPI.Sleep(2, ref errmsg);
} while (dangerStart == true);
motorMove.move(0, 0);
Console.WriteLine("Moved out of end condition");
YAPI.Sleep(150, ref errmsg);
railRealPosition.set_currentValue(500);
quadroPosition = 500;
YAPI.Sleep(50, ref errmsg);
Console.WriteLine("Origin set");
motorMove.move(300, 0);
YAPI.Sleep(300, ref errmsg);
motorMove.move(0, 0);
relay.set_state(YRelay.STATE_A);
Console.Clear();
}
Nous avons rencontré une contrainte au niveau des boutons doubles que nous avons choisis. Ces derniers peuvent se retrouver dans un état ambigu quand le chariot effleure le bouton : le circuit de sécurité qui coupe le moteur s’ouvre alors que la position logique envoyée sur le logiciel n’est pas encore fermée. Pour y remédier à ce souci, nous faisons appel à notre Yocto-PowerRelay-V3 dans la fonction pour s’assurer que le moteur est libre de mouvement pour se dégager du bouton, et nous envoyons une courte impulsion pour nous assurer que le moteur sorte de cet intervalle ambigu. Le relais est ensuite ouvert pour que le moteur soit à nouveau protégé par l’interrupteur de fin de course.
Envoyer le chariot à une position précise
Une fonction setPosition(double value) est responsable d’envoyer le chariot à une position précise sur le rail. La solution de contrôle idéale est naturellement un PID, mais pour ce petit exemple nous nous sommes initialement contentés d’un asservissement avec déplacement d’une consigne linéaire et vitesse proportionnelle à l’erreur entre la consigne et la position réelle.
Nous avons ensuite calculé l’erreur entre cette consigne et la position réelle. Avec ces données, la commande de correction de la position du moteur est en place. Quelques essais nous ont permis de trouver la valeur de commande minimale pour mettre en mouvement le chariot.
{
ulong deltaTime;
ulong startTime, endTime, realTime;
int startPosition, endPosition, realPosition, cmd;
double error, order;
startPosition = quadroPosition;
endPosition = (int)(MAX_POSITION * place);
startTime = YAPI.GetTickCount();
endTime = (startTime + (ulong)(endPosition / SPEED));
do {
showSystemInfo();
realTime = YAPI.GetTickCount();
realPosition = (int)quadroPosition;
deltaTime = (YAPI.GetTickCount() - startTime);
if (deltaTime >= (ulong)(endTime - startTime)) {
order = endPosition;
} else {
order = startPosition + ((endPosition - startPosition) *
((double)deltaTime / (endTime - startTime)));
}
error = order - realPosition;
cmd = (int)error / 8;
if (cmd >= MAXIMUM_SPEED) {
cmd = MAXIMUM_SPEED;
} else if (cmd <= -MAXIMUM_SPEED) {
cmd = -MAXIMUM_SPEED;
}
if (cmd >= 0 && cmd <= MINIMUM_SPEED_L) {
cmd = MINIMUM_SPEED_L;
} else if (cmd <= 0 && cmd >= -MINIMUM_SPEED_R) {
cmd = -MINIMUM_SPEED_R;
}
motorMove.move(cmd, 10);
YAPI.Sleep(3, ref errmsg);
} while ((Math.Abs(realPosition - endPosition) > POSITION_TOLERANCE_VALUE)
&& (systemMode != WARNING));
motorMove.move(0, 0);
}
Nous avons mis une valeur différente comme preset pour chaque bouton du panneau de contrôle afin d’avoir plusieurs repères sur le rail: F1 = 0%, F2 = 25%, F3 = 50%, F4 = 75%, F5 = 100%.
Avec cet algorithme d’asservissement assez trivial, nous arrivons à une précision de ~0.5mm dans les mouvements normaux, et de ~1mm vers la butée de départ, car en raison de l’assemblage du rail, le moteur a plus de difficulté mécanique à atteindre cette position, et nous avons dû utiliser des vitesses minimales différentes en fonction de la direction désirée afin que le chariot puisse néanmoins atteindre sa consigne. Un PID complet permettrait certainement d’améliorer encore significativement la précision sur toute la longueur.
Conclusion
Ce projet vous a montré comment piloter un moteur DC avec du matériel très standard, et l'intérêt d'utiliser un capteur angulaire avec encodeur en quadrature pour mesurer précisément les déplacements d'un moteur de ce type.