Le multitâche a conduit les ordinateurs à une révolution où un ou plusieurs programmes peuvent s’exécuter simultanément, ce qui augmente l’efficacité, la flexibilité, l’adaptabilité et la productivité. Dans les systèmes embarqués, les microcontrôleurs peuvent également gérer le multitâche et effectuer deux tâches ou plus simultanément sans arrêter les instructions en cours.

Ici, dans ce tutoriel, nous allons apprendre comment Arduino effectue le multitâche avec la fonction Arduino millis. Généralement, une fonction delay() est utilisée dans Arduino pour une tâche périodique comme le clignotement de la LED, mais cette fonction delay() arrête le programme pendant un certain temps définitif et ne permet pas d’autres opérations. Cet article explique donc comment nous pouvons éviter d’utiliser la fonction delay() et la remplacer par millis() pour effectuer plusieurs tâches simultanément et faire de l’Arduino un contrôleur multitâche. Avant d’entrer dans les détails, commençons par sous-estimer le multitâche.

Qu’est-ce que le multitâche ?

Le multitâche signifie simplement exécuter plusieurs tâches ou programmes simultanément en même temps. Presque tous les systèmes d’exploitation disposent du multitâche. Ce type de systèmes d’exploitation est connu sous le nom de MOS (système d’exploitation multitâche). Le MOS peut être un système d’exploitation pour PC mobile ou de bureau. Le bon exemple du multitâche dans les ordinateurs est lorsque les utilisateurs exécutent l’application de messagerie, le navigateur Internet, le lecteur multimédia, les jeux, en même temps et si les utilisateurs ne veulent pas utiliser l’application qu’ils exécutent en arrière-plan si elle n’est pas fermée. L’utilisateur final utilise toutes ces applications en même temps, mais OS prend ce concept un peu différent. Discutons de la façon dont le système d’exploitation gère le multitâche.

Qu'est-ce que le multitâche dans Arduino

Comme on le voit sur l’image, le CPU divise le temps en trois parties égales et attribue chaque partie à chaque tâche / application. C’est ainsi que le multitâche se fait dans la plupart des systèmes. Le concept sera presque le même pour l’Arduino Multitâche, sauf que la répartition du temps sera un peu différente. Étant donné que l’Arduino fonctionne en basse fréquence et que la RAM se compare à un ordinateur portable / Mobile / PC, le temps accordé à chaque tâche sera également différent. Arduino a également une fonction delay() qui est largement utilisée. Mais avant de commencer, discutons de la raison pour laquelle nous ne devrions pas utiliser la fonction delay() dans un projet.

Pourquoi sauter delay() dans Arduino?

Si la documentation de référence d’Arduino est considérée, il existe deux types de fonctions de retard, la première est delay() et la seconde est delayMicroseconds(). Les deux fonctions sont identiques en termes de génération de retard. La seule différence est que, dans la fonction delay(), l’entier de paramètre passé est en millisecondes, c’est-à-dire que si nous écrivons delay(1000), le délai sera de 1000 millisecondes, soit 1 seconde. De même dans la fonction delayMicroseconds(), le paramètre passé est en microsecondes, c’est-à-dire que si nous écrivons delayMicroseconds(1000), le délai sera de 1000 microsecondes, soit 1 milliseconde.

Voici le point, les deux fonctions mettent le programme en pause pendant le temps écoulé dans la fonction de retard. Donc, si nous donnons un délai de 1 seconde, le processeur ne peut pas passer à l’instruction suivante avant que 1 seconde ne soit passée. De même, si le délai est de 10 secondes, le programme s’arrêtera pendant 10 secondes et le processeur ne permettra pas de suivre les instructions suivantes jusqu’à ce que les 10 secondes se soient écoulées. Cela entrave les performances du microcontrôleur en termes de vitesse et d’exécution des instructions.

Le meilleur exemple pour expliquer l’inconvénient de la fonction de retard est l’utilisation de deux boutons poussoirs. Considérons que nous voulons basculer deux LED à l’aide de deux boutons-poussoirs. Donc, si un bouton-poussoir est enfoncé, la LED correspondante doit s’allumer pendant 2 secondes, de même si la seconde est enfoncée, la LED doit s’allumer pendant 4 secondes. Mais lorsque nous utilisons delay(), si l’utilisateur appuie sur le premier bouton, le programme s’arrêtera pendant 2 secondes et si l’utilisateur appuie sur le deuxième bouton avant 2 secondes de retard, le microcontrôleur n’acceptera pas l’entrée car le programme est en phase d’arrêt.

La documentation officielle d’Arduino le mentionne clairement dans ses Notes et avertissements de description de la fonction delay(). Vous pouvez passer en revue et vérifier cela pour le rendre plus clair.

