Arduino - Les bases de la programmation

Transcription

Arduino - Les bases de la programmation
3
Éléments du langage C
Le langage de programmation qui permet de programmer une carte Arduino se nomme
le langage C. Ce chapitre vous propose d'en découvrir ou d'en revoir les éléments fondamentaux. Ce que vous allez apprendre au cours de ce chapitre vous servira dans tous les
programmes que vous allez concevoir pour Arduino. Pour bien tirer profit d'Arduino,
il faut avoir compris ces éléments fondamentaux.
Programmer
Il n'est pas rare de nos jours que les gens parlent plus d'une langue. D'ailleurs, plus vous
en apprenez, plus il devient simple d'en apprendre d'autres, parce que vous commencez à
repérer des invariants de grammaire et de vocabulaire qui sont partagés entre plusieurs
langues. Il en va de même avec les langages de programmation. Autrement dit, si vous
avez déjà pratiqué un autre langage, vous serez vite à niveau en langage C.
La bonne nouvelle avec les langages de programmation informatique est que leur
vocabulaire est bien plus restreint que celui d'une langue humaine. De plus, c'est un
langage écrit et non parlé, ce qui vous permet de toujours pouvoir recourir au dictionnaire en cas de doute. La grammaire et la syntaxe d'un langage informatique sont très
strictes. Une fois que vous avez assimilé une poignée de concepts simples, la progression
devient quasiment naturelle.
© 2013 Pearson France – Arduino – Simon Monk
ARDUI__Monk.indb 25
21/03/13 18:05
 
26
Arduino : les bases de la programmation
Vous pouvez comparer un programme informatique (les programmes source Arduino
s'appellent des croquis ou sketch), comme une liste d'instructions que le processeur
doit exécuter dans l'ordre dans lequel elles apparaissent. Prenons comme exemple les
trois lignes suivantes :
digitalWrite(13, HIGH);
delay(500);
digitalWrite(13, LOW);
Chacune de ces trois lignes fait réaliser une action. La première ligne force le passage à
l'état haut (HIGH) de la broche 13 du circuit. C'est sur cette broche qu'est installée une
LED sur la carte Arduino. Cet ordre oblige donc à faire allumer la LED. La deuxième
ligne se contente de suspendre l'exécution pendant 500 millisecondes (une demiseconde). La troisième ligne est ensuite exécutée pour éteindre la LED. L'exécution de
ces trois lignes permet donc de faire clignoter une fois la LED.
Vous aurez remarqué la présence de plusieurs signes de ponctuation et l'apparent oubli
d'espaces entre les mots (et de lettres accentuées). Bien des débutants en programmation
savent ce qu'ils veulent faire, mais ils ne savent comment le formuler par écrit. Ne vous
inquiétez pas, nous allons tout expliquer.
Voyons d'abord ce problème de ponctuation et d'absence d'espaces entre les mots. Ces
manières d'écrire sont conformes à la syntaxe du langage et la plupart des langages
de programmation vous demandent d'être très précis à ce niveau. Une des règles de
syntaxe majeure est que les noms donnés aux choses doivent être constitués d'un seul
mot sans espaces. Autrement dit, digitalWrite() est le nom de quelque chose, plus
précisément le nom d'une fonction préprogrammée (nous reparlerons des fonctions
plus tard). Cette fonction va réaliser une action de changement de l'état d'une broche
de sortie sur la carte Arduino. Non seulement il faut éviter les espaces dans les noms,
mais il faut tenir compte de la différence entre majuscules et minuscules, c'est-à-dire
la casse des lettres. Pour le programme, digitalWrite() n'est pas la même chose que
DigitalWrite() ou Digitalwrite().
Notre fonction digitalWrite() a besoin que vous lui indiquiez quelle broche elle doit
modifier et s'il faut forcer l'état électrique de la broche à l'état haut (HIGH) ou bas (LOW).
Ces deux informations s'appellent des arguments, et ces arguments sont transmis à la
fonction lorsqu'elle est appelée. Les arguments d'une fonction doivent être entourés par
un couple de parenthèses et séparés les uns des autres par une virgule.
Par convention, la parenthèse ouvrante suit immédiatement la dernière lettre du nom
de la fonction. Une autre convention qui facilite la lecture par les humains consiste à
ajouter un espace après chaque virgule séparant deux arguments. Vous pouvez cependant
ajouter plus d'espaces entre les parenthèses si cela vous aide à la lecture.
Notez que lorsqu'une fonction n'a qu'un seul argument, il n'y a aucune virgule.
© 2013 Pearson France – Arduino – Simon Monk
ARDUI__Monk.indb 26
21/03/13 18:05
 
