Mis à jour le mercredi 30 novembre 2016
  • 15 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

Vous pouvez obtenir un certificat de réussite à l'issue de ce cours.

J'ai tout compris !

Utilisez les constantes, les variables, les conditions et le moniteur série

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Bon, J'espère que vous avez fait le plein de sommeil, d'énergie, d'attention, bref que vous êtes à bloc ! Ce qui s'annonce dans ce chapitre va vous titiller un peu les méninges. Assurez-vous donc que vous avez bien compris le chapitre précédent, et en avant pour de nouvelles notions, nouveaux mots de vocabulaire et nouveaux exercices de réflexion !

L'Arduino permet d'aller assez loin dans la programmation. Pour ceux qui développent, la manipulation de données (stockage, transformation, portée) n'est pas différente. En revanche, la communication entre l'Arduino et le PC ou l'Arduino et les montages, apporte quelques nouveautés (nouvelles fonctions, nouvelles constantes...).

Nous aborderons dans ce chapitre la notion de variables et de constantes, indispensable à la programmation. Nous verrons comment les créer, les manipuler, et surtout leur intérêt dans un programme.

Nous aborderons aussi le moniteur série de l'IDE (logiciel de programmation de l'Arduino), pour le moment dans son utilisation d'affichage des données provenant de la carte Arduino. Vous verrez qu'elle est souvent d'une grande utilité.

Enfin nous finirons par la conception d'un programme (codé de deux façons différentes), qui ne nécessite pas de montages électroniques particuliers.

J'en profiterai pour vous apporter  la notion de condition qui est d'une utilisation fondamentale dans toute programmation.

Allez, on jette son chewing-gum, on s'installe confortablement et on envoie la purée !

Constantes et variables

Constantes

Dans le chapitre précédent, nous avons construit un programme qui permet de faire clignoter la LED 13.  Certains des mots clés étaient colorés de bleu :  HIGH ,  LOW ,  OUTPUT . Ce sont des constantes. Pour nous, humains, ces trois mots sont intelligibles, mais pour la machine, ils ne veulent rien dire. En revanche, lors de la compilation (voir chapitre précédent) l'IDE transforme ces mots en nombres que le microcontrôleur va comprendre.

Quels sont ces nombres ? Et pourquoi on ne les met pas directement dans le code ?

Dans le cas deHIGH etLOW, on peut remplacer les mots respectivement par 1 et 0 (faites l'essai) et ça fonctionne. En revanche pourOUTPUT je n'ai pas d'idée du nombre correspondant, et vous savez quoi ? On s'en moque. En effet, c'est tout l'intérêt des constantes ! Le mot-clé correspond à un nombre dont nous ignorons tout, mais nous connaissons l'utilisation du mot clé. L'IDE se chargera de la traduction. Pour nous le programme est clair, et pour l'Arduino aussi. Tout le monde est gagnant.

Alors les constantes en bleu ( LOW ,  HIGH ,  OUTPUT ) sont réservées à l'IDE. Nous pouvons les utiliser mais pas les définir. Mais là où ça devient intéressant, c'est qu'on peut se créer ses propres constantes.

Vous avez remarqué que nous avons écrit le nombre 13 trois fois au total dans le programme. Ce nombre dans notre programme n'a pas de raison de changer. Il va être constant pendant toute l'exécution. Nous pourrions donc en faire une constante ! Et nous allons le faire !!

Reprenez le programme et modifiez le comme suit (je modifie les commentaires) :

// on définit la constante en donnant un nom et un nombre.
const int CONNEXION=13;

void setup()
{
    // on l'utilise en écrivant juste son nom
    pinMode(CONNEXION,OUTPUT);
}
void loop()
{
    // là encore.
    digitalWrite(CONNEXION,HIGH);
    delay(1000);
    // et là encore.
    digitalWrite(CONNEXION,LOW);
    delay(1000);
}

Voici le rendu sur l'IDE :

Déclaration et utilisation d'une constante
Déclaration et utilisation d'une constante

Bon plusieurs points à signaler :

  • On écrit le nom des constantes en majuscules (ça fait partie des conventions de programmation) ça permet de savoir que ce sont justement des constantes.

  • Le nom de notre constante (CONNEXION) ne s'écrit pas en bleu car elle n'est pas une constante réservée à l'IDE mais bien une à nous, qu'on a fait tout seul comme un grand !

  • La déclaration d'une constante (c'est-à-dire sa construction) commence par le mot clé  const  suivi du type de constante (dans notre cas la constante CONNEXION est de type “int”, qui signifie nombre entier - nous y reviendrons plus loin).

  • La déclaration d'une constante est toujours de la forme : 

    const type NOMDELACONSTANTE=valeur;

