Hora de escrever algo de jeito.

Tinha um comando de TV, comprado nos chineses há bastante tempo, ali encostado (RM-E86). Não pode ser! Tenho de lhe dar uma utilidade!
Pois bem, daí partiu a mais recente engenhoca. Um circuito receptor de IR, usando um microcontrolador PIC16F88 e o sensor receptor, neste caso retirado de uma televisão velha.

          

O primeiro passo foi recorrer a um logic analyser e ver o que o sensor recebe quando pressiono a tecla "1".

Depois de guardada esse sequência, pressionei a tecla "2" e guardei a sequência também.

Nisto, voltei a analisar o que corresponde à tecla "1", mas como a janela mal dimensionada, testei novamente. Eis que tive a impressão que embora tenha carregado as 2 vezes na tecla "1", o gráfico lógico não era igual.

Ganhei gratuitamente mais um problema para resolver...

Conclui que o código da tecla "1" era diferente do da tecla "2", mas se carregasse 2 vezes seguidas a tecla "1", este código era exactamente igual ao primeiro da tecla "2".

Xiiii... meu Deus que confusão.
Estive a pesquisar um pouco sobre protocolos de IR para controlos remotos e encontrei este página:

Podem ver vários outros protocolos, pelo menos o principio de funcionamento deles.

Por aquilo que tinha lido, o protocolo da ITT era mais fácil de "manipular" a sua recepção. No site falam em apenas 14 pulsos, etc, etc...

Passo seguinte, encontrar o manual do comando e alterar o código para um equipamento da ITT.

Feito isto, voltava ao ponto de partida. Desta vez carreguei a tecla "1" e "2" várias vezes para confirmar que o código era sempre o mesmo.

Resultou nisto:
Tecla "1" - clique para ver maior

Tecla "2"
Tecla "2" - clique para ver maior

Um bocado diferente do que esperava (os tais 14 pulsos, bla bla bla), mas ok! Sem problema, demora um pouco mais, mas também se faz!

O micro foi programado para quando receber o sinal correspondente à tecla "1" ou "2", acender um led de acordo com o que foi recebido.

O código, compilado em CCS:

#include <16F88.h>
#FUSES INTRC_IO, NOWDT, NOMCLR, PUT, NOBROWNOUT, NOLVP
#USE delay(clock=4000000)
#include <stdlib.h>

#use standard_io(A)
#use standard_io(B)

//usado protocolo ITT

void pic_init()
{
    SETUP_CCP1(CCP_OFF);
    setup_comparator(NC_NC_NC_NC);
    setup_oscillator(OSC_4MHZ);
    SETUP_ADC(ADC_OFF);
    SETUP_ADC_PORTS(NO_ANALOGS);
    SETUP_TIMER_0(T0_DIV_32);                        //incrementa a cada 32uS, overflow 8.19mS
}

void main()
{

    int codigo[32], i;
    const int numum[]={2,2,1,1,1,1,1,2,1,2,1,2,2,2,2,1,2,1,1,1,2,1,1,1,1,2,2,2,1,2,2,2};
    const int numdois[]={2,2,1,1,1,1,1,2,1,2,1,2,2,2,2,1,1,2,1,1,2,1,1,1,2,1,2,2,1,2,2,2};
    
    pic_init();
    
    output_bit(PIN_B0,1);
    output_bit(PIN_B1,1);
    delay_ms(500);
    output_bit(PIN_B0,0);
    output_bit(PIN_B1,0);
    
    while(TRUE)
    {
        
        for(i=0;i<32;i++)                                                //colocar todo o vector a 1's
        {
            codigo[i]=1;
        }
        
        while(input(PIN_A1));                                       //espera pela descida
        while(!input(PIN_A1));                                     //espera pela subida                                    
        while(input(PIN_A1));                                    //espera pela descida
        
        
        for(i=0;i<32;i++)
        {    
            while(!input(PIN_A1));                               //espera pela subida
            set_timer0(0);
            while(input(PIN_A1));                                //espera pela descida
            codigo[i]=get_timer0();                              //tempo em alto
        }
        
        
        for(i=0;i<32;i++)                                               //atribuir valores mais faceis ao vector
        {
            if(codigo[i]>14 && codigo[i]<20)               //se for curto
                codigo[i]=1;
            else
            {    
                if(codigo[i]>45 && codigo[i]<53)           //se for longo
                    codigo[i]=2;
                else codigo[i]=0;                                           //se for José Castelo Branco
            }
        }
                                                                                    //comparar com os vectores originais
        for(i=0;i<32;i++)
        {
            if(codigo[i]!=numum[i])
                goto proximo2;
        }
        
        output_bit(PIN_B0,1);
        output_bit(PIN_B1,0);
        goto proximo3;
        
        proximo2:
            for(i=0;i<32;i++)
            {
                if(codigo[i]!=numdois[i])
                    goto proximo3;
                
            }
            
        output_bit(PIN_B0,0);
        output_bit(PIN_B1,1);
        
        proximo3:
        
        delay_ms(500);                                                  //aguarda o final de ecos
        
    }
}



