Cours:TPs Mecatro : Différence entre versions
m (→TP-4 Boutons Leds mémorisation et temps) |
m (→TP) |
||
Ligne 157 : | Ligne 157 : | ||
==TP== | ==TP== | ||
− | + | ===Introduction=== | |
− | + | Suivre le document de cours à partir de la page 81 jusqu'à 85. La partie décodeur 4 bits vers 7 segments ne sera donc pas traitée | |
+ | ===Plus loin avec affichage 7 segments et boutons=== | ||
+ | Compteur automatique ou manuel : 1 bouton pour le choix, un bouton manuel. | ||
=TP-4 Boutons Leds mémorisation et temps= | =TP-4 Boutons Leds mémorisation et temps= |
Version du 22 novembre 2015 à 10:03
Carte d'extension arduino pour les Tps d'info
Comme d'habitude, on se réfère à : Premiers Pas en Informatique Embarquée document de cours (de Simon Landrault et al.)
Sommaire
TP-1 Diode électroluminescente
Cours
Notion de setup()
Notion de loop()
Notion d'entrée/sortie :
- pinMode
- digitalWrite et digitalRead
TP : led seule
- Suivre le document à partir de la page 48
TP Faire clignoter un groupe de LEDs
- Suivre le document à partir de la page 61.
Notre partie matérielle sera différente : elle sera constituée d'un shield tout fait dont on vous donne la documentation.
Numéro | f5 | f4 | f3 | f2 | f1 | f0 | p1 | p0 |
---|---|---|---|---|---|---|---|---|
Couleur | r | o | v | r | o | v | v | r |
Arduino Pin | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 |
Port Arduino UNO | PB5 | PB4 | PB3 | PB2 | PB1 | PB0 | PD7 | PD6 |
Port Arduino LEONARDO | PC7 | PD6 | PB7 | PB6 | PB5 | PB4 | PE6 | PD7 |
TP Réaliser un chenillard
- Suivre le document de cours à partir de la page 64 jusqu'à la page 65.
- Pouvez-vous réaliser le même chenillard avec une boucle ?
- Réaliser des chenillards de votre propre invention. Si vous n'avez pas d'idée, demandez à votre enseignant.
TP Feux de signalisation routière
- Suivre le document de cours à partir de la page 67 en repérant les modifications de notre shield par rapport aux branchements donnés dans ce cours.
TP-2 Boutons et diodes électroluminescantes
Cours
Détecter la position d'un bouton
Il est naturellement possible de connecter des boutons poussoirs à un PORT et de demander au micro-contrôleur de dire si le bouton est appuyé ou relâché. Sur un robot mobile on peut utiliser ce principe pour détecter des objets (un peu tard d'ailleurs puisqu'il y a eu contact).
Regardez attentivement le dessin de gauche et en particulier la connexion sur le bit PB4. On sait parfaitement ce qu'il se passe si le bouton est appuyé : on est relié à Vcc on aura donc un un logique en lecture. Mais qu'en est-il si on lâche le bouton poussoir ? Tout dépend de la technologie du PORT. La technologie TTL fournirait un un logique donc aucune différence suivant que le bouton est appuyé ou pas !
Remarques :
- L'idée qui consiste à croire que puisqu'on est relié à rien, alors on lit systématiquement un zéro logique est parfois une idée fausse !!!
- Le bit PB4 du schéma de droite ne fonctionne pas forcément comme on l'attend : lâché est un un logique, appuyé est un zéro logique !
- Le bit PB0 du schéma de droite fonctionne normalement : appuyé = un logique, relâché = zéro logique
Il faut donc utiliser une résistance supplémentaire que l'on appelle résistance pullup (ou Résistance de tirage en français). Soit elle existe à l'intérieur du PORT, soit il faut l'ajouter à l'extérieur du PORT.
Utiliser une pullup interne
L'utilisation d'une résistance de pullup interne permet de simplifier le schéma. Il y a deux façons de réaliser un pullup interne :
- écriture d'un un logique après passage en entrée
void setup() {
// put your setup code here, to run once:
pinMode(11,INPUT);
digitalWrite(11,HIGH);
}
- déclaration directe
void setup() {
// put your setup code here, to run once:
pinMode(11,INPUT_PULLUP);
delay(1); // obligatoire !!!!
}
Détecter un changement d'état d'un bouton poussoir
Pourquoi détecter un changement d'état d'un bouton ? Réponse en cours.
Voici la technique à méditer très longuement :
unsigned char etatPresent=0,etatPasse=0;
void setup(){
..... // configuration des e/s
}
void loop(){
etatPasse=etatPresent; // mémorise l'état précédent (le présent devient le passé)
etatPresent=digitalRead(??); // lecture de la valeur actuelle
if ( ( etatPresent == ?? ) && ( etatPasse == ?? ) ) { // si appui alors ....
.....
}
delay(20); // est-ce obligatoire ???
}
TP
Suivre le document de cours à partir de la page 71 jusqu'à la page 80. Vous utiliserez au choix un montage avec plaque à essais ou le shield de l'IUT.
Pour ceux qui sont rapides, réalisez trois chenillard différents qui peuvent être appelés avec un bouton poussoir :
- j'appuie sur le bouton poussoir pour passer au chenillard 1
- j'appuie sur le bouton poussoir pour passer au chenillard 2
- j'appuie sur le bouton poussoir pour passer au chenillard 3
- un nouvel appui repasse au chenillard 1 ...
Correction partielle
unsigned char etatPresent=0,etatPasse=0;
unsigned char menu=0,tempo=0;
unsigned char leds;
void setup(){
char i;
for (i=6;i<=13;i++) pinMode(i,OUTPUT); // Déclaration des 6 so
pinMode(2,INPUT);
}
void allumeLeds(unsigned char motif){
char i;
for (i=0;i<8;i++) {
digitalWrite(i+6,(motif>>i) & 1);
}
}
void loop(){
etatPasse=etatPresent; // mémorise l'état précédent (le présent devient le passé)
etatPresent=digitalRead(2); // lecture de la valeur actuelle
if ( ( etatPresent == 0 ) && ( etatPasse == 1 ) ) { // si appui alors ....
menu++;
if (menu==3) menu = 0;
}
tempo++;
if (tempo == 50) {
tempo = 0;
switch(menu) {
case 1 : leds = leds << 1;if (leds==0) leds = 1;break;
case 2 : leds = leds >> 1;if (leds==0) leds = 128;break;
}
}
allumeLeds(leds);
delay(20); // est-ce obligatoire ? OUI
}
TP-3 Afficheurs sept segments
Cours
- Opérateurs de décalage : retour sur la gestion du temps de la correction du TP précédent
- Sous-programme
- affichage 7 segments
- affichage sur 1 seul digit
- affichage sur deux digits
TD : Plus loin sur la gestion du temps
Soit le programme :
void loop() {
tempo++; // déclaré en global comme unsigned char
if ((tempo & 0x01)==0x01) {
// faire chose1 ici
}
if ((tempo & 0x02)==0x02) {
// faire chose2 ici
}
delay(2);
}
- Tous les combien de temps chose1 et chose2 sont réalisés ?
- Comment modifier ce programme pour détecter un front sur un interrupteur environ toutes les 20 ms ?
TP
Introduction
Suivre le document de cours à partir de la page 81 jusqu'à 85. La partie décodeur 4 bits vers 7 segments ne sera donc pas traitée
Plus loin avec affichage 7 segments et boutons
Compteur automatique ou manuel : 1 bouton pour le choix, un bouton manuel.
TP-4 Boutons Leds mémorisation et temps
Cours
- Autre manière pour gérer le temps sans bloquer le programme : utiliser millis
Voici une façon de faire :
// 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;
}
//****** 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);
}
TP-5 GRAFCETs
Ex 6: POUR ALLER PLUS LOIN : lien avec l'automatisme
Les GRAFCETs abordés en automatisme (Module M2102) peuvent être transformés en équations de récurrences puis en programmes.
Équation de récurrences
La méthode simple consiste à écrire pour chacune des étapes les conditions d'activations (notées Échec d'analyse (L’exécutable <code>texvc</code> est introuvable. Lisez math/README pour le configurer.): AC_i ) et les conditions de désactivations (notées Échec d'analyse (L’exécutable <code>texvc</code> est introuvable. Lisez math/README pour le configurer.): D_i ).
Définition
La condition d'activation Échec d'analyse (L’exécutable <code>texvc</code> est introuvable. Lisez math/README pour le configurer.): AC_i s'obtient en se posant la question : comment activer l'étape i si elle n'est pas active ?
La condition de désactivation s'obtient quant à elle en se posant la question : quelles sont les conditions nécessaires pour que le jeton quitte l'étape i s'il est dedans ?
Transformation en équations de récurrences
Avec ces conditions on va pouvoir former les équations de récurrences :
- Pour la ou les étapes initiales : Échec d'analyse (L’exécutable <code>texvc</code> est introuvable. Lisez math/README pour le configurer.): x_i^+=AC_i + \overline{D_i} \cdot x_i + Init
- Pour les étapes non initiales : Échec d'analyse (L’exécutable <code>texvc</code> est introuvable. Lisez math/README pour le configurer.): x_i^+=(AC_i + \overline{D_i} \cdot x_i) \cdot \overline{Init}
L'entrée "Init" sera abandonnée dans toute cette section !
L'indice i parcourant toutes les étapes, il y a autant d'équations de récurrences que d'étapes. En terme matériel, cela signifie que l'on utilisera un bit mémoire par étape. Pour nous on utilisera une variable (de type char) par étape, ce qui est un énorme gaspillage ! mais simplifie la programmation.
Bien sûr, un codage des états (abordé ICI) permet de faire des économies de ce côté là mais rappelez-vous qu'à ce point on a que des étapes et pas encore des états.
Nous allons partir d'un GRAFCET assez général pour réaliser un exemple complet.
Prenez un peu de temps pour relire l'équation de AC1 et celle de D3 qui prennent en compte le parallélisme. C'est le seul type de situation qui diffère du Logique séquentielle : Description par graphe d'état.
Trouvez l'erreur dans l'équation de récurrence x4+.
Transformation en programme
Un programme gérant un GRAFCET devra comporter trois parties :
- une partie pour gérer (et éventuellement calculer) les entrées (temporisées ou pas)
- une partie pour gérer les équations de récurrences
- une partie pour gérer les actions
Le tout est dans une boucle infinie
Exemple correspondant au GRAFCET ci-dessus
Les LEDs du shield IUT Troyes sont couplés à l'arduino MEGA2560. Une lecture de son schéma fait apparaître la correspondance :
Numéro | f5 | f4 | f3 | f2 | f1 | f0 | p1 | p0 |
---|---|---|---|---|---|---|---|---|
Couleur | r | o | v | r | o | v | v | r |
Arduino Pin | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 |
Port UNO | PB5 | PB4 | PB3 | PB2 | PB1 | PB0 | PD7 | PD6 |
Port MEGA2560 | PB7 | PB6 | PB5 | PB4 | PH6 | PH5 | PH4 | PH3 |
Etape de GRAFCET | 1 | 2 | 3 | 4 | 5 | - | - | - |
Le code donné ci-dessous est pour la carte MEGA2560. Il devra être adapté par vos soins pour la carte UNO.
Voici le code correspondant :
//*********** Programme pour MEGA2560 ********************
char x1; // étape 1
void setup(){
//******* sorties
DDRB |= 0xF0;//f5 f4 f2 f1
DDRH |= 0x40;// f0
//******* entrees
DDRE &= 0xCF; // 2 and 3
DDRF &= 0xFC; //A0 et A1
//******* initialisation du GRAFCET
x1 = 1;
}
void loop(){
char e1,e2,e3,e4;
static char x2,x3,x4,x5;
char xf1,xf2,xf3,xf4,xf5; // f pour futur remplace le +
//******* calcul des entrées
if (PINE & 0x20) e1 = 1; else e1 = 0; // 2:Bas gauche
if (PINE & 0x10) e2 = 1; else e2 = 0; // 3:Haut gauche
if (PINF & 0x02) e3 = 0; else e3 = 1; // A0:bas droite
if (PINF & 0x01) e4 = 0; else e4 = 1; // A1:Haut droite
//******* calcul des equations de récurrence
xf1 = x3 & x5 & e4 | x1 & !e1;
xf2 = x1 & e1 | x2 & !e2;
xf3 = x2 & e2 | x3 & !(e4 & x5);
xf4 = x1 & e1 | x4 & ! e3;
xf5 = x4 & e3 | x5 & !(e4 & x3);
// mise à jour du present avec le futur
x1 = xf1;
x2 = xf2;
x3 = xf3;
x4 = xf4;
x5 = xf5;
//******* calcul des sorties (pour MEGA2560)
if (x1) PORTB |= (1<<PB7); else PORTB &= ~(1<<PB7);
if (x2) PORTB |= (1<<PB6); else PORTB &= ~(1<<PB6);
if (x3) PORTB |= (1<<PB5); else PORTB &= ~(1<<PB5);
if (x4) PORTB |= (1<<PB4); else PORTB &= ~(1<<PB4);
if (x5) PORTH |= (1<<PH6); else PORTH &= ~(1<<PH6);
delay(500);
}
La partie calcul des entrées sera mieux comprise avec les informations suivantes :
Bouton | Position | Arduino Pin | Port MEGA2560 | Résistance de tirage | Niveau logique si bouton appuyé |
---|---|---|---|---|---|
A | Bas Gauche | 2 | PE4 | Pull Up + inverseur | 1 |
D | Haut Gauche | 3 | PE5 | Pull Up + inverseur | 1 |
B | Bas Droite | A0 | PF0 | Pull Down + inverseur | 0 |
C | Haut Droite | A1 | PF1 | Pull Down + inverseur | 0 |
La documentation correspondante pour votre carte UNO est disponible ICI.
Travail à faire
Modifier le programme précédent pour :
- l'adapter à votre carte UNO. Pourquoi x1 est une variable globale ?
- que l'arrivée dans l'étape 5 fasse clignoter la LED correspondante
- que l'arrivée dans l'étape 3 fasse clignoter la LED correspondante à une autre fréquence
- que la transition e1 soit sur front montant (sans utiliser d'interruption)
- que la transition e1 soit sur front montant (en utilisant une interruption)