Régulation de position et de vitesse avec un codeur
Comment exploiter le codeur de notre robot gyropode ?
Pour aller plus loin que le simple maintien en équilibre du robot nous avons besoin d'un codeur.
Comment contrôler la position des roues et la position du robot ?
Réponse : le codeur et la régulation de position.
Comment maitriser la vitesse de déplacement du robot ?
Réponse : le codeur et la régulation de vitesse.
Réaliser système instrumenté permettant de déterminer la position, la vitesse et l’accélération d’un objet.
Cahier des charges :
- Analyser le fonctionnement du codeur à deux sorties à l'aide d'un oscilloscope
- Réaliser un programme Arduino qui exploite
les 2 codeurs du robot afin de réaliser un codeur incrémental.
Prévoir une structure facile à intégrer dans le programme gyropode avec régulation d'angle. - Modifier la fonction compteur pour être sûr de ne manquer aucune impulsion.
- Réaliser une régulation de position.
- Réaliser une régulation de vitesse
1. Pourquoi 2 sorties A et B pour un codeur ?
Les moteurs de notre robot sont équipés d'un codeur incrémental à effet Hall.
Comme le montre la doc technique, le codeur offre 2 sorties CNTA1 (A) et CTNA2 (B).
Le capteur est placé sur l'axe du moteur, il est constitué :
- d'un rotor sur lequel est fixé 11 petits aimants ,
- d'un stator sur lequel on place
2 capteurs à effet hall séparés d'un nombre entier de pas + un quart de pas .
Un tour moteur correspond à 11 impulsions.
Un tour de roue avec le réducteur correspond à 30 tours moteur.
Pour un tour de roue nous avons 30*11= 330 impulsions.
1.
Placer les sondes de l'oscilloscope sur les sorties
codeur :
- Y1 sur Hall_D_A1 soit la patte D5 de l'Arduino
- Y2 sur Hall_D_A2 soit la patte D2 de l'Arduino
- relier les masses Arduino et oscillo ensemble
La fonction moteur que nous allons utiliser est disponible sur ce lien.
Faites tourner le moteur gauche à 100 (sur 255) :
Relever la fréquence f du signal.
Faites une capture 1 de l'écran d'oscilloscope à joindre au compte
rendu.
Mettez en évidence l'état du signal A2 (voie 2) pour un front
montant de A1.
Sens 1 : Pour un front montant de A1, A2 est à l'état ........
Avec un stroboscope mesurer la vitesse du moteur N en tr/s.
Etablir une relation entre N et f.
En déduire le nombre d'impulsions pour un tour de moteur.
Faites tourner le moteur gauche à -100 (sur -255) :
Relever la fréquence f du signal.
Faites une capture 2 de l'écran d'oscilloscope à joindre au compte
rendu.
Notez l'état du signal A2 (voie 2) pour un front montant de A1.
Sens 2 : Pour un front montant de A1, A2 est à l'état ........
2. Pourquoi un codeur incrémental a 2 sorties ?
Appel 1 : Présenter oralement vos oscillogrammes et le fonctionnement du codeur.
2. Comment utiliser ces codeurs avec un Arduino ?
Le codeur génère des impulsions qu'il faudra compter pour obtenir la position relative.
Variables à utiliser : Cd : compteur droit, Cg : compteur gauche
Durée de cycle : 20*dt =20*5 = 100 ms Cd0 : compteur droit cycle précédent...
3. En partant du programme ci-contre
et des fonctions iniPin()
disponible ici,
concevoir les fonctions : void compteur() - Elle doit détecter les fronts montants de Hall_D_A1
- Utiliser la fonction Had=digitalRead(Hall_D_A1);
et son état précédent stocké dans Had0 - Idem pour les fronts montants de Hall_G_A1 et son compteur associé Cg - appeler cette fonction à l'endroit le plus opportun dans le programme loop()
- Si (Compteur droit =Compteur droit précédent et Cg=Cg0) ne rien faire... - sinon affiche toutes les 100 ms Cd;Cg Ajouter toutes les variables nécessaire pour faire tourner ce programme. Vérifier que vos compteurs fonctionnent et détectent le sens de rotation. Faites un repère sur les roues, combien d'impulsions détectez-vous pour un tour de roue ? Le diamètre des roues est de 6,8 cm. Un
tour de roue représente quelle distance d en cm ? |
Pour pouvoir facilement associer la
régulation de position et de vitesse à la
régulation
d'angle de tangage, Le compteur i compte le nombre de cycles
de 5ms. void setup() { Serial.begin(115200); //Pour communiquer rapidement avec Labview iniPin(); //Initialisation pinMode du shield digitalWrite(buz,HIGH); delay(10); digitalWrite(buz,LOW); } void loop() { t0=micros(); // top départ boucle if (i%20==0) affiche(); // Affiche tous les 20*5=100ms if (!digitalRead(BP) && i-iBP>50) raz(); if (i-recu>2)digitalWrite(buz,LOW); i++; while (micros()-t0<dt*1e6); } |
4. Que fait le bouton poussoir associé à la fonction void
raz() ?
On souhaite allumer les moteurs pendant une seconde lorsque
Cd=0 et Cg=0.
Ajouter les lignes de code pour répondre à ce cahier des
charges.
if (???) dep=i;
if (???) moteur(255,255); else moteur(0,0);
Les résultats annoncés par le compteur vous semblent-ils cohérents ?
Appel 2 : Monter le bon fonctionnement de votre compteur au professeur.
3. Sommes-nous sûr de compter toutes les impulsions ?
La plaque signalétique du moteur indique :
DC 12V 320 tr/min avec réducteur 30
moteur(255,255) alimente le moteur en 12 V (selon la charge de la batterie).
5. Lors de la question 4 nous avons fait tourner
notre moteur durant une seconde à 12 V
si on néglige les régimes transitoires, calculer :
-
la vitesse du moteur N en tr/s;
-
le nombre d'impulsions Imp ;
-
la période T d'une impulsion ;
-
le décalage ΔT=T/4 entre le signal A1 et A2 ;
-
la vitesse maxi. du robot v en m/s (diamètre des roues = 6,8 cm).
Cela vous semble-t-il cohérent avec la question
4 ?
Nous testons la vitesse
du robot à vide, elle doit-être légèrement supérieure à sa vitesse
nominale.
A cette vitesse, il doit s'écouler au maximum ΔT=142 µs entre 2 appels de void compteur() pour détecter l'impulsion et son signe.
Pour un programme minimaliste c'est possible. Par contre pour un programme plus complexe nous allons louper des impulsions...
Nous allons remplacer void compteur() par des interruptions.
Arduino ne gére que deux interruptions sur d2 et d3.
Aussi nous devons utiliser
cette bibliothèque
qui permet de créer des interruptions sur toutes les pattes :
#include <PinChangeInt.h>
Nous allons placer dans void setup() :
attachPinChangeInterrupt(Hall_G_A1, Code_gauche,
RISING );
attachPinChangeInterrupt(Hall_D_A1, Code_droite,
RISING );
6. Remplacer void compteur() par les 2 fonctions suivantes :
void Code_gauche() // Si G_A2 Cg-- sinon Cg++ void Code_droite() // Si D_A2 Cd++ sinon Cd--
Tester vos nouvelles fonctions et corriger les
problèmes de signes.
En marche avant les compteurs doivent s'incrémenter.
En marche arrière les compteurs doivent se décrémenter.
Faites tourner les moteurs durant une seconde à pleine vitesse.
Les résultats obtenus sont-ils cohérents ?
7. Est-ce que les deux moteurs tournent à la même vitesse ?
Proposer une solution pour remédier à ce problème.
Appel 3 : Faites valider par le professeur.
4. Comment faire une régulation de position ?
8.
Ecrire la fonction void regulation2() répondant au
cahier des charges suivant :
- Calculer grâce à une régulation proportionnelle les
puissances droite et gauche à appliquer aux moteurs
- Appliquer une borne absolue supérieure à vmax ou -vmax
- Eviter les vibrations permanentes à l'équilibre, par
exemple :
Appliquer une borne
absolue inférieure à 20 ou - 20 (puissance mini pour vaincre le
couple statique)
Si la position est
proche à 3 impulsions près stopper les moteurs.
Respectez les cahiers des charges suivants pour être compatible avec le VI Labview disponible ici.
Ecrire la fonction void
réception() capable de recevoir une chaîne de type : 330;200;5.6;
et de l'interpréter ainsi :
- consigne=330
- vmax=200
- Kp=5.6
Pour confirmer la réception envoyer la réponse : Cons.=330
Vmax=200 Kp=5.60
Modifier la fonction affiche, pour afficher 5 variables :
1. consigne;
2. Cd;
3. droite;
4. Cg;
5. gauche;
Afficher les résultats toutes les 20ms pour avoir plus
de résultats à afficher lorsque (Cd!=Cd0 || Cg!=Cg0)
Mettre au point le programme.
9. Evaluer les qualités de votre régulation en
remplissant ce tableau récapitulatif :
avec vmax=255 et un échelon de 1 tour soit 330 impulsions
Consigne ( en imp) |
330 |
330 |
330 |
330 |
Kp |
5.6 |
|
|
|
Bande Proportionnelle |
45 imp |
|
|
|
Dépassement d1 (en %) |
|
20 % |
5% |
|
Nb de dépassement |
|
|
|
0 |
tr5% en s |
|
|
|
|
Erreur statique |
|
|
|
|
Capture d’écran |
1 |
2 |
3 |
4 |
Précision (de +++ à -) |
|
|
|
|
Stabilité (de +++ à -) |
|
|
|
|
Rapidité (de +++ à -) |
|
|
|
|
Tr5% : temps de réponse à 5% soit ±16 impulsions.
Tr1% : temps de réponse à 1% soit ±3 impulsions.
Bande Proportionnelle : A partir de quand l'action PWM n'est
plus vmax=255 ?
PWM=Kp*écart → 255=Kp*BP→ BP= 255/5.6 = 45 imp
Puis en % de l'échelon : BP(en %) = 45 /330 = 13.6%
Souvent la BP en % de la gamme de mesure remplace Kp dans la
programmation des correcteurs industriels.
Dépassement en % : un dépassement de 20 % d'un échelon de 330 imp
représente 66 imp de dépassement soit un max de 396 imp
Est-ce que les courbes Cd(t) et Gg(t) sont identiques ?
10. Couplage électronique des moteurs : on souhaite que les
positions des moteurs droite et gauche soient quasi-identiques.
Modifier void
regulation2() dans ce but. Par exemple :
Si (Cd>Cg) alors il faut ralentir droite :
droite=droite-10*(Cd-Cg)
sinon il faut ralentir gauche : gauche= gauche-10*(Cg-Cd)
Appel 4 : En vous inspirant de la vidéo de présentation et de votre
tableau,
montrer de manière qualitative au professeur que votre régulation
est :
- précise;
- rapide;
- stable même avec une entrée perturbatrice.
5. Etes-vous capable de concevoir une régulation de vitesse ?
11. Conception et Mise en Oeuvre d'une régulation de vitesse à partir du bloc codeur - moteur - réducteur - roue.
-
Calculer et afficher vitD et vitG (en imp/s) toutes les 100ms
Vérifier à l'aide de l'oscilloscope la validité de votre affichage. -
A partir du moniteur série on pilote la vitesse N (en imp/s) Kp et Ki
-
Créer un VI Labview qui affiche vitD et vitG en imp/s , en tr/s et en cm/s
Le VI peut aussi modifier la consigne, Kp et Ki -
Trouver le Kp permettant une régulation stable, précise et rapide.
-
Quelle est la résolution ΔN (en imp/s et tr/s) de la vitesse affichée si Δt = 0,1s ?
Partir du programme régulation de position et faites les modifications nécessaires.
Comment programmer
?
Piste 1 : simple mais peu dynamique (rafraichissement
100 ms)
appeler regulation2() tous les 20 cycles, soit 20*5 = 100 ms
Piste 2 : moins simple mais plus
dynamique (rafraichissement 5 ms)
créer un tableau en variable globale :
stocker dans cette file d'attente First
In First
Out les 20+1
derniers relevés :
[i%21] : pointe sur Cd(t), compteur Cd actuel
[(i-20)%21] : pointe sur Cd(t-0,1), compteur Cd 20 cycles en
arrière...
-
L'action proportionnelle seule est-elle précise ?
-
Ajouter une action Intégrale pour la vitesse droite.
Puis comparer vitD et vitG
12. Réaliser un système instrumenté permettant de déterminer la position, la vitesse et l’accélération d’un objet.
-
Calculer l'accélération en imp.s-2 grâce à fifoCd la file d'attente des 20 dernières mesures.
-
Modifier le programme Arduino et l'interface Labview afin d'afficher la position, la vitesse et l’accélération du robot.
Pourquoi toutes ces régulations ?
La régulation d'angle de tangage nous a permis de maintenir en équilibre le robot.
Piloter ce robot est un défi que nous pouvons relever grâce à tous nos capteurs.
Comment le faire se déplacer, virer, suivre un parcours ?
Voici quelques pistes de travail pour la bonne utilisation des capteurs (MPU6050 et codeur) du robot :
- tangage : permet de maintenir l'équilibre avec une consigne de tangage ct=0.
- position : pour éviter de virer lors de la phase d'équilibre
pourquoi ne pas vérouiller électroniquement les 2 roues ?
- vitesse : pour que le robot se déplace il suffit de le faire
pencher légèrement en avant
pourquoi ne pas faire une régulation en cascade : cV
(consigne Vitesse) → ct
(consigne tangage) → θ, V
- lacet : avec une régulation de l'angle de lacet nous pouvons
réguler un changement de cap d'angle θ et
calculer le Δ à appliquer : droite=droite-Δ
gauche=gauche+Δ pour virer...
- position : grâce au codeur nous pourrons programmer un parcours
automatique :
avancer de 1,2m puis virage à droite de 90° puis avancer de 2m....