sexta-feira, 27 de março de 2015

Controle remoto com PIC - Parte2

         Conforme demonstrado anterior o projeto é dividido em codificador e decodificador, agora vou mostrar como é o código do receptor de controle remoto.

O código fonte:

/*
 *                                               usando o modo CCP no MPlab XC8
 *
 * Compilador : MPlabXC8
 * Microcontrolador: 16F648A
 * Autor: aguivone
 * Versão: 1
 * Data :  01 de março de 2013
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h> //para usar funçoes de string deve se adicionar este header
#define _XTAL_FREQ 4000000    // oscilador interno de 4 Mhz
#include <xc.h>
/////////////////////////////////////////////////////////configuraçôes//////////////////////////////////////////////////
#define LED_STATUS RB0
#define SINAL PORTAbits.RA0

#pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
#pragma config BOREN = ON       // Brown-out Detect Enable bit (BOD enabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

////////////////////////////////////////////////variaveis globais///////////////////////////////////////////////////////////
long  anterior = 0, atual = 0,largura_pulso = 0;
int   primeiro_pacote = 0,valor_pulso=0;
long  timeout = 0;
long  bit_0=0,bit_1=0,start_stop=0,range_bit=150;

///////////////////////////////////////////////////interrupção//////////////////////////////////////////////////////////////
void interrupt CCP1(void)
{
 if(CCP1IF) //verifica se é interrupção de cpp
    {// cada incremtento do timer será a cada 1us ,pois estou usando o oscilador interno de 4mhz
        atual = CCPR1;
        CCP1IF = 0; //limpa interrupção de captura de sinal
                if (anterior > atual)
                {
                    largura_pulso = (0XFFFF - anterior) + atual;
                }
                else
                {
                    largura_pulso = atual - anterior;
                }
       anterior = atual;
   }
 }
/////////////////////////////////funçoes usadas pela uart //////////////////////////////////////////////////////
void inicializa_RS232(long velocidade,int modo)
{////por padrão é usado o modo 8 bits e sem paridade, mas se necessario ajuste aqui a configuração desejada.
    //verifique datasheet para ver a porcentagem de erro e se a velocidade é possivel para o cristal utilizado.
    RCSTA = 0X90;//habilita porta serial,recepção de 8 bit em modo continuo,assincrono.
    int valor;
        if(modo == 1)
        {//modo = 1 ,modo alta velocidade
         TXSTA = 0X24;//modo assincrono,trasmissao 8 bits.
         valor =(int)(((_XTAL_FREQ/velocidade)-16)/16);//calculo do valor do gerador de baud rate
        }
        else
        {//modo = 0 ,modo baixa velocidade
         TXSTA = 0X20;//modo assincrono,trasmissao 8 bits.
         valor =(int)(((_XTAL_FREQ/velocidade)-64)/64);//calculo do valor do gerador de baud rate
        }
    SPBRG = valor;
    RCIE = 0;//não vou receber nenhum dado do pc
    //RCIE = 1;//habilita interrupção de recepção
    TXIE = 0;//deixa interrupção de transmissão desligado(pois corre se o risco de ter uma interrupção escrita e leitura ao mesmo tempo)
}
void escreve(char valor)
{
    TXIF = 0;//limpa flag que sinaliza envio completo.
    TXREG = valor;
    while(TXIF ==0);//espera enviar caracter
}
void imprime(const char frase[])
{
     char indice = 0;
     char tamanho = strlen(frase);
      while(indice < tamanho ) ///veja que o programa pode travar se aqui não tiver as duas aspas
       {
           escreve(frase[indice]);
           indice++;
       }
}
void inicializa_CCP() {
    //habilita captura de pulso na borda de subida (prescaler sem divisão)
    CCP1CON = 0X05;//modo de captura sem divisão (borda de subida)
    CCP1IF = 0; //limpa flag de interrupção de captura
    CCP1IE = 1;//habilita modo de captura de pulsos*/
}

void inicializa_timer1() {
    TMR1IF = 0; //limpa flag de interrupção de timer
   // TMR1IE = 1; //habilita interrupção de estouro do timer
    TMR1IE = 0; //desabilita interrupção de estouro do timer
    T1CON = 0x81; //habilita leitura do timer 1 e o timer 1,sem prescaler
}


//////////////////////////////////////////////////////Rotina principal///////////////////////////////////////////////////////////////

