Vous êtes sur la page 1sur 231

Frédéric SILLON

S’initier
à
Arduino
Programmation
et montages électroniques
Inclus
+ de 30 plans
de montage
détaillés
Frédéric SILLON

S’initier
à
Arduino
Programmation
et montages électroniques
Inclus
+ de 30 plans
de montage
détaillés
Direction artistique : Nicolas Wiel
Graphisme de couverture : Pierre-André Gualino
Mise en pages : PCA

© Dunod, 2021
11 rue Paul Bert, 92240 Malakoff
www.dunod.com
ISBN 978-2-10-083007-7
TABLE DES
MATIÈRES

INTRODUCTION 7

/>1 DÉCOUVERTE 9
Présentation 9
La famille des cartes Arduino 11
Un peu d’histoire… 14
Sécurité 16
Les microcontrôleurs 16
Électricité statique et électronique 19
Installation de l’IDE 20
Découverte de l’IDE 25
Schéma et Pinout de la carte Arduino Uno 27
Les connecteurs de l’Arduino Uno 30
Branchement de la carte, précautions 30

/>2 PREMIER PROGRAMME 33


Blink 34
Utilisation des aides en ligne d’Arduino 40

/>3 LE LANGAGE 43
La mémoire, les nombres et le reste… 43
Les bases du langage Arduino 49
Le programme Blink 57

Table des matières /5


Étude des premières fonctions Arduino 60
Premier programme en solo : MonBlink 79
Les Bibliothèques 84

/>4 COMPOSANTS ÉLECTRONIQUES 89


Les composants de la carte Arduino Uno 89
Les schémas 90
Montage de la Led et de la Résistance 91
Courant, Tension et Puissance 96
Application à notre Led 102
Association de résistances 104

/>5 PREMIERS MONTAGES 109


Montage d’une Led supplémentaire 109
Montage d’un bouton poussoir 113
Montage d’un potentiomètre 117
Conversion analogique/numérique 121
Le Moniteur série d’Arduino 129
Et à l’envers… 132
Plus fort avec le transistor… 136

/>6 FONCTIONS AVANCÉES 151


Le PWM 151
La liaison série 159
Les liaisons I2C et SPI 176
Les interruptions 188

/>7 ÉCRANS, MOTEURS, CAPTEURS… 191


Le Servomoteur, pour donner du mouvement à ses projets 191
Le Buzzer, pour faire du bruit 195
L’écran LCD, pour mieux communiquer avec Arduino 201
Le capteur de lumière, pour jouer avec le jour et la nuit 207
Le capteur de température, pour intéragir avec l’environnement 210

/>8 POUR ALLER PLUS LOIN 215


La programmation Objet 215
Créer ses propres bibliothèques 216
Les modules du commerce 219
Deux exemples de projets réalisables avec ce que l’on a appris 224

CONCLUSION 231

6/ Table des matières


/> INTRODUCTION

Quand auparavant, on voulait débuter en électronique ou en développement


de logiciels, il fallait un matériel coûteux, quelquefois assez difficile à trouver,
et tout ça semblait réservé à quelques privilégiés que l’on regardait parfois
avec envie.
Ces temps sont révolus et de nos jours, il existe des cartes d’apprentissage
et des kits d’expérimentation que l’on peut se procurer facilement et pour une
somme modique, neufs ou même d’occasion si on a un budget très serré.
Pour nos expériences, le choix va se porter sur la carte Arduino : son faible prix
et sa disponibilité en font une plateforme de choix. De plus, il en existe différentes
versions avec plus ou moins de périphériques embarqués. Il n’y a qu’à se laisser
tenter.
Pour la partie programmation, une configuration puissante n’est pas néces-
saire. On pourra utiliser un ordinateur portable ou de bureau, mais aussi une carte
Raspberry Pi.
Pour les composants, on pourra toujours démonter des appareils qui ne servent
plus et récupérer ce que l’on peut ou bien se procurer des kits avec un panachage
de composants divers.
Bref, il n’y a plus aucune raison de ne pas franchir le pas et de ne pas rentrer
dans ce monde excitant où se mêlent électronique et programmation !
Le monde qui nous entoure est plein d’électronique, d’appareils qui fonc-
tionnent tout seuls, qui obéissent à la voix, qui suivent nos mouvements. On est
déjà allés sur la Lune et on va bientôt partir pour Mars et ce ne sera pas avec une
machine à vapeur.
Prenez le train en marche et osez, expérimentez, testez – et avant tout,
­amusez-vous  !

Introduction /7
Listings à télécharger sur www.dunod.com
Tous les listings présents dans cet ouvrage sont disponibles
sur le site www.dunod.com. Si vous pouvez les récupérer tels
quels, nous conseillons cependant de les réécrire à la main,
car il n’y a rien de mieux pour apprendre à programmer que de
saisir soi-même les lignes de code.

// REMERCIEMENTS
Je tiens particulièrement à remercier mon épouse Isabelle ainsi que mes deux
enfants, Manon et Erwan, qui m’ont accompagné tout au long de ce livre et qui
m’accompagnent aussi dans la vie.
/> CHAPITRE 
DÉCOUVERTE
1

Dans ce premier chapitre, nous allons faire un peu d’histoire, découvrir notre
carte Arduino et son environnement de programmation.
>> Présentation
>> Les microcontrôleurs dans notre environnement et leur histoire
>> Installation
>> Découverte de l’environnement de programmation et de la carte Arduino Uno
>> Schéma de la carte Arduino Uno
>> Premiers branchements

PRÉSENTATION
Nos appareils quotidiens sont remplis de cartes électroniques qui compor­
tent des composants classiques ainsi que des composants programmables.
Les compo­sants programmables sont des composants électroniques qui ont
l’avantage d’être modifiables
comme bon nous semble (ou
presque…). On peut faire
énormément de choses
avec, à conditions d’arriver
à leur expliquer comment
ils doivent le faire. De la
machine à laver à la télévi-
sion en passant par la voi-
ture, la fusée ou la console
de jeux, notre monde en est
rempli. Il suffit de regarder
autour de nous pour nous en
apercevoir rapidement. Figure 1.1 Détail d’une carte électronique

Présentation /9
Parmi ces composants programmables, on va trouver notamment des micro-
contrôleurs, des microprocesseurs, ainsi que d’autres composants plus ou moins
complexes et on va leur expliquer ce qu’ils doivent faire en les programmant.

Figure 1.2 Un microprocesseur, le MC68000

Au départ réservé à des gens très spécialisés, ce petit monde a beaucoup évo-
lué durant ces dernières années, et des logiciels de programmation très simples
d’utilisation sont apparus.
En partant du principe qu’il faut essayer pour mieux comprendre, les mon-
tages que nous allons étudier ensemble utilisent des microcontrôleurs, ainsi que
des composants plus classiques mais tout aussi indispensables, et nous allons
voir comment faire fonctionner tout ce petit monde pour créer nos propres
montages.
Le cœur de notre carte, ou plutôt son cerveau, est un composant microcontrô-
leur qui s’appelle ATMega328P. De nombreux fabricants proposent des micro-
contrôleurs, comme Microchip, NXP, ST, Renesas ou Intel.
Que ce soient des microcontrôleurs ou des microprocesseurs, ces composants
ont la particularité commune d’être programmables. À eux seuls, ils ne savent rien
faire à part calculer très très vite et avoir une mémoire d’éléphant. On va donc
pouvoir leur apprendre plein de choses qu’ils vont exécuter tout seuls et très vite.
En travaillant progressivement et sans se décourager, à la fois sur les compo-
sants et sur les programmes, on va explorer ces deux mondes très proches l’un
de l’autre : l’électronique et la programmation.
Internet regorge de ressources. Quand on maîtrisera mieux ces deux mondes,
on pourra y trouver beaucoup d’idées pour réaliser les projets les plus fous,
comme sur la page create.arduino.cc/projecthub du site Arduino.

10/ Chapitre 1 : Découverte


LA FAMILLE DES CARTES ARDUINO
Il existe toute une grande famille de cartes Arduino et de cartes compatibles
Arduino, avec des différences et des points communs pour chacune. On choisira
notre carte en fonction de notre budget et de ce que l’on veut en faire : montages
simples avec la Uno, plus complexes, connectés, wearables (wearable = que l’on
peut coudre sur ses vêtements), etc.

Figure 1.3 La carte Arduino Uno

Uno, c’est la carte de base, qui comporte tout de même 14 entrées/sorties digitales
et 6 entrées analogiques. D’un prix très abordable, elle sera la base de nos montages.
Avec ses 32 ko de mémoire flash et ses 2 ko de RAM, on pourra déjà bien s’amuser.

Figure 1.4 La carte Arduino Mega 2560

Arduino Mega 2560 est une carte beaucoup plus complète, qui comporte
54 entrées/sorties digitales, 16 entrées analogiques et 4 ports série. La mémoire
est également plus fournie, avec 256 ko de mémoire flash et 8 ko de mémoire RAM.

La famille des cartes Arduino /11


Figure 1.5 La carte Arduino Mini

L’Arduino Mini est une toute petite carte avec 14 entrées/sorties digitales et
8 entrées analogiques. Par contre, elle ne comporte pas de port USB comme la
Uno ou la Mega.
Il existe de très nombreux modèles dont certains sont équipés de liaisons Wifi
ou de ports Ethernet. Nous n’en parlerons pas ici car nous avons déjà assez à faire
avec les fonctions standard… Cependant, ces cartes seront très intéressantes à
utiliser pour des montages communicants.
Il existe aussi des cartes dites compatibles Arduino, qui ne sont pas les origi-
nales mais qui sont programmables et utilisables de la même façon, comme celle
de Velleman.

Figure 1.6 La carte Velleman, compatible Arduino

Certaines ont des fonctions qui sont très sympathiques, comme la carte Flora
d’Adafruit Industrie, que l’on peut coudre sur ses vêtements.

12/ Chapitre 1 : Découverte


Figure 1.7 La carte Flora (avec l’aimable autorisation de Adafruit Industrie, NYC)

Quoi que vous choisissiez, le principal sera de bien utiliser sa carte et d’explorer
toutes ses fonctions. Cela permettra d’apprendre beaucoup de choses qui per-
mettront plus tard de faire de gros projets.

Figure 1.8 Toute une famille d’Arduino à la plage…

La famille des cartes Arduino /13


Le cœur de nos montages sera donc cette petite carte électronique pas
plus grande qu’une boîte d’allumettes, que l’on peut trouver très facilement
sur Internet ou dans des boutiques spécialisées pour un prix proche de 20 € :
l’Arduino Uno (on pourra trouver des cartes compatibles pour beaucoup moins
cher, certaines de bonne qualité et d’autres beaucoup plus bas de gamme). On
en trouve également d’occasion sur des sites spécialisés de vente entre parti-
culiers. On pourra ainsi s’équiper pour pas trop cher en matériel, cartes d’exten-
sions et outillages.
Cette carte Arduino, qui a été à l’origine codéveloppée en Italie dans les
années 2000 par Massimo Banzi, a connu rapidement un très grand succès : on
peut s’en offrir une facilement, et elle reste simple au niveau de sa programmation.
De plus, ses plans sont disponibles gratuitement.
Comme elle est simple et abordable, beaucoup de gens l’utilisent et partagent
leurs connaissances sur Internet. On va donc pouvoir trouver très facilement de
l’aide lorsqu’il y en aura besoin, mais également trouver des idées de montages,
des schémas et des milliers d’exemples de programmes.
À ce jour, le moteur de recherche que j’utilise sur Internet a trouvé
334 000 000 sites avec le mot clé Arduino… Ce chiffre varie tous les jours, mais
il y a de quoi faire…
On peut également ajouter des cartes d’extension toutes prêtes à notre
Arduino (des Shields), mais on peut aussi fabriquer les nôtres.
De nombreux labos (fablabs) et associations de Makers et DIY (Do It Yourself)
existent en France. Tout le monde peut y accéder pour construire et dévelop-
per avec d’autres personnes. Ils proposent bien souvent du matériel comme des
oscilloscopes et des multimètres, ou encore des tours et des fraiseuses pour la
mécanique ou des imprimantes 3D.

UN PEU D’HISTOIRE…
On peut dire que l’électronique est née au début du vingtième siècle avec
la naissance des premiers tubes à vide. Il s’agissait alors de gros composants
électroniques qui ressemblaient à des ampoules électriques comme celles qui
nous servent à nous éclairer aujourd’hui. Ils étaient très rudimentaires, mais
pourtant révolutionnaires à leur époque. Cette science s’est développée pour
devenir celle que l’on connaît actuellement, avec une grande évolution appa-
rue dans le milieu du vingtième siècle avec l’invention du transistor, du circuit
intégré et plus tard du microprocesseur. Ces composants ont bouleversé notre
monde technologique, bien qu’il s’agisse tout de même d’une discipline assez
récente dans notre histoire.
L’idée de la programmation est pourtant apparue bien avant les premiers ordi-
nateurs modernes. Par exemple, Lady Ada Lovelace – qui s’appelait en réalité
Augusta Ada King, comtesse de Lovelace –, née en 1815, est considérée comme la
première programmeuse. Les ordinateurs n’existaient pas à cette époque, mais

14/ Chapitre 1 : Découverte


son ami mathématicien Charles Babbage avait créé une machine de calcul mathé-
matique en bois et en métal, avec des engrenages, pour laquelle Lady ­Lovelace
avait défini des algorithmes qui permettaient d’effectuer des calculs complexes
avec cette machine. Ces diagrammes sont aujourd’hui considérés comme les pre-
miers programmes informatiques. Beaucoup plus tard, au vingtième siècle, un
langage de programmation a d’ailleurs été développé pour l’armée américaine et
qui porte son nom : le langage Ada.
À la même époque, dans les années 1850, un Anglais du nom de George Boole
a décrit ce que l’on appelle l’algèbre de Boole, et nous y reviendrons plus tard,
car il s’agit d’une notion fondamentale en programmation. Pour faire simple, il ne
compte pas de 0 à 10 comme on le fait dans la vie de tous les jours, mais il compte
seulement de 0 à 1… autrement dit en binaire.
D’autres ancêtres de nos ordinateurs sont également remarquables, comme la
Pascaline qui est une machine à calculer avec des engrenages et qui a été inventée
par Blaise Pascal dans les années 1640 (au temps de Louis xiii…). Il y a eu ensuite
beaucoup de machines à calculer qui ressemblaient à des machines à écrire, et
qui ont également révolutionné leur époque. Certaines étaient programmables
avec des cartes perforées en carton qui étaient donc remplies de trous, et que ces
machines comprenaient comme des suites d’opérations à effectuer. On pouvait
ainsi garder le « programme » et le relancer plus tard ou le recopier sur une autre
machine.
D’autres pionniers ont eu un rôle essentiel pour nous, avec par exemple l’in-
vention des transistors, des circuits intégrés et des microprocesseurs, qui ont
eu un impact considérable dans l’évolution de l’électronique et de l’informatique.
D’autres savants comme l’Anglais Alan Turing ont développé des théories qui
sont encore utilisées aujourd’hui et qui ont constitué les bases de l’informatique
moderne. À cette époque, durant la Seconde Guerre mondiale et juste après, les
ordinateurs remplissaient une pièce entière, étaient rares et coûtaient une for-
tune… Peu de gens savaient les maîtriser.
Viendront ensuite les ordinateurs beaucoup plus proches de ceux que nous
connaissons aujourd’hui, comme L’Apple II, l’IBM PC, le ZX81 ou l’Atari ST (fin
des années 70 et début des années 80). À présent, ils font partie de notre his-
toire technologique et ne sont plus utilisés que par quelques passionnés. On parle
même d’ordinausores… Ils ont été imaginés ou développés par des grands noms
que nous entendons encore souvent aujourd’hui, tels que Bill Gates pour ­Microsoft
MS-DOS et Windows, Steve Wozniak et Steve Jobs pour Apple ou encore Linus
Torvalds pour le système Linux.
Durant toute cette phase de mise en place de l’informatique telle que nous la
connaissons aujourd’hui, beaucoup de langages de programmation ont été déve-
loppés. Voici les plus connus : Basic, Ada, Fortran, Cobol, Pascal, Assembleur,
Java, Objective-C, Swift, Python, C, C++, C#...
De Babbage à Steve Jobs, tous ont commencé un jour par ouvrir un livre pour y
apprendre les bases de ce qu’ils ont ensuite développé avec passion.

Un peu d’histoire… /15


SÉCURITÉ
Tout au long de cet ouvrage, nous allons donc parler de programmation et
d’électronique afin de mélanger ces deux matières, ce qui nous permettra d’être
beaucoup plus libres pour la création et la programmation de nos propres cartes.
Qui dit électronique dit aussi électricité, et qui dit électricité dit danger.
Il faudra donc faire très attention lors du branchement des différents appareils,
même lorsqu’ils sont alimentés avec une petite alimentation comme un chargeur
de téléphone USB ou directement par le port USB de l’ordinateur.
En effet, un court-circuit peut être dangereux pour les composants élec­
troniques, mais aussi pour nous. Les composants qui « crament » dégagent une
fumée qui peut être toxique, et ils peuvent aussi projeter des matières en fusion
comme du plastique mou et brûlant. Il faudra donc se faire aider par un adulte ou
par un ami plus expérimenté lorsque ce sera nécessaire.
Sur nos circuits, les différents points notés GND doivent être
reliés ensemble. De même, la tension nécessaire au fonctionne-
ment de nos circuits peut être dangereuse pour notre corps, et
on fera donc bien attention de ne JAMAIS toucher un composant
lorsqu’il est branché. Notre sécurité est notre plus grande règle.
C’EST LA PLUS GRANDE RÈGLE.

LES MICROCONTRÔLEURS

// QU’EST-CE QU’UN MICROCONTRÔLEUR ?


Un microcontrôleur, comme notre ATMega328P présent sur la carte Arduino
Uno, est un circuit intégré qui comporte plusieurs fonctions évoluées et qui lui
permettent par exemple de calculer une durée, de lire des informations du monde
extérieur, d’agir sur son environnement, de communiquer. C’est le gros boîtier
noir avec plein de pattes que l’on voit sur la Uno…
Un transistor est quant à lui un petit composant électronique qui a révolutionné
cette discipline.

Figure 1.9 Transistors et circuits intégrés

16/ Chapitre 1 : Découverte


On peut dire que sa fonction de base est de laisser passer un peu, beaucoup ou
pas du tout de courant, un peu comme un interrupteur ou un robinet ultraminia-
ture. Un microcontrôleur en possède plusieurs milliers, voire plusieurs dizaines de
milliers dans son petit boîtier en plastique…
À partir de ces fonctions de base, nous allons pouvoir faire énormément de
choses. Avec un peu d’électronique autour de lui, il pourra mesurer une tempé-
rature, nous indiquer s’il y a de la lumière à proximité, faire des bips, allumer des
lumières et bien plus encore : commander des moteurs, piloter un robot…
Chaque fabricant peut avoir une gamme de microcontrôleurs spécialisés dans
une tâche ou une autre, d’autres seront plus généralistes. On peut citer par
exemple le ATMega328P que nous allons utiliser, le MC68HC11, le PIC16F84, le
LPC1788 et bien d’autres encore. On peut également les classer par famille : ARM,
Cortex, avec une structure 8 bits, 16 bits, 32 bits, mais au final ils sont très simi-
laires.
On va généralement désigner un microcontrôleur par l’abréviation µC (µ pour
micro et C pour Contrôleur).

// ET UN MICROPROCESSEUR ?
Un microprocesseur est également un circuit intégré plus ou moins complexe,
mais qui n’a qu’une seule fonction principale : celle de calculer. Par contre, il va
calculer très très vite et servira de gros cerveau à une carte électronique. On va
alors lui associer de la mémoire, ainsi que d’autres circuits qui s’occuperont de
gérer son environnement. Au final, on aura un système un peu identique à un µC,
mais qui sera beaucoup plus puissant en termes de calcul. Dans nos ordinateurs
de bureau ou dans nos portables, on va donc retrouver un microprocesseur qui
va calculer, gérer la mémoire, et s’entourer de divers autres circuits pour gérer le
disque dur, le clavier, l’écran et les autres systèmes autour de lui.
On peut citer parmi les noms les plus connus les Core i7, i5, Xenon, MC68000,
MC68020, ou encore MC6809 pour les plus anciens, et on peut également les
classer par famille : 8, 16, 32 ou 64 bits.
On va généralement l’appeler µP (µ pour micro et P pour Processeur).
Par définition, étant donné que le µC comporte déjà des interfaces vers le
monde extérieur, une carte électronique avec un µC sera souvent plus petite
qu’une équipée d’un µP pour effectuer les mêmes fonctions. Celle avec le µC
sera par contre souvent beaucoup plus lente ou beaucoup plus limitée en termes
d’extensions.
Les cartes à microprocesseur sont donc généralement plus complexes que les
cartes à microcontrôleur, car ces premiers n’ont ni mémoire interne, ni circuits
internes pour communiquer avec le monde extérieur.
Pour débuter dans le monde de la programmation, une carte à µC est donc un
très bon choix.

Les microcontrôleurs /17


Figure 1.10 Prototype à microprocesseur MC68020 (en marron), avec ses circuits externes

Figure 1.11 Autre exemple de prototype à microprocesseur (MC68000, à gauche)

On voit ici que ces prototypes sont plus complexes que notre Arduino Uno…

// DES CARTES À PROGRAMMER


Les µC et les µP sont donc plus ou moins évolués, plus ou moins puissants, plus
ou moins chers, mais ils ont tous les deux leur place dans notre monde, et ils ont
un point commun : ils sont programmables.
Pour les programmer, nous avons vu qu’il existe plusieurs langages comme le
Basic, l’Assembleur, Ada, le C, et encore beaucoup d’autres. Certains sont très
utilisés, d’autres beaucoup moins.
Un peu comme si on apprenait une langue étrangère, nous allons apprendre à
parler à notre µC, et comme il est très sympa, il va faire ce qu’on lui demande…
ou presque. Pour cela, nous allons apprendre un langage proche de C et C++ et
qui est le standard de programmation de l’Arduino.

18/ Chapitre 1 : Découverte


On va écrire nos programmes avec un logiciel qui est un peu comme un petit
traitement de texte. Il sera notre nouvel environnement de programmation et
on l’appelle un IDE (Integrated Development Environment, ou en français EDI,
environnement de développement intégré). On va ensuite demander à cet IDE
de traduire ce que l’on a écrit dans un langage compréhensible par notre micro-
contrôleur. C’est la compilation. On pourra alors envoyer cette traduction dans la
mémoire de notre carte afin que notre µC exécute tout ça, exactement comme on
lui a demandé : c’est le téléversement.

Figure 1.12 Déroulement de la conception d’une application

Il ne va rien corriger à notre place et si ça ne fonctionne pas, c’est que l’on s’est
trompé. Mais rien de grave, il suffira de trouver l’erreur, de la corriger et de lui
renvoyer le nouveau programme. On parle alors de déboggage, pour trouver les
bugs de programme.
Une des explications connues du terme débogguer viendrait d’ailleurs du
monde de l’électronique au temps des premiers ordinateurs qui fonctionnaient
avec des relais, dans les années 1940-1950. À cette époque, un ordinateur moins
puissant que notre Arduino prenait la place d’une pièce entière, et consommait
énormément d’énergie.
En consommant de l’énergie, les armoires où se trouvaient tous ses compo-
sants étaient assez chaudes pour que les insectes du genre punaises, cafards et
autres papillons s’y installent. Un de ces systèmes étant alors tombé en panne, il
a fallu le dépanner. La cause de la panne fut trouvée, et elle était due à un insecte
(bug en anglais), qui s’était coincé dans un des composants. Jolie légende…
Aujourd’hui, nous n’avons plus d’insectes dans nos ordinateurs, mais les bugs
sont toujours bien là et nous apprendrons à les trouver.

ÉLECTRICITÉ STATIQUE ET ÉLECTRONIQUE


Une chose qui est très importante en électronique, c’est l’électricité statique.
Lorsque nous touchons des objets en plastique, et cela concerne surtout les
vêtements que nous portons qui sont bien souvent en matières synthétiques, on
se charge en électricité statique.

Électricité statique et électronique /19


Pour s’en apercevoir, il suffit de prendre un ballon de baudruche, et de le frotter
sur ses cheveux. Tout d’un coup, les cheveux se collent au ballon, et se dressent sur
la tête. Ils se sont chargés en électricité statique, et sont attirés par le ballon comme
par un aimant. Pour arrêter ce phénomène, il suffit de décharger cette électricité
statique en passant plusieurs fois la main dans les cheveux, loin du ballon.
Si cette expérience est amusante, elle est très dangereuse pour nos compo-
sants électroniques. En effet, si on décharge l’électricité que notre corps peut
transporter en touchant nos composants, ils vont se détériorer sans même que
l’on s’en aperçoive. Quand on voudra s’en servir, ils ne fonctionneront plus et on
n’aura rien vu.
Donc, lorsque l’on va manipuler notre carte Arduino, on fera bien
attention de ne pas toucher les composants avec les doigts, et on la
prendra par les parties où il n’y a rien dessus. En général, on la tient
par les côtés.
Pour nos composants, on fera de même, et on prendra bien soin de ne jamais
les manipuler en les tenant par leurs pattes en métal.

Figure 1.13 Comment tenir une carte

INSTALLATION DE L’IDE
Nous allons à présent installer notre IDE. Les installations suivantes ont été
faites sous Windows 10, sous MacOS ElCapitan, Mojave et Catalina mais aussi
sur un Raspberry équipé de Linux Raspbian. Les procédures peuvent légèrement
changer suivant les ordinateurs utilisés, mais on s’y retrouvera facilement.
Le site officiel d’Arduino est www.arduino.cc. Bien que ce site soit en anglais,
il est très facile de comprendre ce qu’il s’y passe. Pour télécharger la version de
l’IDE qui correspond au système d’exploitation de notre ordinateur, on va aller à
la page www.arduino.cc/en/Main/Software.

20/ Chapitre 1 : Découverte


Figure 1.14 Téléchargement Arduino

On choisira ensuite la version correspondante sur la partie droite de cette fenêtre.


Dans la fenêtre suivante, on est libre de faire un don pour aider au développe-
ment d’Arduino. Suivant la version de mise à jour du site arduino.cc, le design de
ces pages peut légèrement changer. De même pour la version de l’IDE, qui ici est
en version 1.8.12.

Figure 1.15 Contribution facultative Arduino

On clique alors sur le bouton Contribute and Download pour faire un don, ou sur
le bouton Download pour simplement télécharger, au choix.

Installation de l’IDE /21


// INSTALLATION SUR MAC
L’installation décrite ici a été faite sous MacOS 10.14.6 Mojave.
À la fin du téléchargement, on va récupérer un fichier du type arduino-1.8.12-­
macosx.zip. Ce fichier de près de 200 Mo va mettre un certain temps pour se télé-
charger, donc un peu de patience… Profitez-en pour admirer votre carte Arduino !
Une fois que le téléchargement est terminé, on va déplacer ce fichier qui a été
automatiquement renommé Arduino vers le dossier Applications du Mac.
En allant dans le Launchpad, on va pouvoir retrouver l’icône de notre nouvel IDE.

Figure 1.16 Application Arduino sur Mac

Il suffira alors de cliquer sur cette icône pour lancer notre nouvel IDE Arduino
qui s’ouvre avec un nouveau programme par défaut. Le premier lancement est
parfois un peu long, mais rien d’affolant.

Figure 1.17 Ouverture d’un programme

22/ Chapitre 1 : Découverte


// INSTALLATION SUR PC WINDOWS
L’installation suivante a été faite sous Windows 10.
Après avoir cliqué sur le bouton Download de la version Windows sur le site
Arduino comme décrit précédemment, le téléchargement commence. Lorsqu’il
est terminé, repérer le fichier zip qui est présent dans le répertoire Télécharge-
ment du PC (où à l’emplacement que vous avez indiqué) et le déplacer dans le
répertoire souhaité. Dans cet exemple, il a été déplacé sur le Bureau.
Cliquer alors avec le bouton droit sur ce fichier, et choisir Extraire Tout…

Figure 1.18 Extraction du fichier compressé Arduino

Une fois l’extraction terminée, aller dans ce nouveau répertoire créé et cliquer
sur Arduino.

Figure 1.19 L’IDE est disponible

Installation de l’IDE /23


L’IDE Arduino se lance alors avec un nouveau programme !

Figure 1.20 L’IDE est lancé

// INSTALLATION SOUS LINUX


Sous Linux, la procédure n’est pas tellement plus compliquée. Il suffit égale-
ment d’aller sur le site arduino.cc et de choisir le fichier d’installation correspon-
dant à sa version de Linux.
Après le téléchargement, il faudra alors extraire le contenu du fichier télé-
chargé et lancer le script install.sh qui se trouve dans ce répertoire. L’installation
s’effectue et un nouveau raccourci Arduino est alors disponible sur le Bureau.

Figure 1.21 L’installation sous Linux terminée

24/ Chapitre 1 : Découverte


DÉCOUVERTE DE L’IDE
Découvrons quelles sont les principales fonctions disponibles dans notre nou-
vel IDE, avec ses trois parties de la fenêtre principale.

Figure 1.22 Fenêtres de l’IDE

Partie 1 : tout en haut, il s’agit du panneau de commande où l’on retrouve les
boutons pour Compiler, Téléverser et Créer, Charger, Sauver un programme.
Partie 2 : au centre, on retrouve l’Éditeur, dans lequel nous allons écrire notre pro-
gramme source (notre code source, ou sketch ou encore croquis en langage Arduino).
Partie 3 : et en bas, il s’agit de la fenêtre de Résultats, dans laquelle notre IDE
nous dira s’il a trouvé un bug, si tout s’est bien passé ou autre.

// ÉDITER, COMPILER, TÉLÉVERSER ?


Que veut vraiment dire éditer, compiler, téléverser ?
Comme nous l’avons déjà vu, ce sont tout simplement des mots que nous allons
utiliser dans le monde de la programmation pour définir ce que nous faisons :
>> Éditer : cela veut dire que l’on écrit notre programme (notre code source),
comme on le ferait avec un traitement de texte simple. Ce programme que
l’on écrit s’appelle un sketch ou un croquis pour notre Arduino.
>> Compiler : une fois notre croquis correctement écrit, il va falloir le traduire
pour que notre Arduino le comprenne. Il s’agit de la compilation, qui est faite
par le compilateur et gérée par notre IDE lui-même.
>> Téléverser : une fois cette traduction effectuée par le compilateur, il va falloir
envoyer toutes ces données à la carte Arduino pour qu’elle la mette dans sa
mémoire. On dit alors que l’on téléverse le programme dans la carte.

Découverte de l’IDE /25


REMARQUE
Lorsque que notre carte Arduino est éteinte, elle conserve son programme en
mémoire, et il sera de nouveau exécuté lorsque la carte sera de nouveau branchée.

// CHANGER LA LANGUE DE L’IDE


Pour passer l’IDE en français, il suffit d’aller dans le menu Préférences et de
choisir le français dans la liste des langues disponibles dans Editor Language.

Figure 1.23 Choix de la langue de l’IDE

Il faudra également cocher la case Afficher les résultats pendant le téléver-


sement ou Show verbose… puis relancer l’IDE pour que les modifications soient
prises en compte.
On pourrait parcourir les autres menus de l’IDE, mais nous le ferons ensemble au fur
et à mesure des besoins, pas la peine de trop se compliquer l’existence pour l’instant…

// LES SAUVEGARDES
Lorsque l’on clique sur le bouton Enregistrer, l’IDE sauvegarde le sketch sur
lequel on travaille sur le disque de l’ordinateur. Par exemple, si ce sketch s’appelle
Prog1, l’IDE va se charger de le renommer Prog1.ino (il met lui-même ino après
chaque nom de fichier afin de s’y retrouver). Il va même créer un répertoire Prog1
dans lequel il va ranger le programme Prog1.ino. Il est super ordonné !
Si on avait déjà un sketch nommé Prog1.ino sur notre disque dur, il sera rem-
placé par le nouveau Prog1.ino, ce qui est normal.

26/ Chapitre 1 : Découverte


Imaginons que l’on a fait plein de modifications sur le sketch Prog1, et qu’il ne
fonctionne plus du tout car on est complètement perdu dans notre raisonnement
de programmeur (si, si, ça arrive…). Comment revenir en arrière pour retrouver
le Prog1 d’hier matin qui fonctionnait à merveille ? Eh bien, on ne pourra pas…
Une bonne habitude est alors de faire des sauvegardes de nos sketchs avec des
noms différents.
Lorsque Prog1 fonctionne bien et que l’on veut le modifier de façon assez
conséquente, on va l’enregistrer sous le nom de Prog2, et on va travailler sur ce
nouveau Prog2. De cette façon, on pourra toujours revenir à Prog1 si besoin.
Lorsque Prog2 fonctionne bien et que l’on veut aller encore plus loin, on le
sauvegarde de nouveau en Prog3 pour travailler dessus et ainsi de suite.
Il faudra aussi se rappeler que notre ordinateur qui fonctionne à merveille
aujourd’hui sera peut-être en panne demain, à cause d’un virus ou d’une panne
électronique (ça m’est arrivé récemment…). Il est donc également très prudent
de sauvegarder régulièrement son travail et ses documents sur une clé USB ou un
stockage en ligne de type cloud, par exemple. Il existe même des logiciels gratuits
spécialisés comme SourceTree pour gérer ses sauvegardes.

UN BON RÉFLEXE POUR PLUS TARD


Les sauvegardes semblent toujours inutiles quand tout va bien, mais sont essen-
tielles lorsque l’on en a besoin… Donc, SAUVEGARDONS !

SCHÉMA ET PINOUT DE LA CARTE ARDUINO UNO


Maintenant que notre IDE est installé, regardons un peu ce qu’il se passe du
côté de notre carte Arduino. Le schéma officiel de notre carte Arduino Uno ainsi
que son pinout – c’est-à-dire son brochage – sont disponibles à l’adresse store.
arduino.cc/arduino-uno-rev3. En ouvrant l’onglet Documentation de cette page,
nous allons trouver plein d’informations intéressantes.

Figure 1.24 Accès aux docs du site Arduino

Schéma et Pinout de la carte Arduino Uno /27


// LE SCHÉMA
Nous allons nous intéresser au schéma de la
carte et le télécharger en cliquant sur l’icône
Schematics in pdf.
Le schéma va nous expliquer tout le fonc-
Figure 1.25 Accès au schéma Arduino
tionnement de la carte, pourquoi tel composant
est ici, et pourquoi celui-là a telle valeur. Un schéma peut être très très complexe
à analyser, mais dans tous les cas, il ne faut pas s’effrayer, et tout d’abord trier les
parties qui nous intéressent le plus. J’avoue que ce schéma n’est pas très lisible
car assez chargé, et on préfèrera celui présenté plus bas sur la même page du
site Arduino. Suivant les mises à jour du site arduino.cc, les versions de schémas
peuvent être différentes de celui-ci.

Figure 1.26 Schéma Arduino Uno (source : arduino.cc)

Pour l’instant, on se rappellera que le µC qui sert de cerveau à notre Arduino


Uno se trouve en bas à droite du schéma, avec la référence ATMega328P-PU.
Le second µC qui se trouve à gauche avec la référence ATMega16U2 ne nous
intéressera pas dans ce livre, mais il faudra juste savoir qu’il sert d’interface USB
entre notre ordinateur et notre µC ATMega328P-PU que nous allons programmer.
Sur la partie en haut à gauche se trouve l’alimentation de la carte, utilisée seule-
ment si on se branche avec une alimentation externe. Si nous utilisons uniquement
la prise USB pour alimenter notre carte, cette partie ne nous concernera pas.

28/ Chapitre 1 : Découverte


En haut à droite se trouve la Led L qui est montée sur la carte et que nous
ferons clignoter plus tard.
Nous verrons tout cela en détail par la suite, mais on voit dès à présent que
l’on peut facilement simplifier le schéma de notre carte si on ne considère que les
composants avec lesquels nous allons travailler directement.
En exagérant, on pourrait se faire une mini carte compatible Arduino avec seu-
lement la partie en bas à droite. Il faudrait utiliser une autre technique pour la
programmer car nous n’aurions plus de port USB, mais c’est envisageable…
En tout cas, pas d’affolement si ce schéma vous paraît un peu complexe.

// LES COMPOSANTS SUR UN SCHÉMA


Sur le schéma de notre carte Arduino, on voit que
chaque composant a un symbole spécial. Par exemple, une
résistance a le symbole suivant :
À côté du symbole, on va trouver sa valeur (1K) et son
nom dans le schéma (RN4D). Nous reviendrons plus tard
sur les schémas, sur ces composants et leurs symboles, il Figure 1.27 
n’y a rien de très compliqué dans ce que nous étudierons. Un symbole de schéma

// LE PINOUT
Un document très important est le pinout de notre carte. Le pinout explique
sur quels connecteurs nous allons trouver les informations qui nous intéressent,
et comment elles sont reliées au µC de notre Arduino. Il peut également être
téléchargé sur cette page : store.arduino.cc/arduino-uno-rev3.

Figure 1.28 Pinout Arduino Uno (source arduino.cc)

Schéma et Pinout de la carte Arduino Uno /29


Le pinout va être beaucoup plus important que le schéma de la carte Arduino
lui-même pour nos projets, car il nous permettra de connecter les bons compo-
sants au bon endroit. De plus, il nous permettra de savoir comment les appeler
dans notre programme.
Chaque carte Arduino étant différente (Arduino Uno ou Mega, par exemple), le
schéma et le pinout de chacune seront différents. Si on utilise des programmes
venant d’Internet, il faudra peut-être les adapter à notre carte Uno.

LES CONNECTEURS DE L’ARDUINO UNO

Figure 1.29 Carte Arduino Uno

Sur notre carte Uno, on va retrouver quatre principaux connecteurs :


>> En haut à gauche, nous avons des entrées/sorties digitales
>> En haut à droite, se trouvent d’autres entrées/sorties digitales
>> En bas à gauche, les alimentations
>> En bas à droite, les entrées analogiques
Certaines pattes (pins) de ces connecteurs peuvent avoir plusieurs fonctions.
Les symboles tilde (~) que l’on trouve sur certaines pins indiquent qu’il s’agit
de sorties qui ont également une fonction PWM. Nous verrons plus tard ce que
cela signifie.

BRANCHEMENT DE LA CARTE, PRÉCAUTIONS


Nous allons brancher notre carte Arduino sur notre ordinateur pour commen-
cer les premiers programmes, faire nos premiers sketchs. Comme on l’a vu précé-
demment, il va falloir faire attention à l’électricité statique en manipulant la carte.
De la même façon, il faudra bien faire attention à la poser sur une surface
plane et dégagée de tout objet qui pourrait la faire tomber, et surtout de tout

30/ Chapitre 1 : Découverte


objet métallique car dans ce cas un court-circuit pourrait advenir. Si vous avez
un ordinateur portable avec un boîtier en aluminium, ne posez surtout pas
votre carte dessus lorsqu’elle est branchée, sinon votre Arduino partira vite
en fumée… et votre ordinateur pourrait lui aussi être endommagé. Il faut donc
bien faire attention, et réfléchir avant de brancher la carte à l’ordinateur ou à
son alimentation : Est-ce que tout va bien ? Pas de risque de court-circuit ? Pas
de branchement à l’envers ?
OK, on peut y aller !

// CHOIX DE LA CARTE ARDUINO


Comme nous utilisons une carte Arduino Uno, il va falloir l’indiquer à notre IDE.
Pour cela, on va aller dans le menu Outils, puis Type de carte et enfin on cliquera
sur Arduino Uno.

Figure 1.30 Choix de la carte dans l’IDE

// CHOIX DU PORT
Maintenant que nous avons indiqué à notre IDE quel type de carte nous utili-
sons, il va falloir lui indiquer sur quelle prise (sur quel Port) de notre ordinateur
nous allons la brancher.

Sur un ordinateur Windows


Sur un ordinateur fonctionnant sous Windows, il suffit d’aller dans le menu
Outils, puis dans Port et enfin de choisir le Port Série sur lequel est branché la
carte, COM11 (Arduino Uno) dans mon cas.

Branchement de la carte, précautions /31


Figure 1.31 Choix du port sous Windows

Sur un ordinateur Macintosh


Sur un Mac, le principe reste le même, et il faudra aller dans Outils, puis Port et
ensuite choisir la ligne qui devra va spécifier (Arduino Uno). Pour ma part, il s’agit
de /dev/cu.usbmodem141101 (Arduino Uno)/.

Figure 1.32 Choix du port sur Mac

Sur un ordinateur Linux


Sous Linux, la procédure sera la même et le nom du port dépendra de la confi-
guration dont on dispose.
/> CHAPITRE 
PREMIER PROGRAMME
2

Nous allons voir comment créer notre premier programme.


>> Sa préparation et son exécution
>> La correction des erreurs
>> L’utilisation des aides
Sur Internet, on va trouver une foule d’informations, plus ou moins utiles, mais
aussi beaucoup d’exemples de programmes pour notre Arduino. Il faudra que l’on
passe du temps à les lire et à les comprendre afin de progresser, et nous commen­
cerons cela ensemble.
Bien souvent, et c’est une bonne habitude à prendre dès le départ, les pro-
grammeurs mettent dans le texte de leur programme des explications supplé-
mentaires, que l’on appelle les commentaires.
Si on a téléchargé un exemple de programme sur Internet, il y a de fortes
chances que les commentaires soient écrits en anglais, mais pas de panique. Avec
quelques notions simples et vite apprises, on pourra comprendre ce que le pro-
grammeur a voulu dire, et si c’est un peu trop compliqué au niveau des mots utili-
sés, pas de souci, on pourra demander à un site de traduction gratuit sur Internet
de nous aider à mieux comprendre, il en existe plein.
Dès le départ, on s’habituera donc à mettre des commentaires dans les fichiers
sources des programmes que nous allons écrire. Non seulement cela pourra aider
les autres programmeurs quand on leur montrera nos sources, mais cela nous
aidera aussi lorsque l’on voudra y revenir plus tard. Bien souvent, lorsque l’on
revient sur un programme que l’on a écrit il y a quelque temps en arrière, on se
demande : « Mais pourquoi est-ce que j’ai écrit ça ? Et ça, à quoi ça sert ? ». Avec
un code bien commenté, les choses seront plus faciles.
Pour écrire un commentaire sur une seule ligne, il suffira de la faire commencer
par deux slashs // :
// On peut faire des commentaires sur une seule ligne
Pour mettre tout un bloc de lignes en commentaire, il suffit de mettre /* au
début de la première ligne, et */ à la fin de la dernière.

Premier programme /33


Tout ce qui sera compris entre ces symboles /* et */ seront des commentaires.
/*
   Ou sur plusieurs lignes
   pour écrire plein de choses utiles…
*/

BLINK
Pour nous faciliter les choses, l’EDI de l’Arduino est livré avec tout un tas
d’exemples que l’on peut étudier et réutiliser. Ils peuvent servir de base à nos
propres créations.
Sur un système à µC ou à µP avec un écran, ou sur un ordinateur, on a pour
habitude d’appeler notre premier programme d’apprentissage « Hello World »,
c’est-à-dire « Bonjour le monde ». Comme nous n’avons pas d’écran sur notre
Arduino, l’autre premier programme d’apprentissage que nous allons pouvoir
écrire s’appelle « Blink » en anglais, ou « Clignoter ».
Généralement sur les petits systèmes à µC, on a l’habitude de mettre une Led
que l’on pourra allumer ou éteindre à volonté, et qui pourra être parfois bien pra-
tique pour nous servir de repère dans notre programme.
Par exemple, si un endroit de notre programme fonctionne mal, on pourra le
découper en parties plus petites, et allumer et éteindre cette Led à différentes
étapes. Si la Led ne s’allume pas alors qu’elle aurait dû le faire à un moment pré-
cis, cela veut sans doute dire que notre programme comporte un bug juste avant
cela et qu’il est bloqué.
Ces exemples vont aussi nous permettre d’explorer toutes les facettes de
notre carte. Cependant, il y a des exemples qui ne fonctionneront pas avec notre
Arduino Uno, comme ceux qui font appel aux liaisons Ethernet.
En effet, notre carte n’a pas de connexion Ethernet et il faudrait alors utiliser
un autre modèle d’Arduino.
Nous allons donc pour l’instant ouvrir le sketch Blink qui se trouve dans les
exemples livrés avec l’IDE, puis le compiler et le téléverser sur la carte.
Ce sketch fait clignoter la Led notée L sur notre carte, et elle clignotait déjà
lorsque l’on a branché la carte toute neuve sur l’ordinateur car ce programme était
déjà embarqué. Ce n’est pas grave, car nous allons tout de même apprendre pas
mal de choses essentielles pour continuer et Blink nous servira de cobaye pour nos
premières expériences.
Allons-y !

// CHARGEMENT
Pour ouvrir le programme Blink et donc le charger dans l’EDI, il suffira d’aller
dans le menu Fichier, puis Exemples et 01.Basics et enfin Blink.

34/ Chapitre 2 : Premier programme


Figure 2.1 Chargement de Blink

Le sketch Blink se charge alors dans l’éditeur.

Figure 2.2 Blink dans l’EDI

La première partie du sketch est comprise dans un bloc de commentaires.


/*
Blink
Turns an LED on for one second, then off for one second, repeatedly.
…………
*/
Le programme en lui-même va commencer un peu plus loin, et nous allons
bientôt regarder ensemble comment il fonctionne.
// the setup function runs once when you press reset or power the board
void setup() { // initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
}

Blink /35
// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on
delay(1000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off
delay(1000); // wait for a second
}
Pour l’instant, nous allons juste le compiler et le téléverser dans notre carte.

// COMPILATION
La compilation d’un sketch se fait simplement en cliquant sur le bouton Vérifier.

Figure 2.3 Compilation

Pendant cette étape de


compilation, notre EDI va
lire chaque ligne du sketch
et regarder s’il n’y a pas de
fautes de langage.
Si tout est correct, il va
traduire tout ça dans le lan-
gage directement compré-
hensible par notre carte
Arduino. Dans la partie basse
de l’EDI, il y a une fenêtre
noire dans laquelle il va nous
indiquer que tout s’est bien
passé (ou pas…).
Ici, il nous dit que tout
s’est bien passé, il n’y a pas
de message d’erreur.

Figure 2.4 Résultat de la compilation

36/ Chapitre 2 : Premier programme


// TÉLÉVERSEMENT
Maintenant que notre sketch est compilé et qu’il n’y a pas d’erreur, nous allons
pouvoir le transférer dans la carte et voir ce qu’il se passe.
Pour cela, il suffit de cliquer sur le bouton Téléverser qui se trouve juste à côté.

Figure 2.5 Téléversement

Pendant et après le téléversement, l’EDI écrit beaucoup de choses en orange


dans la fenêtre du bas, mais rien d’alarmant.
Si tout s’est bien passé, il va même nous remercier en nous disant Thank you…

Figure 2.6 Téléversement terminé

Blink /37
Pendant le téléversement, deux
Leds jaunes Rx et Tx de la carte
Arduino se sont mises à clignoter rapi-
dement, au fur et à mesure que l’EDI
dialoguait avec elles. Une fois ces
échanges terminés, la Led orange L se
met à clignoter indéfiniment.
Notre premier programme s’exé-
cute sans souci !
Maintenant que cette première
étape est passée, nous pourrons Figure 2.7 La Led L de la carte Arduino
regarder d’un peu plus près comment
tout cela fonctionne.

// ET SI TOUT NE SE PASSE PAS COMME PRÉVU ?


Si notre sketch comporte des erreurs de frappe, l’IDE ne comprendra pas ce
que nous avons voulu dire, et il ne pourra pas terminer la compilation. Voilà pour-
quoi le bouton de compilation s’appelle Vérifier, et non pas Compiler. Sur certains
IDE, les deux fonctions existent séparément, Vérifier et Compiler. Pour l’Arduino,
ces deux fonctions ne font qu’une.
Notre IDE vérifie donc ce que nous avons écrit.
Par exemple, si je tape n’importe quoi dans l’EDI et que je compile, on va tout de
suite voir la différence… De plus, il nous indique sur quelle ligne se trouve l’erreur.

Figure 2.8 Erreur de compilation

38/ Chapitre 2 : Premier programme


Par contre, notre IDE ne réfléchit pas à notre place. Si notre raisonnement est
faux mais que nous n’avons pas fait de faute de frappe, la syntaxe sera correcte et
la compilation sera correcte, sans erreurs. Dans ce cas, on pourra tout de même
téléverser le programme dans notre carte, mais il ne fonctionnera pas (ou très mal).
Pour éviter ce genre de problème, on pourra s’habituer à faire un organigramme
(ou encore appelé ordinogramme) afin de mieux réfléchir à la façon de résoudre notre
problème, plutôt que de se lancer tête baissée dans l’écriture de lignes de code qu’il
faudra bien souvent entièrement réécrire si on s’est vraiment beaucoup trompé…

UN ORGANIGRAMME
Un organigramme est un dessin avec des cases qui permet de découper chaque
étape du programme et de les mettre les unes après les autres sur le papier. Ainsi,
on pourra réfléchir comme notre µC le fait lui-même, et si on n’arrive pas au résul-
tat voulu en suivant cet organigramme, notre Arduino n’y arrivera pas non plus
(une fois de plus, il ne réfléchit pas à notre place…).

Par exemple, pour Blink, on veut faire clignoter la Led L qui se trouve sur notre
carte Arduino. Cela signifie qu’il faut l’allumer, attendre, l’éteindre, attendre, et
recommencer indéfiniment.
L’organigramme général pourrait être comme ceci.

Figure 2.9 Organigramme de Blink

Pour ceux qui connaissent déjà Scratch, cela ressemblerait à ça.

Figure 2.10 Blink en Scratch

Blink /39
On voit ici que cet exemple en Scratch ressemble beaucoup à un organi-
gramme…
Pour en revenir à nos moutons, j’avais fait une faute dans le sketch de Blink en
tapant la phrase « N’importe quoi ! ». Maintenant que l’on a vu pourquoi la vérifi-
cation avait échoué, nous allons donc aller à la ligne indiquée en orange par l’EDI
et la corriger.
Lorsque l’erreur est corrigée, ce qui n’est pas toujours facile avouons-le, on
peut recompiler le sketch et le téléverser.

UTILISATION DES AIDES EN LIGNE D’ARDUINO


Avant d’aller plus loin, on peut dire un mot sur le menu Aide de l’IDE.
Notre IDE est un environnement de développement simple d’utilisation, mais
tout de même très complet et dédié à l’apprentissage. Il est donc tout naturel d’y
trouver de nombreuses aides.
En allant dans ce menu Aide, on va pouvoir trouver des informations précieuses,
et notamment dans le menu Aide pour débuter, ainsi que dans le menu Référence.
Ces aides sont en anglais, mais il est possible d’utiliser les fonctions de Google
ou autre pour la traduction.
Dans le menu Référence, on trouvera toutes les instructions de programmation
disponibles, ainsi que la façon de les utiliser. Il ne faudra pas hésiter à utiliser ces
précieuses ressources.
On pourra également se servir de ces aides pour commenter notre sketch
lorsque l’on utilise une nouvelle fonction.

Figure 2.11 Aide Arduino

40/ Chapitre 2 : Premier programme


Par exemple, dans notre programme Blink, on utilise l’instruction suivante :
digitalWrite(LED_BUILTIN, HIGH);
Que veut dire digitalWrite ? Comment l’utilise-t-on ?
On verra tout cela en détail dans le chapitre suivant, mais pour l’instant on va
aller dans le menu Aide et Référence, et chercher digitalWrite.

Figure 2.12 Aide digitalWrite()

Voilà ce que l’on apprend.


La formule magique (on parle de syntaxe) pour utiliser digitalWrite est ins-
crite ainsi à la rubrique syntax :
digitalWrite(pin, value)
On voit que ça ressemble beaucoup à ce qu’il y a dans Blink. Regardons de plus
près. Dans l’aide, on a :
digitalWrite(pin, value)
Dans Blink, on a :
digitalWrite(LED_BUILTIN, HIGH);
Une petite traduction rapide de l’aide issue du site arduino.cc nous indique que
digitalWrite permet de mettre à 5 V ou à 0 V la sortie correspondante de notre
Arduino, selon que l’on écrit HIGH ou LOW pour value.

Utilisation des aides en ligne d’Arduino /41


Si on revient au pinout que nous avons vu précédemment, on s’aperçoit que
LED_BUILTIN correspond à la Led intégrée à la carte Arduino. On est sur le bon
chemin…
Il y a même un petit exemple un peu plus bas sur cette page d’aide qui nous
indique comment l’utiliser (cet exemple est Blink, ça tombe plutôt bien…).
Avec 5 V, la Led va s’allumer et avec 0 V elle va s’éteindre. L’aide nous apprend
donc que :
>> si on veut allumer la Led L de la carte Arduino, on va devoir écrire :
digitalWrite(LED_BUILTIN, HIGH);
>> si on veut l’éteindre, on va écrire :
digitalWrite(LED_BUILTIN, LOW);
/> CHAPITRE 
LE LANGAGE
3

Comme pour apprendre à parler une nouvelle langue étrangère, il y a quelques


notions à regarder avant d’aller plus loin.
>> Comment parler à Arduino : la mémoire, les octets, les bits et le reste…
>> Le programme Blink
>> L’étude de fonctions simples
>> Le premier projet en solo

LA MÉMOIRE, LES NOMBRES ET LE RESTE…


Pour écrire notre programme, on va utiliser toute une syntaxe que l’on va
découvrir, et également utiliser une autre façon de compter que l’on retrouvera
dans de nombreux programmes. Cette syntaxe est un ensemble d’instructions,
tout comme les mots d’une langue.
Tout d’abord, les instructions que l’on va écrire dans notre sketch ressemblent
beaucoup à des termes anglais, et ils s’écrivent sans accents. Les minuscules et
majuscules (ce que l’on appelle la casse) sont aussi importantes.
Par exemple, ceci est différent de Ceci et aussi de ceCi. C’est une source
­d’erreur fréquente et il faudra y faire attention, mais le compilateur de notre EDI
va vite nous le rappeler…
De même, on utilisera une façon d’écrire qui s’appelle camelCase : on ­commence
un mot par une minuscule, et au lieu de mettre des espaces entre les mots, on met
une majuscule. Par exemple, on dira : faitCeci ou faitCela.
On appelle ça camelCase, car camel veut dire chameau en anglais, et c’est vrai que
les majuscules des mots écrits ainsi ressemblent un peu aux bosses d’un chameau.
La mémoire de notre Arduino est un peu comme une grande boîte avec des
compartiments à l’intérieur : ce sont les cases mémoires. Pour notre µC, c’est un
peu comme notre mémoire à nous. Il va y chercher ou bien y ranger tout ce dont
il a besoin pour calculer. On peut représenter la mémoire d’un sytème à µC ou µP
de cette façon.

La mémoire, les nombres et le reste… /43


Chaque case mémoire est donc comme une
boîte, et l’ensemble de la mémoire est comme
un empilage de ces boîtes. Pour s’y retrouver,
chaque case a une adresse qui permettra de
la reconnaître et d’y accéder pour ranger ou
récupérer des valeurs numériques. Dans cet
exemple, à l’adresse 5 se trouve la valeur 32 et à
l’adresse 11 se trouve la valeur 47.
De plus, une mémoire de 1 kilo octet (1 Ko) com-
portera 1 024 boîtes empilées. Pourquoi 1 024 ?
Cela vient de la façon dont on compte en binaire,
et on en parlera dans un court instant.
Chaque case mémoire quant à elle est divisée
en huit parties : ce sont les bits. Un ensemble de
huit bits forme un octet. Voilà pourquoi on parle
Figure 3.1 Représentation mémoire
de µC 8 bits…
Continuons… On a l’habitude de représenter un octet de cette façon.

Figure 3.2 Représentation d’un octet (8 bits) en mémoire

On voit que chaque bit d’un octet mémoire porte un petit nom, de b7 à b0.
b7 b6 b5 b4 b3 b2 b1 b0
Chaque bit peut avoir deux valeurs possibles, soit 0 soit 1. On dit qu’il est posi-
tionné à 1 ou à 0. De plus, il peut aussi ne comporter qu’un seul symbole et on
peut dire que b7 vaut 1 ou 0, mais on ne peut pas dire que b7 vaut 101, car 101 est
constitué de trois symboles.
Pourquoi cela ? Avant d’aller plus loin, on ne panique pas sur ce qui va suivre, et on
prend un papier et un crayon pour réfléchir en même temps qu’on lit les exemples…

// LES SYSTÈMES DÉCIMAL ET BINAIRE


Pour compter, nous utilisons habituellement les chiffres 0, 1, 2 jusqu’à 9. Notre
système de comptage est un système décimal (décimal = dix symboles, de 0 à 9).
Si on veut compter davantage une fois arrivé à 9, on reprend le symbole 1, et
on lui colle le symbole 0 pour faire 10, et on continue de compter : 10‑11‑12‑13-…
Arrivé à 19, on recommence avec 2 et 0 pour faire 20, puis 21‑22‑23-… et on
continue ainsi indéfiniment.
On a donc : 0‑1-2‑3-4‑5-6‑7-8‑9-10‑11‑12‑13‑14‑15‑16‑17‑18‑19‑20‑21‑22‑23…
Pour George Boole dont on a déjà parlé, les symboles 0 et 1 suffisent pour
compter. On compte 0 puis 1, puis on recommence comme on le fait habituelle-

44/ Chapitre 3 : Le langage


ment dans notre système décimal, mais seulement avec ces deux symboles : 1 et
0 pour faire 10, puis 1 et 1 pour faire 11, puis 1 et 0 et 0 pour faire 100, etc.
Dans ce système dit binaire de George Boole, on a donc :
0‑1-10‑11‑100‑101‑110‑111‑1000‑1001‑1010‑1011‑1100‑1101‑1110‑1111‑10000-…
Cette notion est fondamentale en électronique et en informatique. En effet, on
peut dire que si on écrit 0, cela signifie que le signal électrique ne passe pas, et si
on écrit 1, cela signifie que le signal électrique passe.
Pour notre programmation, on note que HIGH = 1, et LOW = 0.
Avec ce système binaire, notre µC peut compter, mais il peut aussi faire des
opérations, l’addition par exemple.
Si on dit qu’une case mémoire de notre µC contient par exemple l’octet suivant :
b7 b6 b5 b4 b3 b2 b1 b0
1 1 0 1 1 0 0 1
On peut alors dire qu’elle contient en fait le nombre décimal 217. Pour nous
humains, c’est plus simple de dire 217 que de dire 11011001 (on prononce un un
zéro un un zéro zéro un, et non pas onze million onze mille un). Par contre, 11011001
convient mieux à notre Arduino.
Comment fait-on pour en arriver là ? C’est assez simple.
Chaque bit d’un octet possède ce que l’on appelle un Poids. Le bit b7 est le bit
de poids fort (on le met à gauche), le bit b0 est le bit de poids faible (on le met à
droite), ce qui permet de les ranger dans le bon ordre, chaque bit possédant une
valeur bien à lui. Le Poids est la position du bit dans l’octet.
En résumé, si on regarde la valeur équivalente de chaque bit en décimal, on a
notre octet qui va être ainsi :
b7 b6 b5 b4 b3 b2 b1 b0
128 64 32 16 8 4 2 1 (poids de chaque bit)
Pour notre Arduino, cela ne convient pas car on a vu que chaque octet mémoire
est divisé en huit cases, et que chaque case ne peut contenir qu’un seul symbole.
Chaque bit à 1 garde sa valeur équivalente en décimal. S’il est à 0, il vaudra bien 0.
Ensuite, on additionne tous les résultats obtenus pour avoir le résultat final.
Ainsi, notre case mémoire vaudra en binaire et en équivalent décimal :
b7 b6 b5 b4 b3 b2 b1 b0
1 1 0 1 1 0 0 1 (binaire)
128 64 32 16 8 4 2 1 (poids de chaque bit)

REMARQUE
En informatique, on utilise le symbole * au lieu du symbole mathématique × pour
faire une multiplication. Par exemple, 3 fois 2 se note 3 * 2, et non pas 3 × 2.

Donc, en combinant tout ça, et en ne prenant que les bits qui sont positionnés
à 1, on a la valeur décimale de notre octet qui est alors :
1*128 + 1*64 + 0*32 + 1*16 + 1*8 + 0*4 + 0*2 + 1*1
Donc 128 + 64 + 16 + 8 + 1 = 217.
Et voilà !

La mémoire, les nombres et le reste… /45


Un autre exemple ?
À quoi équivaut 100110 ? Et bien, si on se replace sur 8 bits, on a :
b7 b6 b5 b4 b3 b2 b1 b0
1 0 0 1 1 0 (binaire)
On commence toujours par remplir notre octet par les bits de poids faible,
comme on le fait habituellement en décimal. Par exemple, en décimal 592 = 0592
= 00592. On peut mettre autant de zéros que l’on veut à gauche de notre chiffre,
ça ne le change pas. En binaire, c’est la même chose, et s’il manque des bits à
gauche, on complète avec des zéros, histoire de ne pas laisser de cases vides
(il faut bien que notre µC sache à quoi s’en tenir).
On a donc :
b7 b6 b5 b4 b3 b2 b1 b0
0 0 1 0 0 1 1 0 (binaire)
En revenant en décimal, on a vu que chaque bit avait un poids.
b7 b6 b5 b4 b3 b2 b1 b0
128 64 32 16 8 4 2 1
Donc, en refaisant notre équivalence :
b7 b6 b5 b4 b3 b2 b1 b0
0 0 1 0 0 1 1 0 (binaire)
128 64 32 16 8 4 2 1
On obtient donc :
0*128 + 0*64 + 1*32 + 0*16 + 0*8 + 1*4 + 1*2 + 0*1,
donc 32 + 4 + 2 = 38.
On peut donc dire que 100110 en binaire vaut 38 en décimal ! Trop fort !

QUESTION PIÈGE
Si on parle du nombre 101, est-ce que c’est 101 en décimal, ou 101 en binaire ? Et
bien si on écrit simplement 101, on considère qu’il s’agit de 101 en décimal, comme
on compte d’habitude. Si on veut parler de la valeur 101 en binaire, on écrit habi-
tuellement 0b (zéro suivi de la lettre b) devant afin de montrer que l’on parle d’une
valeur binaire. Ainsi, 0b101 est bien un nombre binaire qui équivaut à 5 en décimal
si on refait notre petite conversion comme tout à l’heure.

À quoi ça sert ?
Et bien lorsque l’on a étudié le pinout de notre carte Arduino, on a vu que cer-
taines pins de nos connecteurs s’appellent par exemple D0 ou D7.
Si on se dit que D7 peut correspondre à b7 de notre octet, et si D0 du connec-
teur peut correspondre à b0, alors on comprend mieux à quoi cela peut servir.
On va pourvoir associer chaque pin du connecteur à un bit d’octet, ce qui nous
permettra de mettre cette pin à 1 ou à 0, c’est-à-dire de l’activer ou non.
Si on met des Leds sur chaque sortie des connecteurs de D7 à D0, que l’on met
notre octet à 11011001 comme on vient de le voir, et que l’on transfère cet octet sur
les sorties D7 à D0 du connecteur, alors les Leds branchées sur D7-D6-D4-D3-D0

46/ Chapitre 3 : Le langage


vont s’allumer car les bits correspondants seront à 1 et donc actifs, les autres
seront éteintes car leurs bits seront à 0.
C’est plutôt pas mal…
Par contre, on voit que pour écrire 217, on a besoin de trois symboles dans notre
base décimale (le symbole 2, le symbole 1 et le symbole 7), alors qu’en binaire il
nous en a fallu beaucoup plus (on en a utilisé huit…).

// LE SYSTÈME HEXADÉCIMAL
En dehors de notre système de comptage décimal et du système binaire que
nous venons de voir, il existe un autre système de comptage que l’on utilise beau-
coup en informatique : le système hexadécimal.
Décimal était sur une base de 10 (on compte de 0 à 9 en utilisant 10 symboles,
puis on recommence). Hexadécimal est quant à lui sur une base de 16 symboles
(d’où son nom de hexa).
En binaire, on a deux symboles : 0‑1.
En décimal, on a 10 symboles : 0‑1-2‑3-4‑5-6‑7-8‑9.
En hexadécimal, on a 16 symboles : 0‑1-2‑3-4‑5-6‑7-8‑9-A-B-C-D-E-F.
C’est un peu déroutant, mais notre nombre 217 décimal qui s’écrivait également
0b11011001 peut maintenant s’écrire D9 en hexadécimal…
Au lieu de trois symboles, on n’en utilise que deux, d’où son utilité.
On a vu que pour compter en décimal, après 8‑9 on reprend 1 et on lui colle 0
pour avoir 10 puis 11‑12‑13‑14, etc.
En hexa, ce sera la même chose. Après D-E-F, on reprend 1 et on lui colle 0 pour
continuer ainsi : D-E-F-10‑11‑12…

Décimal
0‑1-2‑3-4‑5-6‑7-8‑9-10‑11‑12‑13‑14‑15‑16‑17‑18‑19‑20‑21‑22‑23…
Hexadécimal
0‑1-2‑3-4‑5-6‑7-8‑9-A-B-C-D-E-F-10‑11‑12‑13‑14‑15‑16‑17‑18‑19‑1A-1B-1C-1D-
1E-1F-20…

On voit tout de suite que l’on peut compter en utilisant moins de symboles.
Pour faire la conversion, on va regrouper notre octet en deux groupes de quatre
bits.
Ainsi, pour notre valeur 217, on écrira en exagérant :
b7 b6 b5 b4 b3 b2 b1 b0
1 1 0 1 1 0 0 1
Pour le système décimal, on avait fixé l’équivalence suivante.
b7 b6 b5 b4 b3 b2 b1 b0
128 64 32 16 8 4 2 1
Pour notre conversion hexa, comme on considère notre octet de huit bits en
deux groupes de quatre bits (deux quartets), on ne va s’occuper que d’un quartet

La mémoire, les nombres et le reste… /47


à la fois en comptant jusqu’à F (0‑1-2‑3-4‑5-6‑7-8‑9-A-B-C-D-E-F) et en refaisant
une conversion intermédiaire en décimal. Ça a l’air compliqué, mais c’est super
simple.
Reprenons notre nombre 217 (11011001 en binaire), en séparant les deux quar-
tets :
b7 b6 b5 b4 b3 b2 b1 b0
1 1 0 1 1 0 0 1
On commence par ne prendre que le quartet de gauche (le quartet de poids
fort), que l’on considère comme s’il était tout seul.
1 1 0 1
Comme on n’a que 4 bits à considérer, on peut dire ici que l’on a en décimal :
1*8 + 1*4 + 0*2 + 1*1, donc 8 + 4 + 1 = 13.
Si on reprend notre suite en hexadécimal, 0‑1-2‑3-4‑5-6‑7-8‑9-A-B-C-D-E-F,
on voit tout de suite que 13 en décimal équivaut à D.
On fait la même chose avec le quartet de poids faible.
1 0 0 1
On a alors 1*8 + 0*4 + 0*2 + 1*1 = 9, et donc 9 dans notre suite hexa.
On reprend alors la conversion du quartet de poids fort que l’on colle à la
conversion du quartet de poids faible, et on obtient D9.
La conversion de 217 en hexadécimal vaut alors D9, et on a utilisé deux sym-
boles au lieu de trois.
Comme on l’a fait en plaçant 0b devant la valeur binaire, on place 0x devant la
valeur convertie en hexadécimal afin de ne pas se mélanger. On peut alors dire
que ces trois nombres sont équivalents, mais chacun écrit dans sa base.
217 = 0b11011001 = 0xD9
Encore un pour la forme…
0b11001011 en binaire vaudra en décimal :
1*128 + 1*64 + 0*32 + 0*16 + 1*8 + 0*4 + 1*2 + 1*1 = 128 + 64 + 8 + 2 + 1 = 203
En hexadécimal, on aura en divisant notre octet binaire en deux quartets :
0b11001011 g 1100 1011
>> Quartet de poids fort : 1100 = C
>> Quartet de poids faible : 1011 = B
On aura donc : OxCB
C’est un peu bizarre au début, mais avec un peu d’exercice, on s’y retrouve
vraiment très facilement.
Dans l’autre sens, 0xF3 vaudra en binaire :
>> Quartet de poids fort : F en hexa vaut 15 en décimal, soit 8 + 4 + 2 + 1 soit
1111 en binaire.
>> Quartet de poids faible : 3 en hexa vaut 3 en décimal, soit 2 + 1 soit 0011 en
binaire.
Donc, 0xF3 = 0b11110011
Facile…

48/ Chapitre 3 : Le langage


REMARQUE
Certains compilateurs acceptent 0x devant un nombre hexa, alors que d’autres
demandent d’avoir 0h ou $.
Les trois écritures 0x25, 0h25 et $25 sont équivalentes, mais notre compilateur
Arduino demande d’avoir la notation 0x25.
Si la notation en hexadécimal paraît trop complexe, on pourra rester en décimal,
notre IDE n’y verra aucun inconvénient. Il faut savoir que cette notation existe car on
la retrouvera dans de nombreux programmes informatiques, de même pour le binaire.

Avec tout ça, on comprend maintenant pourquoi 1 Ko de mémoire contient


1 024 octets. Comme nos adresses mémoires sont comptées en binaire (ou en hexa)
et si on voulait doubler notre mémoire petit à petit, on aurait les adresses suivantes :
1‑2-4‑8-16‑32‑64‑128‑256‑512‑1024… C’est en fait un peu plus compliqué que cela,
mais cette explication est une bonne représentation et une façon simple de s’en
rappeler. De la même façon, 2 Ko vaudraient alors 2 048 octets, et ainsi de suite.

LES BASES DU LANGAGE ARDUINO


Comme pour tout langage, un langage informatique a une syntaxe, et nous n’y
échapperons pas pour programmer notre Arduino. Il va falloir que l’on apprenne
à lui parler correctement.
Arduino se programme avec une syntaxe proche du langage C, et qui comporte
aussi des éléments du langage C++ (on prononce C plus plus). Ces deux langages
sont très utilisés dans l’industrie, et programmer Arduino est donc un très bon choix.

// PRINCIPE KISS
Avant tout, un sketch est une suite d’instructions qui seront exécutées les unes
après les autres. On va donc avoir un ensemble de lignes de codes, chaque ligne
(ou presque) étant terminée par un point virgule ; et un retour à la ligne.
Même s’il ne sert à rien pour le compilateur, le retour à la ligne permettra de
faire des programmes plus lisibles.
On peut dire sans beaucoup se tromper que ceci :
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}

Les bases du langage Arduino /49


est tout de même plus lisible que cela :
void setup(){pinMode(13,OUTPUT);}void loop(){digitalWrite(13,HIGH);delay↵
(1000);;;;digitalWrite(13,LOW);delay(1000);}
et encore plus que ça…
void setup(){pM(13,1);}void loop(){dW(13,0);d(1s);;;;dW(13,0);d(0x3E8);}
ou ça :
bool I::o(void){return((g()<=+_GMi)&&(g()>=+_GMa));}
Ces programmes fonctionnent, mais on voit rapidement qu’un programme bien
écrit est tout de même plus lisible et plus compréhensible… Le but n’est pas de
faire compliqué, mais de faire quelque chose qui fonctionne.
En anglais, on appelle cela KISS principle (Keep It Simple, Stupid. Ce qui veut
dire : Garde-le simple, idiot…). Un truc simple mais qui fonctionne bien sera tou-
jours plus impressionnant qu’un autre compliqué et qui ne marche pas.
On va garder ce principe pour nos logiciels, ainsi que pour nos schémas élec-
troniques. On aura bien le temps de se triturer les méninges avec des problèmes
complexes à résoudre…
Autre chose : on n’utilise jamais d’accents dans les termes d’un programme. On
écrira elephant au lieu de éléphant.

// LES TYPES DE DONNÉES


Dans un programme, on va manipuler pas mal de nombres, et on devra préciser
de quel type ils sont, c’est-à-dire : est-ce qu’ils sont à virgule ? Entiers ? Petits ?
Grands comment ?
Ces classements des nombres sont les types et on va les appeler ainsi :
>> byte : nombre entier (et donc sans virgule), et compris entre 0 et 255.
>> int : nombre entier. Sur un Arduino Uno, il peut prendre n’importe quelle
valeur comprise entre –32 768 et 32 767.
>> short : comme int.
>> unsigned int : nombre entier de 0 à 65 535.
>> word : comme unsigned int.
>> float : nombre à virgule, allant de –3.4028235E+38 à 3.4028235E+38
(« E+ » étant une notation utilisée en informatique pour les puissances
de 10 : 3.40E+38 est égal à 3,40×1038). On pourra par exemple écrire
3.1415926535897932 ou 124543.9900993 et le symbole décimal sera un
point et non pas une virgule. Attention au piège !
>> double : comme float.
>> long : nombre entier de –2147483648 à 2147483647.
>> unsigned long : nombre entier de 0 à 4294967295.
>> boolean : deux valeurs, 0 ou 1.
>> char : nombre de –128 à 127, et qui représente un caractère comme A, Z, p ou $.

50/ Chapitre 3 : Le langage


>> unsigned char : nombre entier, de 0 à 255.
>> void : rien. Ne représente rien comme nombre mais très utile…
La première question que l’on se pose en voyant tous ces types de données est
la suivante : pourquoi en avoir autant de différents si ce n’est pour attraper une
bonne migraine ?
C’est simplement pour réduire l’utilisation de la mémoire de notre Arduino
et de tout système informatique. En effet, on a vu qu’il stocke toutes les ins-
tructions et toutes les données dans sa mémoire, et que celle-ci est limitée.
Même sur un ordinateur moderne avec plusieurs giga octets de mémoire, elle
est tout de même limitée, c’est-à-dire non infinie. Il va donc falloir apprendre à
l’économiser.
Si on veut dire juste Oui ou Non, ou alors Vrai ou Faux, on n’utilise que deux
symboles. On peut donc se dire que pour dire Vrai on utilisera le symbole 1, et pour
dire Faux on utilisera le symbole 0. Ça tombe plutôt bien, puisque le type boolean
n’utilise que deux valeurs, 0 et 1.
Ça ne vous rappelle rien ? George Boole… et son système booléen…
On a également vu que le nombre 255 s’écrit 0xFF en hexadécimal et 0b11111111
en binaire, donc occupe une case mémoire de 8 bits dans notre Arduino.
Si on effectue la conversion, le nombre 4294967295 s’écrit 0xFFFFFFFF en
hexadécimal et 0b11111111111111111111111111111111 en binaire, donc il utilise 32 bits soit
4 cases mémoires de 8 bits (car 8*4 = 32…)
On comprend vite que si on veut dire juste Vrai ou Faux, soit 1 ou 0, il vaut mieux
utiliser le type boolean qui n’utilise que 1 bit.
De même, pour stocker le nombre 208, qui est compris entre 0 et 255, on utili-
sera de préférence le type unsigned char. Par contre, un unsigned char ne pourra
pas stocker un nombre tel que 308. Il y aura débordement, et tous nos calculs
seront faux.
Il est donc judicieux d’utiliser le bon type pour stocker la bonne donnée afin
de ne pas utiliser trop de mémoire pour rien, mais aussi pour ne pas risquer un
débordement.
Dans le pire des cas, il vaut mieux utiliser un type un peu trop grand que trop
petit (on est plus à l’aise avec des chaussures trop grandes que trop petites…).
En plus, en utilisant la bonne taille de données, notre programme sera sans
doute plus rapide, car il manipulera de plus petits nombres, ou en tout cas juste
ce qu’il faut.

// LES VARIABLES ET LES CONSTANTES


Pour ranger les nombres que l’on utilise dans nos programmes, on va utiliser
les cases mémoires de notre µC. Pour y ranger nos données, on va utiliser ce
que l’on appelle des variables. Pour simplifier notre programme, on pourra aussi
utiliser des constantes.

Les bases du langage Arduino /51


Les constantes
Les constantes vont nous servir à stocker des nombres qui ne changeront pas
tout au long de notre programme. Par exemple, notre année de naissance peut
être considérée comme une constante, car elle ne changera jamais.
Pour définir une constante, on va utiliser le mot clé #define devant son nom.
#define anneeDeNaissance 1910
On remarquera qu’il n’y a pas de point-virgule à la fin de la ligne, c’est une
exception du langage.
Si on voulait se rajeunir, on pourrait essayer d’écrire dans notre programme :
anneeDeNaissance = 2012;
Le compilateur de notre IDE ne le voudra pas, car une constante doit rester
constante comme son nom l’indique…
Par habitude, afin de mieux repérer les constantes dans nos programmes, on
les notera entièrement en lettres majuscules.
#define ANNEEDENAISSANCE 1910
Il n’y a alors plus de camelCase, étant donné que tout est en majuscules ; ce
n’est pas très lisible. Il suffira de mettre des underscores _ pour séparer les mots :
#define ANNEE_DE_NAISSANCE 1910
C’est tout de suite beaucoup plus clair, et on repère facilement les constantes
avec leurs majuscules. D’ailleurs, dans le sketch Blink, on a vu que LED_BUILTIN et
HIGH étaient écrits en majuscules avec des underscores…
digitalWrite(LED_BUILTIN, HIGH);
On peut également utiliser le mot réservé const pour définir une constante, et
il faudra alors lui donner un type.
const int annee = 92;
Comment va-t-on faire pour mémoriser notre âge qui, lui, varie tous les ans ?
Et bien, nous allons utiliser des variables.

Les variables
Nous avons vu que les constantes sont simples à utiliser et qu’il n’y a pas besoin
de leur donner de type si on les define car le compilateur s’en charge tout seul, ce
qui n’est pas le cas des const. Les variables sont également simples à utiliser, mais
il y a quelques précautions à prendre tout comme avec les const.
Pour déclarer une variable, il va falloir indiquer au compilateur combien de
cases mémoires on veut qu’il lui réserve. On le fera en indiquant le type de chaque
variable.
byte monAge;
Ici, on peut choisir un type byte qui peut contenir un nombre de 0 à 255, il y a
peu de chances que l’on puisse le dépasser. Un byte suffit donc.
Si on veut mémoriser le nombre de jours de soleil dans les îles, on devra
prendre un nombre plus grand, int ou un unsigned int.
int nombreDeJoursDeSoleil;

52/ Chapitre 3 : Le langage


On pourra ensuite effectuer des calculs et mettre les résultats dans ces
variables.
#define ANNEE_DE_NAISSANCE 1910
int anneeDeMesDeuxCentAns;
int nombreDeJoursDeSoleil;
byte monAge;
………
nombreDeJoursDeSoleil = 301;
monAge = monAge + 1; // Si c’est mon anniversaire …
anneeDeMesDeuxCentAns = ANNEE_DE_NAISSANCE + 200;

Les tableaux
Pour ranger nos données, on pourra utiliser les tableaux. Dans un tableau, on
aura des lignes et des colonnes et toutes les données devront être du même type.
On pourra ainsi créer des tableaux de char ou d’unsigned int par exemple.

Tableau à une dimension


Les tableaux à une seule dimension sont simples à créer et à utiliser. C’est un
peu comme une liste dans laquelle on a rangé nos affaires.
char monTableau[10];
Ici, on a créé un tableau de dix éléments de type char. Pour l’instant il est vide,
mais on pourra le remplir par exemple en mettant 123 à la case 5, 43 à la case 2
et 3 à la case 0.
monTableau[5] = 123;
monTableau[2] = 43;
monTableau[0] = 3;

À NOTER
La première case de notre tableau de dix cases aura donc l’indice 0, et la dernière
l’indice 9.

On peut également faire des tableaux de chaînes de caractères. Comme une


chaîne de caractères en C est définie par char*, notre tableau sera donc déclaré
et utilisé ainsi :
char* mesPhrases[10];
mesPhrases[3] = "Salut";
On peut également initialiser notre tableau à sa création, ce qui peut être très
pratique.
char* mesPhrases[4] = { // Tableau de 4 lignes
"Bonjour",
"Arduino",
"Programme",
"Livre"
};

Les bases du langage Arduino /53


Pour accéder à un élément du tableau, il suffira de mettre son indice entre
crochet []. Ainsi, si on veut écrire Arduino, il suffira de faire :
Serial.println(mesPhrases[1]); // Ligne 2, donc indice 1

Tableau à deux dimensions


Les tableaux à deux dimensions sont comme les précédents, mais avec deux
indices. Le premier indice sera le numéro de la ligne, et le second sera le numéro
de la colonne.
Il se déclarera ainsi :
monTableau[4][2];
On a donc un tableau de quatre lignes et de deux colonnes.
Pour trois colonnes, on aurait écrit :
monTableau[4][3];
On peut également faire des tableaux de chaînes de caractères pour faire des
traductions, par exemple avec quatre mots et trois langues.
char* monTraducteur[4][3] = {
{"Bonjour", "Hello", "Buongiorno"},
{"Arduino", "Arduino", "Arduino"},
{"Programme", "Program", "Programma"},
{"Livre", "Book", "Libro"}
};
Pour accéder à un élément du tableau, on donnera tout d’abord le premier
indice entre crochets [] et ensuite le second entre crochets également [].
Par exemple, si on veut la traduction du troisième mot français du tableau en
italien, on aura :
Serial.println(monTraducteur[2][0]); // Donnera Programme
Serial.println(monTraducteur[2][2]); // Donnera Programma

// LES FONCTIONS
Pour écrire notre programme, on va utiliser des fonctions qui sont déjà définies
et connues par notre EDI, ainsi que d’autres fonctions qu’il ne connaît pas mais
que l’on va lui apprendre au fur et à mesure de nos besoins.

Les fonctions simples


Une fonction regroupe un ensemble d’instructions, donc de choses à exécuter.
Pour savoir où commence et où se termine une fonction, on va utiliser des acco-
lades ouvertes et fermées { }.
Une accolade ouverte { marque le début d’un bloc ou d’une fonction, et une
accolade fermée } en marque la fin.
Cette fonction va donc faire ce qu’on lui demande, et va peut-être nous ren-
voyer un résultat de calcul par exemple.
Si on n’attend rien en retour, elle commencera par le mot clé void, qui signifie
vide ou néant. Elle fera simplement ce qu’on lui aura demandé, et elle ne nous
répondra rien.

54/ Chapitre 3 : Le langage


void maFonction() {
ecritAuTableau("Hello");
}
Donc maFonction fera tout ce qu’il y a entre l’accolade ouverte et l’accolade
fermée. À la suite de son nom maFonction, il y a aussi une parenthèse ouverte et
une fermée ( ). Retenons juste cela pour l’instant.
Par contre, si on a besoin d’une réponse, par exemple si on demande à la fonc-
tion effectueAddition de nous retourner le résultat d’une addition qu’elle a
effectuée, on pourra alors le lui demander en lui expliquant ce que l’on attend en
retour, ici un nombre entier de type int par exemple.
int effectueAddition() {
bla bla bla…
renvoieMoiUnResultat …
}
Cette fonction va donc effectuer effectueAddition, et nous renvoyer le résul-
tat dans une case mémoire. Pour placer ce résultat dans la case mémoire que l’on
aura choisi d’appeler calcul, par exemple, on dira :
calcul = effectueAddition();
Si notre fonction est chargée d’effectuer plusieurs additions, comment saura-
t-elle quel résultat nous renvoyer ?
Imaginons qu’elle fasse :
int jeuxARevendre() {
nombreDeCartes = lesRouges + lesBleues;
nombreDeBilles = nombreDeBillesBleues + nombreOeilDeTigre;
nombreDeVieuxJeux = nombreDeBilles + nombreDeCartes;
… … …
}
Est-ce qu’elle va nous renvoyer la quantité de cartes à jouer ? La quantité de
billes ? La quantité de vieux jeux ? Tout à la fois ? Rien du tout ?
C’est simple, on va lui demander de nous retourner la valeur qui nous intéresse
avec l’instruction return ( ).
Si on veut que notre fonction nous retourne le nombreDeVieuxJeux, on écrira
alors :
int jeuxARevendre() {
nombreDeCartes = lesRouges + lesBleues;
nombreDeBilles = nombreDeBillesBleues + nombreOeilDeTigre;
nombreDeVieuxJeux = nombreDeBilles + nombreDeCartes;
return (nombreDeVieuxJeux);
}
Si on voulait qu’elle nous retourne la quantité de billes que l’on peut revendre,
on aurait pu écrire :
int jeuxARevendre() {
nombreDeCartes = lesRouges + lesBleues;
nombreDeBilles = nombreDeBillesBleues + nombreOeilDeTigre;

Les bases du langage Arduino /55


nombreDeVieuxJeux = nombreDeBilles + nombreDeCartes;
return (nombreDeBilles);
}
Bien que notre fonction effectue d’autres calculs, elle ne nous retourne que la
valeur que l’on a choisie avec l’instruction return ( ). Facile…
Par exemple, nous voulons obtenir le résultat de ce calcul dans une case
mémoire que l’on aura appelée auGrenier, on écrira :
auGrenier = jeuxARevendre();
Cette case mémoire auGrenier (que l’on appelle donc une variable) contiendra
maintenant le nombre de billes calculé par notre fonction. On pourra alors s’en
servir pour effectuer d’autres calculs ou pour l’afficher sur un écran par exemple.
Nous allons beaucoup nous servir des fonctions dans nos sketchs, car cela per-
met d’une part de découper un long programme mais aussi de le simplifier.

Les fonctions avec paramètre


On pourrait améliorer notre fonction pour qu’elle ne retourne le calcul effectué
que sur les billesBleues ou que sur les oeilDeTigre. En l’appelant, il va falloir lui
dire ce que l’on attend de plus : donneQuantiteDeBilles mais que lesBleues.
Pour ce faire, on va lui passer un paramètre.
Comment faire ? Et bien on va utiliser les parenthèses ( ) que l’on a mis après
son nom pour lui envoyer une valeur qu’elle va récupérer pour faire ses calculs.
On déclarera la fonction ainsi pour lui expliquer ce que l’on veut :
int donneQuantiteBilles(int quellesBilles) {
bla bla bla
return (leResultatDuCalcul);
}
Maintenant que cette déclaration est faite, il va falloir l’utiliser dans le pro-
gramme et c’est à ce moment-là qu’on lui dira que l’on veut un calcul sur les-
Bleues :
lesBillesAGarder = donneQuantiteBilles(lesBleues);
Si on veut les billes rouges, on pourra lui demander en utilisant la même fonc-
tion, mais en utilisant le bon paramètre.
lesAutresBillesAGarder = donneQuantiteBilles(lesRouges);
Il faudra se rappeler qu’il faut déclarer une fonction avant de l’utiliser. En effet,
notre compilateur ne va pas deviner ce que l’on veut faire si on ne le lui dit pas…
On peut aussi passer plusieurs paramètres à une fonction, par exemple :
int donneQuantiteBilles(int quellesBilles, int quellesAutresBilles) {
bla bla bla
return (leResultatDuCalcul);
}
C’est ce qu’il se passe avec la fonction digitalWrite() de notre programme
Blink, on lui passe deux paramètres. Si tout ceci paraît un peu confus pour l’ins-
tant, pas de panique. Nous aurons l’occasion d’utiliser les fonctions un peu plus
loin et tout deviendra plus clair...

56/ Chapitre 3 : Le langage


LE PROGRAMME BLINK
Tout à l’heure, nous avons compilé et téléversé Blink, et la Led L de la carte
Arduino s’est mise à clignoter.
Voyons maintenant comment tout cela est possible en étudiant son sketch :
// the setup function runs once when you press reset or power the board
void setup() { // initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on
delay(1000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off
delay(1000); // wait for a second
}
Comme nous l’avons déjà vu rapidement, on voit qu’il y a deux parties. Celles-ci
sont essentielles dans un sketch Arduino.
Il s’agit de setup() et de loop(), qui sont toutes les deux des fonctions.
Lorsque notre programme est exécuté par l’Arduino, celui-ci va tout d’abord
exécuter une seule fois les instructions qui se trouvent dans la fonction setup(),
puis il exécutera en boucle tout ce qui se trouve dans la fonction loop(). C’est
ainsi que cela a été défini par ses créateurs lors de la conception de la carte
Arduino et de notre compilateur, et tous les sketchs seront organisés de la
même façon.
Donc, on peut dire que notre sketch est composé de deux fonctions :
void setup() {
}
Et aussi :
void loop() {
}
Nous avons également déjà vu que les lignes commençant par // sont des
commen­taires, et qu’elles ne seront donc pas compilées, ni téléversées. On pourra
donc les ignorer pour nos explications, mais il faut se rappeler que les commen-
taires sont importants pour que nous puissions nous y retrouver dans quelques
jours ou quelques mois. D’ici là, on risque d’avoir oublié ce que l’on a voulu dire et
il peut devenir presque impossible de corriger un bug. On sera obligé de bricoler
notre sketch jusqu’à ce qu’il fonctionne à peu près sans que l’on sache trop pour-
quoi (jusqu’à ce que qu’il tombe en marche…)

// REGARDONS SETUP( ) DE PRÈS


void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}

Le programme Blink /57


On voit qu’elle va effectuer ce qu’il y a entre ses deux accolades {}, c’est-à-dire :
pinMode(LED_BUILTIN, OUTPUT);
Premier réflexe : regarder les aides de l’EDI.
Cette aide nous indique ce que fait la fonction pinMode( ).

Figure 3.3 Aide de pinMode

En résumé, pinMode( ) permet de configurer les pins des connecteurs de


­l’Arduino en entrée ou en sortie.
Dans le détail, au paragraphe Syntax, on voit que cette fonction comporte deux
paramètres entre parenthèses : pin et mode. On retrouve un peu notre syntaxe
des billes bleues de tout à l’heure.
Ici, le paramètre pin indique le numéro de la pin que l’on veut prendre en
compte, et le paramètre mode indique si on veut la mettre en entrée avec la
valeur INPUT, en sortie avec la valeur OUTPUT, ou en INPUT_PULLUP (ne nous
en ­occupons pas pour l’instant).
On voit donc que Blink commence par demander à setup d’utiliser pinMode
pour mettre la pin nommée LED_BUILTIN en OUTPUT.
Pour notre compilateur, la Led L montée sur la carte électronique s’appelle
LED_BUILTIN. On pourra l’appeler autrement dans un moment.

58/ Chapitre 3 : Le langage


// ET PUIS LOOP
Une fois setup() effectué, notre Arduino va exécuter la fonction loop() indé-
finiment, et c’est dans cette fonction que l’on va mettre le cœur de notre pro-
gramme.
Setup() n’était que les préparatifs.
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}
>> La première instruction est :
digitalWrite(LED_BUILTIN, HIGH);
>> L’aide d’Arduino nous indique que digitalWrite() utilise deux paramètres.
Le premier qui est ici fixé à LED_BUILTIN indique que l’on parle de la Led L
embarquée sur la carte, et le paramètre HIGH indique que l’on veut que
­l’Arduino Uno envoie une tension de 5 volts sur cette LED_BUILTIN.
>> Si on lui donne 5 volts, elle va s’allumer et si on lui envoie 0 volt, elle va
s’éteindre.
>> La deuxième instruction est :
delay(1000);
>> Avec delay(), notre Arduino va rester à attendre en se tournant les pouces,
sans rien faire d’autre. Toujours d’après l’aide, il va attendre le temps qu’on
lui demande par le paramètre qu’on lui envoie, avec un temps compté en
millisecondes. La milliseconde est le millième de seconde, et donc 1 seconde
= 1 000 ms.
>> Ici, delay(1000) va donc demander à notre Arduino d’attendre pendant
1 000 millisecondes, soit 1 seconde.
>> La troisième instruction est :
digitalWrite(LED_BUILTIN, LOW);
>> On comprend tout de suite que l’on va mettre la LED_BUILTIN à 0 volt, et
donc l’éteindre.
>> La dernière instruction est de nouveau :
delay(1000);
On arrive ensuite à la parenthèse qui ferme l’ensemble, et la fonction se ter-
mine.
Comme nous l’avons dit, loop() s’exécute indéfiniment sur notre carte Arduino.
On va donc avoir :
>> On allume la Led L.
>> On attend 1 seconde.

Le programme Blink /59


> On éteint la Led L.
> On attend 1 seconde.
> Et on recommence tout indéfiniment.

Figure 3.4 On a fait un clignotant (blink en anglais) !

ÉTUDE DES PREMIÈRES FONCTIONS ARDUINO


Notre IDE met beaucoup de fonctions à notre disposition, nous allons étudier
les plus utiles pour nos futurs projets.
Pour chaque fonction, je vous conseille d’aller sur le site arduino.cc afin de lire
l’aide complète, même en anglais.

/ FONCTIONS
digitalWrite()
digitalWrite() permet d’écrire 1 ou 0 sur la pin du connecteur que l’on désire
activer ou désactiver.
pin est le numéro de la pin, value est l’état HIGH ou LOW que l’on désire mettre.
On s’en servira pour allumer ou éteindre une Led par exemple.
Syntaxe :
digitalWrite(pin, value)
Paramètres :
> pin : Numéro de la pin
> value : HIGH ou LOW
Exemple :
digitalWrite(LedRouge, LOW)

digitalRead()
digitalRead() permet de lire l’état de la pin du connecteur que l’on désire
interroger.
On pourra s’en servir pour lire l’état d’un bouton poussoir.

60/ Chapitre 3 : Le langage


Syntaxe :
digitalRead(pin)
Paramètres :
>> pin : numéro de la pin
Exemple :
lectureDeLaPin = digitalRead(leBoutonPoussoir);

pinMode()
pinMode() permet de mettre la pin du connecteur en entrée ou en sortie.
Le mode peut être en entrée INPUT, en sortie OUTPUT ou encore en entrée avec
une résistance de pull-up activée INPUT_PULLUP (nous reparlerons de ce mode).
On l’utilisera pour indiquer à l’Arduino comment arranger son électronique
interne pour lire un bouton poussoir ou activer une Led par exemple.
Syntaxe :
pinMode(pin, mode);
Paramètres :
>> pin : numéro de la pin
>> mode : INPUT, OUTPUT ou INPUT_PULLUP
Exemples :
pinMode(LedRouge, OUTPUT);
pinMode(leBoutonPoussoir, INPUT);

analogRead()
En plus de ses entrées numériques qui ne peuvent gérer que des valeurs
binaires (marche/arrêt ou on/off par exemple), l’Arduino Uno comporte des
entrées analogiques (des pins A0 à A5), qui peuvent lire toutes les valeurs
­comprises entre 0 et 5 V, avec une grande précision.
Dans ses circuits internes, il a un convertisseur analogique/numérique qui
va pouvoir transformer une tension 0‑5 V en une valeur binaire que l’on pourra
ensuite utiliser dans nos programmes.
Nous avons déjà vu les conversions décimales vers binaire, et il s’agit un peu
de la même chose pour les conversions analogiques/numériques. Notre µC va
regarder ce qu’il se passe sur une de ses entrées analogiques avec une grande
précision, regarder si cette valeur est petite, moyenne, grande ou autre et ranger
le résultat de sa conversion sur un mot binaire de 10 bits.
Cela veut dire que pour une tension de 0 V sur une de ces entrées, notre µC va tra-
duire ça en 0b0000000000 et pour une tension maximale de 5V il va traduire cela
en 0b1111111111. Pour 2,5 V ce sera la moitié de cette valeur binaire et ainsi de suite.
Si on refait un rapide calcul sur 10 bits, 0b1111111111 est égal à 1 024 en décimal. Il est
donc capable de mesurer cette tension de 5V en la découpant en 1 024 morceaux.
On en reparlera un peu plus tard en étudiant le potentiomètre. Retenons le
fait que la valeur retournée par cette fonction est sur 10 bits (1 024 en décimal),

Étude des premières fonctions Arduino /61


et qu’il faudra donc que le type choisi pour ranger le résultat soit bien adapté.
On ne pourra pas ranger ce résultat dans une variable de type byte, car le résultat
maximal qui pourrait y être mémorisé est 255. On choisira un type plus grand,
int ou unsigned int.
La documentation du site arduino.cc nous indique que la fonction analogRead()
retourne une valeur de type int. On choisira donc une variable de type int pour y
ranger le résultat d’une conversion.
Syntaxe :
analogRead(pin);
Paramètres :
>> pin : numéro de la pin
Exemple :
int valeurMesuree;
valeurMesuree = analogRead(entreePotentionmetre);

analogWrite()
La fonction analogWrite() permet de créer une tension variable sur la pin considé-
rée. Sur la carte Arduino Uno, il s’agira d’un signal PWM qu’il faudra associer à d’autres
composants pour créer un vrai signal analogique que nous étudierons plus tard.
Syntaxe :
analogWrite(pin, value)
Paramètres :
>> pin : numéro de la pin
>> value : valeur entre 0 et 255
Exemple :
int out = 9; // sortie analogique sur pin 9
void setup() {
pinMode(out, OUTPUT); // pin out en sortie
}
void loop() {
analogWrite(out, 125); // met un PWM à 125
}

tone()
Si on connecte un buzzer ou un haut-parleur sur la sortie pin, la fonction tone()
permet de créer un signal qui permettra de produire un son de fréquence fre-
quency. Cette fréquence s’exprime en hertz (Hz).
Par exemple, la note LA a une fréquence de 440 Hz, et chaque note est définie
par sa fréquence.
Pour stopper le son, on utilisera ensuite la fonction noTone().
Une autre syntaxe est disponible pour cette fonction avec laquelle on peut indi-
quer la durée du son par le paramètre duration. Dans ce cas, la fonction noTone()
n’est plus utile.

62/ Chapitre 3 : Le langage


Syntaxe :
tone(pin, frequency)
tone(pin, frequency, duration)
Paramètres :
>> pin : numéro de la pin
>> frequency : fréquence à générer
>> duration : durée du signal sonore
Exemple :
tone(sortieBuzzer, 440) // Joue la note La sur la pin sortieBuzzer

noTone()
Cette fonction permet de stopper le signal qui a été mis à disposition par la
fonction précédente sur la sortie pin.
Syntaxe :
noTone(pin)
Paramètres :
>> pin : numéro de la pin
Exemple :
noTone(sortieBuzzer)

delay()
La fonction delay() permet de créer un temps d’attente d’une durée de ms,
exprimé en millisecondes (ms : millièmes de secondes).
Syntaxe :
delay(ms)
Paramètres :
>> ms : durée en millisecondes
Exemple :
delay(1000); // Crée un temps d’attente de 1 seconde

delayMicroseconds()
La fonction delayMicroseconds() permet quant à elle de créer un temps
­d’attente de us, exprimé en microsecondes (µs : millionièmes de seconde).
La valeur maximale de ce délai est de 16 383 microsecondes (16 383 µs).
Il y a 1 000 µs dans une ms, et 1 000 ms dans 1 seconde.
Syntaxe :
delayMicroseconds(us)
Paramètres :
>> ms : durée en microsecondes
Exemple :
delayMicroseconds(1000); // Crée un temps d’attente de 0,001 seconde

Étude des premières fonctions Arduino /63


// CONSTANTES DÉCLARÉES
#define
Le mot clé #define permet de déclarer et donner une valeur à une constante
pour la compilation du programme.
Ainsi, pour définir la valeur de la constante LED_ROUGE qui est branchée sur
la pin 8, on écrira :
#define LED_ROUGE 8
Comme nous en avons déjà parlé, les noms des constantes définies par #define
sont généralement écrits en majuscules afin de mieux les reconnaître.
La ligne se termine sans point virgule.

#include
#include indique au compilateur qu’il devra inclure ce qu’il y a dans un fichier
bibliothèque lors de la compilation.
Par exemple, si on veut inclure le code source qu’il y a dans le fichier biblio_
LCD.h que l’on avait écrit pour un autre projet, on indiquera :
#include <biblio_LCD.h>
Ainsi, on pourra utiliser tout ce qu’il y a dans ce fichier bibliothèque, sans avoir
à tout réécrire (d’où l’intérêt d’une bibliothèque…).
Nous essaierons les bibliothèques un peu plus tard.

HIGH
Il s’agit d’une constante qui correspond à l’état haut dans le monde Arduino.
Ainsi, on pourra l’utiliser pour activer une sortie :
digitalWrite(LED_BUILTIN, HIGH);

LOW
À l’opposé de HIGH, il s’agit d’une constante qui va servir à mettre une sortie à
l’état bas.
digitalWrite(LED_BUILTIN, LOW);

INPUT
INPUT est une constante du monde Arduino qui permettra de positionner une
broche du µC en entrée afin de pouvoir lire la valeur du signal qui arrive dessus.
Par exemple, pour paramétrer une pin du microcontrolleur qui devra recevoir
un bouton poussoir pour lire son état, on écrira :
pinMode(BOUTON, INPUT);

OUTPUT
De la même manière, OUTPUT servira à configurer une pin du µC en sortie, pour
activer une Led par exemple :
pinMode(LED_ROUGE, OUTPUT);

64/ Chapitre 3 : Le langage


INPUT_PULLUP
Il s’agit d’une constante un peu particulière qui permettra d’activer une résis-
tance interne au µC sur l’entrée désirée.
Ainsi, il sera inutile de câbler une résistance externe pour la lecture d’un bou-
ton poussoir par exemple. Nous pourrons utiliser cette fonction sur l’un de nos
montages.
pinMode(BOUTON, INPUT_PULLUP);

LED_BUILTIN
Cette constante représente la Led qui est montée en standard sur notre carte
Arduino, et que nous activons avec le premier programme Blink.
digitalWrite(LED_BUILTIN, HIGH);

true
Cette constante vaut 1 et représente la valeur Vrai pour des tests.

false
Celle-ci représente la valeur Faux et vaut 0.

// OPÉRATEURS
Pour effectuer des opérations comme l’addition ou la multiplication par
exemple, nous aurons besoin d’opérateurs.
Les opérateurs qui suivent sont donc utilisés pour les opérations mathéma-
tiques, mais aussi pour comparer des nombres ou des variables. Il existe égale-
ment des opérateurs logiques qui permettront de faire des opérations sur nos
octets.

Addition, soustraction, multiplication, division


Ces opérateurs sont maintenant connus, et on ne va pas s’y attarder : + – * /
resultat = 1 + 1;
resultat = resultat * 25;
resultat = resultat / 3;
resultat = 25 - resultat + 56;

Test d’égalité, symbole ==


Pour tester une égalité, on va utiliser l’opérateur ==, qui est différent de l’opé-
rateur d’affectation =.
Si on veut dire que maValeur vaut 4, on écrit :
maValeur = 4;
Si on veut tester maValeur pour savoir si elle est égale à 4, on écrira :
Si (maValeur == 4)
alors …

Étude des premières fonctions Arduino /65


Test d’inégalité, symbole !=
Pour tester une inégalité, on utilisera alors l’opérateur !=
Si on veut par exemple savoir si maValeur est différente de 4, on écrira :
Si (maValeur != 4)
alors …

Test Inférieur et Supérieur


Pour connaître l’ordre de grandeur d’une variable, on utilisera les opérateurs :
>> Inférieur à : <
>> Supérieur à : >
>> Inférieur ou égal : <=
>> Supérieur ou égal : >=
Par exemple :
Si (maValeur >= 3) et si (maValeur < 5)
alors …

Opérateur de comparaison ET, symbole &&


Cet opérateur ET && permet de comparer deux variables logiques et de ren-
voyer true si les deux sont vraies et false dans le cas contraire.
Par exemple,
Si (digitalRead(BP1) == true) && (digitalRead(BP2) == true)
alors … // Si les deux valeurs sont égales à true, alors …

Opérateur de comparaison OU, symbole II


Cet opérateur OU || permet de comparer deux variables logiques et de ren-
voyer true si au moins une des deux est vraie.
Par exemple,
Si (digitalRead(BP1) == true) || (digitalRead(BP2) == true)
alors … // Si au moins une des deux valeurs vaut true, alors …

Opérateur NON, symbole !


Cet opérateur NON ! permet de renvoyer true si la variable est false, et false si
la variable est vraie. Il se place devant le nom de la variable à tester.
Par exemple,
Si ( !digitalRead(BP1) == true )
alors … // Si digitalRead() N’EST PAS égale à true, alors …

Opérateurs composés
Certains des opérateurs vus précédemment peuvent avoir une écriture un peu
particulière, mais très pratique.
Par exemple, on peut très bien écrire :
x = 7;
x = x + 1; // on ajoute 1 à la variable x, donc x = 8

66/ Chapitre 3 : Le langage


Pour simplifier, les opérateurs composés permettent d’écrire :
x = 7;
x++; // x ++ permet d’ajouter 1 à x, donc x = 8
On peut faire la même chose avec les autres opérateurs mathématiques.
x=7;
x++; // donc, x = 8
x--; // donc, x = 7
Si on voulait ajouter ou retrancher autre chose que 1, on a aussi deux solutions.
x = 7;
x += 2; // x vaut maintenant 9 ( x = x + 2 )
x -= 3 // x vaut maintenant 6 ( x = x - 3 )
On peut faire la même chose avec les autres opérateurs.
x = 5;
x *= 2; // x = 2*x = 2*5 = 10
On peut aller plus loin en écrivant l’opérateur composé avant ou après le nom
de la variable, par exemple :
x = 7;
y = x; // y = 7
z = x++; // Donc, z = x, puis x = x +1, donc z = 7 et x = 8
w = ++x; // Donc, w = 8, car on a d’abord fait ++ à x avant de le mettre
// dans w
// donc ++x donne x = 8, donc w = 8
Dans ces exemples, l’ordre d’écriture est important, et le résultat en dépend.
Selon que l’on met l’opérateur avant ou après la variable, on récupèrera son
ancienne ou sa nouvelle valeur.
On peut faire la même chose avec les opérateurs logiques, comme avec :
maValeur &= 0b00001111 // maValeur = maValeur & 0b00001111

Opérateurs logiques
Un opérateur logique va donc, comme son nom l’indique, faire des opérations
de logique booléenne. On va ainsi pouvoir faire des opérations sur des bits, et des
donc des opérations sur des octets.
Par la suite, on pourra appliquer ces opérateurs à des signaux électriques à
l’aide de portes logiques. On parle alors de logique combinatoire.
Il ne faut PAS les confondre avec les opérateurs de comparaison !

ET logique, symbole & A B A&B


Par exemple, si on a un bit A et un bit B, on peut dire que 0 0 0
pour chaque valeur binaire que peuvent prendre A et B on 0 1 0
aura les résultats suivants : 1 0 0
On peut bien sûr remplacer 0 et 1 par true et false. 1 1 1
On voit sur ce tableau que pour avoir A & B vrais, il faut
que A soit vrai et que B soit vrai. Dans tous les autres cas, le résultat est faux (0).
Cette fonction ET s’appelle aussi fonction AND. Ainsi, on pourra écrire A AND B.

Étude des premières fonctions Arduino /67


OU logique, symbole I A B AIB
Pour nos mêmes bits A et B, le OU logique (ou OR) don- 0 0 0
nera les résultats suivants : 0 1 1
On a ici A OR B qui est vrai lorsque A tout seul est vrai, 1 0 1
mais aussi lorsque B tout seul est vrai (ou les deux).
1 1 1
On a donc bien l’un OU l’autre de vrai pour avoir un résul-
tat vrai.

NON logique, symbole ~


A B A&B ~(A & B)
Le symbole tilde ~ représente le NON logique
(NOT). Si A vaut vrai, alors ~A vaudra faux et 0 0 0 1
inversement. Si A vaut 0, alors ~A vaudra 1. 0 1 0 1
On peut également combiner le NOT avec le ET 1 0 0 1
ou avec le OU : 1 1 1 0
Ici, on a effectué un A AND B, ou A & B, puis on
a inversé le résultat avec un opérateur ~, ce qui
A B AIB ~(A I B)
donne un opérateur NON ET, ou NAND.
0 0 0 1
Pour le NOR, on appliquera le même principe :
En électronique, on utilisera les notations A 0 1 1 0
AND B ou A NAND B par exemple. 1 0 1 0
En programmation, ce sera A & B ou bien ~(A & B). 1 1 1 0

Les portes NAND


Il existe des circuits intégrés qui sont spécialisés dans ces opérations : les cir-
cuits logiques. Parmi eux, on trouvera la très utilisée porte NAND 74LS00, et sa
fiche de caractéristiques indique son fonctionnement ainsi.

Figure 3.5 Porte NAND (doc. Fairchild semiconductor)

On retrouve bien notre tableau, avec cependant une notation encore différente
pour dire ~(A&B).
Ici, il y a Y = AB, avec une barre au-dessus. On lit cela AB barre.
La notation en algèbre de Boole dit que AB (ou encore A.B) veut dire A & B,
donc A ET B.

68/ Chapitre 3 : Le langage


La barre, quant à elle, comme elle est placée sur A et B en même temps,
s­ ’applique au résultat de AB. Comme il est difficile d’écrire cette barre au-dessus
des deux symboles avec un ordinateur, on peut également écrire (AB)\. Ainsi,
l’antislash \ veut dire NON. Donc, pour écrire NON A, en informatique on écrira
~A alors qu’en électronique on écrira A\ (que l’on prononcera A barre).
Pour le OR, l’écriture sera le symbole + en électronique : A I B sera alors A+B.
De même, pour écrire une équation en informatique, on pourra dire : Y = ~(A & B) I C
En électronique, on écrira : Y = (AB)\ + C
Cela paraît un peu confus, mais c’est en fait très simple, il suffit de s’y entraîner
un peu et de respecter l’ordre des barres et des parenthèses :
Par exemple, Y = ( (A+B) + A\ +C)\ . AC\
voudra dire :
Y = NON (A OU B OU NON A OU C) ET A ET NON C
Personnellement, je trouve la première notation plus simple…
 
À quoi ça sert ?
Eh bien en électronique, on aura souvent besoin de créer des signaux à partir
d’autres signaux. Pour cela, on va utiliser des composants qui sauront faire ces
opérations logiques simples.
À nous de les combiner avec des équations comme celles-ci afin de créer des
signaux complexes.
Par exemple, dans notre monde on pourrait dire qu’il fait chaud si :
leSoleilBrille ET laTemperatureEstAgreable ET NON laPluie OU unBonRadiateur.
Si on remplace cela par des variables et des opérateurs logiques, et si on se
dit que :
A = leSoleilBrille,
B = laTemperatureEstAgreable ,
C = laPluie,
D = unBonRadiateur,
on a bien : il fait chaud = ABC\ + D
Facile !

Symboles des opérateurs logiques en électronique


Ces opérateurs logiques ont chacun un symbole en électronique afin de pou-
voir les incorporer dans un schéma.

OR
Sortie = A + B donc A OU B

Figure 3.6

Étude des premières fonctions Arduino /69


AND
Sortie = AB donc A ET B

Figure 3.7

NOT
Sortie = A\ donc NON A

Figure 3.8

NOR
Sortie = (A+B)\ donc NON (A OU B)

Figure 3.9

NAND
Sortie = (AB)\ donc NON (A ET B)

Figure 3.10

Il reste encore un opérateur que nous n’avons pas vu et qui est le XOR, ou bien
OU EXCLUSIF.

70/ Chapitre 3 : Le langage


XOR
Son symbole est ^, et sa table de vérité est la suivante : A B A^B
On voit que pour être vrai, il faut qu’une seule des deux 0 0 0
entrées soit vraie. Si les deux sont vraies ou sont fausses en 0 1 1
même temps, le résultat sera faux.
1 0 1
Son symbole en électronique est :
1 1 0
Sortie = A ^ B

Figure 3.11

On utilisera assez peu le XOR par rapport aux autres portes, mais il peut nous
servir à simplifier des équations.

Utilisation des portes logiques


Par exemple, si nous voulons inverser un signal sur notre schéma ou bien créer
un nouveau signal par la combinaison de plusieurs autres, on utilisera des portes
logiques comme celles-ci. C’est ce qu’il se passe à l’intérieur de notre µC qui
­combine plusieurs milliers de ces portes logiques pour répondre aux instructions
que l’on va lui demander d’exécuter.
Après ce petit tour logique, passons aux instructions qui nous permettront
d’écrire notre programme.

// INSTRUCTIONS
Afin d’indiquer à notre µC ce qu’il doit faire précisément, on va utiliser tout un
jeu d’instructions qui est propre à chaque langage. Par exemple, en C on pourra
dire :
if (valeur == 10) {
   montantDuLoyer = 25;
   Changer = true;
}
En assembleur, on aura quelque chose qui ressemblera à ceci :
.CursOff MOVE.L D0, (A0)+     ; Display On, Curseur off, not Blink
MOVEQ #$0C, D0
MOVE.B D0, LCD
JSR .WaiLCD
MOVE.L -(A0), D0
RTS

Étude des premières fonctions Arduino /71


En Swift, on aura du code qui ressemblera à :
if player.frame.intersects(tileRect) && direction == .below {
  print(«  touché")
   self.player.shouldJump = true
   player.onGround = true
   adjustment += CGPoint(x:0, y:intersection.size.height)
   velocityFactor *= CGPoint(x:1,y:0)
}
Comme on le voit, chaque langage a sa propre syntaxe et ses propres règles,
même si certains sont relativement proches les uns des autres. Le langage uti-
lisé pour programmer l’Arduino a de grandes ressemblances avec le C et le C++,
ce qui est un gros avantage car ceux-ci sont très utilisés dans l’industrie (machines,
jeux vidéos, logiciels embarqués, etc.).
Les instructions que nous utiliserons sont donc les suivantes, il n’y a rien de bien
compliqué, il faut juste s’entraîner à les utiliser et ne pas hésiter à lire les aides.

if
L’instruction if, qui veut dire si en anglais, permet de tester la valeur de nos
variables. Par exemple, si on veut savoir si leScore est égal à 10, on utilisera la
forme suivante en pseudocode (du code qui ressemble à du code, et qui n’en est
pas vraiment mais qui permet de réfléchir…)
si (leScore est 10)
alors onLesABattu
onEstContents
onVaFeterCa
Ce que l’on peut facilement traduire par :
if (leScore == 10) {
onLesABattu = true;
onEstContents = true;
onVaFeterCa = true;
}

PRÉSENTATION DU CODE
Contrairement à d’autres langages comme Python, nous n’avons pas besoin de
respecter une mise en forme particulière pour notre code. On pourra tout aussi
bien écrire :
if (leScore == 10) {
onLesABattu = true;
onEstContents = true;
onVaFeterCa = true;
}
Ou encore :
if (leScore == 10) {
onLesABattu = true;

72/ Chapitre 3 : Le langage


onEstContents = true;
onVaFeterCa = true;
}
Ou même :
if (leScore == 10) {
onLesABattu = true;onEstContents = true;onVaFeterCa = true;
}
Il n’y a pas de règle à propos des espaces ou des tabulations que l’on peut mettre
en début de chaque ligne. Le principal est de garder un code clair et aéré, c’est tout.

On voit ici que la ligne commence par if, puis on met ce que l’on veut tester
entre parenthèses. On met ensuite une paire d’accolades {} entre lesquelles on
va mettre ce qu’il y a à faire si la condition testée est vraie.
On a donc la syntaxe suivante :
if (condition est vraie) {
on fait ceci
et encore cela
}
Une erreur de frappe courante est d’écrire :
if (leScore = 10) {
bla bla bla…
}
Qui voit l’erreur ?
Eh bien on a utilisé = au lieu de == (un seul signe = au lieu de deux).
On a ainsi dit leScore vaut 10 au lieu de poser la question Est-ce que le score
vaut 10 ? Grave erreur, car le compilateur ne verra pas l’erreur. En effet, il n’y a
pas de faute de syntaxe. Par contre, le programme ne fonctionnera pas comme
attendu.
Nous avons déjà vu les opérateurs de comparaison, comme == ou encore >=.
C’est ici que l’on va principalement les utiliser.
De même, s’il n’y a qu’une seule chose à faire après la comparaison, on peut se
passer de mettre les accolades :
if (leScore > 10)
onEstSuperBons = true;
On peut également utiliser plusieurs termes dans la comparaison.
Par exemple, si on veut tester ceci :
si (leMatch est gagné) et (leTemps est ensoleillé)
alors on va piqueniquer
On pourrait utiliser l’opérateur ET que nous avons vu précédemment :
if ((leMatchEstGagne == true) && (leTemps == SOLEIL)) {
onVaPiqueNiquer();
}

Étude des premières fonctions Arduino /73


On voit que chaque valeur à tester est entourée de parenthèse, de même que
l’ensemble des valeurs à tester : if ( (…) && (…) )
De même, la ligne du if ne comporte pas de point virgule.

else
Le else est utilisé avec le if. Si on traduit else en français, cela veut dire autre,
dans le sens autrement ou sinon.
On peut donc dire par exemple :
si (leMatch est gagné) et (leTemps est ensoleillé)
alors on pourrait piqueniquer
sinon
on mangera dedans
et on rentrera en bus
Et donc en code :
if ((leMatchEstGagne == true) && (leTemps == SOLEIL))
onVaPiqueNiquer();
else {
onMangeraDedans();
onRentreraEnBus = true;
}
On voit ici que je n’ai pas mis d’accolade après le if. En effet, il n’y a qu’une
seule instruction ensuite. Par contre, j’en ai mis pour le else car il y a plusieurs
lignes à prendre en compte.
On peut donc dire en résumé :
if (condition vraie) {
on fait ceci
et cela
}
else {
on fera ça
et ça
}
On peut même enchaîner les instructions if pour traiter plusieurs cas.
if (condition vraie) {
on fait ceci
et cela
}
else if (autre condition vraie) {
on fera ça
}
else {
on fera ça
et ça
}

74/ Chapitre 3 : Le langage


Que l’on peut traduire par le pseudo code suivant :
Si (condition est vraie)
alors on fait ça
sinon si (l’autre condition est vraie)
alors on fait ça
sinon on fera ça

while ()
L’instruction while permet d’effectuer une boucle, c’est-à-dire que si la condi-
tion qui se trouve entre parenthèses est vraie, le programme va effectuer ce qu’il
y a entre les parenthèses suivantes indéfiniment.
Il ne sortira de cette boucle que lorsque la condition deviendra fausse, et il
restera dans la boucle tant que la condition ne sera pas remplie.
On peut par exemple dire :
Tant que (leScore < 10)
onMarqueDesButs
etOnContinue
encoreEtEncore
Ce que l’on peut traduire par :
while (leScore < 10) {
onMarqueDesButs();
etOnContinue();
encoreEtEncore();
}
Comment sortir de la boucle ? On en sortira lorsque leScore sera égal à 10, ce
qui veut dire qu’il faut marquer un but à chaque tour de while si on veut s’en sortir
rapidement… Ensuite, le programme reprendra son cours normal.
while (leScore < 10) {
onMarqueDesButs();
etOnContinue();
encoreEtEncore();
leScore ++; // Ici, leScore = leScore +1
}
onAGagne(); // A la sortie de la boucle, on continue
Si la condition est vraie au moment où l’on va rentrer dans la boucle, celle-ci ne
sera pas exécutée. En effet, si on a déjà 10 buts ou plus, pas la peine d’en marquer
d’autres, on a déjà gagné.

Étude des premières fonctions Arduino /75


En termes d’organigramme, on va pouvoir écrire cela ainsi :

Figure 3.12 Organigramme du while()

do...while ()
L’instruction do while () ressemble à l’instruction while().
La seule différence est que la condition est testée à la fin de la boucle, ce qui
veut dire que celle-ci sera exécutée au moins une fois.
do {
onMarqueDesButs(); // On marque TANT QUE le score est < 10
} while(leScore < 10);

for
Pour faire des boucles où on comptera le nombre de tours effectués, on utili-
sera une boucle for.
Par exemple :
for (int i=0; i<10; i++) {
onRepete(); // On refait ça 10 fois
}

76/ Chapitre 3 : Le langage


Ici, on répète cette boucle dix fois, depuis le moment où la variable i vaut 0
jusqu’au moment où elle vaudra 10. À chaque tour de boucle, i sera incrémenté
par l’instruction i++ comprise dans le for.
On peut également se servir de i pour faire quelque chose avec à chaque tour :
for (int i=0; i<10; i++) {
Serial.println(i);
}
Dans cet exemple, on comptera de 0 à 9 sur le moniteur série, donc 10 fois.

goto
L’instruction goto est très peu utilisée en C, et on évitera son emploi.
On pourra s’en servir pour sortir d’une boucle, et aller à un endroit bien spéci-
fique du programme.
for (int i=0; i<10; i++) {
Serial.println(i);
if (i==4) goto QUATRE;
}
QUATRE:
Serial.println("QUATRE FOIS");
Lorsque i vaudra 4, au lieu de continuer dans la boucle normalement, le pro-
gramme sera interrompu et ira directement à l’étiquette QUATRE. Le résultat sur
le Moniteur Série sera alors 0-1-2-3-4-QUATRE FOIS…

return
L’instruction return permet de retourner un résultat depuis une fonction. Si
une fonction doit retourner la valeur d’une variable x de type int par exemple,
on aura alors :
int leCalcul(void) {
x = x+1;
return(x);
}
On pourra alors récupérer le résultat de ce calcul lors de l’appel de la fonction :
y = leCalcul();
Dans ce cas-là, la variable y prendra la valeur retournée par notre fonction,
c’est-à-dire par ce qui a été calculé dans leCalcul().

break
Le break va permettre de casser une séquence, par exemple pour sortir d’une
boucle for ou d’un while plus tôt que prévu, sans exécuter le reste.
for (i=0, i<10, i++) {
Serial.println(i);
if (i==4) break; // On sort prematurement
}

Étude des premières fonctions Arduino /77


switch...case
Si on veut faire quelque chose si laVariable vaut 1, et autre chose si elle vaut
2, et encore autre chose si elle vaut 4, on pourrait faire par exemple :
if (laVariable == 1) {
onFaitCeci();
}
else if (laVariable == 2) {
onFaitCela();
}
else if (laVariable == 4) {
ouEncoreCa();
etAussiCa();
}
Une autre façon de faire est d’utiliser un switch.
switch(laVariable) {
case 1: onFaitCeci();
break;
case 2: onFaitCela();
break;
case 4: ouEncoreCa();
etAussiCa();
break;
default:
break;
}
Dans le cas (case) où laVariable vaut 1, onFaitCeci(), dans le cas où elle vaut
2, onFaitCela(), et ainsi de suite.
Chaque case se termine par un break, ce qui permet de mettre plusieurs ins-
tructions à faire dans le même case, comme dans le case 4.
Si on n’a aucun cas qui se vérifie, on sautera au default, qui peut contenir une
instruction faire, ou juste un break s’il n’y a rien de spécial à faire.

continue
À l’inverse de break, continue va permettre de retourner au début de la boucle
si on le souhaite, sans effectuer les instructions qui suivent :
for (int i = 0; i < 10; i ++)
{
if (i > 4){ // retour au debut si i > 4
continue;
Serial.println(i); // On ecrit: 0 1 2 3 4 0 1 2 …
}
Avec tout ça, on a déjà de quoi bien s’amuser, et passer de longues heures à coder.
Il ne faudra pas hésiter à faire des petits sketches de quelques lignes, juste
pour essayer et voir comment fonctionnent ces instructions.
Le moniteur Série que nous utiliserons plus tard sera alors d’une grande utilité.

78/ Chapitre 3 : Le langage


PREMIER PROGRAMME EN SOLO : MONBLINK
Pour notre premier programme en solo, on va partir d’un exemple que nous
connaissons bien à présent : Blink.
On va donc charger Blink dans l’éditeur, et le sauver sous un autre nom afin
de ne pas modifier Blink lui-même. Ainsi, on pourra le retrouver intact si besoin.

Figure 3.13 Ouvrir Blink

Comme tout à l’heure, on va dans le menu Fichier, Exemples, 01.Basics, et Blink.


Nous allons maintenant renommer ce fichier en l’appelant par exemple MonBlink.
Allons dans le menu Fichier, puis Enregistrer sous…
Dans la fenêtre qui s’ouvre alors, nous pouvons donner un nouveau nom à notre
fichier, donc MonBlink.

Figure 3.14 MonBlink

Notre EDI va l’enregistrer dans le répertoire Croquis, qui est le répertoire par défaut
de nos sketchs. Ce répertoire par défaut est défini dans les Paramètres d’Arduino.

Premier programme en solo : MonBlink /79


Pour ma configuration, ce répertoire est le suivant dans la ligne Emplacement
du carnet de croquis du menu Arduino/Préférences.

Figure 3.15 Emplacement du carnet de croquis

Si on va voir ce qu’il se passe à cet emplacement, car nous sommes curieux, on


verra qu’un répertoire a automatiquement été créé, et qu’il s’appelle MonBlink.
Dans ce répertoire, il y a un fichier qui s’appelle MonBlink.ino et il s’agit de notre
sketch lui-même. Pour l’EDI, chaque sketch doit se trouver dans un répertoire qui
porte le même nom que lui. Ça l’aide à s’y retrouver, laissons-le donc faire…
À présent, nous avons donc notre propre programme que nous allons pouvoir
modifier.

Figure 3.16 MonBlink

80/ Chapitre 3 : Le langage


On voit bien que dans le titre de sa fenêtre, l’EDI l’a bien appelé MonBlink.
Sur la ligne 1 de l’EDI, on peut remarquer qu’il y a une tout petite case avec
le signe – à l’intérieur. En cliquant sur ce signe, le bloc de commentaire qu’il
y a au départ du fichier va disparaître. Ainsi, la lecture sera plus simple et les
­commentaires du début de fichier ne seront pas supprimés, mais simplement
cachés. Le signe – s’étant alors transformé en signe +, on pourra faire réappa-
raître ces commentaires en cliquant simplement dessus. On pourra faire de même
pour les fonctions sur un grand programme.

Figure 3.17 Cacher un bloc de lignes

On a caché un bloc de commentaires mais dans un long programme, on pourra


cacher des lignes de code afin de faciliter la lecture.
Si on avait créé un nouveau programme avec la commande Fichier/Nouveau,
l’IDE aurait créé un nouveau Sketch avec deux parties que l’on retrouvera dans
tous nos programmes :
void setup() {
// put your setup code here, to run once:
}
Pour rappel, cette première partie setup est utilisée pour placer tout ce que
notre Arduino devra faire une seule fois au début de chaque lancement.
void loop() {
// put your main code here, to run repeatedly:
}
Cette deuxième partie loop est utilisée pour placer le code source qui sera
notre programme par lui-même.
Pour l’instant, on va réfléchir un peu à ce que l’on pourrait apporter comme
améliorations à notre nouveau sketch MonBlink.

Premier programme en solo : MonBlink /81


Voici comment il se présente pour l’instant, sur la base de Blink.
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}
On voit que le temps du delay() est 1 000 pour l’allumage et pour l’extinc-
tion de la Led. On pourrait peut-être rajouter deux constantes de temps, une
pour ­l’allumage, et une pour l’extinction. Ainsi, si on veut modifier un temps ou
un autre, on n’aura pas besoin de chercher partout dans le programme, il suffira
d’aller voir du côté des constantes. C’est nettement plus pratique.
On pourrait faire ainsi, en mettant ON et OFF à deux valeurs différentes :
#define TEMPS_ON 1000 // 1000 milliseconde = 1 seconde
#define TEMPS_OFF 500 // 500 millisecondes = 0,5 secondes
Notre loop( ) deviendrait alors :
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(TEMPS_ON);
digitalWrite(LED_BUILTIN, LOW);
delay(TEMPS_OFF);
}
Comme on a déjà parlé des fonctions dans les chapitres précédents, il est
temps de les essayer. Au lieu d’appeler digitalWrite( ) puis delay( ), on pour-
rait regrouper ces deux fonctions en une seule, en lui passant un paramètre de
temps par exemple.
Déclarons notre fonction d’allumage :
void allumeLed(int duree) {
digitalWrite(LED_BUILTIN, HIGH);
delay(duree);
}
Et notre fonction d’extinction :
void eteindLed(int duree) {
digitalWrite(LED_BUILTIN, LOW);
delay(duree);
}
Ici, dans notre fonction allumeLed( ), on appelle digitalWrite( ), puis delay( )
en lui passant la valeur de la durée. Même chose pour la fonction eteindLed( ).

82/ Chapitre 3 : Le langage


MonBlink ressemblera alors à ceci maintenant :
#define TEMPS_ON 1000 // On defini la constante du temps d allumage
#define TEMPS_OFF 500 // et celle du temps d extinction

void setup() { // Le Setup


pinMode(LED_BUILTIN, OUTPUT); // Met la pin de la Led en sortie
}

void allumeLed(int duree) { // Pour allumer la Led


digitalWrite(LED_BUILTIN, HIGH); // On appelle digitalWrite, etat High
delay(duree); // Et on appelle le delay avec duree
}

void eteindLed(int duree) { // Pour éteindre la Led


digitalWrite(LED_BUILTIN, LOW); // On appelle digitalWrite, état Low
delay(duree); // Et on appelle le delay avec duree
}

void loop() { // La boucle principale loop()


allumeLed(TEMPS_ON); // Allumage, TEMPS_ON
eteindLed(TEMPS_OFF); // Puis extinction, TEMPS_OFF
}
On voit tout de suite que notre programme principal loop() est beaucoup plus
simple ainsi. De même, avec la déclaration des constantes de temps, on peut faci-
lement les modifier pour clignoter plus ou moins vite.
Est-ce que l’on ne pourrait pas également simplifier les deux fonctions d’allu-
mage et d’extinction ? Elles font presque la même chose, alors on devrait pouvoir
les simplifier elles-aussi… KISS…
Si on écrit une fonction qui allume ou qui éteigne la Led pendant un certain
temps, il faudrait lui envoyer deux paramètres, un pour lui dire allume/éteint et
l’autre pour lui donner le temps. Elle pourrait ressembler à ceci :
void gereLed(bool etat, int temps) {
digitalWrite(LED_BUILTIN, etat);
delay(temps);
}
Notre loop() serait alors ainsi.
void loop() {
gereLed(HIGH, TEMPS_ON);
gereLed(LOW, TEMPS_OFF);
}
Si on téléverse ce sketch dans l’Arduino, on aura le même résultat qu’avec Blink,
mais écrit d’une autre façon. Ceci nous a permis de voir l’utilisation des fonctions,
avec un ou deux passages de paramètres.

Premier programme en solo : MonBlink /83


Notre programme complet serait donc :
#define TEMPS_ON 1000 // On definit la constante du temps d allumage
#define TEMPS_OFF 500 // et celle du temps d extinction

void setup() { // Le Setup


pinMode(LED_BUILTIN, OUTPUT); // Met la pin de la Led en sortie
}
void gereLed(bool etat, int temps) {
digitalWrite(LED_BUILTIN, etat);
delay(temps);
}

void loop() {
gereLed(HIGH, TEMPS_ON);
gereLed(LOW, TEMPS_OFF);
}

LES BIBLIOTHÈQUES
En plus d’être un IDE simple à utiliser, notre environnement de programmation
nous donne accès à une fonction qui est intéressante, et qui est la gestion des
Bibliothèques.
Une Bibliothèque (ou une Librairie) regroupe des fonctions qui ont été écrites
par d’autres développeurs par exemple, et que l’on peut utiliser de façon simple.
Par exemple, dans notre sketch MonBlink, on a écrit des fonctions intéressantes
telles que gereLed(), allumeLed() ou eteindLed(). Chaque fois que l’on utilise des
Leds dans nos montages, on pourrait reprendre la source de MonBlink, retrouver
ces fonctions et faire des copier/coller dans notre nouveau sketch. Ce serait une
solution, mais pas très élégante. De plus, si on a écrit d’autres fonctions dans d’autres
sketchs, il faudrait à chaque fois essayer de les retrouver pour les réutiliser ailleurs.
Pas très pratique…
D’où l’idée de regrouper toutes ces petites fonctions dans des fichiers séparés,
de les classer par type, et de les réutiliser plus tard. On aurait ainsi créé une biblio-
thèque, dans laquelle on pourrait venir piocher nos fonctions au besoin, sans tout
réécrire à chaque fois. De même, pour les partager avec d’autres programmeurs,
ce serait super simple. On pourrait par exemple avoir une bibliothèque avec plein
de fonctions pour les Leds, une autre spécialisée dans les boutons poussoirs, une
autre dans la gestion d’un écran, etc.
Allons dans le menu des exemples pour ouvrir le fichier Exemples/Liquid
Crystal/Cursor.

84/ Chapitre 3 : Le langage


Figure 3.18 Ouverture de l’exemple LiquidCrystal/Cursor

Ce sketch montre l’utilisation d’un écran LCD avec l’Arduino, ce que nous ferons
un peu plus tard.
Pour utiliser un écran, il faudrait donc écrire toutes les fonctions qui per-
mettent de gérer le curseur, d’écrire un caractère, d’effacer l’écran et j’en passe.
Pas mal d’heures de programmation et de déboggage en perspective. Heureu-
sement, il existe une bibliothèque toute prête pour gérer un écran LCD, et nous
pouvons l’utiliser.
Regardons à la ligne 41 de l’exemple que nous venons d’ouvrir :
// include the library code:
#include <LiquidCrystal.h>
Après le commentaire, on y trouve un #include, suivi de < > avec un nom de
fichier qui est ici LiquidCrystal.h.
Ce nom de fichier correspond au fichier entête de cette librairie, c’est-à-dire au
fichier dans lequel on va retrouver les noms de toutes les fonctions, variables et
constantes disponibles.
Pour ajouter une bibliothèque à notre IDE, il suffit d’aller dans le menu Croquis/
Inclure une bibliothèque.

Les Bibliothèques /85


Figure 3.19 Inclure une bibliothèque à l’IDE

Si on va dans le menu Gérer les bibliothèques, notre IDE va d’abord faire une
mise à jour des bibliothèques dont il peut disposer.

Figure 3.20 Mise à jour des bibliothèques

Ensuite, on va pouvoir choisir la bibliothèque qui correspond à notre besoin


dans cette liste (après en avoir lu la description…).
Choisissons par exemple d’installer la librairie RBDLights. Il suffit de la trouver
dans la liste et de cliquer sur Installer.
En cliquant sur le bouton more info de la bibliothèque choisie dans cette liste,
on arrivera par exemple sur github.com/alextaujenis/RBD_Light qui nous don-
nera toutes les informations nécessaires à son utilisation.
Une fois l’installation effectuée, on va la retrouver dans la liste des biblio-
thèques.

86/ Chapitre 3 : Le langage


Figure 3.21 La bibliothèque est disponible dans l’IDE

En cliquant sur cet item dans le menu, l’IDE va automatiquement rajouter sa


référence dans notre sketch en rajoutant la ligne :
#include <RBD_Light.h>
La bibliothèque sera alors prête à être utilisée.
On pourra trouver davantage d’informations (en anglais…) sur l’installation des
librairies sur www.arduino.cc/en/Guide/Libraries
Si la bibliothèque d’un composant particulier que l’on voudrait utiliser n’est pas
dans la liste, on peut également l’importer en tant que fichier ZIP.
Prenons par exemple un composant avec lequel nous jouerons plus tard et qui est
un petit module GPS, le TEL0094 (que l’on trouve pour environ 15 € sur Internet).
Une rapide recherche nous amène sur un site marchand qui le vend, et qui met
un lien à disposition vers un fichier compressé ZIP ou RAR. Notre IDE n’accepte
que des fichiers ZIP pour l’import des bibliothèques. Dans le cas d’un fichier RAR,
il suffit de le décompresser, et de le recompresser en format ZIP.
Un fois fait, il suffira d’aller dans le menu Croquis/Inclure une bibliothèque/
Ajouter la bibliothèque ZIP.

Les Bibliothèques /87


Figure 3.22 Importer une bibliothèque ZIP

On choisit alors le fichier ZIP correspondant, et il apparaîtra alors dans la liste


de nos bibliothèques disponibles.
Trop fort !
Si cette bibliothèque se trouve dans un répertoire non compressé, il suffira de
le zipper afin de l’importer avec le gestionnaire de bibliothèques de notre IDE.
Sur ce site marchand vendant notre module GPS, on aura accès au site
github.com à l’endroit où se trouvent les fichiers de notre GPS. On pourra télé-
charger un répertoire contenant les fichiers sources de la bibliothèque, ainsi que
des exemples.
Pour utiliser cette nouvelle bibliothèque, il suffira alors d’ajouter la ligne sui-
vante au début de notre croquis.
#include <TinyGPS++.h>
Nous verrons l’utilisation de ce petit module un peu plus tard.
De même, on apprendra à créer nos propres bibliothèques, pour notre propre
usage ou pour partager avec d’autres programmeurs.
/> CHAPITRE 
COMPOSANTS
ÉLECTRONIQUES
4

Nous allons commencer l’étude de certains composants électroniques et aussi


de leurs schémas.
>> Les composants de la carte Arduino Uno
>> Les schémas électroniques avec Fritzing
>> Plein d’autres composants pour s’amuser

LES COMPOSANTS DE LA CARTE ARDUINO UNO


Maintenant que l’on a vu comment était composé un sketch, on peut regarder
comment sont les composants de notre carte Arduino.

Figure 4.1 Les composants sur l’Arduino UNO

On voit que notre carte comporte des composants bien différents les uns des
autres et nous allons regarder comment les représenter sur un schéma.

Les composants de la carte Arduino Uno /89


LES SCHÉMAS
Pour faire un branchement correct de tous nos composants entre eux, et sans
se tromper, on va faire un schéma, c’est ce que nous avons commencé à faire au
chapitre précédent.

C’EST QUOI UN SCHÉMA ? COMMENT EN FAIRE UN ?


Un schéma est un dessin d’électronicien qui explique comment les composants
sont branchés entre eux.

Un architecte fait des plans pour construire une maison, et un électronicien


fait un schéma pour construire un circuit électronique… Tous les électroniciens
font des schémas : pour inventer Arduino, pour créer une alarme ou pour faire
un plus gros projet comme une fusée ou un satellite. Même pour faire clignoter
une Led…
Il existe des logiciels spécifiques pour faire les schémas électroniques, tels que
Eagle ou Kicad par exemple. Ces deux logiciels de CAO (Conception assistée par
ordinateur) sont très performants, et bien qu’un peu compliqués à utiliser pour
l’instant, leurs noms sont à retenir. Bien sûr, il en existe beaucoup d’autres, et le
choix pourra se faire plus tard parmi une foule de propositions pour plusieurs rai-
sons : leur facilité d’utilisation, leur prix, leur gratuité et bien d’autres encore. On
peut également citer LibrePCB qui est disponible gratuitement à cette adresse :
librepcb.org.
Fritzing, que nous allons utiliser, permet également de faire des schémas pré-
cis. Il est disponible à cette adresse : fritzing.org/home/. Pour le téléchargement,
une contribution de 8 € est actuellement demandée sur le site. On peut égale-
ment utiliser la version online www.rollapp.com/app/fritzing qui utilise la version
bêta de Fritzing.
Une bonne habitude est aussi de dessiner ses schémas à la main, même si ça
fait un peu old school, car c’est une bonne façon d’apprendre sans compter sur
l’assistance d’un logiciel de CAO. On va déjà avoir pas mal de choses nouvelles à
apprendre pour l’instant…
Revenons-en à notre schéma. Nous avons déjà parlé de la Led et de la
­Résistance. On va à présent regarder comment les dessiner pour faire un schéma
qui va nous expliquer comment les brancher ensemble.
Ensuite, on pourra les brancher sur l’Arduino.
Pour faire des schémas électroniques, on utilise donc des symboles.

// SYMBOLE DE LA RÉSISTANCE
On a déjà vu à quoi ressemble le symbole de la résistance, mais suivant la
convention utilisée (ou le logiciel de schémas utilisé), on peut avoir ces deux
représentations possibles et qui sont strictement identiques :

90/ Chapitre 4 : Composants électroniques


Figure 4.2 Figure 4.3

En général, on lui donne aussi un nom. Ici, elle s’appelle R (comme Résistance),
suivi du chiffre 1 comme c’est la première résistance du schéma, et bien cela
donne le nom de R1.
Si on en rajoute une, elle s’appellera R2 et cela donnera par exemple :

Figure 4.4

On note aussi sa valeur, par exemple 1 KΩ (sur les schémas, on marque parfois
seulement 1 K au lieu de 1 KΩ – on prononce 1 kilo ohm).
La liste de tous les composants utilisés s’appelle alors une nomenclature.

// SYMBOLE DE LA LED
En électronique, on dessine le symbole de la Led de cette façon :

Figure 4.5

On lui donne aussi un nom (LED1), et une valeur (Rouge par exemple).
Les petites flèches sur le symbole de la Led montrent qu’elle fait de la lumière,
et on a un triangle et une barre droite.

MONTAGE DE LA LED ET DE LA RÉSISTANCE


Nous allons à présent étudier de plus près ces quelques composants de base,
et que avons déjà utilisés dans Blink.

Montage de la Led et de la Résistance /91


Pour nos prochains montages, nous aurons besoin d’une Led, celle que j’ai prise
est rouge mais on peut prendre n’importe quelle couleur bien sûr, d’une résis-
tance et d’une plaque d’expérimentation avec quelques fils de connexion.
>> Une Led rouge
>> Une résistance de 220 Ω avec les couleurs rouge-rouge-­marron-or
>> Une plaque d’expérimentations
>> Des fils de connexions : 1 noir, 1 rouge, 1 bleu par exemple (ou autre couleur,
au choix)…

Figure 4.6 Figure 4.7 Figure 4.8 Figure 4.9

Il y a déjà une Led intégrée à la carte Arduino, et nous allons donc en câbler une
seconde sur le connecteur d’extension de l’Arduino.
Nous allons la brancher avec une RÉSISTANCE, mais on va tout d’abord obser-
ver ces composants de très près.

// LA LED
La LED (Light Emitting Diode), ou Diode Electro Luminescente (DEL) en ­français,
est un composant qui va s’allumer lorsqu’elle est traversée par un courant.
Pourquoi ma LED a-t-elle une patte plus grande que l’autre ? C’est normal ?
Eh bien OUI, c’est normal. En fait, c’est normal et c’est même très pratique.
Une LED a bien deux pattes, et comme beaucoup de composants en élec­
tronique, elles ne servent pas toutes les deux à la même chose.
Si on regarde la LED de près, et même de très très près, on va également aper-
cevoir ce qu’il y a à l’intérieur : on va voir son PLUS et son MOINS…
Regardons-la à la loupe :

Figure 4.10

On voit qu’à l’intérieur il y a une plus petite plaque et une autre moins petite.

92/ Chapitre 4 : Composants électroniques


La plus petite est le PLUS, et la moins petite est le MOINS… Et si on regarde les
pattes, la plus longue va sur la plaque PLUS, et la moins longue va sur la plaque
MOINS.
En parlant d’une LED, on va dire que la patte la PLUS longue est l’ANODE (le
PLUS), et que la patte la MOINS longue est la CATHODE (le MOINS).
Pour faire de la lumière avec une LED, il faut bien que l’électricité rentre d’un
côté et ressorte de l’autre. En fait, le courant électrique rentre par le côté PLUS,
et il ressort par le côté MOINS.
Par exemple, si on voulait brancher la LED sur une pile pour l’allumer, on bran-
cherait le PLUS de la LED sur le PLUS de la pile, et le MOINS de la LED sur le
MOINS de la pile.
Mais ne le faisons pas tout de suite.

IMPORTANT
La LED a donc une ANODE et une CATHODE.
L’ANODE est la PLUS grande patte, la CATHODE est la MOINS grande patte.
On branche l’ANODE au PLUS, et la CATHODE au MOINS.

Figure 4.11 La Led et son symbole

Pour câbler la Led sur l’Arduino, il va également nous falloir une Résistance.

// LA RÉSISTANCE
La Résistance est un composant essentiel en électronique.
­ renons-en une en main, par exemple une qui est Rouge-Rouge-
P
Figure 4.12
Marron-Or dans la main et observons-la également.
Comme on le voit, elle a un corps avec deux pattes et des
anneaux de couleurs.

Montage de la Led et de la Résistance /93


Et est-ce qu’elle résiste la Résistance ?
Eh oui, elle résiste… Elle résiste au passage de l’électricité, ou plutôt elle freine
le courant électrique.
S’il n’y a pas de résistance dans le circuit, le courant passe fort, et s’il y a une
résistance, alors il passe moins fort.
Par exemple, si on veut que la Led s’allume juste un peu, on va laisser passer un
petit peu de courant dedans. Si on veut qu’elle s’allume beaucoup, on fera passer
beaucoup de courant.
C’est tout simple, et cela change avec la valeur de la résistance.
Pour mesurer la valeur de la Résistance, on a choisi les OHM comme unité (on
prononce ôme…). Au lieu d’écrire ohm, on utilise le symbole Ω.
On dit que la résistance choisie a par exemple une valeur de 1 KΩ.
g On écrit 1 KΩ et on lit 1 kilo ohm.
Or, on sait que pour toutes les unités on a :
kilo hecto déca unité déci centi milli
1 000 100 10 1 0,1 0,01 0,001
Donc, si on a mille ohms, on dit que l’on a 1 kilo ohm, que l’on va écrire 1 KΩ
(K pour kilo, et Ω pour ohms).
Pour différencier les différentes résistances par leur valeur, on va trouver des
BAGUES peintes sur les résistances.
En regardant ces couleurs sur notre résistance de 220 ohms, on a une première
bague Rouge, une seconde bague Rouge, une bague Marron et une bague couleur
Or. Si on commence à lire les bagues dans l’autre sens, on aura par exemple Or,
Marron, Rouge, Rouge.
En fait, il n’y a qu’un seul vrai sens de lecture. Avant de lire la couleur des
bagues, la convention indique de mettre la bague Or du côté droit, et de mettre
les autres à gauche :

Figure 4.13

Dans ce cas-là, on lira effectivement de gauche à droite : Rouge-Rouge-Marron-Or.


La bague dorée couleur Or indique simplement que la valeur de la résistance
est précise à 5 %.
Avec ces couleurs, on a associé un CODE DES COULEURS qui permet de coder
les valeurs.

94/ Chapitre 4 : Composants électroniques


Figure 4.14 Le code des couleurs

Avec ce code, si on veut écrire 220 Ω, on va prendre les deux premiers chiffres
de la valeur, et ensuite le nombre de zéros qu’il y a après.
Sur le CODE DES COULEURS, on a donc :
Bague 1 : 2 = Rouge
Bague 2 : 2 = Rouge
Bague 3 : 0 = Marron
Bague Or dans la main droite.
On a donc 220 = Rouge-Rouge-Marron…
Pour 1 KΩ par exemple, soit = 1 000 Ω, on peut dire que 1 000 s’écrit un peu
comme 10 suivi de deux zéros, soit 10 00.
En prenant le code des couleurs, on a :
Bague 1 : 1 = Marron
Bague 2 : 0 = Noir
Bague 3 : 00 = Rouge
Et Bague Or à droite :

Figure 4.15

Montage de la Led et de la Résistance /95


Nous avons donc une résistance 1 KΩ avec des bagues de couleur Marron-Noir-
Rouge.
Comment se rappeler de toutes ces couleurs ?
Et bien il y a une formule magique :
Ne Manger Rien Ou Jeûner, Voilà Bien Votre Grande Bêtise…
Si on ne garde que la première lettre de chaque mot, on retrouve nos couleurs :
Noir Marron Rouge Orange Jaune Vert Bleu Violet Gris Blanc
Pas mal, non ?

// BRANCHONS LA LED AVEC LA RÉSISTANCE


La résistance n’a pas d’anode, ni de cathode, on peut donc la brancher dans un
sens ou dans l’autre, cela n’a pas d’importance.
Il n’y a que pour lire sa valeur avec le code des couleurs que l’on met la bague
couleur OR dans la main droite.
Le schéma qui va nous montrer comment brancher la résistance et la Led avec
des fils sera donc ainsi :

Figure 4.16

Pour notre montage, on va choisir une résistance de valeur 220 Ω, soit avec des
bagues Rouge-Rouge-Marron-Or.
Nous verrons plus tard comment on peut calculer cette valeur de résistance de
façon plus précise.

COURANT, TENSION ET PUISSANCE


Avant d’aller plus loin, nous allons essayer de comprendre ce que sont les volts,
les ampères et la notion de résistance électrique.
Avant tout ça, regardons de très près ce qu’il se passe…
Dans la nature, tous les éléments, qu’ils soient simples ou complexes, sont
composés d’autres éléments disons « rudimentaires ».
Prenons une bouteille d’eau pure par exemple. Dans cette bouteille, il y a une
multitude de gouttes d’eau. Si on prend à présent une goutte d’eau, elle aura les
mêmes propriétés que les autres gouttes de la bouteille, car c’est la même eau,
une eau sans impuretés mais juste en plus petite quantité.
Imaginons que l’on divise cette goutte en deux autres gouttes plus petites, on
aura toujours la même eau. On divise à nouveau cette nouvelle goutte en deux,
puis en deux, puis en deux, on aura toujours la même eau.

96/ Chapitre 4 : Composants électroniques


On continue de la diviser en deux à l’aide de super lunettes grossissantes, et au
bout d’un moment on s’apercevra que l’on ne peut plus. Non pas qu’elle soit deve-
nue trop petite (nos lunettes ont des super pouvoirs, donc elles nous permettent
toujours de voir notre mini-goutte…), mais si on la divisait de nouveau en deux,
ce ne serait plus de l’eau. Pourquoi donc ?
Cette dernière goutte d’eau que l’on a obtenue après toutes ces divisions est une
molécule d’eau. Elle a toutes les propriétés de notre eau de départ, mais si on la
divise en deux, on casse cette dernière mini-goutte et elle perd ses propriétés d’eau.
Si on regarde cette molécule d’eau de plus près, on verra qu’elle est composée
de plusieurs éléments que l’on appelle des atomes. Elle a deux atomes d’hydro-
gène et un atome d’oxygène.

Figure 4.17 Molécule d’eau (ça me rappelle quelqu'un…)

L’écriture chimique de cette molécule d’eau est H2O, ce qui veut dire qu’elle est
composée de deux molécules d’hydrogène (H) et d’une molécule d’oxygène (O).
Si on regarde à présent son atome d’hydrogène avec nos super lunettes, on
verra qu’il est lui-même composé d’éléments élémentaires. Il comporte un noyau
avec un électron qui tourne autour de ce noyau. Ce sont des éléments extrême-
ment petits.

Figure 4.18 L’atome d’hydrogène

Pour tous les atomes, le noyau est constitué de neutrons et de protons, et on


voit bien ici que l’électron tourne autour de son noyau.
L’électron a une charge électrique négative, alors que le noyau a une charge élec-
trique positive. Le tout s’équilibre et l’électron tourne autour du noyau sans être
attiré ni éjecté par celui-ci, comme si on avait deux aimants, ni trop près, ni trop loin.

Courant, Tension et Puissance /97


Un atome peut avoir plusieurs électrons qui tournent autour de son noyau, pour
constituer par exemple un atome d’oxygène qui en aura huit. Ce nombre d’élec-
trons est donné par le Numéro atomique de l’atome.

Figure 4.19 L’atome d’oxygène

On voit aussi que tous les électrons ne tournent pas sur la même orbite, et qu’il
peut y en avoir une très grande quantité qui tourne autour du noyau. Il y en a qui
sont proches du noyau, d’autres qui sont plus loin.
Une matière est généralement constituée d’un assemblage de plusieurs types
d’atomes qui vont donc former des molécules, ces molécules assemblées les unes
aux autres vont former la matière que nous connaissons. Un fil électrique est par
exemple constitué d’un assemblage de cuivre et potentiellement d’autres maté-
riaux. Ce qui veut dire aussi que sous nos yeux, tout ce petit monde bouge en
permanence, et ceci dans tous les matériaux qui nous entourent.
Tous ces éléments primaires sont classés dans le Tableau périodique des élé-
ments ou Tableau de Mendeleïev, imaginé par le chimiste russe Dmitri Ivanovitch
Mendeleïev en 1869. On y trouve différentes informations sur la constitution de
chacun des atomes que nous connaissons.

// LE COURANT
On a vu que ces électrons qui tournent autour du noyau lui sont fortement liés,
et ils ne peuvent en principe pas partir. Ils vont tourner autour du noyau indéfini-
ment. Ce sont donc des électrons liés. Cependant, si des électrons tournent sur
une orbite qui se trouve plus loin du noyau, sur la dernière couche par exemple, ils
peuvent être éjectés et récupérés par un autre atome. Si un autre électron a déjà
été éjecté d’un atome voisin, le nôtre ira prendre sa place et tournera autour de
ce nouveau noyau. Ce sont des électrons libres. Ils se baladent d’atome en atome.
S’ils se baladent ainsi d’atome en atome et tous dans le même sens, ils créent
alors un courant d’électrons : c’est le courant électrique.
Si un élément est constitué uniquement d’électrons fortement liés, il n’y aura
donc pas de courant électrique. Le sens de déplacement de tout ce beau monde
déterminera également les électrodes positives ou négatives. Par convention,

98/ Chapitre 4 : Composants électroniques


on dira que le courant se dirige de l’électrode positive vers l’électrode négative, à
l’extérieur du générateur créant ce courant électrique (fil rouge, puis résistance,
puis Led, puis fil gris pour un retour à la pile).

Figure 4.20 Un circuit électrique

Pour mesurer la quantité d’électrons qui se baladent ainsi, on utilise l’unité


dénommée coulomb (symbole C). Un coulomb équivaut à environ 6,24 suivi de
18 zéros… électrons. Ça fait beaucoup… Si à présent on calcule le nombre de cou-
lombs qui passent dans un fil électrique en une seconde, on obtient des ampères
(du nom du physicien français du xviiie siècle André-Marie Ampère).
On peut donc dire qu’un ampère correspond à la quantité d’électrons qui se
déplacent dans notre fil électrique par seconde (1 A = 1 C/s).
En électronique, on parlera d’ampères (symbole A), mais aussi de milliampères
si on veut mesurer des valeurs plus petites (mA).
L’appareil qui va nous permettre de mesurer les ampères est un ampèremètre.
Comme il va mesurer la quantité d’électrons qui se déplacent dans notre fil
électrique, il va falloir qu’il soit lui-même inséré dans ce circuit électrique.

// LA TENSION
Pour que nos électrons aient envie de se déplacer ainsi, et tous dans le même
sens, il faut qu’il y ait quelque chose que les y oblige un peu. En effet, on a vu que
les électrons libres peuvent sauter sur des atomes qui ont déjà perdu un électron
et prendre leur place.
Pour réaliser cela, il faut donc créer un déséquilibre électrique entre les deux
extrémités de notre fil afin de permettre ce déplacement d’électrons. Ce déséqui-
libre est appelé différence de potentiel et se mesure en volts (du nom d ­ ’Alessandro
Volta, physicien italien du xviiie siècle). C’est la tension.
Le courant et la tension se mesurent ainsi, avec un ampèremètre et un volt-
mètre.

Courant, Tension et Puissance /99


Figure 4.21 Montage ampèremètre et voltmètre

// LA PUISSANCE
Maintenant que l’on connaît le courant et la tension, on va pouvoir commencer
à écrire des équations intéressantes.
La première qui lie ces deux valeurs est la puissance, et c’est le produit du
courant et de la tension.

PUISSANCE
P=U×I

Elle s’exprime en watts (W), du nom de l’ingénieur écossais James Watt vivant
au xviiie siècle. Dans cette équation, la tension U s’exprime en volts et le courant I
s’exprime en ampères.
Si on considère des milliampères dans notre montage, il faudra impérativement
les convertir en ampères avant d’utiliser cette équation.
Il est très important de calculer la puissance que reçoit un composant (la puis-
sance absorbée), afin de vérifier qu’il est bien capable de résister aux contraintes
de courant et de tension qu’on lui impose, sans qu’il ne parte en fumée… Si on fait
passer 10 W dans un composant qui ne peut accepter que 1 W, il va très rapidement
brûler.

// LA RÉSISTANCE ÉLECTRIQUE
La résistance électrique d’un matériau est sa capacité à s’opposer au passage
du courant, c’est-à-dire au déplacement des électrons libres qui le constituent.
Cette résistance définit si un corps est électriquement conducteur ou isolant.
Dans un matériau isolant, les électrons libres sont peu nombreux et le courant a
donc du mal à se créer puisque peu d’électrons sont capables de se déplacer. Au
contraire, dans un matériau conducteur, il y a beaucoup d’électrons libres qui ne
demandent qu’à se balader. De plus, le matériau facilite leur déplacement.

100/ Chapitre 4 : Composants électroniques


Le diamètre et la longueur du fil électrique par exemple influent aussi sur sa
résistance électrique. Dans un petit fil, les électrons libres vont se bousculer et
n’auront pas la place de passer. Il y aura donc une plus grande résistance au pas-
sage du courant que dans le même fil, mais d’une plus grosse section où les élec-
trons auront plus de place pour passer sans se heurter les uns aux autres. De plus,
ils vont se bousculer pour essayer de passer et le fil va avoir tendance à chauffer.
De même, la longueur du fil électrique aura une influence car nos électrons libres
auront davantage d’obstacles sur leur passage pour aller d’un bout à l’autre du fil.
Cette résistance électrique se calcule en ohm (symbole Ω), du nom du physicien
allemand du début du xixe siècle, Georg Ohm.
La formule de base (que nous n’utiliserons jamais…) qui relie ces différents
paramètres est :
ρL
R=
S
L : longueur en mètre, S : section en mètre carré et ρ : résistivité en ohm mètre.
On utilisera très peu cette formule, mais la suivante va être beaucoup plus inté-
ressante.

// LA LOI D’OHM
Pour calculer la valeur de la résistance à utiliser dans nos montages, on utili-
sera la loi d’Ohm qui fait intervenir la tension en volts, le courant en ampère et
donc la résistance en ohm. Ils sont reliés par la formule suivante :

LOI D’OHM
U=R×I

Dans cette équation fondamentale, U représente la tension en volts, R la résis-


tance en ohms et I l’intensité du courant en ampères.
Comme beaucoup de formules mathématiques, on peut la tourner un peu dans
tous les sens.

FORMULES USUELLES
Si on veut calculer la tension : U = R × I (en volts)
U
Si on veut calculer le courant : I = (en ampères)
R
U
Si on veut calculer la résistance : R = (en ohms)
I

U
On voit donc bien le rôle de la résistance sur cette équation I = .
R
Plus la résistance est grande, plus le courant sera faible.

Courant, Tension et Puissance /101


Par exemple, si on dit que la tension qui alimente notre circuit est de 5 V, et que
l’on utilise une résistance de 1 KΩ, on aura :
I = 5 / 1 000 = 0,005 A, soit 5 mA
Si notre résistance vaut 10 KΩ, on aura :
I = 5/10 000 = 0,5 mA
On voit bien que le courant diminue si la résistance augmente.
Par contre, si on diminue la résistance, par exemple à 10 Ω :
I = 5/10 = 0,5A
Là, ça commence à chauffer sérieusement pour notre pauvre circuit…

APPLICATION À NOTRE LED


Si on alimente notre Led rouge avec une tension de 5 V, il va falloir calculer la
bonne valeur de résistance à utiliser. Une résistance trop forte, et la Led éclairera
peu ; une valeur de résistance trop faible, et notre Led risque de brûler…
Comment connaître les valeurs à utiliser ? Et bien, il suffit de lire la data-
sheet de la Led. Une datasheet est une feuille de caractéristiques écrite par le
constructeur du composant, et qui le décrit entièrement. Pour notre Led rouge
par exemple, une recherche sur Internet avec le mot clé « datasheet led rouge »
nous amènera sur un site où on pourra télécharger cette fiche technique dont
voici un extrait.

Figure 4.22 Datasheet d’une Led

Les caractéristiques qui nous intéressent à présent vont se trouver ici où


l’on voit que Forward Voltage (tension directe) est de 2 V, pour un courant IF de
20 mA.
Comme pour les mètres et les millimètres, les ampères ont également des mul-
tiples et des sous-multiples, ce qui veut dire que 20 mA (milli ampères) équivalent
à 0,020 ampère (tout comme 20 millilitres correspondent à 0,02 litre).
Nous allons donc prendre ces deux valeurs pour notre montage : 2 V et 20 mA.
Comme notre Led est mise en série avec la résistance, on a le schéma suivant
en considérant que le symbole à gauche du schéma correspondrait à une pile de
5 volts, ou bien à une sortie de notre Arduino qui serait capable de nous donner
une tension de 5 volts, par exemple avec la fonction digitalWrite() que nous
connaissons déjà.
On reconnaîtra facilement le symbole de la Led et de la résistance.

102/ Chapitre 4 : Composants électroniques


Figure 4.23 La tension sur la Led et la résistance

La sortie de notre Arduino sur laquelle est connectée la Led avec sa résistance
donne une tension de 5 V. Sur ce schéma, on voit que la Led et la résistance sup-
portent également cette tension de 5 V à elles deux.
Comme la datasheet de la Led nous indique que la tension à ses bornes est de
2 V lorsqu’elle est correctement alimentée, on peut dire que la résistance voit une
tension de 5 – 2 = 3 V.
Ici, la Led et la résistance sont traversées par le même courant car elles sont
en série, l’une derrière l’autre, et on voit que le courant qui sort de la pile ne peut
pas aller ailleurs que dans la résistance puis dans la Led.
Comme on veut calculer la valeur de la résistance, on va prendre le courant qui la
traverse, ainsi que la tension qu’il y a à ses bornes, soit 3 V comme on vient de le voir.
Donc notre formule R = U / I devient R = 3 / 0,020 = 150 Ω.
Pour les résistances que l’on utilise couramment, toutes les valeurs n’existent
pas en réalité. On n’aura pas par exemple de résistance de 250 ohms ou de
251,3 ohms.
Il n’existe que des valeurs approchées et normalisées et celles que l’on va
utiliser appartiennent à une famille que l’on appelle la série E12 pour laquelle il
n’existe que 12 valeurs qui sont :
1,0 ; 1,2 ; 1,5 ; 1,8 ; 2,2 ; 2,7 ; 3,3 ; 3,9 ; 4,7 ; 5,6 ; 6,8 ; et 8,2 ainsi que leurs mul-
tiples et sous-multiples.
Par exemple, on trouvera des résistances d’une valeur de 1,5 ohm ou de
15 ohms ou encore de 1 500 ohms, tout comme des résistances de 2 700 ohms ou
27 000 000 ohms.
Comme il nous faut une résistance de 150 ohms pour notre montage, ça tombe
bien puisqu’elle existe dans la série E12. Dans le cas où le calcul donnerait une
valeur qui n’est pas dans cette série E12, on pourrait prendre la valeur la plus
proche, ou bien changer de série et prendre des résistances de précision de la
série E48 ou E96 par exemple, mais qui seraient plus chères à l’achat.

Application à notre Led /103


Un autre point à considérer est que si un courant traverse notre résistance, elle
va se mettre à chauffer, tout comme les résistances de puissance qui sont dans
notre four de cuisine ou dans un radiateur électrique. C’est le courant qui traverse
cette résistance qui va la faire chauffer, et qui grillera notre pizza au four. C’est
pareil. Donc, si on ne veut pas que la résistance de notre Led grille, il va falloir
regarder si elle peut faire passer tout ce courant sans risque pour elle.
On va pour cela utiliser une autre formule, celle de la puissance en watts (W)
qui se calcule par :
P=U×I
Comme notre résistance voit une tension de 3 V et qu’elle est traversée par un
courant de 20 mA (ou 0,020 A), on peut dire que :
P = 3 × 0,020, soit P = 0,06 watt.
Il faut donc que notre résistance puisse absorber une puissance de 0,06 W sans
risque. Une valeur de puissance courante pour une résistance est 0,25 W, ce qui
est largement suffisant (on dit aussi 1/4 W).
Notre résistance aura donc une valeur de 150 ohms pour une puissance de
1/4 W. Une résistance de ce type coûte aux environs de 10 centimes et est très
courante.
Tout à l’heure, on a regardé le code des couleurs d’une résistance de 220 ohms.
Et si on prenait celle-ci ? Est-ce qu’elle conviendrait tout de même ? Cela éviterait
d’en acheter une de 150 ohms pour rien… Et bien regardons.
Avec 220 ohms, le courant serait de I = U/R = 3/220 = 0,013A, soit 13 mA.
On serait donc toujours dans les bonnes valeurs du tableau de la datasheet.
Et pour la puissance ? Et bien on aurait P = U x I = 3 x 0,013 = 0,04 W. Notre
valeur de 1/4 W (0,25 W) est donc toujours largement suffisante.
On va utiliser celle de 220 ohms pour notre montage étant donné qu’on l’a déjà
à la main, ce sera tout aussi bien, la luminosité ne changera pas trop et notre Led
aura une plus grande durée de vie. Tant que l’on ne dépasse pas les 20 mA, tout
va bien. De plus, on consommera moins sur la pin de sortie de notre Arduino sur
laquelle on connectera notre Led avec sa résistance.

ASSOCIATION DE RÉSISTANCES
Les résistances sont des composants simples d’utilisation, mais sont indispen-
sables à tous nos montages, et leur valeur est quelquefois très importante bien
que l’on puisse assez souvent choisir une valeur approximative.
Par exemple, on voudrait utiliser une résistance de 220 ohms pour notre mon-
tage, mais on a récupéré une pleine poignée de 100 ohms et de 470 ohms sur un
ancien appareil électronique. Comment faire ? On ne peut pas les couper en deux
pour n’en prendre que 220 ohms, mais il y a un autre moyen d’y arriver…
Il existe deux façons d’associer les résistances : on peut les monter en série ou
en parallèle.

104/ Chapitre 4 : Composants électroniques


// MONTAGE EN SÉRIE
Le montage en série consiste à les monter l’une derrière l’autre, comme les
wagons d’un train. Ainsi, leur résistance au passage du courant qui les traverse
augmente, et la valeur globale de cette association correspond à la somme de
toutes leurs résistances.

Figure 4.24 Montage en série

La valeur de la résistance équivalente est alors ici :


R équivalent = R1 + R2
Donc, R équivalent = 100 + 100
R équivalent = 200 Ω
On arrive presque à notre résistance de 220 ohms de tout à l’heure…
Que se passera-t-il pour notre Led avec deux résistances en série de 100 ohms ?
On aura alors pour le courant :
U
I=
R
3
qui deviendra I = = 0,015 = 15 mA.
(100 + 100)
On est OK.

// MONTAGE EN PARALLÈLE
Le problème est que l’on a aussi récupéré des résistances de 470 Ω sur ce vieil
appareil que l’on a démonté.
Essayons de les monter en parallèle.

Figure 4.25 Montage en parallèle

Association de résistances /105


La valeur de la résistance équivalente à ce montage est un peu plus compliquée
à calculer, mais rien d’insurmontable.
On appliquera alors la formule suivante :
R 1 × R2
R équivalent =
R 1 + R2
Donc dans notre cas :
470 × 470
R équivalent =
470 + 470
220900
R équivalent =
940
Donc :
R équivalent = 235 ohms

On arrive pratiquement à nos 220 ohms que nous voulions utiliser.


Pour notre montage, on pourra donc utiliser une seule résistance de 220 Ω, ou
bien deux résistances de 100 Ω en série ou encore deux résistances de 470 Ω en
parallèle.

Figure 4.26 Montages équivalents

Sur notre plaque d’essai, on peut alors avoir l’un de ces trois montages au choix.

Figure 4.27 Trois configurations de résistances

106/ Chapitre 4 : Composants électroniques


RAPPELONS-NOUS DE CES FORMULES
POUR LES RÉSISTANCES
Montage en série :
R équivalent = R1 + R2
Montage en parallèle :
R 1 × R2
Réquivalent =
R 1 + R2
/> CHAPITRE
PREMIERS MONTAGES
5

Avec tout ce que nous avons déjà appris, nous allons pouvoir commencer à
créer des montages plus sympas et voir comment on pourra :
>> Rajouter des Leds à Arduino
>> Utiliser des boutons poussoirs, un potentiomètre
>> Réaliser des montages très cools

MONTAGE D’UNE LED SUPPLÉMENTAIRE


// BRANCHONS-NOUS SUR L’ARDUINO
Sur les deux côtés de l’Arduino Uno, nous avons déjà vu les grands connecteurs
noirs qui servent à rajouter des circuits électroniques à la carte.

Figure 5.1 Connecteurs Arduino

Eh bien, il est temps de s’en servir !


Sur le connecteur le plus long, celui qui est en haut de la carte, on va brancher
le montage Led/Résistance entre le 8 et le GND.

Montage d’une Led supplémentaire /109


Figure 5.2 Détail du connecteur Digital Out n° 1

Regardons de plus près comment s’y prendre.

// MISE EN ŒUVRE
Le montage
Prenons la plaque d’expérimentation pour effectuer ce câblage.

Figure 5.3 Liaisons d’une plaque d’expérimentation

Les trous qui sont sur


des rangées verticales
sont déjà reliés entre eux
à l’intérieur de la plaque,
comme sur les traits que
j’ai rajoutés en vert. Il n’y
aura donc pas besoin de
rajouter des fils dans ce
sens et on peut le voir en
regardant le dessous de
la plaque.
On aura donc le mon-
tage suivant :
Figure 5.4 Montage Led et résistance

110/ Chapitre 5 : Premiers montages


Ce montage correspond au schéma simplifié que voilà :

Figure 5.5 Schéma Led et résistance

Le programme
Comme on l’a fait au chapitre précédent avec le programme Blink qui était dans
les exemples livrés avec Arduino, on va écrire notre programme, et le téléverser
sur la carte.
Reprenons le programme de l’exemple Blink, qui a servi à faire clignoter la Led
orange de la carte Arduino.

Programme Blink
Reprenons le sketch Blink d’origine, et sauvegardons-le en LedExterne.ino.
Voici ce que l’on a :
// the setup function runs once when you press reset or power the board
void setup() { // initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
}

// the loop function runs over and over again forever


void loop() {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on
delay(1000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off
delay(1000); // wait for a second
}
Essayons de le téléverser sur la carte Arduino. Qu’est-ce qu’il se passe ? Il fait
clignoter la petite Led orange L de la carte Arduino, et pas la nôtre. Pas celle que
l’on a rajoutée.

Montage d’une Led supplémentaire /111


La Led orange de l’Arduino est branchée comme la nôtre, sauf qu’elle est bran-
chée sur la patte 13 de l’Arduino. La grosse différence est que l’on a branché notre
nouvelle Led sur la patte 8.
Comment faire dans ce cas ? Si on se souvient de ce que l’on a dit en étudiant
le sketch de Blink, on avait vu que les fonctions pinMode() et digitalWrite()
avaient comme paramètre LED_BUILTIN, c’est-à-dire qu’elles font référence à la
Led L de la carte Arduino. C’est donc bien normal que ce soit elle qui clignote et
non pas la nôtre… Il faut donc lui dire de changer de patte et de travailler avec la
LED sur la patte 8 en définissant une nouvelle Led pour notre IDE, et le tour est
joué… Pour ce faire, on va donc inclure cette ligne vers le début de notre sketch,
et y faire référence pour les deux fonctions qui nous intéressent :
#define LED_EXTERNE 8
Ensuite, on pourra écrire ceci pour mettre la pin correspondante en sortie :
pinMode(LED_EXTERNE, OUTPUT);
Et ensuite pour l’allumer :
digitalWrite(LED_EXTERNE, HIGH);
Notre nouveau sketch sera donc le suivant :
// (c)Frédéric SILLON 2020
// Clignotant avec la Led Externe sur Pin 8
#define LED_EXTERNE 8 // Explique à l’IDE que la Led est sur la pin 8

// fonction setup(): Initialisation de la carte Arduino


void setup() { // Initialise la pin 8 en sortie
pinMode(LED_EXTERNE, OUTPUT);

// Fonction loop(): notre clignotant


void loop() { 
digitalWrite(LED_EXTERNE, HIGH); // Led externe ON
delay(1000); // Attente
digitalWrite(LED_EXTERNE, LOW); // Led externe OFF
delay(1000); // Attente
} // On reboucle !!
Voilà donc notre nouveau programme qui s’appelle maintenant LedExterne.

Figure 5.6 Sketch LedExterne dans l’IDE

112/ Chapitre 5 : Premiers montages


Téléversons le programme sur la carte Arduino, et regardons ce qu’il se passe.
La Led externe rouge clignote ! Magique…

Et si on voulait faire clignoter les deux :


// (c)Frédéric SILLON 2020
// Clignotant avec la Led Externe sur Pin 8 et Led interne L
#define LED_EXTERNE 8 // Explique à l’IDE que la Led est sur la pin 8
// fonction setup(): Initialisation de la carte Arduino
void setup() {
pinMode(LED_EXTERNE, OUTPUT); // Initialise la pin 8 en sortie
pinMode(LED_BUILTIN, OUTPUT); // Ainsi que la sorite de la Led L
}

// Fonction loop(): notre clignotant avec deux Leds


void loop() {
digitalWrite(LED_EXTERNE, HIGH); // Led externe ON
digitalWrite(LED_BUILTIN, HIGH); // Led L ON
delay(1000); // Attente
digitalWrite(LED_EXTERNE, LOW); // Led externe OFF
digitalWrite(LED_BUILTIN, LOW); // Led L OFF
delay(1000); // Attente
} // On reboucle !!!!
On voit bien ici le rôle de la fonction digitalWrite().
Dès que l’on voudra agir sur le monde extérieur par les sorties digitales de
l’Arduino, par exemple pour piloter des Leds ou actionner des relais, on utilisera
cette fonction.
Si on utilise des Sorties, cela veut peut-être dire qu’il y a aussi des Entrées…
Et bien les voici !

MONTAGE D’UN BOUTON POUSSOIR


Un bouton poussoir est comme un interrupteur qui va laisser passer le signal
lorsque l’on appuie dessus, et qui coupera ce même signal si on le relâche. C’est
un peu comme l’interrupteur qui allume la lumière du plafond à la maison, mais
en plus petit…

Figure 5.7 Un bouton poussoir

Montage d’un bouton poussoir /113


Imaginons que l’on câble un bouton poussoir que l’on appellera BP dans notre
schéma avec une Led et sa résistance pour qu’elle s’allume quand on appuie sur le
bouton, et qu’elle s’éteigne quand on relâche le bouton. Ce serait sympa.
En faisant un petit schéma, on va vite voir comment on pourrait faire.

Figure 5.8 Schéma avec un bouton poussoir

Ici, on a branché notre résistance avec sa Led, un bouton poussoir et le tout


alimenté par notre pile imaginaire.
On voit que la Led est éteinte car le courant ne peut pas passer depuis la pile
vers la Led à travers la résistance. En effet, les contacts du Bouton Poussoir sont
ouverts, donc rien ne se passe. À la maison, il faut bien appuyer sur l’interrupteur
pour allumer la lumière. C’est exactement pareil dans notre montage.
Quand on ferme le contact du bouton poussoir en appuyant dessus, le courant
peut alors passer de la pile à la Led au travers de la résistance : la Led s’allume.

Figure 5.9 Allumage de la Led avec BP

Pour faire un clignotant comme on l’a fait avec Blink, on pourrait faire exac-
tement comme avec ce bouton poussoir, et cela fonctionnerait. Par contre, il va
falloir aller vite si on veut que ça clignote rapidement… Notre programme Blink
était donc une bonne solution.

114/ Chapitre 5 : Premiers montages


Est-ce que l’on ne pourrait pas utiliser le bouton poussoir avec l’Arduino pour
par exemple ne conserver l’allumage de la Led que lorsque l’on appui sur ce BP ?
Il faudrait donc que notre Arduino sache que l’on a appuyé sur le bouton si on
le branche sur un de ses connecteurs. Ce qui veut dire qu’Arduino devrait être
capable de lire ce qu’il se passe sur une de ces pins.
Pour cela, on va utiliser la fonction digitalRead() et stocker ce qu’elle nous renvoie
dans une variable, que l’on appellera par exemple etatDuBouton. Il faudra tout d’abord
penser à déclarer cette variable (que l’on initialisera à 0 même si ça ne sert à rien ici),
et aussi indiquer sur quelle pin le bouton poussoir est branché (disons sur la pin 7).
#define laPinALire 7
int etatDuBouton = 0;

etatDuBouton = digitalRead(laPinALire);
Suivant si le bouton est appuyé ou non, etatDuBouton vaudra donc true ou false.
Dans l’initialisation, on a mit etatDuBouton=0, même si on va lui donner un peu
plus tard la valeur du bouton. Dans le fond, ça ne sert à rien, mais c’est une bonne
habitude à prendre d’initialiser les variables, même si on pense qu’elles ne servent
pas tout de suite. En effet, une variable non initialisée peut être une source de bug
importante et difficile à détecter.
Il va donc à présent falloir modifier notre schéma pour brancher le bouton
poussoir sur l’Arduino, ainsi que la Led. Le symbole utilisé pour le bouton poussoir
est ici un peu bizarre par rapport au schéma précédent, mais c’est celui qui est
dans la bibliothèque Fritzing, donc nous allons l’utiliser. La résistance du bouton
poussoir est ici de 10 K, car nous n’avons pas besoin de beaucoup de courant pour
entrer dans l’Arduino. Comme tout à l’heure, nous allons brancher la Led rouge et
sa résistance, sur la sortie 8. Le bouton poussoir sera quant à lui câblé sur la pin 7.

Figure 5.10 Schéma avec Led et BP

Montage d’un bouton poussoir /115


Figure 5.11 Implantation Led et BP

Attention au câblage du bouton poussoir s’il a quatre pattes, car elles sont
souvent reliées deux à deux sur ces modèles.
Notre programme ressemblera donc à ceci.
// (c)Frédéric SILLON 2020
// Bouton poussoir sur pin 7 pour allumer ou eteindre la Led
#define LED_EXTERNE 8 // Explique à l’IDE que la Led est sur la pin 8
#define BOUTON_POUSSOIR 7 // Bouton poussoir connecte sur pin 7
int etatDuBouton = 0; // Sauvegarde de l'état du bouton (on/off)

// fonction setup(): Initialisation de la carte Arduino


void setup() {
pinMode(LED_EXTERNE, OUTPUT); // Initialise la pin 8 en sortie
pinMode(BOUTON_POUSSOIR, INPUT); // On veut lire le bouton, donc une Input
}

// fonction loop(): notre clignotant avec deux Leds


void loop() {
etatDuBouton = digitalRead(BOUTON_POUSSOIR); // On lit l'etat du bouton
if (etatDuBouton == true) // Si relache,
digitalWrite(LED_EXTERNE, LOW); // Led externe OFF
else // Sinon,
digitalWrite(LED_EXTERNE, HIGH); // Led externe ON
}

116/ Chapitre 5 : Premiers montages


REMARQUE
On voit ici que etatDuBouton est à true si celui-ci est relâché. C’est un peu dérou-
tant, mais c’est normal car, dans ce cas, l’entrée de l’Arduino voit la résistance R2
reliée à 5 volts. On a donc bien un état haut qui arrive sur cette entrée.

On aurait pu allumer la Led directement avec le BP comme dans les chapitres


précédents, mais ça aurait été beaucoup moins fun. De plus, on sait à présent lire
une entrée numérique par digitalRead().
À la place du bouton poussoir, on aurait pu avoir un capteur qui se ferme quand
un robot touche un obstacle, un autre capteur si la porte de la fusée est mal fer-
mée, ou d’autres choses dans ce genre. C’est plutôt pas mal…
On peut gérer tout ce qui est ouvert/fermé.

MONTAGE D’UN POTENTIOMÈTRE


Maintenant que l’on sait utiliser digitalWrite() et digitalRead(), on va regar-
der une autre fonction très intéressante qui est analogRead().
De la même façon que l’on a utilisé digitalRead() pour voir si une entrée est
activée ou pas par le monde extérieur (notre BP de tout à l’heure), on va pouvoir
regarder de quelle façon une entrée dite Analogique est active. En fait, on verra
non seulement s’il se passe quelque chose sur cette entrée, mais on pourra aussi
mesurer « combien ».
C’est un peu le principe du bouton de volume de la chaîne HiFi. Le système
interne de la chaîne regarde à quelle valeur se trouve le bouton de volume afin de
régler le bon niveau de son.
Pour faire ce réglage, on va utiliser un potentiomètre. Le potentiomètre est une
résistance dont la valeur est réglable. Si on prend un potentiomètre de 10 KΩ par
exemple, sa valeur pourra varier de 0 à 10 000 ohms.
Le symbole du potentiomètre est celui-ci :

Figure 5.12 Symbole du potentiomètre

Montage d’un potentiomètre /117


Pour nos montages, on va en utiliser un plus petit que celui de la chaîne HiFi,
mais qui marche exactement de la même façon et qui ressemblera par exemple
à ce modèle.

Figure 5.13 Exemple de potentiomètre

On voit bien qu’il s’agit d’une résistance, mais avec une patte en plus. Cette
patte supplémentaire est le curseur. C’est lui que l’on va raccorder à notre entrée
analogique, et qui nous donnera une valeur en ohms qui sera variable en fonction
de sa position, ce que l’on comprend bien sur le schéma. Les deux autres pattes
se branchent comme une résistance normale.
Si on place le curseur de notre potentiomètre au milieu de sa course, on
­comprend facilement que l’on a partagé cette résistance en deux parties égales,
et que l’on a un peu la même chose que sur le schéma de droite (5 KΩ + 5 KΩ
= 10 KΩ).

Figure 5.14 Circuit équivalent au potentiomètre

Si on branche cet ensemble de deux résistances en 5 V, on voit aussi qu’il n’y
aura que la moitié des 5 V sur le curseur, donc 2,5 V.

118/ Chapitre 5 : Premiers montages


Figure 5.15 Diviseur de tension

On a réalisé ce que l’on appelle un Pont diviseur de tension.


Si on met le curseur de ce montage sur une pin d’entrée analogique de notre
Arduino et que l’on utilise la fonction analogRead(), on pourra faire un petit calcul
qui nous permettra de lire cette valeur de 2,5 volts. En plus de simuler un poten-
tiomètre de volume, on aura aussi réalisé un petit voltmètre !
Si on avait mis par exemple des résistances de 2,5 KΩ pour faire le montage,
on aurait pu lire 1,25 V ou 3,75 V suivant le montage effectué.

Figure 5.16 Autre position du potentiomètre

Montage d’un potentiomètre /119


Comme on a quatre résistances égales de 2,5 KΩ, on peut dire que chacune
d’elles voit la tension de 5 V divisée par 4, soit 1,25 V.
À la position du curseur, on se retrouve donc avec 3 x 1,25 = 3,75 V.
On imagine bien que si on mettait le curseur tout en bas, il verrait une tension
de 1 x 1,25 V = 1,25 V.
Le potentiomètre marche exactement comme ceci, sauf qu’il peut prendre
n’importe quelle valeur entre 0 et 10 KΩ (pour un potentiomètre d’une valeur
de 10 KΩ, évidemment. Un potentiomètre de 4,7 KΩ prendrait toutes les valeurs
possibles entre 0 et 4,7 KΩ).

Figure 5.17 Potentiomètre réglé à 3,7K

Comment peut-on calculer la valeur de la tension qu’il y aura sur le curseur si


par exemple il se trouve positionné comme ceci à 3,7 KΩ et 6,3 KΩ ?
Sans formule magique, ça risque d’être un peu plus compliqué à calculer.
Heureusement, il y en a une…
Cette formule nous dit que :
R2
tensionCurseur = tensionAlimentation ×
R 1 + R2
Dans notre cas, on aurait donc :
6300
tensionCurseur = 5 ×
3700 + 6300
6300
Donc, tensionCurseur = 5 ×
10000
D’où tensionCurseur = 5 × 0,63 = 3,15
Ce qui nous donne au final : tensionCurseur = 3,15 V
La tension sur le curseur vaut donc 3,15 volts !
De façon plus générale, on écrit la formule du pont diviseur de tension de cette
façon, en se disant que le curseur est la sortie de ce petit montage (Vout) alimenté
pour nous en 5 volts (Valim).

120/ Chapitre 5 : Premiers montages


PONT DIVISEUR DE TENSION
R2
Vout = Valim ×
R 1 + R2

Dans cette formule, il est important de bien respecter qui est R1 et qui est R2,
sinon tout sera faux. On peut se dire pour s’en souvenir que R1 est en haut et R2
est en bas par exemple.
On voit aussi que l’on a réussi à convertir la position du curseur qui est en ohms
en une valeur en volts que l’on pourra mesurer avec notre Arduino. C’est plutôt
intéressant.
On pourra raccorder ce fameux potentiomètre à notre carte suivant ce schéma,
mais nous ferons le montage et les essais un peu plus tard.

Figure 5.18 Potentiomètre sur Arduino

Avant cela, il faut étudier analogRead() d’un peu plus près, et voir de quelle
manière cette fonction est utilisable.

CONVERSION ANALOGIQUE/NUMÉRIQUE
Si on regarde de nouveau l’aide d’Arduino sur le site de référence à la rubrique
analogRead (www.arduino.cc/reference/en/language/functions/analog-io/­
analogread/), on voit que l’Arduino Uno comporte six entrées analogiques notées A0
à A5, et qu’elles ont un operating voltage de 5 volts et une résolution max de 10 bits :

Conversion analogique/numérique /121


Figure 5.19 Entrées analogiques Arduino

Sur notre montage, le potentiomètre est alimenté en 5 V, avec son curseur sur
l’entrée A0 de l’Arduino. C’est donc OK pour l’operating voltage et aussi pour le
choix de l’entrée A0 (usable pin = pin utilisable).
À quoi correspondent ces 10 bits de résolution ?
La description de analogRead sur le site indique ceci :
Reads the value from the specified analog pin. Arduino boards contain a multi­
channel, 10-bit analog to digital converter. This means that it will map input
voltages between 0 and the operating voltage (5V or 3.3V) into integer values
between 0 and 1023. On an Arduino UNO, for example, this yields a resolution
between readings of: 5 volts / 1024 units or, 0.0049 volts (4.9 mV) per unit. See
the table below for the usable pins, operating voltage and maximum resolution
for some Arduino boards.
On pourra utiliser un traducteur en ligne pour traduire ce paragraphe si on
n’est pas trop à l’aise en anglais, et il ne faudra pas hésiter à s’aider de ce type
d’informations car elles seront très utiles. De plus, notre niveau en anglais tech-
nique va s’améliorer petit à petit, ce qui est également une très bonne chose…
Globalement, ça veut donc dire que notre UNO va découper sa tension de
5 volts en 1 024 petites unités, ce qui lui donnera une résolution de 5 volts / 1 024
= 0,0049 volts par unité, soit 4,9 mV.
Il va ensuite lire ce qui est présent sur l’entrée A0 par exemple, et compter
combien de fois il y a d’unités de 4,9 mV.
Comme il part de la valeur zéro pour compter, ces 1 024 unités iront de 0 à
1 023 (ce qui fait bien 1 024 en tout si on compte le 0).
Par exemple, si on lui présente 1,25 V sur l’entrée A0, il va nous retourner un
chiffre correspondant au nombre d’unités 4,9 mV contenues dans 1,25 V. Si on
fait le calcul, on aura 1,25/0,0049 = 255. C’est cette valeur qui sera donnée par
analogRead().
Cela veut dire qu’avec une instruction analogRead(), notre Arduino Uno pourra
lire une tension sur une des pins A0 à A5 avec une précision de 4,9 mV.
C’est plutôt pas mal du tout. Il pourra par exemple faire la différence entre 1,0 V
et 1,0049 V.
La tension qu’il lira sera alors :
Tension = ValeurLue * 0,0049 volt.
Par exemple, s’il lit 236, la tension vaudra 236*0,0049 = 1,1564 V.

122/ Chapitre 5 : Premiers montages


Par contre, d’où vient cette valeur de 1 024, et quel rapport avec la max résolu­
tion 10 bits annoncée par le site Arduino ?
Si on revient au chapitre où nous avons appris à compter en binaire, ce sera
plus clair.
La résolution analogique de l’Arduino est sur 10 bits, donc en binaire on pourra
aller de 00 0000 0000 à 11 1111 1111 (on a bien 10 bits ici).
Si on convertit ce mot binaire 0b1111111111 en décimal, on a :
b9 b8 b7 b6 b5 b4 b3 b2 b1 b0
1 1 1 1 1 1 1 1 1 1 (binaire)
512 256 128 64 32 16 8 4 2 1 (décimal)
La conversion donne :
1x512 + 1x256 + 1x128 + 1x64 + 1x32 + 1x16 + 1x8 + 1x4 + 1x2 + 1x1 = 1023.
Si on considère la valeur 0000000000, on arrive bien à nos 1 024 combinai-
sons possibles ! On retrouve ici toute l’utilité de nos conversions en binaire.
On parle ici de conversion de Analogique/Numérique, c’est-à-dire que l’on va
convertir une valeur du monde analogique (un peu comme le monde réel), en
valeur numérique (la représentation en chiffres de cette valeur du monde réel).
Suivant les modèles, un convertisseur analogique/numérique peut effectuer
sa conversion sur 8, 10 ou 12 bits par exemple. Plus le nombre de bits utilisés est
élevé, plus la précision sera grande.
Mettons cela en application avec un programme, mais d’abord inter­rogeons-
nous sur la façon de lire cette valeur, car nous ne sommes pas à l’intérieur
­d’Arduino…
Arduino va donc lire la valeur de la tension présente sur son entrée A0 par
­analogRead(), et on va mettre ce résultat dans une variable. Cette mesure don-
nera par exemple 217. Par contre, il va garder cette valeur dans sa mémoire, et il
va falloir que l’on puisse y avoir accès pour voir par nous-même ce qu’il a lu.
On va essayer deux méthodes.
Avec la première, on va faire varier la vitesse de clignotement de Leds par
exemple. Avec la seconde méthode, on va utiliser l’interface série de l’Arduino qui
nous permettra de lire directement la valeur qu’il a réussi à convertir.
Allons-y !

// LE CHENILLARD
Avant d’aller plus loin, nous allons réaliser un chenillard avec quatre Leds. Il
nous servira pour notre test de conversion analogique/numérique avec le poten-
tiomètre. Le principe est de les allumer et de les éteindre les unes après les autres
afin de créer un effet de défilement.
Voici le schéma avec les quatre Leds et leurs résistances. Chaque Led sera
pilotée par une sortie de l’Arduino, de D9 à D12. Les valeurs des résistances ont
déjà été calculées dans les chapitres précédents, nous n’y reviendrons donc
pas ici.

Conversion analogique/numérique /123


Figure 5.20 Schéma du chenillard

Figure 5.21 Câblage du chenillard

Pour chaque sortie, et chacune à leur tour, on fera appel à digitalWrite() pour
les allumer ou les éteindre.
Pour régler la vitesse, on mettra une temporisation avec la fonction delay().
Enfin, en mettant tout ça dans la boucle loop(), le chenillard défilera indéfiniment.
Bien sûr, il faudra tout d’abord définir les pins que nous utiliserons en output
dans la fonction setup() de notre programme.
// (c)Frédéric SILLON 2020
// Chenillard avec Leds sur pins 9, 10, 11, 12
// Arduino UNO

124/ Chapitre 5 : Premiers montages


// --- Definition des Leds sur les pins 9, 10, 11, 12 du connecteur Arduino
#define LED_A 9
#define LED_B 10
#define LED_C 11
#define LED_D 12

// --- On met les pins de chaque Led en sortie dans le setup()


void setup() {
pinMode(LED_A, OUTPUT); // En sortie pour chaque Led
pinMode(LED_B, OUTPUT);
pinMode(LED_C, OUTPUT);
pinMode(LED_D, OUTPUT);
digitalWrite(LED_A, LOW); // On eteint les Leds
digitalWrite(LED_B, LOW);
digitalWrite(LED_C, LOW);
digitalWrite(LED_D, LOW);
}

// --- Le chenillard se deroule dans le loop()


void loop() {
digitalWrite(LED_A, HIGH);
delay(500);
digitalWrite(LED_A, LOW);

digitalWrite(LED_B, HIGH);
delay(500);
digitalWrite(LED_B, LOW);

digitalWrite(LED_C, HIGH);
delay(500);
digitalWrite(LED_C, LOW);

digitalWrite(LED_D, HIGH);
delay(500);
digitalWrite(LED_D, LOW);
}
On compile et on téléverse le logiciel : on a un super beau chenillard !
Par contre, je trouve que ce programme est un peu trop long, surtout que l’on
répète presque quatre fois la même chose dans le loop().
Profitons-en pour essayer de faire un peu mieux : accrochons-nous…
Si on regarde notre schéma et les #define du programme d’un peu plus près,
on se rend compte que LED_A vaut 9, que LED_B vaut 10, LED_C vaut 11 et que LED_D
vaut 12.
Ça n’a l’air de rien, mais on pourrait aussi dire que LED_B = LED_A + 1 et aussi
que LED_C = LED_B + 1, et ainsi de suite.
Pourquoi ?

Conversion analogique/numérique /125


Et bien comme LED_A vaut 9, si on fait LED_A + 1, on obtient la valeur 10, ce qui
correspond à LED_B de nos #define. On a donc le droit de dire que LED_B = LED_A + 1.
On pourrait donc créer une boucle for en augmentant le numéro de la LED à
chaque tour de boucle.
Par exemple, on pourrait allumer LED_A puis attendre et l’éteindre et ensuite
faire de même avec LED_A + 1 (qui est en fait LED_B…), et ainsi de suite.
On pourrait déclarer une variable qui compterait 1…2…3…4…1…2…3…4…1…
Ainsi, le numéro de la LED changerait tout seul.
Regardons le nouveau programme ainsi obtenu avec un loop() modifié.
// (c)Frédéric SILLON 2020
// Chenillard avec Leds sur pins 9, 10, 11, 12 version amelioree
// Arduino UNO

// --- Definition des Leds sur les pins 9, 10, 11, 12 du connecteur Arduino
#define LED_A 9
#define LED_B 10
#define LED_C 11
#define LED_D 12

// --- On met les pins de chaque Led en sortie


void setup() {
pinMode(LED_A, OUTPUT); // En sortie pour chaque Led
pinMode(LED_B, OUTPUT);
pinMode(LED_C, OUTPUT);
pinMode(LED_D, OUTPUT);
digitalWrite(LED_A, LOW); // On eteint les Leds
digitalWrite(LED_B, LOW);
digitalWrite(LED_C, LOW);
digitalWrite(LED_D, LOW);
}

// --- Le chenillard se deroule


void loop() {
int i;
for (i=0; i<4; i++) {
digitalWrite(LED_A + i, HIGH);
delay(500);
digitalWrite(LED_A + i, LOW);
}
}
Si on compile et que l’on téléverse ce programme sur notre Arduino, on aura
toujours le chenillard, mais écrit de façon plus élégante.
Si on veut aller plus loin, on peut carrément faire la même chose dans le setup().
On aura un sketch plus court et plus élégant, mais qui prendra aussi beaucoup moins
de place dans la mémoire de notre Arduino. De même pour les define, on ne définira
que LED_A car les autres sont calculées par le programme lui-même dans la boucle for.

126/ Chapitre 5 : Premiers montages


// (c)Frédéric SILLON 2020
// Chenillard avec Leds sur pins 9, 10, 11, 12 version amelioree davantage
// Arduino UNO

// --- Definition des Leds sur les pins 9, 10, 11, 12 du connecteur Arduino
#define LED_A 9 // On definit LED1, les autres seront calculees
// automatiquement
// --- On met les pins de chaque Led en sortie
void setup() {
int i;
for (i=0; i<4; i++) {
pinMode(LED_A + i, OUTPUT); // En sortie pour chaque Led
digitalWrite(LED_A + i, LOW); // On eteint les Leds
}
}

// --- Le chenillard se deroule


void loop() {
int i;
for (i=0; i<4; i++) {
digitalWrite(LED_A + i, HIGH);
delay(500);
digitalWrite(LED_A + i, LOW);
}
}
C’est plutôt pas mal, non ?
Cette façon de faire peut paraître un peu compliquée à comprendre au début,
et dans ce cas il faudra y réfléchir avec un papier et un crayon afin de faire tourner
le programme à la main, comme si on était l’Arduino, instruction par instruction
(d’où l’intérêt de l’organigramme).
On retiendra un autre principe : DRY (Don’t Repeat Yourself : Ne te répète pas).
Si on voit que beaucoup de lignes de code se répètent, il y a sûrement moyen
de faire autrement, de façon plus compacte et plus élégante.
KISS est aussi bien appliqué dans cet exemple, car si une chose nous paraît
compliquée au départ, on pourra toujours la découper en parties plus petites qui
au final seront assez simples.
Revenons-en à notre entrée analogique et à son potentiomètre…

// DE PLUS EN PLUS VITE


Pour faire varier la vitesse de défilement de notre chenillard, on peut modifier
la valeur d’attente qu’il y a dans l’appel à la fonction delay(). Le problème est
que l’on devra recompiler et retéléverser à chaque fois que l’on veut ralentir ou
accélérer. Ce n’est pas très cool.
On a vu que analogRead() permettait de lire la valeur analogique sur une des entrées
A0 à A5, et qu’elle retournait une valeur comprise entre 0 et 1 023. Si on c­ ompare cette

Conversion analogique/numérique /127


valeur à la valeur de la temporisation que l’on donne à la fonction delay(), on n’en est
pas très loin, d’autant plus que delay() attend une valeur en millisecondes.
Si on lui passait une valeur comprise entre 0 et 1 023, on aurait donc un chenil-
lard avec une vitesse de défilement comprise entre 0 et 1,023 seconde.
On pourrait donc câbler le potentiomètre sur A0, et donner la valeur lue à
delay() afin de régler la vitesse de défilement ! Trop bien…

Figure 5.22 Schéma du chenillard

Figure 5.23 Implantation du chenillard

128/ Chapitre 5 : Premiers montages


Et enfin le programme :
// (c)Frédéric SILLON 2020
// Chenillard avec Leds sur pins 9, 10, 11, 12
// Reglage de vitesse avec potentiometre
// Arduino UNO
 
// --- Definition des Leds sur les pins 9, 10, 11, 12 du connecteur Arduino
#define LED_A 9 // On definit LED1, les autres seront calculees
// automatiquement
#define POTENTIO A0 // Et le potentiometre sur entrée A0
 
// --- On met les pins de chaque Led en sortie
void setup() {
int i;
for (i=0; i<4; i++) {
pinMode(LED_A + i, OUTPUT); // En sortie pour chaque Led
digitalWrite(LED_A + i, LOW); // On eteint les Leds
}
}

// --- Le chenillard se deroule avec le delay reglable


void loop() {
int i;
for (i=0; i<4; i++) {
digitalWrite(LED_A + i, HIGH); // Allume LED
delay(analogRead(POTENTIO)); // Lecture POTENTIO pour delay
digitalWrite(LED_A + i, LOW); // Extinction LED
}
}
En maintenant, la vitesse de défilement du chenillard varie bien en fonction de
la position du potentiomètre, et donc en fonction de la valeur de tension présente
sur l’entrée analogique A0 !
On avait parlé d’une autre façon de visualiser la valeur de cette tension sur A0,
et même de mesurer précisément cette tension comme le ferait un voltmètre.
Pour cela, on va utiliser le Moniteur série d’Arduino.

LE MONITEUR SÉRIE D’ARDUINO


Pour téléverser le programme sur la carte Arduino, on passe par le port USB de
l’ordinateur. Cette liaison permet d’établir un dialogue qui peut aussi être utilisé
d’une autre façon.

Le Moniteur série d’Arduino /129


Si on clique sur le menu Outils puis Moniteur série :

Figure 5.24 Accès au Moniteur Série

On va voir apparaître une nouvelle fenêtre.

Figure 5.25 Le moniteur série

Il s’agit d’une fenêtre qui nous permet de dialoguer avec notre Arduino par le
biais du cordon USB.
L’Arduino va pouvoir y envoyer des résultats, et on pourra taper des comman­
des qui seront envoyées à la carte. À nous programmeurs de développer le pro-
gramme qui lira ces données reçues par l’Arduino.
Pour que l’Arduino envoie une chaîne de caractères vers le Moniteur série, il
suffit de mettre une ligne dans notre programme, par exemple :
Serial.print(“Bonjour”);
Avant cela, il faudra lui indiquer à quelle vitesse on veut que les informations
circulent. Dans le moniteur série, on voit que la vitesse est ici de 19 200 bauds.
Il va alors falloir mettre la même vitesse dans notre programme afin que les
deux se comprennent, et on mettra cette instruction dans le setup():
Serial.begin(19200);
Petite astuce : si on rajoute \n à la fin de la phrase, le moniteur série sautera une
ligne après avoir écrit, ce qui sera beaucoup plus lisible pour la phrase suivante :
Serial.begin(19200);
Serial.print("Initialisation du setup terminée \n");
Serial.print("Tout est prêt !!");

130/ Chapitre 5 : Premiers montages


Figure 5.26 Résultat dans le Moniteur Série

Donc, si on veut que notre Arduino envoie la valeur lue sur la pin A0 (le
­POTENTIO), on pourra passer par cette fonction Serial.print().
// (c)Frédéric SILLON 2020
// Chenillard avec Leds sur pins 9, 10, 11, 12
// Reglage de vitesse avec potentiometre et sortie sur le Moniteur Serie
// Arduino UNO

// --- Definition des Leds sur les pins 9, 10, 11, 12 du connecteur Arduino
#define LED_A 9 // On ne definit que LED_A
#define POTENTIO A0 // Et le potentiometre sur A0

// --- On met les pins de chaque Led en sortie


void setup() {
int i;
for (i=0; i<4; i++) {
pinMode(LED_A + i, OUTPUT); // En sortie pour chaque Led
digitalWrite(LED_A + i, LOW); // On eteint les Leds
}
Serial.begin(19200); // Init de Serial pour Moniteur
Serial.print("Initialisation du setup terminée \n");
Serial.print("Tout est prêt !!"); // Messages sur Moniteur
}

// --- Le chenillard se deroule


void loop() {
int i;
for (i=0; i<4; i++) {
digitalWrite(LED_A + i, HIGH); // Allume LED
delay(analogRead(POTENTIO)); // Lecture POTENTIO pour delay
Serial.print(analogRead(POTENTIO)); // Envoie sur Moniteur serie
Serial.print("\n"); // On saute une ligne sur moniteur
digitalWrite(LED_A + i, LOW); // Extinction LED
}
}
Pour l’instant, on effectue deux lectures de A0 avec la fonction analogRead(),
une pour le delay(), et l’autre à la ligne suivante pour le moniteur. Faire ces deux
conversions fait perdre beaucoup de temps à notre Arduino. Il vaut mieux n’en
faire qu’une seule, et sauvegarder le résultat dans une variable que l’on utilisera

Le Moniteur série d’Arduino /131


ensuite. De plus en faisant ainsi, on est sûr que ce qui est envoyé sur le moniteur
est bien la même valeur que celle du delay(). En effet, le potentiomètre aurait pu
bouger entre les deux instructions analogRead().
On arrive donc à ceci en utilisant la variable conversion, et en ne réécrivant que
le loop(), le reste étant inchangé.
void loop() {
int i;
int conversion; // On declare la variable conversion
for (i=0; i<4; i++) {
conversion = analogRead(POTENTIO); // Memorisation conversion
digitalWrite(LED_A + i, HIGH); // Allume LED
delay(conversion); // Lecture POTENTIO pour delay
Serial.print(conversion); // Envoie sur Moniteur serie
Serial.print("\n"); // On saute une ligne sur moniteur
digitalWrite(LED_A + i, LOW); // Extinction LED
}
}
On voit tout de suite l’intérêt du Moniteur série…

ET À L’ENVERS…
Maintenant que l’on sait faire varier la vitesse de notre chenillard avec le poten-
tiomètre, on va essayer de le faire tourner à l’envers.
Si on utilisait le bouton poussoir, on pourrait le faire tourner dans un sens si
le bouton est relâché, et dans l’autre sens s’il est appuyé, tout ceci en gardant le
réglage de vitesse…
Allons-y !
Comme dans l’exemple du bouton poussoir, on va le câbler sur la pin D7, le che-
nillard restera tel qu’il est déjà et on va donc avoir le schéma suivant.

Figure 5.27 Schéma du chenillard avec BP et Potentio

132/ Chapitre 5 : Premiers montages


Figure 5.28 Implantation du chenillard avec BP et Potentio

Voyons à présent le croquis de ce montage.


// (c)Frédéric SILLON 2020
// Chenillard avec Leds sur pins 9, 10, 11, 12
// Reglage de vitesse avec potentiometre et sortie sur Moniteur serie
// Inversion du sens avec BP
// Arduino UNO

// --- Definition des Leds sur les pins 9, 10, 11, 12 du connecteur Arduino
#define LED_A 9 // On ne definit que LED_A
#define POTENTIO A0 // Et le potentiometre sur A0
#define BOUTON_POUSSOIR 7 // Bouton poussoir connecte sur pin 7

int etatDuBouton = 0; // Sauvegarde de l'état du bouton (on/off)

// --- On met les pins de chaque Led en sortie et le BP en entree


void setup() {
int i;
for (i=0; i<4; i++) {
pinMode(LED_A + i, OUTPUT); // En sortie pour chaque Led
digitalWrite(LED_A + i, LOW); // On eteint les Leds
}
pinMode(BOUTON_POUSSOIR, INPUT); // On veut lire le bouton, donc Input
Serial.begin(19200);
Serial.print("Initialisation du setup terminée \n");
Serial.print("Tout est prêt !!");
}

Et à l’envers… /133
// --- Le chenillard se deroule
void loop() {
int i; // Pour compter dans la boucle for
int conversion; // Pour lecture du Potentio

etatDuBouton = digitalRead(BOUTON_POUSSOIR); // On lit l'etat du bouton


conversion = analogRead(POTENTIO); // On lit Potentionmetre
if (etatDuBouton == true) { // Si BP relache, donc entree=High
for (i=0; i<4; i++) { // On boucle 4 fois
digitalWrite(LED_A + i, HIGH); // Allume LED
delay(conversion); // Lecture POTENTIO pour delay
Serial.print(conversion); // Envoie sur Moniteur serie
Serial.print("\n"); // Saute une ligne sur moniteur
digitalWrite(LED_A + i, LOW); // Extinction LED
}
}
else {
for (i=0; i<4; i++) { // On boucle 4 fois
digitalWrite(LED_A + 3 - i, HIGH); // Allume LED
delay(conversion); // Lecture POTENTIO pour delay
Serial.print(conversion); // Envoie sur Moniteur serie
Serial.print("\n"); // Saute une ligne sur moniteur
digitalWrite(LED_A + 3 - i, LOW); // Extinction LED
}
}
}
Dans ce croquis, on a l’initialisation de l’ensemble dans le setup() avec les Leds
en sortie, et le bouton poussoir en entrée. On a déjà étudié tout ça.
Ensuite, dans le loop(), on lit la valeur du potentiomètre que l’on mémorise
dans conversion, et aussi l’état du bouton poussoir que l’on mémorise dans etat-
DuBouton.
Comme dans l’exemple précédent parlant du bouton poussoir, il est relié à l’ali-
mentation 5V par une résistance de 10 KΩ. Si le bouton poussoir est relâché,
l’entrée de l’Arduino va donc voir ce 5V qu’il considère comme un état haut. La
fonction digitalRead() renverra donc true.
Lorsqu’il est appuyé, l’entrée de l’Arduino verra 0 volt car elle se retrouvera à
GND et digitalRead() renverra donc false.

Pour mieux comprendre, il faudra réfléchir en regardant attentivement le schéma.


Donc, si le BP est appuyé ou relâché, on va faire défiler le chenillard dans un
sens ou dans l’autre.
Pour le premier sens, on conserve les lignes de code que l’on avait écrites dans
les exemples précédents puisqu’elles fonctionnent.
Par contre, pour faire tourner le chenillard dans l’autre sens, il va falloir décré-
menter le numéro de la Led au lieu de l’incrémenter.

134/ Chapitre 5 : Premiers montages


Pour rappel, incrémenter veut dire plus et décrémenter veut dire moins.
En même temps, on va faire 4 tours de la boucle for. On peut donc se servir de
ces quatre tours pour calculer en même temps le numéro de la Led à éteindre ou
à allumer.
Si on réfléchit un peu, et en repensant à nos Leds A B C D qui sont montées sur
les pins 9 10 11 et 12 de l’Arduino comme on l’a déjà vu, on a pu dire que :
LED_B = LED_A + 1
LED_C = LED_B + 1
LED_D = LED_C + 1
Ça marche aussi dans l’autre sens :
LED_C = LED_D – 1
LED_B = LED_C – 1
LED_A = LED_B – 1
Si ce n’est pas clair, on réfléchit de nouveau avec un papier et un crayon pour
faire un petit dessin…
En partant de ce constat, pour allumer la LED_A (câblée sur la pin 9), cela
revient à allumer la LED_B–1 (car LED_B est sur la pin 10, donc pin 10–1 = pin 9 :
on arrive bien sur la LED_A).
Pareil pour allumer la LED_C, on peut se dire que c’est la LED_D–1.
En allant plus loin, la LED_D est bien la LED_A+3…
En effet, la LED_A est câblée sur la pin 9, et comme 9 + 3 vaut 12, cela corres-
pond bien au numéro de pin de la LED_D qui est 12.
Facile…
Avec le chenillard dans ce sens, la Led de départ est la LED_D et on va donc
changer le sens de défilement en décrémentant le numéro de la pin en partant de
LED_D. Pour faire LED_D LED_C LED_B LED_A, on va donc faire 12–11–10–9, et
sortir de la boucle for.
On part donc de LED_A+3 (qui est bien la LED_D), et lui retrancher la valeur de
la variable i qui compte de 0 à 4 dans la boucle for.
Comme i augmente de 1 à chaque tour de cette boucle, on va bien avoir :
LED_A + 3 – i qui vaut au premier tour : 9 + 3 – 0 = 12 (donc LED_D)
LED_A + 3 – i qui vaut au second tour : 9 + 3 – 1 = 11 (donc LED_C)
LED_A + 3 – i qui vaut au troisième tour : 9 + 3 – 2 = 10 (donc LED_B)
LED_A + 3 – i qui vaut au premier tour : 9 + 3 –3 = 9 (donc LED_A)
On voit bien que l’on a fait défiler le chenillard à l’envers de façon simple au
niveau du code.
Il a juste fallu réfléchir un peu afin d’adapter le code que nous avions déjà fait
à cette nouvelle situation de chenillard inversé.
On voit que les deux boucles sont très proches au niveau de leur construction,
il n’y a que le calcul du numéro de la Led qui change. Toujours avec notre principe
DRY, il doit y avoir moyen de raccourcir ce code en utilisant ce que l’on a déjà
appris sur les fonctions dans les chapitres précédents.

Et à l’envers… /135
Je vous laisse faire l’exercice tout seul, et même s’il ne fonctionne pas du
premier coup, il ne faut pas se décourager. Pour savoir si votre nouvelle version
­fonctionne, il faudra juste vérifier qu’elle se compile correctement, et que le résul-
tat est bien celui attendu lorsque le croquis sera téléchargé sur la carte Arduino.

PLUS FORT AVEC LE TRANSISTOR…


Un autre composant très intéressant pour nos montages est le transistor. Il
s’agit d’un composant dit semiconducteur, car au lieu de toujours conduire le cou-
rant comme le fait une résistance par exemple, il a la super fonction de conduire
ou pas le courant, un peu ou beaucoup en fonction des autres composants avec
lesquels il travaille.
Comme nous l’avons déjà un peu abordé, le transistor a été une véritable
révolution, et il est à l’origine de l’électronique moderne. Tous les µC ou µP en
contiennent des milliers, même notre Arduino, et on les trouve également dans
des petits boîtiers en métal ou en plastique. Ils peuvent faire passer des quantités
de courant très impressionnantes sans se détériorer, à condition de les utiliser
dans de bonnes configurations.
Nous allons rapidement regarder à quoi ils peuvent nous servir avec notre carte
Arduino.
Chaque pin de notre Arduino peut fournir une certaine quantité de courant
avant de brûler. En effet, on a vu dans les chapitres précédents que le courant
qui passe dans un fil génère de la chaleur due aux mouvements des électrons.
Si on demande trop de courant à une sortie de notre Arduino, cette sortie va se
détruire. Elle ne sera plus utilisable, et notre Arduino non plus.
Le µC de notre Arduino est un ATMega328P, et si on télécharge sa datasheet
sur Internet, on verra une rubrique qui s’appelle Absolute Maximum Ratings. On
peut traduire ça par Valeurs maximales à ne pas dépasser.
Si on regarde la ligne DC Current per I/O pin, (courant DC par pin) on voit que
la valeur donnée pour ce maximum rating est de 40 mA.

Figure 5.29 ATMega328P maximum ratings

136/ Chapitre 5 : Premiers montages


Si on dépasse cette valeur de courant sur une pin, elle a de très grandes
chances d’être détruite. On va donc essayer de rester en dessous de cette valeur
dans toutes les circonstances, en se fixant une limite à 30 mA par exemple afin de
garder un peu de sécurité supplémentaire.
De plus, il faudra réduire encore cette valeur maximale si plusieurs sorties sont
activées en même temps afin de ne pas dépasser la valeur maximale que le µC
lui-même peut fournir sur toutes ses sorties.
Comment faire si on a besoin de piloter un petit moteur électrique de robot qui
va consommer 300 mA par exemple ?
Et bien dans ce cas, le transistor entre dans la danse !

// LE TRANSISTOR NPN

Figure 5.30 Symbole du transistor NPN

On voit sur ce symbole que le transistor a trois pattes. À gauche, il s’agit de la


Base, en haut du Collecteur et en bas de l’Emetteur.
On voit également qu’il y a une flèche sur l’émetteur, avec son sens qui sort du
transistor. Il s’agit ici d’un transistor de type NPN (il existe des types PNP, avec la
flèche dans l’autre sens), et le courant va circuler dans le sens de la flèche.
En résumé, on peut dire que si on apporte un petit peu de courant sur la Base
du transistor, il va faire passer un courant plus important que celui-ci sur sa liai-
son Collecteur-Emetteur. De même, si on ne met pas de courant sur sa Base, il
n’en fera pas passer sur sa liaison Collecteur-Emetteur. C’est un peu comme la
commande d’un robinet dans ce cas, ou comme un interrupteur commandé en
courant.
On va régler ce courant que l’on applique sur sa base avec une résistance.
On pourra se servir de cette fonction d’amplification du courant, pour faire par
exemple un… amplificateur…
La relation qu’il y a entre le courant de Base et le courant Collecteur s’appelle
le Gain en courant, et il est défini dans la datasheet de chaque modèle de transis-
tor. Ainsi, certains transistors ont un gros gain en courant, d’autres seront choisis
pour leur rapidité à passer d’ouvert à fermé, etc. Certains montages à transistors
peuvent être très complexes.

Plus fort avec le transistor… /137


On peut aussi utiliser les transistors en commutation. Dans ce cas, on va mettre
un courant suffisamment élevé sur sa base pour qu’il se conduise comme un inter-
rupteur. Certains transistors sont plus particulièrement adaptés pour être utilisés
en amplification, d’autres en commutation.
On voit tout de suite l’intérêt du transistor dans notre cas : si notre Arduino ne
peut pas fournir assez de courant sur une pin configurée en sortie pour piloter
notre petit moteur, on pourra alors piloter un transistor avec l’Arduino, et ensuite
piloter le moteur avec le transistor.
On pourrait également piloter une Led avec ce même principe, par exemple
avec ce montage.

Figure 5.31 Montage d’un transistor avec une Led

On va essayer de faire ce montage pour piloter la Led depuis notre Arduino.


Avant cela, regardons le schéma d’un peu plus près, en imaginant que la résis-
tance mise sur la Base laisse passer assez de courant pour que le transistor fonc-
tionne en commutation.
Si on met un niveau High sur la sortie qui pilotait jusqu’à présent notre Led
LED_EXTERNE depuis Arduino, on va amener un peu de courant sur la base du
transistor par la résistance R2 qui vaut ici 1 KΩ.
Comme on peut dire que l’on amène suffisamment de courant pour que le tran-
sistor conduise, il va laisser passer un courant à travers R1 et la Led, en fermant
sa jonction Collecteur-Emetteur.
Il est alors un peu comme un interrupteur fermé, la Led s’allume.

138/ Chapitre 5 : Premiers montages


Figure 5.32 Le transistor conduit

On voit bien sur ce schéma équivalent que le courant qui traverse la Led n’est
pas fourni par la sortie de l’Arduino, mais directement par l’alimentation 5V du
système. On ne risque plus de détruire notre cher ATMega.
Si on met un état Low sur la sortie de l’Arduino qui pilote ce montage, on n’aura
pas de courant qui va arriver sur sa Base, et le transistor sera bloqué.
Il est alors comme un interrupteur ouvert et la Led est éteinte.

Figure 5.33 Le transistor est bloqué

Plus fort avec le transistor… /139


Essayons cela sur notre Arduino.
Les transistors que nous allons utiliser ici sont des modèles 2N2222 en boîtier
TO92. Il s’agit d’un petit boîtier plastique, et il existe aussi en boîtier métallique
TO18. C’est un modèle très courant et pas cher, que l’on pourra facilement trouver
chez les revendeurs de composants, mais aussi sur de nombreux appareils élec-
troniques que l’on aura récupérés.
Si on cherche la datasheet du 2N2222 sur Internet, on en trouvera par exemple
une chez le constructeur ON Semi. Comme d’habitude, on y trouvera toutes
les caractéristiques de ce transistor, mais également son brochage (brochage
= comment le brancher).

Figure 5.34 Brochage 2N2222, boîtier TO-92

On retrouve effectivement ici le symbole que nous avons utilisé pour notre
schéma, et aussi le brochage en boîtier TO92. Il en existe deux versions, avec les
pattes droites ou pliées.
En partant de la gauche, on voit bien où est le Collecteur, la Base et l’Emetteur.
Pour le repérer sur le boîtier lui-même, il suffit de mettre la face plate face à
soi, et la pin 1 se trouvera à gauche.
Passons au schéma et à l’implantation sur l’Arduino.

140/ Chapitre 5 : Premiers montages


Figure 5.35 Schéma Transistor / Led

Avant de brancher tout ça sur l’ordinateur, il faudra bien vérifier le câblage afin
d’être sûr qu’il n’y ait pas de court-circuit, car le montage commence à devenir un
petit peu complexe à câbler.
Dans ce schéma, on utilise l’alimentation 5V de l’Arduino pour alimenter le
montage à transistor.
Un des autres avantages de ce type de montages est que l’on peut utiliser une
autre source d’alimentation. Par exemple, on pourrait alimenter notre Arduino
en 5V, et le transistor pilotant la Led en 12V.
Cela permet de piloter des systèmes différents de celui de commande de façon
très simple.
On aurait également pu utiliser un transistor spécialisé en commutation, mais
notre petit 2N2222 est suffisant pour ce type de montages. Si on n’en a pas, il
suffira de regarder les caractéristiques d’un autre modèle et d’adapter la résis-
tance de base par exemple.
On pourra aussi démonter un vieil appareil qui ne sert plus et récupérer un
transistor dessus. De toutes façons, ces petits transistors ne sont pas très chers
et sont très souvent utilisés, et ce sera une bonne chose d’en avoir une poignée
sous la main pour divers montages.

Plus fort avec le transistor… /141


Figure 5.36 Implantation Transistor/Led

Au niveau du code, on pourra reprendre le croquis que l’on avait écrit pour
MonBlink. On obtiendra exactement le même résultat, mais avec un montage dif-
férent qui fait intervenir notre transistor.
// (c)Frédéric SILLON 2020
// Clignotant avec la Led Externe sur Pin 8 et la Led interne L

#define LED_EXTERNE 8 // Explique à l’IDE que la Led est sur la pin 8


// fonction setup(): Initialisation de la carte Arduino
void setup() {
pinMode(LED_EXTERNE, OUTPUT); // Initialise la pin 8 en sortie
pinMode(LED_BUILTIN, OUTPUT); // Ainsi que la sorite de la Led L
}
// fonction loop(): notre clignotant
void loop() {
digitalWrite(LED_EXTERNE, HIGH); // Led externe ON
digitalWrite(LED_BUILTIN, HIGH); // Led L ON
delay(1000); // Attente
digitalWrite(LED_EXTERNE, LOW); // Led externe OFF
digitalWrite(LED_BUILTIN, LOW); // Led L OFF <
delay(1000); // Attente
} // On reboucle !!

142/ Chapitre 5 : Premiers montages


Et voilà, on sait à présent utiliser un montage simple à transistor.
En faisant tourner ce programme sur notre carte Arduino, on remarque que
la Led externe pilotée par le transistor s’allume et s’éteint en même temps
que la LED_BUILTIN.

/ TRANSISTOR PNP
On a vu que ce transistor est un modèle NPN. Que se passe-t-il avec un modèle
PNP ? Pour le savoir, on va réaliser le même type de montage, mais avec un tran-
sistor 2N2907, toujours en boîtier TO-92.
En cherchant la datasheet du 2N2907 sur Internet, on la trouvera également
chez le fabricant OnSemi. Son brochage et son symbole sont :

Figure 5.37 Transistor PNP 2N2907

On voit tout de suite que la flèche qui est présente sur son symbole au niveau
de l’émetteur est dans l’autre sens. Il y a fort à parier que son utilisation sera
différente…
Si on refait le même montage que précédemment avec ce 2N2907 (PNP), la
Led et la résistance seront toujours sur le Collecteur, mais avec l’Emetteur à l’ali-
mentation au lieu du zéro volt.

Plus fort avec le transistor… /143


Figure 5.38 Schéma avec transistor PNP

Figure 5.39 Implantation avec transistor PNP

Au niveau du code, on laisse MonBlink comme précédemment dans l’Arduino,


et on regarde ce qu’il se passe.

144/ Chapitre 5 : Premiers montages


Qu’est-ce que l’on observe ? Et bien on voit que la Led pilotée par ce transis-
tor et LED_BUILTIN ne s’allument plus en même temps comme précédemment. À
présent, LED_BUILTIN s’allume lorsque la Led transistorisée s’éteint et vice versa.
On a donc réalisé un montage qui fonctionne à l’envers, qui est un inverseur
pour notre Led externe.
Généralement, le transistor NPN est plus souvent utilisé que le modèle PNP,
mais il est bon d’avoir les deux modèles dans ses tiroirs.

/ LE TRANSISTOR MOSFET
Les transistors précédents sont des modèles dits bipolaires (PNP et NPN).
Il existe cependant d’autres modèles, dont le MOSFET. Si on recherche de nou-
veau une datasheet de mosfet sur Internet, on choisira par exemple le BS170.

Figure 5.40 Brochage du Mosfet BS170

On voit tout de suite qu’il s’agit d’un composant bien différent. Il est plus parti-
culièrement adapté au mode commutation et s’utilise très simplement.
On ne parlera plus de Base, Collecteur et Emetteur, mais de Grille (Gate en
anglais), Drain et Source.
Si on regarde les Maximum Ratings du BS170, on verra qu’il ne faut pas dépas-
ser certaines valeurs comme la tension VDSS qui représente la tension maximale
qu’il peut y avoir entre le Drain et la Source (60 V). Dans notre montage, il n’y aura
que 5 volts au maximum, on sera donc correct. Pareil pour la tension VGSS (entre
Gate et Source) qui doit être de 20 V max. Avec notre sortie Arduino qui ne fournit
que 5 V, on sera également très bien.
Le courant circulant dans le Drain ne devra pas dépasser 500 mA. Il faudra
donc bien calculer notre résistance de drain pour ne pas dépasser cette valeur.

Figure 5.41 Maximum ratings BS170

Plus fort avec le transistor… /145


En technologie mosfet il n’y a pas de PNP ou NPN comme en technologie bipo­
laire, mais il y a des canal N ou canal P. Le BS170 est un canal N.
Le montage avec notre Led ressemblera à présent à ceci :

Figure 5.42 Montage avec un MOSFET BS170

Figure 5.43 Implantation avec un MOSFET BS170

146/ Chapitre 5 : Premiers montages


Toujours en conservant MonBlink dans l’Arduino, on verra la Led externe pilo-
tée par le BS170 qui s’allume en même temps que la LED_BUILTIN.
À présent, si on ajoute un second BS170 à la suite du premier, on pourra faire
clignoter deux Leds en même temps.

Figure 5.44 Schéma avec deux MOSFET BS170

On voit ici que le premier mosfet Q1 est piloté par notre sortie D8 Arduino.
Donc lorsque la sortie Arduino amènera un niveau HIGH sur ce premier mosfet,
celui-là deviendra conducteur. Sa jonction Drain-Source sera comme un interrup-
teur fermé, et la cathode de la Led_1 se trouvera à Gnd. Elle va donc s’allumer. Si
ce n’est pas très clair, on pourra revoir les chapitres précédents.
Si l’Arduino applique un niveau LOW sur sa sortie D8, le mosfet Q1 sera alors
bloqué et se comportera comme un interrupteur ouvert. La Led_1 sera alors
éteinte.
Pour le second mosfet Q2, lorsque la sortie Arduino mettra un état HIGH sur
sa sortie D8, on vient de voir que la jonction Drain-Source de Q1 est comme un
court-circuit, et la cathode de Led_1 est à Gnd. Cela veut dire que la Grille de Q2
est également à Gnd. Donc, Q2 va être bloqué et sa jonction Drain-Source sera
ouverte. Dans ce cas, la Led_2 sera éteinte.
Si Arduino met ensuite sa sortie D8 à LOW, on a vu que Q1 est bloqué, donc sa
jonction Drain-Source est ouverte. Dans ce cas, la grille de Q2 ne voit plus Gnd,
mais elle voit la tension qu’il y a sur la cathode de la Led_1. Q2 va fermer sa jonc-
tion Drain-Source. La Led_2 va alors s’allumer.
Si on regarde ces signaux avec un oscilloscope, on pourra voir comment tout
cela se passe en réalité.

Plus fort avec le transistor… /147


Figure 5.45 Oscillogramme Grille de Q1 et Grille de Q2

Un oscilloscope est un appareil que l’on branche sur le circuit que l’on veut exa-
miner. Il permet de visualiser les signaux électriques comme ils sont en réalité.
Comme il s’agit d’un appareil coûteux et assez complexe à utiliser, nous n’en par-
lerons pas davantage, mais il est bon de savoir qu’il existe. On branche simplement
ses fils sur les signaux que l’on veut visualiser, et on peut les observer en vrai !
La trace du haut est branchée sur la sortie D8 de l’Arduino, et la trace du bas
est branchée sur la grille de Q2. On voit bien ici que pendant que la première est
à HIGH, la seconde est à LOW et inversement.
Comme un petit dessin vaut mieux qu’un grand discours, voici le schéma pour
l’état HIGH et pour l’état LOW de la sortie D8 de notre cher Arduino.

Figure 5.46 Sortie D8 à l’état HIGH

148/ Chapitre 5 : Premiers montages


Figure 5.47 Sortie D8 à l’état LOW

Passons maintenant à l’implantation.

Figure 5.48 Implantation avec deux MOSFET BS170

Et on conserve toujours MonBlink dans l’Arduino : Led_1 et Led_2 s’allument à


tour de rôle.

Plus fort avec le transistor… /149


Le but de ce chapitre n’était pas de faire un cours complet sur le transistor.
C’est un composant qui peut être utilisé dans des montages très complexes avec
de nombreux calculs qui sortent du cadre de cet ouvrage. Il s’agit simplement
d’entrevoir les possibilités qu’il offre, et de mieux le comprendre lorsqu’il appa-
raît dans un schéma. Pour en apprendre davantage à son sujet, on pourra donc
consulter les nombreux ouvrages qui lui sont consacrés, ainsi que les sites des
constructeurs.
/> CHAPITRE
FONCTIONS AVANCÉES
6

Nous allons voir des fonctions que l’on appelle « avancées » de notre Arduino,
en utilisant des fonctions plus complexes dont il dispose en interne.
Accrochons-nous…

LE PWM
Le PWM est une fonction interne de l’Arduino, qui signifie Pulse Width Modula­
tion… En français, il s’agit de modulation en largeur d’impulsion, ou MLI.
Jusqu’à présent, nos sorties digitales de l’Arduino nous donnaient des états
High ou Low lors de l’utilisation de digitalWrite(). Comme on l’a vu sur l’oscil-
logramme du chapitre précédent sur la sortie D8, on avait choisi par programme
que la durée de l’état High était d’une seconde, et que la durée de l’état Low était
d’une seconde également.
On peut donc dire que nos impulsions ont une durée d’une seconde.
Si on voulait faire varier cette largeur de nos impulsions, on pourrait changer
la valeur du delay() à chaque passage dans la boucle.
Ce serait un peu complexe, mais ça fonctionnerait. On pourrait également
garder la même durée de l’état Low, et ne changer que la durée de l’état High à
chaque tour de loop().
En faisant ainsi, on aurait en quelque sorte une modulation en largeur d’im-
pulsion, car on modifierait la largeur de nos impulsions à chaque tour de loop().
Ce n’est pas très pratique, mais c’est un peu le principe du PWM. Non seule-
ment il gère lui-même la largeur de ces impulsions, mais aussi à quel moment a
lieu le changement d’état.

Le PWM /151
Si on regardait un tel programme à l’oscilloscope, on aurait quelque chose comme :

Figure 6.1 Oscillogramme de largeur d’impulsion

Le rapport qu’il y a entre l’état haut et l’état bas du signal ainsi créé s’appelle
le rapport cyclique. Dans notre sketch Blink, lorsque l’on a mis delay(1000) pour
l’allumage et pour l’extinction des Leds, on avait un rapport cyclique de 50 % car
la durée de l’état haut était égale à la durée de l’état bas.
Un rapport cyclique de 0 % indique que le signal est toujours Low, et un rap-
port cyclique de 100 % indique qu’il est toujours High. Entre ces deux extrêmes,
le rapport cyclique varie.
Il y a un second paramètre à prendre en compte pour un PWM : la fréquence.
La fréquence indique à quelle vitesse le signal se répète. S’il repasse à l’état haut
toutes les secondes, il aura une fréquence de 1 hertz (1 Hz).
Le hertz est l’unité de mesure de fréquence.
À partir d’un top départ, s’il repasse à l’état haut toutes les 0,1 seconde, on aura
une fréquence de 10 Hz.
La formule magique pour déterminer la fréquence F en fonction du temps T est :
1
F=
T
Le temps T est en secondes, et la fréquence F en hertz.
Ainsi, si le signal revient à l’état haut toutes les 0,1 seconde, on aura une fré-
quence de 1/ 0,1 = 10 Hz. Il revient alors à l’état high 10 fois par seconde.

Figure 6.2 Signal 10 hertz, rapport cyclique 50 %

Comme pour les autres unités, on va avoir des Hz, des KHz (1 KHz = 1 kilohertz
= 1 000 Hz), des MHz (1 MHz = 1 mégahertz = 1 000 000 Hz) et bien plus encore.

152/ Chapitre 6 : Fonctions avancées


Les deux paramètres à prendre en compte pour un PWM sont donc la fréquence
du signal ainsi que son rapport cyclique.
Dans notre Arduino, certaines sorties sont capables de travailler en PWM, et
elles sont repérées par un symbole Tilde (~) sur les connecteurs de notre carte.

Figure 6.3 Sorties PWM repérées par tilde ~

Sur la carte Arduino UNO, on voit que ces sorties sont D3, D5, D6, D9, D10 et D11.
Nous avons déjà utilisé les sorties D9, D10, D11 et D12 pour notre chenillard par
exemple, et cela veut donc dire que certaines pins de notre Arduino peuvent avoir
plusieurs fonctions.
Pour programmer D9 en état HIGH ou LOW par exemple, on avait utilisé la fonc-
tion digitalWrite(). On aurait également pu mettre un bouton poussoir sur D9 au
lieu de le mettre sur D7 comme nous l’avons fait précédemment avec digitalRead().
À présent, nous allons utiliser une autre fonction que l’on va associer à une pin :
analogWrite(). Nous avions déjà parlé de analogWrite(), car elle permet de géné-
rer un signal variable sur la pin considérée. Si on veut créer un signal qui varie de 0
à 5 volts (un signal analogique), il faudra associer quelques composants simples à
cette sortie. Pour l’instant, on va l’utiliser telle quelle est, en fonction PWM.
Nous avons vu qu’un PWM est défini par la fréquence du signal qu’il produit,
ainsi que par son rapport cyclique. Avec analogWrite(), nous allons simplement
définir la pin à utiliser, ainsi que le rapport cyclique désiré qui peut varier de 0
à 100 %. Pour la fréquence du signal, c’est l’Arduino lui-même qui s’occupe de tout.
La syntaxe est alors la suivante :
analogWrite(pin, valeur);
Pin est le numéro de la sortie.
Valeur est un entier qui varie de 0 à 255 pour définir un rapport cyclique de 0
à 100 % (127 correspondra donc à 50 %).
Pour utiliser une sortie en PWM avec analogWrite(), il n’est pas nécessaire
de la déclarer en sortie avec pinMode() comme nous l’avions fait pour digital
Write(). Arduino se débrouille tout seul…
Avec le petit sketch que voici, nous allons pouvoir créer un PWM, et l’observer
à l’oscilloscope.

Le PWM /153
// (c)Frédéric SILLON 2020
// Signal PWM sur la sortie D9

#define SIGNAL_PWM 9 // On va sortir un PWM sur la pin 9


#define RAPPORT_CYCLIQUE 255/4 // On va faire un PWM à 25%
// (donc 255 divisé par 4)

void setup() {
analogWrite(SIGNAL_PWM, RAPPORT_CYCLIQUE);
}

void loop() {
// Rien à faire, le PWM tourne tout seul ...
}

Figure 6.4 Oscillogramme du PWM à 25 %

Il y a deux choses que l’on peut remarquer.


La première dans le code source est que le loop() est vide, ce qui est assez
inhabituel… En effet, nous avons initialisé le PWM dans le setup(), et une fois
initialisé, il va tourner indéfiniment sans que l’on s’en occupe.
La seconde sur l’oscillogramme montre que la fréquence que l’Arduino a géné-
rée tout seul est de 500 Hz. On voit bien que l’état haut dure un quart du temps de
la totalité comprise entre les deux curseurs en pointillés. On voit également que
la période du signal que l’on a ainsi fabriqué est comprise entre les deux curseurs.
Comme on l’a vu précédemment, la fréquence est définie par la formule :
1
F=
T
On en déduit facilement que le temps T vaudra :
1
T=
F
Comme la fréquence que l’oscilloscope mesure est de 500 Hz, la période de ce
signal sera alors de T = 1/500 = 0,002 s.
La totalité du signal dure donc 0,002 seconde, soit 2 millisecondes avant de se
reproduire à l’identique. L’état haut quant à lui durera donc 25 % de ces 2 ms, soit
2/4 = 0,5 ms soit 500 µS (500 micro secondes). C’est plutôt pas mal…
154/ Chapitre 6 : Fonctions avancées
// UN GRADATEUR DE LUMIÈRE AVEC LE PWM
Maintenant que l’on sait comment produire un signal en PWM, voyons ce que
l’on peut en faire.
Si on mettait une Led sur cette sortie PWM, on pourrait régler le temps pen-
dant lequel elle est allumée. Avec un PWM à 100 %, elle serait alliée en perma-
nence et avec un PWM à 0 %, elle serait éteinte. Jusque-là rien de nouveau, car
on faisait déjà ça avec digitalWrite().
Par contre, si on réglait le PWM à 50 % par exemple, elle clignoterait super vite,
et tellement vite par les 500 Hz de la fréquence du signal PMW qu’on ne la verrait
même pas s’éteindre.
Tout ce que notre œil verrait est qu’elle brillerait moins car elle ne serait pas
tout le temps alimentée. Avec un PWM à 25 %, elle brillerait encore moins.
En fait, on pourrait réaliser un gradateur de lumière, comme sur les lampes de
salon qui ont un bouton pour s’allumer plus ou moins fort.
Essayons en branchant une Led avec sa résistance de 220 ohms sur la sor-
tie D9. Je ne vous donne pas le schéma, je vous laisse le faire tout seul.
Pour se rassurer, on pourra toujours se reporter au schéma de MonBlink…
Voyons un peu le sketch.
// (c)Frédéric SILLON 2020
// Signal PWM avec LED sur la sortie D9
#define SIGNAL_PWM 9 // On va sortir un PWM sur la pin 9
int rapportCyclique; // Memo PWM pour pouvoir modifier ensuite

void setup() {
rapportCyclique = 0;
analogWrite(SIGNAL_PWM, rapportCyclique);
}

void loop() {
rapportCyclique +=10;
analogWrite(SIGNAL_PWM, rapportCyclique);
delay(100);
if (rapportCyclique==255)
rapportCyclique = 0;
}
À présent, on a déclaré une variable rapportCyclique afin de pouvoir la faire
varier dans le loop() en l’incrémentant de 10 toutes les 100 ms de delay().
Ainsi, notre Led va s’allumer progressivement toute seule pendant que le rap-
port cyclique du PWM passe de 0 à 255.

// LA LED RVB EN PWM


Il existe une super Led que nous allons utiliser avec notre nouveau PWM, la Led
RVB (ou RGB en anglais) :
>> RVB : Rouge-Vert-Bleu
>> RGB : Red-Green-Blue
Le PWM /155
Que ce soit en français ou en anglais, il s’agit d’une Led qui comporte les trois
couleurs dans le même boîtier. Elle a quatre pattes : une pour chaque couleur et
une cathode commune aux trois autres.
Il faut se rappeler que chaque Led a une tension VF comme nous l’avons déjà
vu, et c’est encore plus vrai pour les Leds en couleur.
Pour simplifier, on va se contenter de mettre une résistance identique sur
chaque couleur et de préférence 470 ohms ou plus, car ce type de Led a un boîtier
transparent qui éclaire vraiment fort et qui peut être désagréable pour les yeux.
On va donc pouvoir piloter chaque couleur individuellement en les reliant cha-
cune à une sortie PWM de l’Arduino. En plus, comme on pourra faire varier chaque
rapport cyclique, on pourra même nuancer le rouge, le bleu et le vert de façon
indépendante. En mélangeant tout ça, notre Led pourra prendre toutes les cou-
leurs de l’arc-en-ciel !
En fait, chaque couleur pourra prendre 256 nuances différentes, codées sur
8 bits.
Comme nous avons trois couleurs, le codage total se fera donc sur 3 × 8 = 24 bits.
Voilà pourquoi on parle parfois de couleurs 16 bits ou 24 bits sur les ordina-
teurs. Avec trois couleurs mélangées, on aura une Led qui pourra prendre plus de
16 millions de couleurs différentes ! Pour calculer le nombre de ces combinaisons
possibles, on va calculer 224, c’est-à-dire 2 × 2 × 2… × 2 × 2 (répété 24 fois).
Si on prend une calculatrice, cela nous fera 16 777 216 possibilités.
On a de quoi s’amuser !
Comme il y a trois Leds dans le même boîtier (une rouge, une verte et une bleu),
on devrait donc avoir six pattes à notre boîtier de Led RGB (deux par Led).
En fait, il existe deux types de Leds RGB, qui sont à cathode commune ou bien
à anode commune. Celle que nous avons dans l’exemple suivant est un modèle à
cathode commune, ce qui veut dire que les cathodes des trois Leds sortent sur la
même patte représentant la cathode, et qui est donc commune aux trois.

Figure 6.5 Schéma d’une Led RGB, Figure 6.6 Brochage de la Led RGB,


cathode commune cathode commune

156/ Chapitre 6 : Fonctions avancées


Sur ce schéma, on voit bien que la cathode est la patte la plus longue. Les
autres seront, de la gauche vers la droite : Red, Green, Blue.
Voilà donc le schéma du montage avec notre Led RGB.

Figure 6.7 Schéma Led RGB en PWM

Figure 6.8 Implantation de la Led RGB

Le PWM /157
Passons maintenant au code.
Nous avons vu qu’il fallait câbler nos trois anodes sur les sorties PWM de
­l’Arduino afin de pouvoir utiliser la fonction analogWrite() pour créer un effet
de fader sur chaque couleur. Nous avons donc utilisé D9, D10 et D11 qui sont repé-
rées par le symbole tilde (~) sur le connecteur de notre carte.
Pour gérer les trois couleurs de façon indépendante, nous allons donc créer
trois variables qui vont s’incrémenter à chaque tour de loop() afin de changer la
couleur finale des trois composantes (RGB) mélangées, et qui seront mises dans
les PWM correspondant à chaque couleur.

Premier essai
// (c)Frédéric SILLON 2020
// Signal PWM avec LED RGB multicolore
#define RED 9 // Led RED sur la pin 9
#define GREEN 10 // Led GREEN sur la pin 10
#define BLUE 11 // Led BLUE sur la pin 11
unsigned char redPWM, greenPWM, bluePWM; // Rapport cyclique PWM des trois↵
composantes
void setup() {
redPWM = greenPWM = bluePWM = 0;
analogWrite(RED, redPWM);
analogWrite(GREEN, greenPWM);
analogWrite(BLUE, bluePWM);
}

void loop() {
redPWM +=10;
greenPWM +=10;
bluePWM +=10;
analogWrite(RED, redPWM);
analogWrite(GREEN, greenPWM);
analogWrite(BLUE, bluePWM);
delay(100);
}
Avec ce croquis, on voit que la Led produit une lumière blanc/bleu, mais qu’il
n’y a pas nos 16 millions de couleurs. En effet, quand on mélange les trois couleurs
RGB en quantités égales, on va créer une lumière presque blanche.
Si on veut une lumière qui soit davantage rouge, on va par exemple incrémenter
redPWM beaucoup plus lentement afin de conserver cette couleur plus longtemps
que les deux autres, ou bien la laisser fixe sans l’incrémenter.

Second essai
redPWM = 200; // On initialise redPWM à une valeur fixe
En jouant sur les différentes valeurs des trois PWM, on va pouvoir obtenir des
couleurs vraiment très belles.
Je vous laisse essayer et choisir les valeurs de PWM pour vos plus belles couleurs.

158/ Chapitre 6 : Fonctions avancées


Figure 6.9

LA LIAISON SÉRIE
Pour que notre Arduino communique avec le monde extérieur, nous avons déjà
utilisé les fonctions telles que digitalRead() et digitalWrite() par exemple.
Avec ce type de fonctions, on peut agir sur le monde extérieur, mais il est plus
difficile de transmettre des ordres par exemple, ou des résultats de calcul.
Pour les résultats, on pourrait très bien les coder en binaire et sortir sur des Leds.
On pourrait imaginer de brancher huit Leds sur l’Arduino et ainsi créer un octet
qui nous servirait à écrire un résultat en binaire. L’inconvénient pour nous humains
est qu’il faudrait faire la conversion de tête à chaque fois qu’un résultat se présente.
De même, on serait limités à des nombres de 8 bits, donc compris entre 0 et 255.
Pour écrire sur l’Arduino, on pourrait également imaginer huit boutons pous-
soirs ou interrupteurs branchés sur les entrées de notre Arduino.
Ainsi, suivant le code binaire que l’on appliquerait sur ces entrées avec nos
interrupteurs, notre µC pourrait interpréter ça comme tel ou tel ordre.
En fait, ce principe était utilisé au tout début des ordinateurs, certains n’avaient
ni clavier ni écran, et on communiquait avec eux de cette façon.
Par chance, notre Arduino dispose d’une interface que nous avons déjà utilisée,
et qui est l’interface série.

// LA SÉRIALISATION
Le principe de la sérialisation est simple : plutôt que de coder nos dialogues sur
huit bits, il suffit de prendre chacun des bits à tour de rôle, et de recopier leur état
sur une seule sortie, un peu comme des billes dans une sarbacane.
On va commencer par le bit b0 par exemple, et suivant s’il est à 1 ou à 0, on va passer
la sortie série à High ou à Low. Ensuite, on regarde l’état du bit b1 et suivant son état,
on passera la même sortie de communication série à High ou à Low. Et ainsi de suite.
De cette façon, on peut passer une très grande quantité d’informations sur un
seul fil, à la queue leu leu.

Figure 6.10 Bits transmis en série

Pour sécuriser cette transmission, on pourra intercaler des bits de contrôle dans
ce flux de données. Par exemple, à la fin de la transmission, on pourra envoyer un
octet (avec tous ses bits à la queue leu leu) qui donnera le nombre de bits envoyés.

La liaison série /159


Du côté du récepteur, il suffit de compter combien de bits on a reçus, et de
comparer ce résultat à l’octet de contrôle. Si les deux correspondent, la transmis-
sion s’est bien passée.
Dans le cas contraire, on peut demander à l’expéditeur du message de le ren-
voyer car on n’a pas tout compris et des bits ont dû se perdre en cours de route.
Ce n’est qu’un exemple, et il y a de nombreuses méthodes pour sécuriser une
transmission série de façon irréprochable. En effet, quand des systèmes impliquant
la sécurité des personnes ou des biens effectuent des transactions délicates, il faut
être sûr et certain que tous les messages sont correctement transmis.
Dans notre Arduino, nous n’irons pas jusque-là, mais la liaison série que nous
allons utiliser comporte tout de même des contrôles qui permettent de détecter
un certain nombre d’erreurs.
D’un autre côté, il faudrait pouvoir envoyer tous ces bits le plus vite possible,
car si on a beaucoup d’informations à transmettre, il faudrait tout de même le
faire dans un minimum de temps. Par contre, si on va trop vite, on prend le risque
d’en perdre la moitié en route. Il faudrait donc que l’on puisse également régler la
vitesse de cette transmission.
En effet, si on est dans un environnement idéal, sans parasites, on pourrait aller
très vite. Par contre, si l’environnement de notre système est pollué par des para-
sites, ou si les fils qui relient l’émetteur et le récepteur sont de mauvaise qualité
ou trop longs, on prend également le risque de perdre des informations en cours
de transmission car le signal pourrait se retrouver affaibli du côté du récepteur.
Lorsque l’on a utilisé le Moniteur Série de notre IDE, on a vu qu’il y avait la pos-
sibilité de changer une valeur de 19 200 bauds en 9 600 bauds par exemple, nous
y reviendrons dans les pages suivantes.

Figure 6.11 Le Moniteur Série

Cette valeur qui est la rapidité de modulation correspond à la quantité globale


de bits transmis par seconde, et elle s’exprime en bauds (symbole Bd). C’est en
fait la vitesse globale de notre transmission série. Si on parle d’une vitesse de
transmission de 19 200 bauds, cela veut dire que l’on aura transmis 19 200 bits
sur notre liaison série en une seconde. Par contre, si notre liaison série incorpore

160/ Chapitre 6 : Fonctions avancées


des bits de contrôle dans nos messages, ceux-ci seront à retirer de notre vitesse
de transmission de l’information que l’on voulait faire passer.
Par exemple, si on transmet nos octets sur une liaison série qui comporte deux
bits de contrôle, on aura alors à transmettre nos huit bits (de notre octet), auquel
notre système ajoute ses deux bits de contrôle. On aura donc à transmettre 8 + 2
= 10 bits pour un seul octet d’information. On voit alors que sur une seule seconde,
on aura transmis plus de bits au total que de bits appartenant à nos octets. D’où
la différence entre les bauds (Bd) et les bits par seconde (bit/s).
Il existe plusieurs types de liaison série, suivant l’électronique qui va servir
à transporter cette information sur nos fils, mais aussi suivant les protocoles
utilisés (protocole = façon de transmettre les informations). Dans les liaisons
séries simples à mettre en œuvre, on va trouver RS232 et RS485 notamment.
Par chance, notre Arduino comporte une liaison série de type RS232. Enfin
presque…
En principe, il faudrait relier cette sortie RS232 de notre µC ARMega à un port
RS232 de notre ordinateur afin qu’ils puissent dialoguer tous les deux. Par contre,
en regardant nos ordinateurs actuels de très près, et même de très très près, il
est difficile de trouver un port série RS232 (c’est un connecteur de type SubD
9 points, qui ressemble un peu au connecteur VGA).
Ces ports série ont disparu de nos ordinateurs depuis quelques années main-
tenant… Dommage, ils étaient assez simples à utiliser.
Comment faire à présent ? Et bien les concepteurs d’Arduino ont tout simple-
ment intercalé un circuit spécialisé entre le port RS232 de l’ATMega et le monde
extérieur. Et on va retrouver cette interface sur le connecteur USB de notre carte !
Si on revient au tout début de ce livre, lorsque l’on a aperçu le schéma de la
carte Arduino pour la première fois, il y avait une partie sur la gauche avec un
second µC, un ATMega16U2. Eh bien, c’est lui qui se charge de cet interfaçage.
Grâce à cela, le port RS232 est vu comme un port USB par notre ordinateur.
C’est par là que nos sketchs sont téléversés dans notre Arduino, et c’est par là que
nous pouvons utiliser le Moniteur Série (on parle aussi de Console série). C’est
super malin ! On peut également utiliser deux pins de notre Arduino qui sont Tx
pour la transmission et Rx pour la réception.
Voyons comment se passe la transmission d’un octet sur cette liaison série.
Disons que nous voulions transmettre la valeur 168, donc 0xA8 en hexadécimal,
et donc 0b10101000 en binaire.
Si on représente notre octet de façon graphique avec ses valeurs High et Low,
on aura alors :

Figure 6.12 Notre octet 0xA8 en binaire

La liaison série /161


On voit bien ici que pour transmettre cette information à un autre circuit, il
nous faudrait huit fils, avec un fil par bit. Dans ce cas, on aurait une liaison dite
parallèle. La liaison parallèle demande donc plus de fils de communication, mais
elle a l’avantage d’être plus simple à gérer et permet de passer toute l’information
en une seule fois.
Avec la liaison série, il faudra sérialiser notre information afin de sortir les bits
de notre octet un par un sur le même fil, il s’agira de la trame. Par contre, un seul
fil suffit pour transmettre notre octet…
Pour les sortir un par un (les sérialiser), on a le choix de commencer à trans-
mettre b7 ou alors b0. Si on commence à transmettre b0 puis b1 puis b2 et les
autres ensuite, on a une configuration little-endian.
À l’opposé, si on commence par transmettre l’octet de poids fort b7 puis b6 puis
b5 et les autres ensuite, on aura une configuration big-endian.
Pour désigner ces deux termes, on parle alors d’endianness. L’endianness
dépend souvent de la configuration matérielle de notre système, et on le laissera
gérer ça tout seul. Dans notre cas, l’ATMega de notre Arduino a une configuration
little-endian, il commencera donc par envoyer b0 sur la liaison série.
La partie de ses circuits internes qui gère cette communication est son USART
(Universal Synchronous Asynchronous Receiver Transmitter : transmetteur/
récepteur universel synchrone/asynchrone en français…). C’est un peu difficile
à placer dans une conversation, mais pas de panique sur ce terme, il s’agit pour
nous d’un USART et c’est tout. Arduino se chargera du reste.

// FORMAT
Dans notre transmission série, il va donc y avoir un émetteur (notre Arduino
par exemple), et un récepteur (notre ordinateur avec l’IDE et son Moniteur Série).

Figure 6.13 Émission/Réception série

Du côté récepteur, les bits reçus sont poussés les uns après les autres en
mémoire afin de reconstituer notre octet. C’est plutôt bien fait…
De cette façon, on peut donc faire passer nos 8 bits les uns après les autres,
mais on pourrait en transmettre 16 ou 64 ou plus, toujours avec notre fil unique.
Si on reprend la datasheet de notre ATMega328P, on aura les informations
suivantes sur la trame transmise (frame en anglais).

162/ Chapitre 6 : Fonctions avancées


Figure 6.14 Frame format ATMega328P (doc. Microchip)

On retrouve bien notre schéma précédent, avec les bits à transmettre, chacun
d’eux ayant ici un petit nom particulier (notés en anglais sous la trame).
Idle : représente l’état de repos du fil de transmission qui pourrait être High ou
Low. Dans une transmission série comme celle-ci, l’état de repos correspond à High.
St : il s’agit du bit de Start, qui passe à l’état Low pour signaler que la transmis-
sion commence. C’est le coup de sifflet du chef de gare.
0 à 8 : voici les bits d’information à transmettre, de b0 à b8 (ce qui fait 9 bits
au total). Si on veut transmettre seulement 8 bits (de b0 à b7), on l’indiquera à
notre ATMega lors de la configuration de son USART. Si on veut en transmettre
davantage, il suffira de les envoyer les uns après les autres dans d’autres octets
en suivant, c’est simple.
P : il s’agit de l’un de ses fameux bits de contrôle dont nous avions parlé un peu
plus tôt. Celui-là est le bit de Parité. Lorsqu’il transmet, l’USART calcule tout seul
la valeur High ou Low de ce bit, en fonction du nombre de bits à High ou Low qu’il
y a dans notre octet b0-b8 à transmettre. On ne va pas s’y attarder, cette infor-
mation intéressera surtout l’USART qu’il y a du côté du récepteur, car il contrôlera
alors la valeur de ce bit comme l’a fait l’émetteur. Si un bit s’est perdu en cour de
route à cause de parasites par exemple, il pourra alors le détecter.
Pour l’instant, ce ne sont que des histoires d’USARTs…
SP : Stop Bit. À la fin de la transmission, on peut demander à l’USART de rajou-
ter un ou deux bits supplémentaires pour indiquer que la transmission est termi-
née. De cette façon, le récepteur saura que c’est la fin du message.
Lorsque tout est transmis, la ligne série repasse à l’état idle en attendant la
prochaine frame à transmettre.

// VITESSE DE TRANSMISSION
Pour transmettre notre frame, l’USART du circuit émetteur et l’USART du cir-
cuit récepteur doivent dialoguer à la même vitesse pour se comprendre. En effet,
quand on va transmettre notre frame de bits sur notre fil série, il faudra bien que
l’on ait une information sur la vitesse de cette transmission (nos fameux bauds…).

La liaison série /163


Sinon, il y en a un qui parle vite, et l’autre qui écoute doucement… ça ne fonc-
tionne pas.
En fait, cette vitesse est définie dans la trame elle-même, c’est-à-dire que
chaque bit va partir sur la liaison série un certain temps après celui qui vient juste
de partir. Ce certain temps est défini par nos 19 200 bauds par exemple, et il fau-
dra régler la même vitesse dans le logiciel de l’émetteur (donc dans notre Arduino)
mais aussi dans le logiciel du récepteur. Dans notre cas, ce sera le Moniteur Série
de notre IDE qui se trouve donc sur notre ordinateur.
Pour régler la vitesse de transmission dans le moniteur série, nous avons déjà
vu comment faire.
Pour la régler dans notre sketch Arduino, il va falloir regarder de quelles fonc-
tions on dispose dans la bibliothèque proposée par notre IDE.
Si on regarde de nouveau sur le site arduino.cc à la rubrique Serial, on va voir
qu’il y a plein de fonctions dédiées à la liaison série.
Pour commencer notre dialogue avec le Moniteur, il va donc falloir que l’on
initialise cette communication : on va le faire à l’aide de begin(). En regardant sa
syntaxe, on verra qu’elle peut être utilisée de deux façons :
Serial.begin(speed);
Serial.begin(speed, config);
Avant begin(), on voit qu’il y a le mot clé Serial. En fait, écrire Serial.begin()
indique que l’on va utiliser la fonction begin() relative à Serial. Nous verrons cela
dans quelques temps, pour l’instant contentons-nous de l’utiliser ainsi.
Pour ce qui est des deux façons de faire l’initialisation, la première possibilité
nous permet de n’indiquer que la vitesse de transmission par speed, alors que
la seconde permet de définir également une config qui pourra par exemple être
SERIAL_8N1. Dans ce cas, cela veut dire que la transmission se fera avec 8 bits de
donnée (8), sans bit de parité (N) et avec un bit de Stop (1).
En utilisant la syntaxe simple Serial.begin(speed), le format de la trame sera
de toutes façons par défaut avec 8 bits de donnée, sans bit de parité et avec un bit
de Stop. La seconde syntaxe sera davantage utilisée pour s’adapter à des récep-
teurs ayant un mode de fonctionnement plus spécifique.
Pour initialiser notre liaison série à 19 200 bauds, on va donc écrire simplement :
Serial.begin(19200);

// INITIALISATION
Nous avions déjà utilisé le Moniteur Série lors de notre sketch avec le poten-
tiomètre afin de lui envoyer les valeurs lues sur l’entrée analogique POTENTIO.
Dans le setup(), on avait initialisé notre liaison série à 19 200 bauds, puis nous
avions utilisé Serial.print() pour ressortir les résultats sur le moniteur série.
void setup() {
Serial.begin(19200);
Serial.print("Initialisation du setup terminée \n");
}

164/ Chapitre 6 : Fonctions avancées


L’utilisation du port Série est donc assez simple sur notre Arduino, et on
c­ omprend mieux à présent comment cette interface fonctionne. Lorsque l’on n’a
pas d’écran pour afficher des résultats, c’est un très bon moyen à utiliser pour le
déboggage. Pour écrire sur le moniteur, on utilisera print() et println().

// SYNTAXE DE PRINT() ET PRINTLN() POUR LE MONITEUR SÉRIE


La fonction Serial.print() est très puissante car elle va nous permettre de
transmettre tout un tas de données sans trop avoir de lignes de code à écrire.
Par exemple, elle nous permettra d’envoyer un nombre en décimal, en binaire
ou en hexa directement sur le moniteur de façon simple. Pour cela on utilisera
BIN, HEX ou DEC (ou rien du tout) comme second argument à la fonction.
On peut également utiliser println() au lieu de print(). La différence est que
le moniteur passera à la ligne suivante après avoir écrit la fin de sa phrase.
On peut faire la même chose en écrivant print(“\n“ ). C’est au choix, mais le
\n nous permet de sauter des lignes comme bon nous semble.
De la même façon, \t permettra de placer des tabulations afin de faire de belles
colonnes…
Essayons ceci pour voir :
void setup() {
Serial.begin(19200);
}
void loop() {
Serial.println(25,HEX); // écrira 19
Serial.println(25, BIN); // écrira 11001
Serial.println(25); // écrira 25
Serial.println(25+2); // écrira 27
Serial.println("25+2"); // écrira 25+2 (et ne fera pas le calcul…)
Serial.print("Essai de saut de lignes\n ");
Serial.print("\tEssai de saut de lignes\n");
}

Figure 6.15 Sortie sur le Moniteur Série

La liaison série /165


// SERIAL.PRINT() ET LES VARIABLES
Pour écrire une variable sur le moniteur série, ce sera à peu près la même
chose, il suffira de lui indiquer le nom de la variable dont on veut écrire le contenu
sur le moniteur.
Par exemple, on pourra écrire :
char maVariable[] = "Arduino c’est cool";
void setup() {
Serial.begin(19200);
}
void loop() {
Serial.println(maVariable);
}
Tout d’abord, nous avons ici déclaré une chaîne de caractères pour y stocker
notre phrase. En C, une phrase ou un mot n’est autre qu’un ensemble de carac-
tères, que l’on déclare ainsi :
char maVariable[] = "Arduino c’est cool";
Les deux crochets [ ] désignent un ensemble. Comme on ne lui donne pas de
taille, notre IDE se débrouillera tout seul en fonction de la longueur de la chaîne
de caractères qui suit cette déclaration.
Si on veut déclarer une chaîne de huit caractères pour l’utiliser plus tard, on
pourra faire :
char maFutureVariable[7];
On met 7, car les tableaux Arduino commencent à 0, donc on a bien
0.1.2.3.4.5.6.7, ce qui fait 8 éléments au total…
On pourra ensuite l’utiliser en la remplissant avec un maximum de huit carac-
tères. Par contre, on ne pourra pas faire ceci :
maFutureVariable = "Arduino"; // ERREUR DE COMPILATION
Il faudra passer par une fonction du langage C qui est strcpy(), et à qui on fait
passer notre variable, ainsi que la chaîne avec laquelle on veut la remplir :
strcpy(maFutureVariable, "Arduino");
Dans ce cas-là, notre compilateur va calculer la longueur de la chaîne et la
mettre correctement en mémoire.
On aura donc :
// (c)Frédéric SILLON 2020
// Variable chaine de caractères
char maFutureVariable[7];
void setup() {
Serial.begin(19200);
}

void loop() {
strcpy(maFutureVariable, "Arduino");
Serial.println(maFutureVariable);
}

166/ Chapitre 6 : Fonctions avancées


// RÉCEPTION SUR LE PORT SÉRIE
Qui dit parler dit écouter, donc qui dit émission dit réception…
Comme le Moniteur Série est sur notre ordinateur, il y a fort à parier que si on
tape quelque chose sur le clavier, on va le recevoir dans notre Arduino…
Si on reprend notre dernier montage avec la Led RGB, on pourrait par exemple
allumer le rouge en tapant R, le vert en tapant V et le bleu en tapant B sur le cla-
vier de l’ordi.
Allons-y, reprenons ce schéma (voir pages précédentes), ainsi que le sketch que
nous simplifions pour l’adapter à la lecture Serial.
Nous avons déjà vu que pour l’écriture sur le port série, on utilisait Serial.
print(), donc pour la lecture nous allons tout naturellement utiliser Serial.read().
// (c)Frédéric SILLON 2020
// LED RGB multicolore pilotée par ordi

#define RED 9 // Led RED sur la pin 9


#define GREEN 10 // Led GREEN sur la pin 10
#define BLUE 11 // Led BLUE sur la pin 11
#define PWM 255 // On met le même PWM pour toutes les Leds
char lectureSerie; // On declare une variable pour la lecture Serial
void setup() {
analogWrite(RED, 0); // On eteint Rouge
analogWrite(GREEN, 0); // On eteint Vert
analogWrite(BLUE, 0); // On eteint Bleu
Serial.begin(19200); // Init liaison serie 19200 Bds
}
void loop() {
lectureSerie = Serial.read(); // On lit la liaison Serial

if (lectureSerie == 'R') { // Si on a reçu R


analogWrite(RED, PWM); // Allumage Red
analogWrite(GREEN, 0); // Extinction Vert
analogWrite(BLUE, 0); // Extinction Blue
}
else if (lectureSerie == 'V') { // Si on a reçu V
analogWrite(RED, 0); // Extinction Red
analogWrite(GREEN, PWM); // Allumage Green
analogWrite(BLUE, 0); // Extinction Blue
}
else if (lectureSerie == 'B') { // Si on a reçu B
analogWrite(RED, 0); // Extinction Red
analogWrite(GREEN, 0); // Extinction Green
analogWrite(BLUE, PWM); // Allumage Blue
}
}
Et voilà ! Si on tape R ou V ou B sur la barre de saisie du Moniteur Série, la Led
correspondante va s’allumer. C’est plutôt pas mal, non ?

La liaison série /167


Figure 6.16 Saisie dans la barre de saisie du Moniteur Série

Si on reprend notre principe KISS, on voit que l’on répète un peu la même chose
pour chaque Led au niveau de son allumage et de l’extinction des autres. On pour-
rait écrire une fonction changeCouleur() par exemple, qui se chargerait de regar-
der quelles Leds éteindre et quelle Led allumer en fonction de la lettre reçue. Sa
déclaration pourrait être par exemple :
void changeCouleur(char laLettre);
Je vous laisse essayer de l’écrire de la façon la plus simple possible.
Pour savoir si elle fonctionne, il suffira de la compiler, de la téléverser et de voir
si tout fonctionne correctement.
En faisant ainsi, on n’a que les trois couleurs de base de notre Led, car on allume
une seule partie et on éteint les deux autres. L’intérêt de cette Led RGB étant de
pouvoir nous donner ses seize millions de couleurs, il faudra également essayer
de créer une fonction qui fasse par exemple du jaune ou du marron si on rentre
les lettre J ou M. Je vous laisse faire également…
Pour aller plus loin, on peut également écrire les couleurs en entier, comme
rouge ou vert…
Par contre, R est un caractère, alors que rouge est une chaîne de caractères.
En langage Arduino, une chaîne de caractères est un type String.
Il va donc falloir déclarer une variable String pour mémoriser la chaîne reçue
depuis le Moniteur Série, et ensuite demander à Serial de lire une String au lieu
d’un simple caractère.
La lecture de la String se fera par Serial.readString().
Notre sketch sera donc :
// (c)Frédéric SILLON 2020
// LED RGB multicolore pilotée par ordi
// Lecture des couleurs par mots

#define RED 9 // Led RED sur la pin 9


#define GREEN 10 // Led GREEN sur la pin 10
#define BLUE 11 // Led BLUE sur la pin 11
#define PWM 255 // On met le même PWM pour toutes les Leds
String lectureCouleur; // On declare une variable pour la lecture Serial

168/ Chapitre 6 : Fonctions avancées


void setup() {
analogWrite(RED, 0); // On eteint Rouge
analogWrite(GREEN, 0); // On eteint Vert
analogWrite(BLUE, 0); // On eteint Bleu
Serial.begin(19200); // Init liaison serie 19200 Bds
}

void loop() {
lectureCouleur = Serial.readString(); // On lit la liaison Serial

if (lectureCouleur == "rouge") { // Si on a reçu rouge


analogWrite(RED, PWM); // Allumage Red
analogWrite(GREEN, 0); // Extinction Vert
analogWrite(BLUE, 0); // Extinction Blue
}
else if (lectureCouleur == "vert") { // Si on a reçu vert
analogWrite(RED, 0); // Extinction Red
analogWrite(GREEN, PWM); // Allumage Green
analogWrite(BLUE, 0); // Extinction Blue
}
else if (lectureCouleur == "bleu") { // Si on a reçu bleu
analogWrite(RED, 0); // Extinction Red
analogWrite(GREEN, 0); // Extinction Green
analogWrite(BLUE, PWM); // Allumage Blue
}
}
C’est tout de suite plus sympa, et on pourra ainsi saisir tous les noms de cou-
leurs que l’on veut.
Pour aller encore plus loin, on pourrait même écrire un jeu de questions-­
réponses. Au lieu d’écrire le nom d’une couleur, on donnerait la réponse à une
question posée par l’Arduino.
Si la réponse que l’on donne est juste, Arduino allumerait la Led verte ; et si la
réponse est fausse, il allumerait la Led rouge.
Ici, la question est posée dans le setup(), mais on pourrait poser plusieurs ques-
tions dans le loop() après chaque réponse donnée.
// (c)Frédéric SILLON 2020
// LED RGB multicolore pilotée par ordi
// Question Reponse
#define RED 9 // Led RED sur la pin 9
#define GREEN 10 // Led GREEN sur la pin 10
#define BLUE 11 // Led BLUE sur la pin 11
#define PWM 255 // On met le même PWM pour toutes les Leds

String lectureReponse; // On declare une variable pour lecture Serial


String questionPosee; // On declare une String pour poser la question

La liaison série /169


void setup() {
analogWrite(RED, 0); // On eteint Rouge
analogWrite(GREEN, 0); // On eteint Vert
analogWrite(BLUE, 0); // On eteint Bleu
Serial.begin(19200); // Init liaison serie 19200 Bds
questionPosee = "Aimes-tu Arduino ?";
Serial.println(questionPosee);
}

void loop() {
if (Serial.available() > 0) {
lectureReponse = Serial.readString(); // On lit la liaison Serial
if (lectureReponse == "oui") { // Si on a reçu oui
analogWrite(RED, 0); // Extinction Red
analogWrite(GREEN, PWM); // Allumage Green
analogWrite(BLUE, 0); // Extinction Blue
}
else { // Sinon,
analogWrite(RED, PWM); // Allumage Red
analogWrite(GREEN, 0); // Extinction Vert
analogWrite(BLUE, 0); // Extinction Blue
}
}
}
On voit ici une nouvelle fonction qui est Serial.available(). Elle va nous indi-
quer combien de caractères sont reçus par l’Arduino depuis sa liaison série. Dans
notre cas, on veut effectuer les tests dès qu’au moins un caractère est reçu, donc
on teste le résultat renvoyé par Serial.available() et on regarde s’il est simple-
ment supérieur à zéro.
Je vous laisse améliorer ces exemples : on dispose à présent d’une porte
ouverte sur le monde extérieur, avec un vrai dialogue utilisateur.

Remarque sur RS232


La liaison série RS232 de notre Arduino passe par son connecteur USB par
l’intermédiaire de l’adaptateur créé avec le second µC de la carte, l’ATMega16U2
qui se trouve sur la gauche du schéma du Uno.
Or, sur le connecteur du haut de notre carte, on voit deux pins qui sont Tx et
Rx. En fait, ce sont les vrais signaux RS232 de notre ATMega328, avant d’être
convertis en USB.
On pourrait donc utiliser Tx pour transmettre vers le Rx d’un autre Arduino Uno,
et Rx pour recevoir de la part de ce second Arduino Uno. Il suffit de relier le Tx de
l’un avec le Rx de l’autre, et inversement. Il faudra également relier le Gnd du pre-
mier au Gnd du second, et aussi leur +5V si la première carte alimente la seconde.
Par contre, ce ne sera pas valable avec d’autres types de carte car les signaux
RS232 sont normalisés en tensions +12V et –12V alors que notre Arduino ­utilise

170/ Chapitre 6 : Fonctions avancées


une liaison USART 0V et +5V pour créer cette liaison. Alors prudence avec
d’autres cartes que Arduino, bien lire les datasheet de chaque élément avant de
les connecter.
Essayons donc de connecter deux Arduino Uno avec Rx et Tx, en reprenant la
base de notre schéma RGB en PWM.
En rajoutant un bouton poussoir sur le premier UNO A qui est le Master, on
pourra allumer la Led RGB du second UNO B qui est le Slave…

Figure 6.17 Deux Arduino Uno en liaison série

Au niveau de l’implantation, cela donne ceci :

Figure 6.18 Implantation Série Uno A et Uno B

La liaison série /171


Comme on a deux Arduino, il nous faudra deux programmes.
>> Pour Uno_A qui est le maître (Master) : il va scruter le bouton poussoir, et
envoyer ROUGE s’il est cliqué, et VERT dans les autres cas.
>> Pour Uno_B qui est l’esclave (Slave) : il attend les instructions du Uno_A et
allume la Led RGB en rouge s’il reçoit le mot clé ROUGE, et l’éteint dans les
autres cas.
Voyons tout ça.
Pour le UNO_A :
// (c)Frédéric SILLON 2020
// LED RGB multicolore pilotée en liaison Série
// Liaison Serie avec deux Arduino UNO
// Logiciel de la carte UNO_A, Master
#define BOUTON A0 // Bouton sur A0
void setup() {
pinMode(BOUTON, INPUT); // A0 utilisee en digital Input
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(19200); // Init liaison serie 19200 Bds
}
void loop() {
if (digitalRead(BOUTON) == LOW) { // Bouton appuye ?
Serial.write("ROUGE"); // Oui car LOW, donc ROUGE
}
else {
Serial.write("VERT"); // Non car HIGH, donc VERT
}
}
Pour le UNO_B :
// (c)Frédéric SILLON 2020
// LED RGB multicolore pilotée en liaison série
// Liaison Serie avec deux Arduino UNO
// Logiciel de la carte UNO_B, Slave
#define RED 9 // Led RED sur la pin 9
#define GREEN 10 // Led GREEN sur la pin 10
#define BLUE 11 // Led BLUE sur la pin 11
#define PWM 255 // On met le même PWM pour toutes les Leds
String lectureReponse; // Declare variable pour lecture Serialr eponse

void setup() {
analogWrite(RED, 0); // On eteint Rouge
analogWrite(GREEN, 0); // On eteint Vert
analogWrite(BLUE, 0); // On eteint Bleu
Serial.begin(19200); // Init liaison serie 19200 Bds
}

void loop() {
if (Serial.available() > 0) {

172/ Chapitre 6 : Fonctions avancées


lectureReponse = Serial.readString(); // On lit la liaison Serial
if (lectureReponse == "ROUGE") { // Si on a reçu ROUGE
analogWrite(RED, PWM); // Allumage Red
analogWrite(GREEN, 0); // Extinction Green
analogWrite(BLUE, 0); // Extinction Blue
}
else { // Sinon,
analogWrite(RED, 0); // Extinction Rouge
analogWrite(GREEN, PWM); // Allumage Vert
analogWrite(BLUE, 0); // Extinction Blue
}
}
}
Et bien voilà, quand on appuie sur le bouton poussoir du Master, on allume la
Led du Slave !

// MODULE GPS EN LIAISON SÉRIE


Avec cette liaison série, on va pouvoir connecter plein de cartes, capteurs et
d’autres choses telles qu’un module GPS par exemple. On en trouve des modèles
bon marché sur Internet comme le TEL0094 chez dfrobot.com.
Par contre pour l’utiliser il va falloir lire et comprendre tout ou partie de la data-
sheet qui le compose (référence VK2828U7G5LF), et ensuite écrire les drivers
par nous-même (les morceaux de programme qui le feront marcher, fonction par
fonction).
Cela devrait demander pas mal d’heures de codage et de bons maux de crâne
car ses fonctions sont nombreuses.
Une autre solution serait de regarder si ce travail n’a pas déjà été fait, et s’il
n’existe pas d’exemple que l’on pourrait utiliser au début pour apprendre à s’en
servir.
De même, il existe peut-être des bibliothèques que l’on pourrait utiliser. Si ces
logiciels sont libres, on pourra les utiliser, tout en prenant soin de ne pas modifier
leurs entêtes afin de bien respecter le travail de leurs auteurs d’origine.
On peut rajouter un entête supplémentaire en tant que contributeur si on a
amélioré ou modifié ce code source, tout en indiquant bien le but de ces ajouts et
modifications avec un nouveau numéro de version et la date.
On ne s’attribue pas le travail des autres programmeurs, mais on contribue.
Grosse différence…
Donc, si on cherche TEL0094 sur Internet, il y a de fortes chances que l’on
trouve un bel exemple d’utilisation à décortiquer et des bibliothèques à utiliser.
C’est ce que nous avons fait au chapitre des Bibliothèques.
Lorsque nous avons installé la bibliothèque de ce module GPS (TinyGPS++),
des exemples ont également été installés automatiquement.
On va les retrouver dans le menu Fichiers/Exemples/TinyGPS++, et on remer-
ciera au passage leurs auteurs et leurs contributeurs.

La liaison série /173


Pour la connexion du module GPS à notre Arduino, il va falloir utiliser le port série,
mais comme on voudrait aussi l’utiliser pour le MoniteurSérie, cela va poser un pro-
blème, car on ne peut relier que deux éléments sur un port RS232, pas davantage.
Pour y remédier, l’exemple fourni avec TinyGPS++ propose d’utiliser un port
série « virtuel », fait avec d’autres pins de notre Arduino. Pas bête, comme ça, on
pourra utiliser les deux à la fois. L’idée du port virtuel (ou SoftSerial) est d’utiliser
une entrée et une sortie digitales standard, et les faire agir comme un vrai port
série par logiciel.
Si on charge le programme de démonstration que l’on va trouver dans Fichier/
Exemples/TinyGPS++/DeviceExample, on va pouvoir avoir des informations
importantes en plus du code source du sketch.

Figure 6.19 Chargement de l’exemple de TinyGPS++

Regardons simplement le début cet exemple de plus près, et apprenons-en


davantage :
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
/* This sample sketch demonstrates the normal use of a TinyGPS++ (TinyGPSPlus)↵
object.
It requires the use of SoftwareSerial, and assumes that you have a
4800-baud serial GPS device hooked up on pins 4(rx) and 3(tx).
*/
static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 4800;
// The TinyGPS++ object
TinyGPSPlus gps;

// The serial connection to the GPS device


SoftwareSerial ss(RXPin, TXPin);
void setup()
{

}
void loop()
{

}

174/ Chapitre 6 : Fonctions avancées


Ici, nous laisserons volontairement de côté le code du setup() et du loop().
On remarquera principalement que dans le setup(), la liaison série standard
est initialisée à 115 200 bauds, et que la liaison série logicielle (SoftSerial) est
initialisée à 4 800 bauds en reprenant la valeur de la constante GPSBaud.
Dans le loop(), les données fournies par le module GPS sont alors affichées
avec gps.location.lat() pour la latitude ou gps.date.day() pour la date.
Par contre, comment connecter notre module GPS à l’Arduino ?
Et bien si on regarde l’entête de ce sketch d’un peu plus près, on verra que le
SoftSerial est défini avec Rx sur la pin 4 et Tx sur la pin 3.
Comme nous l’avions vu précédemment, il suffit alors de connecter le Rx de
l’émetteur sur le Tx du récepteur, et vice versa.

Figure 6.20 Connexion du GPS sur l’Arduino

Sur mon module GPS, les connexions sont celles-ci.

Figure 6.21 Connexions du GPS (doc. V.KEL)

Une fois ces connexions effectuées, il suffit de compiler et téléverser le sketch


dans notre Arduino.
Après quelques trente secondes d’initialisation du module, la Led verte du
module GPS va clignoter.

La liaison série /175


Si on ouvre le Moniteur Série, on va voir défiler plusieurs informations, par exemple :
Location: 48.862725, 2.287592 Date/Time: 9/19/2020 21:37:41.00
Il s’agit là de la latitude, de la longitude de l’endroit sur Terre où se trouve le
GPS, ainsi que la date et l’heure où il se trouve. Pour l’heure, il faudra tenir compte
des fuseaux horaires ainsi que de l’heure été/hiver.
Si on récupère ces coordonnées et qu’on les rentre sur un site de localisation
que l’on peut trouver sur Internet tel que www.mapsdirections.info ou autre, on
verra sur la mappemonde où se trouve notre Arduino…
C’est plutôt cool, et ça ouvre plein de nouveaux terrains de jeu. Par exemple,
on pourrait en profiter pour alimenter notre Arduino avec un batterie USB comme
celles servant à recharger les smartphones, et aller se balader. Si notre sketch
enregistre notre position toutes les dix secondes par exemple, on pourrait refaire
le tracé du chemin en rentrant. En le montant sur un petit robot, on pourrait étu-
dier son parcours, ou bien créer un programme pour lui dire de se positionner à
une latitude/longitude données.
Cela ouvre énormément de perspectives, et on a pu faire cet essai en très peu
de temps en utilisant la librairie qu’un nature programmeur a mis à notre disposi-
tion. Reste ensuite à l’améliorer et l’adapter à notre besoin.
Si on utilise ses bibliothèques, c’est plutôt sympa de remercier son auteur en
lui envoyant un petit mot.
Pour établir une liaison Bluetooth entre Gemini que nous verrons plus tard et
un smartphone, j’ai pu ainsi utiliser et adapter un bout de programme qui avait été
réalisé par un étudiant du MIT aux États-Unis.
Son application de base était d’allumer des Leds multicolores dans sa chambre
avec son téléphone, donc rien à voir avec mon projet, mais il était super content
que son programme ait pu servir à quelqu’un, et qu’il ait aussi servi de base pour
faire autre chose de totalement différent.

LES LIAISONS I2C ET SPI


Dans le petit monde merveilleux des liaisons série, notre Arduino possède aussi
une liaison I2C et une liaison SPI.

// LE BUS I2C
La liaison I2C (ou bus I2C ou I²C) a été développée par la société Philips dans
les années 80 pour établir des communications entre circuits intégrés sur une
même carte. Au lieu de tirer plein de pistes de cuivre sur un circuit imprimé pour
faire dialoguer des circuits intégrés, ils ont eu l’idée de créer un bus spécifique,
le Inter Integrated Circuits (d’où I2C). On peut ainsi enchaîner les circuits I2C les
uns derrière les autres, avec un minimum de fils de connexion.
Pour transmettre les informations d’un circuit à l’autre, le bus I2C dispose d’un
fil nommé SDA (Serial Data) et d’un fil SCL (Serial Clock). À cela, on ajoute la
masse Gnd, et le tour est joué.

176/ Chapitre 6 : Fonctions avancées


Figure 6.22 Connexion sur I2C Arduino

Dans ce système de bus, il y a un maître et des circuits esclaves tous connectés


ensemble. Chacun reçoit le signal d’horloge SCL qui va rythmer les échanges,
ainsi que les données par la ligne SDA.
Pour que chacun puisse s’y reconnaître, le bus I2C définit un système
d’adresses, et le maître va par exemple parler à tout le monde, tout en indiquant
dans son message à qui il veut s’adresser en particulier. Celui à qui s’adresse ce
message va le prendre en compte et répondre.

Figure 6.23 Le bus I2C

Pour faciliter les choses, notre IDE met la bibliothèque Wire à notre disposition afin
de gérer tous ces échanges. Regardons sur un exemple comment cela fonctionne.

Exemple I2C
Une carte qui est sympa à tester en I2C est par exemple le capteur de mouve-
ments 3D de chez dfrobot.com, que l’on peut trouver chez gotronic.fr ou mouser.fr
pour moins de 20 €. Le capteur détecte nos mouvements juste en passant au-
dessus de ses électrodes, sans contact. On peut par exemple créer un code secret
avec un geste au-dessus du capteur…

Figure 6.24 Carte capteur de mouvement 3D (image dfrobot.com)

Les liaisons I2C et SPI /177


En allant sur le site de dfrobot.com, on va retrouver le lien de téléchargement
de la librairie Arduino pour ce capteur. Une fois ce répertoire téléchargé, on y
trouvera le code source de la bibliothèque, ainsi que le schéma de branchement
du capteur sur un module compatible Arduino.
On va donc zipper ce répertoire, et l’importer dans nos bibliothèques comme
nous l’avons déjà fait pour le GPS.
Une fois importée, on la retrouvera dans notre liste des bibliothèques disponibles.

Figure 6.25 La bibliothèque du capteur 3D importée

Dans le menu Fichier/Exemples, nous allons donc à présent trouver un exemple


d’utilisation de ce capteur 3D.

Figure 6.26 Exemple capteur 3D

Il faudra alors compiler, téléverser ce sketch et aussi ouvrir le moniteur série.


Lorsque tout est en route, il suffira de survoler le capteur avec la main et par
exemple de commencer le mouvement en Right et de le finir en Left pour que le
moniteur série nous indique alors « Left ».
Nous n’irons pas plus loin dans ce programme, mais on pourrait le compléter
pour faire par exemple un jeu codé, qui allume une Led lorsque le joueur a fait le
mouvement programmé au-dessus du capteur, ou encore pour désactiver une
alarme avec un mouvement secret au-dessus de ce même capteur. Bref, pas mal
de projets en perspective…
Toutefois, il faudra un certain entraînement pour que nos gestes soient correc-
tement reconnus, mais ça fonctionne plutôt bien.

Comment ça marche ?
Pour en savoir davantage, on peut aller faire un tour sur le site arduino.cc, à la
page des librairies : www.arduino.cc/reference/en/libraries/. On verra alors un
lien vers la librairie Wire qui se charge de la gestion du bus I2C, et qui pourra nous
donner plus d’informations.

178/ Chapitre 6 : Fonctions avancées


Dans l’exemple livré avec le capteur 3D, on voit que les premières lignes de
code sont :
#include <DFRobot_Gesture.h>
#include <Wire.h>
En plus d’utiliser la bibliothèque spécifique au capteur 3D, le créateur de ce
programme a donc utilisé la bibliothèque Wire pour la gestion de l’I2C.

Écriture I2C
Pour écrire sur un périphérique I2C, on procèdera ainsi :
#include <Wire.h>
void setup()
{
Wire.begin(); // Initialisation du Bus I2C
}

void loop()
{
Wire.beginTransmission(0x25); // On adresse le circuit d’adresse 0x25
Wire.write(123); // On lui envoie la valeur 123
Wire.endTransmission(); // On libère le bus
}

Lecture I2C
Pour effectuer la lecture sur un circuit I2C, le site arduino.cc nous donne la
solution, avec un exemple d’utilisation de la fonction Wire.read().
Voici cet exemple.
#include <Wire.h>
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial for output
}

void loop()
{
Wire.requestFrom(2, 6); // request 6 bytes from slave device #2
while(Wire.available()) // slave may send less than requested
{
char c = Wire.read(); // receive a byte as character
Serial.print(c); // print the character
}
delay(500);
}
Les commentaires, bien qu’en anglais, sont très bien écrits, et donc facilement
compréhensibles.

Les liaisons I2C et SPI /179


Tout d’abord, le setup() initialise la liaison I2C par Wire.begin(), puis initialise
la liaison avec le Moniteur Série à 9 600 bauds.
Ensuite, la loop() demande à Wire de lire 6 octets du Slave d’adresse I2C 0x02.
Wire.requestFrom(2, 6);
Ensuite, tant qu’il y a des caractères à lire la boucle while() va permettre de
lire ces caractères les uns après les autres et de les envoyer sur le Moniteur Série.
while(Wire.available())
{
char c = Wire.read();
Serial.print(c);
}
La méthode est simple et efficace.
Par contre, comment connaît-on l’adresse du circuit I2C concerné ?

Adresse I2C
Comme nous l’avons dit, chaque circuit I2C est défini par une adresse sur ce bus.
Pour les composants ou les modules que l’on peut trouver avec leurs biblio-
thèques, on n’aura pas à s’en occuper la plupart du temps car leur auteur aura
pris soin de gérer cette partie.
Par contre, si c’est un composant sans bibliothèque, il faudra la gérer nous-mêmes.
Pour la trouver et la calculer, il suffira une fois de plus de trouver la datasheet
du composant.

Capteur de couleur I2C


Un autre capteur très sympa à utiliser est le module TCS34725 de chez Adafruit
Industries.

Figure 6.27 Module capteur de couleur


(avec l’aimable autorisation de Adafruit Industries, NYC)

Sur le site d’Adafruit, adafruit.com, on va trouver une multitude de kits et de


sketchs pour apprendre à utiliser des capteurs et autres composants un peu exo-
tiques et souvent très funs.

180/ Chapitre 6 : Fonctions avancées


En recherchant le TCS34725 sur leur site, on va trouver sa datasheet, sa biblio-
thèque, ainsi que des exemples de programme et de câblage.
Le but de ce capteur est de reconnaître la couleur à laquelle il est soumis. Si on
passe quelque chose de bleu devant lui, il le reconnaîtra, de même pour le rouge,
le vert et les autres nuances.
Dans les chapitres précédents, on a étudié la Led RGB en PWM, et maintenant
nous avons un capteur de couleurs…
Si on pouvait allumer la Led de la même couleur que ce que lit le capteur, ce
serait trop fort !
Il va d’abord falloir regarder le brochage de ce capteur afin de le brancher sur
notre Arduino. Sa documentation chez Adafruit nous l’indique, ce qui correspond
bien au tableau que nous avons vu précédemment.

Figure 6.28 Brochage du capteur

On peut donc le câbler ainsi, et garder le montage que nous avion déjà pour la
Led RGB.
Si vous l’aviez décâblé, profitez-en pour mettre des résistances de 470 ohms si
ce n’est pas déjà fait, ce sera plus doux pour les yeux…

Figure 6.29 Schéma Led RGB et capteur de couleur

Les liaisons I2C et SPI /181


Sur la platine, cela donnera le montage suivant.

Figure 6.30 Implantation Led RGB et capteur de couleur

Au niveau du code, il va donc falloir reprendre notre sketch de la LED RGB, et


rajouter l’initialisation du capteur ainsi que la lecture des couleurs.
Ensuite, on pourra regarder quelle est la composante dominante de la couleur
lue, et allumer la Led RGB avec cette même couleur.
Allons-y !
// (c)Frédéric SILLON 2020
// Signal PWM avec LED RGB multicolore
// Detection de couleur avec Adafruit TCS34725

#include <Wire.h>
#include "Adafruit_TCS34725.h"
#define RED 9 // Led RED sur la pin 9
#define GREEN 10 // Led GREEN sur la pin 10
#define BLUE 11 // Led BLUE sur la pin 11
Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS,↵
TCS34725_GAIN_4X); // Déclaration variable Capteur de couleur
float red, green, blue; // Couleurs à capturer et reproduire

182/ Chapitre 6 : Fonctions avancées


void setup() {
red = green = blue = 0;
analogWrite(RED, 0); // Extinction de la Led RGB
analogWrite(GREEN, 0);
analogWrite(BLUE, 0);
tcs.begin(); // Init du capteur de couleurs
}

void loop() {
tcs.getRGB(&red, &green, &blue); // Lecture de la couleur
if ((red>blue) && (blue>green)) { // dominante Red, on allume RED
analogWrite(RED, red);
analogWrite(BLUE, 0);
analogWrite(GREEN, 0);
}
if ((blue>red) && (red>green)) { // dominante Blue, on allume BLUE
analogWrite(BLUE, blue);
analogWrite(RED, 0);
analogWrite(GREEN, 0);
}
if ((green>blue) && (blue>red)) { // dominante Green, on allume GREEN
analogWrite(GREEN, green);
analogWrite(BLUE, 0);
analogWrite(RED, 0);
}
}
Au début de ce sketch, il y a une ligne un peu nouvelle dans sa construction et
qui mérite un peu d’attention.
Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS,↵
TCS34725_GAIN_4X); // Déclaration variable Capteur de couleur
En fait, il s’agit de déclarer une variable nommée tcs de type Adafruit_
TCS34725, et de l’initialiser en même temps comme le demande la librairie du
capteur écrite par son auteur.
Si on avait eu plusieurs capteurs de couleur sur la carte par exemple, on aurait pu
déclarer plusieurs variables de type Adafruit_TCS34725, comme tcs_1, tcs_2, tcs_3.
Dans ce cas, chaque capteur associé à sa propre variable saurait être géré par
la bibliothèque. C’est une partie très puissante de notre langage de programma-
tion que nous aborderons plus tard.
Dans le setup(), on éteint la Led RGB et on lance la communication I2C avec le
capteur par tcs.begin().
Dans le loop(), il ne reste plus qu’à interroger le capteur avec tcs.getRGB()
et récupérer les couleurs pour rechercher la dominante afin d’allumer la bonne
couleur de Led.
Il y a une particularité dans l’appel à la fonction tcs.getRGB(). En effet, on
passe l’adresse des variables par &nomVariable afin que la fonction y range les
bonnes valeurs.

Les liaisons I2C et SPI /183


Pour rappel, si on avait par exemple écrit :
laVariable = 10;
maFonction(laVariable);
on aurait alors juste envoyé la valeur 10 dans la fonction.
Si maintenant on écrit :
laVariable = 10;
maFonction(&laVariable);
Au retour, laVariable ne vaudra pas 10, mais aura pris la valeur que la fonction
lui a donné pendant ses calculs. C’est ainsi que l’on peut récupérer les valeurs des
trois couleurs avec l’appel d’une seule fonction.
À présent, il reste à compiler ce sketch et à le téléverser dans notre Arduino
pour voir ce qu’il se passe. En passant des objets très colorés Rouge, Vert et
Bleu devant le capteur, la Led prendra automatiquement la même couleur. C’est
magique !
Pour ma part, j’ai pris de petits jetons en plastique fortement colorés, mais
on peu utiliser n’importe quoi : une orange, un concombre pour le vert et une
jolie pomme pour le rouge par exemple. Certains matériaux absorbent ou réflé-
chissent différemment la lumière, à vous de trouver les bons éléments pour ces
expériences.

Figure 6.31 Le capteur de couleur en action

Maintenant, si on combinait ce que l’on a appris avec le capteur de couleurs, la


Led RGB et le module GPS sur un petit robot mobile, il pourrait suivre une ligne
en couleur, changer de couleur suivant le lieu où il se trouve comme un caméléon,
localiser des couleurs et plein d’autres choses encore.

184/ Chapitre 6 : Fonctions avancées


// BUS SPI
Le bus SPI est donc aussi un bus de communication série qui va quant à lui
transmettre l’information du maitre vers l’esclave par un fil nommé MOSI (Master
Output, Slave Input), puis de l’esclave vers le maître par un autre fil nommé MISO
(Master Input, Slave Output). On retrouve un peu le même genre de configuration
que sur l’USART ou RS232 pour la transmission et la réception.
La grosse différence est que ces deux entrées/sorties ont des niveaux de tension
de 0/5V ou 0/3,3V suivant le cas, alors que la RS232 normalisée atteint – 12V/+ 12V.
Pour la liaison RS232, nous avions vu que l’émetteur et le récepteur comptent
eux-mêmes le temps d’attente entre chaque nouveau bit émis/reçu, car ils ont
tous deux la même vitesse de transmission en bauds. C’est le générateur de bauds
intégré à notre ATMega et celui de l’autre circuit connecté qui donnent la cadence.
Pour le SPI, un autre fil a été ajouté, il s’agit de SCK qui transporte un signal
supplémentaire qui sert d’horloge. Émetteur et Récepteur peuvent alors regarder
cette horloge chacun de leur côté pour travailler ensemble et s’échanger les bits
à la bonne vitesse : c’est le maître qui gère ce signal.
Comme SPI est aussi un bus inter-circuits, ce serait intéressant de pouvoir en
brancher plusieurs à la queue leu leu. C’est possible, et un maître peut alors parler
à plusieurs esclaves. Pour se reconnaître lorsqu’ils sont tous ensemble, un autre
fil a été rajouté : il s’agit de SS. Il s’agit d’un signal que le maître va utiliser pour
sélectionner le circuit avec lequel il veut discuter (slave select). On va souvent le
brancher sur le Chip Select (CS) de l’esclave.
La bibliothèque qui nous permettra d’utiliser le bus SPI se déclarera par :
#include <SPI.h>
Pour un dialogue SPI, on va donc utiliser les fils suivants : MOSI, MISO, SCK, SS
qui se trouvent sur le connecteur supérieur de l’Arduino Uno, sur les pins 10–11–
12–13. On connectera également Gnd et Vcc.

Figure 6.32 Connecteur avec bus SPI sur D10–11–12–13

Comme exemple d’utilisation du bus SPI, nous allons regarder l’exemple qui
se trouve sur le site officiel Arduino, à l’adresse www.arduino.cc/en/Tutorial/
LibraryExamples/DigitalPotControl. Cela va nous permettre d’étudier un projet
développé par un autre programmeur.
Dans les chapitres précédents, nous avions utilisé un potentiomètre pour
nos expériences. Avec un petit tournevis, on pouvait changer la position de son

Les liaisons I2C et SPI /185


c­ urseur afin de faire varier sa résistance. Dans cet exemple DigitalPotControl du
site arduino.cc, un super composant est utilisé : il s’agit du potentiomètre numé-
rique AD5206 (on parle aussi d’XPot).
Plus besoin de tournevis pour le régler, on peut le faire par logiciel !
Sur la datasheet de cet exemple, on voit que le circuit utilisé comporte six
potentiomètres numériques, et que chacun est désigné par A, B et W.
A et B sont les deux extrémités d’un des six potentiomètres, et W est le curseur
(Wiper). Ainsi, en envoyant une valeur comprise entre 0 et 255 à chaque potentio-
mètre intégré par le bus SPI, le potentiomètre se règlera à sa valeur maximale ou
minimale. Toute valeur comprise entre 0 et 255 amènera le curseur à une position
intermédiaire, comme on le ferait avec notre tournevis sur un potentiomètre manuel.
Dans le schéma pris en exemple et suivant le réglage de chaque Wiper, la Led
associée s’allumera plus ou moins.
Comme on le voit sur le code de cet exemple, le setup() place la pin qui servira
de SlaveSelect (SS) en sortie, et initialise ensuite le bus SPI.
Auparavant, la bibliothèque a été déclarée avec un include.
#include <SPI.h>
void setup() {
pinMode(slaveSelectPin, OUTPUT);
SPI.begin();
}
On ne s’attardera pas sur le reste du code, mais simplement sur la façon de
dialoguer avec le potentiomètre en SPI.
Pour écrire la valeur 0-255 que l’on veut envoyer sur un des six potentiomètres
intégrés, la fonction digitalPotWrite() est utilisée avec le numéro du potentio-
mètre channel et donc la valeur level.
digitalPotWrite(channel, level);
La fonction digitalPotWrite() est quant à elle construite ainsi.
void digitalPotWrite(int address, int value) {
digitalWrite(slaveSelectPin, LOW);
delay(100);
SPI.transfer(address);
SPI.transfer(value);
delay(100);
digitalWrite(slaveSelectPin, HIGH);
}
Pour adresser le circuit intégré lui-même, on a vu que le master utilisait le
signal SS vers son slave. SS est donc ici relié à la pin CS (Chip Select) du AD5206.
En réalité, il s’agit de CS\ et non pas de CS.
Quelle est la différence ?
Et bien quand on parle d’un SIGNAL\, cela veut dire qu’il est actif sur un état
LOW. Quand on parle d’un SIGNAL, cela veut dire qu’il est actif sur un état HIGH.
Comme l’indique la datasheet du AD5206, on a affaire à CS\ pour sélectionner
le circuit. Il faudra donc appliquer un état LOW sur cette pin pour la valider.

186/ Chapitre 6 : Fonctions avancées


Reprenons… Donc, tout d’abord l’XPot est adressé en passant la ligne SS du
master à LOW, puis attente de 100 ms qui permet au wiper de se stabiliser.
digitalWrite(slaveSelectPin, LOW);
delay(100);
Ensuite, l’adresse du circuit auquel on s’adresse est placée sur le bus, puis la
valeur à écrire, suivi d’une attente de 100 ms.
SPI.transfer(address);
SPI.transfer(value);
delay(100);
À la fin de l’échange, la ligne SS est remise à High afin de dé­selecter le slave
car la discussion est terminée avec lui.
En résumé, voici le timing de l’échange, vu du AD5206.

Figure 6.33 Timing SPI AD5206 (doc. Analog Device)

Vu du côté de l’XPot, notre MOSI est connecté à son SDI (MasterOutput de


l’Arduino vers SlaveDataInput de l’XPot), et il doit donc recevoir ses trois bits
d’adresse (A2-A1-A0), et ses huit bits de donnée (D7 à D0). Pour valider cet
échange, son CS\ doit être à Low pendant la communication, puis revenir à High
ensuite (il s’agit donc notre SS car son CS\ est connecté à notre SS…).
Un petit coup d’œil au schéma de l’exemple et tout ira mieux…
On voit ici que l’échange en SPI est simple, car la bibliothèque SPI.h se charge
de tout pour nous. Merci à son ou à ses auteurs !
Du côté du maître, on aura donc MOSI, MOSI, SS et SCK et du côté esclave on
pourra avoir un CS\ par exemple, puis un SDI ou un SI (données depuis le maître),
ensuite un SDO ou un SO (données vers le maître) et enfin un SCK ou un CLK par
exemple (horloge venant du maître).
Dans tous les cas, tout sera expliqué sur la datasheet du composant que l’on
veut utiliser, et on voit sur cet exemple que cela peut être rendu très simple.
Comment connaître l’adresse du potentiomètre avec lequel on veut dialoguer
en SPI, ou encore l’adresse de tout autre circuit SPI ?
Et bien une fois de plus, il faut regarder… la datasheet !
Sur cet exemple du site arduino.cc, on en voit un extrait avec le pinout du circuit.

Les liaisons I2C et SPI /187


Figure 6.34 Extrait datasheet du AD5206 (doc arduino.cc)

On voit ici qu’il est question des deux extrémités du potentiomètre numéro 6
(A et B), ainsi que de son curseur (W).
La ligne numéro 2 est intéressante car il est noté que addr = 1012.
On peut donc en déduire que l’adresse du wiper du potentiomètre numéro 6 se
trouve à l’adresse 101 en binaire (base 2, d’où le petit 2 noté en indice). Si on fait
une rapide conversion, 101 vaut 5 en décimal.
L’adresse du potentiomètre numéro 6 est donc 5 sur le bus SPI lorsque la
ligne CS du circuit est LOW. En continuant de lire cette datasheet, on verra que
le potentiomètre 5 est à l’adresse 4, le potentiomètre 4 à l’adresse 3, et ainsi de
suite jusqu’au potentiomètre 1 qui est à l’adresse 0.
Donc, pour écrire la valeur 123 sur le potentiomètre 6, il faudra écrire :
SPI.transfer(5);
SPI.transfer(123);
C’est assez simple d’utilisation, et le AD5206 est un super composant. De plus,
il est en plus possible de l’alimenter en 5V, ce qui correspond tout à fait à notre
Arduino. La seule chose à laquelle il faudra faire attention est son boîtier. En effet,
il devient plus difficile de le trouver en boîtier DIL (Dual In Line = gros boîtier
comme notre ATMega328 sur l’Arduino Uno).
La tendance étant à la miniaturisation, on le trouvera plus facile en boîtier CMS
(comme le second µC de notre Arduino Uno).
Dans ce cas, il sera très délicat de le câbler sans outillages spécialisés.

LES INTERRUPTIONS
Actuellement, toutes les instructions à exécuter en dehors du setup() se
trouvent dans le loop().
Dans ce loop(), toutes les tâches sont exécutées les unes après les autres,
ce qui fait que dans notre montage avec le bouton poussoir et le chenillard par
exemple, il y a un certain temps d’attente entre le moment où on appuie sur le
bouton et le moment où notre programme réagit. Est-ce que notre µC est trop
lent ? Non, pas du tout. Il exécute les instructions les unes après les autres, et il

188/ Chapitre 6 : Fonctions avancées


faudra donc attendre qu’il arrive sur les instructions qui traitent le bouton pous-
soir pour qu’il le prenne en compte.
Si on veut que tout ça réagisse plus vite, il faudrait pourvoir interpeller notre
µC et l’interrompre dans ce qu’il fait pour qu’il fasse autre chose. Ce moyen existe,
et il s’agit des Interruptions.
Le déroulement du programme sera le même, le loop() sera exécuté norma-
lement, et lorsque l’on appuie sur le bouton poussoir, il stoppera immédiatement
pour exécuter le bout de programme que l’on veut.
Quand ce petit bout de programme sera terminé, il reviendra à l’ancienne tâche
en cours, comme si de rien n’était.
Voyons cela sur un exemple.
// (c)Frédéric SILLON 2020
// Bouton poussoir Led sans interruption
#define BOUTON 2 // Bouton poussoir sur pin 2
int etatDuBouton = 0; // Sauvegarde de l'état du bouton (on/off)
void setup() {
pinMode(LED_BUILTIN, OUTPUT); // Initialise Led en sortie
pinMode(BOUTON, INPUT); // Bouton, donc Input
}

void loop() {
etatDuBouton = digitalRead(BOUTON); // Lit etat du bouton
if (etatDuBouton == true) // Si relache,
digitalWrite(LED_BUILTIN, LOW); // Led OFF
else // Sinon
digitalWrite(LED_BUILTIN, HIGH); // Led ON
delay(5000);
}
Si on exécute ce sketch, il faudra attendre la fin de la tempo de 5 secondes
avant que la Led ne change d’état.
Regardons maintenant ce qu’il se passe si on attache notre bouton poussoir au
système d’interruptions de notre µC (je vous laisse faire le câblage avec le bouton
sur la pin D2).
// (c)Frédéric SILLON 2020
// Bouton poussoir Led AVEC interruption
#define BOUTON 2 // Bouton poussoir sur pin 2
int etatDuBouton = 0; // Sauvegarde de l'état du bouton (on/off)
void setup() {
pinMode(LED_BUILTIN, OUTPUT); // Initialise Led en sortie
pinMode(BOUTON, INPUT); // Bouton, donc Input
attachInterrupt(digitalPinToInterrupt(BOUTON), changeLed, CHANGE);
}
void changeLed() {
etatDuBouton = digitalRead(BOUTON_POUSSOIR); // Lit etat du bouton
if (etatDuBouton == true) // Si relache,

Les interruptions /189


digitalWrite(LED_BUILTIN, LOW); // Led OFF
else // Sinon
digitalWrite(LED_BUILTIN, HIGH); // Led ON
}
void loop() {
delay(5000);
}
On voit que le loop() est simple, et qu’il n’exécute que la temporisation. Il
tourne en rond en attendant qu’il se passe quelque chose.
Tout se passe alors dans l’interruption qui relie le bouton à la fonction change
Led().
Avec cette méthode, malgré la temporisation, la Led change d’état dès que l’on
appui sur le bouton, sans aucun un temps d’attente. Le loop() est interrompu et
exécute le programme d’interruption.
Pour lier une interruption à une entrée, il faut utiliser attachInterrupt() dans
le setup() et indiquer quelle pin on lui relie avec digitalPinToInterrupt(), puis
quelle fonction sera exécutée (ici il s’agit de changeLed) et ensuite sur quel évé-
nement aura lieu l’interruption. Donc pour cet exemple, ce sera sur le changement
d’état du bouton par CHANGE.
On peut également choisir un événement comme le fait que l’entrée soit à l’état
bas, ou le passage de bas à haut ou le contraire :
>> LOW : lorsque la pin est figée à l’état bas
>> CHANGE : lorsque la pin passe d’un état à l’autre
>> RISING : lorsque la pin passe de l’état bas à l’état haut
>> FALLING : lorsque la pin passe de l’état haut à l’état bas
Avec un peu d’habitude, les interruptions sont un excellent moyen de ne pas
rater d’événements extérieurs.
Il faudra juste veiller à ce que la fonction appelée en interruption ne soit pas
trop longue.
/> CHAPITRE
ÉCRANS, MOTEURS,
CAPTEURS…
7

Nous allons maintenant pouvoir regarder des montages plus évolués, qui pour-
ront être le début de grandes aventures…

LE SERVOMOTEUR, POUR DONNER


DU MOUVEMENT À SES PROJETS
Si on voulait construire un robot mobile, on pourrait utiliser des petits moteurs
à courant continu, ou bien des servomoteurs. Les moteurs sont un peu plus
­complexes à utiliser que les servomoteurs du point de vue de l’électronique qui
les pilote, nous allons donc essayer de jouer avec un servo.
Un servomoteur (ou servo) est un petit moteur, mais qui incorpore un peu
d’électronique pour le piloter. On s’en sert surtout en modélisme, pour faire bou-
ger les gouvernes des avions par exemple, ou pour faire tourner une tourelle sur
un camion ou un char.
Celui que j’ai choisi est un FS90R de chez Feetech, mais on pourra prendre à
peu près celui que l’on veut pour faire des essais.

Figure 7.1 Exemple de servomoteur (doc. gotronic.fr)

Le Servomoteur, pour donner du mouvement à ses projets /191


Pour faire tourner un moteur à courant continu, il suffit de le brancher sur une
alimentation ou une pile, et il se met à tourner (à condition que l’alimentation soit
de 5V pour un moteur 5 volts par exemple, normal…).
Pour le faire tourner en sens inverse, il suffit d’inverser le branchement de
l’alimentation.
Pour un servo, c’est différent. Tout d’abord, il a trois fils au lieu de deux pour un
moteur à courant continu standard.
Deux fils sont l’alimentation et le Gnd. Le troisième fil est sa commande en
PWM (le fameux PWM…).
En fait, pour le faire tourner, il va falloir lui amener des impulsions précises sur
ce troisième fil, et avec cela il va savoir tourner dans un sens, dans l’autre ou bien
s’arrêter et garder sa position.
En général, un servo ne peut pas faire de tours complets, et a un angle de
rotation limité.
Le FS90R par contre est un modèle à rotation continue, ce qui veut dire qu’il est
capable de tourner sur 360°, et on peut donc lui visser une roue.

Figure 7.2 Servo avec roue (doc. pololu.com)

Le connecteur de mon servo a le brochage suivant.

Figure 7.3 Brochage servo

Au niveau du schéma, on pourra par exemple connecter la commande PWM sur


D9, qui est une sortie PWM de notre Arduino Uno.

192/ Chapitre 7 : Écrans, moteurs, capteurs…


Figure 7.4 Schéma du servo

Et donc au niveau du câblage, on aura :

Figure 7.5 implantation du servo

Maintenant que tout est câblé, il va falloir le faire tourner. Comme on l’a vu, la
commande d’un servo se fait en PWM.
Pour cela, on a deux solutions. La première est de créer par nous-même ces
signaux en PWM, en respectant les bons timings pour tourner dans un sens ou
dans un autre.

Le Servomoteur, pour donner du mouvement à ses projets /193


Figure 7.6 Timings du servo

On pourrait par exemple passer la commande à HIGH pendant 2 ms, puis à LOW
pendant 18 ms pour respecter les timings, ce qui pourrait donner :
digitalWrite(SERVO, HIGH);
delay(2);
digitalWrite(SERVO, LOW);
delay(18);
Ce n’est ni élégant, ni très pratique. On pourrait utiliser le PWM de notre
Arduino pour faire la même chose. Il pourrait même exister une bibliothèque toute
faite pour gérer les servos…
En tapant « arduino servo » sur Internet, on arrive facilement sur le site Arduino
qui nous propose la bibliothèque servo.h…
Si on regarde l’exemple Sweep, on va y voir plus clair, et on voit les différentes
étapes pour faire tourner le servo dans un sens et dans l’autre.
En commençant par quelque chose de très simple, on pourrait :
> déclarer la pin PWM sur laquelle est connecté le servo ;
> déclarer une variable monServo pour utiliser la bibliothèque ;
> initialiser monServo sur la pin où on est connecté ;
> écrire le sens de rotation (et la vitesse).

194/ Chapitre 7 : Écrans, moteurs, capteurs…


Sur un servo standard, 0 correspond à 0° (tout à gauche), 180 à 180° (tout
à droite) et 90 à 90° (au milieu). Les autres valeurs définissent donc les autres
angles.
Par contre, sur un servo comme le nôtre qui est à rotation continue, 90 cor-
respond à l’arrêt de la rotation, 0 correspond à une rotation continue à gauche et
180 correspond à une rotation continue à droite. Toutes les valeurs intermédiaires
comme 25 ou 138 donneront une rotation à gauche ou à droite, mais avec une
vitesse différente.
Essayons donc ceci :
// (c)Frédéric SILLON 2020
// Gestion du servomoteur

#include <Servo.h> // Utilisation bibliotheque Servo


Servo myServo; // Declaration variable myServo
void setup() {
myServo.attach(9); // Initialise le servo sur la pin 9
}

void loop() {
myServo.write(90); // Arrêt du servo
delay(500);
myServo.write(100); // Tourne dans un sens lentement
delay(500);
myServo.write(0); // Tourne dans l'autre sens vite
delay(500);
}
On voit bien le sens de rotation et la vitesse suivant les valeurs prises.
Le servo est un moyen très simple, assez bon marché et peu encombrant pour
motoriser un petit robot mobile. Le choix se fera ensuite sur un servo standard ou
un modèle à rotation continue suivant ce que l’on veut en faire.
Selon que nous lui mettons une roue ou autre chose, on pourra l’utiliser pour
se déplacer, pour faire tourner une tourelle avec un radar par exemple, ou encore
pour tirer ou baisser un levier, un pont-levis, une barrière, la porte d’une fusée,
bref il y a plein d’applications possibles.

LE BUZZER, POUR FAIRE DU BRUIT


Le buzzer est aussi un composant électronique sympa à utiliser. On en trouve
un peu partout, et sous diverses formes. Dans chaque objet qui fait bip-bip, il y a
fort à parier qu’il y en ait un.
Le buzzer est constitué d’une fine partie en céramique qui a la propriété de
se déformer lorsqu’on lui envoie un signal électrique : c’est sa propriété piézo-
électrique. En se déformant, il va produire un son. Certains buzzers ont à l’intérieur
de leur boîtier plastique un peu d’électronique pour générer ce signal électrique.
Dès qu’on les branche, ils bippent. Ils sont simples d’utilisation.

Le Buzzer, pour faire du bruit /195


Figure 7.7 Le buzzer

Le modèle choisi est un SV12-5 qui va émettre un son continu lorsqu’on l’ali-
mente, et en regardant sa datasheet, on verra que son alimentation doit être
­comprise entre 3V et 6V au maximum, ce qui correspond bien à notre Arduino
qui va générer des signaux de 5V et un son d’une fréquence de 3,2 KHz. Pour
ce modèle, on peut tout de même émettre différents sons en modulant le signal
qu’on lui envoie, et il va donc falloir générer ce signal avec une fréquence qui
correspond à la note que l’on veut jouer. Cela ne fonctionnera pas correctement
pour toutes les fréquences, mais suffisamment bien si on reste aux alentours des
3,2 KHz (3 200 hertz) qu’il est capable d’émettre seul.
Pour en revenir aux notes, le La correspond à un signal de fréquence 440 hertz
(Hz). C’est celui que l’on entend en décrochant un téléphone, et qui sert aussi à
accorder les instruments de musique.
Plus le son est aigu, plus sa fréquence est haute, et un DO grave aura une
fréquence de 261 hertz environ alors qu’un DO aigu aura une fréquence de
2 093 hertz.
En effet, chaque son correspond à une fréquence, que notre cerveau analyse
comme une note, agréable ou non. Les notes générées par le buzzer ne sont pas
très agréables, mais elles ont le mérite d’exister.
Si on voulait jouer Au clair de la lune, qui est un peu le Hello World de la musique,
on ferait la séquence de notes : do-do-do-ré-mi-ré-do-mi-ré-ré-do.
Dans les sons assez aigus proches des 3 200 Hz de notre buzzer, on trouvera
le DO à 2 093 Hz, le RÉ à 2 349 Hz et le MI à 2 637 Hz environ.
Pour jouer des notes, notre Arduino a bien évidemment la fonction qui va bien :
tone(). Pour jouer un LA 440 Hz sur un buzzer qui sera branché sur la sortie 8
par exemple, on écrirait :
tone(8, 440);
Pour stopper la musique, on fera aussi simplement :
noTone(8);
On peut aussi indiquer pendant combien de temps la note doit être jouée.
tone(8, 440, 500); //jouée pendant500 ms
On voit que c’est assez simple de créer des sons et de jouer des notes.
Essayons de brancher notre buzzer sur l’Arduino.

196/ Chapitre 7 : Écrans, moteurs, capteurs…


Figure 7.8 Branchement du buzzer

Avant de câbler le buzzer, on fera attention à sa polarité.


Le buzzer a un plus et un moins, qui sont marqués sur son boîtier. Le plus sera
très souvent repéré par un symbole + ou un point. Le plus sera donc branché sur
la sortie de l’Arduino alors que l’autre patte sera branchée à Gnd.

Figure 7.9 Implantation du buzzer

Le Buzzer, pour faire du bruit /197


Et donc si on veut faire trois bips au démarrage à la fréquence naturelle de
3,2 KHz de notre buzzer et ensuite jouer Au clair de la lune, il ne reste plus qu’à
coder.
// (c)Frédéric SILLON 2020
// Gestion du buzzer
const byte PIN_BUZZER = 8; // Le Buzzer est sur la pin 8
#define DO 2093 // Definition fréquence des notes
#define RE 2349
#define MI 2637
void troisBips(void) { // Function pour faire trois Bips
for (int i=0; i<3; i++) {
digitalWrite(PIN_BUZZER, HIGH); // Buzzer ON
delay(200); // Attente
digitalWrite(PIN_BUZZER, LOW); // Buzzer OFF
delay(200); // Attente
}
}

void setup() {
pinMode(PIN_BUZZER, OUTPUT); // Pin du buzzer en sortie
troisBips(); // Appel de TroisBips au demarrage
}

void loop() {
tone(PIN_BUZZER, DO, 200); // Note
delay(400); // Silence
tone(PIN_BUZZER, DO, 200); // Note
delay(400); // Silence
tone(PIN_BUZZER, DO, 200); // ...
delay(400);
tone(PIN_BUZZER, RE, 200);
delay(400);
tone(PIN_BUZZER, MI, 200);
delay(800);
tone(PIN_BUZZER, RE, 200);
delay(800);
tone(PIN_BUZZER, DO, 200);
delay(400);
tone(PIN_BUZZER, MI, 200);
delay(400);
tone(PIN_BUZZER, RE, 200);
delay(400);
tone(PIN_BUZZER, RE, 200);
delay(400);
tone(PIN_BUZZER, DO, 200);
delay(1500);
}

198/ Chapitre 7 : Écrans, moteurs, capteurs…


On a donc appris à se servir de notre super buzzer de deux façons différentes,
en le laissant bipper tout seul en activant simplement la sortie à laquelle il est
connecté ou en le modulant avec la fonction tone(). De quoi donner un peu de
vie à nos montages !
En revanche, on a beaucoup de lignes de code qui se répètent une fois de plus.
Comment faire pour simplifier un peu ?
On pourrait déjà faire une fonction comme :
joueNote(laNote, laDuree, leSilence);
Ainsi, on pourrait par exemple écrire :
joueNote(DO, 200, 400);
joueNote(DO, 200, 400);
joueNote(DO, 200, 400);
joueNote(RE, 200, 400);
Et ainsi de suite…
Ce serait un bon début.
Si on pouvait regrouper les notes et leur durée avec la durée du silence dans un
tableau, ce serait encore plus simple.
Pour cela, regardons comment faire.
Nos données de durée sont par exemple des unsigned int, car ils dépassent la
valeur 255 qui est le maximum pour un char.
On va donc créer notre tableau ainsi.
unsigned int melodie[11][3] = {
{DO, 200, 400},
{DO, 200, 400},
{DO, 200, 400},
{RE, 200, 400},
{MI, 200, 800},
{RE, 200, 800},
{DO, 200, 400},
{MI, 200, 400},
{RE, 200, 400},
{RE, 200, 400},
{DO, 200, 1500}
};
Ensuite, il faudra lire ce tableau à deux dimensions et envoyer chaque élément
à notre fonction joueNote(). On pourra faire une boucle for() et s’en servir pour
faire une itération sur ce tableau.
for (int i=0; i<11; i++)
joueNote(melodie[i][0], melodie[i][1], melodie[i][2]);
Quand i vaudra 0, on va donc lire la première ligne du tableau et récupérer
l’élément 0, l’élément 1 et l’élément 2. Comme tous les tableaux en C, le premier a
l’indice 0, le second l’indice 1, le troisième l’indice 2 et ainsi de suite.
Donc quand on aura melodie[0,0], ce sera le premier indice de la première ligne,
donc DO. Ensuite, melodie[0,1] donnera le second indice de la première ligne donc
200, et melodie[0,2] donnera 400.

Le Buzzer, pour faire du bruit /199


On va donc parcourir le tableau de la mélodie ligne par ligne et, à chaque fois,
on lira le premier, le second et le troisième indice.
Ensuite, on passe à la seconde ligne et on recommence jusqu’à la dernière ligne.
Le programme sera alors le suivant.
// (c)Frédéric SILLON 2020
// Au clair de la lune en Tableau
const byte PIN_BUZZER = 8;
#define DO 2093
#define RE 2349
#define MI 2637
unsigned int melodie[11][3] = {
{DO, 200, 400},
{DO, 200, 400},
{DO, 200, 400},
{RE, 200, 400},
{MI, 200, 800},
{RE, 200, 800},
{DO, 200, 400},
{MI, 200, 400},
{RE, 200, 400},
{RE, 200, 400},
{DO, 200, 1500}
};

void joueNote(unsigned int laNote, unsigned int laDuree, unsigned int leSilence) {
tone(PIN_BUZZER, laNote, laDuree);
delay(leSilence);
}

void setup() {
pinMode(PIN_BUZZER, OUTPUT);
}

void loop() {
for (int i=0; i<11; i++)
joueNote(melodie[i][0], melodie[i][1], melodie[i][2]);
}
Si on veut jouer autre chose, il suffit de modifier le tableau et le nombre d’ité-
rations de la boucle for().
Mis à part la déclaration du tableau, on joue maintenant la mélodie avec deux
lignes de code. C’est tout de même plus élégant !

200/ Chapitre 7 : Écrans, moteurs, capteurs…


L’ÉCRAN LCD, POUR MIEUX COMMUNIQUER
AVEC ARDUINO
Pour interagir avec notre Arduino, nous avions jusqu’à présent notre écran
d’ordinateur, qui est d’une grande aide lors du déboggage de nos programmes,
mais qui ne nous permet pas d’avoir un système autonome. En effet, on ne pourra
pas emporter notre ordinateur partout… On a aussi des Leds, et des boutons
poussoirs. Avec ça, on peut déjà faire pas mal de choses, et c’est d’ailleurs ce
qui était utilisé sur les tout premiers ordinateurs tels que l’Altair 8800 dans les
années 1970.

Figure 7.10 Altair 8800 (doc. oldcomputers.net)

Cependant ça fonctionne, mais ce n’est tout de même pas très friendly à l’heure
actuelle…
On pourrait également utiliser un écran comme sur les PC connectés en HDMI,
mais un peu trop compliqué pour l’instant. Le bon compromis est l’écran LCD
alphanumérique, comme on en trouve un peu partout.

Figure 7.11 Écran LCD alphanumérique

L’écran LCD, pour mieux communiquer avec Arduino /201


Comme son nom l’indique, un écran alphanumérique ne peut écrire que des
chiffres et des lettres, donc pas question de dessiner avec. Par contre, il est tout à fait
adapté pour afficher une température, des coordonnées GPS, et si on ajoute des bou-
tons poussoirs à notre Arduino (cinq suffisent : droite, gauche, haut, bas, enter), on
peut écrire un système de menus complexe sur plusieurs pages et avoir un vrai petit
ordinateur. Ces afficheurs sont classés par leur nombre de caractères affichables en
même temps (de huit à quarante) et par le nombre de lignes (d’une à quatre).
Bien évidemment, un afficheur 4 × 40 sera plus grand et plus coûteux qu’un
modèle 2 × 8 ; et il existe des verts, des bleus, des jaunes, le choix se fera en fonction
de l’utilisation. Nous utiliserons ici un modèle 2 × 16 caractères, référencé 1602A.

Figure 7.12 Brochage de l’affiche 1602A

Il y a seize pins, mais on va essayer de simplifier un peu.


Tout d’abord l’alimentation, classique en 5 V entre Vcc et Gnd.
Ensuite, on a l’entrée Vo sur laquelle on va amener une tension comprise entre
0 et 5V, et qui permet de régler le contraste de l’afficheur. Et comment faire ?
Avec un potentiomètre… On va câbler ses deux extrémités entre Vcc et Gnd et
connecter son curseur sur Vo, et on prendra un modèle de 10 kohms par exemple.
C’est tout simple.
Pour écrire un caractère sur l’afficheur, il va falloir lui dire à quel endroit, et
quel caractère. Pour faire la différence entre les deux, on va utiliser la pin RS qui
indiquera à l’afficheur si on veut écrite un caractère ou une instruction.
On peut écrire sur l’afficheur, mais on peut également lire ses registres pour
savoir s’il est prêt à recevoir un nouveau caractère à écrire par exemple. Pour cela,
on va utiliser R/W qui lorsqu’elle est à High indiquera à l’afficheur qu’on veut le lire,
et à Low qu’on veut lui écrire. On écrit plus généralement R/W\, où le\ indique de
le W est actif à Low. On a ainsi R actif à l’état haut et W\ actif à l’état bas.

202/ Chapitre 7 : Écrans, moteurs, capteurs…


Pour écrire sur l’afficheur, il faut lui indiquer que c’est à lui seul que l’on parle,
donc on utilisera E pour cela. En plaçant E à High, l’afficheur sera sélectionné (on
dit aussi sélecté) et il prendra les données et instructions à son compte.
On va utiliser le Bus de Données huit bits DB0-DB7 pour échanger avec notre
afficheur, en plaçant nos octets dessus.
Pour simplifier les choses, les concepteurs de ce genre d’afficheurs nous pro-
posent deux modes de dialogue : bus 8 bits ou bus 4 bits. Pour simplifier le câblage,
on utilisera donc le mode 4 bits, ce qui compliquera un peu la programmation car il
faudra dialoguer avec l’afficheur en deux étapes, mais ce n’est pas grave.
Pour finir, si on veut que l’afficheur soit lumineux, on pourra placer une ali-
mentation supplémentaire sur LED+ afin d’allumer les Leds de backlight qui sont
intégrées à notre module LCD. Il faudra placer une résistance série d’environ
220 ohms avec cette alimentation pour limiter le courant.
Par contre, le backlight consomme pas mal de courant, et on pourra augmenter
un peu la valeur de cette résistance à 330 ou 470 ohms par exemple. En voyant
tout ça, on est un peu mitigé car cela semble à la fois simple et complexe et on ne
sait pas trop quoi faire de tout ça.
Donc, petit tour par… la datasheet.

Figure 7.13 Séquence initialisation écran LCD, mode 4 bits

L’écran LCD, pour mieux communiquer avec Arduino /203


En effet, ça a l’air un peu compliqué (mais on s’en sort tout de même facile-
ment avec un peu d’entraînement…). Sinon, autre solution : regarder s’il existe
une bibliothèque de gestion de l’écran LCD… Si on regarde les exemples fournis
avec notre IDE (Fichier/Exemples), on va trouver une rubrique LiquidCrystal avec
un exemple HelloWorld. C’est exactement ce qu’il nous faut.

Figure 7.14 Exemple HelloWorld

Si on ouvre cet exemple et que l’on regarde les commentaires en entête, on va


trouver les informations nécessaires pour câbler l’écran correctement.
The circuit:
* LCD RS pin to digital pin 12
* LCD Enable pin to digital pin 11
* LCD D4 pin to digital pin 5
* LCD D5 pin to digital pin 4
* LCD D6 pin to digital pin 3
* LCD D7 pin to digital pin 2
* LCD R/W pin to ground
* LCD VSS pin to ground
* LCD VCC pin to 5V
* 10K resistor:
* ends to +5V and ground
* wiper to LCD VO pin (pin 3)
On voit que l’afficheur est câblé en mode 4 bits, en utilisant D4 à D7. En effet,
en mode 8 bits on utilise D0 à D7 alors qu’en mode 4 bits on utilise toujours D4
à D7 (et non pas D0 à D3 comme on pourrait s’y attendre).
Ensuite, le potentiomètre est utilisé pour le contraste.
RS et E sont reliés à notre Arduino qui va les gérer par logiciel.
En ce qui concerne R/W, elle est ici connectée à Gnd (ground), ce qui veut dire
qu’elle verra toujours l’état Low et donc que l’afficheur sera toujours en mode W\
(write).
On pourra écrire des données vers l’afficheur, mais pas le lire. Pas de souci, ça
fonctionne très bien aussi.
On va d’abord établir le schéma et l’implantation suivant ce modèle, et on
regardera le code source par la suite.

204/ Chapitre 7 : Écrans, moteurs, capteurs…


Figure 7.15 Schéma LCD mode 4 bits

On voit tout de suite que cette configuration avec bus parallèle D4-D7 est
beaucoup moins simple à câbler qu’une liaison série de type SPI par exemple.
Par contre, le fait de pouvoir travailler en mode 4 bits au lieu de 8 bits offre un
bon compromis pour simplifier un peu ce câblage.

Figure 7.16 Implantation LCD mode 4 bits

L’écran LCD, pour mieux communiquer avec Arduino /205


Revenons-en au code en ouvrant l’exemple HelloWorld. Compilons-le et télé-
chargeons-le sur la carte. Si rien ne s’affiche, pas de panique, il suffit d’ajuster le
potentiomètre de contraste, et tout devrait s’arranger.
On voit que cet exemple utilise la bibliothèque LiquidCrystal et crée une
variable lcd de type LiquidCrystal en l’initialisant avec les numéros de pins sui-
vant le câblage effectué.
On aurait également pu faire ainsi.
#include <LiquidCrystal.h>
#define RS 12
#define EN 11
#define DB4 5
#define DB5 4
#define DB6 3
#define DB7 2
LiquidCrystal myLCD(RS, EN, DB4, DB5, DB6, DB7); // On declare et Init myLCD
Ensuite, le setup() indique de quel modèle de LCD il s’agit, ici un 2 x 16 carac-
tères.
myLCD.begin(16,2);
L’écran est à présent prêt à être utilisé, et on va pouvoir écrire dessus avec :
lcd.print(”Hello”);
Comme on vient d’initialiser le curseur, il se trouve en haut à gauche de l’écran,
c’est-à-dire aux coordonnées 0,0 et donc colonne 0 et ligne 0. Pour écrire à la
position 5 de la ligne 2, les coordonnées seront donc (4,1).
lcd.setCursor(4,1);
lcd.print(”Hello”);
On voit que la librairie comporte un grand nombre de fonctions, par exemple
setCursor()ou scrollDisplayLeft().
// (c)Frédéric SILLON 2020
// Gestion de l'écran LCD 1602A
#include <LiquidCrystal.h>
#define RS 12
#define EN 11
#define DB4 5
#define DB5 4
#define DB6 3
#define DB7 2
LiquidCrystal myLCD(RS, EN, DB4, DB5, DB6, DB7); // On declare et Init myLCD
void setup() {
myLCD.begin(16, 2); // Ecran 2x16
myLCD.setCursor(4, 1); // Curseur colonne5 ligne 2
myLCD.print("Hello"); // 'Hello'}

void loop() {

206/ Chapitre 7 : Écrans, moteurs, capteurs…


for (int i=0; i<5; i++) { // Boucle 5 fois
myLCD.scrollDisplayRight(); // Scrolling droite
delay(500);
}
for (int i=0; i<5; i++) { // Boucle 5 fois
myLCD.scrollDisplayLeft(); // Scrolling gauche
delay(500);
}
}
On voit que la bibliothèque est une fois de plus une opportunité puissante, car
elle permet de mettre facilement en œuvre divers composants en ne se souciant
que du côté application de notre montage. Si on avait voulu utiliser l’écran par
nous-même sans librairie, il aurait fallu écrire quelques centaines de lignes de
code.

LE CAPTEUR DE LUMIÈRE,
POUR JOUER AVEC LE JOUR ET LA NUIT
Dans la série des composants sympas à utiliser, on va trouver la LDR. Qu’est-ce
que c’est ? C’est une Light Dependant Resistor, ce qui veut dire résistance dépen-
dant de la lumière. En bref, il s’agit donc d’une résistance dont la valeur ohmique
dépend de l’éclairage qu’elle reçoit. Cela paraît intéressant car si on pouvait
mesurer la valeur de cette résistance avec notre Arduino, on pourrait savoir s’il
fait jour ou nuit, sombre ou clair. Avec notre super buzzer, on pourrait faire un
réveil qui nous réveille quand le jour se lève… ou autre chose.
En étudiant le potentiomètre, on a parlé des associations de résistances et du
pont diviseur avec la formule :
R2
Vout = Valim ×
R 1 + R2
Cela veut dire que si on fait un pont diviseur avec une résistance et notre LDR,
on devrait pouvoir obtenir une tension qui varie en fonction de la lumière.
Il ne restera plus qu’à l’injecter sur une entrée analogique de notre Arduino, et
le tour est joué !
La LDR choisie est une LDR720, et si on regarde ses caractéristiques, elle a
une résistance supérieure à 5 mégaohms (5 MΩ) dans l’obscurité et inférieure à
300 Ω en pleine lumière.
On devrait donc bien voir la différence entre lumière/nuit sur un pont diviseur.
En choisissant une résistance de 1 KΩ, la différence entre lumière et obscurité est
assez sensible.
Il faudra sans doute adapter cette valeur en fonction de la LDR choisie, mais
aussi en fonction de la lumière ambiante. Pour ma part, 1 KΩ fonctionne bien.

Le capteur de lumière, pour jouer avec le jour et la nuit /207


Figure 7.17 Schéma LDR et LCD

Figure 7.18 Implantation LDR et LCD

208/ Chapitre 7 : Écrans, moteurs, capteurs…


Au niveau du sketch, on peut par exemple lire la valeur du pont diviseur sur
l’entrée analogique A0, la convertir en niveau de tension et mettre un seuil à partir
duquel l’Arduino verra le jour et la nuit.
// (c)Frédéric SILLON 2020
// Gestion de la LDR
#include <LiquidCrystal.h>
#define RS 12
#define EN 11
#define DB4 5
#define DB5 4
#define DB6 3
#define DB7 2
#define LDR A0
LiquidCrystal myLCD(RS, EN, DB4, DB5, DB6, DB7); // On declare et Init myLCD
float lumiere = 0; // Memorisation lecture analogRead

void setup() {
myLCD.begin(16, 2); // Afficheur 2x16
myLCD.setCursor(4, 1); // Curseur en col 5 ligne 2
myLCD.print("Hello"); // Affichage Hello
}

void loop() {
lumiere = analogRead(LDR)*0.0049; // Lecture et conversion
myLCD.setCursor(0, 0); // Curseur en 0,0
myLCD.print(lumiere); // Ecriture valeur tension
myLCD.setCursor(0,1); // Curseur en col 1, ligne 2
if (lumiere > 3.0) // Si lumiere faible
myLCD.print("Obscurite"); // Obscurite
else // Sinon
myLCD.print("Lumiere "); // Lumiere forte
}
Dans l’affichage des mots Obscurité et Lumière, il y a une petite astuce qui
évite d’effacer l’écran pour chaque affichage : les deux mots n’ont pas la même
longueur et Lumière est complété avec des espaces. Sans cela, l’affichage serait
Obscurité puis Lumièreité. En effet, Lumière est écrit en position 0.1, tout comme
Obscurité, mais comme il est plus court et que l’écran n’est pas effacé, les der-
niers caractères ne seraient pas effacés et resteraient sur l’afficheur. En faisant
ainsi, on les efface tout de même. Essayez de supprimer les espaces qu’il y a après
le mot Lumière dans le sketch afin de voir la différence.
On pourrait également effacer l’écran avec un myLCD.clear(), mais l’écran se
mettrait à clignoter. Essayez de le faire également pour voir la différence, en posi-
tionnant un myLCD.clear() avant d’écrire chacun des deux mots.
Nous voilà prêts à faire pas mal de choses avec tout ça.

Le capteur de lumière, pour jouer avec le jour et la nuit /209


LE CAPTEUR DE TEMPÉRATURE,
POUR INTÉRAGIR AVEC L’ENVIRONNEMENT
Il existe plusieurs moyens pour mesurer la température. Comme les LDR qui
réagissent à la lumière, les CTN et CTP sont des résistances qui réagissent forte-
ment à la température et on peut les utiliser comme les LDR.
Une autre façon est d’utiliser des capteurs de température un peu plus évolués
qui nous donnent directement une tension proportionnelle à leur température.
Dans notre exemple, nous allons utiliser un TMP36 de chez Analog Device.

Figure 7.19 TMP36 Analog Device (doc. gotronic.fr)

Son boîtier ressemble à un transistor, a trois pattes et son brochage est le suivant.

Figure 7.20 Brochage TMP36 (doc. Analog Device)

Sur ce brochage, on voit que le TMP36 est alimenté entre Vs et Gnd (de 2,7 à 5V
d’après la datasheet), et que la sortie de mesure est Vout.
Comment connaître la température en fonction de la tension présente sur
Vout ? Eh bien une fois de plus, petit tour sur la datasheet.

Figure 7.21 Courbe de température TMP36 (doc Analog Device)

210/ Chapitre 7 : Écrans, moteurs, capteurs…


Sur cet abaque, on voit plusieurs courbes qui correspondent à plusieurs types
de capteurs. Le nôtre étant un TMP36, on regardera donc la courbe b.
Sur cette courbe, le capteur est alimenté en 3V (Vs = 3V) et il amène une tension
de 0,5 V à 0 °C. Tout ça nous donne une idée, mais n’est pas très précis pour le reste.
Une lecture plus approfondie de la datasheet nous indique :

Figure 7.22 Datasheet TMP36 (doc. Analog Device)

Une rapide traduction nous indique donc que le TMP36 fonctionne de –40
à 125 °C, qu’il donne une tension de 750 mV à 25 °C, et également qu’il a une
échelle en sortie de 10 mV/°C.
C’est plus clair maintenant. À chaque degré, on aura 10 mV de plus et le 0 °C
amène une tension de 500 mV.
Comme sa sortie Vout nous donne une tension analogique, on va donc le
connecter sur une entrée analogique de notre Arduino, par exemple sur A1.

Figure 7.23 Schéma TMP36

Le capteur de température, pour intéragir avec l’environnement /211


Figure 7.24 Implantation TMP36

Voyons maintenant comment coder tout ça. Si on reprend ce que l’on a vu pré-
cédemment, on a 10 mV par °C et 500 mV à 0 °C.
Comme on part de 0 °C à 500 mV, on peut donc dire que 1 °C donnera
500 + 10 mV, que 2 °C donnera 500 + 20 mV, etc.
Il faudra alors retirer ces 500 mV des mesures de tension qui seront faites. On
aura ainsi la valeur de tension à partir de 0 °C.
Comme on a nos 10 mV pour 1 °C, une simple règle de trois nous amènera à :
V – 500
T=
10
Si on lit 750 mV, on aura donc :
750 – 500
T= = 25
10
Comme annoncé par la datasheet, on retrouve bien nos 25 °C pour 750 mV.
On pourra donc coder la valeur de température ainsi :
temperature = (analogRead(A1)*0.0049*1000 - 500) / 10;
D’où viennent ce 0.0049 et ce 1000 ? Et bien si on se rappelle du chapitre de la
conversion avec analogRead(), on avait vu que :
Tension = valeurLue * 0.0049, car 0.0049 correspond à une unité du conver-
tisseur de notre Arduino, c’est-à-dire à 49 mV par bit.

212/ Chapitre 7 : Écrans, moteurs, capteurs…


Ensuite, comme notre formule de calcul de la tension est en volts et que l’on
veut des millivolts, il faut multiplier le résultat par 1 000.
Et maintenant, codons en reprenant l’exemple de la LDR que l’on va améliorer.
// (c)Frédéric SILLON 2020
// Gestion de la LDR et du thermometre
#include <LiquidCrystal.h>
#define RS 12
#define EN 11
#define DB4 5
#define DB5 4
#define DB6 3
#define DB7 2
#define LDR A0
#define TEMPERATURE A1

LiquidCrystal myLCD(RS, EN, DB4, DB5, DB6, DB7); // On declare et Init myLCD
float lumiere = 0; // Memo lecture lumiere
float temperature = 0; // Memo temperature

void setup() {
myLCD.begin(16, 2); // Afficheur 2x16
myLCD.setCursor(0, 0); // Curseur en col 5 ligne 2
myLCD.print("Soleil Chaleur"); // Affichage titre
}

void loop() {
lumiere = analogRead(LDR)*0.0049; // Lecture et conversion
temperature = (analogRead(TEMPERATURE)*0.0049*1000 -500) / 10;
myLCD.setCursor(0, 1); // Curseur en 0,1
if (lumiere > 3.0) // Si lumiere faible
myLCD.print("Obscurite: "); // Obscurite
else // Sinon
myLCD.print("Lumiere : "); // Lumiere forte
myLCD.print(temperature);
}
On voit que la mesure bouge beaucoup dans la valeur affichée après la virgule.
Si on veut afficher seulement les degrés sans s’occuper de la partie décimale,
on va transtyper la valeur float en int.
myLCD.print((int) temperature);
myLCD.print(" C");
Au passage, on rajoute le symbole C pour marquer la température.
Sur certains écrans LCD, il n’est pas possible d’afficher les caractères accen-
tués ni les symboles spéciaux comme le ° pour écrire °C. C’est le cas du mien, il
peut afficher des caractères japonais, mais pas d’accents.
Si on voulait le faire, il faudrait redéfinir certains caractères dans la mémoire
de l’écran.

Le capteur de température, pour intéragir avec l’environnement /213


Ça n’a l’air de rien, mais on a fait une mini station météo pour voir le temps qu’il
fait sans sortir… Il faut juste placer le montage près d’une fenêtre, et bien calibrer
le seuil Lumière/Obscurité dans le programme pour voir passer les nuages. C’est
un bon début.
/> CHAPITRE
POUR ALLER PLUS LOIN
8

Nous allons aborder des notions plus complexes, mais qui vont permettre de
créer des bibliothèques de codes déjà existants et d’utiliser différents modules
du commerce, ce qui évite de tout réinventer à chaque fois.

LA PROGRAMMATION OBJET
Si on reprend notre sketch MonBlink, on a pu allumer et éteindre notre Led
très simplement. Une fonction qui allume la Led, et une autre qui l’éteint. Ça fonc-
tionne plutôt bien. Par contre, si on avait 8 Leds à gérer, il y a fort à parier que l’on
aurait beaucoup de lignes de code qui se répètent et on allongerait notre code
pour rien. En plus, si on voulait changer le comportement des Leds, par exemple
les faire clignoter deux fois au lieu d’une à chaque fois, il faudrait réécrire le code
de chaque Led. On pourrait également s’en sortir en utilisant des fonctions qui
regroupent plusieurs actions.
Autre remarque. Quand on a utilisé l’écran LCD, on a commencé par déclarer
une variable myLCD car c’est ce qui était demandé pour pouvoir utiliser la biblio-
thèque qui gère l’écran. Ensuite, on a pu avoir accès aux fonctions le LCD comme
myLCD.print() par exemple.
Si on avait eu un second écran, on aurait ainsi pu déclarer une seconde variable
mySecondLCD et ensuite disposer des mêmes fonctions que précédemment et
écrire mySecondLCD.print(). Et encore un troisième, et un quatrième de la même
façon, sans réécrire toutes les fonctions à chaque fois, juste en déclarant une
variable du type LiquidCrystal.
En fait, c’est un peu comme si notre écran savait faire plein de choses tout seul,
comme un objet qui peut s’allumer, s’éteindre, écrire ou faire plein d’autres choses
si on les lui demande.
Et bien c’est le cas, et ceci nous amène à la programmation Objet et à la créa-
tion de nos propres bibliothèques.
En programmation objet, au lieu d’écrire des fonctions pour chaque chose, on
va plutôt construire des objets qui auront leurs propres variables, leurs propres

La programmation Objet /215


fonctions et leurs propres comportements. Ensuite, on pourra déclarer autant de
variables que l’on veut de ce type d’objet, et ces variables auront donc ces mêmes
comportements.
Par exemple, une balle est un objet. Elle est ronde, elle rebondi, elle roule, elle
a une couleur, elle est en caoutchouc. Si maintenant on déclare que l­aJolieBalle
est une balle, elle rebondira que la même façon. De même pour taBalle ou
pour laBalleDuChien. laBalleDuChien sait rebondir, sait rouler et elle est bleue.
­laJolieBalle sait aussi rebondir et rouler (car c’est une balle), mais elle est verte.
Pour déclarer un objet, on va créer une class de cet objet, qui regroupe toutes
les variables qui lui sont propres et toutes ses fonctions. Ensuite, on va décrire
chaque fonction pour apprendre à notre objet comment il se comporte.
Quand tout ça sera fait, on pourra donc créer des variables Balle comme
laBalleDuChien et dire par exemple laBalleDuChien.roule().
On va ainsi pouvoir créer des bibliothèques que les autres programmeurs pour-
ront utiliser, mais que l’on pourra également réutiliser dans d’autres projets sans
tout réécrire à chaque fois.

CRÉER SES PROPRES BIBLIOTHÈQUES


En programmation objet, on va donc déclarer un objet Led (une class) par
exemple et on va lui apprendre plein de choses : s’allumer, s’éteindre, clignoter.
On va tout d’abord créer un fichier qui aura l’extension .h et qui s’appellera
Led.h dans notre exemple. Ce fichier est un header, c’est-à-dire un fichier d’entête
qui va montrer aux autres programmes ce que notre Led sait faire.
Pour cela, on va déclarer une class qui pourra ressembler à ceci :
#include <stdint.h>
class Led {
public:
void init(unsigned char pin);
void allumer(void);
void eteindre(void);
void clignoter(void);
private:
unsigned char _pin;
};
Tout d’abord, on va vouloir initialiser notre led en indiquant sur quelle pin de
l’Arduino elle est connectée. Ensuite, on voudra l’allumer, l’éteindre et la faire cli­
gnoter. Toutes ces fonctions sont public car on veut qu’elles soient accessibles à
tous les programmeurs.
Ensuite, si on veut déclarer des variables ou des fonctions qui nous sont réser-
vées, on les déclarera comme étant privées (private). Ici, il s’agit de mémoriser le
numéro de la pin sur laquelle est branchée la Led.
Dans ce fichier Led.h, on déclarera également les define nécessaires s’il y en a.

216/ Chapitre 8 : Pour aller plus loin


À présent que nous avons déclaré notre class Led, il va falloir écrire le code qui
fera toutes ces fonctions. Pour cela, on va créer un autre fichier qui aura l’exten-
sion cpp, dans notre cas Led.cpp.
Dans ce fichier, on va reprendre chaque fonction décrite dans notre fichier
Led.h et écrire le code en faisant précéder chaque nom de fonction par Led::
(Led deux points deux points).
Par exemple, on écrira dans notre fichier Led.cpp :
#include "Led.h"
#include "pins_arduino.h" // Pins Arduino
#include "wiring_private.h" // Constantes diverses

Led::Led(unsigned char pin) {


pinMode(pin, OUTPUT); // La pin est en sortie
_pin = pin; // Memorise la pin où la Led est connectee
}

void Led::allumer(void) {
digitalWrite(_pin, HIGH); // Allumage Led memorisee
}

void Led::eteindre(void) {
digitalWrite(_pin, LOW); // Extinction Led memorisee
}

void Led::clignoter(void) {
allumer(); // allumage
delay(1000); // Temporisation
eteindre(); // Extinction
delay(1000); // Temporisation
}
On va écrire nos fonctions ainsi :
void Led::allumer(void) {
… // Le code des choses à faire
}
Cette écriture est spécifique à la programmation objet et toutes nos fonctions
commenceront ainsi Led::
La première fonction est un peu spéciale, il s’agit du Constructeur. Le Construc­
teur permet d’initialiser l’objet et de le créer en mémoire. Ainsi, le constructeur
de notre Led sera Led::Led().
Maintenant que le code de notre objet Led semble correct, il va falloir zipper les
fichiers cpp et h ensemble afin d’obtenir un fichier Led.zip.
On pourra alors l’inclure dans les bibliothèques de notre IDE. Pour cela, on ira
dans le menu Croquis/Inclure une bibliothèque/Ajouter la bibliothèque ZIP.

Créer ses propres bibliothèques /217


Figure 8.1 Inclure une bibliothèque

Il suffit alors de choisir le fichier zip que l’on vient de créer.

Figure 8.2 Fichier ZIP pour bibliothèque

Notre IDE nous dit alors que la bibliothèque a été ajoutée.

Figure 8.3 Notre bibliothèque prise en compte

Et on la voit maintenant dans le menu Croquis/Inclure une bibliothèque.

Figure 8.4 La bibliothèque est ajoutée

218/ Chapitre 8 : Pour aller plus loin


Pour l’utiliser, on va donc créer un nouveau fichier, par exemple biblioTest. En
retournant dans le menu précédent des bibliothèques et en cliquant sur le nom
de notre Led, l’IDE va automatiquement inclure son nom.
#include <Led.h>
On va ensuite déclarer une variable myLed et l’initialiser avec son Constructeur.
Ici, la Led est celle de la carte Arduino, donc en pin 13.
Led myLed(13);
Rien à mettre dans le setup() car la Led est initialisée par son constructeur.
Et enfin dans le loop(), on veut juste la faire clignoter.
myLed.clignoter();
Super facile, non ?
Si on avait une seconde Led sur la pin 8, on aurait simplement déclaré une
variable :
Led ledRouge(8);
Et pour la faire clignoter :
ledRouge.clignoter();
C’est tout !
En résumé, on aurait :
#include <Led.h>
Led myLed(13);
Led ledRouge(8);

void setup() {
}

void loop() {
myLed.clignoter();
ledRouge.clignoter();
}
C’est un peu bizarre au début, mais c’est super puissant, et on retrouve bien
ici l’esprit des bibliothèques que l’on a déjà utilisées pour l’écran et le GPS par
exemple.
La seule chose à faire est de bien documenter les fonctions de la bibliothèque
afin que d’autres programmeurs puissent l’utiliser facilement.

LES MODULES DU COMMERCE


Il existe une multitude de cartes d’extension dans le commerce que l’on peut
monter sur les connecteurs d’extension de notre Arduino. Ces cartes d’extension
sont appelées des shields. Il y a des cartes de pilotage de moteurs, des modules
Ethernet, Bluetooth, des shields multifonctions avec boutons poussoirs, écran
LCD et buzzer, bref on trouve de tout pour tout le monde.

Les modules du commerce /219


D’ailleurs, le logiciel Fritzing que nous avons utilisé pour les schémas et les
implantations permet de créer ses propres shields.
Nous allons ici nous intéresser à un module de chez Adafruit Industries, qui
comporte un écran couleur tactile. De quoi faire de super beaux montages.

// L’ÉCRAN TFT…
Utiliser l’écran LCD nous permet d’afficher de petits messages, par exemple la
température des chapitres précédents.
Avec un écran graphique, on pourrait dessiner, faire des menus, des boutons
pour cliquer et plein d’autres choses. On pourrait faire une belle IHM pour nos
montages. Une IHM est une Interface Homme Machine, c’est-à-dire un système
de boutons et de menus qui va permettre à l’utilisateur de dialoguer avec notre
montage. Si on rajoute une dalle tactile, on pourrait tout commander avec un
seul doigt !
Par contre, un écran graphique est assez difficile à piloter, de même que la
dalle tactile. Comme d’habitude, le bon réflexe sera de regarder s’il existe une
bibliothèque pour nous aider à démarrer, et apprendre comment cela fonc-
tionne.
La société Adafruit qui est basée à New York propose une multitude de cartes
et composants pour l’Arduino, ainsi qu’un grand nombre de bibliothèques.
Pour s’essayer à l’utilisation de l’écran tactile, on pourra essayer le modèle 2.8"
TFT Touch Shield for Arduino with Resistive Touch Screen par exemple.
Quelles sont donc ses caractéristiques ? 2.8’’ est la taille de sa diagonale, soit
environ 7 cm (1 pouce = 2,54 cm).
Il est TFT, ce qui veut dire qu’il est constitué de « Thin Film Transistors ». Chaque
pixel est commandé par transistors et on parle aussi de matrice active. Ces écrans
sont réactifs et bien contrastés.
Il a aussi un Resistive Touch Screen, c’est-à-dire une dalle tactile résistive. Le
circuit intégré qui contrôle cette dalle résistive est capable de calculer les coor-
données de l’emplacement où l’on a appuyé avec le doigt. Cette technologie est
meilleure marché que celle donnant une dalle tactile capacitive.
Pour installer la bibliothèque, on va aller dans le menu suivant.

Figure 8.5 Installation bibliothèque

220/ Chapitre 8 : Pour aller plus loin


À partir de là, on va chercher la librairie graphique Adafruit (GFX).

Figure 8.6 Bibliothèque TFT Adafruit

Si l’installateur le demande, on le laissera installer les librairies dont il a besoin.


Pour la dalle tactile, il faudra également installer la librairie ILI9341.

Figure 8.7 Installation de la bibliothèque ILI9341

Une fois les installations terminées, il faudra quitter l’IDE et le relancer.


À partir de là, on pourra trouver un exemple comme TouchPaint, qui nous per-
mettra de dessiner sur l'écran.

Figure 8.8 Exemple de TouchPaint

Les modules du commerce /221


En le simplifiant, on peut ne garder que la partie affichage.
// (c)Frédéric SILLON 2020
// Ecriture sur écran TFT
// D’après l’exemple fourni avec l’écran tactile par Adafruit Industries.
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <SPI.h>

// Communication SPI avec ecran , sur pins 9 et 10


#define TFT_CS 10
#define TFT_DC 9
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC); // Init ecran

void setup(void) {
tft.begin(); // Init Ecran
tft.fillScreen(ILI9341_BLACK); // Efface Ecran

tft.setCursor(0, 0); // Curseur en 0,0


tft.setTextColor(ILI9341_WHITE); // texte en blanc
tft.setTextSize(2); // Taille 2

tft.println("Hello World!"); // Ecriture texte


delay(1000);

tft.fillScreen(ILI9341_BLACK); // Efface Ecran


tft.setTextColor(ILI9341_YELLOW); // Texte en jaune
tft.setTextSize(1); // Taille 1
}

void loop()
{
tft.println("J'aime Arduino !!"); // Ecrit a chaque tour de loop
}
Dans cet exemple, on a tout d’abord créé une variable tft de type Adafruit_
ILI9341. On retrouve ici ce que l’on a vu avec les bibliothèques et les objets.
Ensuite, le setup() démarre la gestion de l’écran et l’efface en le remplissant
d’un grand fond noir. On positionne ensuite le curseur au point d’origine (0,0) et
on choisi d’écrire en blanc avec une fonte de caractères de taille 2.
On écrit notre message et après le delay, on efface de nouveau l’écran avant de
choisir une police de caractères jaune en taille 1.
Dans le loop(), on va écrire notre message en continu, en allant à la ligne à
chaque fois.
Avec ce petit exemple, on voit comment écrire facilement sur l’écran, et en
explorant la bibliothèque Adafruit on pourra apprendre à utiliser les fonctions de
dessin pour faire des lignes, des ronds et des carrés très simplement.
De quoi faire une belle IHM.

222/ Chapitre 8 : Pour aller plus loin


// … ET SA DALLE TACTILE
Si on veut utiliser la dalle tactile de cet écran, on va de nouveau regarder
l’exemple précédent.
Tout d’abord, il faut inclure la librairie qui va gérer cette dalle.
#include <Adafruit_STMPE610.h>
Ensuite, on va initialiser la pin qui servira à sélectionner ce composant sur le
bus SPI.
#define STMPE_CS 8
Par la même occasion, on initialise une variable ts (ts : TouchScreen), de type
Adafruit_STMPE610 comme le demande la bibliothèque.
Adafruit_STMPE610 ts = Adafruit_STMPE610(STMPE_CS);
Notre écran a une résolution de 320 x 240 pixels, mais la dalle tactile a une
résolution beaucoup plus élevée. Il va donc falloir redimensionner les coor-
données renvoyées par la dalle afin qu’elles correspondent à la résolution de
l’écran. Pour cela, deux constantes sont définies afin de faire ce calcul dans
le loop().
#define TS_MAXX 3800
#define TS_MAXY 4000
Et aussi la largeur du crayon pour dessiner, 2 pixels.
#define CRAYON 2
Ensuite, il faudra l’initialiser dans le setup().
ts.begin();
Maintenant que tout est prêt, le loop() va pouvoir récupérer les coordonnées du
point touché par l’utilisateur sur l’écran, réajuster ces coordonnées à la résolution
de l’écran et réagir à ce toucher.
TS_Point p = ts.getPoint(); // Recupere les coordonnées du toucher
Ensuite, on réajuste (remappe) ces coordonnées à celles de l’écran.
p.x = map(p.x, 0, TS_MAXX, 0, tft.width()); // Remappe x sur largeur ecran
p.y = map(p.y, 0, TS_MAXY, 0, tft.height()); // Remappe y sur hauteur ecran
La fonction map() est une fonction de la librairie Arduino, et en allant sur le site
arduino.cc, on aura les informations suivantes :
map(value, fromLow, fromHigh, toLow, toHigh);
Avec :
>> Value : valeur à remapper (ici, ce sont nos points de coordonnées)
>> fromLow, fromHigh : les valeurs limites basse et haute du départ
>> toLow, toHigh : les valeurs limites basse et haute de résultat
Ainsi, on aura transformé les coordonnées relatives à la dalle en coordonnées
relatives à l’écran.
Ensuite, on va pouvoir afficher un point à l’endroit appuyé, ce qui permettra de
dessiner avec le doigt.
tft.fillCircle(p.x, p.y, CRAYON, ILI9341_MAGENTA);

Les modules du commerce /223


Figure 8.9 Tic Tac Toe sur l’écran TFT

Maintenant, on peut dessiner sur l’écran, mais surtout détecter la position du


toucher, ce qui veut dire que l’on pourra dessiner des boutons (en dessinant des
carrés par exemple), et détecter lorsque l’utilisateur aura cliqué dessus. À partir
de là, on pourra déclencher des actions.

DEUX EXEMPLES DE PROJETS RÉALISABLES


AVEC CE QUE L’ON A APPRIS
Nous pouvons à présent regrouper ce que nous avons appris dans de plus gros
projets. Nous avons appris beaucoup de choses depuis le premier Blink, au niveau
de la programmation, mais aussi au niveau des bases de l’électronique. Avec ça, il
va être possible de créer des montages évolués, soit à partir de shields existants
que l’on pourra adapter, soit en créant un montage complet from scratch (ce qui
veut dire en partant de zéro…).
Tout d’abord, que sait-on faire à présent ? On sait :
>> Programmer un Arduino Uno sous Windows, Mac ou Linux
>> Utiliser et créer des bibliothèques
>> Utiliser des Leds standard et multicolores
>> Utiliser des résistances pour limiter le courant et faire un pont diviseur
>> Utiliser un potentiomètre, un bouton poussoir, un potentiomètre numérique
XPot
>> Utiliser une LDR
>> Utiliser un écran LCD et un écran tactile TFT
>> Utiliser des transistors PNP, NPN et MOS en commutation
>> Utiliser un buzzer
>> Utiliser un servo et un capteur de température
>> Utiliser un GPS, un capteur de mouvement et un capteur de couleurs
>> Communiquer avec un ordinateur en RS232
Ça fait quand même pas mal de choses, non ?

224/ Chapitre 8 : Pour aller plus loin


// STEELLAC : UNE PLATEFORME
POUR APPRENDRE À PROGRAMMER
Si on mettait plusieurs de ces nouvelles connaissances sur un seul montage, on
pourrait faire une carte comme celle-ci :

Figure 8.10 La carte d’Erwan « Steellac »

Le µC ATMega328P est embarqué sur la carte (sous l’afficheur LCD), et les trois
boutons poussoirs permettent de naviguer dans le système de menus.
Quatre Leds et deux Leds RGB permettent d’améliorer le dialogue utilisateur,
un capteur de température et une LDR permettent de voir le temps qu’il fait.
Par exemple, les deux Leds RGB peuvent être vertes s’il fait beau, bleues s’il
fait froid et s’allumer plus faiblement la nuit. Le buzzer peut faire sonner une
alarme s’il fait trop froid ou trop chaud.
Avec les trois boutons poussoirs, on peut également faire un jeu sur l’écran en
répondant à des questions préprogrammées, puis compter les points et allumer
les Leds.
On peut aussi faire un jeu de mémorisation des couleurs qui défilent avec les
Leds jaune, verte, rouge et bleue.
Le tout est alimenté par le connecteur USB qui sert aussi à communiquer avec
le Moniteur Série de l’IDE. On peut ainsi dialoguer avec la carte par l’intermédiaire
du port RS232.
En résumé, nous avons là une bonne petite plateforme pour apprendre à pro-
grammer, compatible au niveau logiciel avec l’Arduino Uno et son IDE.
On retrouve ainsi l’application de certains exemples sur lesquels nous avons
travaillé ensemble dans les chapitres précédents.

Deux exemples de projets réalisables avec ce que l’on a appris /225


// GEMINI : UN PETIT ROBOT BOURRÉ DE CAPTEURS
En allant plus loin, on peut aussi faire un petit robot comme Gemini.
On y retrouve deux LDR pour capter la lumière, des capteurs infrarouges
devant, derrière et dessous, un module Bluetooth, deux moteurs, deux leds mul-
ticolores, des leds bicolores, un buzzer.

Figure 8.11 Le robot Gemini

Avec ses capteurs infrarouges (IR) avant et arrière, Gemini peut voir les obsta-
cles qui se présentent devant lui, ou derrière lui s’il doit reculer.
Les capteurs IR se trouvant dessous lui permettent de détecter le sol et évitent
qu’il ne tombe de la table, mais lui permettent aussi de suivre une ligne tracée par
terre.
Pour avancer, il a deux moteurs à courant continu, mais on pourrait tout aussi
bien utiliser deux mini servos comme celui que l’on a utilisé dans les chapitres
précédents.
Les deux LDR à droite et à gauche lui permettent de suivre une lumière ou de
lui échapper. On peut ainsi le diriger avec une lampe de poche dans le noir…
Les Leds multicolores peuvent donner une indication de son état lorsqu’il ne
sait plus où aller par exemple, tandis que les Leds bicolores rouge/vert qui sont
placées à l’avant et à l’arrière s’allument en vert lorsque la voie est libre, et en
rouge lorsqu’un obstacle est détecté.

226/ Chapitre 8 : Pour aller plus loin


Enfin, le module Bluetooth permet de dialoguer avec une tablette de style iPad
ou avec un smartphone. Ainsi, on peut le piloter à distance ou lui programmer un
parcours à effectuer.
Nous n’avons pas appris à utiliser ce module Bluetooth, car il nécessite égale-
ment la programmation d’une application sur le smartphone, et ceci dépasse le
cadre de cet ouvrage. Par contre, on pourrait mettre un module GPS à la place et
programmer un parcours à suivre.
Gemini est programmable avec notre IDE préféré, tout comme l’Arduino.
On peut aussi le programmer en scratch grâce à de nouvelles extensions que
j’ai spécialement développées pour lui.

Figure 8.12 Exemple de programmation en scratch pour Gemini

Le but de ce petit robot est de prendre rapidement la main afin de réaliser très
rapidement de petits programmes, qui deviendront de plus en plus complexes.
De même, on peut s’en servir pour jouer à plusieurs, créer des algorithmes
entre copains et voir lequel est le plus performant.
Qu’est-ce qu’un algorithme ? C’est simplement la façon de résoudre un pro-
blème avec des étapes bien définies, qui s’enchaînent les unes après les autres.
On va faire ceci, puis cela et ensuite encore autre chose, d’une façon bien struc-
turée un peu comme mettre un pied devant l’autre. Pour y arriver, on enchaîne
toute une série de mouvements précis et ordonnés sans même s’en rendre
compte. Si on mélange ces opérations, on tombe…
Pour aborder facilement cette notion d’algorithmes avec les enfants et les
débutants, j’ai développé un langage graphique basé sur un système de cartes
qui ressemblent à des cartes à jouer. Chaque carte comporte des dessins repré-
sentant les diverses instructions, actions ou choix possibles pour le robot, et cer-
taines d’entre elles ont même l’équivalent en code Arduino inscrit dessus.
On les met alors par terre ou sur la table les unes derrière les autres pour créer
l’algorithme que l’on veut faire.

Deux exemples de projets réalisables avec ce que l’on a appris /227


Figure 8.13 Cartes de programmation Gemini

228/ Chapitre 8 : Pour aller plus loin


On voit sur cet exemple qui va du haut vers le bas que l’on donne les instruc-
tions suivantes au robot.
Avance devant toi
Va doucement
La route est-elle dégagée devant toi à gauche ?
Oui: Arrête-toi
Non: Compte jusqu’à 8 et arrête-toi
Ça m’a tout l’air d’être un piège, car il va rentrer dans l’obstacle…
Comme on le voit sur cet autre exemple, il ne reste plus qu’à recopier cet algo-
rithme dans le logiciel graphique en cliquant sur les icônes correspondant aux
cartes que l’on a utilisées.

Figure 8.14 Exemple de codage graphique de Gemini

Le code Arduino correspondant est automatiquement écrit par le logiciel, et on


peut directement le téléverser dans le robot.
Un enfant de 5 ans peut alors programmer une carte compatible Arduino, sim-
plement en positionnant les cartes dans le bon ordre et en cliquant ensuite sur
les images. Un peu plus tard, il pourra alors lire le code automatiquement généré.
Bref, beaucoup d’heures de codage et d’amusement en perspective avec ces
nouvelles connaissances !
/> CONCLUSION

Nous voilà donc arrivés à la fin…


Tout au long de ces chapitres, nous avons appris à utiliser notre carte Arduino
Uno, à écrire des programmes de plus en plus complexes et nous avons également
abordé les bases de l’électronique.
Toutes ces nouvelles connaissances doivent être travaillées petit à petit et assi-
milées afin de créer de plus gros projets en toute autonomie.
Dans cet apprentissage, Internet est une source inépuisable d’informations
variées et diverses qui sont d’une grande aide lorsque la situation semble blo-
quée, mais également une grande source d’inspiration en regardant ce que les
autres ont fait, et surtout pour imaginer ce qu’ils n’ont pas encore fait.
Il ne faut pas avoir peur d’expérimenter, de se tromper et de recommencer : la
réussite du projet est au bout de ces expérimentations.
Bonne programmation et bons développements pour la suite de vos montages !

Vous aimerez peut-être aussi