Pourquoi utiliser millis() ?

Pour surmonter le problème causé par l’utilisation de delay, un développeur doit utiliser la fonction millis() qui est facile à utiliser une fois que vous devenez habituel et qu’elle utilisera des performances CPU à 100% sans générer de retard dans l’exécution des instructions. millis() est une fonction qui renvoie simplement la quantité de millisecondes qui se sont écoulées depuis que la carte Arduino a commencé à exécuter le programme en cours sans geler le programme. Ce nombre de temps va déborder (c’est-à-dire revenir à zéro), après environ 50 jours.

Tout comme Arduino ont delayMicroseconds(), il a également la version micro de millis() comme micros(). La différence entre micros et millis est que le micros() débordera après environ 70 minutes, par rapport à millis() qui est de 50 jours. Donc, selon l’application, vous pouvez utiliser millis() ou micros().

Using millis() instead of delay():

Pour utiliser millis() pour la synchronisation et le délai, vous devez enregistrer et stocker l’heure à laquelle l’action a eu lieu pour démarrer l’heure, puis vérifier à intervalles réguliers si l’heure définie s’est écoulée. Donc, comme indiqué, stockez l’heure actuelle dans une variable.

unsigned long currentMillis = millis();

Nous avons besoin de deux variables supplémentaires pour savoir si le temps requis s’est écoulé. Nous avons stocké l’heure actuelle dans la variable currentMillis, mais nous devons également savoir quand la période de synchronisation a-t-elle commencé et quelle est la durée de la période. Donc, l’intervalle et le Précédentmillis est déclaré. L’intervalle nous indiquera le délai et previosMillis stockera la dernière fois que l’événement s’est produit.

unsigned long previousMillis;unsigned long period = 1000;

Pour comprendre cela, prenons un exemple de LED clignotante simple. La period=1000 nous indiquera que la LED clignotera pendant 1 seconde ou 1000ms.

const int ledPin = 4; // the LED pin number connectedint ledState = LOW; // used to set the LED stateunsigned long previousMillis = 0; //will store last time LED was blinkedconst long period = 1000; // period at which to blink in msvoid setup() { pinMode(ledPin, OUTPUT); // set ledpin as output}void loop() { unsigned long currentMillis = millis(); // store the current time if (currentMillis - previousMillis >= period) { // check if 1000ms passed previousMillis = currentMillis; // save the last time you blinked the LED if (ledState == LOW) { // if the LED is off turn it on and vice-versa ledState = HIGH; } else {ledState = LOW;} digitalWrite(ledPin, ledState);//set LED with ledState to blink again }}

Ici, l’instruction < if(currentMillis-previousMillis >=period) > vérifie si les 1000 ms sont passés. Si 1000 ms est passé, la LED clignote et revient au même état. Et ça continue. Ça y est, nous avons appris à utiliser millis au lieu de delay. De cette façon, il n’arrêtera pas le programme pour un intervalle particulier.

Les interruptions dans Arduino fonctionnent de la même manière que dans les autres microcontrôleurs. La carte Arduino UNO dispose de deux broches séparées pour fixer les interruptions sur les broches GPIO 2 et 3. Nous l’avons couvert en détail dans le tutoriel sur les interruptions Arduino, où vous pouvez en savoir plus sur les interruptions et comment les utiliser.

Ici, nous montrerons le multitâche Arduino en gérant deux tâches en même temps. Les tâches comprendront le clignotement de deux LED dans un délai différent avec un bouton-poussoir qui sera utilisé pour contrôler l’état MARCHE / ARRÊT de la LED. Ainsi, trois tâches seront effectuées simultanément.

Schéma de circuit pour le Multitâche Arduino

Composants requis

  • Arduino UNO
  • Trois LED (Toutes couleurs)
  • Résistances (470, 10k)
  • Cavaliers
  • Planche à pain

Schéma de circuit

Le schéma de circuit pour démontrer l’utilisation de la fonction Arduino Millis() est très facile et n’a pas beaucoup de composants à attacher comme indiqué ci-dessous.

Schéma de circuit pour le multitâche Arduino utilisant la fonction Arduino Millis()

Programmation Arduino UNO pour le multitâche

La programmation Arduino UNO pour le multitâche ne nécessitera que la logique derrière le fonctionnement de millis() qui est expliquée ci-dessus. Il est recommandé de pratiquer la LED clignotante en utilisant millis encore et encore pour clarifier la logique et vous mettre à l’aise avec millis() avant de commencer à programmer Arduino UNO pour le multitâche. Dans ce tutoriel, l’interruption est également utilisée avec millis() simultanément pour le multitâche. Le bouton sera une interruption. Ainsi, chaque fois qu’une interruption est générée, c’est-à-dire qu’un bouton-poussoir est enfoncé, la LED passe à l’état ON ou OFF.

