• 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 potentiomètres, les entrées analogiques et la fonction de mappage

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

Jusqu’ici, vous avez utilisé des entrées numériques qui ne prennent que deux valeurs : 1 ou 0. Vous allez à présent découvrir comment utiliser des entrées analogiques qui permettent de recevoir des données électriques plus subtiles.

Cette découverte des entrées analogiques se fera à travers la prise en main d’un nouveau composant : le potentiomètre analogique. Vous allez apprendre à vous en servir pour créer toute une nouvelle gamme de réactions en traitant des données qui ne sont pas uniquement des 1 et des 0. Cela vous amènera à enrichir votre vocabulaire de programmation avec la notion de mappage de valeurs.

Tout ceci sera bien sûr l'occasion de créer de nouveaux programmes, comme un clignotant à vitesse variable.

Vous aborderez enfin le principe de joystick, si cher à nos jeux préférés...

Le potentiomètre analogique

Le potentiomètre analogique se présente sous plusieurs formes. Mais avant d'aller plus loin, il faut en comprendre la fonction.

Vous avez, jusqu'ici, utilisé des résistances. Je vous rappelle que ces résistances ont des mesures précises ( 100 Ω, 220 Ω, 1 kΩ,10 kΩ...) et qu'une résistance ne peut être remplacée que par une résistance de valeur identique.

Et bien les ingénieurs électroniques (plus précisément Johann Christian Poggendorff) ont créé une forme de résistance qui varie : le potentiomètre ! C'est très pratique et depuis on l'utilise dans bien des domaines !

