• 15 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 08/11/2019

Installez la chaîne de développement

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

Pour faire fonctionner notre robot, il est indispensable d'écrire du code. Nous allons voir comment installer la plateforme de programmation. Nous découvrirons également la structure type d’un code Arduino, avec ses constituants et ses éléments du langage.

Ils nous permettront de répondre aux besoins de nos applications robot.

Ce cours est basé sur la philosophie “learning by doing”.  Cependant, un minimum de connaissances techniques sur le langage sont nécessaires pour s’y retrouver dans la galaxie immense des codes. Ne vous laissez toutefois pas impressionner par la longueur de ce chapitre. Si vous ne retenez pas tout, ça n'a pas tant d'importance. La compétence s'acquiert avec la pratique personnelle. Nous vous recommandons donc de parcourir sans trop vous attarder les éléments ci-dessous. En revanche, il vous sera sans doute nécessaire d'y revenir quand vous en éprouverez le besoin, quand vous vous efforcerez de développer votre propre code.

À la fin de ce chapitre, vous serez néanmoins capable d'écrire vos propres lignes de code Arduino !

Installation du logiciel et branchement de la carte sur l'ordinateur

On obtient le logiciel ici.

Prenez garde à installer la version qui correspond bien à votre plateforme : Windows, Linux ou MacOs. L'installation à proprement parler ne devrait pas poser de problème particulier. Une fois le logiciel lancé, l'éditeur s'ouvre et vous obtenez quelque chose comme ça :

plate-forme Arduino
Plateforme Arduino

Dans le menu général "Outils", il faut d'abord sélectionner la carte Arduino. À priori, la carte Uno est sélectionnée par défaut. Comme c'est celle que nous utilisons, on peut laisser ce réglage par défaut. Ensuite, connectez l'ordinateur à la carte à l'aide du câble USB. Il reste alors à choisir le type de connexion entre l'ordinateur et la carte Uno. Toujours dans le menu général "Outils", sélectionnez "Port" et choisissez "/dev/cu.usbmodem1421".

Pour la toute première prise en main logicielle de la plateforme, le plus simple et efficace est de travailler sur un des exemples fournis. Pour ce faire, nous ouvrons dans le sous-menu “02.Digital”, le programme “BlinkWithoutDelay”. Le code correspondant s’affiche. Concrètement, cliquez sur l'icône "Ouvrir" selon l'image ci-dessous :

Les icones principales de l'éditeur Arduino
Les icônes principales de l'éditeur Arduino

Ouvrez dans le sous-menu “02.Digital”, le programme “BlinkWithoutDelay”.

Avant de commenter en détail la structure du code dans le paragraphe suivant, nous allons l'exécuter. Commencez par identifier la séquence de code suivante dans le programme :

// constants won't change:
const long interval = 1000; // interval at which to blink (milliseconds)

C'est en modifiant la valeur numérique, ici 1000, qu'on modifie la fréquence de clignotement de la LED. Essayez avec des valeurs numériques différentes, 200, 2000, etc., pour voir l'effet produit sur l'exécution du code. Pour lancer le code, il suffit d'actionner l'icône (cf. ci-dessus) "Téléverser".

Premier programme de prise en main

Maintenant que vous avez exécuté votre premier code, il faut étudier un peu la structure du langage. Nous recommandons d'identifier les parties de code dans le présent texte sur l'éditeur Arduino, pour profiter des fonctionnalités de la plateforme Arduino. Entre autres, l'éditeur est contextuel, en ce sens qu'il identifie les mots réservés et les affiche dans une couleur qui dépend de leur nature. Le code est ainsi bien plus lisible dans l'éditeur Arduino que ci-dessous.

