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).
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
I'm Michael BOUVY, CTO and co-founder of Click&Mortar, a digital agency based in Paris, France, specialized in e-commerce.
Over the last years, I've worked as an Engineering Manager and CTO for brands like Zadig&Voltaire and Maisons du Monde.
With more than 10 years experience in e-commerce platforms, I'm always looking for new challenges, feel free to get in touch!