void main(void) {
    TRISA = 0XFF;//como entrada
    TRISB = 0X08;//configura portB  B3 (ccp1) como entrada
    PORTB = 0;  // limpar as portas que estão configuradas como saidas
    inicializa_CCP();
    inicializa_timer1();
    inicializa_RS232(9600,1);//modo de alta velocidade
    imprime("controle remoto");
    PEIE = 1;//habilita interrupção de perifericos do pic
    GIE = 1; //GIE: Global Interrupt Enable bit
    for(;;)
    {
          if(largura_pulso > 0)//leu pulsos
                     {
                      valor_pulso = largura_pulso;
                      if(primeiro_pacote == 0)
                          {
                           primeiro_pacote = 1;//descarta pois virá com lixo
                          }
                      else
                      {
                      if(primeiro_pacote == 1)
                        {//tenta localizar o protocolo
                          primeiro_pacote = 2;
                             escreve('\n');//pula para proxima linha
                             escreve('\r');//coloca no inicio da linha
                           if((valor_pulso > 2900)&&(valor_pulso < 3200))
                            {
                               escreve('N');
                               bit_0 = 1200;
                               bit_1 = 1800;
                               start_stop=3000;
                            }
                           if(valor_pulso < 2900)
                            {
                               escreve('P');
                               bit_0 = 1800;
                               bit_1 = 2700;
                               start_stop=0;
                               if(valor_pulso > (bit_0 + range_bit))
                              {//bit 1
                                escreve('1');
                              }
                              else
                              {//bit0
                                 escreve('0');
                              }
                            }
                            if((valor_pulso > 8000)&&(valor_pulso < 10000))
                            {
                               escreve('S');
                               bit_0 = 1100;
                               bit_1 = 2250;
                               start_stop=9000;
                            }
                            if(valor_pulso > 10000)
                            {
                               escreve('L');
                               bit_0 = 1100;
                               bit_1 = 2250;
                               start_stop=13500;
                            }

                        }
                      else
                      {
                         if((valor_pulso > (start_stop - range_bit))&&(valor_pulso < (start_stop + range_bit)))
                              {//start bit
                                escreve('S');//pra indicar que recebeu um bit de inicio ou fim de pacote
                              }
                      if(valor_pulso < (bit_1 + range_bit))
                      {
                          if(valor_pulso > (bit_0 + range_bit))
                              {//bit 1
                                escreve('1');
                              }
                              else
                              {//bit0
                                 escreve('0');
                              }

                      }
                      }
                      }
                    largura_pulso=0;
                        timeout = 3000;//prepara contagem
                     }//fim do leu pulsos
     if(timeout>0)
     {
     timeout--;
     }
     if(timeout==1)
     {// tempo usado para resetar ou descartar pacotes com defeito
      primeiro_pacote = 0;
     }
    }//loop infinito

}
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Depois de montado os códigos vamos a simulação,na simulação o primeiro pacote dá um erro, mas logo em seguida tudo funciona normalmente.Veja a imagem da simulação e do esquemático no proteus :


O esquemático:
    
     Testando com um controle remoto e com o prototipo montado numa proto-o-board recebi os seguintes códigos do controle:

Padrão samsung, 33bits + start_stop_bit:
 
Power = 111000001110000001000000101111110
vol+  = 111000001110000011100000000111110
vol-  = 111000001110000011010000001011110
ch+   = 111000001110000001001000101101110
ch-   = 111000001110000000001000111101110

Padrão LG, 32bits + start_stop_bit:

Power = 01000001101111100010000111011110
vol+  = 01000001101111101000000101111110
vol-  = 01000001101111111000000001111110
ch+   = 01000001101111100000000111111110
ch-   = 01000001101111110000000011111110

padrão sony, repete 3 vezes um codigo de 11 bits + start_bit
com intervalos de 27ms 
         
Power = 10101001000
vol+  = 01001001000
vol-  = 11001001000
ch+   = 00001001000
ch-   = 10001001000

padrão philips envia 10 bits sem pulsos de inicio e fim

Power = 0100000101
vol+  = 0100001100
vol-  = 0000001101
ch+   = 0000011000
ch-   = 0100011001

Para pegar os dados eu montei na proto-o-board o esquema elétrico seguinte:



Em breve vou postar um artigo usado este projeto como base para acionar leds com diferentes controles, até a próxima!

Um comentário :

olá,digite aqui seu comentário!