/*
Blink without Delay
Turns on and off a light emitting diode (LED) connected to a digital pin,
without using the delay() function. This means that other code can run at the
same time without being interrupted by the LED code.
The circuit:
- Use the onboard LED.
- Note: Most Arduinos have an on-board LED you can control. On the UNO, MEGA
and ZERO it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN
is set to the correct LED pin independent of which board is used.
If you want to know what pin the on-board LED is connected to on your
Arduino model, check the Technical Specs of your board at:
https://www.arduino.cc/en/Main/Products
created 2005
by David A. Mellis
modified 8 Feb 2010
by Paul Stoffregen
modified 11 Nov 2013
by Scott Fitzgerald
modified 9 Jan 2017
by Arturo Guadalupi
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
*/
// constants won't change. Used here to set a pin number:
const int ledPin = LED_BUILTIN;// the number of the LED pin
// Variables will change:
int ledState = LOW; // ledState used to set the LED
// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0; // will store last time LED was updated
// constants won't change:
const long interval = 1000; // interval at which to blink (milliseconds)
void setup() {
// set the digital pin as output:
pinMode(ledPin, OUTPUT);
}
void loop() {
// here is where you'd put code that needs to be running all the time.
// check to see if it's time to blink the LED; that is, if the difference
// between the current time and last time you blinked the LED is bigger than
// the interval at which you want to blink the LED.
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa:
if (ledState == LOW) {
ledState = HIGH;
} else {
ledState = LOW;
}
// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);
}
}

Nous allons commenter ce tout premier code pour un premier contact avec le langage. Dans la section suivante, nous compléterons la description du langage Arduino, parce que ce premier programme “BlinkWithoutDelay” ne couvre pas le minimum de ce qu’il faut savoir pour attaquer des projets plus ambitieux.

Les commentaires

Dans le langage Arduino, il y a deux façons d’écrire les commentaires :

  1. Les deux caractères /* marquent le début d’un bloc de commentaires qui peut posséder un nombre de lignes illimité. Pour marquer la fin du bloc, il faudra la suite des deux caractères */.

  2. Les deux caractères // marquent le début d’une ligne, une ligne unique de commentaires. Si on veut que les commentaires figurent sur des lignes consécutives, il faut alors marquer chaque nouvelle ligne avec la suite //.

Dans le petit programme “BlinkWithoutDelay”, on voit d’abord un premier bloc de commentaires qui fait environ 25 lignes. Le bloc est encadré par les deux suites /* en début et */ en fin de bloc.

/*
Blink without Delay
Turns on and off a light emitting diode (LED) connected to a digital pin,
without using the delay() function. This means that other code can run at the
same time without being interrupted by the LED code.
The circuit:
- Use the onboard LED.
- Note: Most Arduinos have an on-board LED you can control. On the UNO, MEGA
and ZERO it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN
is set to the correct LED pin independent of which board is used.
If you want to know what pin the on-board LED is connected to on your
Arduino model, check the Technical Specs of your board at:
https://www.arduino.cc/en/Main/Products
created 2005
by David A. Mellis
modified 8 Feb 2010
by Paul Stoffregen
modified 11 Nov 2013
by Scott Fitzgerald
modified 9 Jan 2017
by Arturo Guadalupi
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
*/

On voit ensuite dans la suite du code régulièrement une, voire quelques lignes de commentaires qui sont toutes marquées par la suite //. Par exemple,

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store

Les constantes et variables

Pour améliorer la lisibilité d’un code, il est utile de définir des constantes, des valeurs fixées une fois pour toutes (en opposition avec les variables) qui sont ensuite utilisées dans le code. Les variables, quant à elles, sont des objets dont les valeurs vont évoluer au cours de l’exécution du code.

On peut définir ce bloc de constantes et variables en tout début de fichier, comme c’est le cas ici dans le programme “BlinkWithoutDelay” selon les lignes qui suivent :

// constants won't change. Used here to set a pin number:
const int ledPin = LED_BUILTIN;// the number of the LED pin
// Variables will change:
int ledState = LOW; // ledState used to set the LED
// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0; // will store last time LED was updated
// constants won't change:
const long interval = 1000; // interval at which to blink (milliseconds)
  • la définition d’une constante commence par le mot-clé “const” qui apparaît en bleu dans l'éditeur Arduino ;

  • Juste après le mot clé“const”, on voit le type, c’est-à-dire la nature de la constante ou de la variable, qui peut être divers selon que les nombres correspondants seront positifs ou positifs et négatifs, entiers, réels, etc.

