Cómo obtener códigos consistentes del módulo receptor IR TSOP1738

Estoy haciendo algunos experimentos con un módulo receptor TSOP1738 . Tomé un pequeño 'control remoto' (también conocido como un transmisor IR) del sistema de audio de mi automóvil y estoy tratando de enviar un comando a un robot. No tengo idea de qué codificación está usando este control remoto en particular. Conecté el módulo TSOP a un osciloscopio y descubrí las señales que salían de él. Lo decodifiqué de la siguiente manera.

  • La ráfaga inicial es de alrededor de 4000+ uS.
  • El 1 lógico es para alrededor de 2000+US
  • 0 lógico es para alrededor de 600+US

A partir de esta información, decodifiqué los comandos enviados por el control remoto y parecía bastante razonable. Conecté el módulo TSOP a un Arduino y trabajé poco a poco con los datos que llegaban del módulo receptor IR. Últimamente descubrí que todos los primeros 16 bits que provenían de él eran exactamente iguales para todos los botones que presiono en el control remoto. Así que lo eliminé y usé los últimos 16 bits para crear un valor de clave int sin firmar para cada botón del control remoto. Lo encontré funcionando como se esperaba. Pero el problema al que me enfrento en este momento es que obtengo diferentes valores clave para la misma pulsación de botón. Es decir, si presiono dos veces el botón de encendido del control remoto, ambas presiones me dan datos diferentes. ¿Cómo puedo hacer esto consistente? ¿Es este algún tipo de ruido que causa el problema?

Aquí está el boceto de arduino que uso.

int irPin = 2;          //Sensor pin 1 wired to Arduino's pin 2
int statLED = 13;       //Toggle the status LED every time Power is pressed
int start_bit = 2200;   //Start bit threshold (Microseconds)
int bin_1 = 2000;       //Binary 1 threshold (Microseconds)
int bin_0 = 600;        //Binary 0 threshold (Microseconds)

void setup() {
    pinMode(statLED, OUTPUT);
    digitalWrite(statLED, LOW);
    pinMode(irPin, INPUT);
    Serial.begin(9600);
    Serial.println("Waiting: ");
}

void loop() {
    unsigned int key = getIRKey();
    Serial.print(" > ");
    Serial.println(key);
}

int getIRKey() {
    int data[32];
    int i;

    while(pulseIn(irPin, LOW) < start_bit);//Wait for a start bit

    for(i = 0 ; i < 32 ; i++)
        data[i] = pulseIn(irPin, HIGH);    //Start measuring bits, only high    pulses needed.

    int key_data[16];                      //First 16 bits arw the same for all keys.
    for(i = 16 ; i < 32 ; i++)  {          //Parse them
        Serial.print(data[i]);
        Serial.print(" ");
        if(data[i] > bin_1)                //is it a 1?
            key_data[i-16] = 1;
        else if(data[i] > bin_0)           //is it a 0?
            key_data[i-16] = 0;
        else
            return -1;                     //Flag the data as invalid;
    }

    Serial.print(" = ");
    unsigned int result = 0;
    for(i = 0 ; i < 16 ; i++)  {           //Convert key_data bits to integer
        Serial.print(key_data[i]);
        if(key_data[i] == 1)
            result |= (1 << i);
    }
    return result;
}

Y este es el resultado del boceto anterior, cuando presiono el mismo botón en el control remoto un par de veces.

