mercredi 16 janvier 2013

Clonage d'une télécommande infrarouge avec un Arduino (1)

Construire votre propre télécommande de téléviseur au moyen d'un Arduino?  Bonne idée!

Vous pourriez, par exemple, réunir sur une même télécommande les fonctions les plus utilisées de plusieurs télécommandes différentes (oui, je connais l'existence des télécommandes universelles, mais c'est une solution beaucoup trop simple!).   Ou encore construire une télécommande qui limitera automatiquement le temps d'utilisation du téléviseur, l'éteignant au bout d'un certain délai, ou refusant de le mettre en marche aux heures interdites...  Ça pourrait aussi être un dispositif qui allume et éteint automatiquement le téléviseur en votre absence, pour que les cambrioleurs ne sachent pas que vous êtes parti en voyage depuis 3 semaines.

1° Décoder le signal

Lorsque vous appuyez sur un bouton de votre télécommande, celle-ci s'allume et s'éteint plusieurs fois très rapidement de façon à envoyer un message codé à votre téléviseur (ça ressemble un peu à du code morse).  Le rayonnement infrarouge est invisible à l'oeil nu, mais si vous observez l'extrémité de votre télécommande au moyen d'une caméra numérique, vous devriez voir la LED s'allumer brièvement lorsque vous appuyez sur un de ses boutons (par contre vous ne percevez pas les clignotements car ils sont trop rapides).

Pour contrôler votre téléviseur, l'Arduino devra alimenter une LED infrarouge de façon à ce qu'elle émette exactement le même signal.

La première étape consiste donc à capter ce signal et à l'analyser.  Pour ce faire, il vous faut un capteur infrarouge modulé à 38 kHz qui devrait faire l'affaire pour la plupart des télécommandes (dans certains cas, plus rares, il vous en faudra un modulé à 56 kHz).  J'ai utilisé le TSOP4836 de Vishay, mais il existe bien sûr d'autres possibilités (j'avais précédemment tenté l'expérience avec le KSM-2012 de Kodenshi sans le moindre succès).