Alors comment ça marche pour l'IDE ? Et bien dans le cas de constantes, il ne va rien stocker dans la mémoire de l'Arduino. Au moment de la compilation (transformation du programme en langage machine) il va remplacer chaque mot CONNEXION par la valeur 13. C'est la raison pour laquelle une constante n'est pas modifiable, car à aucun moment le microcontrôleur sait qu'on en a utilisé une.

Alors je vois à vos yeux sceptiques plissés et interrogateurs que vous vous demandez pourquoi on s'embête à ajouter une ligne de code et remplacer le nombre 13 (2 caractères) par le mot CONNEXION (9 caractères) pour obtenir le même résultat ?

Et bien deux raisons vont me permettre de transformer ces visages fermés en visages auréolés de compréhension...

Tout d'abord, l'utilisation de constantes facilite la lecture du programme : rien ne ressemble plus à 13 que 13 alors que CONNEXION est plus parlant en terme de contexte. Cela nous permet donc de voir plus facilement quand on a utilisé la valeur de la constante ou quand il s’agit d’autre chose.

La seconde raison est le gain de temps. Ici notre programme est minuscule, et nous perdons en effet du temps à changer 13 en CONNEXION. Imaginez maintenant un programme de 300 lignes (ça reste faible ;)) qui contient 127 fois le nombre 13, dont 56 fois liés à la valeur de la connexion et le reste lié à des valeurs utilisées à d'autres fins. Et là vous vous dites : je préfèrerais utiliser finalement la connexion 7. Vous allez devoir tout remplacer à la main (l'outil de recherche/remplace ne ferait pas le bon travail car il remplacerait tout) et vous en aurez pour un bout de temps et bien des risques d'erreur. Alors qu'avec le principe de définition des constantes, vous n'aurez qu'à modifier une seule ligne : celle de la déclaration de la constante en début de programme, l'IDE se chargera du reste !

On s'arrête là pour le moment en ce qui concerne les constantes. Passons aux variables.

Variables

Alors si les constantes sont constantes, c’est qu’elles ne varient pas pendant l’exécution du programme, donc vous voyez où je veux en venir... ben oui ! Les variables elles, peuvent varier, c'est à dire changer de valeur au cours du programme. C'est hyper-méga pratique !!!

La déclaration de variable peut se faire de différentes façons. Pour des raisons de bonnes habitudes et de lisibilité, nous allons utiliser une méthode en deux temps. Je la trouve plus utile dans le cas où vous voudriez un jour programmer sur autre chose que l'Arduino et en plus elle est moins coûteuse en espace mémoire (ce qui, vous le verrez est important pour les microcontrôleurs).

  • Premier temps : je dis à l'IDE que je réserve une place en mémoire pour une variable et je lui donne un nom (cette opération est faite une seule fois dans le programme).

  • Autres temps : je dis à l'IDE d'affecter une valeur à la variable (cette opération peut être faite à tout moment dans le programme).

Comment faire ? Voyez plutôt dans ce bout de code :

int nombreDeBilles;//on déclare une varialbe de type int nommée nombreDeBilles
nombreDeBilles=4;//on affecte le nombre 4 à la variable nombreDeBilles
nombreDeBilles=8;//on affecte le nombre 8 à la variable nombreDeBilles

Dans le cas de variables, l'IDE ne procède pas comme pour les constantes. Lors de la déclaration, il va traduire en langage machine qu'il faut réserver une place de la bonne dimension (c'est le type) dans la mémoire vive (c'est-à-dire modifiable) de l'Arduino. Puis, lors des modifications de variables, l'Arduino ira déposer dans sa mémoire, à la place prévue, la nouvelle valeur, qui à chaque fois remplacera la précédente.

