Cours:ArduinoBoutonsNano

De troyesGEII
Aller à : navigation, rechercher
Retour à la liste des Tps
Éléments de correction
Carte d'extension arduino pour les Tps d'info


Ce Tp va permettre d'introduire quelques éléments indispensables à la programmation d'une carte arduino, et surtout d'apprendre à se servir d'une documentation, en l'occurrence celle disponible sur le site arduino.

Il convient de bien comprendre qu'une carte arduino (et plus exactement toute carte utilisant un microcontrôleur) peut servir à faire de multiples tâches. On utilise nécessairement des extensions (shields) et nous devrons spécifier dans le programme la façon de "communiquer"/gérer cette carte. Physiquement, cette communication s'opère à travers de connexions dont le nombre dépend de la carte utilisée. Nous utiliserons une carte arduino NANO qui possède 2 connecteurs pour l'échange de données, numérotés de 0 à 13 et de A0 à A5, soit un total de 20 connexions.

Si nous nous considérons à la place de la carte arduino, chaque connexion peut être :

  • une entrée/INPUT (mesure, observation). Par ex,
    • capteur de température
    • interrupteur
    • mesure de tension
    • microphone
  • une sortie/OUTPUT (action). Par ex,
    • résistance chauffante
    • lampe, voyant lumineux
    • haut parleur


Notions fondamentales

Gestion des sorties

On souhaite allumer et éteindre une led sur la carte.

Nous utiliserons les 2 leds (sérigraphie L1 et L2 sur la carte) qui sont reliées sur la carte arduino :

Led numéro arduino
L1 D5
L2 D13

Principe

Nous pouvons maintenant écrire le programme qui comporte nécessairement une partie configuration ( setup() ) et une boucle ( loop() ) :

  • le setup() exécuté une seule fois
  • le loop() exécuté en boucle (loop veut dire boucle en anglais)

On commence par la partie configuration qui nous permet de définir les entrées et sorties :

void setup()
{
  pinMode(5,OUTPUT); // on précise ici que la patte 5 est une sortie
}

On peut ensuite décrire le comportement souhaité :

void loop()
{
  digitalWrite(5,0); // extinction de la led
  digitalWrite(5,1); // éclairement de la led
}

Todo.jpg Saisir le programme, l'exécuter et constater que ....

ça ne clignote pas !

En effet, les instructions étant exécutées très rapidement, il est impossible d'observer le clignotement.


Todo.jpg Ajoutons donc une temporisation ce qui nous donne le programme suivant :

void setup()
{
  pinMode(5,OUTPUT); // on précise ici que la patte 5 est une sortie
}

void loop()
{
  digitalWrite(5,0); // extinction de la led
  delay(100);
  digitalWrite(5,1); // éclairement de la led
  delay(100);
}

Vous trouverez des détails sur la fonction delay() sur cette page.

Todo.jpg Utilisons maintenant une variable pour la position de la led afin de rendre notre code plus facilement lisible et modifiable :

const unsigned int ledPin = 5;

void setup()
{
  pinMode(ledPin,OUTPUT); // on précise ici que la patte 5 est une sortie
}

void loop()
{
  digitalWrite(ledPin,0); // extinction de la led
  delay(100);
  digitalWrite(ledPin,1); // éclairement de la led
  delay(100);
}

Avec cette structure, vous pouvez maintenant facilement changer de led.

Ex avec les leds

Écrire les programmes répondant aux cahiers des charges suivants :

Question.jpg Allumer une led pendant 1s et l'éteindre pendant 3s.

Question.jpg Allumer 2 leds pendant 100ms et les éteindre pendant 3s.

Question.jpg Allumer en alternance la led L1 puis la led L2, chacune étant allumée 1s

Question.jpg Allumer la led L1 puis les 2 leds puis seulement la led L2 puis tout éteint, en changeant toutes les 500ms

Clignotement

Nous allons essayer de faire clignoter les leds à des rythmes différents.

