Post

Masterclass : Comprendre et utiliser un émetteur et récepteur infrarouge avec Arduino

On décortique les protocoles de transmission infrarouge et les montages électroniques associés à l'émission et réception d'instruction distantes.

Masterclass : Comprendre et utiliser un émetteur et récepteur infrarouge avec Arduino

Une tech increvable

Historiquement, on est parti de télécommandes filaires, suivi de télécommandes qui balancent des flashs de lumière puis des ultrasons, pour enfin avoir un contrôle à base d’infrarouges. Et pendant 40 ans, la technologie de ce côté n’a quasiment jamais évolué. Certes, aujourd’hui de plus en plus de télé vont choisir le Bluetooth comme moyen de communication avec la télécommande, mais cela est encore loin de faire l’unanimité. Les récentes avancées en matière de domotique sont sans doute celles qui poussent de plus en plus de constructeurs d’avoir un matériel compatible avec le wifi ou au moins les systèmes radio pour s’intégrer avec la pléthore d’offres logicielle et domotique en constante évolution.

Reste que les télécommandes infrarouges sont encore absolument partout autour de nous et ont encore de beaux jours devant elles. Cet article qui va avec sa vidéo associée a pour but de vous apprendre les bases des protocoles de communication infrarouge en émission et réception à l’aide d’une Arduino.

Ressources

Pour ceux qui répondent à l’appel fait depuis la vidéo, voici la liste des ressources mentionnées :

La lumière infrarouge

La lumière qui rend tout ce qui nous entoure visible et que nous sommes capables de voir n’est que le résultat de l’interprétation d’ondes électromagnétiques par notre cerveau. Comme les ondes sonores qui viennent faire vibrer nos tympans, certaines ondes électromagnétiques vibrent à une certaine fréquence et possèdent une certaine longueur d’onde. Et une toute petite fraction du spectre électromagnétique est correctement interprétée par notre petit cortex visuel de babouin.

Voici une illustration qui vous montre la catégorisation du spectre électromagnétique. Comme vous pouvez le constater, le spectre des ondes visuelles se situe entre 400 et 800 nanomètres. En dessous de 400 nm, on parle alors d’ultra violet, cette lumière qui vous permet de bronzer, ou vous donne des coups de soleil. Au-dessus de 800 nm se trouvent les infrarouges qui nous intéressent aujourd’hui.

light_wave.png

Comment utiliser la lumière infrarouge

Tout corp genérant de la chaleur va émettre dans le spectre de l’infrarouge. Toute source de lumiére va émettre dans le spectre de l’infrarouge. Nous baignons littéralement dans une soupe d’infrarouge. Cependant, toute cette soupe est érratique, varie en intensité et en régularité. Ce qui fait que pour trancher avec tout le bruit infrarouge ambiant, l’industrie a opté pour canaliser les communications infrarouges sur une fréquence porteuse comprise entre 33 et 56 kHz. Cela permet de filtrer la majorité du bruit infrarouge ambient et permettre aux équipements récepteurs de ne pas constament s’agiter pour rien. La norme la plus courante est le 38 kHz.

À l’intérieur du module de reception infrarouge se trouve un démodulateur dont le seul boulot et de retirer le signal de la porteuse et de ne laisser passer que l’information restante. Les 38 000 batements par seconde de la porteuse sont enlevés pour ne laisser que la partie informative modulée selon differents type de modulations.

Les différentes façons de moduler l’information

Comme nous l’avons étudié en détail dans la vidéo/article sur le DHT11 et la modulation “1 wire”, pour communiquer de l’information via des impulsions, il suffit de convenir de quelques règles logiques sur les timings et de ce qui relève d’information importante à retenir de ce qui relève du sursaut. Un premier travail se fait au niveau matériel, on appelle cela : la modulation.

Modulation PWM

Si vous avez suivi la vidéo/article sur la LED RGB, alors vous devriez déjà avoir un très bon aperçu de la modulation PWM.

La modulation PWM tient de l’acronyme Pulse Width Modulation. Modulation de la largeur d’impulsion. Il découle du rapport entre le temps à l’état haut par rapport au temps passé à l’état bas. Sur l’image ci-dessous, vous pouvez comparer la ligne rouge à la ligne basse adjacente à droite, ou comparer la ligne bleue en rapport à la ligne basse à sa droite. Dans le 1er cas, le rouge représente 75% tandis que la ligne bleue représente 25%.