Chapitre 3
Éléments du langage C
27
Vous remarquez que chacune des trois lignes se termine par un signe point-virgule.
Vous pourriez trouver plus logique d'utiliser des points, puisque cela signifie la fin d'une
commande, un peu comme en fin de phrase.
Nous allons découvrir maintenant ce qui se passe lorsque vous transférez le programme
grâce au bouton Téléverser (Upload) de l'ordinateur de développement vers la carte
Arduino, à partir de l'atelier. Nous allons ensuite pouvoir faire quelques essais pratiques
de programmation.
Qu'est-ce qu'un langage de programmation ?
Certains lecteurs seront peut-être surpris de constater que nous avons attendu d'en être
au Chapitre 3 pour définir exactement ce qu'est un langage de programmation, alors
que c'est le sujet de ce livre. Au point où nous en sommes, vous savez déjà reconnaître
un croquis Arduino et avez certainement une idée générale de ce à quoi servent ces
programmes. Nous devons maintenant aller voir plus précisément comment le code
source du langage, c'est-à-dire un ensemble de mots dans un programme d'édition,
finit par se transformer en quelque chose qui agit sur le monde réel, comme allumer
ou éteindre une LED.
La Figure 3.1 montre les grandes étapes de cette chaîne de production qui va de la saisie
du code source dans l'atelier IDE Arduino jusqu'à l'exécution du programme sur la carte.
Figure 3.1
Du code source
à la carte.
Lorsque vous utilisez le bouton de téléversement de votre atelier Arduino, vous
déclenchez une série d'événements dont les deux dernières étapes correspondent à
l'installation du programme exécutable sur la carte Arduino et à son démarrage. Notez
qu'il ne s'agit pas de simplement transférer les instructions de code source que vous
avez saisies vers la carte Arduino.
La première étape de cette chaîne se nomme la compilation. Elle consiste à analyser les
instructions de code source que vous avez écrites pour les convertir en séquences de code
© 2013 Pearson France – Arduino – Simon Monk
ARDUI__Monk.indb 27
21/03/13 18:05
 
28
Arduino : les bases de la programmation
machine, c'est-à-dire le langage binaire que peut comprendre le processeur de la carte
Arduino. Si vous utilisez le bouton triangulaire de vérification dans l'atelier Arduino,
vous demandez de faire une compilation du programme C sans faire suivre cette action
du transfert du code résultant vers la carte. La compilation du code permet en effet de
vérifier que la totalité du contenu est conforme aux règles de syntaxe du langage C.
Si vous saisissez les deux mots Ciao Bella alors que la zone d'édition de l'atelier est vide,
puis utilisez le bouton Vérifier, vous obtiendrez les résultats de la Figure 3.2. Observez
notamment le bandeau inférieur de la fenêtre.
Figure 3.2
La preuve qu'Arduino
ne comprend pas
l'italien.
L'atelier Arduino a essayé de compiler les deux mots "Ciao Bella". Malgré ses origines
italiennes, il n'a rien compris à ce que vous avez tenté de lui dire. Ce texte n'est en
effet pas du langage C. Voilà pourquoi vous voyez apparaître dans le bas de l'écran un
message un peu obscur : "'Ciao' does not name a type." Cela signifie que ce que vous
avez écrit ne convient pas du tout.
© 2013 Pearson France – Arduino – Simon Monk
ARDUI__Monk.indb 28
21/03/13 18:05
Chapitre 3
 
