Modifications

Sauter à la navigation Sauter à la recherche
9 810 octets ajoutés ,  4 avril 2019 à 17:17
aucun résumé de modification
Ligne 1 : Ligne 1 :  
{{SenseurIR-Nav}}
 
{{SenseurIR-Nav}}
   −
== xxx ==
+
{{ADFImage|IR-appleremote.jpeg|400px}}
xxx
     −
{{ADF-Accord}}
+
Pour notre projet final, nous allons utiliser une commande à distance pour envoyer des messages à un microcontrôleur. Par exemple, cela peut être utile afin de pouvoir piloter un robot à distance. C'est également un technique intéressante pour contrôler un projet à distance, sans avoir besoin de fils.
   −
{{MCH-Accord}}
+
En guise de télécommande, ce tuto utilise une télécommande Apple. Vous pouvez utiliser n'importe quelle type de télécommande, une déjà utilisée à la maison ou une de récupération.
 +
 
 +
Nous allons utiliser le code du croquis/sketch précédent pour lire les données en provenance de la télécommande mais cette fois, nous allons afficher le contenu des informations sous forme de tableau afin de détecter plus facilement un ''pattern'' (un patron).
 +
 
 +
<nowiki>
 +
void printpulses(void) {
 +
    Serial.println("\n\r\n\rReceived: \n\rOFF \tON");
 +
    for (uint8_t i = 0; i < currentpulse; i++) {
 +
      Serial.print(pulses[i][0] * RESOLUTION, DEC);
 +
      Serial.print(" usec, ");
 +
      Serial.print(pulses[i][1] * RESOLUTION, DEC);
 +
      Serial.println(" usec");
 +
    }
 +
    // print it in a 'array' format
 +
    Serial.println("int IRsignal[] = {");
 +
    Serial.println("// ON, OFF (in 10's of microseconds)");
 +
    for (uint8_t i = 0; i < currentpulse-1; i++) {
 +
      Serial.print("\t"); // tab
 +
      Serial.print(pulses[i][1] * RESOLUTION / 10, DEC);
 +
      Serial.print(", ");
 +
      Serial.print(pulses[i+1][0] * RESOLUTION / 10, DEC);
 +
      Serial.println(",");
 +
    }
 +
    Serial.print("\t"); // tab
 +
    Serial.print(pulses[currentpulse-1][1] * RESOLUTION / 10, DEC);
 +
    Serial.print(", 0};");
 +
}
 +
</nowiki>
 +
 
 +
Le nouveau croquis téléversé sur notre Arduino, pressons le bouton "Jouer" de la télécommande et voyons le résutlat que nous allons obtenir:
 +
 
 +
<nowiki>
 +
int IRsignal[] = { // ON, OFF (in 10's of microseconds)
 +
    912, 438,
 +
    68, 48,
 +
    68, 158,
 +
    68, 158,
 +
    68, 158,
 +
    68, 48,
 +
    68, 158,
 +
    68, 158,
 +
    68, 158,
 +
    70, 156,
 +
    70, 158,
 +
    68, 158,
 +
    68, 48,
 +
    68, 46,
 +
    70, 46,
 +
    68, 46,
 +
    68, 160,
 +
    68, 158,
 +
    70, 46,
 +
    68, 158,
 +
    68, 46,
 +
    70, 46,
 +
    68, 48,
 +
    68, 46,
 +
    68, 48,
 +
    66, 48,
 +
    68, 48,
 +
    66, 160,
 +
    66, 50,
 +
    66, 160,
 +
    66, 52,
 +
    64, 160,
 +
    66, 48,
 +
    66, 3950,
 +
    908, 214,
 +
    66, 3012,
 +
    908, 212,
 +
    68, 0 };
 +
</nowiki>
 +
 
 +
