Les interruptions sous Arduino / ATMega

Comme vous le savez certainement, il est possible sur les cartes Arduino (Uno, Mega, Due, etc.) de gérer des interruptions.

Le Arduino Uno (ATMega328) peut gérer 2 interruptions externes sur ses pins INT0 et INT1, mappés sur D2 et D3 (respectivement pins 4 et 5 du ATMega328 format PDIP).

Pins d’interruptions externes sur un Arduino Uno

A noter que les ATMega328 peuvent également gérer des interruptions de changement d’état sur 20 de ses pins ; cependant, la gestion de ces interruptions n’est pas aussi simple que les externes : il faut déterminer quel pin a généré l’interruption, pour quelle raison, etc. Une librairie Arduino a été développée afin de permettre l’utilisation de ces interruptions : arduino-pinchangeint.

Les interruptions peuvent être déclenchées selon 4 modes :

  • LOW : le pin est à un état bas
  • RISING : le pin passe d’un état bas à haut
  • FALLING : le pin passe d’un état haut à bas
  • CHANGE : le pin change d’état

Une ligne suffit à « écouter » une interruption sur un Arduino ; par exemple sur le pin INT0 (soit D2) nous attachons une interruption, qui appellera la fonction « myInterrupt » lors d’un passage du pin à l’état haut :

attachInterrupt(0, myInterrupt(), RISING);

Bien que le pin Arduino soit « D2 », nous indiquons ici « 0 » qui est le n° de pin d’interruption (0 pour INT0 / D2, 1 pour INT1 / D3).

Il faut ensuite définir la fonction qui sera appelée lors de l’interruption ; à noter que celle-ci ne reçoit aucun argument et ne doit rien retourner :

void myInterrupt() {
  // do something ...
}

Quelques limitations

Dans la fonction attachée à une interruption, celles-ci étant basées sur les timers de votre microcontrôleur, la fonction delay() ne marchera pas, millis() ne s’incrémentera pas.

Plus généralement, il est déconseillé de réaliser des opérations basées sur le temps, qui bloqueront votre µC ; par exemple la transmission de données en série (UART), I2C, etc.

Bonnes pratiques

L’usage des interruptions est idéal lors d’actions utilisateur, comme l’utilisation d’un bouton, d’un keypad, ou pour détecter un changement d’état rapide (signal infrarouge coupé), sans avoir à constamment « écouter » l’état d’un pin.

Idéalement, une fonction attachée à une interruption doit être la plus courte et rapide possible : une bonne pratique consiste à s’en servir pour stocker une valeur dans une variable (déclarée « volatile »). L’exécution de l’action à proprement parler se fera dans votre routine principale (loop()).

Par exemple :

volatile int change = 0;

void main() {
  attachInterrupt(0, myInterrupt(), RISING);
}

void loop() {
  if(change == 1) {
    // do something ...
change = 0;
  }
}

Liens utiles

About 

Développeur PHP freelance Symfony2 & Magento, passioné de programmation et d'électronique.

  • googleplus
  • twitter
  • nux tux

    Bonjour,
    Il y a une petite erreur dans le code lors de l’appel de la fonction => attachInterrupt(0, myInterrupt(), RISING); il ne faut pas mettre les parenthèses.
    Voici le bon code : attachInterrupt(0, myInterrupt, RISING);

    cdt,

  • JD

    Bonjour,
    Il faut aussi veiller à désactiver les interruptions si on manipule la variable partagée avec l’interruption (change) pour éviter les effets de bord. En effet, il y a une forte probabilité que l’interruption change la valeur de la variable alors que le code dans loop() traite la variable
    Cordialement