Cours:MiniQ : Différence entre versions

De troyesGEII
Aller à : navigation, rechercher
m (Travail à faire : Exercice 1 (arduino))
m (Utilisation du timer 0 pour la MLI)
Ligne 31 : Ligne 31 :
  
 
={{Bleu|Description et utilisation des commandes moteurs}}=
 
={{Bleu|Description et utilisation des commandes moteurs}}=
==Utilisation du timer 0 pour la MLI==
+
==Utilisation de Analogwrite pour la MLI==
Un chapitre entier a été consacré [[../Le_Timer_0| au timer 0]] dans ce livre. Vous avez intérêt à le relire avant d'aller plus loin.
 
 
 
Certains se demandent probablement s'il ne serait pas mieux d'utiliser le timer 1 pour la réalisation de la [[w:Modulation_de_largeur_d'impulsion|MLI (Modulation de Largeur d'Impulsion)]]. C'est probablement vrai, mais c'est impossible à réaliser sans interruption. Nous allons essayer d'expliquer pourquoi maintenant.
 
 
 
 
===Commande des deux moteurs===
 
===Commande des deux moteurs===
 
[[File:Moteurs.png|thumb|Right|150px|Module de commande des moteurs]]
 
[[File:Moteurs.png|thumb|Right|150px|Module de commande des moteurs]]
Ligne 45 : Ligne 41 :
 
avec i=1 ou i=2 pour chacun des moteurs.
 
avec i=1 ou i=2 pour chacun des moteurs.
  
Le code d'initialisation de la PWM (ou MLI) est examiné maintenant.
+
Le code d'utilisation de la PWM (ou MLI) est examiné maintenant.
 
 
====Code pour initialiser la MLI====
 
Rappelons avant de commencer comment est câblé le module de commande des moteurs avec le processeur à l'aide d'une figure ci-contre)
 