Pour initialiser une variable, on peut utiliser la boucle dusetup() ou un autre endroit dans le programme. L'important c'est que la variable soit initialisée avant son utilisation.

Voici un exemple de code :

int tempsDePause;// déclaration de la variable tempsDePause
void setup()
{
    tempsDePause=100; // initialisation de la valeur de tempsDePause à 100
}

void loop()
{
    // utilisation de la variable tempsDePause dans un delay()
    delay (tempsDePause);
    // changement de la valeur de tempsDePause à 200
    tempsDePause=200;
}

Si vous téléversez ce programme, il va tourner et modifier la valeur de la variabletempsDePause  comme vous lui avez demandé, mais il ne vous affichera rien du tout. Nous verrons plus loin comment faire pour qu’un programme affiche des valeurs à l’écran. Mais avant cela un petit point sur le type des données.

Le typage des variables et constantes

Cette notion est un peu rébarbative, mais c'est comme le dentiste, faut y passer.

Le typage est obligatoire lorsqu'on définit une variable ou une constante. Dans certains langages (comme le Python par exemple), il n'est pas nécessaire car le compilateur se chargera de le faire et l'exécution du programme s'occupera des modifications éventuelles. Mais pour l'Arduino (et le langage C) on n'a pas le choix.

Chaque type de variable ne prend pas le même espace en mémoire et ne sera pas traité de façon équivalente lors de l'exécution. Je ne vais pas vous faire un cours pesant sur la mémoire des processeurs (bien des cours sur ce site le font très bien) mais je vais vous en faire un survol.

La mémoire d'un processeur (gros ou petit) est un ensemble d'espaces de même taille qui se suivent (virtuellement sur une même ligne). Et comme ils se suivent on peut les retrouver grâce à leur position sur cette ligne virtuelle. Leur taille est d'un byte, c'est-à-dire 8 bits. Le bit (non Lukas, je n'ai pas fait d'erreur !) c'est l'unité de base en informatique et ça vaut 0 ou 1. Donc on imagine des 0 et des 1 qui se suivent, formant une ligne qui s'étend sur des kilomètres, par groupes de 8 bits. Genre :

La mémoire d'un processeur
La mémoire d'un processeur

Et bien chaque type de variable (un peu comme les bateaux à la bataille navale) prend un nombre de tranches différent pour être stocké. La taille minimum est de 1 tranche (un byte).Quand on utilise une variable de taille 3 tranches, le processeur va cherche sur la ligne à quelle tranche commence le stockage (c'est l'adresse) et va récupérer le contenu des trois tranches qui se suivent à partir de cette adresse et les transformer en valeur. Donc si le typage n'existait pas pour préciser l’espace pris en mémoire par la variable, on récupérerait soit trop soit pas assez d'infos pour la valeur attendue.

Je vous donne quelques types et leur taille pour commencer (il en existe beaucoup plus) ainsi que ce qu'ils peuvent stocker :

type

taille en byte

valeurs stockées

boolean

1

true ou false

char

1

un caractère ou un entier entre -128 et 127

unsigned char

1

un entier entre 0 et 255

byte

1

un entier entre 0 et 255

int

2

un entier entre -32768 et 32767

unsigned int

2

un entier entre 0 et 65535

float

4

un décimal, précis à 7 chiffres après la virgule

"Et, je te le dis, je n'irai pas plus loin." (J.Brel)

Ça nous suffit largement pour le moment ! Vous verrez qu'avec ces types de variables on peut faire bien des choses !

Petit point sur les conventions des noms de variables

Nous l'avons vu pour les constantes, il est de bon ton de tout mettre en MAJUSCULES.

Pour les variables il existe une façon agréable, lisible et surtout conventionnelle de les nommer : on écrit le nom tout attaché et on met des majuscules à chaque mot sauf au premier. Voici un exemple de nom de variable :

int valeurDuContactAvantDroit;

