Mis à jour le jeudi 13 juillet 2017
  • 20 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 le pilotage infrarouge

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

Dans ce chapitre il s'agit de voir comment l'Arduino peut lire et interpréter les informations envoyées par une télécommande infrarouge (ou un autre équipement qui envoie un code infrarouge).

Le capteur infrarouge

Les  capteurs de type TSOP permettent de capter un signal infrarouge. Ce n'est donc pas seulement la présence d'une lumière infrarouge qui les fait réagir : il faut que cette lumière clignote dans une certaine fréquence pour qu'ils réagissent. Cette fréquence est de 38 kHz pour les deux TSOP.

Tout d'abord, il faut être attentif aux connexions ! Les TSOP ont 3 broches :

  • Une à connecter au ground ;

  • Une à connecter au +5V ;

  • Une à connecter à un pin numérique en mode input.

En fonction du TSOP que vous avez entre les mains, les connexions ne sont pas les mêmes ! Il est important de vous référer à la datasheet de votre composant (en tapant sur un moteur de recherche son nom). Vous aurez accès alors à un schéma pour connecter correctement votre composant. Un exemple simple ci-dessous :

Broches pour TSOP38238 (gauche) et TSOP1737 (droite)
Broches pour TSOP38238 (gauche) et TSOP1738 (droite)

Nous allons pour ce chapitre, utiliser le TSOP38238 (celui de gauche sur l'image). Il faut donc connecter la patte 1 sur le pin numérique pour la lecture, la patte 2 sur le ground et  la patte 3 sur le +5V.

Dans un premier temps, nous allons tester si le capteur est fonctionnel. Pour ce faire nous allons utiliser un montage simple, qui ne nécessite pas de programmation.

Lorsqu'un TSOP reçoit un signal infrarouge, il passe sa sortie à LOW. Nous allons donc le connecter en ajoutant une LED (visible à l'oeil nu, contrairement aux LED infrarouges) qui s'allumera lorsque le TSOP recevra un signal. Voici le montage :

Test d'un TSOP 38238 avec LED visible
Test d'un TSOP 38238 avec LED visible

Si vous prenez une télécommande infrarouge (celle de votre télévision, de votre chaîne hi-fi, de votre vidéo projecteur...) et que vous appuyez sur un bouton, vous devriez voir la LED clignoter rapidement. Si c'est le cas, votre TSOP est correctement connecté et il fonctionne.

La lumière infrarouge n'est pas visible par l'œil humain. C'est la raison pour laquelle on utilise une LED simple.

Là encore, attention à la connexion en fonction de votre TSOP ! Promis, je ne vous le dis plus. ;)

Bien passons maintenant à l'étape suivante...

Décoder un signal infrarouge

Il n'est pas si simple de décoder un signal infrarouge. En effet, il existe des normes de communications qui dépendent des propriétaires (constructeurs) des appareils pilotés par infrarouge. Du coup, lorsqu'on appuie sur le bouton pour augmenter le volume sur une télécommande, le code infrarouge n'est pas le même s'il s'agit d'une télécommande SANYO, HITACHI, YAMAHA...

Ce qui veut dire que votre programme doit prendre en compte ces différences.

Je vous conseille de choisir une télécommande et de vous y tenir, ce qui vous évitera de modifier votre code à chaque fois !

Le montage que nous avons effectué dans la section précédente allume une LED lorsqu’il reçoit un signal infrarouge.  On imagine bien que si on connecte la sortie (OUT) du TSOP à un pin numérique en mode INPUT, nous serons à même d'obtenir une sorte d'image du code envoyé.