Il existe deux principaux types de potentiomètres analogiques : les potentiomètres linéaires et les potentiomètres logarithmiques (bon en vrai il y a une troisième forme qui a peu d'intérêt pour nous).

Si je précise potentiomètre analogiques, c'est qu'il existe des potentiomètres numériques qui ne font pas l'objet de ce chapitre.

Alors, des potentiomètres (je ne vais pas ajouter analogique à chaque fois ), ça ressemble à ça :

Différentes formes de potentiomètre analogiques (source : multi-rotor-fans-club.com)
Différentes formes de potentiomètre analogiques (source : multi-rotor-fans-club.com)

Si vous observez bien, vous voyez que tous ces potentiomètres ont trois pattes ! C'est une nouveauté, en effet, jusqu'à maintenant, tout ce que nous avions connecté n'avait que deux pattes. 

Le principe est assez simple : un curseur se déplace sur une piste résistante (au passage de l'électricité) et permet de faire varier la résistance du potentiomètre. Donc l'électricité entre par un côté du potentiomètre et sort par le curseur. Si le curseur est proche de l'entrée, la résistance est faible et si le curseur est éloigné de l'entrée, la résistance et grande.

D'ailleurs le symbole pour représenter un potentiomètre en électronique est assez parlant :

Symbole du potentiomètre linéaire
Symbole du potentiomètre linéaire

La flèche représente le curseur. En réalité, vous devrez connecter le potentiomètre sur la patte du curseur (celle au centre, notée C sur l'image) et connecter ensuite l'une des deux pattes restantes (soit A ou B) sur le +5V et l'autre sur le ground.

On dit qu'il s'agit d'un potentiomètre linéaire, car le déplacement du curseur fait augmenter la résistance de façon régulière. On peut donc s'attendre, en positionnant le curseur bien au centre, que la valeur de la résistance soit égale à la moitié de la résistance totale possible. Un exemple sera sûrement plus parlant !

Si vous utilisez un potentiomètre de résistance maximum 10 KΩ :

  • Si vous placez le curseur à fond du côté de la patte d'entrée, la valeur de résistance sera de 0 Ω.

  • Si vous placez le curseur au milieu, la valeur de résistance sera de 5 KΩ (la moitié du maximum).

  • Si vous placez le curseur à fond de l'autre côté, la valeur de la résistance sera de 10 kΩ (valeur max).

Il existe des potentiomètres droits (on déplace le curseur sur une ligne) ou des potentiomètres circulaires (on déplace le curseur en le faisant tourner). Certains nécessitent l'utilisation d'un tournevis pour le faire tourner, d'autres ont une tige qui permet la rotation.

Ha oui ! Je vois, c'est comme sur mon ampli de guitare, avec le bouton du volume ?

Et bien non, pas tout à fait. Les boutons de volume sur la guitare, ou les amplis, ou sur des enceintes, sont bien des potentiomètres, mais il ne sont pas dits linéaires, mais logarithmiques (non Lukas, rien à voir avec le fait de ne pas avoir le rythme...).

Logarithmique veut dire, sans trop entrer dans les détails, que quand on fait varier la position du curseur, on n'ajoute pas une valeur de résistance mais on la multiplie donc :

  • À la patte d’entrée, la valeur de la résistance est bien 0 Ω.

  • À la patte de sortie, la valeur de la résistance est bien au maximum.

  • Mais au milieu d’un potentiomètre logarithmique, la valeur de la résistance ne correspond pas à la moitié du maximum. Et le calcul n'est pas un calcul simple à effectuer.

Nous utiliserons dans les montages de ce cours uniquement des potentiomètres linéaires car ce qui nous intéressera justement, c'est la variation prévisible de la résistance.

Je vous propose un premier montage de test, mais cette fois, sans image Fritzing pour vous habituer à lire ce genre de montage :

Montage pour faire varier deux diodes en opposition
Montage pour faire varier deux diodes en opposition

Vous avez compris le schéma ? Il s’agit de connecter la résistance vers le +5 V de l’Arduino, puis la patte centrale du potentiomètre à la résistance. On connecte ensuite chaque autre patte du potentiomètre à la borne + d’une diode, et chaque diode au ground.

Si le montage est correct, en faisant varier le potentiomètre, vous voyez augmenter la luminosité d'une diode pendant que l'autre diminue en luminosité.

Nous pouvons donc dire qu'avec un potentiomètre, nous avons un moyen de faire varier la résistance du passage du courant, donc à intensité égale nous faisons varier la tension aux bornes du potentiomètre !!! ( Lukas, plutôt que de feindre la compréhension, allez donc relire la section précédente sur la loi d'Ohm ).

C'est justement cette variation de tension que notre Arduino est capable de lire !

Les entrées analogiques

Pour mieux comprendre ce qui se passe dans l’Arduino, nous allons commencer par bien faire la distinction entre entrée analogique et numérique.
Comme il s’agit d’entrée électriques dans notre cas, on parlera plutôt de signal analogique ou numérique. Pour faire simple, un signal analogique peut prendre une infinité de valeurs entre deux bornes alors qu'un signal numérique n'en prendra qu'un certain nombre précis.

Petite illustration avec le potentiomètre et le montage qui suit :

Potentiomètre seul
Potentiomètre seul

Sur cet exemple, en faisant tourner le bouton du potentiomètre (curseur), vous ferez varier la tension à ses bornes de 0 V à 5 V. Cette variation dépendra de la rotation, de votre précision... En tous cas vous pourrez obtenir un nombre infini de valeurs entre 0 et 5 volts. Et il sera difficile d'obtenir précisément 3,234532 V. C’est ce que l’on appelle un signal analogique, dont toutes les valeurs possibles peuvent être représentées par la ligne rouge ci-dessous.

En revanche un signal numérique prendra, lui, un nombre de valeurs définies (c'est le principe de l'escalier), ce que l'on peut voir en bleu sur le schéma. On peut en fait imaginer que les valeurs progressent cran par cran. La valeur de ces crans s'appelle la résolution du signal numérique.

Évolution des valeurs numériques et analogiques de la tension d'un potentiomètre
Évolution des valeurs numériques et analogiques de la tension d'un potentiomètre

Chercher la valeur numérique d'un signal analogique s'appelle la quantification.

Pour transformer un signal analogique en signal numérique, il nous faut un convertisseur analogique numérique, qu'on appelle plus simplement CAN.

Et bien là où vous avez une chance inouïe, c'est que l'Arduino possède non pas 1, ni 2, ni 3 CAN, mais 6 CAN !!!

En effet, vous pouvez transformer jusqu'à 6 signaux analogiques en signaux numériques, donc en nombres entiers ! Ce n'est qu'une fois le signal transformé en nombre qu'il est exploitable avec un programme.

L'Arduino a tout de même une limite de définition, c'est à dire de résolution du signal. En effet, il ne peut transformer un signal reçu qu'en nombre compris entre 0 et 1023, soit 1024 valeurs possibles. Ce qui, vous le verrez, est déjà très bien.

L'autre limite de l'Arduino est que le signal reçu ne doit pas être supérieur à +5V.

Mais où sont donc ces 6 CAN ? 

Prenez votre carte et observez cette zone :

Les entrées analogiques de L'Arduino
Les entrées analogiques de l'Arduino

Vous voyez 6 connexions possibles, notées A0, A1, A2, A3, A4, et A5. C'est ici que l'on peut connecter un fil pour recevoir un signal analogique. L'Arduino le transformera ensuite en signal numérique compris entre 0 et 1023.

Nous allons donc de ce pas réaliser un montage et un programme qui permet de numériser (c'est-à-dire convertir une valeur analogique en valeur numérique) les valeurs de la tension aux bornes d'un potentiomètre.

Tout d'abord, voici le schéma électrique :

Connexion d'un potentiomètre au pin A0 de l'Arduino
Connexion d'un potentiomètre au pin A0 de l'Arduino

Les trois broches sont utilisées : l'une des extrémités au +5V, l'autre au ground, et le curseur au pin A0.

Nous voyons donc que le courant part du +5V, entre dans le potentiomètre par l'une des deux pattes d'extrémité, puis sort par le curseur vers le pin A0 de l'Arduino. La connexion au ground permet la lecture par l'Arduino de la valeur de position du curseur.

Voici l'image de montage :

Montage d'un potentiomètre pour lecture sur l'entrée A0
Montage d'un potentiomètre pour lecture sur l'entrée A0

Vous remarquerez que j’utilise un potentiomètre rotatif de valeur 10 kΩ, je vous propose de faire de même. 

Bien, maintenant comment allons nous procéder pour récupérer la valeur ?

Nous allons utiliser un mot-clé du langage de programmation :  analogRead(pin);. La valeur "pin" entre les parenthèse peut être : A0, A1, A2, A3, A4 ou A5. Il est possible d'enlever le A devant le chiffre et d'écrire juste : 0, 1, 2, 3, 4 ou 5. Les deux écritures suivantes sont correctes pour lire une valeur sur le pin A2 :

analogRead(A2);
analogRead(2);

Grâce à la fonction  analogRead, l'Arduino va nous renvoyer un nombre de type  int compris entre 0 et 1023. Il est de bon ton de le stocker dans une variable de type  int. Par exemple comme ceci :

int valeurPot; //déclaration de la variable qui va stocker la valeur numérique de la tension du potentiomètre
valeurPot=analogRead(A0); //On stocke la valeur lue par le CAN A0 dans la variable valeurPot

Et mieux encore, pour une lecture du code plus agréable et des connexions plus simples, on peut stocker la valeur du pin concerné dans une variable de type  int. Donc comme ceci :

int pinPot=0; //on va lire sur le pin A0 de l'arduino
int valeurPot; //on déclare la variable qui va stocker la  tension du potentiomètre
valeurPot=analogRead(pinPot); //on lit et stocke la valeur.

Vous savez utiliser la console pour afficher une valeur. Je vous propose d'essayer par vous-mêmes d'écrire le code qui affiche la valeur d'un potentiomètre connecté au pin A0 de l'Arduino (comme dans le montage proposé). Comme d'habitude, même si je me répète, je vous conseille d'essayer de créer ce code par vous-mêmes 

Voici donc le code en question :

int pinPot=0; //variable pour définir le CAN où est connecté le potentiomètre
int valPot=0; //variable pour récupérer la tension aux bornes du potentiomètre traduite par le CAN . On l’initialise à 0.
void setup() {
  Serial.begin(9600); //Initialisation de la communication avec la console
}

void loop() {
  valPot=analogRead(A0); //lit la tension, la convertit en valeur numérique et la stocke dans valeurPot
  Serial.print("Valeur lue : ");
  Serial.println(valPot);
}

Ouvrez votre console et observez les résultats lorsque vous tournez la molette du potentiomètre. Je sais pas vous, mais moi ça me fait toujours de l'effet .

Vous remarquerez que la précision de l'Arduino (sa résolution) est largement suffisante. En effet, il est très difficile de réussir à faire progresser les nombres de 1 en 1.

Voyons donc maintenant une application possible de ce que nous venons d'apprendre... (Lukas, ce n'est pas un accélérateur, et merci de nous faire grâce des bruits de moto !)

Le clignotant à vitesse variable

Vous avez déjà, dans les chapitres précédents, fait clignoter une LED. Je vous propose de concevoir un programme qui répondrait au cahier des charges suivant (ça claque de le dire comme ça je trouve...) :

  • La LED du montage clignote plus ou moins vite en fonction de la position du curseur du potentiomètre.

  • Au plus lent, elle clignote toutes les secondes. C'est à dire qu'elle s'allume 0,5 s et s'éteint pendant 0,5 s.

  • Au plus rapide, elle clignote 5 fois par seconde (5 Hz), donc elle s'allume pendant 0,1 s et s'éteint pendant 0,1 s de façon répétitive.

  • Elle doit prendre les valeurs précises de clignotement de 1 fois par seconde, 2 fois par seconde, 3 fois par seconde, 4 fois par seconde ou 5 fois par seconde. Mais pas de valeurs intermédiaires. Le temps d'allumage est le même que le temps d'extinction.

Je vous propose de chercher d'abord seul (Lukas je vous ai entendu... oui je l'ai déjà dit, mais je le répète !) pour voir la difficulté éventuelle de cette réalisation.

Pour le montage, nous connecterons une diode sur le pin 8 (avec la résistance qui va bien ;) ) et le potentiomètre sur le pin A0.

