Outils pour utilisateurs

Outils du site


tpir

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentes Révision précédente
Prochaine révision
Révision précédente
tpir [2015/03/29 15:56]
bvandepo
tpir [2019/03/13 10:22]
bvandepo [Analyse]
Ligne 17: Ligne 17:
  
 ====Analyse==== ====Analyse====
 +
 +<ifauth @prof>
 +Tracé de chronogrammes pour le NEC non étendu:
 +http://​techdocs.altium.com/​display/​FPGA/​NEC+Infrared+Transmission+Protocol
 +</​ifauth>​
 +
 ===Format des trames=== ===Format des trames===
-Pour rappel, une trame NEC étendue est constitué ​d'un train de bits modulé à 38Khz. Il existe 2 types de trames:+Une trame NEC étendue est constituée ​d'un train de bits modulé à 38Khz. Il existe 2 types de trames:
   - les trames complètes   - les trames complètes
   - les trames de répétition   - les trames de répétition
Ligne 24: Ligne 30:
 La trame complète contient: La trame complète contient:
   - un entête de trame   - un entête de trame
-  - une adresse sur 16 bits (identifiant ​la télécommande) +  - une adresse sur 16 bits (codant le numéro de la télécommande), octet de poids fort d'​abord et bit de poids faible d'​abord ​ 
-  - une valeur sur 8 bits (identifiant ​la touche) +  - une valeur sur 8 bits (codant le numéro de la touche), bit de poids faible d'​abord 
-  - le complément à 1 de la précédente valeur sur 8 bits+  - une valeur sur 8 bits codant ​le complément à 1 de la précédente valeur sur 8 bits (redondance pour la détection d'​erreur)
   - l'​envoi d'un bit à 1 et un retour à l'​état de repos   - l'​envoi d'un bit à 1 et un retour à l'​état de repos
  
Ligne 38: Ligne 44:
 ===Codage des bits=== ===Codage des bits===
 Les bits sont codés de la manière suivante: ​ Les bits sont codés de la manière suivante: ​
-  - Le bit "​1"​ est représenté par un train d'​impulsion à 38Khz (avec rapport cyclique 50%) pendant 560us suivi par une inactivité ​pour une durée totale du bit de 2.25ms. +  - Le bit "​1"​ est représenté par un train d'​impulsion à 38Khz (avec rapport cyclique 50%) pendant 560us suivi par une inactivité. La durée totale du bit est de 2.25ms. 
-  - Le bit "​0"​ est représenté par un train d'​impulsion à 38Khz (avec rapport cyclique 50%) pendant 560us suivi par une inactivité ​pour une durée totale du bit de 1.12ms.+  - Le bit "​0"​ est représenté par un train d'​impulsion à 38Khz (avec rapport cyclique 50%) pendant 560us suivi par une inactivité. La durée totale du bit est de 1.12ms.
  
 Les entêtes de trames sont codés de la manière suivante: ​ Les entêtes de trames sont codés de la manière suivante: ​
Ligne 45: Ligne 51:
   - La trame de répétition commence par un train d'​impulsion à 38Khz (avec rapport cyclique 50%) pendant 9ms suivi par une inactivité de durée 2.25ms.   - La trame de répétition commence par un train d'​impulsion à 38Khz (avec rapport cyclique 50%) pendant 9ms suivi par une inactivité de durée 2.25ms.
 ===Dessin des chronogrammes=== ===Dessin des chronogrammes===
 +A faire sur papier et à faire noter par l'​enseignant:  ​
 +  - Dessiner l'​allure des chronogrammes pour l'​envoi d'une trame complète depuis la télécommande 0x1234 pour la touche 0x56 en faisant apparaître la valeur des différents bits transmis et la correspondance avec les données à transmettre (adresse de A15 à A0, touche de B7 à B0). 
 +  - Dessiner l'​allure des chronogrammes pour l'​envoi d'une trame de répétition depuis la télécommande 0x1234 pour la touche 0x56 (attention au piège!).
  
-Dessiner l'​allure des chronogrammes pour l'​envoie d'une trame complète depuis la télécommande 0x1234 pour la touche 0x56. 
  
- +{{http://​homepages.laas.fr/​bvandepo/​files/​iut/​tp_pic/​validation.png}}
-Dessiner l'​allure des chronogrammes pour l'​envoie d'une trame de répétition depuis la télécommande 0x1234 pour la touche 0x56. +
- +
- +
  
  
  
-===Configuration du timer 2=== +===Configuration du timer 2 pour la génération du signal modulé à 38Khz=== 
-[[http://​homepages.laas.fr/​bvandepo/​files/​iut/​Atmega328p_timer2.pdf]]+Consulter la documentation du timer 2 de l'​ATMEGA328P: ​[[http://​homepages.laas.fr/​bvandepo/​files/​iut/​Atmega328p_timer2.pdf]]
  
 L'​Atmega328 dispose de 4 timers : L'​Atmega328 dispose de 4 timers :
Ligne 63: Ligne 68:
  - Timer 2/3 : 8-bit avec PWM et possibilité d'​horloge externe  - Timer 2/3 : 8-bit avec PWM et possibilité d'​horloge externe
  
-Dans la suite des exercices nous utiliserons le Timer 2 en mode 7 "FAST PWM" (voir les différents mode en p 155!!!). +Dans la suite des exercices nous utiliserons le Timer 2 en mode 7 "FAST PWM" (voir les différents mode en p 155 de la documentation). 
  
  
-A l'aide de la documentation, ​proposer ​l'​algorithme de configuration du timer 2 pour pouvoir générer un signal à 38Khz sur une broche du microcontrôleur sans solliciter le processeur. ​Identifier quelle ​broche du micro-contrôleur ​le timer 2 peut piloter.+A l'aide de la documentation, ​nous allons définir ​l'​algorithme de configuration du timer 2 pour pouvoir générer un signal à 38Khz sur une broche du microcontrôleur sans solliciter le processeur. ​Le timer 2 peut piloter la broche ​3 (numérotation Arduino) ​du micro-contrôleur. Cette broche ​peut recopier l'​état d'un signal OC0B, que l'on peut décider de commuter à intervalle de temps fixé. La recopie ou non de ce signal sur la broche permet de générer facilement le signal modulé à 38Khz.
  
 +Pour configurer le timer, les registres TCCR2A et TCCR2B doivent être réglés en "​Normal port operation"​. ​
  
-<ifauth @prof> +Pour OC0A en "​disconnected",​ les bits COM2A doivent être réglés à
-Solution+  COM2A=00 ​   
-Configurer ​COM2A=00:  ​Normal port operationOC0A disconnected.+Pour OC0B en "​disconnected",​ (initialement le timer ne doit pas générer de signal PWM) les bits COM2B doivent être réglés à 
 +  COM2B=00  
 +Le mode de fonctionnement doit être réglé à 7 (voir table 18-8p155):  
 +  WGM2 = 111: Fast PWM, TOP=OCRA 
 +Pour régler la fréquence à 38Khz, le facteur de prescaling doit être réglé à 1/8 
 +  CS2 = 010 :  
 +et le registre OCR2A doit être réglé pour obtenir une fréquence du signal à 38Khz:  
 +  OCR2A= ​ valeur max du timer= ((16.000.000/​8)/​38.000)-1 
 +Pour régler la valeur du TON pour obtenir un rapport cyclique de 50%: 
 +  OCR2B=OCR2A/​2 
 +  ​
  
-(voir table 18-6, p154) 
-Configurer 
-  - COM2B=00: ​ Normal port operation, OC2B disconnected. 
-  - COM2B=10: ​ Clear OC2B on Compare Match, set OC2B at BOTTOM, (non-inverting mode). 
  
-(voir table 18-8p155): WGM2 111Fast PWM, TOP=OCRA+Proposer l'​algorithme pour la fonction **void setup(void)** qui permet de configurer le timer en réglant les registres TCCR2A, TCCR2B, OCR2A et OCR2B pour qu'il soit prêt à générer le signal à 38Khz. Vous penserez également à configurer la broche en sortie et à lui imposer un état bas.   
 +   
 +   
 +   
 +Le signal modulé est obtenu en alternant les mode de fonctionnement "​disconnected"​ et "Clear OC2B on Compare Match, set OC2B at BOTTOM, (non-inverting mode)" pour OC0B. Pour activer le signal PWM en sortie du timerOC0B devra être réglé en "Clear OC2B on Compare Match, set OC2B at BOTTOM, (non-inverting mode)" 
 +  COM2B=10       
 +Pour autoriser la sortie PWM sur cette broche, il faut passer le timer en mode 10 en mettant ​ 1 le bit COM2B1: 
 +  TCCR2A |= _BV(COM2B1);​ 
 +Pour empêcher la sortie ​PWM sur cette brocheil faut passer le timer en mode 00 en mettant ​ 0 le bit COM2B1: 
 +  TCCR2A &~(_BV(COM2B1));​ 
 +Dans la suite, pour maîtriser les durées, nous utiliserons la fonction **delayMicroseconds(time);​**
  
-CS2 = 010: prescaling 1/8+Les fonctions **void mark(int time)** et **void space(int time)** sont fournies. Elles permettent respectivement d'​activer (ou inhiber) le signal à 38 kHz pendant une durée time exprimée en us.
  
-Pour régler la période: OCR2A= ​ valeur max du timer= ((16.000.000/8)/38.000)-1+<file cpp ir1.ino>​ 
 +////////////////////////////////////////////////////////////////////////​  
 +void mark(int time) // pulse parameters in usec 
 +
 +  // Sends an IR mark for the specified number of microseconds. 
 +  // The mark output is modulated at the PWM frequency. 
 +  TCCR2A |_BV(COM2B1); // Enable pin 3 PWM output 
 +  if (time > 0) delayMicroseconds(time);​ 
 +
 +////////////////////////////////////////////////////////////////////////​ 
 +void space(int time) // pulse parameters in usec 
 +
 +  // Sends an IR space for the specified number of microseconds. 
 +  // A space is no output, so the PWM output is disabled. 
 +  TCCR2A &= ~(_BV(COM2B1)); // Disable pin 3 PWM output 
 +  if (time > 0) delayMicroseconds(time);​ 
 +
 +////////////////////////////////////////////////////////////////////////​ 
 +</​file>​
  
-Pour régler le TON: OCR2B=OCR2A/​2 
- </​ifauth>​ 
  
 +Proposer l'​algorithme pour la fonction **void loop(void)** qui permet de piloter le timer pour activer la sortie à 38Khz pendant 200us puis la désactiver pendant 400us.
  
-Que faire pour autoriser la sortie PWM sur cette broche? 
  
-<ifauth @prof> +Proposer ​(en utilisant les fonctions fourniesl'​algorithme ​pour la fonction **void sendNECBYTE(unsigned char data)** qui permet d'​envoyer,​ bit de poids faible d'​abord,​ les 8 bits de data.
-Solution: passer en mode 10 +
-  TCCR2A |= _BV(COM2B1)+
-</​ifauth>​ +
-    +
-Que faire pour empécher ​la sortie PWM sur cette broche?+
  
-<ifauth @prof> 
-Solution: passer en mode 00 
-  TCCR2A &= ~(_BV(COM2B1));​ 
-</​ifauth>​ 
  
 +Proposer l'​algorithme pour la fonction **void sendNECFrame(unsigned int adr, unsigned char cmd)** qui permet d'​envoyer la trame NEC complète, **adr** étant le numéro de télécommande et **cmd** le numéro de la touche.
  
 +Proposer l'​algorithme pour la fonction **void ​ sendNECFrameRepeat()** qui permet d'​envoyer la trame NEC de répétition.
  
-Dans la suite, pour maîtriser les durées, nous utiliserons la fonction **delayMicroseconds(time);​** 
  
 +{{http://​homepages.laas.fr/​bvandepo/​files/​iut/​tp_pic/​validation.png}}
  
-Proposer l'​algorithme pour la fonction **void sendNECBYTE(unsigned char data)** qui permet d'​envoyer,​ bit de poids faible d'​abord,​ les 8 bits de data. 
  
  
-Proposer l'​algorithme pour la fonction **void sendNECFrame(unsigned int adr, unsigned char cmd)** qui permet d'​envoyer la trame NEC complète, **adr** étant le numéro de télécommande ​et **cmd** le numéro de la touche.+==== Codage ​et tests ====
  
-Proposer l'​algorithme pour la fonction ​**void ​ ​sendNECFrameRepeat()** qui permet ​d'envoyer la trame NEC de répétition.+Implémenter les fonctions ​**void ​setup(void)** et **void loop(void)** pour configurer la sortie PWM à 38Khz. <color #​FF0000>​** Programmer la maquette et vérifier la fréquence du signal obtenu sur la broche 3 à l'​aide ​d'un oscilloscope.**</​color>​
  
  
-==== Codage et tests ====+{{http://​homepages.laas.fr/​bvandepo/​files/​iut/​tp_pic/​validation.png}}
  
-Implémenter la fonction **void setup(void)** pour configurer la sortie PWM à 38Khz. Vérifier à l'​oscilloscope la fréquence du signal généré. 
  
-implémenter ​les fonctions **void sendNECBYTE(unsigned char data)**, **void sendNECFrame(unsigned int adr, unsigned char cmd)** et **void ​ sendNECFrameRepeat()** et proposer un programme principal de test. +Implémenter ​les fonctions **void sendNECBYTE(unsigned char data)**, **void sendNECFrame(unsigned int adr, unsigned char cmd)** et **void ​ sendNECFrameRepeat()** et proposer un programme principal de test qui permette de balayer plusieurs adresses et numéros de commandes. Vous veillerez à assurer un temps d'​attente entre l'​émission de 2 trames consécutives pour obtenir au minimum une durée de 110ms entre chaque début de trame (pour cela calculer la durée minimum pour chacune des trame, et ajouter un délai à l'aide de la fonction Delay(time) ) 
  
  
-Utiliser une caméra de téléphone portable pour visualiser l'​activité de la Led infrarouge et demander à l'​enseignant de valider avec le récepteur/démodualteur infrarouge.+{{http://​homepages.laas.fr/​bvandepo/​files/​iut/​tp_pic/​validation.png}}
  
  
 +Programmer la carte Arduino et fermer le cavalier permettant de relier les Leds à la broche 3 de l'​Arduino. Utiliser une caméra de téléphone portable pour visualiser l'​activité de la Led infrarouge et demander à l'​enseignant de valider avec le récepteur/​démodulateur infrarouge.
 +  ​
 +
 +{{http://​homepages.laas.fr/​bvandepo/​files/​iut/​tp_pic/​validation.png}}
  
  
Ligne 235: Ligne 268:
  
 </​file>​ </​file>​
 +</​ifauth>​
 +
 +
 +
 +==== Réception/​décodage====
 +
 +Lire la documentation du récepteur VISHAY - TSOP2238 - RECEPTEUR IR 38KHZ , ref farnell 4913073
 +
 +datasheet: http://​www.farnell.com/​datasheets/​30485.pdf
 +
 +Lire et interpréter le fichier suivant: {{http://​homepages.laas.fr/​bvandepo/​files/​iut/​tp_ir/​maeNECPIC2.pdf}}
 +Proposer un portage de cette fonctionnalité sur l'​Arduino UNO R3.
 +
 +<ifauth @prof>
 +Solution:
 +
 +<file cpp testrecep2.ino>​
 +
 +
 +#define PIN_RX_IR ​ 8
 +#define PIN_DEBUG_IR ​ 13
 +#define PINRX (PINB & 0x1)
 +#define PORTDEBUG1 PORTB |=0x20;
 +#define PORTDEBUG0 PORTB &​= ​ ~0x20;
 +////////////////////////////////////////////////////////////////////////////////////////////////////////////​
 +///////// Function to print in hexadecimal with a known number of digits
 +void printHex(int num, int precision) {
 +     char tmp[16];
 +     char format[128];​
 +     ​sprintf(format,​ "​%%.%dX",​ precision);
 +     ​sprintf(tmp,​ format, num);
 +     ​Serial.print(tmp);​
 +}
 +////////////////////////////////////////////////////////////////////////////////////////////////////////////​
 +
 +inline void AttenteBas()
 +{
 +    while ( (PINRX) == 0);
 +}
 +////////////////////////////////////////////////////////////////////////////////////////////////////////////​
 +inline void AttenteHaut()
 +{
 +  while ( (PINRX) != 0);
 +}
 +////////////////////////////////////////////////////////////////////////////////////////////////////////////​
 +inline bool DetecteBas()
 +{
 +  return ​ (digitalRead(PIN_RX_IR) == 0);
 +}
 +////////////////////////////////////////////////////////////////////////////////////////////////////////////​
 +inline bool DetecteHaut()
 +{
 +  return (digitalRead(PIN_RX_IR) != 0);
 +}
 +////////////////////////////////////////////////////////////////////////////////////////////////////////////​
 +void setup()
 +{
 +  pinMode(PIN_DEBUG_IR,​ OUTPUT);
 +  pinMode(PIN_RX_IR,​ INPUT);
 +  digitalWrite(PIN_RX_IR,​ LOW);
 +  Serial.begin(9600);​
 +  // The string in Flash
 +  Serial.print( F(",​Filename:​ "));
 +  Serial.println( F(__FILE__));​
 +  Serial.print( F("​Compiled:​ "));
 +  Serial.print( F(__DATE__));​
 +  Serial.print( F(", "));
 +  Serial.println( F(__TIME__));​
 +  Serial.print( F("​GCC:"​));​
 +  Serial.println( F(__VERSION__));​ // -- compiler version as a string
 +  Serial.print(F( "​Arduino IDE version: "));
 +  Serial.println( ARDUINO, DEC);
 +  /*
 +  while(1)
 +  {
 +          PORTDEBUG0
 +        delay(10);
 +                PORTDEBUG1
 +                delay(10);
 +  }
 +  */
 +}
 +////////////////////////////////////////////////////////////////////////////////////////////////////////////​
 +unsigned int temps = 0;
 +unsigned int temps2 = 0;
 +unsigned int deltat = 0;
 +unsigned char etat = 0;
 +unsigned char error;
 +unsigned char octets[4] = {0, 0, 0, 0};
 +unsigned int repeat = 0;
 +unsigned char cptbit = 0;
 +unsigned char bytes[4];
 +////////////////////////////////////////////////////////////////////////////////////////////////////////////​
 +void loop()
 +{
 +  // mesure durée à l'​état haut, précis à 8us près...
 +  /*  AttenteBas();​
 +    temps = micros();
 +    AttenteHaut();​
 +    temps2 = micros();
 +    deltat=temps2 - temps;
 +    Serial.println(deltat,​ DEC);
 +    if ( (deltat>​4000) && (deltat<​5000))
 +        Serial.println("​normal"​);​
 +    if ( (deltat>​2000) && (deltat<​2500))
 +        Serial.println("​repeat"​);​
 +    delay(100);
 +    AttenteHaut();​
 +     }
 +     */
 +  switch (etat)
 +  {
 +    case 0:
 +      PORTDEBUG1
 +      if (DetecteBas())
 +      {
 +        temps = micros();
 +        etat = 1;
 +        error = 0;
 +      }
 +      break;
 +    case 1:
 +      PORTDEBUG0
 +      if (DetecteHaut())
 +      {
 +        temps2 = micros(); ​ deltat = temps2 - temps; temps = temps2;
 +        if ( (deltat > 8000) && (deltat < 9000))
 +        {
 +          etat = 2;
 +        }
 +        else
 +          etat = 0;
 +        //        error = 1;
 +      }
 +      break;
 +    case 2:
 +      PORTDEBUG1
 +      if (DetecteBas())
 +      {
 +        temps2 = micros(); ​ deltat = temps2 - temps; temps = temps2;
 +        //​Serial.println(deltat,​ DEC);
 +        if ( (deltat > 4000) && (deltat < 5000))
 +        {
 +          etat = 3;
 +          repeat = 0;
 +          cptbit = 0;
 +          bytes[0] = 0;
 +          bytes[1] = 0;
 +          bytes[2] = 0;
 +          bytes[3] = 0;
 +          //  Serial.println("​repeat"​);​
 +        }
 +        else   if ( (deltat > 2000) && (deltat < 2500))
 +        {
 +          etat = 0;
 +          repeat++;
 +          Serial.print("​+"​);​
 +          //  Serial.println("​repeat"​);​
 +        }
 +        break;
 +      case 3:
 +        PORTDEBUG0
 +        if (DetecteHaut())
 +        {
 +          temps2 = micros(); ​ deltat = temps2 - temps; temps = temps2;
 +          //    Serial.println(deltat,​ DEC);
 +          // delay(100);
 +          if (cptbit < 32)
 +            etat = 4;
 +          else
 +          {
 +            etat = 0;
 +            if (bytes[2] = ~bytes[3])
 +            {
 +              Serial.print("​="​);​
 +               ​printHex(bytes[0],​2); ​ //        Serial.print(bytes[0],​ HEX);
 +              Serial.print("​ ");
 +               ​printHex(bytes[1],​2); ​ //        Serial.print(bytes[1],​ HEX);
 +              Serial.print("​ ");
 +               ​printHex(bytes[2],​2); ​ //        Serial.print(bytes[2],​ HEX);
 +              Serial.print("​ ");
 +              /*
 +              Serial.print("​Trame complete:"​);​
 +              Serial.print(bytes[0],​ HEX);
 +              Serial.print(","​);​
 +              Serial.print(bytes[1],​ HEX);
 +              Serial.print(","​);​
 +              Serial.print(bytes[2],​ HEX);
 +              Serial.print(","​);​
 +              Serial.println(bytes[3],​ HEX);
 +              */
 +            }
 +          }
 +        }
 +        break;
 +      case 4:
 +        PORTDEBUG1
 +        if (DetecteBas() )
 +        {
 +          temps2 = micros(); ​ deltat = temps2 - temps; temps = temps2;
 +          //    Serial.println(deltat,​ DEC);
 +          // delay(100);
 +          if (deltat > 800)
 +            bytes[cptbit >> 3] |= (1 << (cptbit & 7));
 +          etat = 3;
 +          cptbit++;
 +          // if  (deltat > 2000)
 +        }
 +        break;
 +      }
 +  }
 +}
 +</​file> ​
 </​ifauth>​ </​ifauth>​
  
Ligne 281: Ligne 527:
 il faut du 950nm (j'en ai 10): http://​forums.futura-sciences.com/​electronique/​83501-led-ir.html il faut du 950nm (j'en ai 10): http://​forums.futura-sciences.com/​electronique/​83501-led-ir.html
  
- 
-=====recepteur===== 
-VISHAY - TSOP2238 - RECEPTEUR IR 38KHZ , ref farnell 4913073 
- 
- 
-datasheet: http://​www.farnell.com/​datasheets/​30485.pdf 
  
  
Ligne 346: Ligne 586:
 } }
 </​file>  ​ </​file>  ​
 +
 +
 +===== solution sous linux avec port série=====
 +http://​www.lirc.org/​
 +
 +http://​www.lirc.org/​receivers.html
  
 </​ifauth>​ </​ifauth>​
tpir.txt · Dernière modification: 2019/03/13 10:22 par bvandepo