Le tableau ci-dessous identifie les principaux types :

Les principaux types de constantes et variables

Type

Nature de l'objet

Valeurs extrêmes

Nombre de bits de représentation

Nombre d’octets de représentation

Int

Entier relatif

-32768 à +32767

16

2

Long

Entier relatif

-2^31 à +(2¨^31)-1

32

4

Char

Entier relatif

-128 à +127

8

1

double

réel

-3,4.10^38 à +3,4.10^38

32

4

Unsigned char

Entier positif

0 à 255

8

1

Unsigned int

Entier positif

0 à 65535

16

2

Unsigned long

Entier positif

0 à (2^32)-1

32

4

byte

Entier positif

0 à 255

8

1

word

Entier positif

0 à 65535

16

2

boolean

Logique (Vrai, Faux)

0 et 1

1

1

On voit sur le code que la première constate,“ledPin”, est de type "int". Elle est affectée à la valeur LED_BUILTIN que l’éditeur a aussi reconnue comme mot réservé (d’où la couleur bleue du mot dans l’éditeur) à l’environnement Arduino. En fait, ce mot réservé, LED_BUILTIN, contient la valeur 13 parce que la LED physique de la carte Arduino Uno est connectée à cette broche numéro 13 des E/S digitales.

La deuxième ligne (hors commentaires) déclare la variable “ledState” de type "int" aussi, qui est affectée initialement à la valeur “Low” c’est-à-dire 0. On dit que la variable est initialisée. Elle évoluera ensuite au gré de l’exécution du code, mais on lui assigne une valeur initiale au moment où elle est déclarée. Comme cette variable représente l’état de la LED, comme elle affectée initialement à Low, quand le code sera exécuté, la LED sera initialement éteinte.

La troisième ligne (hors commentaire) déclare la variable “previousMillis” de type "unsigned long" initialisée à 0. Nous verrons plus loin son utilité.

Et enfin, la quatrième ligne (hors commentaire) déclare la constante "interval” affectée à 1000 et de type long

Le bloc setup

Ce bloc doit exister dans le code, quand bien même il serait vide, ce qui est possible. Il s’agit d’une partie d’initialisation (=setup) avant la partie proprement utile du code qui figurera dans le bloc suivant. On en voit ici la teneur pour le programme “BlinkWithoutDelay”:

void setup() {
// set the digital pin as output:
pinMode(ledPin, OUTPUT);
}

Le bloc contient la fonction "setup".

En l'occurrence, dans ce bloc d’initialisation, la seule instruction consiste en l’appel de la fonction“pinMode” avec deux paramètres d’entrées, "ledPin" et "OUTPUT". Vous vous souvenez que “ledPin” avait été déclarée dans le bloc de déclaration des constantes et variables. Cette fonction"pinMode"  est appelée pour fixer la broche d’E/S correspondante comme étant une sortie, puisque nous voulons écrire l’état de la LED pour la contrôler, allumée ou bien éteinte.
On peut enfin passer au code à proprement parler. :magicien:

Le bloc loop

C’est le bloc qui est exécuté en boucle (d’où le mot réservé “loop”) quand le programme est téléversé de l’ordinateur vers la carte Arduino. Tant que la carte est alimentée, qu’on n’a pas fait un reset, le code tourne en tâche de fond.

Il ne faut pas oublier que tout ce qui figure juste après la fonction "loop()"  est exécuté en boucle. La boucle commence par l’appel à la fonction"millis"  identifiée comme telle par l’éditeur, d’où la couleur orange. On ne peut évidemment pas deviner ce que fait cette fonction. Pour l’apprendre, il faut aller sur le site.

Chemin pour trouver la fonction
Chemin pour trouver la fonction "millis" sur le site Arduino