Il suffit ensuite de convenir que supérieur à 50% c’est un 1, et vous avez la base du fonctionnement de votre communication.

linecode_pwm.png

Modulation PDM

La modulation PDM indique Pulse Distance Modulation. Modulation de la distance d’impulsion. À ne pas confondre avec Pulse Density Modulation.

Beaucoup plus répandue dans le monde des modulations infrarouges, celle-ci joue sur la combinaison de deux informations. Un marqueur qui est un signal haut qui fait globalement toujours la même durée et qui sert de valeur étalon. Le marqueur est suivi d’une durée en signal bas qui contient l’information 0 ou 1. Lorsque le signal BAS fait la même durée que le marqueur, alors cela sera interprété par un 0.

Constatez par vous-même, on voit bien les 0 en bleu faire la même taille que les marqueurs qui les précèdent. En général le signal bas pour un 1 correspond à trois fois la durée du marqueur.

Remarquez que contrairement à la modulation PWM, pour passer la même information, le signal aura duré, au final, moins longtemps due aux zéros échangés.

linecode_distance.png

Modulation Manchester (bi-phase)

La modulation Manchester va cette fois se concentrer sur la phase de transition pour séparer les uns des zéros. Si le signal passe d’un état haut à un état bas, ce sera un 0, dans le cas contraire, cela sera un 1. Cette modulation peut commencer par une phase de calibration pour que le receveur puisse avoir une idée de la durée totale pour transmettre un bit d’information. Cela permet de séparer les transitions qui sont au milieu de l’échange d’un bit, des transitions qui sont en fin bit et qui servent à répéter le bit précédent et qu’il faudra ignorer.

Vous pouvez vous rendre compte de cet effet lors de l’échange des deux premiers 1. Une transition haut-bas a lieu entre eux et sera ignorée. Le même effet se reproduit plus tard entre les deux 0 d’affilé.

linecode_manchester.png

La couche logicielle

Maintenant équipé d’une modulation matérielle, il faut convenir d’une norme pour interpréter les 0 et 1 qui arrivent au récepteur. C’est ici que rentrent en scène les protocoles inventés par les différents constructeurs au fil des années. Par chance, beaucoup se sont juste contentés de protocoles standards, mais certains des plus gros fabricants de matériel électro-ménager y sont allés de leur propre petite recette.

En me basant sur ce que propose une librairie Arduino dédiée à l’infrarouge, je dénombre une trentaine de protocoles. Voici une partie d’entre eux sur cette infographie avec la taille de l’information qui transite et la modulation matérielle sous-jacente.

protocoles.png

RC-5 fait partie des pionniers utilisés avec les tout premiers systèmes infrarouges. NEC est celui qui va nous intéresser de près. PulseDistance est sans doute celui que vous verrez le plus souvent lorsque votre récepteur ne comprend pas à quelle famille la donnée qu’il vient de lire appartient.

La structure d’un protocole simple

Pour définir un protocole de communication, on va souvent s’appuyer sur un gabarit relativement standardisé. Il y aura évidemment toujours des subtilités propres aux équipements cherchant à communiquer entre eux, mais dans l’ensemble, on peut distinguer un motif se répéter. En ce qui concerne les protocoles pour les télécommandes, voici une structure assez commune :

  • Marqueur de début de communication
  • Nombre total de bits à échanger
  • Adresse de l’équipement
  • Commande à exécuter
  • Gestion des erreurs
  • Sens de lecture des bits reçus
  • Motif d’une répétition de commande
  • Marqueur de fin de communication

Le protocole NEC

Vu que le protocole NEC est très répandu et utilisé par tout constructeur qui a besoin d’une communication générique, nous allons étudier sa structure en détail.

protocole_nec.png

