Si vous n’avez jamais utilisé Arduino mais que vous avez l’envie de vous y mettre, cet article est fait pour vous puisqu’il montre, avec de nombreuses copies d’écran, comment réaliser un premier programme fonctionnel. Alors laissez-vous guider et vous découvrirez que la programmation d’Arduino n’est pas aussi compliquée que vous pouvez l’imaginer.
Arduino : toute première fois !
.
Par :
DIFFICULTÉ :★☆☆
Prérequis pour la lecture de cet article
Cet article s’adresse à ceux qui débutent vraiment. Présenté comme un tutoriel, il vous guide pas à pas pour découvrir et programmer un module Arduino ; à ce titre, il ne sera vraiment efficace que si vous réalisez les manipulations proposées et pour cela, vous devez disposer d’un module Arduino UNO ou Genuino UNO et d’un câble USB de type A-B comme le montre la figure 1.
Il ne vous faut rien d’autre que ces deux éléments ; nous vous conseillons d’acheter un module d’origine Arduino ou Genuino et non un clone d’origine asiatique qui pourrait présenter des petites différences dans son fonctionnement. De même, avant d’acheter le câble USB, regardez si vous n’en avez pas déjà un : ce genre de câble accompagne les lecteurs multimédia externes comme les disques durs, les lecteurs ou graveurs DVD, bluray, etc.
Il faut également que vous ayez installé sur votre ordinateur le logiciel qui permet de programmer des modules (ou cartes) Arduino ; ce logiciel s’appelle IDE (pour Integrated Development Environment) et son installation est expliquée en détails dans l’article Installation de l’IDE Arduino.
Aucune connaissance concernant Arduino n’est nécessaire puisque nous allons découvrir ensemble ce bijou de technologie. Néanmoins, pour pouvoir être à l’aise dans ce tutoriel, vous devez connaître les fonctions de base de votre ordinateur, à savoir :
- Ouvrir et exécuter un programme.
- Redimensionner une fenêtre en grand.
- Fermer une fenêtre.
- Savoir utiliser la souris (clic gauche – clic droit).
- Comprendre comment utiliser une arborescence de menus (menus et sous-menus).
De la même façon, écrire un programme pour Arduino revient à écrire un texte. Il est donc recommandé de savoir faire les manipulations de base comme :
- Positionner le curseur à un endroit précis du texte (avec la souris).
- Sélectionner une portion de texte.
- Supprimer ce qui a été sélectionné.
- Couper ce qui a été sélectionné.
- Copier ce qui a été sélectionné.
- Coller ce qui a été coupé ou copié à un autre endroit précis du texte.
Il faut donc maîtriser ce qu’on appelle le « couper-copier-coller » ; si vous n’êtes pas à l’aise dans ce domaine, demandez à quelqu’un de vous montrer car c’est très simple et cela vous servira dans d’autres logiciels.
J’en profite pour vous faire remarquer la différence entre supprimer et couper :
- Supprimer : le texte sélectionné disparaît et est définitivement perdu.
- Couper : le texte sélectionné disparaît mais est stocké dans le presse-papier. Il n’est donc pas perdu (sauf si on met autre chose dans le presse-papier ou qu’on ferme le programme) et on peut le récupérer avec la fonction « coller ».
Utiliser « couper » plutôt que « supprimer » vous évitera de faire des bêtises. Une fois le texte sélectionné, les fonctions « couper-copier-coller » sont accessibles avec un clic droit de la souris ou bien par un raccourci clavier (plusieurs touches manipulées ensemble) : il est intéressant de connaître les deux techniques.
Si vous ne savez pas où commander votre matériel, vous pouvez toujours consulter l’article Où acheter ? et en attendant qu’il arrive, lire l’article Conférence sur Arduino faite à Trainsmania (avril 2017) pour découvrir ce qu’il est possible de faire avec un Arduino dans le domaine du modélisme ferroviaire, histoire de vous mettre l’eau à la bouche.
Voilà, nous sommes prêts pour commencer ensemble ce tutoriel. L’article est trop long pour être lu en une seule fois ; étudiez-le par morceaux en étant certains d’avoir bien compris avant de passer à la suite. Le tutoriel est proposé pour un environnement Windows ; si vous êtes sous Mac OS ou bien Linux, c’est quasiment la même chose et les petites différences sont décrites dans les articles Bien utiliser l’IDE d’Arduino (1) et Bien utiliser l’IDE d’Arduino (2).
Structure d’un programme pour Arduino
Lancez le programme IDE en cliquant ou double-cliquant sur son icône (figure 2) ; vous obtenez une fenêtre semblable à la figure 3.
Selon votre environnement, cliquez sur le bouton permettant d’afficher la fenêtre en grand (voir figure 3) : la fenêtre ne change pas, elle est simplement plus grande ce qui est plus confortable pour travailler.
La zone encadrée en rouge dans la figure 3 est la zone où nous écrirons nos programmes. On constate qu’elle n’est pas vide mais constituée de deux fonctions :
- La fonction setup (entourée en vert).
- La fonction loop (entourée en bleu).
Vous remarquerez que les lignes sont numérotées sur la gauche ; si ce n’est pas le cas pour vous, aller dans le menu Fichier > Préférences (ou Arduino > Préférences sous Mac) et cocher la case « Afficher les numéros de lignes » comme le montre la figure 4.
Les deux fonctions setup et loop sont obligatoires pour tout programme Arduino et c’est pourquoi elles sont proposées dès l’ouverture du logiciel ou d’un nouveau programme ; il n’y a plus qu’à les compléter en écrivant les instructions à exécuter les unes à la suite des autres, instructions qu’il faut placer dans l’espace compris entre l’accolade ouvrante et l’accolade fermante (voir figure 3). Ceci est rappelé par les lignes de commentaires qui disent en anglais « Insérez ici le code du setup pour l’exécuter une fois » ou bien « Insérez ici le code du programme pour l’exécuter de façon répétitive ». Un commentaire se reconnaît parce qu’il commence par un double slash // ; on peut en mettre autant qu’on veut puisque le compilateur (programme qui traduit ce qu’on écrit en code compréhensible par le microcontrôleur) ignore tous les caractères depuis le double slash // jusqu’au prochain caractère « Retour à la ligne ». Ne vous inquiétez pas, nous reviendrons en détail sur tout cela. Sur la figure 3, le commentaire dans la fonction loop est entouré en jaune.
Toutes les instructions que vous mettrez dans la fonction setup seront exécutées une seule fois ; la fonction setup sert en général à initialiser les entrées-sorties (E/S) du module Arduino, avant d’exécuter le programme.
Toutes les instructions que vous mettrez dans la fonction loop seront exécutées en boucle (de façon répétitive) jusqu’à ce qu’on coupe le courant sur le module Arduino. C’est donc dans la fonction loop en général qu’on place les instructions du programme principal.
Donc à l’ouverture d’un nouveau programme, on obtient une fonction setup et une fonction loop, toutes deux vides d’instruction ; ceci constitue le programme minimum pour un module Arduino mais sans instruction, ce programme ne fait absolument rien. Nous allons vérifier cela. Vérifiez le programme en cliquant sur le bouton « vérifier », comme le montre la figure 5. Le compilateur vérifie alors qu’il n’y a pas d’erreur de syntaxe dans l’écriture du programme et que toutes les variables ont bien été déclarées, ainsi que les fonctions utilisées, bref que tout est en ordre pour traduire ce programme en code compréhensible par le microcontrôleur. Si tout se passe bien, on obtient un message qui indique que le programme occupe tant d’octets de la place mémoire réservée pour le programme ainsi que tant d’octets de la place mémoire réservée pour les variables (l’octet étant en quelque sorte l’unité de place mémoire). Si cela se passe mal, vous obtenez un beau message d’erreur. La figure 5 montre que la compilation s’est bien terminée et que le programme occupe 444 octets en mémoire de programme et 9 octets de mémoire de données.
Sélectionnez maintenant tout ce qui concerne la fonction setup comme indiqué sur la figure 6 et supprimez ce qui est sélectionné (donc la fonction setup).
Revérifiez à nouveau votre programme sans fonction setup. Vous obtenez un message d’erreur comme on le voit sur la figure 7 : Erreur de compilation pour la carte Arduino/Genuino UNO. Le compilateur n’est pas content de n’avoir pas trouvé la fonction setup. Cela aurait donné un résultat identique si vous aviez supprimé la fonction loop au lieu de setup, ce qui est bien la preuve que ces deux fonctions sont obligatoires.
Écrire un programme consiste à compléter les fonctions setup et loop par une suite d’instructions afin d’indiquer au microcontrôleur du module Arduino ce qu’il doit faire et surtout comment il doit le faire. Pour bien comprendre cela, nous allons prendre un exemple très simple mais qui a son utilité sur un réseau de trains miniatures.
Faire clignoter une ampoule
Imaginez que vous vouliez faire clignoter une ampoule dans votre appartement (plafonnier, lampadaire, lampe de chevet, peu importe) : comment vous y prendriez-vous ? Écrivons une procédure qui résume les actions à faire :
- Allumer l’ampoule (en manipulant l’interrupteur).
- Attendre un certain délai.
- Éteindre l’ampoule (en manipulant l’interrupteur).
- Attendre un certain délai.
- Recommencez à partir de 1 tant que vous voulez que l’ampoule clignote.
Pour l’instant, nous n’avons écrit aucun programme mais nous avons fait un travail d’analyse qui a consisté à décomposer la tâche à réaliser (faire clignoter l’ampoule) en une suite de tâches élémentaires. Ce travail d’analyse ne doit pas être négligé ; il ne faut rien oublier. S’il est bien fait, l’écriture du programme avec les instructions sera facilitée et le programme fonctionnera du premier coup. Trop souvent les amateurs se placent devant leur ordinateur et écrivent des lignes d’instructions (appelées lignes de code) puis essaient leur programme et devant les dysfonctionnements, reprennent les lignes de code pour ajouter une rustine, par ci, par là ; ce n’est pas la bonne méthode ! L’écriture d’un programme commence par un travail d’analyse sur ce qu’il faut faire et comment le faire (en gros, 80% du temps de réflexion), ensuite seulement, on traduit ce travail en instructions (les 20% restants du temps de travail). Écrire un programme se fait d’avantage avec un stylo et un bloc de papier plutôt qu’avec un ordinateur !
Commentons notre travail d’analyse :
- Allumer l’ampoule en manipulant l’interrupteur revient à établir une tension aux bornes de l’ampoule, ce qui permettra à un courant de traverser l’ampoule qui se mettra à éclairer.
- Attendre se passe de commentaires à la condition de savoir combien de temps il faut attendre.
- Éteindre l’ampoule en manipulant l’interrupteur revient à couper la tension d’alimentation de notre ampoule, coupant ainsi le courant qui la traverse, ce qui fait que l’ampoule ne brille plus.
- Recommencer les opérations revient à parcourir en boucle les instructions.
Les quatre premières instructions constituent un cycle d’allumage-extinction et ce cycle est répété pour faire clignoter l’ampoule. La période du cycle est la somme du temps où l’ampoule est allumée et du temps où elle est éteinte (on prend pour hypothèse que le passage de l’état allumé à l’état éteint et réciproquement est instantané : ce n’est pas tout à fait exact mais ce temps est négligeable devant les temps où l’ampoule est allumée ou éteinte). La fréquence du cycle est l’inverse de la période, soit encore f = 1 / P.
Faire clignoter la DEL du module UNO
Le module UNO est livré avec une DEL (diode électroluminescente) reliée à une broche du microcontrôleur : nous allons profiter du travail d’analyse effectué au paragraphe précédent pour faire clignoter cette DEL. Plutôt qu’écrire un programme nous-même, nous allons utiliser un programme déjà écrit et donné en exemple : le programme « Blink » (blink signifie clignoter en anglais). Cliquez sur le menu Fichier puis naviguez dans les sous-menus pour atteindre Blink (Fichier > Exemples > 01.Basics > Blink) comme le montre la figure 8.
Une nouvelle fenêtre s’ouvre comportant le programme Blink comme le montre la figure 9. Agrandissez la comme vous savez le faire, ce sera plus confortable ; c’est maintenant dans cette fenêtre que nous allons travailler.
Le module UNO possède 14 entrées-sorties (E/S) dites numériques, numérotées de 0 à 13 (en informatique, on utilise le chiffre 0 puisqu’il a le mérite d’exister, et plutôt que numéroter les 14 E/S de 1 à 14, on les numérote à partir de 0, donc de 0 à 13 ; il faudra vous y habituer !). La DEL que nous voulons faire clignoter est reliée par construction à l’E/S numérotée 13 : cette DEL est appelée LED_BUILTIN (LED en anglais pour Light Emitting Diode et BUILTIN qui signifie implantée par construction sur le module), nom que connaît le compilateur qui sait que cela concerne l’E/S 13.
Entrée ou sortie, il faut choisir.
Une E/S numérique de module Arduino doit être utilisée soit en tant qu’entrée, soit en tant que sortie mais il faut faire ce choix avant de l’utiliser. Pour savoir si c’est une entrée ou une sortie, il faut raisonner en tant que transfert d’information. Le programme que nous étudions permet au microcontrôleur du module UNO d’allumer ou d’éteindre une DEL. L’état de la DEL (allumée ou éteinte) est une information que le microcontrôleur a sortie de lui pour la délivrer au milieu extérieur et cette information peut être vue de toute personne du milieu extérieur (il suffit de regarder la DEL). Cette information a transité par une broche du microcontrôleur pour sortir vers le milieu extérieur, donc la broche est une sortie.
Prenons un autre exemple, celui d’un interrupteur extérieur au microcontrôleur mais relié à celui-ci par l’intermédiaire d’une de ses broches. L’état de l’interrupteur (ouvert ou fermé) est une information que le microcontrôleur peut connaître et cette information transite depuis le milieu extérieur pour parvenir au microcontrôleur par l’intermédiaire d’une de ses broches qui est donc une entrée.
Dans les deux cas, nous avons raisonné en terme d’information transitant par la broche, pour savoir si elle entre ou sort du microcontrôleur. Nous verrons à la fin de cet article qu’on ne peut pas raisonner en considérant le sens du courant délivré par la broche, qu’il entre ou qu’il sorte de la broche.
La broche, l’E/S qui est reliée à la DEL doit donc être une sortie ; il faut que le microcontrôleur adapte cette broche en tant que sortie et c’est ce que réalise l’instruction comportant la fonction pinMode qui est entourée en bleu dans la figure 10 ; cette instruction figure dans la fonction setup car elle n’a besoin d’être exécutée qu’une seule fois, avant que la procédure de clignotement démarre.
Notre initialisation a consisté en :
pinMode(LED_BUILTIN, OUTPUT) ;
pinMode est la fonction qui permet de choisir entre une entrée ou une sortie. Respectez la casse (minuscule/majuscule) et les parenthèses qui suivent.
LED_BUILTIN désigne la broche 13 sur laquelle est reliée la DEL.
OUTPUT signifie sortie en anglais (c’est bien ce qu’on veut).
Les espaces et les caractères de tabulations sont ignorés par le compilateur ; on peut donc en rajouter avant ou après les parenthèses mais pas au milieu de noms comme LED_BUILTIN ou OUTPUT. On peut donc écrire pinMode(LED_BUILTIN,OUTPUT);
ou bien pinMode (LED_BUILTIN, OUTPUT) ;
(la deuxième formulation se lit mieux).
Remarquez bien le point-virgule en fin d’instruction car sa présence est obligatoire et son absence entraînerait un message d’erreur de la part du compilateur lors de la vérification.
La DEL étant reliée à la sortie 13, on aurait pu écrire :
pinMode (13, OUTPUT) ;
mais cela aurait été moins bien car notre programme n’aurait pas fonctionné sur un module différent du module UNO où la DEL serait reliée à une sortie autre que la sortie 13. En utilisant LED_BUILTIN, c’est le compilateur qui se charge d’utiliser le bon numéro de sortie en fonction du module utilisé.
La procédure jouée en boucle
Notre travail d’analyse nous a fourni une procédure qui doit être jouée en boucle. Nous allons la traduire en instructions que nous placerons dans la fonction loop exécutée en boucle. Comme nous l’avons vu, allumer une ampoule ou une DEL consiste à établir une tension et éteindre l’ampoule ou la DEL consiste à couper cette tension. Or, il existe une fonction qui permet d’appliquer sur une sortie numérique soit une tension de 5 V (le haut niveau repéré par HIGH), soit une tension de 0 V (le bas niveau repéré par LOW), ce qui revient au même que couper la tension. Cette fonction est la fonction digitalWrite (respectez la casse et les parenthèses).
L’instruction
digitalWrite(LED_BUILTIN, HIGH) ;
établit une tension de 5 V (HIGH) sur la broche 13 (LED_BUILTIN), donc allume la DEL.
L’instruction
digitalWrite(LED_BUILTIN, LOW) ;
établit une tension de 0 V (LOW) sur la broche 13 (LED_BUILTIN), donc éteint la DEL.
Après chacune de ces actions, la procédure nous demande d’attendre un certain temps, ce qui est réalisé par la fonction delay où le temps d’attente est précisé entre parenthèses en millisecondes : dans ce programme, l’attente est de 1000 ms soit une seconde.
Le programme Blink fait donc clignoter la DEL en l’allumant une seconde et en l’éteignant une seconde et ainsi de suite. La période est de deux secondes et la fréquence de 0,5 Hz (= 1/2). Nous n’avons rien modifié de ce programme, il va donc fonctionner du premier coup. Cliquez sur le bouton « vérifier » : tout se passe normalement et vous obtenez le message « Le croquis utilise 928 octets (2%) de l’espace de stockage de programmes. Le maximum est de 32256 octets. Les variables globales utilisent 9 octets (0%) de mémoire dynamique, ce qui laisse 2039 octets pour les variables locales. Le maximum est de 2048 octets. »
Raccordement du module UNO à l’ordinateur
Il est temps de raccorder votre module UNO à votre ordinateur avec le câble USB ; introduisez la prise B du câble (celle qui a un embout carré) dans la prise USB du module UNO (voir figure 11) et la prise A du câble (embout plat) à une sortie USB de votre ordinateur. Le module UNO est alimenté dès qu’il est branché en USB à un ordinateur et une DEL verte s’allume pour le signaler (voir figure 11).
La figure 12 montre que le module UNO a été détecté par l’ordinateur et qu’un port de communication lui a été affecté (ce doit être le cas si vous avez bien installé le logiciel et les pilotes comme cela est expliqué dans l’article Installation de l’IDE Arduino).
Nous allons maintenant téléverser le programme Blink dans le module UNO ou, ce qui revient au même, programmer le microcontrôleur du module UNO pour qu’il fasse clignoter la DEL. Avant cela, nous allons faire quelques vérifications dans le menu Outils : vérifiez que le type de carte est bien Arduino/Genuino UNO (sinon cochez la bonne option), vérifiez que le programmateur est bien AVRISP mkII (sinon changez pour celui-ci) et enfin vérifiez que le PORT série par lequel le logiciel va communiquer est bien le PORT qui a été affecté au module comme on peut le lire en bas à droite (sinon changer pour le bon port). Il est conseillé de faire ces trois vérifications avant chaque téléversement de programme. Ceci est résumé par la figure 13.
La figure 13 indique également sur quel bouton il faut cliquer pour téléverser le programme dans le module. Voici dans les grandes lignes ce qu’il se passe à ce moment. Le logiciel commence par faire une vérification du programme comme il l’aurait fait avec le bouton « vérifier » ; on voit une barre de progression qui se remplit en vert. Si tout est correct, le logiciel transforme le programme en code exécutable par le microcontrôleur et envoie ce code dans la mémoire programme du microcontrôleur. À ce moment, on voit clignoter rapidement les DEL Rx et Tx reliées aux broches 0 et 1 (voir figure 14), car c’est par ces broches que les données de programmation transitent. Lorsque ces DEL ne clignotent plus, le programme est téléversé et le logiciel vous l’indique par le message « Téléversement terminé » comme le montre la figure 15. On peut alors voir la DEL (LED_BUILTIN) clignoter en restant allumée une seconde puis éteinte une seconde.
Changer la fréquence de clignotement
Nous allons modifier le programme Blink pour que la DEL clignote plus rapidement. Il suffit de modifier les délais d’attente en remplaçant 1000 par 250 dans la fonction loop. La période sera d’une demi-seconde (0,5 s) et la fréquence sera de 2 Hz (= 1/0,5), la DEL clignotera quatre fois plus rapidement.
Lorsque les changements sont faits, enregistrez votre programme sous le nom « Blink_2Hz » avec Fichier > Enregistrer sous… comme le montre la figure 16. Téléversez votre nouveau programme dans votre module UNO et observez la DEL qui clignote quatre fois plus vite.
Changer la symétrie de clignotement
Jusque-là, le clignotement s’effectue avec une durée d’allumage de la DEL identique à sa durée d’extinction. Nous allons modifier le programme pour que la DEL émette des flashes. La durée d’allumage sera de 0,3 s (300 ms) et la durée d’extinction sera de 1,7 s (1700 ms), ce qui donne une période de 2 secondes (0,3 + 1,7) et donc une fréquence de 0,5 Hz.
Plutôt que remplacer les durées en chiffre dans le programme, nous allons créer deux variables :
- duree_allumage
- duree_extinction
Notez que je n’ai pas utilisé de caractères accentués dans mes noms de variables car ceux-ci ne sont pas acceptés pour nos programmes. L’espace, qui ne doit pas figurer au milieu d’un nom, a été remplacé par le caractère underscore, mais nous aurions aussi pu choisir dureeAllumage comme nom de variable où la majuscule se remarque bien.
Lorsqu’on crée une variable, il faut choisir un type de variable et un nom explicite. Le type de variable dépend de la donnée à stocker en mémoire et en fonction, utilisera un nombre plus ou moins important de cases mémoires (appelées octets) pour stocker le nombre. Sans entrer dans le détail (car vous aurez l’occasion par la suite d’approfondir cela), un octet de mémoire permet de stocker un nombre entier compris entre 0 et 255 ; c’est suffisant pour stocker le numéro d’une broche du microcontrôleur. Deux octets permettent de stocker un nombre entier compris entre -32768 et +32767, et si on indique au programme que le signe n’est pas utile, deux octets permettent alors de stocker un nombre positif compris entre 0 et 65535.
Ne vous encombrez pas l’esprit avec cela pour l’instant, remarquez simplement que les valeurs des deux variables sont 300 et 1700 (millisecondes) donc elles sont trop grandes pour tenir sur un seul octet mais peuvent tenir sur deux octets si on déclare comme type de variable le type int (pour integer qui signifie nombre entier signé (positif ou négatif)).
Les noms que j’ai choisis pour mes variables sont suffisamment explicites pour que chacun comprenne de quoi il s’agit. La paresse aurait pu me pousser à choisir des noms plus courts, plus faciles à taper, comme par exemple da et de, mais c’est une mauvaise pratique car un autre programmeur aura du mal à comprendre ce que ces noms représentent. Même vous, si vous reprenez ce programme dans un an, aurez du mal à vous rappeler ; choisissez toujours des noms compréhensibles et des types de variables adaptés à leurs valeurs.
Nous allons donc rajouter deux lignes à notre programme, au tout début c’est-à-dire avant la fonction setup. Pour cela, positionnez le curseur juste avant « void setup » et faites un retour à la ligne (touche « Entrée » ou « Return » suivant les claviers) ; cela crée une ligne vide. Positionnez le curseur sur la ligne vide ainsi créée et tapez le texte suivant :
int duree_allumage = 300 ;
int duree_extinction = 1700 ;
N’oubliez pas le point-virgule à la fin de chaque ligne.
Il reste maintenant à changer les arguments des fonctions delay() (ce qu’il y a entre parenthèses).
Mettez :
delay(duree_allumage) ;
pour le premier delay et mettez :
delay(duree_extinction) ;
pour le deuxième delay.
La figure 17 montre le programme ainsi modifié qu’on enregistrera sous le nom « Blink_Flash ». Vérifiez le programme puis téléversez-le et observez la DEL : celle-ci émet un flash d’une durée de 0,3 s qui se répète toutes les deux secondes.
Au secours, j’ai tout compris !
Le temps est venu pour vous d’écrire votre premier programme de A jusqu’à Z, pour que votre module UNO émette un S.O.S par l’intermédiaire de la DEL branchée sur la sortie 13. Vous avez toutes les connaissances nécessaires pour écrire ce programme. Commencez par ouvrir un nouveau fichier avec Fichier > Nouveau ; une nouvelle fenêtre s’ouvre avec les deux fonctions setup et loop qu’il n’y a plus qu’à compléter.
En code Morse, le S est codé par trois points et le O par trois traits. Utilisez les commentaires pour bien décrire les différentes parties de votre programme :
- initialisation des variables
- setup (pour que la broche 13 soit une sortie)
- loop (émettre le S, puis le O, puis le S selon les directives ci-dessous)
Vous aurez besoin de plusieurs variables de type entier (int) :
- la durée du point est de 0,2 s
- la durée du trait est de 0,6 s
- entre deux points ou deux traits, on doit laisser 0,4 s
- entre deux lettres, on doit laisser 1 s
- entre deux S.O.S ; on doit laisser trois secondes
Les instructions servant à émettre le premier S peuvent être intégralement copiées puis collées plus loin pour émettre le deuxième S. Le fait d’avoir créé des variables vous permettra de changer le rythme de votre S.O.S très facilement (quelques lignes à changer au début du programme au lieu de changer des valeurs dans tout le programme). Enregistrez ce programme sous le nom « Titanic », premier navire à avoir émis un S.O.S. La vidéo ci-dessous montre le résultat à obtenir et une solution est donnée en fin d’article. À vous de jouer !
Changer de sortie
La figure 18 montre comment brancher une DEL sur une sortie numérique du module UNO. Il faut monter en série (à la suite) une DEL et une résistance qui limite le courant qui traverse la DEL.
Peu importe que la résistance soit avant ou après la DEL ; les deux branchements de la figure 18 sont valables. La valeur de la résistance n’est pas très critique (aux alentours de 330 Ω). C’est l’anode de la DEL qui est reliée à la sortie et l’autre extrémité de la DEL, donc la cathode, est reliée à la masse (GND) qu’on trouve à trois endroits des connecteurs du module UNO comme le montre la figure 18. Ainsi, quand on applique une tension de 5 V (HIGH) sur la sortie numérique, on établit une différence de potentiel aux bornes de l’ensemble DEL + résistance, ce qui permet à un courant (limité par la résistance) de traverser la DEL et de l’allumer. Il faut que la broche utilisée soit déclarée en sortie dans le programme : par exemple, si on utilise la broche 10, il faut placer dans le setup :
pinMode (10, OUTPUT) ;
Mais le mieux est d’utiliser une variable pour définir le N° de la broche sur laquelle est branchée la DEL :
int pinLed = 10 ;
et mettre dans le setup :
pinMode (pinLed, OUTPUT) ;
Ainsi, si vous décidez ultérieurement de transférer la DEL sur une autre broche (pin) que la 10, il n’y aura qu’une seule ligne à changer dans le programme (par exemple int pinLed = 7 ;
si vous utilisez la sortie 7 du module).
Amélioration du programme Blink
Reprenons notre procédure pour faire clignoter une lampe de notre appartement (voir plus haut), à savoir :
- Allumer l’ampoule en manipulant l’interrupteur.
- Attendre un certain délai.
- Éteindre l’ampoule en manipulant l’interrupteur.
- Attendre un certain délai.
- Recommencez à partir de 1 tant que vous voulez que l’ampoule clignote.
Finalement, cette procédure pourrait s’écrire plus simplement :
- Manipuler l’interrupteur.
- Attendre un certain délai.
- Recommencez à partir de 1 tant que vous voulez que l’ampoule clignote.
En effet, peu importe que la manipulation de l’interrupteur allume ou éteigne la lampe, le fait de le manipuler plusieurs fois de suite suffit à faire clignoter la lampe. On remarque au passage que notre nouvelle procédure n’a plus qu’un seul délai d’attente, ce qui signifie que le clignotement sera symétrique (durée où la lampe est allumée = durée où elle est éteinte), mais c’est souvent ce qu’on cherche à faire.
Que se passe-t-il lorsqu’on manipule l’interrupteur ? Celui-ci ne peut avoir que deux états possibles : soit il est ouvert, soit il est fermé.
S’il est ouvert, quand on le manipule il devient fermé.
S’il est fermé, quand on le manipule il devient ouvert.
L’état contraire (ou inverse) d’ouvert est fermé et l’état inverse de fermé est ouvert.
Tout ce que nous avons fait jusque-là nous permet de comprendre qu’une sortie numérique de notre module Arduino peut être considérée comme un interrupteur qu’on peut manipuler par programme. Cette sortie numérique ne peut avoir que deux états possibles :
- soit HIGH (tension de 5 V)
- soit LOW (tension de 0 V)
Manipuler l’interrupteur peut donc se traduire en langage de programmation par mettre la sortie à l’état inverse de ce qu’elle était (la mettre à HIGH si elle était à LOW et la mettre à LOW si elle était à HIGH). Encore faut-il savoir à quel état est la sortie avant de faire le changement. Il existe une fonction qui permet de lire l’état d’une sortie numérique du module Arduino. Cette fonction est :
digitalRead (Numero_sortie) ;
Une fois qu’on connaît l’état de la sortie, il faut écrire sur cette sortie l’état inverse. Or, le langage de programmation d’Arduino est basé sur le langage C et l’inverse se note avec un point d’exclamation. Manipuler l’interrupteur se traduit en langage de programmation par :
digitalWrite (Numero_sortie, ! digitalRead (Numero_sortie)) ;
On peut d’ailleurs lire cette instruction de la droite vers la gauche :
digitalRead (Numero_sortie) nous donne l’état de la sortie en retournant HIGH ou bien LOW.
Le point d’exclamation nous permet d’accéder à l’état inverse que l’on écrit alors sur la sortie par la fonction digitalWrite.
Voyons comment mettre tout cela sous la forme d’un programme. Ouvrez le programme Blink (voir plus haut). Dans la fonction loop, remplacez la première instruction par :
digitalWrite (LED_BUILTIN, !digitalRead(LED_BUILTIN)) ;
Attention : il faut deux parenthèses fermantes à la fin et le point-virgule.
Gardez la deuxième instruction :
delay(1000) ;
Supprimez la troisième et quatrième instruction.
La figure 19 montre le programme qu’on enregistrera sous le nom « BlinkSelonLocoduino ». Téléversez le dans votre module UNO et observez le clignotement de la DEL à la fréquence de 0,5 Hz, comme dans le programme Blink.
Un autre point faible de notre programme (et également de Blink) est qu’on fait appel à la fonction delay() pour effectuer une attente. Or, cette fonction est bloquante, ce qui signifie que pendant que le microcontrôleur attend que le délai arrive à son terme, il ne fait rien d’autre. Plutôt qu’utiliser la fonction delay() qui consiste à attendre sans rien pouvoir faire d’autre, on décide de travailler à d’autres tâches en consultant très souvent sa montre pour savoir si le délai est atteint : si oui, on délaisse temporairement les autres tâches et on agit pour faire ce qui doit être fait à la fin du délai. En consultant régulièrement sa montre, on a une notion du temps qui s’écoule. La fonction millis()
nous retourne le temps en millisecondes écoulé depuis l’alimentation en courant du module Arduino. Ce nombre peut être très grand, c’est pourquoi il faut le stocker dans une variable de type « long » qui utilise quatre octets de mémoire de données pour stocker la valeur.
Si nous voulons faire clignoter une DEL à la fréquence de 1 Hz, il faut changer son état toutes les 500 ms (demi-période), comme nous venons d’apprendre à le faire. Chaque fois qu’on change son état, on prend un top et grâce à la fonction millis() qui permet de surveiller le temps qui s’écoule, on regarde si l’intervalle de temps depuis le top arrive à la valeur voulue de 500 ms. Si oui, il suffit de changer l’état de la sortie (donc de la DEL) pour son état inverse. C’est exactement ce que réalise le programme de la figure 20. Complétez le programme BlinkSelonLocoduino pour arriver au programme de la figure 20 puis enregistrez-le (avec la fonction « enregistrer » au lieu de « enregistrer sous » puisqu’il a déjà un nom. Ensuite, téléversez-le dans votre module UNO et observez la DEL qui clignote à la fréquence de 1 Hz. On a utilisé un test « if » (qui signifie si en anglais) ; si la condition entre parenthèses est vraie, alors on exécute les instructions comprises entre les accolades, sinon on passe ces accolades.
Faire clignoter plusieurs DEL en même temps
Il est important de comprendre le programme de la figure 20 car quand on sait faire clignoter une DEL sans utiliser la fonction delay(), on peut alors faire clignoter plusieurs DEL simultanément. Le principe est le même mais avec deux DEL comme le montre le programme de la figure 21 qui utilise deux DEL différentes de la DEL du module UNO. La première clignote à la fréquence de 1 Hz et la deuxième à la fréquence de 3 Hz. Lisez bien les commentaires pour bien comprendre le rôle de chaque instruction. Téléversez ce programme et observez le résultat (pour cet exercice, il vous faut deux DEL et deux résistances de 330 Ω à peu près).
Autre branchement possible pour une DEL
Jusqu’à maintenant, nous avons relié une DEL par son anode à une sortie du module UNO. Dans ce cas, la cathode de la DEL doit être reliée à la masse (GND) et pour qu’un courant traverse la DEL et que celle-ci s’allume, la sortie du module doit être mise au niveau HIGH. Ce branchement, sans oublier la résistance de limitation du courant, est indiqué par la partie a) de la figure 22.
La partie b) de la figure 22 montre un autre branchement possible. Cette fois, c’est la cathode de la DEL qui est reliée à la sortie du module et son anode est reliée au +5 V qu’on trouve sur le connecteur du module comme le montre la figure 23. Mais dans ce cas, pour qu’un courant traverse la DEL et que celle-ci s’allume, la sortie du module doit être à 0 V soit le niveau LOW et l’instruction doit être :
digitalWrite (sortie, LOW) ;
Dans un cas comme dans l’autre (a ou b), la broche du module est utilisée en sortie mais pour que la DEL s’allume, cette sortie doit fournir du courant dans le cas a) alors qu’elle doit absorber du courant dans le cas b). Comme nous l’avons dit plus haut, on ne peut pas raisonner en considérant le sens du courant pour déterminer qu’une E/S est une entrée ou une sortie.
Une E/S du module Arduino est limitée en courant qu’elle peut fournir ou absorber et le module UNO est également limité en courant qu’il peut fournir sur toutes ses sorties confondues (200 mA) ; il faut donc en tenir compte dans la conception d’un programme et si nécessaire, réduire le courant de chaque sortie et amplifier celui-ci au besoin. Nous vous conseillons en fin d’article quelques lectures qui vous apprendront toutes ces techniques.
Que faire pour continuer seul ?
Notre tutoriel s’arrête ici : avec ce que vous avez appris, vous êtes capable de créer vos propres jeux de lumière (feux tricolores, enseigne de commerçant, chenillard, etc.). Bien sûr, il vous reste encore bien d’autres choses à apprendre et c’est pourquoi nous allons vous suggérer quelques lectures.
L’article La carte Arduino Uno vous permettra de mieux connaître votre module UNO, donc ce qu’il est capable de faire. Les articles Bien utiliser l’IDE d’Arduino (1) et Bien utiliser l’IDE d’Arduino (2) vous montreront toutes les subtilités du logiciel de programmation des cartes Arduino, le fameux IDE. L’article Démarrer en électronique vous apprendra comment ajouter un peu d’électronique autour de votre module UNO puisqu’il vous permet de télécharger un cours d’électronique élémentaire composé de 31 chapitres en fichiers PDF. Enfin, les articles Systèmes de numération et Types, constantes et variables vous apprendront comment les nombres sont stockés dans les octets et vous en diront plus sur les types de variables.
Durant votre apprentissage de la programmation de cartes Arduino, n’hésitez surtout pas à explorer les différents programmes donnés en exemple dans l’IDE ; les schémas de branchement des périphériques (servomoteur, moteur pas à pas, haut-parleur, etc.) sont à retrouver sur le site www.arduino.cc dans la rubrique « Learning ».
Enfin, en fonction de vos goûts, vous pouvez parcourir les « Projets ferroviaires (niveau 1) » du site LOCODUINO où vous trouverez des montages très simples pour agrémenter votre réseau de trains miniatures.
Voilà, vous avez mis le pied à l’étrier et nous espérons que cela vous a plu et que vous continuerez par vous-même. Amusez-vous bien !
Voici une solution pour le programme Titanic :
// Titanic.ino
// ce programme emet un S.O.S par l'intermedaire de la DEL du module UNO
// initialisation des variables en respectant les consignes
int duree_point = 200 ;
int duree_trait = 600 ;
int espace_point = 400 ; // idem entre deux traits
int espace_lettre = 1000 ;
int espace_sos = 3000 ;
// fonction setup - initialise LED_BUILTIN en sortie
void setup() {
// put your setup code here, to run once:
pinMode (LED_BUILTIN, OUTPUT) ;
}
// fonction loop - emet le S.O.S
void loop() {
// put your main code here, to run repeatedly:
// emission du S
digitalWrite (LED_BUILTIN, HIGH) ; // allume DEL premier point
delay (duree_point) ;
digitalWrite (LED_BUILTIN, LOW) ; // eteint DEL
delay (espace_point) ; // attente entre deux points
digitalWrite (LED_BUILTIN, HIGH) ; // allume DEL deuxieme point
delay (duree_point) ;
digitalWrite (LED_BUILTIN, LOW) ; // eteint DEL
delay (espace_point) ; // attente entre deux points
digitalWrite (LED_BUILTIN, HIGH) ; // allume DEL troisieme point
delay (duree_point) ;
digitalWrite (LED_BUILTIN, LOW) ; // eteint DEL
delay (espace_lettre) ; // attente entre deux lettres
// emission du O
digitalWrite (LED_BUILTIN, HIGH) ; // allume DEL premier trait
delay (duree_trait) ;
digitalWrite (LED_BUILTIN, LOW) ; // eteint DEL
delay (espace_point) ; // attente entre deux traits
digitalWrite (LED_BUILTIN, HIGH) ; // allume DEL deuxieme trait
delay (duree_trait) ;
digitalWrite (LED_BUILTIN, LOW) ; // eteint DEL
delay (espace_point) ; // attente entre deux traits
digitalWrite (LED_BUILTIN, HIGH) ; // allume DEL troisieme trait
delay (duree_trait) ;
digitalWrite (LED_BUILTIN, LOW) ; // eteint DEL
delay (espace_lettre) ; // attente entre deux lettres
// emission du S
digitalWrite (LED_BUILTIN, HIGH) ; // allume DEL premier point
delay (duree_point) ;
digitalWrite (LED_BUILTIN, LOW) ; // eteint DEL
delay (espace_point) ; // attente entre deux points
digitalWrite (LED_BUILTIN, HIGH) ; // allume DEL deuxieme point
delay (duree_point) ;
digitalWrite (LED_BUILTIN, LOW) ; // eteint DEL
delay (espace_point) ; // attente entre deux points
digitalWrite (LED_BUILTIN, HIGH) ; // allume DEL troisieme point
delay (duree_point) ;
digitalWrite (LED_BUILTIN, LOW) ; // eteint DEL
delay (espace_sos) ; // attente entre deux S.O.S
// on peut recommencer
}