Bon, je propose pour réussir ce projet de procéder par étape. Tout d'abord un clignotement sans l'obligation des temps de clignotement. En gros, on récupère la valeur du potentiomètre et on s'en sert de temps d'attente pour l'allumage et l'extinction.

Voici le code :

int pinPot=0; //variable pour le CAN utilisé
int valPot=0; //variable qui va stocker la tension lue. On l'initialise à 0.
int pinLED=8; // pin de connexion de la LED
void setup() {
  pinMode(pinLED,OUTPUT); //Mode OUTPUT pour le pin de LED
  digitalWrite(pinLED,HIGH);//On allume la LED
}

void loop() {
  valPot=analogRead(A0); //lit la valeur de tension, la transforme et la stocke dans la variable
  int attente=valPot; //le délai d'attente est la valeur du potentiomètre
  digitalWrite(pinLED,HIGH); //on allume la LED
  delay(attente); //on attend en fonction de la variable attente
  digitalWrite(pinLED,LOW); //on éteint la LED
  delay(attente); //on attend
}

Les commentaires devraient suffire à le comprendre. Testez-le pour en voir le résultat.

Maintenant, comment faire pour que la variation de l'attente soit par paliers ?

Il suffit par exemple de faire un tableau de valeur d'attente. On sait que la valeur du potentiomètre est entre 0 et 1023. Il nous faut 5 types de clignotement. On divise donc 1024 par 5 :