Éléments du langage C
29
Prenons un autre exemple. Voyons si nous pouvons compiler un croquis totalement
vide (voir Figure 3.3).
Figure 3.3
Un programme sans
setup() ni loop().
Cette fois-ci, le compilateur vous informe dans le bandeau inférieur que votre croquis
ne contient aucune fonction nommée setup() ou loop(). Si vous vous souvenez de
l'exemple Blink du Chapitre 2, vous savez qu'il fallait insérer un minimum de code
standard (boilerplate) avant de pouvoir ajouter vos instructions spécifiques dans le
programme. Dans la programmation pour Arduino, le code générique prend la forme de
deux fonctions qui doivent toujours être présentes dans un croquis et porter exactement
les noms setup() et loop().
Nous décrirons en détail les fonctions dans le chapitre suivant du livre. Pour l'instant,
contentez-vous d'accepter le fait qu'il est nécessaire de toujours insérer ce code minimal
pour que le compilateur accepte de compiler votre croquis (voir Figure 3.4).
© 2013 Pearson France – Arduino – Simon Monk
ARDUI__Monk.indb 29
21/03/13 18:05
 
30
Arduino : les bases de la programmation
Figure 3.4
Exemple de croquis
pouvant être compilé,
bien qu'il soit vide.
L'atelier Arduino reconnaît vos efforts de rédaction et accepte la compilation. Il vous
le confirme par le message "Compilation terminée." suivi d'un rapport sur la taille du
croquis : 466 octets, par exemple. Le message vous indique également que la taille
maximale du programme est de 32 256 octets, ce qui vous laisse de la marge pour faire
grossir votre croquis.
Examinons de plus près ces six lignes de code initiales qui doivent être présentes dans
tous vos croquis. Nous y trouvons de nouveaux éléments, et notamment le mot void
ainsi que des paires d'accolades. Voyons d'abord à quoi sert le mot void.
La première ligne, void setup(), signifie que vous définissez une fonction portant le
nom setup(). Dans Arduino, certaines fonctions sont préprogrammées, et c'est le cas
de digitalWrite() et de delay(), mais vous pouvez définir vos propres fonctions. Les
deux fonctions setup() et loop() sont particulières : leur nom est immuable, mais c'est
à vous de définir leur contenu dans chacun de vos croquis.
Sachez que vous n'allez pas appeler ces deux fonctions spéciales setup() et loop()
comme vous le feriez pour digitalWrite(). Vous devez définir les deux fonctions, mais
© 2013 Pearson France – Arduino – Simon Monk
ARDUI__Monk.indb 30
21/03/13 18:05
Chapitre 3
 