Commençons par utiliser une variable pour changer l'état de la led :

bool etatLed1 = false; //variable booléenne pour mémoriser l'état de la led
const unsigned int pinLed1 = 5;

void setup()
{
  pinMode(pinLed1,OUTPUT);        // déclarer la broche en sortie
}

void loop()
{
  etatLed1 = ! etatLed1;          // inverser l'état de la variable booléenne
  digitalWrite(pinLed1,etatLed1); // modifier l'état de la sortie
  _delay_ms(200);                 // attendre 200ms avant de recommencer -> rythme de clignotement
}

Todo.jpg Vérifier le bon fonctionnement et comprendre ce programme

On souhaite réduire la valeur du delay tout en conservant la même vitesse de clignotement :

  • réduire le delay à 20ms
  • déclarer une variable cptLed1 de type int
  • incrémenter ce compteur à chaque itération
  • si le compteur vaut 10 :
    • remettre le compteur à 0
    • changer l'état de la variable etatLed1
    • modifier l'état de la sortie

Question.jpg Faire les modifications demandées


Maintenant que nous avons préparé la structure du programme, il est assez simple d'ajouter une 2ème led qui clignotera à un rythme différent :

  • ajouter les variables nécessaires pour cette 2ème led :
    • etatLed2
    • pinLed2
    • cptLed2
  • ajouter la 2ème led en sortie
  • modifier le loop pour que la 2ème led change d'état toutes les 140ms

Question.jpg Faire les modifications pour avoir les 2 leds qui clignotent à des rythmes différents

Gestion d'une entrée

Nous souhaitons maintenant observer l'état d'un bouton sur la carte. Il s'agit donc d'une entrée : la carte arduino observe l'état du bouton, ce n'est pas elle qui modifie son état !

De façon analogue à la partie précédente, trouvons sur la page de documentation le tableau suivant :

Bouton Arduino Pin Port Interruption Niveau logique de l'entrée arduino si bouton appuyé
haut 3 PD3 int1 0
bas 2 PD2 int0 0


Nous choisissons le bouton référencé A et retenons donc le numéro de patte arduino associé : 2

On utilisera astucieusement 2 variables comme :

  • bpPin : qui représentera la position physique du bouton
  • etatBp : qui représentera la valeur du bouton

Il suffit de configurer la patte du bouton en entrée ( pinMode() ) et de lire l'état de cette patte ( digitalRead() ) :

const unsigned int bpPin = 5;
unsigned int etatBp;

void setup()
{
  pinMode(bpPin,INPUT); // le bouton est connecté sur la patte représentée par la variable bpPin
}

void loop()
{
   etatBp = digitalRead(bpPin); // lecture de l'état de l'entrée
   .....                        // la variable etatBp sera utilisée dans la suite de l'algorithme pour tenir compte de l'état du bouton
   .....                        // ex : if ( etatBp == 0) {....;}
}






Ex 1: Entrée, sortie ???

1 bp, 1 led

Commençons tout simplement par commander une sortie tout ou rien (2 états possibles) à l'aide d'un bouton poussoir.

On prendra la led L1, et le bouton du haut.

On se servira des fonctions suivantes :

  • pinMode() permettant de configurer les entrées et sorties(e/s).
  • digitalWrite() permettant de modifier l'état d'une sortie.
  • digitalRead() permettant de lire l'état d'une entrée.

Question.jpg Compléter le programme suivant pour que la led ne s'allume que si le bouton est appuyé.

unsigned int ledPin= ... ;   // qques variables pour la position
unsigned int bpPin = ... ;   // des e/s
unsigned int etatBp;         // et récupérer l'état du bouton

void setup()
{
     pinMode(...,INPUT);      // configuration des e/s
     pinMode(...,OUTPUT);
}

void loop()
{
     etatBp = ..........;     // "Lecture" de l'état de l'entrée
     ...................;     // "Écriture" de l'état de la sortie
}

2 bps, 1 led

On ajoute le deuxième bouton.