Concentrons-nous sur le diagramme qui décrit comment un message complet utilisant le protocole NEC est structuré. Ce protocole s’appuie sur une modulation de type PDM.

  1. Signal HAUT de 9ms suivi de signal BAS 4.5ms : c’est le header, un marqueur permettant de clairement définir qu’un message s’apprête à être transmis.
  2. Transmission de l’adresse de l’équipement. Binaire : 0000 0000. Hexadécimal : 0x00
  3. Transmission de l’inverse logique de l’adresse (NOT). Binaire : 1111 1111. Hexadécimal : 0xFF. Cette partie permet une gestion des erreurs. On envoie deux fois la même adresse de deux façons différentes pour enlever toute ambiguïté. Second rôle, faire en sorte que le bloc adresse + bloc commande fassent toujours la même durée de 27ms
  4. Transmission de la commande à exécuter. Binaire : 0110 1101. Hexadécimal : 0x6D.
  5. Transmission de l’inverse logique de la commande (NOT). Binaire : 1001 0010. Hexadécimal : 0x92. Même rôle. Gestion des erreurs et uniformisation de la durée.
  6. Signal HAUT de la durée du marqueur PDM de 562.5 μs pour marquer la fin du message.

Un total de 32 Bits sont transférés. Sans le marqueur de fin, cela dure un total de 67.5ms.

La liste des commandes présentées sur cette infographie sera la potentielle liste de commandes d’une télécommande NEC pour une télévision. Mais cela reste à titre indicatif. Personnellement, les deux télécommandes NEC que je possède ne suivent pas du tout la même norme.

La structure d’un protocole avancé

On vient de décrire le protocole NEC qui fait partie de ce qu’on pourrait appeler un “protocole simple”. Un bouton = une commande. Mais rendez-vous compte, nous avons utilisé 32 bits pour transmettre une adresse et une commande. C’est un énorme gaspillage.

Il existe un autre type de télécommande que vous avez sûrement déjà eu en main : les télécommandes à états. Typiquement, ce sont celles qui ont un écran comme pour contrôler les climatiseurs. Cette fois, on ne se contente pas de transférer 1 adresse et 1 commande sur 32 bits. Un usage bien plus complexe est fait de l’espace de données et beaucoup plus d’informations sont transmises en une fois.

À chaque fois que vous appuyez sur un bouton de la télécommande, elle lit tous les états en mémoires, reformule la chaîne de donnée à transmettre, et l’envoie. Cela implique qu’appuyer sur le bouton d’allumage tandis que la dernière fois, la clim était à 19 degrés, force 4, ne correspondra pas à la même donnée le lendemain tandis que la clim est à 22 degrés, force 2.

Voici à quoi nous pourrions faire correspondre les 32 bits d’une télécommande de climatiseur. Exemple complètement arbitraire inventé à la volée, lors de l’écriture de cet article.

concept_advanced.png

Voici ce à quoi chaque bit correspond :

  1. État ON/OFF (1 bit)
  2. Balayage vertical actif (1 bit)
  3. Balayage horizontal actif (1 bit)
  4. Mode (froid, chaud, humidité, séchage) (2 bits)
  5. Position volet fixe (2 bits)
  6. Vitesse ventilation (3 bits)
  7. Température (4 bits)
  8. Timer ON actif (1 bit)
  9. Timer ON durée (4 bits)
  10. Timer OFF actif (1 bit)
  11. Timer OFF durée (4 bits)
  12. Checksum (8 bits)

Comme vous pouvez le voir dans cet exemple, on peut envoyer un tas d’informations en une seule instruction. Il suffit de faire un usage plus avancé des masques binaires et de compresser l’information.

Émetteur infrarouge

Une LED infrarouge n’a rien de très spéciale. C’est surtout une LED qui émet une lumière que vous ne pouvez pas voir. Ceci étant, quelques mises en garde qui valent le coup d’être mentionnées.

  • Les LED les plus performantes peuvent consommer plusieurs centaines de milliampères. Il est donc recommandé de ne pas l’alimenter directement sur un port de l’Arduino et lui donner une alimentation dédiée comme vous feriez avec un moteur DC.
  • Utilisée dans un contexte de télécommande, vous pouvez pousser la LED dans des pics de consommation bien supérieure à une utilisation en mode continue. Pensez-y pour vos montages, car cela aura un impact significatif sur la portée de votre émission.
  • Les LED infrarouges, comme les LED lumineuses, ont un angle d’émission. Plus celui-ci sera étroit plus le faisceau sera concentré et pourra porter loin.

Pour la vidéo, j’utilise une LED de type TSAL6200. Voici son datasheet

Récepteur infrarouge

Contrairement à la LED émettrice, une LED réceptrice encapsule tout un micro-circuit qui permet de faire un travail de filtrage et formatage de la donnée reçue afin d’être facilement intégrée aux montages.