2162 725 682 695 694 694 658 730 652 2094 2165 2167 2171 2164 2167 2128  = 1000000001111111 > 65025
2095 721 658 692 696 627 659 650 650 2090 2053 2173 2139 2093 2098 2129  = 1000000001111111 > 65025
2124 2128 2127 654 619 691 620 654 649 648 610 2131 2132 2131 2127 2091  = 1110000000011111 > 63495
2133 2103 2089 613 610 682 619 654 655 654 617 2127 2124 2124 2137 2132  = 1110000000011111 > 63495
2125 2127 2133 654 619 649 612 645 649 648 619 2136 2133 2123 2094 2124  = 1110000000011111 > 63495
2093 2089 2098 657 655 610 649 612 646 648 654 2098 2098 2093 2089 2090  = 1110000000011111 > 63495
2099 2123 2091 684 655 654 657 621 620 683 612 2124 2128 2136 2133 2091  = 1110000000011111 > 63495
2104 2095 2128 657 649 611 688 627 657 665 658 2056 2094 2060 2169 2132  = 1110000000011111 > 63495
2127 1952 2099 692 620 620 657 648 610 682 611 2098 2132 2136 2127 2125  = 1010000000011111 > 63493
2091 649 648 611 683 621 655 655 621 2090 2090 2094 2102 2099 2102 2090  = 1000000001111111 > 65025
2127 649 620 654 655 657 620 683 612 2125 2090 2135 2135 2123 2091 2125  = 1000000001111111 > 65025
2093 649 655 619 691 620 654 684 646 2091 2090 2102 2098 2125 2094 2091  = 1000000001111111 > 65025
2098 655 648 612 682 611 646 658 655 2099 2090 2094 2089 2098 2101 2099  = 1000000001111111 > 65025
2161 694 658 691 697 646 612 686 615 2127 2133 2136 2124 2125 2131 2135  = 1000000001111111 > 65025
2101 2167 2090 683 646 623 655 621 694 691 648 2166 2094 2064 2173 2161  = 1110000000011111 > 63495
2090 2097 2128 658 695 655 658 688 684 615 649 2095 2099 2101 2095 2090  = 1110000000011111 > 63495
2162 729 661 623 697 617 649 722 650 2095 2173 2066 2164 2059 2131 2170  = 1000000001111111 > 65025
@RedGrittyBrick De hecho, vi el video de Dave esta mañana y por eso comencé a trabajar en este proyecto. :) ¿Podría averiguar por qué obtengo datos inconsistentes del módulo TSOP?
¿Estás seguro de que tu control remoto usa una portadora de 38 KHz? El 1738 está bloqueado a 38 KHz, que no es la única frecuencia portadora en uso. A partir de los datos recibidos, parece que su control remoto podría ser de 36 KHz o 40 KHz, ambos lo suficientemente cerca como para ser detectados por el 1738, pero con marcos de datos no válidos. Una comprobación sencilla: conecte un fotodiodo (o, en un apuro, un LED rojo transparente como el agua) a las sondas del osciloscopio y, a continuación, vea qué frecuencia portadora aparece cuando se pulsa un botón en el mando a distancia mientras lo apunta hacia el fotodiodo o el LED.
Su umbral bin1 es demasiado alto, está leyendo 2127 1952 2099 como 101 cuando claramente es 111. El resto parece problemas de sincronización: problemas para identificar el inicio de los datos. Seguiría el consejo de Anindo y luego verificaría si serial.print lento podría estar afectando algo (no estoy familiarizado con las funciones utilizadas en su código). La otra posibilidad es que una pulsación larga inicie una función de botón secundario.
@AnindoGhosh Intenté hacer el experimento que sugeriste. No tengo un fotodiodo y, por lo tanto, probé con un LED rojo claro, pero no puedo obtener la señal en el alcance. Más bien, tengo un módulo receptor separado que obtuve con el sistema de audio que tiene un conector TRS . Entonces esto debería coincidir en la frecuencia de la portadora y todo. Pero no puedo identificar los pines en él. Tengo 804 OHM entre la unión del manguito y 746 OHM entre la unión del manguito y la punta. ¿Algunas ideas? (NB: la segunda solución que tengo en mente es crear un control remoto con LED IR que tengo aquí).
@RedGrittyBrick Probé con los umbrales bin_1 = 1000 y bin_0 = 400 y el problema aún no se resuelve. El problema parece ser, como dijo Anindo, que podría estar usando un control remoto de frecuencia portadora diferente. Aunque aún no está confirmado.
@Napster También puede averiguar la frecuencia de la portadora probando las patas de los LED dentro del control remoto, mientras presiona un botón. Probablemente no tenga ningún problema para conectar sondas de alcance al LED, ya que los controles remotos a menudo usan LED de orificio pasante con patas largas para alcanzar la abertura en la caja de plástico. Fuente: acabo de abrir algunos controles remotos para verificar esto :-)

