Nous allons pendant ces TD travailler sur la plate-forme de prototypage électronique Arduino. Cette plate-forme permet de créer de l’appareillage électronique interactif de manière simple.
Deux versions sont proposées, l’une avec de l’électronique, l’autre sans. Pour ceux qui ont peur de l’électronique, vous commencerez avec les modules Tinkerkit, qui évitent de faire des montages. Vous ferez ensuite, si vous en avez le temps, la version « électronique pure ». Les modules Tinkerkit sont des briques, que l’on connecte tout simplement par des câbles.
Je vous demanderai de faire preuve de mesure et de délicatesse lors des manipulations, les composants sont fragiles. Vous travaillerez à deux. Vous rangerez en fin de séance les composants que vous aurez utilisés dans les bonnes cases, sous peine d’en être privé la fois d’après !
Enfin, si ces TD vous plaisent, vous pouvez prolonger l’expérience chez vous. Un Arduino coûte 20 euros, une boite de composants électroniques (kit de débutants pour Arduino par exemple) dans les 40 euros (on peut trouver moins cher encore, la qualité/solidité sera en conséquence). Et si vous n’avez pas peur de l’anglais, un très bon bouquin, complet : Arduino Cookbook, Michael Margolis, éditions O’Reilly (il existe aussi des livres en français, plus simples et très bien faits, ainsi que des tutoriels sur le net, de qualité variable). Vous pouvez aussi utiliser des modules comme TinkerKit, c’est un peu plus cher et un peu plus simple. Dans ce cas je vous conseille plutôt les modules Grove, Tinkerkit étant en sommeil ces dernières années.
Matériel : vous aurez besoin uniquement d’une carte Arduino et d’un câble USB.
Nous allons faire clignoter une des LED (light emitting diode, diode électro luminescente ou DEL en français) située sur la carte Arduino, sans faire de montage pour l’instant. C’est la diode marquée L sur la carte (repérez-la).
Lancez le programme Arduino sur l’ordinateur. Ce programme est un IDE : environnement de développement. C’est dans ce logiciel qu’on tape les programmes, et qu’on les envoie à la carte Arduino.
Vous devriez pouvoir choisir la langue dans les préférences. Dans outils>carte (Tools>board en anglais), cochez Arduino Uno/Génuino. Allez dans Outils>Port série, regardez quels sont les ports présents. Branchez ensuite la carte arduino via un câble USB. Puis retournez dans Outils>Port Série, vérifiez si la carte apparaît et cochez le port en question. Si elle n’apparaît pas, branchez la carte sur un autre port et recommencez.
Captures d’écran et quelques explications supplémentaires sur le site d'Arduino les différentes étapes de guidage.
Tapez le programme figurant dans la première colonne, dans l’IDE Arduino, en respectant absolument les majuscules et symboles présents :
// Programme écrit par Genie_1 et Genie_2 |
Cette ligne est un commentaire, elle commence par //. On massacre allègrement l’orthographe en ne mettant aucun accent, aucune cédille etc. dans les programmes informatiques. Pour des commentaires de plusieurs lignes, on les écrit entre /* et */ |
void setup(){ |
Le « setup » est l’initialisation du programme, qui ne sera exécuté qu’une seule fois au démarrage. On ouvre le setup avec une accolade |
pinMode(13,OUTPUT); |
On déclare la connexion 13 comme étant une sortie de courant. Chaque ligne de programme se finit par un point-virgule. On décale les instructions, d’une tabulation ou de quatre espaces, à chaque fois que l’on ouvre des nouvelles accolades. |
} |
Fermeture du setup |
void loop() { |
Boucle principale, exécutée à l’infini |
digitalWrite(13,HIGH); |
On envoie du courant dans la broche 13. On attend 1 seconde (1000 millisecondes) On coupe le courant dans la broche 13. On attend 1 seconde |
} |
On ferme la boucle principale |
Matériel : une carte Tinkerkit (un « shield »), un câble Tinkerkit et un module DEL. Branchez le shield sur l’Arduino, et la diode sur le port O0 (Output 0).
Le programme précédent est transformé comme ceci :
#include
|
//la bibliotheque TinkerKit permet d’utiliser les modules
|
Matériel et sa description : Une breadbord, une DEL, une résistance de 220 Ohms, deux câbles male/male (un rouge et un bleu si possible, surtout pour le rouge).
La breadbord est une planche de montage expérimentale (ou de prototypage). Elle se présente sous la forme suivante, où les trous de la même couleur sont reliés entre eux.
Les trous d'en haut/bas servent souvent pour le courant. Par convention, on met un fil rouge/marron pour l'entrée, un fil bleu pour la sortie et un fil noir/bicolore pour la terre pour le 220 V. La couleur rouge est impérativement respectée car dangereuse, notamment avec le 220 V : ne touchez jamais un fil rouge ou marron dans une prise ou un interrupteur sans avoir d’abord coupé le courant !
Ci dessous la connexion du courant sur la breadbord, avec un agrandissement du branchement sur la carte.
La diode est un composant électronique qui ne laisse passer le courant que dans un sens. La diode électroluminescente émet en plus de la lumière. Il faut donc la brancher correctement : repérer la patte plus courte et le côté coupé du côté négatif (cathode).
Il est nécessaire de mettre une résistance avant ou après la diode, sinon le courant est trop fort et va la griller à terme. Un calcul permet de trouver une valeur de 160 ohms. Dans les faits, une résistance entre 100 et 1k ohms est correcte. On met souvent 220 ohms pour une led (rouge rouge marron, vérifier avec la table/méthode ci-dessous). Plus la résistance est forte moins la diode émettra de lumière.
La lecture de la valeur des résitances se fait en fontion du nombre d'anneaux de couleur présents. Il y en a 4, 5 ou 6. Sur une résistance à quatre anneaux, les trois premiers donnent les chiffres significatifs, le dernier le multiplicateur (une puissance de 10). Pour les résistances à trois anneaux, on commence la lecture par la couleur située le plus près d'une extrémité. Le tableau wikipedia donne la valeur des couleurs. De nombreux sites calculent la correspondance valeur/couleurs, comme celui-ci ou celui-là, ou encore celui là.
Le calcul des résistances à mettre dans un circuit électrique n'est pas très compliqué, mais demande des connaissances complémentaires à ce que vous connaissez en seconde (et même en terminale me semble-t-il).
Dans un circuit électrique, on note U (ou V) la tension (ou différence de potentiel) en volts, I l’intensité, en ampères, et R la résistance, en ohms. On peut comparer le courant électrique au flot d’une rivière. La tension correspond alors à la différence d’altitude entre la source et l’embouchure : plus la différence est importante, plus le flot coulera fort : un ruisseau de montagne a une « différence de potentiel » plus forte que la Seine. L’intensité correspond au débit du flot d’eau : la Seine a une « intensité » plus grande qu’un ruisseau de montagne.
Les différences de potentiel nous entourant vont de 20/90 mV (nerfs optiques/musculaires), à 1 000 000 V (la foudre), en passant par 1,5 V (les piles), 220 V (les prises de courant), 10 000/500 000 V (lignes à haute tension).
Des sites expliquent comment calculer la résistance nécessaire pour ne pas griller des composants dans un circuit électronique, en utilisant la loi des mailles, la loi des noeuds et la loi d'Ohm. Pour un exemple simple, voir par exemple ici, ou sur OpenClassroom le cours premiers montages avec Arduino, aller à "calcul de la bonne valeur de résistance pour une led" (adresse url à retrouver...)
Voici une première proposition de montage, à ne pas faire, avec à côté le schéma électronique symbolique :
En fait, nous allons utiliser les broches (pin en anglais) 0 à 13 pour brancher les composants. En effet, le montage ci-dessus envoie du courant en permanence, tandis que l’on peut programmer les broches 0 à 13 pour envoyer le courant quand on le souhaite. Dans les faits, on évite d’utiliser les connexions 0 et 1, qui peuvent servir au port série (que l’on verra ultérieurement) Pour simplifier, on branchera directement le courant sur la colonne de trous où sont les composants, sans passer par les trous du bas (ou du haut).
D’où le montage que l’on réalise (vous pouvez prendre n’importe quelle connexion, sauf 0 et 1) :
Reprendre le programme du 1 et le tester sur votre montage. Attention : déclarer la bonne connexion, ce n’est plus forcément la 13.
Remarque : on peut aussi monter la diode à l’envers : elle sera alors éteinte en mode HIGH et allumée en mode LOW. D’après OpenClassrooms, ce montage économise la carte.
pour i de 0 à xxx
est une instruction qui répète plusieurs fois fois un bloc d’instructions, en général xxx fois. On dit que c’est une instruction itérative (une itération = une répétition). On utilise un compteur de boucle (itérateur) en général i
, j
ou k
. On précise de combien on augmente le compteur de boucle à chaque itération.
Exemples :
i = i + 1
augmente de 1 le compteur i à chaque itération (standard) ;
i++
augmente de 1 le compteur i à chaque itération (raccourci pour i = i + 1
) ;
i = i - 1
diminue de 1 le compteur i à chaque itération;
i = i*2
multiplie le compteur par deux à chaque itération.
En C, la syntaxe du pour est :
for (int i=0; i<10; i++)
{
// diverses instructions
}
On déclare d’abord le compteur i comme étant un entier (int
), qui est crée à la valeur 0
(i = 0
).
On donne ensuite la condition qui permet d’arrêter la boucle (on continue tant que
i < 10
),
et enfin on précise la manière dont on augmente l’itérateur ( i++
).
Tous les exercices seront recopiés dans le dossier documents>devoirs>Mandon ou par email. Ils seront nommés comme suit : ex_arduino_1_1_Nom1_Nom2.ino
(pour le 1er exercice ci-dessous, avec vos noms)Faire clignoter la diode alternativement deux secondes,
puis une seconde (remarque : pas besoin de for
).
La diode doit clignoter 10 fois une seconde, puis s’arrêter.
La diode doit d’abord clignoter 5 fois une seconde, ceci une seul fois, puis alterner 10 clignotements rapides d’une demi seconde, et 10 clignotements lents de deux secondes sans fin.
La diode doit clignoter de plus en plus rapidement, puis de plus en plus lentement,
et ainsi de suite. Par exemple en millisecondes :
200 – 400 – 600 – 800 – 1000 – 800 – 600 – 400 – 200 – etc...
On peut aussi faire 100 – 200 – 400 – 800 – 1600 – 800 – 400 – 200 – 100 – etc...
Remarque : on peut mettre une variable, ou bien un calcul,
dans delay()
. Les opérations usuelles sont +, - ,* , /
.
Le nom de la variable est au choix, les usages donnent par exemple tempsEntreDeuxEtats
.
Il faut déclarer cette variable en début de programme (dans le setup
par exemple on écrira int temps_entre_deux_etats = 100 ;
).
La boucle tant que/while
est aussi une instruction itérative.
Elle répète un bloc d’instruction suivant une condition.
La condition est écrite entre parenthèses, elle peut par exemple être
i == 3
double signe = pour tester l’égalité;
j <= 4
inférieur ou égal, de même pour >, <, >= ;
k != 5
k différent de 5 ;
!(k ==5)
k différent de 5 sous la forme « non k égal à 5 »
int i = 0 // declaration de l'iterateur
while (i < nombre)
{
// diverses instructions
i = i + 1; // ou i ++, ou autre
// methode suivant la condition d'arret
}
Reprendre les exercices de la boucle pour
, en les nommant
ex_arduino_1_1bis_Nom1_Nom2.ino etc... Vous me les ferez parvenir aussi (email ou dossier devoirs>Mandon)
Copiez le programme suivant :
void setup()
|
Le port série est ouvert avec une vitesse de lecture de 9600 bps (bits par seconde). Considérez-le comme une ligne téléphonique qui peut envoyer ou recevoir jusqu’à 9600 nombres 0/1 par seconde. | void loop() {
|
On « imprime » à l’écran par le port série le nombre 200*i, avec print .println signifie qu’en plus on passe à la ligne après avoir écrit le nombre
|
Prenez soit une photorésistance (ou encore light sensor), qui capte la luminosité ambiante, soit une thermistance, qui donne la température ambiante. Les senseurs sont des entrées et non des sorties (INPUT et non OUTPUT).
Branchez le capteur sur l’entrée I0 (input 0).
Déclaration en entrée 0 (input 0), à écrire après l’importation de la bibliothèque Tinkerkit. | TKLightSensor ldr(I0);
|
TKThermistor therm(I0);
|
Lecture de la valeur (luminosité ou température). |
|
|
Matériel et sa description : une breadboard, un arduino, 3 cables dont un rouge et un bleu ou noir.
En plus:
Renvoie un voltage de 10 mV par degrés. Les port d’entrées analogiques renvoient une valeur correspondante entre 0 et 1023. | Appelée CDS parfois. Renvoie un voltage variable suivant la luminosité. Les port d’entrées analogiques renvoient une valeur correspondante entre 0 et 1023. On peut utiliser n’importe quelle résistance entre 1 kΩ et 10 kΩ |
|
|
Tous les exercices seront recopiés dans le dossier documents>devoirs>Mandon ou par email. Ils seront nommés comme suit : ex_arduino_2_1_Nom1_Nom2.ino
Ecrire dans la fenêtre du port série la donnée résultant du capteur, toutes les secondes.
Écrivez un programme qui allume une diode verte si la température ou la luminosité reste en dessous d'un seuil determiné, et rouge sinon. On utilisera l'instruction si/sinon (cf.ci-dessous)
Écrivez un programme qui allume une diode avec une luminosité d’autant plus forte qu’il fait plus sombre si vous utilisez une lumistance, ou froid avec une thermistance. On peut réchauffer le thermistor en soufflant dessus.
Tinkerkit : la luminosité d’une diode se règle avec led.brightness(val);
où val
est une variable déjà récupérée précédemment (et déclarée en début de programme).
Électronique : la luminosité de la diode se régle avec digitalWrite(1numéro_de_labroche , intensité);
. L'instensité est une variabble de type entier ( int
), de valeur comprise entre 0 et 1023.
Faites l’exercice 1 avec un potentiomètre, qui est une résistance variable. Il modifie la valeur du courant rentrant. Les potentiomètres sont soit à molette, soit à curseur.
Déclaration de la broche d'entrée en début de programme. Ne pas oublier si nécesssaire la bibliothèque Tinkerkit. | TKPotentiometer pot(I0);
|
|
Lecture de la valeur dans loop. | valeur = pot.read();
|
val = analogRead(brochePot) ;
|
Le montage électronique :
En C, la syntaxe du « si - sinon » est :
if (condition)
//les conditions s’écrivent comme pour l’instruction tant que.
{
// diverses instructions
}
else // facultatif
{
// autres instructions
}
Faire un montage avec deux diodes. Faire clignoter les deux diodes à des rythmes différents (par exemple 210 ms et 980 ms).
Il faudra :
int minuteur = 0;
int compteurDiode1 = 0;
int compteurDiode2 = 0;
%
,
qui donne le reste de la division euclidienne d’un nombre par un autre (vérifiez les exemples ci-dessous).
x = 2%5 // x contient 2
- x = 16%5 // x contient 1
- x = 100%5 // x contient 0
Il y a deux types d’entrées et de sortie :
TKButton button(I0);
|
// déclaration du bouton (en debut de programme)
|
val = button.read();
|
// lecture de la valeur : HIGH si le bouton est
|
TKTouchSensor touch(I0);
|
// déclaration du capteur de contact |
val = touch.read();
|
// lecture de la valeur : HIGH si le capteur est |
val = touch.readSwitch();
|
// lecture de la valeur comme sur un |
Quand le bouton est ouvert (non pressé), il n'y a pas de connexion entre les deux broches du boutons, et la connexion est au sol via la résistance. On lit donc « low » sur la connexion 2. Quand on appuie, le courant passe entre les deux broches, et on lit « high ».
Remarques :
pinMode(brocheBouton, INPUT_PULLUP) ;
Piqure de rappel : tous les exercices seront recopiés dans le dossier documents>devoirs>Mandon ou par email. Ils seront nommés comme suit : ex_arduino_2_4_Nom1_Nom2.ino
Afficher l’état du bouton à l’aide du port série.
Reprendre le programme de l’exercice 2_2 (diode plus ou moins lumineuse suivant la température/la luminosité). Rajouter un bouton qui met en marche ce programme, ou l’éteint.
L’instruction map permet de transformer une plage de valeurs en une autre (map = carte).
Exemple :
pourcentage = map(valeur,0,1023,0,100)
transforme le contenu de la variable valeur, compris entre les bornes 0 et 1023, en un pourcentage compris entre les bornes 0 et 100, grâce à une fonction affine (au passage un exercice de mathématiques : donner l'expression de la fonction affine en question). On peut mettre des variables à la place des nombres pour les bornes.
faire clignoter une led plus ou moins vite, suivant la position d’un potentiomètre, grâce à un mappage.
Reprendre le programme de l’exercice 2_2 (diode plus ou moins lumineuse suivant la température/la luminosité).
On va reprendre ce programme en « mappant » la donnée du capteur (map signifie carte en anglais). Le but est d’avoir une luminosité maximale/minimale de la diode en fonction des conditions du moment, qui sont variables.
Dans l’initialisation, on va mesurer la donnée maximale, ainsi que la donnée minimale du capteur. Pour cela, il faudra bien sûr déclarer les deux variables en question. On rajoutera également un bouton pour permettre à l’utilisateur d’interagir avec Arduino.
Une interruption permet d’arrêter le programme en cours pour exécuter des instructions que l’on estime urgentes.
Exemple :
// dans le setup par exemple
attachInterrupt(0, Reagir, FALLING);
// en dehors du setup et du loop
Reagir() {
// instructions
}
La connexion pour une interruption est uniquement sur les broches 2 et 3.
Les paramètres de « attachInterrupt » sont dans l'ordre :
Réaliser le montage suivant avec le mini-afficheur 7 segments à del. Les résistances sont de 220 ohms minimum (330, 1000, 2000 fonctionnent très bien aussi).
Écrire un programme qui affiche la lettre F, en mettant les « bonnes » sorties à HIGH et les autres à LOW. Le fonctionnement est très semblable à celui des diodes (ce sont des diodes !) ; inspirez-vous des codes des exercices du premier chapitre. Et observez bien les schémas ci-dessus !
Comme vous l'avez vu en faisant l'exercice ci dessus chap3_1_1, écrire chaque nombre en traitant chaque connexion individuellement est assez long. Il y a plus rapide avec les instructions « bitwise » (bit à bit). Ce type d'instructions permet de traiter les nombres binaires, composés de 8 chiffres qui sont soit 0 soit 1, rapidement. Dans le cas de l'afficheur 8 bits, on traitera les 8 broches avec un seul nombre binaire et peu d’instructions. Un nombre de 8 bits est appelé un octet.
Le programme afficheur_7_segments.ino, dont le code figure ci-dessous, montre l’utilisation de ces opérations. Comprenez d'abord le code, puis téléchargez-le.
/*représentation des segments allumés par des octets. Chaque octet est composé de 8 bits : d'abord les 7 segments de l'afficheur, puis le point décimal. Ces octets sont ranges dans un tableau de 8 éléments, constants (non modifiables). Le type octet est « byte » en C. */
// création du tableau de 8 bytes/octets. Le tableau s'appelle « segments »
//Un byte commence par B, pour montrer que ce n'est pas un nombre entier standard
const byte segments[9] = {
//ABCDEFGdp // correspondance entre les bits et les segments de l'afficheur
B00000001, // segment A
B00000010, // segment B
B00000100, // C
B00001000, // D
B00010000, // E
B00100000, // F
B01000000, // G
B10000000, // point décimal (dp)
B00000000, // tout éteint };
// tableau des broches pour chaque segment et le point décimal. C'est un tableau d'entiers « int » constants
// ordre des broches dans le montage dp2,C3,D4,E5,G6,F7,A8,B9
const int brochesSegments[8] = {8,9,3,4,5,7,6,2}; // vérifier suivant votre câblage à l'aide des schémas ci dessus
void setup(){
for(int i=0; i < 8; i++){
pinMode(brochesSegments[i], OUTPUT); // toutes les broches pour
// l'afficheur sont des sorties
}
}
void loop(){
// boucle qui affiche tous les segments un par un, puis éteint tout
for(int i=0; i <= 8; i++) {
afficheSegment(segments[i]); // la fonction qui affiche est apres
// le loop, voir ci-dessous
delay(1000);
}
}
// Contrôle de l'afficheur. La valeur à afficher est récupérée
// en entrée dans le byte « octet »
void afficheSegment( byte octet){
// la variable segmentAllumeOuEteint est un booléen,
// qui prend soit la valeur 1 = True ou la valeur 0 = False.
boolean segmentAllumeOuEteint;
// la boucle suivante lit les bits de « octet » 1 par 1,
// avec le compteur numeroSegment
for(int numeroSegment = 0; numeroSegment < 8; numeroSegment++){
// segmentAllumeOuEteint est vrai si le bit « numeroSegment »
// lu dans l'octet est 1
segmentAllumeOuEteint = bitRead(octet, numeroSegment);
// la ligne suivante inverse la valeur de bitAllumeOuEteint. Suivant le type de l'afficheur, il faut la supprimer ou la garder
//(si les segments sont allumés au lieu d'être éteints)
// le « ! » est l'opérateur « non », qui inverse vrai et faux.
// segmentAllumeOuEteint = ! segmentAllumeOuEteint; // ligne facultative
// pour les afficheurs à anode commune
digitalWrite( brochesSegments[numeroSegment], segmentAllumeOuEteint);
}
}
Modifier le programme précédent pour qu'il affiche les chiffres de 0 à 9.
Modifier le programme précédent pour qu'il affiche un chiffre au hasard compris entre 0 et 9. Remarquez que l'on peut aussi écrire les lettres A, b, C, d, E et F. Il y a deux endroits où l'on modifie le programme. D'une part, il faut changer le tableau « segments » ; on peut aussi changer son nom en « chiffres » pour que cela soit plus clair. D'autre part, dans la boucle principale, on rajoutera le choix d'un nombre aléatoire avec l'instruction :
float nombreAlea = random(0,9) ; // le 0 est inclus, le 9 est exclu
Si l'on veut en plus avoir l'affichage des lettres, il faut écrire random(0,16)
.
L'instruction random génère des nombres pseudo-aléatoires à partir d'une « graine » (seed en anglais). Pour avoir une graine aléatoire, on l'initialise dans le setup en lisant la valeur d'une broche non connectée, qui donne alors du « bruit » analogique aléatoire, avec randomSeed(analogReag(0)) ;
Ici on suppose que l'entrée 0 n'est pas connectée.