Quelques points à savoir :

  • Une télécommande envoie un signal pulsé à environ 38KHz (comme peut le faire un port PWM de l'Arduino, mais à une fréquence différente). C'est-à-dire que le signal est une succession d'états hauts et bas sur une période d'environ 26 µs. C'est une valeur pour la plupart des télécommandes.

  • Ce signal pulsé est envoyé pendant un temps donné, puis s'arrête. Le code correspondant à un bouton de la télécommande est une suite de signaux émis pendant un temps précis, avec un temps d'arrêt précis entre chaque émission.

  • Le tout forme un code (qui peut être plus ou moins long en fonction des télécommandes).

Si nous voulons décoder un signal, il nous faut pouvoir lire chaque temps où le signal est pulsé et chaque temps où il ne l'est pas. L'avantage d'un capteur de type TSOP, c'est qu'il filtre les signaux à 38Khz (si vous avez le bon capteur) et du coup nous pouvons tenter de capter un signal haut (et non une succession de signaux haut et bas). C'est toute la différence avec une photodiode qui capterait tous les signaux émis !

Testons un premier programme :

const int pin = 8; // pin de lecture du TSOP
const int nbMax = 32; // nombre de lectures
int tableau[nbMax][2]; // tableau pour stocker les valeurs hautes et basses

void setup() {
  pinMode(pin, INPUT); // mode INPUT pour le pin de lecture
  Serial.begin(9600); //initialisation communication série
}

void loop() {
  if (digitalRead(pin)) { //si état haut capté
    lecture(); // appel de la fonction de lecture du code
    affichage(); // appel de la fonction d'affichage du résultat
  }
}

//fonction de lecture du code
void lecture() {
  for (int t = 0; t < nbMax; t++) { //boucle pour le nombre de lectures
    while (digitalRead(pin)) { // tant que état pulsé
      tableau[t][0]++; // on incrémente la valeur du tableau
    }
    while (!digitalRead(pin)) { // puis tant que état non pulsé
      tableau[t][1]++; // on incrémente l'autre valeur du tableau
    }
  }
}

// fonction d'affichage du résultat
void affichage() {
  for (int i = 0; i < 2; i++) { // boucle pour état Haut, puis état Bas
    for (int t = 0; t < nbMax; t++) { //lecture des valeurs
      Serial.print(tableau[t][i]); //affichage
      Serial.print ("\t"); //tabulation pour présentation
    }
    Serial.println(); //saut de ligne
  }
}

Ce programme montre que nous avons bien des codes qui se succèdent à l'état pulsé, puis un temps de repos après l’état pulsé. 

En revanche, il nous est difficile de savoir le temps exact écoulé entre chaque état. En effet nous ne savons pas réellement le temps passé entre chaque incrémentation.

Pour que notre programme soit plus efficace, il nous faut gérer deux points :

  • Le temps réel écoulé entre chaque lecture (et donc chaque incrémentation) ;

  • La vitesse de lecture du pin (donc la vitesse que la fonction  digitalRead(pin)  prend pour s'exécuter.

Juste avant de calculer le temps écoulé entre chaque lecture, il faut savoir que la fonction  digitalRead(pin) est une fonction qui comporte plusieurs instructions. Chaque instruction demande un certain temps d’exécution par la carte Arduino. Pour lire l'état d'un pin, on peut utiliser une méthode plus proche du langage machine (le langage de l'Arduino) : la lecture des registres.

Je vous ai déjà parlé des registres, mais sans vous en donner une explication réelle. Il faut savoir que chaque information de l'Arduino est contenue dans des cases mémoires, chacune avec des adresses (une position dans la mémoire de microprocesseur) définies et fixes. Faire appel à un registre (en lecture ou en écriture) revient à aller directement lire ou écrire dans cette case mémoire ! On gagne du temps mais le programme est beaucoup moins lisible.

Voici donc un programme qui compare, sur 10 mesures, le temps d'exécution de la fonction digitalRead(), et le temps de lecture directe du registre qui contient le pin 8 :

const int pin = 8; // constante de pin lu

void setup() {
  Serial.begin(9600); //initialisation communication série
  pinMode(pin, INPUT); // mise en mode input du pin
}

void loop() {
  calcule(); //appel de la fonction calcule
  delay(500); // délai pour l'affichage
}

void calcule() {
  int tableau[10][2]; //tableau de récupération des valeurs
  for (int t = 0; t < 10; t++) { //boule pour 10 mesures
    unsigned long tpsDep, tpsFin; // variables pour les temps
    tpsDep = micros(); // temps de départ
    digitalRead(pin); // fonction digitaRead()
    tpsFin = micros(); // temps de fin
    tableau[t][0] = tpsFin - tpsDep; // on met le résultat dans le tableau

    tpsDep = micros(); // temps départ
    boolean n = PINB & B00000001;  // lecture du registre
    tpsFin = micros(); // temps de fin
    tableau[t][1] = tpsFin - tpsDep; // on met le résultat dans le tableau
  }

  //affichage du tableau des résultats
  Serial.println("******");
  for (int i = 0; i < 2; i++) {
    for (int t = 0; t < 10; t++) {
      Serial.print(tableau[t][i]);
      Serial.print("\t");
    }
    Serial.println();
  }
  Serial.println();
}

Ce programme ne fonctionne qu'avec la lecture du pin 8 (bien qu'on n'en affiche pas le résultat) !

Vous obtenez une série de mesures qui vous permettent de comparer les vitesses d'exécution. Voici un exemple de résultat que j'obtiens :

******
8 8 8 8 4 4 8 8 8 8
4 0 4 4 4 4 4 0 0 4

La première ligne correspond au temps mis en microsecondes pour exécuter la fonction  digitalRead() .

La seconde ligne correspond au temps mis en mircrosecondes pour lire directement le registre (en extrayant le résultat correspondant au pin 8).

On remarque que la fonction digitalRead(pin) est souvent deux fois plus lente que la lecture directe des registres. Cela peut paraître faible comme différence, mais il faut savoir que pour la lecture des temps d'un code de télécommande, c'est important !

La fonction micros() est elle même gourmande en temps, ce qui explique parfois la différence entre les résultats. De plus elle ne réalise des mesures que par tranche de 4µs (c'est dû au paramétrage du timer 0 de l'Arduino), d'où ces résultats multiples de 4.

Nous allons donc modifier notre programme de décodage pour obtenir des résultats plus proche de la réalité :

  • Utilisation de la lecture directe du registre attaché au pin 8 ;

  • Temporisation de la lecture sur une période de 25µs ajustable.

Voici le code proposé :

const int pin = 8; // pin de lecture du TSOP
const int nbMax = 64; // nombre de lectures
const int temporisation=25;
unsigned int tableau[nbMax][2]; // tableau pour stocker les valeurs hautes et basses

void setup() {
  pinMode(pin, INPUT); // mode INPUT pour le pin de lecture
  Serial.begin(9600); //initialisation communication série.
}

void loop() {
  if (digitalRead(pin)) { //si état haut capté
    lecture(); // appel de la fonction de lecture du code
    affichage(); // appel de la fonction d'affichage du résultat
  }
}

//fonction de lecture du code
void lecture() {
  for (int t = 0; t < nbMax; t++) { //boucle pour le nombre de lectures
    while (PINB & B00000001) { // tant que état pulsé
      tableau[t][0]++; // on incrémente la valeur du tableau
      delayMicroseconds(temporisation);
    }
    while (!(PINB & B00000001)) { // puis tant que état non pulsé
      tableau[t][1]++; // on incrémente l'autre valeur du tableau
      delayMicroseconds(temporisation);
    }
  }
  delay(200);
}

// fonction d'affichage du résultat
void affichage() {
  Serial.println("*");
  for (int i = 0; i < 2; i++) { // boucle pour état Haut, puis état Bas
    for (int t = 0; t < nbMax; t++) { //lecture des valeurs
      Serial.print(tableau[t][i]*temporisation); //affichage en microsecondes
      Serial.print ("\t"); //tabulation pour présentation
      tableau[t][i]=0; //effacement de la valeur pour prochaine lecture
    }
    Serial.println(); //saut de ligne
  }
}

Nous avons maintenant une lecture un peu plus fiable des codes envoyés par la télécommande.

Mais que peut-on faire de ces codes ?

Et bien nous allons les exploiter ! Et pour y arriver, nous allons procéder en deux temps :

  1. D'abord la construction d'un programme qui lit et reconnaît les boutons, et qui nous affiche la succession de temps à prendre en compte.

  2. Ensuite, grâce à d'habiles copier/coller, nous construirons un autre programme qui lui utilisera ces codes pour piloter un servo-moteur (par exemple ;)) grâce aux même boutons de la télécommande.

Tout le principe résidera surtout dans le premier programme. Alors munissez-vous de votre matériel, de votre matière grise, de votre bonne humeur et d'une dose de courage et c'est parti !

(Non Lukas, une paire de moufles n'est pas utile dans cette liste...)

Détecter, stocker et reconnaître un signal infrarouge

Nous allons partir du programme précédent en lui apportant quelques améliorations :

  • On décode le signal envoyé par la télécommande et on le stocke dans un tableau.

  • On compare le code du signal pulsé reçu par le pin 8 aux codes des commandes déjà trouvées (on réalise la comparaison sur une marge d'erreur de 20% par temps pulsé et non pulsé).

  • Si le code correspond à une commande déjà trouvée, on indique quelle touche a été appuyée sur la télécommande.

  • Sinon on ajoute une commande et on propose de la nommer (facultatif, mais plus joli).

  • Le code affichera aussi la suite des temps trouvés pour pouvoir les exploiter avec un simple copier/coller.

Je ne vais pas procéder par étape, mais vous livrer le code tout prêt avec les commentaires ad-hoc (oui Lukas, comme le capitaine !) : 

/*
 * Décodeur infrarouge
 * by Nanomaitre 2015 pour OpenClassRooms
 * Ce programme vous permet de décoder et stocker
 * des commandes infrarouges liées à votre télécommande
 * Si la commande est reconnue, il vous indique la corrrespondance
 * Sinon, il vous propose de l'ajouter en la nommant.
 * Le programme affiche aussi le tableau de résultats
 * qu'il suffit ensuite de copier/coller dans un autre code si besoin
 * /!\ Le pin 8 est utilisé pour ce test, il ne faut pas le changer !!
 * Ce code est dans le domaine public
 */


const int pin = 8; // pin de lecture du TSOP
const int nbMax = 32; // nombre maximum de lectures
const int nbMaxCom = 5; // nombre maximum de commandes stockées
String noms[nbMaxCom] = {""}; // tableau pour stocker les noms des commandes (sur 5 char)
const int temporisation = 20; // temporisation de lecture des signaux pulsés
unsigned int tableau[nbMax * 2] = {0}; // tableau pour stocker les temps lus
unsigned int commandes[nbMaxCom][nbMax * 2] = {0}; // tableau pour stocker les temps des commandes reconnues
int nbCommande = 0; // numéro de commande en cours

void setup() {
  pinMode(pin, INPUT); // mode INPUT pour le pin de lecture
  Serial.begin(9600); //initialisation communication série.
}

void loop() {
  Serial.println("Go..."); //signal l'attente d'un appui
  while (PINB & B00000001);//attend un signal haut en boucle
  lecture(); // appel de la fonction de lecture du code
  affichage(); // appel de la fonction d'affichage
  delay(1000); // attente d'une seconde
}

//fonction de lecture du code
void lecture() {
  for (int t = 0; t < nbMax * 2; t += 2) { //boucle pour le nombre de lectures, progresse de 2 en 2
    while (PINB & B00000001) { // tant que état pulsé
      tableau[t] += temporisation; // on incrémente la valeur du tableau
      delayMicroseconds(temporisation); //attente
    }
    while (!(PINB & B00000001)) { // puis tant que état non pulsé
      tableau[t + 1] += temporisation; // on incrémente l'autre valeur du tableau
      delayMicroseconds(temporisation);
    }
  }
}

// fonction d'affichage du résultat
void affichage() {
  // on crée un affichage copiable sur la console
  Serial.print("const unsigned int code[");
  Serial.print(nbMax * 2 + 1, DEC);
  Serial.print("]={");
  for (int t = 0; t < nbMax * 2; t += 2) {
    Serial.print(tableau[t], DEC);
    Serial.print(", ");
    Serial.print(tableau[t + 1], DEC);
    Serial.print(", ");
  }
  Serial.println("0}");
  compare();//on appelle la fonction de comparaison
  //on efface le tableau pour la prochaine lecture
  for (int t = 0; t < nbMax * 2; t++) {
    tableau[t] = 0;
  }
}

//fonction de comparaison
int compare () {
  boolean trouve = 0; // drapeau de commande trouvée
  for (int c = 0; c < nbMaxCom; c++) { //boucle sur les commandes
    int nbCor = 0; // variable de validation de comparaison
    for (int t = 0; t < nbMax * 2; t++) { // on parcourt les résultats
      int tmoins = tableau[t] - tableau[t] * 20 / 100; // valeur-20%
      int tplus = tableau[t] + tableau[t] * 20 / 100; // valeur+20%
      if (commandes[c][t] > tmoins && commandes[c][t] < tplus && t > 0) { //si dans la fourchette (sauf première valeur)
        nbCor++; // on valide la comparaison
      }
    }
    if (nbCor == nbMax * 2 - 1) { //si tout est validé (sauf première valeur)
      // On affiche la touche correspondante
      Serial.print("Correspondance avec commande ");
      Serial.print(c);
      Serial.print(" = ");
      Serial.println(noms[c]);
      trouve = 1; // on indique que la commande est déjà existante
    }
  }
  if (!trouve && (nbCommande < nbMaxCom)) { //si commande non existante et encore possible d'en ajouter
    //on crée la commande en copiant le tableau des résultats
    for (int t = 0; t < nbMax * 2; t++) {
      commandes[nbCommande][t] = tableau[t];
    }
    //on affiche qu'une nouvelle commande est trouvée
    Serial.println("ajout commande");
    Serial.println("Donner un nom (5 char max) :");
    //et on saisit son nom
    while (!Serial.available())
      noms[nbCommande] = "";
    for (int t = 0; t < 5; t++) {
      char ch = Serial.read();
      if (ch > 32)
        noms[nbCommande] += String(ch);
      delay(10);
    }
    //on vide le cache de réception
    while (Serial.available()) {
      Serial.read();
      delay(10);
    }

    nbCommande++; //on incrémente la commande en cours
  }
  Serial.println();
}

Voyons maintenant comment utiliser une télécommande infrarouge pour piloter un servo-moteur grâce à la carte Arduino…

TP : Piloter un servo-moteur avec une télécommande infrarouge et un Arduino

Je vous propose de réaliser vous-mêmes ce programme. En voici le principe : grâce à 5 touches de votre télécommande (de télévision par exemple), vous allez piloter un servo-moteur.

  • Pour les connexions et le pilotage du servo, vous utiliserez la bibliothèque Servo (vous pouvez vous référer à la section sur cette bibliothèque dans mon cours d'initiation à l'Arduino).

  • Une touche mettra le servo à 0°.

  • Une seconde touche le positionnera à 179°.

  • Une troisième le positionnera à 90°.

  • Une quatrième le fera aller vers les 179° avec un pas de 1° par tour de boucle (attention aux limites).

  • Une cinquième le fera aller vers les 0° avec un pas de 1° par tour de boucle (attention aux limites).

  • Le tout vous permettra de piloter un servo moteur à distance !!!

Je vous donne quelques conseils tout de même pour vous guider un peu...

  • Vous devrez choisir une télécommande qui répond au programme précédent.

  • Il vous faudra copier/coller les codes correspondant aux touches que vous allez utiliser, grâce aux affichages du programme précédent (avec des modifications de noms de variable peut-être).

  • Pour la reconnaissance du code, vous pourrez vous inspirer de la fonction  compare() du programme précédent.

  • Créez des fonctions qui permettent de mieux vous situer dans votre code.

Allez, c'est parti ! Ne lâchez rien et essayez d'aller au bout de ce projet. Ce n'est pas simple certes, mais vous avez assez de connaissances !

TP : Correction

J'espère que vous avez réussi à vous dépatouiller tout seul. Si vous avez réussi, je vous félicite !

/*
 * Pilotage de servomoteur par télécommande Infrarouge
 * by Nanomaitre pour OpenClassRooms
 * Ce programme déplace un servo-moteur en fonction
 * des touches appuyées d'une télécommande
 * Ce code est dans le domaine public
 */

#include "Servo.h" // on ajoute la bibliothèque Servo
const int pinServo = 2; // constante de pin pour le servomoteur
Servo monServo; // on définit l'objet Servo nommé monServo
//tableau qui stocke les codes : 5 codes de 65 valeurs
// /!\ Attention il correspond aux valeurs de ma télécommande
//Pour la vôtre, il faut utiliser le programme "Décodeur infrarouge"
//et créer ce tableau !
const unsigned int codes[5][65] = {
  0, 8620, 4240, 580, 1580, 560, 1580, 580, 500, 560, 500, 560, 1580, 580, 1580, 560, 500, 580, 480, 580, 500, 580, 480, 580, 500, 560, 500, 580, 480, 580, 500, 560, 500, 560, 500, 580, 500, 560, 500, 580, 1560, 580, 1580, 580, 1580, 560, 500, 560, 500, 580, 500, 560, 1580, 580, 1580, 560, 500, 560, 500, 580, 500, 560, 1580, 580, 0,
  0, 8580, 4280, 540, 1620, 540, 1600, 540, 540, 540, 520, 540, 1600, 560, 1600, 540, 520, 540, 540, 540, 520, 540, 520, 560, 520, 540, 520, 540, 520, 560, 520, 540, 520, 540, 520, 560, 520, 540, 520, 540, 1620, 540, 1600, 540, 540, 540, 520, 540, 520, 560, 1600, 540, 1600, 540, 1620, 540, 520, 540, 540, 520, 1620, 540, 1600, 560, 0,
  0, 8620, 4240, 580, 1580, 560, 1580, 580, 500, 560, 500, 560, 1580, 580, 1580, 580, 480, 580, 480, 580, 500, 580, 480, 580, 500, 560, 500, 560, 500, 580, 500, 560, 500, 580, 480, 580, 1580, 580, 480, 580, 1580, 580, 1560, 580, 500, 560, 500, 560, 500, 580, 1580, 560, 500, 580, 1580, 560, 500, 580, 480, 580, 1580, 580, 1580, 560, 0,
  0, 8620, 4240, 560, 1580, 580, 1580, 560, 500, 580, 480, 580, 1580, 580, 1580, 560, 500, 580, 480, 580, 500, 560, 500, 560, 500, 580, 500, 560, 500, 560, 500, 580, 500, 560, 500, 580, 1580, 560, 500, 560, 1600, 560, 1580, 580, 1560, 580, 500, 580, 480, 580, 500, 560, 500, 560, 1580, 580, 500, 560, 500, 580, 500, 560, 1580, 580, 0,
  0, 8620, 4240, 580, 1580, 560, 1580, 580, 500, 560, 500, 560, 1580, 580, 1580, 560, 500, 580, 500, 560, 500, 560, 500, 580, 500, 560, 500, 580, 480, 580, 500, 560, 500, 560, 520, 560, 500, 560, 1580, 580, 1580, 560, 1580, 580, 1580, 560, 500, 580, 500, 560, 500, 580, 1560, 580, 500, 580, 480, 580, 480, 580, 500, 560, 1580, 580, 0
};
//Tableau des noms pour chaque code
String noms[5] = {"90 deg", "179 deg", "0 deg", "Vers 179 deg", "Vers 0 deg"};
const int pin = 8; // pin de lecture du TSOP
const int nbMax = 32; // nombre maximum de lectures
const int temporisation = 20; // temporisation de lecture des signaux pulsés
unsigned int tableau[nbMax * 2] = {0}; // tableau pour stocker les temps lus
int posServo = 90; // variable de position du servomoteur
int ajServo = 0; // variable de déplacement du servomoteur
int nbCode = 0; // numéro de code en cours
unsigned long tpsDep = millis(); // initialisation du temps
void setup() {
  monServo.attach(pinServo); // attache l'objet monServo à pinServo
  pinMode(pin, INPUT); // mode INPUT pour le pin de lecture
  Serial.begin(9600); //initialisation communication série.
}

void loop() {
  while (PINB & B00000001) // tant que aucun signal
    bougeServo(); // on gère le servomoteur
  //sinon
  lecture(); // appel de la fonction de lecture du code


}

//fonction de lecture du code
void lecture() {

  for (int t = 0; t < nbMax * 2; t += 2) { //boucle pour le nombre de lectures, progresse de 2 en 2
    while (PINB & B00000001) { // tant que état pulsé
      tableau[t] += temporisation; // on incrémente la valeur du tableau
      delayMicroseconds(temporisation); //attente
    }
    while (!(PINB & B00000001)) { // puis tant que état non pulsé
      tableau[t + 1] += temporisation; // on incrémente l'autre valeur du tableau
      delayMicroseconds(temporisation);
    }
  }
  delay(500); //délai pour ne plus rien recevoir
  compare(); // appel de la fonction de comparaison
  positionServo(); // appel de la fonction de positionnement du servomoteur
}


//fonction de comparaison
int compare () {
  boolean trouve = 0; // drapeau de commande trouvée
  for (int c = 0; c < 5; c++) { //boucle sur les codes
    int nbCor = 0; // variable de validation de comparaison
    for (int t = 0; t < nbMax * 2; t++) { // on parcourt les résultats
      int tmoins = tableau[t] - tableau[t] * 20 / 100; // valeur-20%
      int tplus = tableau[t] + tableau[t] * 20 / 100; // valeur+20%
      if (codes[c][t] > tmoins && codes[c][t] < tplus && t > 0) { //si dans la fourchette (sauf première valeur)
        nbCor++; // on valide la comparaison
      }
    }
    if (nbCor == nbMax * 2 - 1) { //si tout est validé (sauf première valeur)
      // On affiche la touche correspondante
      Serial.print("Commande ");
      Serial.print(c);
      Serial.print(" => ");
      Serial.println(noms[c]);
      nbCode = c; // on indique le code en cours
      trouve = 1; // on indique que la commande a été trouvée
    }
  }
  if (!trouve) { //si commande non trouvée
    Serial.println("Commande inconnue...");
  }
  //on vide le tableau de lecture
  for (int t = 0; t < nbMax * 2; t++) {
    tableau[t] = 0;
  }
}

//Fonction de positionnement du servomoteur
void positionServo() {
  switch (nbCode) { //en fonction du code
    case 0: // on place le servo à 90°
      ajServo = 0;
      posServo = 90;
      break;
    case 1: // on place le servo à 179°
      ajServo = 0;
      posServo = 179;
      break;
    case 2: // on place le servo à 0°
      ajServo = 0;
      posServo = 0;
      break;
    case 3: // on met la variable de déplacement à 1°
      ajServo = +1;
      break;
    case 4: // on met la variable de déplacement à -1°
      ajServo = -1; 
      break;
  }
}
//fonction de déplacement du servomoteur
void bougeServo() {
  unsigned long tpsAct = millis(); //temps actuel
  if (tpsAct - tpsDep > 50) { //si 50ms passées
    posServo += ajServo; // on déplace le servo
    tpsDep = tpsAct; //on réinitialise le temps
  }
  if (posServo <= 0 || posServo >= 179) // si servo hors limite
    ajServo = 0; // on stoppe le déplacement
  monServo.write(posServo); // on envoie la position du servomoteur
}

Comme indiqué dans le programme, le tableau des codes correspond à mes codes. ;)

En lisant attentivement les commentaires, et en suivant le fil du programme, vous devriez avoir assez d'informations pour le comprendre. Faites-vous confiance !

Pour les vôtres, il vous faut utiliser le programme précédent et réaliser des copier/coller intelligents !

(Lukas, si vous débranchiez la télévision, ça éviterait de changer de chaîne à chaque fois que vous pilotez le servo-moteur...)

En résumé

Vous venez d'apprendre à utiliser un capteur infrarouge pour décoder les signaux émis par une télécommande afin de piloter votre Arduino.

Il existe une bibliothèque qui peut vous faciliter la vie : IRremote. On la trouve en téléchargement dans l'IDE. Il vous suffit de procéder à son téléchargement comme pour n'importe quelle bibliothèque.

Vous pouvez aussi consulter cette présentation de la bibliothèque IRemote pour cloner une télécommande infrarouge avec un Arduino. Une fois le mécanisme compris, il n'est pas difficile de le reproduire.

Sachez qu'il est aussi tout à fait possible de piloter un appareil en utilisant la carte Arduino comme “télécommande infrarouge” (c’est-à-dire en la faisant émettre des signaux infrarouges pulsés à partir du code copié d’une télécommande). Je ne m'y étendrai pas ici car il ne s'agit pas d'une interface homme/machine, mais le lien précédent vous montre un peu comment le faire avec la bibliothèque IRremote, et pour les anglophiles, vous trouverez des informations sur le site d'Adafruit sur ce tutoriel (qui complète d'ailleurs fort bien ce cours ;) ).

Bon nous en avons fini avec la programmation d'interfaces diverses et variées. Vous en trouverez dans le commerce de toutes sortes (pilotables ou non en I2C), l'important est de vous assurer qu'il existe des bibliothèques pratiques pour les piloter, ou tout au moins, que leur programmation est à votre portée. Ce qui devrait être le cas avec les quelques notions que vous venez de voir.

Dans les chapitres suivants, nous allons nous intéresser à la possibilité de connecter l'Arduino sur votre réseau...

Tout un programme !

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