Dans la vidéo, j’utilise le TSOP4838 dont voici le datasheet

receivers_bg.png

Voici l’architecture interne de ce bloc :

IR_block_diagram_hd_bg.png

Le signal lumineux traverse un premier filtre conditionnel enlevant une première partie du bruit ambiant. Vient ensuite une étape d’amplification des signaux lumineux reçus. Un filtre supplémentaire finit de nettoyer le signal avant que le démodulateur retire la porteuse à 38kHz. Le signal finit sur un transistor afin d’émettre un signal carré bien défini.

Étude de cas : simple récepteur infrarouge

Pour ce premier montage, prenez votre module de réception infrarouge et localisez parmi les 3 pins du composant Ground, Vcc et Out. Ce composant est assez simple. La seule chose notable est qu’il est plutôt facile de ne pas avoir le bon datasheet entre vos mains et d’avoir les mauvaises informations.

De ma personnelle expérience, si votre module chauffe entre vos doigts lors du raccordement, débranchez immédiatement et inversez Vcc et Gnd. 😅

Concernant la résistance et le condensateur, ce sont des composants optionnels. Le condensateur filtre une partie du bruit de l’alimentation et la résistance sera une protection pour les surcharges sur Vcc.

montage_recepteur_website.png

Le premier code source qu’on va explorer est extrêmement court. Il va vous permettre d’explorer les messages qu’envoient vos différentes télécommandes. C’est le moment de jouer avec.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <IRremote.hpp> // Librairie IRremote by shirifff, z3t0, ArminJo

const int RECV_PIN = 4;  // Pin sur lequel vous avez raccordé le pin OUT de votre module IR

void setup() {
  Serial.begin(9600);
  IrReceiver.begin(RECV_PIN, ENABLE_LED_FEEDBACK, LED_BUILTIN); 
  Serial.println(F("Démarrage programme de démonstration."));
}

void loop() {
  if (IrReceiver.decode()) {
    IrReceiver.printIRResultShort(&Serial);  // protocole, adresse, commande et valeur brute
    IrReceiver.resume();                     // place le module pret à la réception de nouveaux messages
  }
}

La fonction IrReceiver.printIRResultShort enverra tout ce que l’Arduino recevra sous un format lisible.

Le résultat est décomposé comme suit :

  • Protocol : la façon de communiquer
  • Address : l’adresse du matériel
  • Command : la commande reçue
  • Raw-data : la data brute sous format hexadécimal
  • La taille de l’information reçue
  • Le sens de lecture des bits
  • le temps écoulé depuis la dernière commande (limité à 3.2 secondes)
  • le temps que la donnée a prise pour être reçue

Autre fonction notable, IrReceiver.resume qui permet de relâcher le protocole et replacer l’Arduino en écoute infrarouge.

Étude de cas : récepteur infrarouge avec controle de LED

Dans ce second montage, on va réagir aux signaux reçus pour contrôler un jeu de 3 LED. L’objectif ici, c’est de pouvoir changer l’état des LED :

  • allumer 1,2 ou 3 LED
  • éteindre / allumer toutes les LED en même temps

Pour accomplir ce résultat, grâce au montage précédent, avec la télécommande de votre choix, notez le protocole, l’adresse et la commande pour 3 boutons : Bouton ON / OFF, Volume Up et Volume Down.

Dans mon cas, j’ai noté :

  • Power ON/OFF : Protocole NEC, Address 0x00, Command 0xA8
  • Volume UP : Protocole NEC, Address 0x00, Command 0x9C
  • Volume DOWN : Protocole NEC, Address 0x00, Command 0x8C

Pour le montage suivant, on garde la partie réceptrice précédente qui n’a pas changé et on ajoute le contrôle de 3 LED sur les ports 8,9, et 10.

montage_recepteur_3led_website.png

L’objectif de ce nouveau code source est de permettre le contrôle dynamique des 3 LED.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <IRremote.hpp> // Librairie IRremote by shirifff, z3t0, ArminJo

constexpr uint8_t RECV_PIN = 4;        // Pin sur lequel vous avez raccordé le pin OUT de votre module IR
constexpr uint8_t LED_PIN_LOW = 8;     // Pin LED 1
constexpr uint8_t LED_PIN_MEDIUM = 9;  // Pin LED 2
constexpr uint8_t LED_PIN_HIGH = 10;   // Pin LED 3