La programmation commence par la déclaration des numéros de broches où les LED et le bouton-poussoir sont connectés.

int led1 = 6;int led2 = 7;int toggleLed = 5;int pushButton = 2;

Ensuite, nous écrivons une variable pour stocker l’état des LED pour une utilisation future.

int ledState1 = LOW;int ledState2 = LOW;

Comme expliqué ci-dessus dans l’exemple de clignotement, les variables de period et previousmillis sont déclarées pour comparer et générer un délai pour les LED. La première LED clignote toutes les 1 secondes et une autre LED clignote après 200 ms.

unsigned long previousMillis1 = 0; const long period1 = 1000;unsigned long previousMillis2 = 0;const long period2 = 200; 

Une autre fonction millis sera utilisée pour générer le délai de décollage afin d’éviter les multiples pressions sur le bouton-poussoir. Il y aura une approche similaire à celle ci-dessus.

int debouncePeriod = 20; int debounceMillis = 0;

Les trois variables seront utilisées pour stocker l’état du bouton-poussoir en tant qu’interruption, DEL à bascule et état du bouton-poussoir.

bool buttonPushed = false;int ledChange = LOW; int lastState = HIGH;

Définissez l’action de la broche sur laquelle la broche fonctionnera en ENTRÉE ou en SORTIE.

 pinMode(led1, OUTPUT); pinMode(led2, OUTPUT); pinMode(toggleLed, OUTPUT); pinMode(pushButton, INPUT);

Définissez maintenant la broche d’interruption en attachant l’interruption avec la définition de l’ISR et du mode d’interruption. Notez qu’il est recommandé d’utiliser digitalPinToInterrupt(pin_number) lors de la déclaration de la fonction attachInterrupt() pour traduire le code pin numérique réel en numéro d’interruption spécifique.

attachInterrupt(digitalPinToInterrupt(pushButton), pushButton_ISR, CHANGE); 

Le sous-programme d’interruption est écrit et ne changera que l’indicateur boutonné. Notez que le sous-programme d’interruption doit être aussi court que possible, alors essayez de l’écrire et de minimiser les instructions supplémentaires.

void pushButton_ISR(){ buttonPushed = true; }

La boucle commence par stocker la valeur millis dans une variable currentMillis qui stockera la valeur du temps écoulé à chaque itération de la boucle.

unsigned long currentMillis = millis();

Il y a au total trois fonctions en multitâche, clignotent une LED à 1 seconde, Clignotent une deuxième LED à 200 ms et Si le bouton-poussoir est enfoncé, éteignez / allumez la LED. Nous allons donc écrire trois parties pour faire cette tâche.

La première bascule l’état de la LED toutes les 1 seconde en comparant les millièmes écoulés.

 if (currentMillis - previousMillis1 >= period1) { previousMillis1 = currentMillis; if (ledState1 == LOW) { ledState1 = HIGH; } else { ledState1 = LOW; } digitalWrite(led1, ledState1); }

De même, la seconde bascule la LED toutes les 200 ms en comparant les millièmes écoulés. L’explication est déjà expliquée plus tôt dans cet article.

 if (currentMillis - previousMillis2 >= period2) { previousMillis2 = currentMillis; if (ledState2 == LOW) { ledState2 = HIGH; } else { ledState2 = LOW; } digitalWrite(led2, ledState2); }

Enfin, le drapeau boutonné est surveillé et après avoir généré un retard de debounce de 20 ms, il bascule simplement l’état de la LED correspond au bouton poussoir attaché comme interruption.

 if (buttonPushed = true) // check if ISR is called { if ((currentMillis - debounceMillis) > debouncePeriod && buttonPushed) // generate 20ms debounce delay to avoid multiple presses { debounceMillis = currentMillis; // save the last debounce delay time if (digitalRead(pushButton) == LOW && lastState == HIGH) // change the led after push button is pressed { ledChange = ! ledChange; digitalWrite(toggleLed, ledChange); lastState = LOW; } else if (digitalRead(pushButton) == HIGH && lastState == LOW) { lastState = HIGH; } buttonPushed = false; } }

Ceci termine le tutoriel Arduino millis(). Notez que pour devenir habituel avec millis(), entraînez-vous simplement à implémenter cette logique dans d’autres applications. Vous pouvez également l’étendre pour utiliser des moteurs, des servomoteurs, des capteurs et d’autres périphériques. En cas de doute, veuillez écrire sur notre forum ou commenter ci-dessous.

Le code complet et la vidéo pour démontrer l’utilisation de la fonction millis dans Arduino sont fournis ci-dessous.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.