Question.jpg Écrire un programme qui allume la led uniquement si les 2 boutons sont appuyés

Question.jpg Écrire un programme qui allume la led si au moins l'un des 2 boutons est appuyé

Question.jpg Écrire un programme qui allume la led s'il n'y a qu'un bouton appuyé







Ex 2: Détection de changement d'état

Modifions légèrement le comportement. Nous souhaitons désormais que l'état de la led change à chaque appui sur le bouton du bas. On détecte non plus un état du bouton, mais un changement d'état de celui-ci.

Par interruption

Sans entrer dans le détail pour le moment et sans être exhaustif, nous utiliserons les interruptions de la façon suivante :

Mise en place

Dans la fonction setup(), nous utiliserons la fonction attachInterrupt() qui permettra d'exécuter une fonction particulière lors d'un événement parmi :

  • CHANGE  : la fonction d'interruption est exécutée sur une changement d'état de l'entrée
  • RISING  : la fonction d'interruption est exécutée sur un passage de l'état 0 à 1 de l'entrée
  • FALLING : la fonction d'interruption est exécutée sur un passage de l'état 1 à 0 de l'entrée

On précise également le numéro de l'interruption qui nous intéresse comme indiqué dans le tableau un peut plus haut sur cette page.

Exemple :

void setup()
{
   pinMode(5,OUTPUT);               // On précise que la pin (patte) 13 est une sortie dans la suite de l'exemple.
   attachInterrupt(0,reagir,RISING); // La fonction reagir() sera exécutée lorsque le bouton A (int0) sera relâché.
}

Utilisation

Il convient bien entendu de déclarer la fonction d'interruption (reagir ici) qui permettra par exemple de placer un drapeau (flag) dans un état particulier :

volatile int appui;
int etatLed = 0;

void reagir()
{
   appui = 1;
}

void loop()
{
   if ( appui == 1)
   {
      etatLed = !etatLed ;
      digitalWrite(5,etatLed);
      appui = 0 ;
   }
   delay(1);
}

Test

Todo.jpg Recopier le programme, vérifier son fonctionnement et profitez en pour tester les différents mode de déclenchement de l'interruption.

2 bps, 1 led

Question.jpg A l'aide de la méthode précédente, ajouter le deuxième bouton pour que :

  • la led s'allume lors de l'appui sur le bouton haut.
  • la led s'éteigne lors du relâchement du bouton bas.







En observant le changement de valeur du bouton

Pour ce faire, il convient de remarquer que juste avant l'appui, la valeur lue sur l'entrée correspondant au bouton est à l'état 1, et que dès l'appui la valeur passe à l'état 0.

Vous utiliserez 2 variables de type int (par exemple etatPresent et etatPasse), qui permettront de détecter cette transition.

On utilisera également une variable etatSortie de type unsigned int pour mémoriser l'état de la sortie.

Le programme ressemblera donc à :

int etatPresent=0,etatPasse=0;
unsigned int etatSortie=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 ....
   {
         .....
   }
}

Question.jpg Écrire le programme répondant au cahier des charges.

Ex 4: Game over !

Certains systèmes pour lesquels la sécurité est primordiale comportent un interrupteur de type "homme mort" permettant de vérifier la présence et l'état de conscience de l'opérateur.

Nous allons utiliser l'un des boutons poussoirs de notre carte pour réaliser cette fonction.

Le principe est le suivant : toute les 3s on allume une led. L'opérateur doit alors appuyer sur un bouton poussoir (que vous choisirez) dans les 3s suivantes. Dès l'appui, la 1ère led doit s'éteindre et la 2ème led s'allume.

Si l'opérateur n'a pas appuyé dans le délais imparti, toutes les leds s'éteignent.

On pourra utiliser la fonction millis(), un exemple d'utilisation étant donné sur ce lien. Vous pouvez ajouter dans votre programme une ligne delay(1), qui permettra de rythmer le programme.

Question.jpg A vous de jouer !