// Déclaration et initialisation des 3 codes de télécommande
constexpr uint8_t code_power = 0xA8;
constexpr uint8_t code_vol_down = 0x9C;
constexpr uint8_t code_vol_up = 0x8C;

// Déclaration et initialisation des variables d'états des LED
bool LED_state = false;
int LED_level = 1;

void updateInternalStates(uint16_t code){
  switch(code){
    case code_power:
      // Inverse l'état du système
      LED_state = !LED_state;
      break;
    case code_vol_down:
      // Modification seulement lorsque une des LED est allumée
      if(LED_state){
        // Décrement le niveau
        LED_level -= 1;
      }
      break;
    case code_vol_up:
      // Modification seulement lorsque une des LED est allumée
      if(LED_state){
        // Incrémente le niveau
        LED_level += 1;
      }
      break;
  }
  //cap LED_level entre 1 et 3
  LED_level = constrain(LED_level, 1, 3);
}

void updateLedState(bool state, int level){
  // On combine LED_state et une condition sur LED_level pour determiner l'état de la LED
  digitalWrite(LED_PIN_LOW, state && level > 0);
  digitalWrite(LED_PIN_MEDIUM, state && level > 1);
  digitalWrite(LED_PIN_HIGH, state && level > 2);
}

void setup() {
  Serial.begin(115200);

  // Déclaration des 3 pins pour les 3 LED
  pinMode(LED_PIN_LOW, OUTPUT);
  pinMode(LED_PIN_MEDIUM, OUTPUT);
  pinMode(LED_PIN_HIGH, OUTPUT);

  // Initialisation des 3 LED
  updateLedState(LED_state, LED_level);

  // Initialisation de IrReceiver. LED témoin active.
  IrReceiver.begin(RECV_PIN, ENABLE_LED_FEEDBACK, LED_BUILTIN); 

  Serial.println(F("Démarrage programme controle de 3 LED."));
}

void loop() {
  if (IrReceiver.decode()) {  
    if (IrReceiver.decodedIRData.protocol == NEC                        // Filtrage protocol NEC
        && IrReceiver.decodedIRData.address == 0x00                     // Filtrage Address == 0x00
        && !(IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT)){ // Filtrage contre les répétitions

      IrReceiver.printIRResultShort(&Serial);  // protocole, adresse, commande et valeur brute
      updateInternalStates(IrReceiver.decodedIRData.command);
      updateLedState(LED_state, LED_level);
      Serial.print("Etat: ");
      Serial.println(LED_state);
      Serial.print("Niveau: ");
      Serial.println(LED_level);
    }
    // Reprend l'écoute de signaux IR
    IrReceiver.resume();
  }
}

Le point le plus notable de ce code source porte sur les conditions de déclenchement de la commande reçue.

Vous pouvez trouver une liste des protocoles reconnus dans ce fichier de la librairie IRremote

Remarquez que n’est envoyé que la commande à la fonction updateInternalStates. L’adresse et le protocole ayant déjà été filtré au préalable.

Étude de cas : émission de signaux infrarouge

Pour ce nouvel exercice, nous aurons besoin de la liste des composants suivants :

  • Une LED infrarouge dont vous connaissez la consommation de courant en mA. La mienne est de 100mA.
  • Un transistor (dont la limite de courant permet 200 mA). J’avais un BC337 sous la main, mais un NPN 2N2222 devrait avoir le même fonctionnement.
  • Une résistance appropriée selon votre LED. 22 ohms pour la mienne. Référez vous à cet article pour calculer la votre.
  • Une résistance de pull-up de 10 kOhms pour le bouton poussoir
  • Une résistance entre 220 et 1kOhms pour la base du transistor. Je recommande de commencer avec 1kOhm, puis de descendre cette valeur pour atteindre une meilleure portée.

Le port 3 raccordé à la base du transistor est ici très important. Une fonction interne à Arduino Uno prédispose ce port à avoir été choisi pour être le port par défaut de la librairie IRremote.

montage_emetteur_website.png

Dans cet exercice, nous cherchons à reproduire un signal de télécommande existante pour interagir avec l’équipement de votre choix. J’ai personnellement choisi ma télévision. Elle utilise le protocole Samsung et en analysant les données reçues sur le bouton ON/OFF, j’obtiens l’adresse 0x07 et la commande 0x02. Je travaillerai donc avec ces valeurs.

