C’est bien beau d’allumer une LED, mais si elle ne fait rien d’autre, ce n’est pas très utile. Autant la brancher directement sur une pile (avec une résistance tout de même ! ). Alors voyons comment rendre intéressante cette LED en la faisant clignoter ! Ce que ne sait pas faire une pile… Pour cela il va nous falloir introduire la notion de temps. Eh bien devinez quoi ? Il existe une fonction toute prête là encore ! Je ne vous en dis pas plus, passons à la pratique !
Sommaire
Comment faire ?
Trouver la commande…
Je vous laisse cherche un peu par vous-même, cela vous entrainera !
…
Pour ceux qui ont fait l’effort de chercher et n’ont pas trouvé (à cause de l’anglais ?), je vous donne la fonction qui va bien :
on va utiliser :
delay()
.
Petite description de la fonction : elle va servir à mettre en pause le programme pendant un temps prédéterminé.
Utiliser la commande
La fonction admet un paramètre qui est le temps pendant lequel on veut mettre en pause le programme. Ce temps doit être donné en millisecondes. C’est-à-dire que si vous voulez arrêter le programme pendant une seconde, il va falloir donner à la fonction ce même temps, écrit en millisecondes, soit 1000ms. La fonction est simple à utiliser :
// on fait une pause du programme pendant 1000ms, soit 1 seconde
delay(1000);
Rien de plus simple donc. Pour 20 secondes de pause, il aurait fallu écrire :
// on fait une pause du programme pendant 20000ms, soit 20 secondes
delay(20000);
Mettre en pratique : faire clignoter une LED
Du coup, si on veut faire clignoter notre LED, on peut utiliser cette fonction. Voyons un peu le schéma de principe du clignotement d’une LED :
Vous le voyez, la LED s’allume. Puis, on fait intervenir la fonction
delay()
, qui va mettre le programme en pause pendant un certain temps.
Ensuite, on éteint la LED. On met en pause le programme. Puis on revient au début du programme.
On recommence et ainsi de suite.
C’est cette suite de commandes qui forme le processus faisant clignoter la LED.
Dorénavant, prenez l’habitude de faire ce genre de schéma lorsque vous faites un programme. Cela aide grandement la réflexion, croyez moi ! C’est le principe de perdre du temps pour en gagner. Autrement dit : l' organisation !
Maintenant, il faut que l’on traduise ce schéma, portant le nom d' organigramme , en code.
Il suffit pour cela de remplacer les phrases dans chaque cadre par une ligne de code. Par exemple, "on allume la LED", va être traduit par l’instruction que l’on a vue dans le chapitre précédent :
digitalWrite(led_rouge, LOW); // allume la LED
Ensuite, on traduit le cadre suivant, ce qui donne :
// fait une pause de 1 seconde (= 1000ms)
delay(1000);
Puis, on traduit la ligne suivante :
// éteint la LED
digitalWrite(led_rouge, HIGH);
Enfin, la dernière ligne est identique à la deuxième, soit :
// fait une pause de 1 seconde
delay(1000);
On se retrouve avec le code suivant :
// allume la LED
digitalWrite(led_rouge, LOW);
// fait une pause de 1 seconde
delay(1000);
// éteint la LED
digitalWrite(led_rouge, HIGH);
// fait une pause de 1 seconde
delay(1000);
La fonction qui va boucler à l’infini le code précédent est la fonction
loop()
.
On inscrit donc le code précédent dans cette fonction :
void loop()
{
// allume la LED
digitalWrite(led_rouge, LOW);
// fait une pause de 1 seconde
delay(1000);
// éteint la LED
digitalWrite(led_rouge, HIGH);
// fait une pause de 1 seconde
delay(1000);
}
Et on n’oublie pas de définir la broche utilisée par la LED, ainsi que d’initialiser cette broche en tant que sortie. Cette fois, le code est terminé !
// définition de la broche 2 de la carte en tant que variable
const int led_rouge = 2;
// fonction d'initialisation de la carte
void setup()
{
// initialisation de la broche 2 comme étant une sortie
pinMode(led_rouge, OUTPUT);
}
void loop()
{
// allume la LED
digitalWrite(led_rouge, LOW);
// fait une pause de 1 seconde
delay(1000);
// éteint la LED
digitalWrite(led_rouge, HIGH);
// fait une pause de 1 seconde
delay(1000);
}
Vous n’avez plus qu’à charger le code dans la carte et admirer
mon
votre travail ! La LED clignote !
Libre à vous de changer le temps de clignotement : vous pouvez par exemple éteindre la LED pendant 40ms et l’allumer pendant 600ms :
// définition de la broche 2 de la carte en tant que variable
const int led_rouge = 2;
// fonction d'initialisation de la carte
void setup()
{
// initialisation de la broche 2 comme étant une sortie
pinMode(led_rouge, OUTPUT);
}
void loop()
{
// allume la LED
digitalWrite(led_rouge, LOW);
// fait une pause de 600 ms
delay(600);
// éteint la LED
digitalWrite(led_rouge, HIGH);
// fait une pause de 40 ms
delay(40);
}
Et hop, une petite vidéo d’illustration !
Voici aussi un exemple intégré dans le simulateur interactif pour que vous puissiez tester sans matériel :
Faire clignoter un groupe de LED
Vous avouerez facilement que ce n’était pas bien difficile d’arriver jusque-là. Alors, à présent, accentuons la difficulté. Notre but : faire clignoter un groupe de LED.
Le matériel et les schémas
Ce groupe de LED sera composé de six LED, nommées L1, L2, L3, L4, L5 et L6. Vous aurez par conséquent besoin d’un nombre identique de résistances. Le schéma de la réalisation :
Le programme
Le programme est un peu plus long que le précédent, car il ne s’agit plus d’allumer une seule LED, mais six ! Voilà l’organigramme que va suivre notre programme :
Cet organigramme n’est pas très beau, mais il a le mérite d’être assez lisible. Nous allons essayer de le suivre pour créer notre programme. Traduction des six premières instructions :
digitalWrite(L1, LOW); // notez que le nom de la broche a changé
digitalWrite(L2, LOW); // et ce pour toutes les LED connectées
digitalWrite(L3, LOW); // au micro-controleur
digitalWrite(L4, LOW);
digitalWrite(L5, LOW);
digitalWrite(L6, LOW);
Ensuite, on attend 1,5 seconde :
delay(1500);
Puis on traduit les six autres instructions :
digitalWrite(L1, HIGH); // on éteint les LED
digitalWrite(L2, HIGH);
digitalWrite(L3, HIGH);
digitalWrite(L4, HIGH);
digitalWrite(L5, HIGH);
digitalWrite(L6, HIGH);
Enfin, la dernière ligne de code, disons que nous attendrons 4,32 secondes :
delay(4320);
Tous ces bouts de code sont à mettre à la suite et dans la fonction
loop()
pour qu’ils se répètent.
Je l’ai mentionné dans un de mes commentaires entre les lignes du programme, les noms attribués aux broches sont à changer. En effet, car si on définit des noms de variables identiques, le compilateur n’aimera pas ça et vous affichera une erreur. En plus, le micro-contrôleur ne pourrait pas exécuter le programme car il ne saurait pas quelle broche mettre à l’état HAUT ou BAS. Pour définir les broches, on fait la même chose qu’à notre premier programme :
Maintenant que les broches utilisées sont définies, il faut dire si ce sont des entrées ou des sorties :
pinMode(L1, OUTPUT); // L1 est une broche de sortie
pinMode(L2, OUTPUT); // L2 est une broche de sortie
pinMode(L3, OUTPUT); // ...
pinMode(L4, OUTPUT);
pinMode(L5, OUTPUT);
pinMode(L6, OUTPUT);
Le programme final
Il n’est certes pas très beau, mais il fonctionne :
Voilà, vous avez en votre possession un magnifique clignotant, que vous pouvez attacher à votre vélo !
Une question me chiffonne. Doit-on toujours écrire l’état d’une sortie, ou peut-on faire plus simple ?
C’est là un un point intéressant.
Si je comprends bien, vous vous demandez comment faire pour remplacer l’intérieur de la fonction
loop()
?
C’est vrai que c’est très lourd à écrire et à lire ! Il faut en effet s’occuper de définir l’état de chaque LED.
C’est rébarbatif, surtout si vous en aviez mis autant qu’il y a de broches disponibles sur la carte !
Il y a une solution pour faire ce que vous dites. Nous allons la voir dans quelques chapitres, ne soyez pas impatient !
En attendant, voici une vidéo d’illustration du clignotement :
Et son illustration sur simulateur interactif :
Réaliser un chenillard
Le but du programme
Le but du programme que nous allons créer va consister à réaliser un chenillard. Pour ceux qui ne savent pas ce qu’est un chenillard, je vous ai préparé une petite image .gif animée :
Comme on dit souvent, une image vaut mieux qu’un long discours ! Voilà donc ce qu’est un chenillard. Chaque LED s’allume alternativement et dans l’ordre. De la gauche vers la droite ou l’inverse, c’est au choix.
Organigramme
Comme j’en ai marre de faire des dessins avec paint.net, je vous laisse réfléchir tout seuls comme des grands à l’organigramme du programme. … Bon, aller, le voilà cet organigramme ! Attention, il n’est pas complet, mais si vous avez compris le principe, le compléter ne vous posera pas de problèmes :
À vous de jouer !
Le programme
Normalement, sa conception ne devrait pas vous poser de problèmes. Il suffit en effet de récupérer le code du programme précédent ("allumer un groupe de LED") et de le modifier en fonction de notre besoin. Ce code, je vous le donne, avec les commentaires qui vont bien :
Vous le voyez, ce code est très lourd et n’est pas pratique. Nous verrons plus loin comment faire en sorte de l’alléger. Mais avant cela, un TP arrive… Au fait, voici un exemple de ce que vous pouvez obtenir !
En simulation ça donne ça :
Fonction millis()
Nous allons terminer ce chapitre par un point qui peut être utile, notamment dans certaines situations où l’on ne veut pas arrêter le programme.
En effet, si on veut faire clignoter une LED sans arrêter l’exécution du programme, on ne peut pas utiliser la fonction
delay()
qui met en pause le programme durant le temps défini.
Les limites de la fonction delay()
Vous avez probablement remarqué, lorsque vous utilisez la fonction
delay()
tout notre programme s’arrête le temps d’attendre.
Dans certains cas ce n’est pas un problème mais dans certains cas ça peut être plus gênant.
Imaginons, vous êtes en train de faire avancer un robot. Vous mettez vos moteurs à une vitesse moyenne, tranquille, jusqu’à ce qu’un petit bouton sur l’avant soit appuyé (il clic lorsqu’on touche un mur par exemple).
Pendant ce temps-là, vous décidez de faire des signaux en faisant clignoter vos LED.
Pour faire un joli clignotement, vous allumez une LED rouge pendant une seconde puis l’éteignez pendant une autre seconde.
Voilà par exemple ce qu’on pourrait faire comme code
void setup()
{
pinMode(moteur, OUTPUT);
pinMode(led, OUTPUT);
pinMode(bouton, INPUT);
// on met le moteur en marche (en admettant qu'il soit en marche à HIGH)
digitalWrite(moteur, HIGH);
// on allume la LED
digitalWrite(led, LOW);
}
void loop()
{
// si le bouton est cliqué (on rentre dans un mur)
if(digitalRead(bouton)==HIGH)
{
// on arrête le moteur
digitalWrite(moteur, LOW);
}
else // sinon on clignote
{
digitalWrite(led, HIGH);
delay(1000);
digitalWrite(led, LOW);
delay(1000);
}
}
Attention ce code n’est pas du tout rigoureux voire faux dans son écriture, il sert juste à comprendre le principe !
Maintenant imaginez. Vous roulez, tester que le bouton n’est pas appuyé, donc faites clignoter les LED (cas du
else
).
Le temps que vous fassiez l’affichage en entier s’écoule 2 longues secondes !
Le robot a pu pendant cette éternité se prendre le mur en pleine poire et les moteurs continuent à avancer tête baissée jusqu’à fumer !
Ce n’est pas bon du tout ! Voici pourquoi la fonction millis() peut nous sauver.
Découvrons et utilisons millis()
Tout d’abord, quelques précisions à son sujet, avant d’aller s’en servir. À l’intérieur du cœur de la carte Arduino se trouve un chronomètre. Ce chrono mesure l’écoulement du temps depuis le lancement de l’application. Sa granularité (la précision de son temps) est la milliseconde. La fonction millis() nous sert à savoir quelle est la valeur courante de ce compteur. Attention, comme ce compteur est capable de mesurer une durée allant jusqu’à 50 jours, la valeur retournée doit être stockée dans une variable de type "long".
C’est bien gentil mais concrètement on l’utilise comment ?
Eh bien c’est très simple. On sait maintenant "lire l’heure". Maintenant, au lieu de dire "allume-toi pendant une seconde et ne fais surtout rien pendant ce temps", on va faire un truc du genre "Allume-toi, fais tes petites affaires, vérifie l’heure de temps en temps et si une seconde est écoulée, alors réagis !". Voici le code précédent transformé selon la nouvelle philosophie :
Et voilà, grâce à cette astuce plus de fonction bloquante. L’état du bouton est vérifié très fréquemment ce qui permet de s’assurer que si jamais on rentre dans un mur, on coupe les moteurs très vite. Dans ce code, tout s’effectue de manière fréquente. En effet, on ne reste jamais bloqué à attendre que le temps passe. À la place, on avance dans le programme et teste souvent la valeur du chronomètre. Si cette valeur est de 1000 itérations supérieures à la dernière valeur mesurée, alors cela signifie qu’une seconde est passée.
Attention, au
if
de la ligne 25 ne faites surtout pas
millis() - temps == 1000
.
Cela signifierait que vous voulez vérifier que 1000 millisecondes EXACTEMENT se sont écoulées, ce qui est très peu probable (vous pourrez plus probablement mesurer plus ou moins mais rarement exactement)
Maintenant que vous savez maîtriser le temps, vos programmes/animations vont pouvoir posséder un peu plus de "vie" en faisant des pauses, des motifs, etc. Impressionnez-moi !