La fonction "millis"  apparaît dans le groupe libellé “Time” parce que c’est une fonction liée à la gestion de la base de temps des cartes Arduino. On lit que cette fonction retourne le nombre de millisecondes écoulées depuis le lancement du programme. Évidemment, quand ce nombre devient très grand (au bout d’environ 50 jours), il est réinitialisé à 0 parce qu’en informatique, les grands nombres sont toujours limités en fonction du type associé.

Revenons-en au début de la boucle qui appelle la fonction "millis"  et qui affecte dans "currentMillis" le temps écoulé depuis le début de l’exécution.

void loop() {
// here is where you'd put code that needs to be running all the time.
// check to see if it's time to blink the LED; that is, if the difference
// between the current time and last time you blinked the LED is bigger than
// the interval at which you want to blink the LED.
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa:
if (ledState == LOW) {
ledState = HIGH;
} else {
ledState = LOW;
}
// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);
}
}

L’instruction suivante est un "if", c’est-à-dire un test. La nature du test est décrite à l’intérieur des parenthèses qui suivent immédiatement le mot clé "if" :

  • si la différence entre "currentMillis" qui vient d’être mesuré et "previousMillis" (qui avait été déclaré et initialisé à 0 dans le bloc de déclaration des constantes et variables) est supérieure ou égale à interval (la constante déclarée à 1 000), alors le groupe d’instructions qui figure entre les accolades est exécuté ;

  • si le test est négatif, on passe à la suite derrière l'accolade fermante qui figure presque tout à la fin du code. Mais il n’y a plus rien, donc on redémarre du début juste après le mot-clé"loop()" ;

  • en revanche, si le test est positif, en d’autres termes, si 1 000 nouvelles millisecondes se sont écoulées, alors on exécute le groupe entre accolade ouvrante et accolade fermante.

Dans ce groupe, on commence par actualiser "previousMIllis" en y affectant "currentMillis", la durée écoulée depuis le tout début qui vient d’être lue. Ainsi la différence "currentMillis" – "previousMillis" évoluera toujours entre 0 et 1 000.

Ensuite, il y a une nouvelle instruction de test. Ici, on notera que les tests et toutes les structures de programmation que nous verrons plus loin peuvent être imbriqués.

On en revient au deuxième "if". Ici, on regarde dans quel état est la LED. Si elle est éteinte, on l’allume, sinon on l’éteint.

Vous voyez là une structure "if {…} else {...}"c’est-à-dire en bon français, "si {faire ce groupe} sinon {faire celui-là}". La LED ne pouvant être que dans l’un des deux états "Low" ou "High" (éteinte ou allumée), si elle n’est pas éteinte alors elle est allumée et donc il faut l’éteindre.

Comment agir sur la partie code pour modifier la fréquence de clignotement de la LED ?

Il suffit de modifier la constanteinterval". Chaque fois qu’on divise interval par deux, on double la fréquence de clignotement. :zorro:

Le langage

Tout au long de ce SPOC, nous découvrirons régulièrement les fonctions qui permettent d’exploiter les Entrées/Sorties de la carte Arduino Uno, ce qui permet de faire la liaison entre matériel et logiciel. C’est ce qu’on appelle la programmation “bas niveau”, en ce sens qu’il s’agit de la partie logicielle ou code qui est proche du niveau matériel (hardware) de la plateforme.

Toutefois, quand on veut implémenter des algorithmes évolués de navigation autonome, par exemple, il faut mettre dans le code des règles qui peuvent être subtiles et qui combinent des instructions de type exécution conditionnelle avec des combinaisons de conditions avancées, des structures de boucles imbriquées, etc. Nous sommes alors dans une couche logicielle “haut niveau” plus éloignée des Entrées/Sorties qu’on suppose déjà acquises grâce à la programmation bas niveau. Cette programmation “haut niveau” suppose des structures du langage capables de mettre en œuvre les règles complexes correspondantes. Dans ce paragraphe, nous découvrons l’essentiel de ces structures du langage.

Les instructions

