Tutoriels, exercices, documentations et références
SECONDAIRE | DIFFICULTÉ MOYENNE | 6 À 8 HEURES
- Lecture et écriture d'un signal numérique avec les fonctions
digitalRead();
etdigitalWrite();
. - Lecture et écriture d'un signal analogique avec les fonctions
analogRead();
etanalogWrite();
. - Compréhension des intervalles de valeurs d'un signal analogique entrant (lu) et sortant (écrit):
- Signal analogique entrant (
analogRead();
) : valeur comprise entre 0 et 1023 (intervalle [0 1023]). - Signal analogique sortant (
analogWrite();
) : valeur comprise entre 0 et 255 (intervalle [0 255]).
- Signal analogique entrant (
- La manipulation des variables n'a plus de secrets pour vous grâce à la fonction
map();
.
Si vous maîtrisez ces 4 points, que vous avez bien compris le rôle des "void setup()" et "void loop()" et que vous êtes à l'aise avec le concept de variables, alors vous êtes réellement prêts pour la suite !
Les boucles incrémentielles : "for".
On les appelle également boucles for car elles sont appelées dans le programme avec le mot anglais "for".
Mais ça veut dire quoi "incrémentielle" ? Et bien sachez qu'en informatique, un incrément est la quantité dont on augmente une variable à chaque phase de l'exécution d'un programme.
Comme d'habitude, une petite définition théorique !
Et la meilleure façon pour comprendre, c'est la pratique !
Voici une simulation. Je l'appelle la "DEL respirante". Une DEL s'allume et s'éteint graduellement. On retrouve parfois ceci dans les appareils électroniques lorsqu'ils sont en veille.
Observez la simulation puis nous allons décortiquer le programme ensemble.
- Déclaration des variables :
int del = 3;
- "void setup()" :
pinMode (del, OUTPUT);
C'est le "void loop()" qui est un peu plus obscur :
void loop(){ for (int i=0; i < 256; i++){ analogWrite(del, i); delay(10); } for (int i=255; i > 0; i--){ analogWrite(del, i); delay(10); } }
Concentrons nous sur la première afin de bien comprendre le fonctionnement de ces boucles incrémentielles.
for (int i=0; i < 256; i++){ analogWrite(del, i); delay(10); }
- L'instruction "for" qui comprend 3 paramètres entre parenthèse :
for (int i=0; i < 256; i++)
. - Entre 2 accolades, la partie du programme à éxecuter dans la boucle "for".
Nous pourrions résumer ceci de la façon suivante :
for (initialisation; condition; incrémentation) { //instruction(s) à exécuter; }
Rappelez vous l'initialisation de la boucle "for" :
for (initialisation; condition; incrémentation){}
Il y a 3 points à définir :
- Initilisation : nous déclarons une variable ("i"), dont la valeur de départ est 0 (
int i = 0;
); - Condition : c'est la condition qui permet d'exécuter la boucle. Si elle est vraie, le programme continue d'exécuter la boucle "for", si elle est fausse le programme ne l'exécute plus.
Ici notre condition esti < 256;
. Cela signifie que tant que la variable "i" est plus petite que 256, le programme peut continuer d'exécuter la boucle "for". Lorsque la variable "i" sera égale à 255, la dermière condition sera atteinte et la boucle for ne sera plus exécutée. - Incrémentation : c'est la quantité dont on augmente la variable "i" à chaque boucle. Ici nous avons
i++
. En langage C, ceci équivaut à écrirei = i + 1
. Donc, à chaque boucle d'éxecution du "for", la variable "i" augmente de 1. Jusqu'à atteindre 255, la condition que nous avons fixé préalablement.
analogWrite (del, i);
: Arduino envoie un signal analogique dans la prise de la DEL (#3) d'une valeur "i".- Première boucle : i = 0, la DEL est éteinte.
- Seconde boucle : i = 1, la DEL commence à s'allumer.
- 123ème boucle : i = 122, la DEL est à moitié allumée.
- 256ème boucle : i = 255, la DEL est allumée au maximum.
- 257ème boucle : i = 256, la condition
i < 256;
est fausse, le programme n'éxecute plus le "for".
delay(10);
: une pause de 10 millisecondes entre les boucles afin de percevoir l'augmentation de luminosité. Sans délai, le programme va plus vite que nos yeux et nous verrions la DEL éclairer au maximum d'un coup.
Jouez avec le délai afin de ralentir ou accélérer la "respiration" de la DEL.
Pour la seconde boucle "for", on fait l'inverse :
for (int i=255; i > 0; i--){}
.
- Initialisation :
int i = 255;
. On démarre la variable "i" à 255. - Condition :
i > 0;
. La boucle "for" s'exécutera tant que la variable "i" est plus grande que 0. - Incrémentation :
i--
. La variable "i" diminue de 1 à chaque boucle "for". Ceci équivaut à écrirei = i - 1
.
Et comme tout ceci est dans le "void loop", ça recommence indéfiniment.
Grâce aux boucles "for", le programme est nettement simplifié.
Voici donc le K2000 revisité. Essayez et regardez bien le programme !
Les boucles conditionnelles : "if-else".
On l'appelle également boucle if ou if-else car on la déclare avec les mots anglais "if" et "else", que l'on pourrait traduire par "si"..."sinon".
On pourrait simplifier le concept en s'imaginant dire au programme "si tu remplis cette condition, tu fais ceci; sinon tu fais cela".
Définition d'une boucle conditionnelle :
Jouez avec l'interrupteur et observez ce qu'il se passe.
Si nous étions le programme, il faudrait nous dire :
- SI l'interrupteur est à la position HIGH, tu clignotes la DEL.
- SINON tu allumes la DEL.
Regardons le programme de plus près. Passons la déclaration des variables et le "void setup" qui ne sont pas compliqués et allons directement au "void loop".
void loop() { valInterrupt = digitalRead(interrupteur); if (valInterrupt == LOW){ digitalWrite (del, HIGH); } else { digitalWrite (del, LOW); delay (100); digitalWrite (del, HIGH); delay (100); } }
valInterrupt = digitalRead (interrupteur);
permet de stocker l'état de l'interrupteur (HIGH ou LOW) dans la variable "valInterrupt".Ensuite arrive le "if-else". Concentrons-nous sur le "if" :
if (valInterrupt == LOW){ digitalWrite (del, HIGH); }
Et pour le "else" :
else { digitalWrite (del, LOW); delay (100); digitalWrite (del, HIGH); delay (100); }
De façon générale, une boucle conditionnelle est formatée comme suit :
if (uneVariable opérateurDeComparaison uneValeur) { // faire quelque chose } else { // faire autre chose }
Il est aussi possible d'avoir autant de "if" que vous le désirez. Vous pouvez même avoir des "if" dans des "if", des "if" dans des "for", des "for" dans des "if". Bref, toutes les combinaisons possibles !
Les voici :
Opérateur | symbole mathématique | Syntaxe dans un programme |
---|---|---|
Plus grand | x > y | x > y |
Plus grand ou égal | x ≥ y | x >= y |
Plus petit | x < y | x < y |
Plus petit ou égal | x ≤ y | x <= y |
Différent | x ≠ y | x != y |
Égal | x = y | x == y |
Les bibliothèques.
Dans certains projets Arduino, nous voulons utiliser certains composants (entrés ou sorties : capteurs ou effecteurs) plus complexes à programmer. Nous pourrions par exemple vouloir utiliser dans notre projet un servo-moteur, un écran LCD, un pHmètre, un capteur de fréquence cardiaque, un piano MIDI, une télécommande bref, divers composants périphériques qui rendent Arduino si versatile.
Heureusement pour nous, les fabricants de ces produits ainsi que la communauté de développeurs partout dans le monde mettent à notre disposition des "bibliothèques". C'est à dire un ensemble de procédures toutes faites, contenu dans un fichier séparé, qu'il nous suffira de déclarer dans notre programme pour faire fonctionner le matériel.
Voici la définition des bibliothèques données par la fondation Arduino :
Sur Tinkercad c'est légèrement différent. Voyons cela en images !
Remarquez sur l'image que de nombreuses bibliothèques sont incluses. Par exemple la bibliothèque "Servo" permettra de programmer un servo-moteur. La bibliothèque "LiquidCrystal" servira à programmer un écran à cristaux liquides."IRremote" permet d'utiliser une télécommande infrarouge (télécommande de TV par exemple).
Bref, les projets Arduino peuvent devenir de plus en plus fous grâce aux bibliothèques !
Heureusement, les créateurs de bibliothèques fournissent toujours des exemples d'utilisation. Ils ne sont pas faciles à trouver dans Tinkercad, mais ils sont très accessibles dans le logiciel Arduino IDE
Essayez la simulation et surtout, lisez attentitevement le programme. Nous allons essayer de le comprendre ensemble.
- Ligne #1 :
#include <Servo.h>
(au début du programme). - Ligne #3 :
Servo monMoteur;
(au début du programme). - Ligne #10 :
monMoteur.attach (3);
(dans le "void setup()"). - Ligne #18 :
monMoteur.write (variable);
(dans le "void loop()").
#include <Servo.h>
: c'est la ligne de code qui apparaît toute seule lorsque vous choisissez d'inclure une bibliothèque. Elle dit au programme d'aller chercher un petit fichier (qui est caché dans le dossier d'Arduino) qui s'appelle "Servo.h".Servo monMoteur;
: on créé une instance de l'objet "servo" qui s'appelle "monMoteur". Qu'est-ce que c'est ? Ben en gros c'est un peu comme quand on déclare les variables : on dit ici au programme que dans le reste du programme le moteur s'appelera "monMoteur". J'aurai aussi pu écrireServo poutine
et mon moteur aurait eu "poutine" comme nom.
Vous pouvez créer autant d'instances qu'il y a de moteurs. Si vous utilisez 2 moteurs, vous pourriez écrire :
Servo moteur1;
.
Servo moteur2;monMoteur.attach (3);
: dans le "void setup()", c'est l'équivalent dupinMode();
. Il faut bien que le programme sache sur quelle prise est branchée le moteur ! C'est comme ceci qu'on le lui indique. Ici on dit au programme que le moteur, qui s'appelle "monMoteur" est branché sur la prise 3.monMoteur.write (variable);
: c'est cette fonction qui indique au moteur de fonctionner. De la même façon que la fonctionanalogWrite();
oudigitalWrite();
, la fonctionmonMoteur.write();
prend un argument entre parenthèse qui est la valeur, en degrès, de la rotation que doit effectuer le moteur.
Par exemple,monMoteur.write(90);
indique au moteur de tourner de 90°.monMoteur.write (variable);
indique au moteur de tourner d'un angle qui correspond à la variable. Si cette variable = 720, le moteur fera 2 tours.- Également, si j'avais initialement appelé mon moteur "poutine" en écrivant
Servo poutine;
au début du programme, j'aurai du écrirepoutine.attach(3);
etpoutine.write(variable);
pour rester cohérant.
Résumé de la partie 5.
Syntaxe | Emplacement | Utilisation | Argument(s) |
---|---|---|---|
for (i = a; i * b; c) {d} | loop() | Exécute une action répétitive en utilisant un compteur | i = variable à incrémenter a = valeur de départ : initialisation *= opérateur logique de comparaison: <, >, <=, >=, ==, != b = condition : valeur d'arrivée c = incrémentation de la variable i Exemple: for (i=0; i > 100; i=i+10) {blablablabla} |
If (a * b) {c} | loop() | Exécute la partie de programme entre accolades {c} si et uniquement si la condition a*b est remplie | a et b = variables à comparer *= opérateur logique de comparaison: <, >, <=, >=, ==, != Exemple: if (valeurPhoto > seuil) {blablablabla} |
#include <a.h> | Inclus la bibliothèque "a.h" dans le programme
ex : a = Servo bibliothèque servo.h |
||
Les fonctions suivantes sont spécifiques aux SERVO-MOTEURS | |||
Servo a; | Nomme une variable "servo" (ex : "a" = moteur) | ||
a.attach (b); | setup() | Indique en argument la pin sur laquelle est branchée la variable "servo" | a = nom de la variable "servo" (ex : "a" = moteur) b = nom ou # de la prise Exemple : moteur.attach (servo); |
a.write (x); | loop() | Envoie la position, en degrès, que doit prendre le "servo" associé à la variable a | a = variable servo
(ex : a = moteur) x = position en degrès, ou variable stockant cette position Exemple : moteur.write (valeurPotentiometre) |