Éléments du langage C
31
c'est le système Arduino qui va les appeler. Ce n'est pas un concept facile à comprendre,
mais vous pouvez le comparer à une définition de termes dans un document juridique.
Souvent, les documents juridiques contiennent une section de définition des termes
dans laquelle vous pourriez trouver quelque chose dans le style suivant :
Définitions :
Auteur : Par auteur est désigné la ou les personnes qui sont responsables
de la création du livre.
Une fois qu'un terme est ainsi défini, les avocats peuvent citer le mot "auteur" comme un
raccourci de l'expression "la ou les personnes responsables de la création d'un livre", ce
qui permet de rendre les documents plus courts et plus lisibles. Une fonction équivaut
un peu à une telle définition. Vous définissez la fonction que vous allez ensuite utiliser
ailleurs dans votre croquis ou que le système va appeler.
Revenons au mot void (vide) qui est utilisé en préfixe des deux fonctions. Il signifie
qu'elles ne renvoient aucune valeur, alors que c'est le cas de nombreuses autres fonctions.
Pour dire qu'il n'y aura pas de valeur renvoyée, nous utilisons ce mot réservé void.
Imaginez une fonction qui s'appelle sinus() pour calculer le sinus d'une valeur. Cette
fonction devrait par définition renvoyer une valeur (le résultat de son calcul). Cette valeur
serait le sinus de l'angle qui aura été transmis en argument dans l'appel à la fonction.
De même que l'on utilise des mots pour définir un terme dans un document juridique,
nous utilisons le langage C pour définir des fonctions qui sont ensuite appelées à d'autres
endroits du programme en langage C.
Le mot-clé void est suivi d'un espace, puis du nom de la fonction, puis d'un couple de
parenthèses délimitant la liste des paramètres. Dans les deux cas de notre exemple, il
n'y a aucun paramètre, mais les parenthèses doivent cependant être présentes.
INFO
N.d.T. : Vous rencontrerez les deux termes "paramètre" et "argument". Un paramètre est la
variable théorique définie dans la définition de la fonction. Un argument est une valeur réelle
transmise à la place du paramètre lors d'un appel à la fonction.
Vous remarquez en revanche qu'il n'y a pas de signe point-virgule après la parenthèse
fermante. En effet, il ne s'agit ici que de la première ligne du bloc de définition d'une
fonction. Ce n'est pas un appel à la fonction. C'est entre les accolades que viendront se
placer les instructions à exécuter lorsque la fonction sera appelée.
Toutes les actions que va réaliser la fonction doivent être placées entre ces accolades.
Les accolades et les instructions constituent le corps de la fonction ou son bloc de code.
Nous reviendrons sur ce concept plus tard.
© 2013 Pearson France – Arduino – Simon Monk
ARDUI__Monk.indb 31
21/03/13 18:05
 
