Tag Archives: interrupts

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