Respuestas (1)

En mi experiencia, al decodificar señales IR, casi siempre es mejor ser muy pedante con los tiempos de la señal. Por ejemplo, solo acumular los tiempos ALTOS en una matriz funcionará la mayor parte del tiempo, pero no hará frente a las ráfagas de ruido ocasionales. Debe validar cada período ALTO y BAJO.

Como otro ejemplo de la necesidad de tener cuidado con los tiempos, para la señal de "inicio", solo detecta que el período BAJO inicial (es decir, una ráfaga IR de 38 kHz) es más largo que el mínimo (2200)... pero ¿y si es mucho más debido a una explosión de ruido? ¿Y si el tiempo de tranquilidad inmediatamente después de eso es demasiado largo o demasiado corto? Disparará falsamente y luego continuará tratando de dar sentido a la señal posiblemente aún ruidosa que sigue y obtendrá un resultado poco confiable.

Lo que sugeriría es que use su alcance y las cifras de tiempo para tener una idea de los tiempos correctos (lo que ha hecho en gran medida), y escriba su código para detectar si cada bit individual es válido (es decir, tanto tiempos BAJOS como ALTOS). están dentro de la tolerancia) y, si se encuentra un bit no válido, ignore todas las transiciones adicionales durante, digamos, 100 ms antes de volver a escuchar una secuencia de "inicio". El objetivo es nunca intentar procesar un comando a menos que se sepa que se analizó por completo.

Además (probablemente menos importante) los 16 bits que parecen ser siempre los mismos pueden no ser siempre así. Es posible que simplemente no haya visto los casos en los que son significativos. Tal vez sean para una dirección de dispositivo y/o banderas (como "tecla presionada y sostenida"). En algunos protocolos, la secuencia de la señal cambia significativamente cuando se presiona y mantiene presionada una tecla remota, y otros alternan un poco en el campo "comando" a medida que se emite cada comando.

Creo que una buena manera de analizar rigurosamente una señal IR es usar una máquina de estados finitos (FSM). Para ver un ejemplo, puede ver mi proyecto de código abierto en http://sourceforge.net/projects/irk-usb/ ... no es para arduino, pero de todos modos debería ser útil.

+1 por explicar diferentes aspectos del proceso. De hecho, hice exactamente lo que has explicado en tu respuesta. Hice un análisis riguroso de los valores exactos del código clave y cualquier cosa que viole un rango de tiempo, se descarta según mi nuevo código aquí . El problema que tenemos con este enfoque es que tengo que presionar el mismo botón varias veces para registrarlo correctamente. Es decir, ¡la mayoría de las pulsaciones de teclas se filtran como códigos no válidos! :)
Me acabo de dar cuenta de que el patrón se parece al protocolo NEC IR remotecentral.com/features/irdisp4.htm ... los 32 bits consisten en 4 bytes de 8 bits: [A, ~A, C, ~C] donde A = dirección, C = comando, y ~x significa complemento a uno de x (es decir, invertida). Entonces, una verificación de seguridad adicional que podría hacer es asegurarse de que (A xor ~A) == 0 y (C xor ~C) == 0. De sus ejemplos, parece que hay dos comandos 0x80 y 0xE0 que representan el mismo botón. Una pista es que están agrupados en el tiempo, por lo que podría ser un mecanismo indicador de "pulsación rápida de botón".
Sí, es A,~A,C,~C por supuesto. Pero aún persiste el problema que mencioné en el comentario anterior. He agregado una captura de pantalla de la señal del osciloscopio en la publicación del blog aquí .