Um breve descrição do código:

Esta não será a única forma de pôr isto a funcionar e certamente há outras formas.

Poderia ter colocado tudo a funcionar por interrupções, mas não vi necessidade disso pois o objectivo era ligar 2 (ou mais) LEDs apenas. Estes podem ser substituidos por relés, foguetes, aceleradores interestelares, etc..

Para facilitar a leitura e o armazenamento do vector correspondente à tecla "1" e à tecla "2", substitui os tempos (em nivel alto), dados pelo logic analyser por números simples. Ora os pulsos mais curtos (têm todo o mesmo tempo) atribui o valor 1 e os pulsos maiores (parecem ter o dobro dos curtos) atribui o valor 2. Aos restantes que possam eventualmente surgir de erros ou situações inesperadas (outras teclas do comando, por exemplo) é atribuído o valor 0.

Vector tecla "1" - {2,2,1,1,1,1,1,2,1,2,1,2,2,2,2,1,2,1,1,1,2,1,1,1,1,2,2,2,1,2,2,2}

Vector tecla "2" - {2,2,1,1,1,1,1,2,1,2,1,2,2,2,2,1,1,2,1,1,2,1,1,1,2,1,2,2,1,2,2,2}

Agora só tenho de ler o sensor e guardar os valores. Depois fazer uma associação dos tempos, para ter tudo à base de 1's, 2's ou 0's e por último comprar com estes vectores em cima. Se todo o vector for igual, então encontrei a tecla que foi pressionada.
1º espero pela 1ª descida;

2º espero pela 1ª subida;

3º espero pela 2ª descida;

4º espero pela 2ª subida colocando logo em seguida o timer a zero;

5º espero pela 3ª descida e logo em seguida faço a leitura do timer, que é armazenado num vector;

Repete 4º e 5º até que o vector fique cheio (32 posições, correspondentes as 32 pulsos).

6º Associo os valores temporais a 1, 2 ou 0;

7º Comparação numero a número dos vectores, o recebido e o armazenado na memória;

8º Por último liga o LED correspondente;

Um problema que pode surgir é o do micro ficar retido num dos "while", porque foi detectada numa queda e quando pegar no comando e clicar "1", ele não acciona o LED correspondente.

Um problema mas de fácil resolução. O último delay (o de 500ms) faz com que este problema se resolva.

Vamos supor que vários controlos remotos foram accionados perto deste sensor (eu testei e nem deu grandes problemas) e que o micro já encheu metade do vector! Quando eu carregar "1" ele não vai ligar o LED nº1, porque o vector estava cheio de lixo e quando eu carrego "1" acabo de o encher.

Os restantes pulsos que são enviados pelo comando já não são recebidos pelo circuito, pois ele aguarda um tempo para permitir que esses "ecos"/emissões sejam terminadas e só depois retoma o ciclo.

O grande inconveniente? Bem... se estiver num local muito ruidoso (muitas emissões IR) por vezes será necessário carregar duas vezes a tecla "1" ou "2" para ligar o LED que se pretende.
Solução? Sim, há solução para que isso não aconteça, mas para o caso não vale a pena. O objectivo era ligar um LED com o carregar de um botão num controlo remoto. Foi conseguido!

Fotos:

 

0 Responses so far.

Enviar um comentário