Faites de même, choisissez la commande que vous aimeriez reproduire avec votre montage et récupérez encore une fois : protocole, adresse et commande.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <IRremote.hpp>

constexpr uint8_t IR_SEND_PIN = 3;
constexpr uint8_t PUSH_BTN_PIN = 5;

constexpr uint16_t samsung_address = 0x07;
constexpr uint8_t samsung_power_cmd = 0x02;

constexpr uint8_t NOISE_FILTER_MS = 25;
uint8_t stable_state = LOW;
uint8_t last_btn_state = LOW;
uint32_t last_change_ms = 0;

void setup() {
  Serial.begin(115200);
  pinMode(PUSH_BTN_PIN, INPUT);
  IrSender.begin(IR_SEND_PIN, LED_BUILTIN);
}

void loop() {
  uint8_t btn_state = digitalRead(PUSH_BTN_PIN);

  // Détection d'un changement d'etat. Volontaire OU Bruit.
  if (btn_state != last_btn_state) {
    Serial.println(btn_state);
    last_btn_state = btn_state;
    last_change_ms = millis();            // Réinitialisation du chronomètre
  }

  // - Le temps écoulé depuis le dernier changement d'état détecté doit être supérieur à la durée du filtre anti bruit
  // - Le changement d'état doit être l'inverse de l'état stable actuellement en mémoire
  if ((millis() - last_change_ms) >= NOISE_FILTER_MS && btn_state != stable_state) {
    stable_state = btn_state;             //On enregistre le nouvel état stable
    
    if (stable_state == HIGH) {           
      Serial.println("down");
      IrSender.sendSamsung(samsung_address, samsung_power_cmd, 0);    //On envoie le signal infrarouge
    } else {
      Serial.println("up");
    }
  }
}

Dans ce code source, deux mécaniques sont à l’œuvre : celle de détection de l’appui sur un bouton poussoir et celle de l’action que cela entraîne, à savoir l’envoi de l’impulsion infrarouge.

Pour ce qui est de la partie infrarouge, deux lignes de code notables :

IrSender.begin(IR_SEND_PIN, LED_BUILTIN); : initialise le module IrSender dédié à l’émission de signaux.

IrSender.sendSamsung(samsung_address, samsung_power_cmd, 0); : Cette instruction utilise la fonction dédiée sendSamsung pour émettre le signal infrarouge avec la donnée souhaitée.

Voici une liste des fonctions à utiliser en fonction de votre matériel :

sendFunctions.png

Le reste du code source est une enveloppe pour la détection de l’appui sur le bouton poussoir tout en s’assurant qu’un appui soit comptabilisé une seule fois en filtrant le bruit que génère l’appui. En effet, appuyer sur un bouton poussoir peut entraîner la perception pour l’Arduino que vous avez temporairement spammé le bouton.

La surcouche ajoutée garantit une stabilité de 25 ms avant de passer à l’action.

Capter la donnée Infrarouge brute

Vous avez normalement pu tester jusque-là vos différentes télécommandes. Ainsi, vous avez sans doute constaté un petit éventail de protocoles différents. Mais en dessous de tous ces protocoles, ce que le chapitre Le protocole NEC nous a appris, communiquer en infrarouge n’est qu’une histoire de timing allumé/éteint.

Nous allons donc observer ces timings grâce à une fonction toute faite pour cet usage.

Étudions ce code source :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <IRremote.hpp> // Librairie IRremote by shirifff, z3t0, ArminJo

constexpr uint8_t RECV_PIN = 4;  // Pin sur lequel vous avez raccordé le pin OUT de votre module IR

void setup() {
  Serial.begin(115200);
  IrReceiver.begin(RECV_PIN, ENABLE_LED_FEEDBACK, LED_BUILTIN); 
  Serial.println(F("Récuperation signaux brute."));
}

void loop() {
  if (IrReceiver.decode()) {
    IrReceiver.compensateAndPrintIRResultAsCArray(&Serial, true);   // affiche le tableau rawData[] (Micro secondes)
    Serial.println();                                               // insertion d'un espace
    IrReceiver.resume();                                            // place le module pret à la réception de nouveaux messages
  }
}