1024/5=204.8  que l'on arrondit à 205 (C'est toujours mieux d'utiliser des entiers avec un ordinateur, ça prend moins de place en mémoire).

Donc il nous suffira de tester les valeurs et de définir la valeur d'attente qui correspond. Soit 1 000 millisecondes, divisées par le nombre de clignotement et divisé par 2 car même temps d'allumage que d'extinction.

Valeur du potentiomètre

Valeur d'attente

entre 0 et 204

1000/5/2=100ms

entre 205 et 408

1000/4/2=125ms

entre 409 et 613

1000/3/2=167ms (on arrondit)

entre 614 et 818

1000/2/2=250ms

entre 818 et 1023

1000/1/2=500ms

Il suffit ensuite de faire les tests avec des  if pour définir la valeur d'attente. Voici une première proposition de code :

int pinPot=0; //variable pour le pin où est connecté le potentiomètre
int valPot=0; //variable pour récupérer la valeur lue. On l'initialise à 0.
int pinLED=8;
void setup() {
  pinMode(pinLED,OUTPUT);
  digitalWrite(pinLED,HIGH);
}

void loop() {
  valPot=analogRead(A0); //lit la valeur, la transforme et la stocke dans la variable
  int attente=500;
  if (valPot>=0 && valPot<=204){
    attente=100;
  }
  if (valPot>=205 && valPot<=408){
    attente=125;
  }
  if (valPot>=409 && valPot<=613){
    attente=167;
  }
  if (valPot>=614 && valPot<=818){
    attente=250;
  }
  if (valPot>=818 && valPot<=1023){
    attente=500;
  }
  digitalWrite(pinLED,HIGH);
  delay (attente);
  digitalWrite(pinLED,LOW);
  delay(attente);
}

