[APL] Un récepteur Infrarouge SIRCS

Un récepteur Infrarouge SIRCS

En clair, je vous propose d'utiliser une télécommande SONY pour piloter vos programmes Arduino ou bien d'autres choses encore.

Récupérer un récepteur infrarouge

  • "T'es bien gentil, mais un bidule infrarouge je n'en ai pas et je ne vais pas passer commande juste pour ça !"

Et bien non, il n'est nécessaire de commander ! Le moins cher c'est de le récupérer.

  • "Ok, mais où ?"

Sur un téléviseur jeté à la benne, un vieux magnétoscope qui encombre un ami, ... Pour ma part, j'ai pris l'option "magnétoscope qui encombre". Après avoir démonter l'objet, repérez le capteur, ici sur le circuit imprimé d'un vieux magnétoscope :

Et récupérez le (cassez la plaque ou desoudez, à vous de voir) :

J'ai fait les photos après avoir réaliser le montage, voilà pourquoi on voit une gaine à l'arrière du capteur. :slight_smile:

Le capteur et son câblage

Bon c'est fait le capteur est un...

..., "Sharp GP1U8".

Impossible de trouver de la documentation sur ce capteur, ... j'ai trouvé de la doc. sur d'autre capteurs Sharp similaires mais plus réçents, il semble que les broches soient toujours disposées de la même manière. On va essayer (j'ai essayé ca fonctionne), broche 1, la sortie du capteur, câble gris ; broche 2, +5V, câble rouge ; broche 3, la masse, câble bleu.

Un peu de doc sur l'aspect et le brochage de quelques récepteurs infrarouge : http://etronics.free.fr/dossiers/analog/analog46.htm.

Voyons la suite...

Relions le capteur à Arduino

Facile,

  • une broche numérique pour la sortie du capteur, pour moi, ce sera la broche n°2 ;
  • la masse du capteur sur la broche GND de la carte Arduino ;
  • le +5V du capteur sur la broche 5V de la carte Arduino.

Préparation du programme

C'est quoi SIRCS ?

C'est le protocole utilisé par SONY pour le dialogue entre ses appareils et ses télécommandes. Il peut être utiliser soit sur un support électrique type fils électriques ou être transmis via une lumière infrarouge modulée à 40kHz. C'est le dernier cas qui nous interesse, la télécommande infrarouge.

Plus d'info sur le protocole SIRCS et son application via l'infrarouge :

Dans les grandes lignes, le signal infrarouge est modulé à 40kHz, chaque trame fait 13 bits de long, 1 bit de start qui dure 2,4ms suivi de 12 bits de données qui durent 600 us pour les bits à 0 et 1,2 ms pour les bits à 1. Tous les bits sont espacés de 600us et une trame dure en tout 45ms, l'espace "vide" est comblé par une absence de signal. Une trame doit être répétée 3-4 fois pour être valide.

Pour ce projet, on se fiche de la modulation, le récepteur démodule le signal et seule la première trame d'une série de 3-4 est prise en considération.

Le programme

/* Exemple Recepteur SIRCS  */
/* Benoît ROUSSEAU 14/07/2006  */

#define brocheDonnees 2 // n° broche numérique sur laquelle est reçu le signal SIRCS
#define brocheLED 13    // n° broche numérique du témoin de réception (LED)

#define IR_DEVICE_ID 7  // n° d'ID du péripherique (7 pour la télécommande Sony RMT-831)

#define MIN_START_BIT_TIME 2390 // durée minimale en us d'un bit de départ
#define MIN_HIGH_BIT_TIME  1150 // durée minimum en us d'un bit 1
#define MIN_LOW_BIT_TIME   550  // durée minimum en us d'un bit 0

#define TRAME_VALIDE 1 // decodeTrameSIRCS12bits retourne 1 si trame valide

#ifndef cbi
  #define cbi(sfr, bit) ((sfr) &= ~(1 << (bit)))
#endif
#ifndef sbi
  #define sbi(sfr, bit) ((sfr) |= (1 << (bit)))
#endif

unsigned long trame[20]; // contient les durées des bits IR de la trame reçue
int indexTrame;          // contient l'index général du tableau de la trame reçue
int indexFinTrame;       // contient le dernier index de la trame reçue

int irID;    // contient l'identifiant de l'appareil
int irCode;  // contient le code de la commande

/*-------------------------------------------*/
//                                           //
// Fonction qui attends une trame SIRCS      //
// et retourne le nombre de bits reçus.      //
//                                           //
// Variables globales modifiées :            //
// -> trame[]                                //
// -> indexTrame                             //
//                                           //
/*-------------------------------------------*/
int attendsTrameSIRCS()
{
  indexTrame = 0;
  unsigned long dureeImpulsion;
  
  // attends le bit de départ et mémorise sa durée
  do {
    dureeImpulsion = pulseIn (brocheDonnees, LOW);
  } while (dureeImpulsion < MIN_START_BIT_TIME);
  trame[indexTrame] = dureeImpulsion;
  
  // mémorise les durées des bits suivants
  // jusqu'au bit de départ suivant lui aussi mémorisé
  do {
    indexTrame++;
    do {
      dureeImpulsion = pulseIn (brocheDonnees, LOW);
    } while (dureeImpulsion < MIN_LOW_BIT_TIME);
    trame[indexTrame] = dureeImpulsion;
  } while (dureeImpulsion < MIN_START_BIT_TIME);
  
  return indexTrame;
}

/*-------------------------------------------*/
//                                           //
// Fonction qui attends une trame SIRCS      //
// et retourne 1 si trame valide, 0 sinon.   //
//                                           //
// Variables globales modifiées :            //
// -> irID                                   //
// -> irCode                                 //
// -> indexTrame                             //
//                                           //
/*-------------------------------------------*/
int decodeTrameSIRCS12bits()
{
  int indexBit = 0; // initialisation pour décodage commande
  
  indexTrame = 0;
  irCode = 0;
  irID = 0;
  
  // start bit ok ?
  if (trame[0] < MIN_START_BIT_TIME) return 0;

  // décode le n° de commande 7 bits
  for (indexBit = 0; indexBit < 7; indexBit++)
  {
   if (trame[indexBit+1] < MIN_HIGH_BIT_TIME)
     cbi (irCode, indexBit);
   else
     sbi (irCode, indexBit);
  }
  
  // décode le n° d'ID 5 bits
  for (indexBit = 0; indexBit < 5; indexBit++)
  {
   if (trame[indexBit+8] < MIN_HIGH_BIT_TIME)
     cbi (irID, indexBit);
   else
     sbi (irID, indexBit);
  }
  
  return 1;
}

// FONCTIONS ARDUINO

void setup ()
{
  Serial.begin (9600);
  pinMode (brocheDonnees, INPUT);
  pinMode (brocheLED, OUTPUT);
}

void loop ()
{
  // attends une trame SIRCS
  indexFinTrame = attendsTrameSIRCS();
  
  if (decodeTrameSIRCS12bits() == TRAME_VALIDE)
  {
    if (irID == IR_DEVICE_ID)
    {
      switch (irCode)
      {
        case 24 : Serial.print("[Stop] "); break;
        case 25 : Serial.print("[Pause] "); break;
        case 26 : Serial.print("[Lecture] "); break;
      }
    }
    
    // envoie trame
    Serial.print ("IR : code ");
    Serial.print (irCode);
    Serial.print (", ID ");
    Serial.print (irID);
    Serial.print (13, BYTE); // peut être remplacer par println() mais saute 2 lignes avec l'HyperTerminal
    
    // allume la LED 0.5 seconde pour
    // laisser passer les autres trames
    // et donner retour visuel que la
    // commande est passée
    digitalWrite (brocheLED, HIGH);
    delay(500);
    digitalWrite (brocheLED, LOW);
  }
  else
  {
    // fait clignoter la LED 0.5 seconde
    // pour laisser passer les autres
    // trames et donner retour visuel
    // que la commande n'est pas passée
    for (int i = 0; i < 25; i++)
    {
      digitalWrite (brocheLED, HIGH);
      delay(10);
      digitalWrite (brocheLED, LOW);
      delay(10);
    }
  }
 
}

Que fait le programme ?

Si vous chargez le programme qui précède dans votre Arduino, que le capteur est bien câblé et que vous possédez une téléccommande infrarouge Sony...

Charger un moniteur de liason série type HyperTerminal sous Windows de manière à voir les informations envoyées par la télécommande.

Appuyez sur une touche de la télécommande en direction du capteur.

Si vous avez une LED connectée sur la broche numérique 13 d'Arduino, elle doit s'allumée 1/2 seconde pour vous indiquez que la carte a bien reçue une trame infrarouge valide.

Sur l'écran du moniteur série, vous devriez avoir quelque chose qui ressemble à ceci :

[Lecture] IR : code 26, ID 7
[Lecture] IR : code 26, ID 7
[Lecture] IR : code 26, ID 7
IR : code 42, ID 26
IR : code 42, ID 26
IR : code 42, ID 26
IR : code 28, ID 7
IR : code 27, ID 7
[Stop] IR : code 24, ID 7
[Pause] IR : code 25, ID 7
[Stop] IR : code 24, ID 7
[Lecture] IR : code 26, ID 7
[Pause] IR : code 25, ID 7
[Stop] IR : code 24, ID 7

A chaque fois que la carte reçoit une trame, elle envoie sur la liason série le code de la touche activée ainsi que l'indentifiant (ID) de la classe d'appareils auquelle la commande est adressée.

Dans mon cas, Télécommande de camescope mini-DV SONY RMT-831, selon la touche, l'ID est soit 7 soit 26 selon la fonction du camescope visée (partie caméra ou partie magnétoscope).

J'ai ajouté dans le code un "switch case" qui ajoute [lecture], [pause] ou [Stop] en début de ligne quand l'une de ces commandes est reconnue. C'est pour vous donner un exemple de reconnaissance de quelques touches parmis les autres.

Voilà, c'est fini !
Si vous avez des questions conçernant le code, la mise en oeuvre du programme, ... postez à la suite...

Hello, how to make na rc5 protocol decoder i have specs but your code is hard to produce can you help?Sorry for English, but I dont't understand French! http://www.xs4all.nl/~sbp/knowledge/ir/rc5.htm << specs

Hello ccdust,

I will try to make an RC5 decoder when I'll have some time. I think that you have to use an external interrupt configured with EXTINT_EDGE_ANY and read the type of edge each time to now how about 1 or 0 bit. I think that the main difficult is to ignore faults bits genrated by IR noise.


J'aissaierai de réaliser un récepteur RC5 quand j'aurai un peu de temps. Je pense qu'il faut utiliser une interruption externe configurée avec EXTINT_EDGE_ANY et lire le type de front à chaque occurence pour savoir si c'est un bit 1 ou 0. Je pense aussi que la principale dificultée est d'écarter les bits erronés isu du bruit IR.