32
Arduino : les bases de la programmation
Vous remarquez que bien qu'il faille définir les deux fonctions setup() et loop(), il n'est
pas obligatoire d'insérer des instructions dans leur corps. Cela dit, si les deux fonctions
sont vides, votre croquis n'a aucun effet.
Le retour de Blink !
La raison pour laquelle tout programme Arduino rend obligatoire la présence des deux
fonctions nommées setup() et loop() est que cela permet de séparer les actions qui ne
doivent être réalisées qu'une fois au démarrage du croquis de celles qui doivent pouvoir
se dérouler plusieurs fois.
La fonction nommée setup() n'est exécutée qu'une fois au début du démarrage du
croquis. Nous allons ajouter quelques instructions dans son corps pour faire clignoter
la LED de la carte. Ajoutez les deux lignes d'instruction suivantes dans le corps de la
fonction setup() du croquis précédent, puis demandez le transfert du programme vers
la carte par téléversement :
void setup()
{
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
}
void loop()
{
}
Les deux instructions ajoutées dans setup() correspondent à deux appels de fonctions
prédéfinies qui sont pinMode() et digitalWrite(). Nous connaissons déjà digitalWrite()
mais pas pinMode(). Cette fonction permet de configurer une broche pour qu'elle soit
une broche d'entrée ou de sortie. Pour allumer la LED, nous avons donc deux étapes à
parcourir. D'abord, nous définissons la broche 13 comme devant être utilisée comme
sortie, puis nous forçons cette sortie à l'état haut (HIGH).
Si vous lancez l'exécution de ce croquis, vous verrez la LED s'allumer sur la carte et
rester allumée. Ce n'est pas très intéressant. Essayons de la faire clignoter en provoquant
un allumage suivi d'une extinction dans la boucle loop() et non dans la fonction de
démarrage setup().
Vous pouvez laisser l'appel à pinMode() dans la fonction setup() parce qu'il n'est nécessaire qu'une fois. Cela fonctionnerait toujours si nous déplacions l'appel dans la boucle,
mais il serait inutile de répéter cette action de préparation. Prenez la bonne habitude
de ne faire les choses qu'une fois si cela suffit.
Modifiez le croquis pour qu'il ressemble à celui-ci :
void setup()
{
pinMode(13, OUTPUT);
© 2013 Pearson France – Arduino – Simon Monk
ARDUI__Monk.indb 32
21/03/13 18:05
 
Chapitre 3
Éléments du langage C
33
}
void loop()
{
digitalWrite(13, HIGH);
delay(500);
digitalWrite(13, LOW);
}
Essayez le croquis. Le résultat va peut-être vous étonner. La LED semble rester allumée
en permanence. Comment est-ce possible ?
Déroulons mentalement la logique du croquis ligne par ligne :
1. Nous exécutons setup() pour forcer la broche 13 à être une sortie.
2. Nous entrons dans loop() et forçons la broche 13 au niveau haut (LED allumée).
3. Nous provoquons une pause d'une demi-seconde.
4. Nous forçons la broche 13 à l'état bas (LED éteinte).
5. Nous revenons en début de boucle, c'est-à-dire à l'étape 2, et nous redonnons à la
broche 13 l'état haut (LED allumée).
Le problème se situe entre les étapes 4 et 5. La LED est effectivement éteinte, mais elle
est rallumée immédiatement après. L'intervalle entre les deux actions est si réduit que
la LED semble rester allumée en permanence.
Le microcontrôleur qui équipe la carte Arduino peut réaliser 16 millions d'instructions
machine par seconde. Cela ne revient pas à 16 millions d'instructions en langage C, mais
cela reste très rapide. Voilà pourquoi notre LED s'éteint bien, mais seulement pendant
quelques millionièmes de seconde.
Pour résoudre ce problème, il nous suffit d'ajouter une autre pause après avoir éteint la
LED. Voici comment modifier votre code source :
// sketch_03_01
void setup()
{
pinMode(13, OUTPUT);
}
void loop()
{
digitalWrite(13, HIGH);
delay(500);
digitalWrite(13, LOW);
delay(500);
}
Si vous faites un nouvel essai, vous devriez voir votre LED clignoter joyeusement une
fois par seconde.
© 2013 Pearson France – Arduino – Simon Monk
ARDUI__Monk.indb 33
21/03/13 18:05
 
34
Arduino : les bases de la programmation
Vous aurez remarqué un commentaire en début de listing qui indique "// sketch_03_01".
Pour vous éviter de devoir tout ressaisir, nous mettons à disposition sur le site compagnon
du livre tous les croquis comportant un tel commentaire en en-tête. Vous pouvez les
télécharger en version anglaise à l'adresse http://www.arduinobook.com. (N.d.T. :
Certains sont fournis en version française sur le site www.pearson.fr.)
Variables
Dans notre exemple, nous nous servons de la broche 13 et nous y faisons référence en
trois endroits différents du programme. Pour travailler avec une autre broche, il faudrait
donc modifier le numéro de broche à trois endroits. De même, pour modifier la vitesse
de clignotement (utilisée comme argument de la fonction delay()), il faudrait modifier
la valeur 500 à deux endroits différents.
Une variable est une sorte de symbole pour un nom ou pour une valeur numérique. Elle
permet bien plus de choses, mais servons-nous en déjà en tant que symbole d'une valeur.
Lorsque vous définissez une variable en langage C, vous devez d'abord indiquer le type
de données que la variable va contenir. Ici, nous avons besoin de variables correspondant
à des valeurs numériques entières qui s'appellent en C des valeurs de type int (integer).
Pour définir une variable que nous choisissons de nommer brocheLED et possédant la
valeur 13, nous écririons la déclaration suivante :
int brocheLED 13;
La variable brocheLED est un nom et les règles données plus haut pour les noms des
fonctions s'appliquent. Vous ne pouvez donc pas utiliser d'espaces dans le nom, ni
de lettres accentuées. Par convention, les programmeurs font débuter leurs noms
de variables par une lettre minuscule et commencent chaque nouveau mot par une
majuscule en collant les mots les uns aux autres. Cette écriture est souvent désignée
sous le terme d'écriture en creux et bosses, ou CamelCase.
Ajoutons donc nos déclarations de variables dans le croquis Blink :
// sketch_03_02
int brocheLED = 13;
int dureePause = 500;
void setup()
{
pinMode(brocheLED, OUTPUT);
}
void loop()
{
digitalWrite(brocheLED, HIGH);
delay(dureePause);
digitalWrite(brocheLED, LOW);
delay(dureePause);
}
© 2013 Pearson France – Arduino – Simon Monk
ARDUI__Monk.indb 34
21/03/13 18:05
 