Toute instruction doit être ponctuée par un point-virgule ";" qui marque sa fin.
Les bouts de code qui forment une séquence d’instructions figurent dans des “conteneurs” qui sont marqués par des accolades ouvrantes et fermantes, { et }. On les rencontre systématiquement dans les structures de saut conditionnel et de boucle pour décrire la séquence d’instructions qui doit être exécutée, en cas de condition remplie au test du saut conditionnel ou exécuté en boucle.

Les constantes et variables

Nous les avons déjà rencontrées dans le programme de prise en main “Blink”. Sans pour autant nous répéter inutilement, il est nécessaire d’ajouter encore quelques éléments :

  • les variables et constantes doivent être déclarées avec leur type, comme déjà vu ;

  • dans cette déclaration, la variable peut être initialisée. Ensuite, sa valeur évoluera au gré de l’exécution du programme ;

  • il faut aussi insister sur les noms de variables. Il s’agit de les choisir de manière à ce que le nom soit intelligible et qu’il évoque bien son rôle dans le programme, mais sans accent (cf. supra) et bien veiller à ne pas choisir malencontreusement un nom déjà réservé par ailleurs par le langage ;

  • sur la liste des caractères illicites, en dehors des accents, il faut encore mentionner le point “.” et la virgule “,”. Il est recommandé de se limiter aux caractères alphabétiques classiques de “a” à “z” et leurs équivalents en majuscules “A" à “Z”, les chiffres arabes de 0 à 9 et le caractère underscore (souligné), soit “_”. Avec ce corpus, on aura déjà suffisamment de choix et on évitera les caractères illicites ou les combinaisons ambiguës ;

  • les opérations arithmétiques rassemblent addition, soustraction, multiplication, division, division euclidienne et affectation. Ces opérations permettent la manipulation ordinaire des variables ;

Les opérations arithmétiques Cette image provient du site Arduino, elle est couverte par une licence CC-BY-SA 3.0.
Les opérations arithmétiques. Cette image provient du site Arduino, elle est couverte par une licence CC-BY-SA 3.0.
  • les opérations de comparaison permettent de tester les relations d’égalité et d’ordre (strictement inférieur, inférieur ou égal, par exemple). Il faut bien comprendre que ces opérations de comparaison retournent un résultat booléen, "Vrai" ou "Faux". On le met essentiellement en œuvre dans les instructions d’exécution conditionnelle.

Les opérations arithmétiques Cette image provient du site Arduino, elle est couverte par une licence CC-BY-SA 3.0.
Les opérations arithmétiques. Cette image provient du site Arduino, elle est couverte par une licence CC-BY-SA 3.0.
  •  les opérations booléennes, au nombre de trois, fonctions "NON", "ET" et "OU", permettent de combiner plusieurs tests dans une instruction d’exécution conditionnelle ;

Les opérations booléennes Cette image provient du site Arduino, elle est couverte par une licence CC-BY-SA 3.0.
Les opérations booléennes. Cette image provient du site Arduino, elle est couverte par une licence CC-BY-SA 3.0.
  • les opérations bit à bit permettent la manipulation bit à bit de variables ;

Les opérations bit à bit. Cette image provient du site Arduino, elle est couverte par une licence CC-BY-SA 3.0.
Les opérations bit à bit. Cette image provient du site Arduino, elle est couverte par une licence CC-BY-SA 3.0.
  • les opérateurs composés permettent en une instruction unique de modifier des variables. Pour comprendre, on se contente de montrer un exemple :

     

    x += y; est équivalent à l’expression x = x + y; qui combine une addition et une affectation. Le processeur effectue l’addition des variables x et y et affecte le résultat à la variable x dont l’ancienne valeur est écrasée, perdue, remplacée par la somme calculée au terme de l’exécution de l’instruction.

Les opérateurs composés. Cette image provient du site Arduino, elle est couverte par une licence CC-BY-SA 3.0.
Les opérateurs composés. Cette image provient du site Arduino, elle est couverte par une licence CC-BY-SA 3.0.

Les structures de contrôle

Il en existe une dizaine et il n’est pas nécessaire non plus d’en faire l’étude exhaustive en préalable.