Ce code source est compatible avec le tout premier montage électronique de cet article.

La fonction IrReceiver.compensateAndPrintIRResultAsCArray va afficher les timings reçus en microseconde.

Voici à quoi ressemble le résultat (partiel) d’une séquence de timings reçus.

protocole_nec_raw_data_step3.png

Pour lire cette donnée, il faut prendre la liste en paquet de deux. Les index en position paire sont des temps HAUT et les timings en position impaire sont des temps BAS. Vous pouvez voir sur l’illustration du protocole NEC les timings qui correspondent dans la liste des timings.

Émettre la donnée Infrarouge brute

Une fois la donnée collectée à l’étape précédente, nous allons cette fois réémettre cette donnée brute à l’aide du troisième montage, celui avec le bouton poussoir. Pour ma part, je décide donc de scanner les timings de ma télécommande Samsung et d’utiliser cette liste de timings obtenue.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <IRremote.hpp>

constexpr uint8_t IR_SEND_PIN = 3;
constexpr uint8_t PUSH_BTN_PIN = 5;

// Contenu récupéré avec IrReceiver.compensateAndPrintIRResultAsCArray
uint16_t rawData[] = {
  4480,4520, 530,1670, 580,1670, 530,1670, 580,570, 530,570, 
  530,570, 580,570, 530,570, 530,1720, 530,1670, 580,1670, 
  530,570, 530,570, 580,570, 530,570, 530,570, 580,570, 
  530,1670, 580,570, 530,570, 530,570, 530,570, 580,570, 
  530,570, 530,1720, 530,570, 530,1720, 530,1670, 
  580,1670, 530,1670, 580,1670, 530,1720, 530
};

constexpr uint8_t NOISE_FILTER_MS = 25;
uint8_t stable_state = LOW;
uint8_t last_btn_state = LOW;
uint32_t last_change_ms = 0;

void setup() {
  Serial.begin(115200);
  pinMode(PUSH_BTN_PIN, INPUT);
  IrSender.begin(IR_SEND_PIN, LED_BUILTIN);
}

void loop() {
  uint8_t btn_state = digitalRead(PUSH_BTN_PIN);

  // Détection d'un changement d'etat. Volontaire OU Bruit.
  if (btn_state != last_btn_state) {
    Serial.println(btn_state);
    last_btn_state = btn_state;
    last_change_ms = millis();            // Réinitialisation du chronomètre
  }

  // - Le temps ecoulé depuis le dernier changement d'état détecté doit etre supérieur à la durée du filtre anti bruit
  // - Le changement d'état doit etre l'inverse de l'état stable actuellement en mémoire
  if ((millis() - last_change_ms) >= NOISE_FILTER_MS && btn_state != stable_state) {
    stable_state = btn_state;             //On enregistre le nouvel état stable
    
    if (stable_state == HIGH) {           
      Serial.println("down");
      IrSender.sendRaw(rawData, sizeof(rawData) / sizeof(rawData[0]), 38);   //On envoie le signal infrarouge
    } else {
      Serial.println("up");
    }
  }
}

Tout est identique au code source original, à la différence du tableau rawData[] stockant la liste des timings, et la fonction sendSamsung a cette fois été remplacée par la fonction universelle sendRaw() IrSender.sendRaw(rawData, sizeof(rawData) / sizeof(rawData[0]), 38);

Cette fonction attend 3 paramètres :

  1. le tableau des timings
  2. le nombre d’éléments contenus dans ce tableau
  3. la vitesse de la porteuse. Ici 38 kHz.

Grâce aux fonctions compensateAndPrintIRResultAsCArray et sendRaw, sans avoir la moindre information sur les protocoles utilisés sous-jacents, vous avez là, le système le plus générique et le plus universel pour copier n’importe quel signal infrarouge.

Conclusion

Dans cet article, nous avons couvert un grand pan du monde des télécommandes infrarouges. Cependant, certains aspects ont dû être omis pour ne pas partir dans tous les sens. Il existe d’autres librairies Infrarouge, il existe d’autres façons de faire, sur d’autres plateformes matérielles. Mais soyez certain que je reviens bientôt pour la seconde partie.

D’ici là, agents de la SiliciumCorp, je vous souhaite une aventure électronique toujours plus plaisante.

Cet article est sous licence CC BY 4.0 par l'auteur.