Chapitre 3
Éléments du langage C
35
Vous remarquez que nous avons déclaré une seconde variable nommée dureePause.
À tous les endroits dans le croquis où nous utilisions la valeur 13, nous indiquons
dorénavant le nom brocheLED. De même, là où nous utilisions la valeur 500 (une valeur
littérale) nous indiquons dorénavant le nom de la variable dureePause.
Dorénavant, pour faire clignoter la LED plus rapidement, il suffit de changer à un endroit
la valeur affectée à la variable dureePause. Essayez par exemple de réduire cette valeur
à 100 et relancez le croquis sur la carte Arduino.
Nous avons dit que vous pouviez faire bien d'autres choses avec des variables. Voyons
comment modifier le croquis de sorte que le clignotement commence à fréquence élevée,
puis ralentisse de plus en plus, comme si la carte Arduino commençait à se lasser. Pour
y parvenir, il nous suffit d'ajouter une petite valeur à la valeur actuelle de dureePause
à chaque tour de la boucle.
Modifiez donc le croquis en ajoutant une ligne tout à la fin du corps de la fonction
loop(), comme présenté dans l'extrait suivant. Transférez le programme modifié sur
la carte Arduino. Appuyez sur le bouton poussoir Reset de la carte et observez l'effet
de ralentissement du clignotement.
// sketch_03_03
int brocheLED = 13;
int dureePause = 100;
void setup()
{
pinMode(brocheLED, OUTPUT);
}
void loop()
{
digitalWrite(brocheLED, HIGH);
delay(dureePause);
digitalWrite(brocheLED, LOW);
delay(dureePause);
dureePause = dureePause + 100;
}
Voici que votre carte Arduino fait de l'arithmétique. À chaque appel à la fonction loop(),
nous provoquons un clignotement de la LED puis nous ajoutons 100 à la valeur de la
variable dureePause. Nous reviendrons un peu plus loin sur les opérations arithmétiques. Voyons d'abord comment mieux observer ce que fait la carte Arduino qu'avec
un simple clignotement de LED.
© 2013 Pearson France – Arduino – Simon Monk
ARDUI__Monk.indb 35
21/03/13 18:05

Documents pareils

disponible en PDF

disponible en PDF numériques ------//digitalWrite (bpRouge,HIGH); // Rappel au + activé sur la broche bpRouge configurée en entrée //digitalWrite (bpBleu,HIGH); // Rappel au + activé sur la broche bpBleu configurée ...

Plus en détail

1 Notions de base

1 Notions de base La led L1 que nous voulons utiliser est sur la pin 4 : //LcCligno1.ino clignoter la led L1 pin 4 void setup() { pinMode (4,1);

Plus en détail

Initiation à la mise en oeuvre matérielle et

Initiation à la mise en oeuvre matérielle et programmes. Elle peut être connectée à 13 entrées ou sorties numériques, dont 3 PWM (pouvant donner 3 sorties analogiques : cf http://fr.wikipedia.org/wiki/PWM) et 6 entrées analogiques convertissa...

Plus en détail