Nous allons essayer de détecter ce code. Essayons de démarrer un nouveau croquis appelé IR Commander ([http://github.com/adafruit/IR-Commander la version finale du code est disponible sur le GitHub d'AdaFruit]) qui utilisera une partie de notre précédent croquis.
 +
 
 +
La première partie écourtera simplement le code Infrarouge et placera les temps d'impulsion dans le tableau {{fname|pulses[]}}. Il retournera le nombre d'impulsions détecté comme valeur de retour.
 +
 
 +
<nowiki>
 +
int listenForIR(void) {
 +
currentpulse = 0;
 +
while (1) {
 +
    uint16_t highpulse, lowpulse; // temporary storage timing
 +
    highpulse = lowpulse = 0; // start out with no pulse length
 +
    // while (digitalRead(IRpin)) { // this is too slow!
 +
    while (IRpin_PIN & (1 << IRpin)) {
 +
      // pin is still HIGH
 +
      // count off another few microseconds
 +
      highpulse++;
 +
      delayMicroseconds(RESOLUTION);
 +
      // If the pulse is too long, we 'timed out' - either nothing
 +
      // was received or the code is finished, so print what
 +
      // we've grabbed so far, and then reset
 +
      if ((highpulse >= MAXPULSE) && (currentpulse != 0)) {
 +
          return currentpulse;
 +
      }
 +
    }
 +
    // we didn't time out so lets stash the reading
 +
    pulses[currentpulse][0] = highpulse;
 +
    // same as above
 +
    while (! (IRpin_PIN & _BV(IRpin))) {
 +
      // pin is still LOW
 +
      lowpulse++;
 +
      delayMicroseconds(RESOLUTION);
 +
      if ((lowpulse >= MAXPULSE) && (currentpulse != 0)) {
 +
          return currentpulse;
 +
      }
 +
    }
 +
    pulses[currentpulse][1] = lowpulse;
 +
    // we read one high-low pulse successfully, continue!
 +
    currentpulse++;
 +
    }
 +
}
 +
</nowiki>
 +
 
 +
Notre nouvelle fonction {{fname|loop()}} ne fera qu' "écouter" après les impulsions.
 +
 
 +
<nowiki>
 +
void loop(void) {
 +
    int numberpulses;
 +
    numberpulses = listenForIR();
 +
    Serial.print("Heard ");
 +
    Serial.print(numberpulses);
 +
    Serial.println("-pulse long IR signal");
 +
}
 +
</nowiki>
 +
 
 +
Lorsqu'il fonctionne, il affiche quelque chose comme ceci...
 +
 
 +
{{ADFImage|IR-pulsecounter.jpg}}
 +
 
 +
OK, il est maintenant temps de faire en sorte que notre croquis compare ce qu'il à reçu et ce qu'il a déjà dans le notre tableau de référence:
 +
 
 +
{{ADFImage|IR-ircompare.jpg}}
 +
 
 +
Comme vous pouvez le voir, il y a quelques variations. Lorsque nous faisons la comparaison, nous ne pouvons malheureusement pas attendre d'avoir exactement les mêmes valeurs, nous devons opter pour une méthode un peu plus 'créative'.
 +
 
 +
Disons que la valeur peu varier d'environ 20% - cela devrait être suffisant.
 +
 
 +
<nowiki>
 +
// Quel pourcentage de variation est toléré durant la comparaison de deux code
 +
#define FUZZINESS 20
 +
 
 +
void loop(void) {
 +
    int numberpulses;
 +
    numberpulses = listenForIR();
 +
    Serial.print("Heard ");
 +
    Serial.print(numberpulses);
 +
    Serial.println("-pulse long IR signal");
 +
    for (int i=0; i< numberpulses-1; i++) {
 +
      int oncode = pulses[i][1] * RESOLUTION / 10;
 +
      int offcode = pulses[i+1][0] * RESOLUTION / 10;
 +
 
 +
      Serial.print(oncode); // le signal ON réceptionné
 +
      Serial.print(" - ");
 +
      Serial.print(ApplePlaySignal[i*2 + 0]); // Le signal ON attendu
 +
      // Vérifier pour s'arrure que l'erreur est inférieure à FUZZINESS pourcent
 +
      if ( abs(oncode - ApplePlaySignal[i*2 + 0]) <= (oncode * FUZZINESS / 100)) {
 +
        Serial.print(" (ok)");
 +
      } else {
 +
        Serial.print(" (x)");
 +
      }
 +
      Serial.print(" \t"); // tab
 +
 
 +
      Serial.print(offcode); // Le signal OFF réceptionné
 +
      Serial.print(" - ");
 +
      Serial.print(ApplePlaySignal[i*2 + 1]); // Le signal OFF attendu
 +
      if ( abs(offcode - ApplePlaySignal[i*2 + 1]) <= (offcode * FUZZINESS / 100)) {
 +
        Serial.print(" (ok)");
 +
      } else {
 +
        Serial.print(" (x)");
 +
      }
 +
      Serial.println();
 +
    }
 +
}
 +
</nowiki>
 +
 
 +
{{ADFImage|IR-codecompareok.jpg}}
 +
 
 +
Cette fonction {{fname|loop()}}, est exécutée pour chaque impulsion, fait quelques opérations mathématique. Elle compare la différence absolue ({{fname|abs()}}) entre ce que code réceptionne (IR reçu) et le code auquel nous essayons de le faire correspondre {{fname|abs(oncode - ApplePlaySignal[i*2 + 0])}} et ensuire s'assurer que l'erreur est inférieure FUZZINESS pourcent de la longueur du code
 +
( {{fname| oncode * FUZZINESS / 100}} )
 +
 
 +
Il est généralement nécessaire d'adapter un peu les valeurs stockées pour obtenir 100% correspondance à chaque fois. Le signal infrarouge n'est pas un protocol qui s'appuie sur la précision temporelle (''not a precision-timed protocol''), par conséquent une marge d'erreur de 20% (FUZZINESS=20%) et plus n'est pas une mauvaise chose.
 +
 
 +
Pour finir, Le contenu de {{fname|loop()}} est transformé en sa propre fonction qui retourne '''true''' ou '''false''' en fonction du code que nous luis avons demandé de vérifier. Les lignes {{fname|Serial.print()}} ont également été mises en commentaire.
 +
 
 +
<nowiki>
 +
boolean IRcompare(int numpulses, int Signal[]) {
 +
    for (int i=0; i< numpulses-1; i++) {
 +
        int oncode = pulses[i][1] * RESOLUTION / 10;
 +
        int offcode = pulses[i+1][0] * RESOLUTION / 10;
 +
 
 +
        /*
 +
        Serial.print(oncode); // Le signal ON reçu
 +
        Serial.print(" - ");
 +
        Serial.print(Signal[i*2 + 0]); // Le signal ON attendu
 +
        */
 +
        // Vérifier que l'erreur est inférieure à FUZZINESS pourcent
 +
        if ( abs(oncode - Signal[i*2 + 0]) <= (Signal[i*2 + 0] * FUZZINESS / 100)) {
 +
            //Serial.print(" (ok)");
 +
        } else {
 +
            //Serial.print(" (x)");
 +
            // Pas de correspondance parfaite, retourner false
 +
            return false;
 +
        }
 +
   
 +
        /*
 +
        Serial.print(" \t"); // tabulation
 +
        Serial.print(offcode); // Le signal OFF reçu
 +
        Serial.print(" - ");
 +
        Serial.print(Signal[i*2 + 1]); // Le signal OFF que nous attendons
 +
        */
 +
        if ( abs(offcode - Signal[i*2 + 1]) <= (Signal[i*2 + 1] * FUZZINESS / 100)) {
 +
          //Serial.print(" (ok)");
 +
        } else {
 +
          //Serial.print(" (x)");
 +
          // Pas de correspondance parfaite, retourner false
 +
          return false;
 +
        }
 +
        //Serial.println();
 +
    }
 +
    // Tout correspond!
 +
    return true;
 +
}
 +
</nowiki>
 +
 
 +
Ensuite, nous capturons plus de données infrarouge comme 'précédent' (''rewind'') ou 'suivant' (''fastforward'') et plaçons ces informations dans des tableaux stockés dans le fichier {{fname|ircodes.h}} pour éviter que le croquis/sketch principal ne devienne trop long et illisible ([http://github.com/adafruit/IR-Commander vous pouvez obtenir tout le code depuis le GitHib d'AdaFruit)
 +
 
 +
A la fin, la boucle principale ressemble à ceci:
 +
 
 +
<nowiki>
 +
void loop(void) {
 +
    int numberpulses;
 +
    numberpulses = listenForIR();
 +
 
 +
    Serial.print("Heard ");
 +
    Serial.print(numberpulses);
 +
    Serial.println("-pulse long IR signal");
 +
    if (IRcompare(numberpulses, ApplePlaySignal)) {
 +
      Serial.println("PLAY");
 +
    }
 +
    if (IRcompare(numberpulses, AppleRewindSignal)) {
 +
      Serial.println("REWIND");
 +
    }
 +
    if (IRcompare(numberpulses, AppleForwardSignal)) {
 +
      Serial.println("FORWARD");
 +
    }
 +
}
 +
</nowiki>
 +
 
 +
Nous vérifions les données réçues par rapport aux codes infrarouges que nous connaissons déjà et affichons un message avec ce que nous avons détecté.
 +
 
 +
Voila, une fois nos tests réussis, il ne reste plus qu'a prendre ce code pour en faire quelque-chose de plus utile (en fonction du bouton pressé).
 +
 
 +
{{ADFImage|mulitirbutton.jpg}}
 +
 
 +
{{SenseurIR-TRAILER}}
29 837

modifications

Menu de navigation