Vous remarquerez les tests entre les parenthèses des  if : on utilise le  && qui signifie en informatique : "et".

Nous reviendrons dans un autre chapitre aux différentes possibilités offertes par les tests.

Voici maintenant un code différent qui est basé sur le même principe, qui fait donc la même chose, mais dont la construction des tests change :

int pinPot=0; //variable pour le pin où est connecté le potentiomètre
int valPot=0; //variable pour récupérer la valeur lue. On l'initialise à 0.
int pinLED=8;
void setup() {
  pinMode(pinLED,OUTPUT);
  digitalWrite(pinLED,HIGH);
}

void loop() {
  valPot=analogRead(A0); //lit la valeur, la transforme et la stocke dans la variable
  int attente=100;
  if (valPot>817){
    attente=500;
  }
  else if (valPot>613){
    attente=250;
  }
  else if (valPot>408){
    attente=167;
  }
  else if (valPot>204){
    attente=125;
  }
  digitalWrite(pinLED,HIGH);
  delay (attente);
  digitalWrite(pinLED,LOW);
  delay(attente);
}

Vous remarquez que j'utilise un  else if qui permet de passer aux autres tests si le test précédent n'est pas vérifié. Je fais gagner du temps à l'Arduino car c'est plus rapide de comparer a>b que a>=b. Si aucun des tests n'est vérifié, la variable  attente  prend la valeur qu'on lui a assignée au début de la  loop (valeur 500 dans notre exemple).

Et si on simplifiait encore plus ce code ?

Tout à l’heure nous avons vu que la valeur d’attente pouvait se définir comme une variable :

attente = int(1000/valInter/2)

Il ne reste donc plus qu’à calculer  valInter  ! Pour ça, il n’y a rien de tel qu’une petite règle de trois : 

1024

5

valPot

valInter

où  valInter représente la correspondance entre 1 et 5 des valeurs entre 0 et 1023 et est peut donc être calculée de la façon suivante : 

int valInter=int(valPot*5/1024)+1

Explications :

  • Je rappelle que le signe de la multiplication est l'étoile :  *.

  • On entoure le calcul de parenthèses en mettant 'int' devant, ce qui va transformer un nombre à virgule (type  float) en nombre sans virgule (type  int).

  • On met 1024 dans le calcul (même si les valeurs vont de 0 à 1023). En effet, avec 1023  on obtient un nombre entre 0 et 5 (soit 6 positions). Là on obtient un nombre entre 0 et 4 (donc 5 positions).

  • Le +1 permet d'avoir un nombre entre 1 et 5.

Maintenant que nous avons notre correspondance entre 1 et 5, nous reprenons le calcul précédent :

int attente=int(1000/valInter/2)

Ça représente 1 seconde divisée par le nombre de clignotements. On divise par deux pour avoir le temps qui correspond à l'allumage et à l'extinction.

Voici donc le code  :

int pinPot=0; //variable pour le pin où est connecté le potentiomètre
int valPot=0; //variable pour récupérer la valeur lue. On l'initialise à 0.
int pinLED=8;
void setup() {
  pinMode(pinLED,OUTPUT);
  digitalWrite(pinLED,HIGH);
}

void loop() {
  valPot=analogRead(A0); //lit la valeur, la transforme et la stocke dans la variable
  int valInter=int(valPot*5/1024)+1; //produit en croix
  int attente=1000/valInter/2; // calcul du temps d'arrêt
  digitalWrite(pinLED,HIGH);
  delay (attente);
  digitalWrite(pinLED,LOW);
  delay(attente);
}

Ha, les maths, ça simplifie souvent bien des choses, il faut juste réfléchir un peu avant ;)

Et là, maintenant, devant vos yeux ébahis, je vais sortir de mon chapeau, ou plutôt du chapeau de l'Arduino, la petite formule qui va bien !!!

