Clavier par télécommande Infrarouge

image

Lorsqu'il s'agit d'utiliser un clavier qui ne sert qu'à configurer un appareil, c'est dommage de sacrifier un clavier si rarement utilisé ainsi qu'un nombre important d'entrées-sorties du microcontrôleur pour le connecter.

Pourquoi ne pas utiliser une télécommande infrarouge ? Le clavier n'occupe plus de place sur l'appareil et il suffit d'une patte pour l'interfacer.

Pour ce projet j'ai choisi une télécommande standard qui utilise le code RC5.

Pour réceptionner les signaux infrarouge j'utilise un VS1838B.

image
image

La télécommande émet sur une porteuse. Quand la porteuse est présente, cela représente un 1. Quand elle est absente un 0. Cette technique permet d'éviter les interférences dûent au bruit infrarouge ambiant. Le VS1838B reconnait la porteuse et traduit en un signal propre sur sa sortie OUT.

image

Exemple de signal à la sortie du VS1838B


Algorithme simple pour lire le signal:

La télécommande transmet 14 bit codé au format Manchester. Chaque bit est codé sur 2 bits. Ce code permet de garantir un changement d'état régulier de la ligne et permettrait de se resynchroniser. Dans le cas de l'algorithme présenté ici je ne resynchronise pas et part du principe que les horloges (de la télécommande et du CPU sont suffisamment précises)

  1. Attendre un premier changement d'état
  2. Attendre 1/2 pulse (1/4 de la période d'horloge virtuelle)
  3. Lire le bit
  4. Attendre 1 pulse et reprendre au point 3 27 fois.

Le premier bit des 28 bits est à prendre en compte avant le premier changement d'état qui nous sert de départ à la lecture. Pour décoder le code Manchester j'utilise un buffer de 2 bits. Après deux lectures le buffer contient soit 01 soit 10. si il contient 00 ou 11 c'est une erreur.

Les bits décodés sont introduits par le LSB de la variable "output". A la fin de la lecture celle-ci contient les 14 bits d'information. Les bits 15 et 14 sont inutilisés et à 0. Les bits 13 et 12 sont à 1. C'est le protocole RC5 qui veut ça.

La télécommande envoie une touche de manière répétée tant qu'on la relâche pas. Pour distinguer une double pression rapide sur une même touche de la répétition automatique, le bit 11 change d'état. Les bit 10 à 0 contiennent l'information qui nous intéresse.

int readKey(int timeout) {
  static int last_key = 0;
  int v;
  byte buffer;
  int output;
 
  buffer = 0;
  output = 0;
 
  // Attends la première transition montante, soit après l'émission du premier bit à 0
  unsigned long until = millis() + timeout;
  int last_v = 0;
  do {
    v = readIR();
    if(timeout>0) {
      if(millis()>until) return -3;
    }
  }
  while(v==last_v);

  delayMicroseconds(HALF_DUR);
  for(int cpt=1;cpt<28;cpt++) { // réceptionne les 27 bits restants
      buffer <<=1;
      v = readIR();
      if(v==1) {
        buffer |= 1;
      }
      if(cpt&1) { // tous les deux bits, décode le code manchester
        output <<=1;
        buffer &= 3;
        if(buffer==1) output |= 1;
        else if(buffer==0 || buffer==3) return -2; // erreur
      }
      delayMicroseconds(FULL_DUR - 20);
  }
  if(output!=last_key) {
      last_key = output;
      return last_key & 0x1FF;
  }
  return -1; // meme touche
}
 

Le délais d'attente entre la lecture de deux bits doit tenir compte du temps d'exécution du programme. Ainsi on fait une lecture au milieu de l'impulsion.

J'ai estimé arbitrairement le temps à 20 microsecondes. C'est pourquoi le delayMicroseconds utilise FULL_DUR - 20

Si vous tester ce code et que vous avez un oscillo à deux canaux. Vous pourriez mesurer le signal de la télécommande sur un canal et le moment de lecture sur l'autre. Ainsi vous pourriez ajuster cette valeur.