Les structures de contrôle. Cette image provient du site Arduino, elle est couverte par une licence CC-BY-SA 3.0.
Les structures de contrôle. Cette image provient du site Arduino, elle est couverte par une licence CC-BY-SA 3.0.

On les découvrira au fur et à mesure qu’on les rencontrera dans la mise en œuvre. Pour prendre la mesure de ces structures de contrôles, nous en commentons trois :

  • l’exécution conditionnelle

La structure générale est la suivante:

If (condition)
{ séquence d'instructions à exécuter si le test est positif
}

Cette image provient du site Arduino, elle est couverte par une licence CC-BY-SA 3.0.
Cette image provient du site Arduino, elle est couverte par une licence CC-BY-SA 3.0.

La condition figure entre parenthèses. On peut combiner les conditions avec les opérations logiques :

If (x > 100 && y <= 90) : la séquence sera exécutée si x est strictement supérieur à 100 ET y inférieur ou égal à 90.

Il faut bien comprendre que “condition” est en fait une variable booléenne ("Vrai" ou "Faux") qui a été affectée par l’exécution des opérations de comparaison décrites entre parenthèses. Quand on combine plusieurs opérations de comparaison avec des fonctions logiques (ET, OU), à la fin, on obtient encore une variable booléenne qui décide de l’exécution ou non de la séquence qui suit.

On peut se passer des accolades { et } si une seule instruction est exécutée en réponse au test positif. On consultera le site de référence Arduino pour les nombreux exemples présentés.

Pour écrire des exécutions conditionnelles élaborées, on peut utiliser la structure "if … else"  qui permet un contrôle du code qui autorise les tests multiples regroupés. Là aussi, on recommande d’étudier les exemples fournis sur le site ;

  • les boucles

Il en existe plusieurs variantes.

Pour faire simple, il y a les boucles dont le nombre d’itérations est déterminé par la programmation et les boucles dont l’itération est contrôlée par une condition, c’est la boucle conditionnelle.

a) La boucle"for" est déterminée par la programmation. La séquence d’instructions est effectuée un nombre déterminé de fois.

La boucle
La boucle "for". Cette image provient du site Arduino, elle est couverte par une licence CC-BY-SA 3.0.

Regardons un exemple :

for (int i=0; i <= 255; i++) {
// séquence d’instructions
}

  • l’indice de boucle est la variable de type"int i" qui variera de 0 jusqu’à 255 inclus ;

  • l’instruction"i++" correspond à une combinaison d’instructions, addition de 1 à "i" et réaffectation à "i". À chaque itération de la boucle, "i" est donc incrémentée d'une unité.

b) La boucle "while" est exécutée tant qu’une condition est remplie, condition qui peut être liée à l’état des Entrées/Sorties, l’état d’un bouton poussoir, par exemple. Dans ce cas, le nombre de passages dans la boucle n’est pas déterminé par la programmation mais par les actions externes sur les Entrées/Sorties.

La boucle
La boucle "while". Cette image provient du site Arduino, elle est couverte par une licence CC-BY-SA 3.0.

Dans l’exemple ci-dessous :

while(swithState == Low){
// séquences à répéter
}

  • La variable "swithState" est fixée par la lecture d’un interrupteur sur un shield, par exemple. Pour que la condition de sortie de boucle puisse être remplie, il faut évidemment que la variable "swithState" soit régulièrement lue.

En résumé

Vous avez, à priori, installé la plateforme sur votre ordinateur personnel, vous avez branché la carte Arduino sur le port USB de votre ordinateur et vous avez aussi exécuté un code simple (“Blink” ou équivalent) que vous avez peut-être modifié, même si ce n’est que la fréquence de clignotement de la LED. Enfin, vous vous êtes familiarisé avec les éléments du langage, au moins pour être capable de lire et comprendre des codes récupérés sur Internet. Il nous reste à regarder comment on gère les Entrées/Sorties, et nous serons prêts pour avancer dans notre projet de robot autonome. :magicien:

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