Au début on a tendance à vouloir mettre des noms de variables courts (genre une lettre) parce qu'on a la flemme d'écrire. Mais très vite on s'aperçoit que des noms de variables clairs (presque des phrases) facilitent la lecture du programme et sa compréhension. Habituez-vous très vite à cette façon de faire, vous gagnerez par la suite beaucoup de temps. D'autant que la taille du nom d'une variable n'a pas d'influence sur le programme.

Bon, vous savez déclarer des variables, mais pouvez-vous le faire n'importe où dans le programme ?

Portée des variables ou "scope"

Alors... la portée des variables (appelé aussi scope) c'est une façon commode de dire que là où on déclare une variable, c'est là où on va pouvoir l'utiliser et pas ailleurs.

Rappelez-vous que les accolades définissent des blocs de code à exécuter. Et bien si vous définissez une variable dans un bloc de code (donc entre des accolades), elle ne pourra être appelée ou modifiée QUE dans CE bloc de code.

Pour le moment vous ne connaissez que 2 types de blocs de code :

  • setup() (qui s'exécute une fois), et 

  • loop() (qui s'exécute à l'infini).

Vous verrez qu'il en existe bien d'autres.

Une fois que l'on sort des accolades du bloc, la place utilisée par la variable en mémoire est libérée. Ce qui nous laisse la possibilité de l'utiliser pour une autre variable.

Mais dans les exemples précédents, on a déclaré la variable au tout début, donc ni dans le setup(), ni dans la loop() !

Bien joué Callaghan ! Vous venez de mettre le doigt sur une forme de déclaration qui est très utilisée avec l'Arduino (et très déconseillée dans les autres types de programmation) qu'on appelle la déclaration de variables globales.

Une variable globale est accessible (et modifiable) depuis n'importe quel endroit du programme. C'est pratique, mais ça nécessite de faire attention à son nom pour bien la repérer et surtout, une variable globale ne libère jamais sa place occupée en mémoire. L'utilisation excessive de variables globales peut parfois gêner l'exécution du programme en particulier pour l'Arduino dont la place mémoire est très restreinte.

Je crois que vous avez votre compte avec les variables, les constantes et la mémoire pour le moment. Nous allons maintenant nous amuser un peu avec.

Le moniteur série

Bon avant de commencer ce point, je vais me prendre un petit café... je vous en offre un ? (oui Lukas, j'ai aussi du tilleul menthe, mais je ne comprendrai jamais pourquoi vous y trempez votre sandwich rillettes et saumon !)

Grâce à la magie de l'espace temps, me voici déjà de retour et prêt à vous nourrir de savoir !

La console (ou moniteur série) n'est pas faite pour faire tourner des jeux comme  GOW, GTA,  AC ou FIFA, n'en déplaise à certains (Lukas puisque je vous regarde, il vous reste un morceau de saumon sous la narine droite). Non, la console, même si on peut s'amuser avec, est un moyen simple d'afficher des infos provenant de votre Arduino.

Comme vous l'avez sûrement remarqué, l'Arduino de base n'a pas d'écran. On peut lui en ajouter un, nous aurons l'occasion de le voir plus tard, mais en attendant, on ne peut rien afficher. C'est là qu'entre en scène le moniteur série, qui est une fenêtre que l'on peut ouvrir en cliquant sur la loupe du logiciel Arduino. Cette fenêtre reçoit et envoie des infos sous forme de séries de bytes aux ports concernés. Donc grâce au moniteur série, l'Arduino peut (à condition d'être connecté à un PC) envoyer des infos à l'ordinateur qui va pouvoir les afficher en temps réel. 

Pour ce faire on fait appel à une bibliothèque spéciale, déjà incluse dans l'IDE : la bibliothèque Serial.

Pour utiliser la possibilité de communication entre l'ordinateur et l'Arduino, on procède en deux étapes :

  1. On initialise la communication (ça se fait dans lesetup()).

  2. On communique (ça se fait souvent dans laloop() mais possible dans lesetup()). 

Dans le programme suivant, vous allez découvrir de nouveaux mots-clés de communication commeSerial.begin,  Serial.println... Ne vous inquiétez pas, on y arrive ! Pour l'instant, contentez-vous de lire les commentaires qui vous permettront de comprendre le principal. 

void setup()
{
    Serial.begin(9600);// initialisation de la communication
    Serial.println("Communication initialisée");// envoi d'un message
}
void loop()
{
    Serial.println("Je suis dans la boucle !");//envoi d'un autre message
}

Écrivez-le, téléversez-le. Si tout va bien, rien ne se passe, sauf que la diode TX de votre Arduino est allumée.

Pour comprendre le principe d'utilisation d'une bibliothèque :

  • Les codes liés à une bibliothèque commencent tous par son nom (ici Serial) suivi d'un point et de la commande.

  • La commande est spécifique à la bibliothèque utilisée.

  • La liste des commandes liées à une bibliothèque est ce qu'on nomme la documentation. Elle est souvent liée à la bibliothèque.

  • Pour la bibliothèque Serial, la documentation et les exemples se trouvent sur le site officiel de l'Arduino, dans le menu learning/reference. Je vous donne le lien direct.

Bien, maintenant, cliquez sur le bouton d'affichage du moniteur.

Bouton d'affichage du moniteur
Bouton d'affichage du moniteur

Une fenêtre s'ouvre et là c'est la folie ! Ça défile vers le bas, on a l'impression de rien pouvoir lire, on se demande comment ça s'arrête et si ça ne va pas exploser !

Non, en fait tout est normal. La diode TX est allumée (en fait elle clignote très vite) car elle envoie les messages de l'Arduino vers l'ordinateur. L'IDE les reçoit et les affiche les uns à la suite des autres, sans arrêt. C'est clair que la vitesse d'écriture ferait tomber dans les pommes un moine copiste du moyen-âge. Et encore c'est assez lent car on a le temps de le voir.

 Que diriez-vous d'un petit exercice ?

Je vous propose de modifier ce programme pour que le message dans la boucle ne soit envoyé que toutes les 2 secondes.

Si vous avez réussi, vous remarquerez que la diode TX ne clignote qu'à l'envoi du message.

Vérifiez la solution ! 

Avant de nous lancer dans des exercices plus conséquents, vous allez avoir besoin de savoir certaines choses sur le moniteur série :

  • Le moniteur série utilise les connexions 0 et 1 de l'Arduino (0 pour la diode RX et 1 pour la diode TX lors d'une utilisation en communication). Donc si on utilise le port série, il ne faut pas utiliser les connexions 0 et 1 pour d'autres choses dans votre projet.

  • L'affichage des caractères accentués ou spéciaux n'est pas pris en compte (vous l'avez peut-être remarqué lors de l'affichage du message "communication initialisée" qui donne un résultat bizarre), il faudra donc vous en passer.

  • La vitesse de communication entre Arduino et l’ordinateur peut prendre d’autres valeurs que 9600 bauds. Vous trouverez ces valeurs sur le site officiel avec ce lien. 9600 est la valeur généralement utilisée.

  • Si vous appuyez sur le bouton reset de l'Arduino, cela n'effacera pas les messages précédents affichés sur le moniteur. Pour lancer le moniteur, ça ne se fait pas automatiquement : il vous faut appuyer sur le symbole de la loupe que l'on a vu plus haut. Une fois lancé, le programme de l'Arduino recommencera alors du début. 

