- Qu'est-ce que le multitâche?
- Pourquoi ignorer delay () dans Arduino?
- Pourquoi utiliser millis ()?
- Composants requis
- Schéma
- Programmation Arduino UNO pour le multitâche
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 ou plusieurs tâches simultanément sans interrompre les instructions actuelles.
Ici, dans ce didacticiel, 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 telle que le clignotement des LED, mais cette fonction delay () arrête le programme pendant un certain temps définitif et ne permet pas à d'autres opérations de s'exécuter. Donc, cet article explique comment nous pouvons éviter l'utilisation de la fonction delay () et la remplacer par millis () pour effectuer plus d'une tâche simultanément et faire de l'Arduino un contrôleur multitâche. Avant d'entrer dans les détails, commençons par comprendre le multitâche.
Qu'est-ce que le multitâche?
Le multitâche signifie simplement exécuter plusieurs tâches ou programmes simultanément. Presque tous les systèmes d'exploitation sont multitâches. Ce type de système d'exploitation est connu sous le nom de MOS (système d'exploitation multitâche). Le MOS peut être un système d'exploitation de PC mobile ou de bureau. Le bon exemple de 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, elle s'exécute en arrière-plan si elle n'est pas fermée. L'utilisateur final utilise toutes ces applications en même temps, mais le système d'exploitation prend ce concept un peu différemment. Discutons de la façon dont le système d'exploitation gère le multitâche.
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 le multitâche Arduino, sauf que la distribution 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 aucun projet.
Pourquoi ignorer 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 (), le paramètre entier passé est en millisecondes c'est à dire si on écrit delay (1000) alors le delay sera de 1000 millisecondes soit 1 seconde. De même dans la fonction delayMicroseconds (), le paramètre passé est en microsecondes c'est à dire si on écrit delayMicroseconds (1000), alors le délai sera de 1000 microsecondes soit 1 millisecondes.
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 1 seconde. 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 passer aux instructions suivantes avant que les 10 secondes ne se soient écoulées. Cela nuit aux 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érez que nous voulons basculer deux LED à l'aide de deux boutons poussoirs. Donc, si un bouton-poussoir est enfoncé, la LED correspondante doit briller pendant 2 secondes, de même si le second est enfoncé, la LED doit briller 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, alors 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 sa description de la fonction Notes et avertissements de delay (). Vous pouvez passer par et vérifier ceci pour le rendre plus clair.
Pourquoi utiliser millis ()?
Pour surmonter le problème causé par l'utilisation du délai, un développeur doit utiliser la fonction millis () qui est facile à utiliser une fois que vous devenez habituel et il utilisera 100% des performances du processeur sans générer de retard dans l'exécution des instructions. millis () est une fonction qui renvoie simplement le nombre 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 d'heure débordera (c'est-à-dire reviendra à zéro), après environ 50 jours.
Tout comme Arduino a 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, comparé à millis () qui est de 50 jours. Ainsi, selon l'application, vous pouvez utiliser millis () ou micros ().
Utilisation de millis () au lieu de delay ():
Pour utiliser le 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 si l'heure définie est passée. Ainsi, comme indiqué, stockez l'heure actuelle dans une variable.
non signé long currentMillis = millis ();
Nous avons besoin de deux autres variables pour savoir si le temps requis est écoulé. Nous avons stocké l'heure actuelle dans la variable currentMillis , mais nous devons également savoir que quand la période de temps a-t-elle commencé et quelle est la durée de la période. Ainsi, l'intervalle et le previousMillis sont déclarés. L'intervalle nous indiquera le délai et previosMillis enregistrera la dernière fois que l'événement s'est produit.
unsigned long previousMillis; longue période non signée = 1000;
Pour comprendre cela, prenons un exemple de simple LED clignotante. La période = 1000 nous dira que la LED clignotera pendant 1 seconde ou 1000 ms.
const int ledPin = 4; // le numéro de broche de la LED connectée int ledState = LOW; // utilisé pour définir l'état de la LED unsigned long previousMillis = 0; // stockera la dernière fois que la LED a clignoté const long period = 1000; // période à laquelle clignoter en ms void setup () { pinMode (ledPin, OUTPUT); // définit ledpin comme sortie } void loop () { unsigned long currentMillis = millis (); // stocke l'heure actuelle if (currentMillis - previousMillis> = period) {// vérifie si 1000ms sont passés previousMillis = currentMillis; // enregistre la dernière fois que vous avez fait clignoter la LED if (ledState == LOW) {// si la LED est éteinte, allumez-la et vice-versa ledState = HIGH; } else { ledState = LOW; } digitalWrite (ledPin, ledState); // régler la LED avec ledState pour qu'elle clignote à nouveau } }
Ici, la déclaration
Les interruptions dans Arduino fonctionnent de la même manière que dans les autres microcontrôleurs. La carte Arduino UNO a deux broches séparées pour attacher des interruptions sur les broches GPIO 2 et 3. Nous l'avons couvert en détail dans le didacticiel Arduino Interrupts, où vous pouvez en savoir plus sur les interruptions et comment les utiliser.
Ici, nous allons montrer Arduino Multitasking 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 ON / OFF de la LED. Donc, trois tâches seront effectuées simultanément.
Composants requis
- Arduino UNO
- Trois LED (n'importe quelle couleur)
- Résistances (470, 10k)
- Cavaliers
- Planche à pain
Schéma
Le schéma de circuit pour démontrer l'utilisation de la fonction Arduino Millis () est très simple et n'a pas beaucoup de composants à attacher comme indiqué ci-dessous.
Programmation Arduino UNO pour le multitâche
La programmation d'Arduino UNO pour le multitâche ne nécessitera que la logique du fonctionnement de millis () qui est expliquée ci-dessus. Il est recommandé de pratiquer encore et encore le clignotement de la LED en millis pour clarifier la logique et vous familiariser 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 que le 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;
Tout comme expliqué ci-dessus dans l'exemple de clignotement, les variables pour la période et les millis précédents sont déclarées pour comparer et générer un retard pour les LED. La première LED clignote toutes les 1 seconde et une autre LED clignote après 200 ms.
unsigned long previousMillis1 = 0; const longue période1 = 1000; unsigned long previousMillis2 = 0; const longue période2 = 200;
Une autre fonction millis sera utilisée pour générer le délai anti-rebond pour éviter les pressions multiples 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, LED à bascule et état du bouton poussoir.
bool buttonPushed = false; int ledChange = LOW; int lastState = HIGH;
Définissez l'action de la broche sur laquelle cette broche fonctionnera comme INPUT ou OUTPUT.
pinMode (led1, SORTIE); pinMode (led2, SORTIE); 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 la broche numérique réelle en numéro d'interruption spécifique.
attachInterrupt (digitalPinToInterrupt (pushButton), pushButton_ISR, CHANGE);
Le sous-programme d'interruption est écrit et il ne changera que l' indicateur buttonPushed. Notez que le sous-programme d'interruption doit être aussi court que possible, alors essayez de l'écrire et minimisez les instructions supplémentaires.
void pushButton_ISR () { buttonPushed = true; }
La boucle commence par stocker la valeur en millis dans une variable currentMillis qui stockera la valeur du temps écoulé à chaque itération de la boucle.
non signé long currentMillis = millis ();
Il y a au total trois fonctions en multitâche, faire clignoter une LED à 1 seconde, clignoter la deuxième LED à 200ms et si le bouton-poussoir est enfoncé, éteindre / allumer la LED. Nous allons donc écrire trois parties pour faire cette tâche.
La première consiste à basculer l'état de la LED après chaque seconde en comparant les millisecondes écoulées.
if (currentMillis - previousMillis1> = période1) { previousMillis1 = currentMillis; if (ledState1 == LOW) { ledState1 = HIGH; } else { ledState1 = LOW; } digitalWrite (led1, ledState1); }
De même, la seconde fait basculer la LED toutes les 200ms en comparant les millis écoulés. L'explication est déjà expliquée plus haut dans cet article.
if (currentMillis - previousMillis2> = période2) { previousMillis2 = currentMillis; if (ledState2 == LOW) { ledState2 = HIGH; } else { ledState2 = LOW; } digitalWrite (led2, ledState2); }
Enfin, le drapeau buttonPushed est surveillé et après avoir généré un délai anti-rebond de 20ms, il bascule simplement l'état de la LED correspondant au bouton-poussoir attaché comme interruption.
if (buttonPushed = true) // vérifier si l'ISR est appelé { if ((currentMillis - debounceMillis)> debouncePeriod && buttonPushed) // générer un délai anti-rebond de 20 ms pour éviter plusieurs pressions { debounceMillis = currentMillis; // sauvegarde le dernier temps de retard anti- rebond if (digitalRead (pushButton) == LOW && lastState == HIGH) // change la led après avoir appuyé sur le bouton poussoir { ledChange =! ledChange; digitalWrite (toggleLed, ledChange); lastState = LOW; } else if (digitalRead (pushButton) == HIGH && lastState == LOW) { lastState = HIGH; } buttonPushed = false; } }
Ceci termine le didacticiel 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.