Le circuit ci-dessous est sorti tout droit de la datasheet du TSOP4836; il sera peut-être un peu différent si vous utilisez un autre modèle.  La sortie du capteur est normalement haute (5 V) mais elle devient basse (0 V) sur réception d'un signal infrarouge qui oscille à 38 kHz.  Lorsqu'on appuie sur un bouton de la télécommande en pointant cette dernière vers le capteur, la tension de sortie du capteur va changer de valeur très rapidement (ce que vous pouvez vérifier si vous disposez d'un oscilloscope à mémoire).

Mais pour décoder ce signal, l'Arduino est encore plus pratique qu'un oscilloscope!  Surtout si vous avez préalablement installé la librairie IRRemote mise au point par Ken Shirriff.  (Je suis toujours un peu dérouté par l'interface du site GitHub:  il y a un bouton "ZIP" qui vous permet de downloader tous les fichiers nécessaires en un seul clic).

Une fois la librairie IRRemote installée dans votre répertoire "Libraries", vous branchez votre capteur infrarouge à l'arduino (la sortie du capteur va à l'entrée 11 de l'Arduino), vous téléversez dans l'Arduino le sketch "IRrecvDump" disponible dans le menu des exemples sous l'onglet IRRemote,  vous affichez le moniteur série (en vous assurant qu'il est bien réglé à 9600 bauds), et vous appuyez sur un bouton de la télécommande en visant le capteur.

Voici ce qu'affiche le moniteur série lorsque j'appuie sur le bouton "channel up" de ma télécommande:

Decoded NEC: FDB04F (32 bits)
Raw (68): 4450 8950 -4500 550 -550 600 -500 600 -550 550 -550 600 -500 600 -550 550 -550 600 -500 600 -1650 600 -1650 550 -1700 600 -1650 550 -1650 550 -1700 600 -500 550 -1700 550 -1700 550 -550 550 -1700 550 -1700 550 -550 550 -550 550 -600 550 -550 550 -550 550 -1700 550 -550 550 -600 550 -1650 600 -1650 550 -1700 550 -1650 600
La librairie a reconnu le protocole NEC à 32 bits, et la commande se traduit par la valeur hexadécimale "FDB04F".  C'est tout ce que j'ai besoin de savoir; puisque le protocole a été reconnu, je n'ai nullement besoin d'utiliser les données brutes qui apparaissent dans les lignes suivantes.


2° Émettre le signal

Pour émettre le signal, le circuit est simple:  une LED infrarouge branchée à la sortie 3 de l'Arduino.  On parle souvent d'une résistance de protection de 100 Ω, mais j'ai constaté deux inconvénients:  le signal émis par la LED est peu intense, et la transition entre les signaux numériques "hauts" et "bas" est plus lente (courbe exponentielle déterminée par la constante RC du circuit).  Puisque la LED infrarouge ne fonctionne pas en continu, vous pouvez vous permettre de diminuer considérablement cette résistance de protection.

Lorsque la LED pointe vers le téléviseur, le sketch suivant change de chaîne toutes les 5 secondes (le signal est envoyé 3 fois de suite pour chaque changement de chaîne).:

Include IRremote.h

IRsend irsend;

void loop() {

    for (int i = 0; i < 3; i++) {
      irsend.sendNEC(0xFDB04F, 32);
      delay(40);
    }
  delay(5000);
}

En plus de NEC, d'autres protocoles sont aussi reconnus par la librairie IRRemote: Sony SIRC, Philips RC5, Philips RC6.

Il reste quand même la possibilité que le protocole utilisé par votre télécommande ne soit pas reconnu par la librairie IRRemote:  il faut alors utiliser les données brutes (les délais pendant lesquels la LED est allumée ou éteinte) mais comme il ne sont qu'approximatifs, ça peut devenir plus délicat: ce sera le sujet de ma prochaine rubrique.

Plus d'informations sur la librairie IRRemote.
Plus d'informations sur les différents protocoles de télécommandes

Yves Pelletier (Twitter: @ElectroAmateur)

36 commentaires:

  1. bonjour ,j ouvre le programme IRRemote mise au point par Ken Shirriff.je le verifie et il me dit qu il y a des erreurs , merci de me repondre
    n.theault@laposte.net

    RépondreSupprimer
  2. Bonjour,
    Quels sont les messages d'erreur retournés? Quelle est la version de l'IDE utilisée? Quel type de carte Arduino? Quel est le sketch utilisé pour tester la librairie IRRemote?

    Tu risques d'obtenir une aide plus rapide et efficace en posant la question à http://forum.arduino.cc/ .

    Bonne chance!

    RépondreSupprimer
  3. bonsoir,
    super votre tuto télécommande.
    je suis en train de la construire.
    j'ai une télé Phillips rc6 cela marche.
    j'ai un systeme son logitech (protocole NEC 32)
    et une télécommande Imon pour le pc.

    pour le son, j'ai comme commande 10EF08F7 pour le on /off
    seulement il ne se passe rien , j'ai copier votre prog.
    j'ai revérifié j'ai bien ce code de 8 chiffre ???
    et pour Imon pas de protocole ! :((
    comment procéder ?
    merci pour votre lecture.

    RépondreSupprimer
    Réponses
    1. Attention si tu utilise une arduino mega 2560 il ne faudra pas brancher la led émettrice sur la pin 3 comme indiqué dans l'exemple (juste pour les uno) mais sur la pin 9 de l'arduino mega2560 pour la réception rien ne change tout va bien.

      Supprimer
  4. Bonsoir,
    Il ya déjà quelques temps, j'avais fait un truc similaire. Plus d'info ici
    http://wiki.mdl29.net/doku.php?id=elec:telecommande_universelle

    RépondreSupprimer
    Réponses
    1. Merci, pour ce lien, et salutations aux membres de la Maison du libre Brest!

      Supprimer

  5. Bonjour,
    Ou s'affiche le?
    Decoded NEC: FDB04F (32 bits)
    Raw (68): 4450 8950 -4500 550 -550 600 -500 600 -550 550 -550 600 -500 600 -550 550 -550 600 -500 600 -1650 600 -1650 550 -1700 600 -1650 550 -1650 550 -1700 600 -500 550 -1700 550 -1700 550 -550 550 -1700 550 -1700 550 -550 550 -550 550 -600 550 -550 550 -550 550 -1700 550 -550 550 -600 550 -1650 600 -1650 550 -1700 550 -1650 600

    sur ton pc?
    Car j'aimerai cloner une telecommande LEGO ...

    RépondreSupprimer
  6. Bonjour,
    Ça s'affiche dans le moniteur série (serial monitor) de l'IDE Arduino.

    RépondreSupprimer
  7. Bonjour,
    Dans l'article la référence du récepteur IR est le TSOP4836 or si je comprends bien le TUTO il faut un récepteur 38Khz, le truc c'est que le TSOP4836 est un récepteur 36Khz. Est ce normal ?
    Merci d'avance pour votre réponse
    Thibault

    RépondreSupprimer
    Réponses
    1. Il me semble avoir lu quelque part qu'on dispose d'une certaine marge de manoeuvre sur cette fréquence. J'ai utilisé avec succès le TSOP4836 pour la dizaine de télécommandes que j'ai pu essayer, je suppose qu'un récepteur à 38 kHz exactement devrait fonctionner aussi.

      Supprimer
  8. Du coup je peux me lancer sans inquiétude pour l'achat du TSOP4836 ou alors je peux prendre le TSOP4838 qui fait 38Khz. A votre avis ?

    RépondreSupprimer
    Réponses
    1. Je crois que les deux font l'affaire, mais je peux me tromper (ça arrive souvent!).

      Supprimer
  9. Autre question peut-on afficher les résultats sur un écran connecté au arduino ? sans avoir besoin de pc

    RépondreSupprimer
    Réponses
    1. Il reste beaucoup de pins disponibles pour brancher un afficheur LCD à l'Arduino, donc en modifiant le code ça devrait pouvoir se faire assez facilement.

      Supprimer
    2. Auriez vous une référence d'afficheur LCD qui sera possible de brancher sur un arduino uno en utilisant les pins restante ?
      Encore merci

      Supprimer
    3. N'importe quel afficheur muni du contrôleur Hitachi HD44780 fera l'affaire.

      Supprimer
  10. Bonjour,
    J'ai un problème assez original lorsque je branche mon capteur et que j’envoie le programme de décodage sur un arduino premier modèle sa fonctionne il me décode le signal mais lorsque j’envoie le même programme et que je branche exactement de la même manière sur un arduino rev3 il ne me décode pas le signal.
    Auriez vous une idée du problème?

    Cordialement
    Merci

    RépondreSupprimer
    Réponses
    1. Non, ça me semble assez étrange...

      Supprimer
    2. Est ce que ce ne serait pas parce que l'arduino Uno V1 et l'arduino r3 n'ont pas le même microprocesseur ?

      Supprimer
  11. Je viens de refaire les tests et bizarrement sa fonctionne j'avoue ne pas comprendre ce qui c'est passé merci quand même pour votre aide :)

    RépondreSupprimer
  12. Bonjour, ayant fort apprécier votre tuto je me suis lancé : le but étant que sur envoi d'un signal IR, l'arduino renvoi une suite de signaux IR, j'ai donc modifié votre sketch mais problème après avoir exécuté les signaux en envoi impossible de réceptionner un autre signal, alors que si il n'y a pas d'envoi de code IR je réceptionne toujours. voici l'extrait de code qui pose problème :

    void translateIR() { // takes action based on IR code received

    switch(results.value) {

    case 0xFFA25D:
    Serial.println(" MINIONOFF ");
    //irenvoi("SONY", 0xA90);
    for (int i = 0; i < 3; i++) {
    irsend.sendSony(0xA90, 12);
    delay(40);
    }
    Serial.println("envoi SONY1");
    // irenvoi("SONY", 0xA81);
    for (int i = 0; i < 3; i++) {
    irsend.sendSony(0xA81, 12);
    delay(40);
    }
    Serial.println("envoi SONY2");
    //irenvoi("NEC", 0x617048B7);
    for (int i = 0; i < 3; i++) {
    irsend.sendNEC(0x617048B7, 32);
    delay(40);
    }
    Serial.println("envoi NEC");
    break;

    case 0xFFB04F:
    Serial.println(" USD ");
    break;

    RépondreSupprimer
  13. Salut,
    selon la distance de la télécommande et du recepteur, le code hexa et les valeurs raw, ne sont pas les même. Est-ce normal?
    Merci

    RépondreSupprimer
  14. j'ai suivi votre tuto a la lettre mais il me dit
    LG was not déclared in this the scope
    pitié aidé moi

    RépondreSupprimer
    Réponses
    1. La constante LG est définie dans le fichier IRremote.h , j'aurais donc tendance à suspecter une mauvaise installation de la bibliiothèque.
      Est-ce que la bibliothèque se trouve bien à l'intérieur d'un dossier intitulé "IRremote", lui-même à l'intérieur du dossier "librarairies"?

      Supprimer
  15. Bonjour,
    Avez-vous la référence de votre LED émettrice ?
    Merci

    RépondreSupprimer
  16. Bonjour je veux le programme des 3 leds qui s'allument avec télécommande chaque bouton dans le télécommande allume une led et la quatrième bouton éteindre tous les leds

    RépondreSupprimer
  17. Bonjour Yves! Super tutoriel, qui à parfaitement fonctionné :)
    Cependant, j'aimerais aller un tout petit peu plus loin mais je galère un poil :/ Mettons que ma led envoie le code suivant

    void loop() {
    irsend.sendNEC(0x00000, 32);
    delay(1000);
    }

    (considérons le 00000 comme n'importe quel code)

    J'aimerais que sur mon programme récepteur, au lieu d'afficher dans mon moniteur le 00000 , stocker cette valeur et l'interpréter pour que dans mon moniteur s'affiche un texte , par exemple "Le Bouton de volume est pressé". Et si la led envoie par exemple 00001 , même processus : stockage de la valeur , correspondance avec la base de données -> "Le bouton X est pressé".

    Ce n'est pas ultra clair... En soit, je veux juste que si TEL code est envoyé, ma carte recepteur n'indique pas le code tel quel mais bien une signification de celui ci (que j'aurais donné à mon programme, genre "00000 -> Le bouton de Volume est pressé" )

    Une idée de comment faire ca? Merci d'avance :D

    RépondreSupprimer
    Réponses
    1. tu peut faire:

      if (CODERECU == TONCODE) {
      Serial.print("Touche X pressee");
      }

      En espérant t'avoir aidé...

      Supprimer
  18. Bonjour, moi, avec IRrecvDump, j'obtiens les messages d'erreur suivants:

    Arduino : 1.6.8 (Windows 10), Carte : "Arduino/Genuino Uno"

    C:\Users\Axel\Documents\Arduino\libraries\Arduino-IRremote-master\examples\IRrecvDump\IRrecvDump.ino: In function 'void dump(decode_results*)':

    IRrecvDump:53: error: 'class decode_results' has no member named 'address'

    Serial.print(results->address, HEX);

    ^

    IRrecvDump:56: error: 'LG' was not declared in this scope

    else if (results->decode_type == LG) {

    ^

    IRrecvDump:62: error: 'AIWA_RC_T501' was not declared in this scope

    else if (results->decode_type == AIWA_RC_T501) {

    ^

    IRrecvDump:65: error: 'WHYNTER' was not declared in this scope

    else if (results->decode_type == WHYNTER) {

    ^

    Plusieurs bibliothèque trouvées pour "IRremote.h"
    Utilisé : C:\Program Files (x86)\Arduino\libraries\RobotIRremote
    Non utilisé : C:\Users\Axel\Documents\Arduino\libraries\Robot_IR_Remote
    Non utilisé : C:\Users\Axel\Documents\Arduino\libraries\Arduino-IRremote-master
    exit status 1
    'class decode_results' has no member named 'address'


    Pouvez-vous m'aider plz??

    RépondreSupprimer
  19. Bonjour,
    Mes recherches me font souvent revenir sur votre site que j'apprécie de plus en plus.
    Simple précis et très abordable.
    Je viens de tester la réception infrarouge cela fonctionne très bien !
    J'aimerai votre aide afin d’exploiter une télécommande avec protocole non standard.
    Time between 2 pulses: 0=5.06ms 1=7.59ms
    Modulation period : 26,4µs (37.8Khz)
    (8,8µs High, 17,6µs Low)
    55ms pause between codes
    pulse duration : 700µs
    Il s'agit de la télécommande velleman du K8050

    RépondreSupprimer
  20. bonjour,
    pourquoi dans votre programme lors de l'envoi de l'information d'allumage, vous écrivez 0xFDB04F, pourquoi "0x"? Doit-on faire de même pour un codage RC5? je débute et je ne trouve pas grand chose sur internet.
    Merci d'avance.

    RépondreSupprimer
    Réponses
    1. Bonjour,
      Le "0x" est la façon d'indiquer que la valeur numérique est en format hexadécimal.

      Supprimer
  21. Bonjour, comment le sketch d’émission reconnaît la broche de la led infrarouge (broche 3)?? La librairie reconnait d'elle-même la broche à laquelle est connectée la led? Ou bien il faut rajouter une ligne de code qui n’apparaît pas ici.
    Merci d'avance.

    RépondreSupprimer