(Je suis surpris Lukas de ne pas vous entendre sortir une de vos blagues habituelles...)

Bon, vous êtes fins prêts pour quelques exercices à base de moniteur, de constantes et de variables !

Programme "Hello Arduino World !"

Ceux qui ont déjà appris un langage de programmation savent que l'exemple de base, pour chaque langage, consiste à afficher un "bonjour au monde" (Je me suis toujours demandé d'ailleurs si ce n'est pas une thérapie pour les développeurs asociaux que nous sommes plus ou moins, afin de les rassurer sur le fait qu'il ne sont pas seuls). Nous n'échapperons (rouge) pas à la règle et nous allons nous aussi réaliser ce programme, enfin c'est plutôt vous qui allez réaliser ce programme.

Ce que vous devez obtenir : à l'ouverture du moniteur, un message qui affiche sur trois lignes "Hello Arduino World !" avec un mot par ligne (le point d'exclamation avec le dernier mot). Le message ne doit pas se répéter à l'infini.

Commencez en cliquant sur "nouveau" (3ème bouton). L'étendue de vos connaissances vous permet de réaliser seul(e) ce programme. Il va peut-être vous falloir faire deux ou trois tests et quelques débuggages (néologisme qui est assez clair). Cet exercice n'a d'intérêt que si vous arrivez au bout qu'à la force seule de votre intelligence et vos connaissances liées.

