Cours:MiniQ v2 : Différence entre versions

De troyesGEII
Aller à : navigation, rechercher
(Utilisation de l'infra-rouge pour suivre une ligne)
Ligne 123 : Ligne 123 :
  
 
=Utilisation de l'infra-rouge pour suivre une ligne=
 
=Utilisation de l'infra-rouge pour suivre une ligne=
Le robot mini-Q est équipé de cinq couples leds/photo-transistors (infra-rouge) dirigés vers le bas. Ils sont destinés à mesurer la réflexion du support sur lequel roule le robot. Si vous prenez un support blanc et que vous fixez un scotch noir vous arriverez à détecter le support noir qui n'a pas la même réflectance infra-rouge que le support blanc.
 
  
La mise au point sera difficile car sur le robot que nous avons essayé les sensibilités des capteurs ne sont pas identiques. La calibrage de chacun des capteurs peut se faire par le programme simple :
+
On souhaite maintenant programmer un robot suiveur de ligne, qui sera de couleur noire.
<source lang=C>
 
int data[5]={0X00,0X00,0X00,0X00,0x00};//save the analog value
 
  
void setup(){
+
=={{Bleu|Principe}}==
 +
 
 +
5 capteurs photoréflectifs sont disposés sur le robot tel que résumé dans le tableau ci-dessous.
 +
 
 +
{| class="wikitable"
 +
|-
 +
| Position du capteur || extrême gauche || gauche || centre || droite || extrême droite
 +
|-
 +
| broche µc || 36 || 37 || 38 || 39 || 40
 +
|-
 +
| entrée CAN || ADC7 || ADC6 || ADC5 || ADC4 || ADC1
 +
|}
 +
 
 +
On peut considérer dans un premier temps que la valeur lue sur le CAN est :
 +
*inférieure à 300 sur du noir
 +
*supérieur à 300 pour le blanc
 +
 
 +
On décomposera la vitesse du robot de la même façon que précédemment :
 +
*vt : vitesse de translation, constante par ex 30
 +
*wr : vitesse de rotation, dépendra de la position du robot par rapport à la ligne
 +
*vitMoteurD = vt + wr
 +
*vitMoteurG = vt - wr
 +
 
 +
=={{Bleu|Position de la ligne}}==
 +
 
 +
Le plus important est de trouver la position du robot par rapport à la ligne, que l'on notera pos.
 +
 
 +
Le principe est d'attribuer un poids à chaque capteur, d'autant plus grand que le capteur est excentré. Le signe donne le côté du capteur :
 +
 
 +
{| class="wikitable"
 +
|-
 +
| Position du capteur || extrême gauche || gauche || centre || droite || extrême droite
 +
|-
 +
| poids du capteur || 24 || 12 || 0 || -12 || -24
 +
|}
 +
 
 +
L'algorithme est le suivant :
 +
*initialiser pos à 0
 +
*initialiser nbCaptOnLine à 0
 +
*pour chaque capteur sur la ligne
 +
**incrémenter nbCaptOnLine
 +
**ajouter le poids du capteur à pos : pos <- pos + poids[numeroCapteur]
 +
*normaliser pos : pos <- pos / nbCaptOnLine
 +
 
 +
 
 +
'''Exemples''' :
 +
{| class="wikitable"
 +
|-
 +
|
 +
{| class="wikitable"
 +
|-
 +
| Position du capteur || ex gauche || gauche || centre || droite || ex droite
 +
|-
 +
| poids du capteur || 24 || 12 || 0 || -12 || -24
 +
|-
 +
| Valeur CAN || 100 || 100 || 10 || 20 || 100
 +
|-
 +
| Capteur sur la ligne || N || N || O || O || N
 +
|}
 +
 
 +
pos = (0 + (-12))/2 = -6
 +
||
 +
{| class="wikitable"
 +
|-
 +
| Position du capteur || ex gauche || gauche || centre || droite || ex droite
 +
|-
 +
| poids du capteur || 24 || 12 || 0 || -12 || -24
 +
|-
 +
| Valeur CAN || 100 || 15 || 10 || 20 || 100
 +
|-
 +
| Capteur sur la ligne || N || O || O || O || N
 +
|}
 +
 
 +
pos = (12 + 0 + (-12))/3 = 0
 +
||
 +
{| class="wikitable"
 +
|-
 +
| Position du capteur || ex gauche || gauche || centre || droite || ex droite
 +
|-
 +
| poids du capteur || 24 || 12 || 0 || -12 || -24
 +
|-
 +
| Valeur CAN || 5 || 150 || 100 || 200 || 100
 +
|-
 +
| Capteur sur la ligne || O || N || N || N || N
 +
|}
 +
 
 +
pos = (24)/1 = 24
 +
 
 +
|}
 +
 
 +
 
 +
=={{Bleu|Vérification des capteurs}}==
 +
 
 +
La première étape dans la conception du programme va consister à vérifier le {{CAN}}, en utilisant la led.
 +
 
 +
On testera individuellement chaque capteur :
 +
 
 +
{{Question|Écrire un programme qui allume la led si le capteur est au dessus de la ligne}}
 +
 
 +
{{Question|Modifier ensuite le programme pour boucler sur le 5 capteurs :}}
 +
*lumière bleue avant de lancer les conversions
 +
*pour chaque capteur
 +
**allumer la led en rouge si présence ligne
 +
**allumer en vert pour indiquer qu'on passe au capteur suivant
 +
 
 +
==={{Vert|Comment calibrer correctement les capteurs pour trouver les seuils}}===
 +
Ceci peut être réalisé par un simple programme Arduino qui nous permet de garder la liaison série :
 +
<source lang=c>
 +
void setup() {
 +
  // put your setup code here, to run once:
 
   Serial.begin(9600);
 
   Serial.begin(9600);
}
 
void Read_IRLine(void){ //read the analog value
 
// les capteurs A0, A1 sont peu sensibles sur le robot essayé !!!
 
    data[0]=analogRead(A0); // gauche
 
    data[1]=analogRead(A1);
 
    data[2]=analogRead(A2);
 
    data[3]=analogRead(A3);
 
    data[4]=analogRead(A4);  // droite
 
 
}
 
}
  
void loop(){
+
void loop() {
   Read_IRLine();
+
   int data[5];
   for (char i=0;i<5;i++){
+
  uint8_t i;
     Serial.print(data[i]);
+
  // put your main code here, to run repeatedly:
    Serial.print(" ");
+
   for (i=0;i<5;i++)
 +
  {
 +
    data[i]=analogRead(i);//store the value read from the sensors
 +
     Serial.print(data[i]);Serial.print(" - ");
 
   }
 
   }
   Serial.println(" ");
+
   Serial.println();
   delay(1000);
+
   delay(500);
 
}
 
}
 
</source>
 
</source>
qui affichera toutes les secondes les valeurs des 5 photo-transistors infra-rouges.
 
==Travail à réaliser : Exercice 4==
 
Le travail à réaliser se décompose en plusieurs étapes :
 
  
{{Question|On vous demande de calibrer vos cinq capteurs avec une plaque blanche de test comprenant une piste en chatterton  noir.}}
 
  
Ce travail consiste à utiliser la liaison série pour calibrer vos 5 capteurs. Calibrer veut dire ici, trouver les seuils en-dessous desquels on considère que l'on a du noir. Ces seuils ne sont pas tous identiques pour tous les robots et pour un même robot pour tous les capteurs. Pour les trouver, vous positionnez une fois le capteur sur du blanc, une fois sur du noir et le seuil sera à mi-chemin.
+
Un essai avec un Robot a donné les résultats suivants.
 +
{| class="wikitable"
 +
|-
 +
| Position du capteur || extrême gauche || gauche || centre || droite || extrême droite
 +
|-
 +
| broche µc || 36 || 37 || 38 || 39 || 40
 +
|-
 +
| entrée CAN || ADC7 || ADC6 || ADC5 || ADC4 || ADC1
 +
|-
 +
| entrée Arduino || A0 || A1 || A2 || A3 || A4
 +
|-
 +
| BLANC ||836 || 982 || 980 || 974 || 970
 +
|-
 +
| NOIR || 210 || 390 || 338 || 305 || 305
 +
|-
 +
| Seuil || 523 || 686 || 659 || 639 || 637
 +
|}
  
Un moyen de faire cela de manière assez facile à ajuster consiste à définir des constantes comme ci-dessous :
+
=={{Bleu|Position de la ligne}}==
<source lang=c>
 
#define SEUILGG 985
 
#define SEUILG 970
 
#define SEUIL 750
 
#define SEUILD 700
 
#define SEUILDD 750
 
</source>
 
GG veut dire le plus à gauche, DD le plus à droite.
 
  
{{Question|Une fois les seuils de chaque capteur trouvé, convertir l'ensemble des données en un nombre binaire sur 5 bits. Le bit de poids faible sera à 1 si une ligne noire est présente sous le capteur A0 et ainsi de suite jusqu'au bit b4. Tester de nouveau avec un affichage binaire. Commencez ensuite à lister les valeurs aberrantes et les valeurs possibles de ce nombre binaire.}}
+
Il est temps maintenant de calculer la variable {{rouge|pos}} tel qu'indiqué ci-dessus.
  
'''Indication''' : Serial.print(78, BIN) donne "1001110"
+
{{Question|Modifier la couleur de la led suivant la valeur de pos :}}
 +
*vert si pos = 0
 +
*rouge si pos>0
 +
*bleu si pos<0
 +
*éteindre la led si aucun capteur n'est sur la ligne.
  
Le prototype de "Read_IRLine sera changé comme :
 
<source lang=c>
 
char Read_IRLine(void)
 
</source>
 
pour en faire une fonction qui retourne un nombre binaire.
 
  
'''Indication''' : La conversion binaire vous est partiellement donnée maintenant, mais il vous faut adapter les seuils de vos capteurs... et tester...
+
=={{Bleu|Marche}}==
<source lang=C>
 
//****** seuils très dépendants des ROBOTs
 
#define SEUILGG 941
 
#define SEUILG 500
 
#define SEUIL 400
 
#define SEUILD 880
 
#define SEUILDD 600
 
char Read_IRLine(void){ //read the analog value
 
    char result=0;
 
    data[0]=analogRead(A0); // gauche manque sensibilité sur mon robot
 
    data[1]=analogRead(A1); // manque sensibilité sur mon robot
 
    data[2]=analogRead(A2);
 
    data[3]=analogRead(A3);
 
    data[4]=analogRead(A4); // droite
 
    if (data[0] < SEUILDD) result |= 0x01; else result &= 0xFE;
 
    if (data[1] < SEUILD) result |=        else result &=    ;
 
    if (data[2] < SEUIL) result |=        else result &=    ;
 
    if (data[3] < SEUILG) result |=        else result &=    ;
 
    if (data[4] < SEUILGG) result |=      else result &=    ;
 
    return result;
 
}
 
</source>
 
  
{{Question|Vous commencerez ensuite à essayer de réaliser un programme qui suit une ligne fermée en avançant. Le principe est d'accélérer le bon moteur quand on dévie de la ligne.}}
+
{{Question|Il ne reste qu'à modifier la vitesse angulaire du robot (wr) en fonction de la variable pos}}
  
'''Indication''' : vous pourrez utiliser un "switch" en C qui n'utilise que les valeurs autorisées de Read_IRLine. La valeur 0x00 sera traitée comme valeur aberrante dans un premier temps.
+
'''Remarque''' : attention au signe, sinon la correction se fait dans le mauvais sens !

Version du 25 octobre 2021 à 10:51

Corrections uniquement accessibles aux enseignants


Programmation avec arduino

Le robot miniQ est architecturé autour d'un processeur ATMega32U4. C'est le processeur qui équipe les cartes Leonardo et il est d'ailleurs complètement compatible. Il faut donc changer de board qui est par défaut "Arduino UNO" qui est essentiellement utilisé pour les TPs.

Le processeur 32U4 est capable de gérer une liaison série USB sans l'aide d'un circuit spécialisé (FTDI par exemple).

Le schéma peut être trouvé sur cette page commerciale avec des exemples de code et des exercices en anglais.

En résumé :

  • La carte Arduino équivalente est la : Arduino Leonardo
  • Le programmateur d'origine est : AVR ISP
**********************************************
**********************************************
Attention : pour programmer aller dans le menu
Croquis : Téléverser avec un programmateur
**********************************************
**********************************************

Utilisation de analogWrite() pour la MLI

Commande d'un moteur

Vous trouverez des détails sur le moteur à courant continu et sa commande sur cette page

Vous pourrez consulter plus tard cette page pour comprendre le signal PWM/MLI


Pour faire varier la vitesse d'un moteur il suffit de faire varier sa tension de commande. En général ceci est réalisé avec un signal MLI ou PWM (signal à rapport cyclique variable), nous n'entrerons pas dans le détail dans ce TP.

Tout ceci se fait dans le monde Arduino avec une commande "analogWrite()"

  • analogWrite(broche,255); => tension moyenne de 5v sur la broche
  • analogWrite(broche,127); => tension moyenne de 2.5v sur la broche
  • analogWrite(broche,0); => tension moyenne de 0v sur la broche


Commande d'un moteur : :

  • Il y a deux sorties de commandes du moteur gauche (il faudra donc les positionner en sortie) :
    • broche 5 Arduino (PC6) pour la commande rapport cyclique variable : vitesse de rotation
    • broche 12 Arduino (PD6) pour le sens de rotation
  • On vous donne le fonction ci-dessous qu'il faudra utiliser pour changer la vitesse du moteur :
    • Le premier paramètre est ce qui ira dans la broche 12 : 0 pour marche en avant et 1 pour marche arrière
    • Le deuxième le rapport cyclique qui ira sur la broche 5
void MotorG(int vitesse)//control the motor
{
  if (vitesse<0)
  {
     vitesse=-vitesse;
     digitalWrite(12,1);
  }
  else
  {
     digitalWrite(12,0);
  }
  if (vitesse>255) vitesse=255;
  analogWrite(5,vitesse);
}

Indications : On complète la commande du moteur gauche par celle du moteur droit.

  • Il y a deux sorties de commandes du moteur droit (il faudra donc les positionner en sortie) :
    • broche 6 Arduino (PD7) pour la commande rapport cyclique variable
    • broche 7 Arduino (PE6) pour le sens de rotation
  • On vous donne le code source ci-dessous :
    • Le premier paramètre est ce qui ira dans la broche 7 : 0 pour marche en avant et 1 pour marche arrière
    • Le deuxième le rapport cyclique qui ira sur la broche 6
  • La commande Mi_EN (pour i=1 et i=2) qui choisit le rapport cyclique ne doit pas dépasser 75 !
void MotorD(int vitesse)//control the motor
{
  if (vitesse<0)
  {
     vitesse=-vitesse;
     digitalWrite(7,1);
  }
  else
  {
     digitalWrite(7,0);
  }
  if (vitesse>255) vitesse=255;
  analogWrite(6,vitesse);
}

Travail à faire : Exercice 1 (arduino)

Vous devez réaliser une commande du robot pour qu'il réalise un huit (deux cercles connectés par un point). Vous choisirez le rayon de vos cercles en jouant sur les rapports cycliques. Puis vous jouerez sur les temporisations pour gérer tout cela. Bien entendu, le fait qu'il n'y ait pas d'information de retour sur l'endroit où vous êtes complique un peu la mise au point.

Vous pouvez chercher à innover sur les trajectoires. Des étudiants, par exemple, ont mis deux obstacles et cherché à réaliser un créneau entre ces deux obstacles. Faites-vous plaisir. Il vous faut à tout prix comprendre comment on va en ligne droite et comment on tourne.

Suivre une source de lumière par Conversion Analogique Numérique

Le travail demandé dans cette section utilise encore la conversion analogique numérique. La différence est que maintenant c'est la position d'une source de lumière qui va faire changer les valeurs analogiques.

Étalonnage des capteurs

Détecteurs de lumière sur MiniQ version 2

Vous disposez de deux capteurs de lumière monté comme dans le schéma ci-contre. Utilisez une liaison série pour trouver les zones pour :

  • lumière au centre
  • lumière légèrement à droite
  • lumière très à droite
  • lumière légèrement à gauche
  • lumière très à gauche

Travail à faire exercice 2 : Réalisation d'un suivi de lumière

On vous demande de réaliser un programme capable de suivre parfaitement rotation de la source de lumière qui a servi au calibrage. Pour cela le robot devra tourner sur place.

Correcteur proportionnel

Pour le moment, nous n'utilisons que 5 valeurs différentes pour faire le suivi de lumière. Afin de faire un suivi plus performant, nous allons calculer la vitesse de rotation du robot en fonction de la position de la lumière par rapport au robot :

Question.jpg Trouver une équation permettant de donner l'angle entre l'axe du robot et la source de lumière, en fonction de la valeur du CAN. On considérera qu'il s'agit d'une relation affine.

La vitesse du robot peut être décomposée en une translation et une rotation. On aura donc :

  • vt : vitesse de translation (ex 20)
  • wr : vitesse de rotation
  • vitMoteurD = vt + wr
  • vitMoteurG = vt - wr
  • wr = k * positionAngulaireLumiere

Question.jpg Ecrire un programme permettant de faire le suivi de la lumière d'après ce principe.


Utilisation de l'infra-rouge pour suivre une ligne

On souhaite maintenant programmer un robot suiveur de ligne, qui sera de couleur noire.

Principe

5 capteurs photoréflectifs sont disposés sur le robot tel que résumé dans le tableau ci-dessous.

Position du capteur extrême gauche gauche centre droite extrême droite
broche µc 36 37 38 39 40
entrée CAN ADC7 ADC6 ADC5 ADC4 ADC1

On peut considérer dans un premier temps que la valeur lue sur le CAN est :

  • inférieure à 300 sur du noir
  • supérieur à 300 pour le blanc

On décomposera la vitesse du robot de la même façon que précédemment :

  • vt : vitesse de translation, constante par ex 30
  • wr : vitesse de rotation, dépendra de la position du robot par rapport à la ligne
  • vitMoteurD = vt + wr
  • vitMoteurG = vt - wr

Position de la ligne

Le plus important est de trouver la position du robot par rapport à la ligne, que l'on notera pos.

Le principe est d'attribuer un poids à chaque capteur, d'autant plus grand que le capteur est excentré. Le signe donne le côté du capteur :

Position du capteur extrême gauche gauche centre droite extrême droite
poids du capteur 24 12 0 -12 -24

L'algorithme est le suivant :

  • initialiser pos à 0
  • initialiser nbCaptOnLine à 0
  • pour chaque capteur sur la ligne
    • incrémenter nbCaptOnLine
    • ajouter le poids du capteur à pos : pos <- pos + poids[numeroCapteur]
  • normaliser pos : pos <- pos / nbCaptOnLine


Exemples :

Position du capteur ex gauche gauche centre droite ex droite
poids du capteur 24 12 0 -12 -24
Valeur CAN 100 100 10 20 100
Capteur sur la ligne N N O O N
pos = (0 + (-12))/2 = -6
Position du capteur ex gauche gauche centre droite ex droite
poids du capteur 24 12 0 -12 -24
Valeur CAN 100 15 10 20 100
Capteur sur la ligne N O O O N
pos = (12 + 0 + (-12))/3 = 0
Position du capteur ex gauche gauche centre droite ex droite
poids du capteur 24 12 0 -12 -24
Valeur CAN 5 150 100 200 100
Capteur sur la ligne O N N N N
pos = (24)/1 = 24


Vérification des capteurs

La première étape dans la conception du programme va consister à vérifier le Convertisseur Analogique Numérique, en utilisant la led.

On testera individuellement chaque capteur :

Question.jpg Écrire un programme qui allume la led si le capteur est au dessus de la ligne

Question.jpg Modifier ensuite le programme pour boucler sur le 5 capteurs :

  • lumière bleue avant de lancer les conversions
  • pour chaque capteur
    • allumer la led en rouge si présence ligne
    • allumer en vert pour indiquer qu'on passe au capteur suivant

Comment calibrer correctement les capteurs pour trouver les seuils

Ceci peut être réalisé par un simple programme Arduino qui nous permet de garder la liaison série :

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}

void loop() {
  int data[5];
  uint8_t i;
  // put your main code here, to run repeatedly:
  for (i=0;i<5;i++)
   {
    data[i]=analogRead(i);//store the value read from the sensors
    Serial.print(data[i]);Serial.print(" - ");
  }
  Serial.println();
  delay(500);
}


Un essai avec un Robot a donné les résultats suivants.

Position du capteur extrême gauche gauche centre droite extrême droite
broche µc 36 37 38 39 40
entrée CAN ADC7 ADC6 ADC5 ADC4 ADC1
entrée Arduino A0 A1 A2 A3 A4
BLANC 836 982 980 974 970
NOIR 210 390 338 305 305
Seuil 523 686 659 639 637

Position de la ligne

Il est temps maintenant de calculer la variable pos tel qu'indiqué ci-dessus.

Question.jpg Modifier la couleur de la led suivant la valeur de pos :

  • vert si pos = 0
  • rouge si pos>0
  • bleu si pos<0
  • éteindre la led si aucun capteur n'est sur la ligne.


Marche

Question.jpg Il ne reste qu'à modifier la vitesse angulaire du robot (wr) en fonction de la variable pos

Remarque : attention au signe, sinon la correction se fait dans le mauvais sens !