Le mappage de valeurs

Il faut savoir que le langage de l'Arduino propose directement une fonction qui va nous éviter tous ces calculs !

Elle se présente sous cette forme :

map(valeur,min,max,transMin,transMax);

avec :

  • valeur : c'est la valeur que vous voulez transformer (la tension du potentiomètre du potentiomètre dans notre cas)

  • min et  max : c'est la plage de valeurs (le minimum et le maximum qu'elle peut prendre, soit ici 0 et 1 023 qui correspond à la plage de résolution du CAN de l'Arduino)

  • transMin et  transMax : c'est la plage de valeurs dans laquelle on doit transformer la  valeur (ici 1 et 5, car nous attendons 5 positions différentes)

 On peut donc utiliser la fonction map ainsi dans notre exemple :

int valInter=map(valPot,0,1023,1,5);

Voici donc le code modifié avec l'utilisation de la fonction  map :

int pinPot=0; //stocke le CAN utilisé
int valPot=0; //variable pour récupérer la valeur de tension du potentiomètre. On l'initialise à 0.
int pinLED=8;
void setup() {
  pinMode(pinLED,OUTPUT); //mode OUTPUT pour le pin de LED
  digitalWrite(pinLED,HIGH);//on allume la LED
}

void loop() {
  valPot=analogRead(A0); //lit la valeur de la tension, la numérise et la stocke dans valPot
  int valInter=map(valPot,0,1023,1,5); //fonction de mappage
  int attente=1000/valInter/2; // calcul du temps d'arrêt
  digitalWrite(pinLED,HIGH); //on allume la LED
  delay (attente); //attente calculée
  digitalWrite(pinLED,LOW); //on éteint la LED
  delay(attente); //même attente
}

Ce qui est pratique avec cette fonction, c'est qu'elle peut aussi inverser des valeurs, ou donner une échelle de résultats négatifs. Voici deux exemples :

Appel de la fonction map()

Action

Résultat entier

int valRes=map(128,0,1000,10,0);

Transforme la valeur 128, initialement située entre 0 et 1000, en une valeur entre 10 et 0.

valRes=9

int valRes=map(128,0,1000,-10,10);

Transforme la valeur 128, initialement située entre 0 et 1000, en une valeur entre -10 et 10.

valRes=-8

Avant de passer au chapitre suivant, voyons une dernière application des potentiomètres qui devrait vous plaire…

Le joystick

Nous allons profiter d'avoir aborder les potentiomètres pour parler du joystick (oui Lukas, j'arrive aussi à traduire) que tous les gamers ont entre leurs mains. 

Autrefois, le joystick ne permettait pas une grande précision dans le mouvement. En effet, il s'agissait d'un manche pouvant bouger sur deux axes : avant, arrière, droite et gauche. À chaque mouvement, le manche actionnait un interrupteur qui envoyait un signal binaire à l'ordinateur (quand l'axe était déplacé).

Grâce à l'échantillonnage numérique, les joysticks ont donc gagné en précision. En effet, au lieu d'interrupteurs simples, chaque axe est relié à un potentiomètre (un pour avant/arrière, un pour droite/gauche).

Ce qui permet maintenant, non plus d'avoir un résultat binaire (axe activé ou non) mais une grande nuance de positions possibles entre les axes avant et arrière, et droite et gauche.

Si vous êtes très bricoleur, vous pouvez tenter d'en fabriquer un. Mais sachez qu'il en existe qui sont déjà montés (juste quelques soudures à réaliser) et que l'on trouve dans le commerce comme celui qui suit par exemple, mais il n'est pas le seul format.

Joystick interfaçable avec l'Arduino
Joystick interfaçable avec l'Arduino

Vous pouvez voir un des deux potentiomètres à droite sous le manche.

Une fois connecté, il suffit de récupérer les valeurs des potentiomètres sur entrées analogiques de l'Arduino, de mapper les valeurs avec la fonction  map pour qu'elles correspondent à vos besoins, et le tour est joué !

Petit bonus, ces joysticks ont aussi un bouton poussoir qui s'actionne en appuyant sur le manche verticalement.

Bien je crois qu'on a assez appris sur le potentiomètre, si nous passions au mouvement ?

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