Allez au boulot !

Correction :

//Programme hello world
void setup()
{
    //initialisation de la communication
    Serial.begin(9600);
    //affichage du texte
    Serial.println("Hello");
    Serial.println("Arduino");
    Serial.println("World !");
}
void loop()
{
    
}

Vous remarquerez que l'instructionSerial.println()  affiche le texte entre guillemets et retourne à la ligne. Modifiez le programme en utilisant l'instructionSerial.print()  donc en enlevant 'ln' à la fin. Vous verrez que les mots se collent les uns aux autres. On retient donc que :

  • Serial.println()  : affiche avec retour à la ligne

  • Serial.print()  : affiche sans retour à la ligne

Bien, mais le vrai objectif de mon exercice est dans ce qui suit. Je veux obtenir le même résultat, mais en mettant les instructions d'affichages dans laloop(). Pour pouvoir le réaliser, il vous faut apprendre un nouveau concept : la condition.

La condition

La condition est un test que va réaliser le programme en se posant une question. S'il peut y répondre 'vrai' alors il exécute un bloc d'action (qui sera mis entre accolades), sinon il ne l'exécute pas.

voici le pseudo code correspondant :

debut du programme
si (test)
{
    ce code s'exécute si on peut répondre vrai au test
}
le programme continue

   Et voici une représentation graphique :

Représentation graphique d'un test
Représentation graphique d'une condition

Dans notre programme “Hello Arduino world!”, nous allons ajouter un test pour vérifier si le message a bien été affiché sur la console une fois. Si oui, on ne l'affiche plus.

Voici donc le code correspondant :

int affichageFait;// déclaration de la variable

void setup()
{
    Serial.begin(9600);
    affichageFait=0;//initialisation de la variable
}

void loop()
{
    if (affichageFait==0)
    {
        //ce code n'est exécuté que si la condition est vérifiée
        Serial.println("Hello");
        Serial.println("Arduino");
        Serial.println("World !");
        affichageFait=1;//on passe la variable à 1 pour ne plus exécuter le code
    }
}

Une condition s'écrit donc avec le mot-clé if, puis la condition à tester est mise entre parenthèses, puis le code à exécuter entre accolades :

if (condition) { code à exécuter }

Vous remarquerez que pour tester une valeur dans une condition on met un double égal : ==

C'est la façon d'écrire l'égalité dans une condition voici le tableau des signes de condition :

Code

Condition testée

==

égal

>=

supérieur ou égal

<=

inférieur ou égal

>

supérieur

<

inférieur

!=

différent (non égal)

Observez bien le code précédent pour bien intégrer le mécanisme de condition. Vous verrez par la suite qu'on le complétera et qu'on l'utilisera dans bien des cas. À la fin de cette première partie du cours, vous serez bien plus à l'aise avec le principe.

En résumé

Vous avez rencontré dans ce chapitre beaucoup de nouveauté :

  • Les constantes qui remplacent des valeurs et ne peuvent pas être modifiées en cours de programme

  • Les variables qui stockent des données et peuvent être modifiées en cours de programme

  • Le typage qui définit la taille prise par les variables ou les constantes en mémoire

  • Le scope qui permet de comprendre où utiliser les variables dans un programme

  • La console qui affiche des informations envoyées par l'Arduino

  • La bibliothèque Serial, qui facilite les affichages sur la console

  • La condition if (condition){code}  qui permet d'exécuter un code en fonction d'une condition.

Bon c'était dense et assez compliqué sur la fin. Mais vous allez pouvoir vous poser un peu au prochain chapitre pour concevoir deux programmes qui vont vous permettre de mieux asseoir vos connaissances. Il vous révélera aussi un dernier concept avec les boucles, et vous aurez les bases suffisantes pour vous concentrer sur l’électronique dans les chapitres suivants.

Exemple de certificat de réussite
Exemple de certificat de réussite