delay() Fonction Arduino : Boucles serrées et code de blocage
Vous avez déjà fait un projet Arudino et vous voulez que quelque chose se produise à un intervalle minuté ? Peut-être que toutes les 3 secondes vous voulez qu’un servo se déplace, ou peut-être que toutes les 1 minute vous voulez envoyer une mise à jour de statut à un serveur web.
Comment faites-vous cela ? Existe-t-il une fonction simple et directe qui nous aide à le faire ? Oui, il y en a une ! Nous allons discuter de la fonction delay, ainsi que de la fonction millis(), dans la vidéo ci-dessous :
C’est la partie 2 de notre mini-série sur la fonction millis(). La partie 1 nous aide à comprendre ce que fait la fonction millis(), la partie 2 traite des boucles serrées et du code bloquant, et la partie 3 aborde les cas où la fonction millis() surpasse la fonction delay().
Thèmes de cette leçon
- Boucles serrées
- Code bloquant
- Recette ancienne pour une musique inspirante
Millis() versus Delay()
Donc, vous voulez que quelque chose se produise à un intervalle défini et vous cherchez une solution. Si votre réponse est d’utiliser la fonction retard, eh bien, vous avez en quelque sorte raison. Mais il y a une autre façon.
L’option plus cool et plus snazzier est la fonction Arduino millis(). Et plus vous êtes familier avec l’utilisation de la fonction millis, pour vous aider à chronométrer les événements dans votre code Arduino, plus il sera facile d’incorporer d’autres parties dans votre programme plus tard.
Une fois que vous commencerez à utiliser la fonction millis(), vous serez plus heureux, plus gai, et bon sang, les gens vous aimeront.
Les boucles serrées
Discutons d’abord du concept de boucle serrée. Et quand nous disons une boucle serrée, qu’est-ce que cela signifie ?
Regardons un sketch Arduino pour une démonstration d’une boucle serrée. En commençant par le sketch le plus basique, nous n’avons que deux fonctions : void setup, et void loop. Et comme vous le savez peut-être, void setup ne s’exécute qu’une fois, puis il passe le relais à void loop.
Void loop passe ensuite en revue chaque ligne de code qui pourrait se trouver à l’intérieur de la boucle (à l’intérieur de ces crochets curly).
Il exécute la première ligne, puis il exécute la deuxième, puis la troisième, et ainsi de suite, jusqu’à ce qu’il arrive en bas. Et puis il retourne en haut.
À quelle vitesse exécute-t-il la boucle ? Cela dépend de la carte Arduino que vous utilisez, mais une Arduino Uno a une vitesse d’horloge de 16 mégahertz. Cela signifie donc que 16 millions d’instructions se produisent chaque seconde sur l’Arduino !
Chaque ligne de code n’est pas nécessairement une instruction. En fait, il est plus probable qu’il s’agisse de plusieurs instructions. Mais tout de même, c’est relativement rapide (le processeur de votre ordinateur fonctionne probablement à des vitesses de l’ordre du gigahertz… ce sont des milliards).
Donc, considéreriez-vous ce croquis vide comme une boucle serrée ? Définitivement, c’est aussi rapide et aussi serré que vous pouvez faire une boucle. Comme il n’y a rien à exécuter à l’intérieur de la boucle, le temps nécessaire pour parcourir l’esquisse est pratiquement nul. Dit autrement, l’intervalle entre le début de la boucle et la fin est court (donc il est rapide, ou « serré »).
Ajoutons quelques lignes de code. Nous allons démarrer la communication série, puis imprimer quelque chose dans la fenêtre du moniteur série.
Est-ce une boucle serrée ? C’est-à-dire, du début de la boucle à la fin de la boucle, cela prend-il beaucoup de temps ? Cela prend très peu de temps, donc c’est une boucle rapide et serrée.
Il faut cependant noter que cette boucle n’est pas aussi serrée que l’exemple précédent. Dans l’exemple précédent, nous n’avions pas de code. Donc, c’était juste une course à travers la boucle. Maintenant que nous avons une fonction ici, serial print, cela prendra (un tout petit) peu de temps pour imprimer « Ice Ice Baby » à serial monitor.
Mais c’est encore une boucle assez rapide. Donc ajoutons un peu plus de code. Nous allons demander au programme de vérifier si un bouton est pressé, et si c’est le cas, nous aurons quelque chose de nouveau envoyé au moniteur série
Donc nous avons déclaré un bouton et utilisé une instruction if pour vérifier et voir si le bouton a été pressé. La tension sur la broche 5 est-elle élevée ? Si oui, alors nous imprimons quelque chose d’autre sur la fenêtre du moniteur série.
C’est une boucle serrée ? Donc, du début de la boucle, à la fin de la boucle, est-ce assez rapide ?
Oui, c’est encore assez rapide. C’est une boucle assez serrée. Nous avons 4 lignes de code. Nous imprimons sur le moniteur série, et puis nous faisons une vérification rapide pour voir si un bouton est pressé. Et si c’est le cas, nous imprimons quelque chose. Toujours serré, toujours rapide.
Puis ajoutons un délai à ce programme en utilisant la fonction Arduino delay(). Vous pouvez voir ci-dessous que nous avons ajouté un retard de mille millisecondes (1 seconde) à la boucle.
Est-ce toujours une boucle serrée ? Est-ce que le temps, entre le début de la boucle et la fin de la boucle, est beaucoup de temps ? Non, ce n’est définitivement pas une boucle serrée. Le code commence rapidement, nous faisons l’impression en série, mais ensuite nous sommes arrêtés juste là à la fonction de retard.
Le programme entier s’arrête pendant que nous attendons que ce code de retard se termine.
Quand l’Arduino arrive à cette ligne de code, c’est un peu comme aller à l’épicerie. Vous entrez dans la ligne des 12 articles ou moins, mais ensuite le gars devant vous sort son chéquier, et commence à écrire un chèque. Vous savez que vous allez être là pendant une minute. C’est la même chose ici.
Ce n’est donc pas une boucle serrée. Le temps entre le début et la fin de la boucle est assez important. Surtout par rapport aux deux derniers programmes. L’ordre de grandeur du temps est énorme.
Maintenant, ce que nous avons essayé de démontrer ici est que toute cette idée de boucles serrées est relative. Tout dépend de votre application. Si vous avez besoin de vérifier l’état d’un capteur tous les 10 millionièmes de seconde, alors un programme qui a trois lignes de code peut ne pas être assez serré, cela dépend simplement.
Un autre point à souligner est que toutes les lignes de code ne prennent pas le même temps pour s’exécuter. Si vous appelez une fonction qui fait un tas de choses, comme l’impression en série par exemple, alors cette seule ligne de code peut prendre beaucoup plus de temps que 10 autres lignes de code.
Donc la rigueur d’une boucle est une idée relative.
Code bloquant
Quand un programme s’arrête à un certain point, et prend un certain temps pour exécuter un certain code, ce code peut être appelé code bloquant. C’est un terme général.
Dans notre programme, nous avons la fonction delay qui agit comme un code bloquant. Aucun des codes après le délai ne peut s’exécuter jusqu’à ce que le délai soit terminé, donc il se bloque.
Le code bloquant n’est cependant pas seulement lorsque nous utilisons la fonction delay().
Reprenons notre programme et débarrassons-nous du délai, mais nous allons ajouter une boucle for. Notre boucle for va imprimer des nombres et du texte sur le port série.
Alors, combien de temps cette boucle va-t-elle tourner ? Elle va fonctionner pendant un certain temps car elle doit passer par 100 itérations avant de s’arrêter.
Et qu’en est-il du code après cette boucle for ? Peut-il s’exécuter ? Non, il doit attendre car il est bloqué par la boucle for.
Cette boucle for est imbriquée dans la boucle principale. La boucle for est-elle une boucle « serrée » ? Avant de répondre, soulignons à nouveau comment vous devez y penser : est-ce que cela prend beaucoup de temps de parcourir cette boucle for, de haut en bas ?
Eh bien, pas vraiment. Il n’y a que deux lignes de code. Donc c’est une boucle assez serrée.
Mais c’est une boucle serrée qui doit passer par beaucoup d’itérations avant que le programme puisse arriver au code en dessous. Donc, même une boucle serrée, si elle est forcée de passer par plusieurs itérations, peut bloquer notre code.
Plus sur la fonction delay()
Parlons un peu plus de cette fonction delay. Qu’avons-nous établi jusqu’à présent ?
D’abord, nous avons dit que la fonction delay diminue l’étanchéité d’une boucle. Si vous avez une boucle serrée et que vous ajoutez la fonction de retard, cela va prendre plus de temps et la rendre moins serrée. C’est-à-dire que le temps qu’il faut pour aller du début de la boucle au bas, va augmenter avec la fonction de retard.
Nous savons aussi que la fonction de retard bloque le code. Cela va de pair avec ce que nous venons de dire. Lorsque la fonction de délai est en cours d’exécution, elle bloque l’exécution d’autres codes pendant qu’elle retarde.
Vous pourriez penser que cette fonction de délai est un total fainéant ! Elle ne servira jamais à rien dans nos projets. Mais pour beaucoup de programmes simples que nous écrivons, la fonction delay fonctionne fantastiquement. Elle est simple à utiliser, elle est vraiment facile à épeler et elle fait exactement ce qu’elle dit.
Donc nous ne devrions pas nécessairement ostraciser la fonction delay() de notre boîte à outils de programmation. Nous devrions juste reconnaître que c’est une fonction de programmation simple qui peut fonctionner dans de nombreux cas.
Il y a un moment où vous commencez à rencontrer des problèmes, cependant. Cela a à voir avec l’effet de blocage que la fonction de délai a dans notre programme.
Dans la prochaine leçon de la série, la partie 3, nous allons identifier où cela devient vraiment un problème. Vous apprendrez quand il est judicieux d’utiliser la fonction delay() dans un programme, et quand il est temps de passer à l’utilisation de la fonction millis().
Review
D’abord, nous avons parlé de l’étanchéité d’une boucle. Nous avons dit que la rigueur d’une boucle est relative. Cela dépend de ce qu’est votre application.
Deuxièmement, nous avons parlé du code bloquant, ou du code qui bloque. Essentiellement, c’est un terme générique que nous pouvons donner au code qui va prendre un certain temps pour s’exécuter, et qui va empêcher les autres parties de notre programme de s’exécuter pendant qu’il s’exécute.
Nous espérons avoir apprécié cette leçon ! Dans la prochaine partie de cette série, nous allons continuer notre voyage en apprenant comment utiliser la fonction millis pour créer des événements minutés et répétitifs dans notre code Arduino. Nous vous verrons la prochaine fois !
.