[[File:ATMegaEtMoteurs.png|thumb|Right|250px|Interfacer l'ATMega368 aux modules de puissance (Version corrigée)]]
 
Voici le code fourni avec la platine est le suivant :
 
<source lang=C>
 
void pwm_init(void)
 
{
 
TCCR0A = 0XA3;     
 
TCCR0B = 0X03;//clk/64
 
TCNT0 = 0X00; //initialisation timer 0
 
TIMSK0 = 0X00;//Aucune interruption timer   
 
}
 
</source>
 
Ce que fait la ligne TCCR0B=0X03 est décrit dans le commentaire. On rappelle que la division de l'horloge est choisie par les trois bits de poids faibles de '''TCCR0B'''
 
* (000) arrêt
 
* (001) division par 1
 
* (010) division par 8
 
* (011) division par 64
 
* (100) division par 256
 
* (101) division par 1024
 
* (110) front descendant de T0
 
* (111) front montant de T0
 
T0 est un bit qui n'est pas placé au même endroit suivant la famille.
 
 
 
Ce que fait la ligne TCCR0A = 0XA3 est un peu plus complexe et nécessite la lecture de deux tableaux (qui sont rappelés). Voici le premier pour le poids fort de '''TCCR0A'''.
 
;Mode PWM rapide et comparaison
 
{| class="wikitable"
 
|-
 
! COM0A1 !! COM0A0 !! Description
 
|-
 
| 0 || 0 || Opération Normale PORT, OC0A déconnecté
 
|-
 
| 0 || 1 || WGM02=0 Opération Normale PORT, OC0A déconnecté
 
|-
 
| 0 || 1 || WGM02=1 Basculement de OC0A sur la comparaison
 
|-
 
| 1 || 0 || Mise à 0 de OC0A sur la comparaison et à 1 à BOTTOM
 
|-
 
| 1 || 1 || Mise à 1 de OC0A sur la comparaison et à 0 à BOTTOM
 
|}
 
qui est identique pour COM0B1 et COM0B0. Les deux bits de poids fort du 0xA3 choisissent donc le troisième mode, et idem pour B. On utilise donc pour les deux moteurs la mise à zéro de OC0A (et aussi OC0B) qui sont les deux sorties reliées à EN1 et EN2.
 
 
 
L'autre tableau à lire est :
 
;Description des bits pour la génération de forme d'onde
 
{| class="wikitable"
 
|-
 
! Mode !! WGM02 !! WGM01 !! WGM00 !! Mode de fonctionnement !! Bas si !! Mise à jour de OCRAx si !! Drapeau TOV0 positionné si
 
|-
 
| 0 || 0 || 0 || 0 || Normal || 0XFF || immédiatement || MAX
 
|-
 
| 1 || 0 || 0 || 1 || PWM à phase correct || OXFF || TOP || BOTTOM
 
|-
 
| 2 || 0 || 1 || 0 || CTC || OCR0A || immédiatement || MAX
 
|-
 
| 3 || 0 || 1 || 1 || PWM rapide || 0XFF || BOTTOM || MAX
 
|-
 
| 4 || 1 || 0 || 0 || Reservé || - || - || -
 
|-
 
| 5 || 1 || 0 || 1 || PWM à phase correct || OCR0A || TOP || BOTTOM
 
|-
 
| 6 || 1 || 1 || 0 || Reservé || - || - || -
 
|-
 
| 7 || 1 || 1 || 1 || PWM rapide || OCR0A || BOTTOM || TOP
 
|}
 
Même si WGM02 est dans un autre registre, il n'y a aucune difficulté de remarquer que c'est la ligne 3 (PWM rapide) qui est choisie. Ceci est facilement trouvé avec la figure qui est rappelée :
 
[[File:AVR Timer0 comp.png|thumb|center|500px|La comparaison avec le timer 0]]
 
  
 
====Code pour utiliser les moteurs====
 
====Code pour utiliser les moteurs====

Version du 22 mars 2014 à 20:25

documentations

Schéma de la carte électronique du miniQ


programmation avec arduino

Utilisation de l'adaptateur DFRobot Xbee sur le robot
ROB0081 Xbee 2.jpg



1. Si le programme fait avancer le robot dès la mise en route, pensez à le soulever et à le mettre en marche (sinon pb USB)



2. Brancher la carte de programmation (ci contre) et son cordon ! Un voyant rouge s'allume



3. Choisissez le bon type de carte dans le logiciel arduino


Arduino board.jpeg

Description et utilisation des commandes moteurs

Utilisation de Analogwrite pour la MLI

Commande des deux moteurs

Module de commande des moteurs

Le timer 0 comme les autres timers permet une commande simultanée de deux moteurs. Puisqu'il s'agit du timer 0, les deux bits associés sont OC0A en PD6 (bit 6 du PORTD) et OC0B en PD5. Si le concepteur du robot a cablé ces deux bits comme commande des moteurs il est naturel d'utiliser le timer 0. C'est le cas comme on peut le voir sur le schéma de principe. Vous voyez bien PD5 connecté à EN1... mais par contre PD6 connecté à IN2. C'est forcément une erreur : PD6 doit être connecté à EN2.

Côté puissance, la commande nécessite deux signaux :

  • ENi qui reçoit donc la MLI
  • INi qui détermine le sens de rotation

avec i=1 ou i=2 pour chacun des moteurs.

Le code d'utilisation de la PWM (ou MLI) est examiné maintenant.

Code pour utiliser les moteurs

Il est possible de trouver des exemples de programmation du robot. A partir de ces exemples nous présentons un code source légèrement modifié pour être conforme au schéma de principe. Nous avons aussi renommé les paramètres pour savoir qui est moteur gauche et droit et diminué aussi leur taille.

void Motor_Control(char MD_DIR,char MD_EN,char MG_DIR,char MG_EN){
  //////////MGauche////////////////////////
  if(MG_DIR==FORW)//M1 motor direction
    digitalWrite(IN1,FORW);//forward
  else
    digitalWrite(IN1,BACK);//back
    analogWrite(EN1,MG_EN);//set speed
  ///////////MDroit//////////////////////
  if(MD_DIR==FORW)
    digitalWrite(IN2,FORW);
  else
    digitalWrite(IN2,BACK);
    analogWrite(EN2,MD_EN);
}

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.

1°) Voici un code complet d'initialisation et d'utilisation des moteurs :

#define EN1 6//pin for run the right motor 
#define IN1 7//pin for control right motor direction
#define EN2 5//pin for run the left motor 
#define IN2 4//pin for control left motor direction

#define FORW 1//go forward
#define BACK 0//go back

void setup(){
  pinMode(EN1,OUTPUT);
  pinMode(EN2,OUTPUT);
  pinMode(IN1,OUTPUT);
  pinMode(IN2,OUTPUT);
}

void Motor_Control(char MD_DIR,char MD_EN,char MG_DIR,char MG_EN){
  //////////MGauche////////////////////////
  if(MG_DIR==FORW)//M1 motor direction
    digitalWrite(IN1,FORW);//forward
  else
    digitalWrite(IN1,BACK);//back
    analogWrite(EN1,MG_EN);//set speed
  ///////////MDroit//////////////////////
  if(MD_DIR==FORW)
    digitalWrite(IN2,FORW);
  else
    digitalWrite(IN2,BACK);
    analogWrite(EN2,MD_EN);
}

void loop(){
  Motor_Control(1,100,1,100);
  delay(100);
  Motor_Control(0,0,0,0);
  delay(1000);
  Motor_Control(0,100,0,100);
  delay(100);
  Motor_Control(0,0,0,0);
  delay(1000);
  while(1);
}

Modifier ce code pour réaliser un simple cercle. Seule la partie loop est à modifier !

Attention : Vos essais seront faits sur la table de travail.

  • Il y a des risques de chutes ! Soyez donc prudents !
  • Ne mettez pas de vitesses excessives !
  • N'oubliez pas que votre câble USB n'est pas infini !
  • N'oubliez pas que loop est appelé sans arrêt. Un moyen de coincer le programme est de faire la boucle infinie de l'exemple !

2°) L'inconvénient du code présenté plus haut est que pendant que les moteurs tournent le micro-contrôleur ne peut rien faire d'autre. Nous allons donc modifier profondément notre philosophie d'écriture du code.

// définition d'une durée de 2,4s
#define temps_ARRET 2400
void loop(){
  unsigned long time = millis();
  static char rapport_cyclique,avant;
  if ((time>1000)&&(time<1200)){
    rapport_cyclique = 100;avant=FORW;
  }    
  if ((time>1200)&&(time<2200)) {
    rapport_cyclique = 0;avant=FORW;
  }
  if ((time>2200)&&(time<2400)) {
    rapport_cyclique = 100;avant=BACK;
  }
/*  if ((time>2400)&&(time<13000)) {
    Motor_Control(0,0,0,0);
*/ 
//****** c'est ici qu'on arrete tout  
  if (time > temps_ARRET){ // au bout de 20s
    rapport_cyclique = 0;avant=1;
  }
  Motor_Control(avant,rapport_cyclique,avant,rapport_cyclique); 
}

On voit que le code n'est pas bloqué par un "while(1)" et que les actions à entreprendre sont faites en fonction du temps courant qui est obtenu avec "millis()".

3°) Étude du rayon du cercle. Nous avons vu en cours que Échec d'analyse (L’exécutable <code>texvc</code> est introuvable. Lisez math/README pour le configurer.): R(t) = \frac{L}{2} \frac{v_g(t)+v_d(t)}{v_g(t)-v_d(t)}

Essayez d'étudier si le rayon peut s'écrire Échec d'analyse (L’exécutable <code>texvc</code> est introuvable. Lisez math/README pour le configurer.): R = K \frac{\alpha_g+\alpha_d}{\alpha_g-\alpha_d}Échec d'analyse (L’exécutable <code>texvc</code> est introuvable. Lisez math/README pour le configurer.): \alpha_g et Échec d'analyse (L’exécutable <code>texvc</code> est introuvable. Lisez math/README pour le configurer.): \alpha_d désignent le rapport cyclique des moteurs gauche et droit (qui varient entre 0 et 255) et K est une constante à déterminer. Une des difficultés de cette question est de trouver une méthode pour essayer d'évaluer le rayon du cercle.

Cette question ne peut pas être réalisée en pratique : le robot dévie trop en ligne droite !!!!