Olá, continuando o projeto do decodificador de controle remoto que pode ser usado para acionar relês (neste projeto será acionado 4 leds), com pequenas alterações é possível acionar mais relês ou cargas, mantive a parte de comunicação via serial para o caso de vocês quererem visualizar o código recebido num pc, outro detalhe foi a adição de 4 chaves de toque para fazer a gravação dos códigos além de 5 leds sendo 4 para os código do controle e um para indicar que está recebendo dados do controle remoto, o código fonte segue abaixo:
/* * Decodificando controle remoto MPlab XC8 * * Compilador : MPlabXC8 * Microcontrolador: 16F648A * Autor: aguivone * Versão: 1 * Data : 23 de abril de 2015 */ #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 #define CH1 PORTBbits.RB4 #define CH2 PORTBbits.RB5 #define CH3 PORTBbits.RB6 #define CH4 PORTBbits.RB7 #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; char comando; long byte_cod_baixo = 0; long byte_cod_alto = 0; long CH1_byte_cod_baixo = 1; long CH1_byte_cod_alto = 1; long CH2_byte_cod_baixo = 1; long CH2_byte_cod_alto = 1; long CH3_byte_cod_baixo = 1; long CH3_byte_cod_alto = 1; long CH4_byte_cod_baixo = 1; long CH4_byte_cod_alto = 1; int taman_byte =0; int stopbit_reconhecido = 0; ///////////////////////////////////////////////////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 } void limpa_pacote() { comando =' '; byte_cod_baixo = 0; byte_cod_alto=0; taman_byte =0; } void rotina_tratamento(long byte_alto,long byte_baixo) { int reconhecer = 1; if(CH1 == 0) {//grava codigo do botão 1 CH1_byte_cod_alto = byte_alto; CH1_byte_cod_baixo = byte_baixo; imprime("\n\r CH1_gravado!"); reconhecer = 0; } if(CH2 == 0) {//grava codigo do botão 2 CH2_byte_cod_alto = byte_alto; CH2_byte_cod_baixo = byte_baixo; imprime("\n\r CH2_gravado!"); reconhecer = 0; } if(CH3 == 0) {//grava codigo do botão 3 CH3_byte_cod_alto = byte_alto; CH3_byte_cod_baixo = byte_baixo; imprime("\n\r CH3_gravado!"); reconhecer = 0; } if(CH4 == 0) {//grava codigo do botão 4 CH4_byte_cod_alto = byte_alto; CH4_byte_cod_baixo = byte_baixo; imprime("\n\r CH4_gravado!"); reconhecer = 0; } if(reconhecer == 1)//indica que é pra reconhecer o codigo { TRISB = 0X08;//configura os pinos dos botoes como saidas PORTB = 0XFF;//desliga saidas if((byte_alto == CH1_byte_cod_alto )&&(byte_baixo == CH1_byte_cod_baixo)) { imprime("\n\r CH1_ok"); CH1 = 0;//liga pino } if((byte_alto == CH2_byte_cod_alto )&&(byte_baixo == CH2_byte_cod_baixo)) { imprime("\n\r CH2_ok"); CH2 = 0;//liga pino } if((byte_alto == CH3_byte_cod_alto )&&(byte_baixo == CH3_byte_cod_baixo)) { imprime("\n\r CH3_ok"); CH3 = 0;//liga pino } if((byte_alto == CH4_byte_cod_alto )&&(byte_baixo == CH4_byte_cod_baixo)) { imprime("\n\r CH4_ok"); CH4 =0;//liga pino } __delay_ms(500);//espera 0,5s PORTB = 0XF0;//desliga saidas TRISB = 0XF8;//os pinos voltam a ser entradas } } //////////////////////////////////////////////////////Rotina principal/////////////////////////////////////////////////////////////// void main(void) { TRISA = 0XE7;//todos são entrada exceto as saidas do comparador RA3 RA4 TRISB = 0XF8;//configura portB B3 (ccp1) e de rb4 a rb7 como entrada PORTB = 0; // limpar as portas que estão configuradas como saidas CMCON = 0X06;//habilita somente um comparador interno inicializa_CCP(); inicializa_timer1(); inicializa_RS232(9600,1);//modo de alta velocidade imprime("controle remoto2"); PEIE = 1;//habilita interrupção de perifericos do pic GIE = 1; //GIE: Global Interrupt Enable bit limpa_pacote(); for(;;) { if(largura_pulso > 0)//leu pulsos { valor_pulso = largura_pulso; if(primeiro_pacote == 0) { primeiro_pacote = 1;//descarta pois virá com lixo limpa_pacote(); } 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)) {//sony escreve('G'); comando ='G'; bit_0 = 1200; bit_1 = 1800; start_stop=3000; } if(valor_pulso < 2900) {//philips escreve('P'); comando ='P'; bit_0 = 1800; bit_1 = 2700; start_stop=0; if(valor_pulso > (bit_0 + range_bit)) {//bit 1 escreve('1'); byte_cod_baixo = 1; taman_byte =1; } else {//bit0 escreve('0'); taman_byte =1; } } if((valor_pulso > 8000)&&(valor_pulso < 10000)) {//sansung escreve('S'); comando ='S'; bit_0 = 1100; bit_1 = 2250; start_stop=9000; } if(valor_pulso > 10000) {//lg escreve('L'); comando ='L'; bit_0 = 1100; bit_1 = 2250; start_stop=13500; } LED_STATUS = 1; } else { if((valor_pulso > (start_stop - range_bit))&&(valor_pulso < (start_stop + range_bit))) {//pulso de fim de pacote escreve('F');//pra indicar que recebeu um bit de inicio ou fim de pacote if((comando == 'S')||(comando == 'L')||(comando == 'P')||(comando == 'G')) {//verifica se o pacote é valido para os protocolos, pode ser que outras marcas coicidam e funcione rotina_tratamento(byte_cod_alto,byte_cod_baixo); } stopbit_reconhecido = 1; // no caso do protocolo ca sony aqui pode se fazer a logica e separa os 3 codigos que são //os mesmos } if(valor_pulso < (bit_1 + range_bit)) { if(valor_pulso > (bit_0 + range_bit)) {//bit 1 escreve('1'); if(taman_byte<32) { long valor=1; byte_cod_baixo = byte_cod_baixo + (valor<<taman_byte); } else { long valor=1,temp_byte; temp_byte = taman_byte-32; byte_cod_alto = byte_cod_alto + (valor<<temp_byte); } taman_byte++; } else {//bit0 escreve('0'); taman_byte++; } } } } largura_pulso=0; timeout = 3000;//prepara contagem }//fim do leu pulsos if(timeout>0) { timeout--; } if(timeout==1) {// tempo de estouro por esperar o pacote escreve('T');//timeout if(stopbit_reconhecido == 0) { if((comando == 'S')||(comando == 'L')||(comando == 'P')||(comando == 'G')) {//verifica se o pacote é valido para os protocolos, pode ser que outras marcas coicidam e funcione rotina_tratamento(byte_cod_alto,byte_cod_baixo); } } else { stopbit_reconhecido = 0; } LED_STATUS = 0; comando =' ';//limpa comando taman_byte = 0; primeiro_pacote = 0; } }//loop infinito }
Como eu tive que inverter o sinal de entrada pois usei um modulo de recepção infravermelho da sharp, neste caso o sinal ficou o oposto do que eu havia detectado antes,como me sobraram poucos pinos do microcontrolador tive que usar o recurso de o mesmo pino funcionar como entrada e saída ao mesmo tempo.Na simulação o circuito ficou assim a porta NOT é para simular o modulo receptor de IR
Site com um projeto legal usando esse tipo de modulo : http://zorktronics.blogspot.com.br/2011/06/medindo-velocidade-angular-sem-um.html ,nestes links vendem uns modelos destes :
Para demonstração do algoritmo funcionando, veja o vídeo a seguir:
Nenhum comentário :
Postar um comentário
olá,digite aqui seu comentário!