Página 1 de 1

Lendo Codigo RC5 IR

MensagemEnviado: 18 Abr 2011 10:52
por jandom
Senhores, estou precisando desenvolver um leitor de codigos RC5 baseado em PIC. Achei este programa na net, mas ate o presente momento ainda não consegui fazer funfar!

// Author: Aurelian Nichita nicksubzero@yahoo.com
// Based on: http://www.xs4all.nl/~sbp/knowledge/ir/sirc.htm
#include <18F452.h>

#fuses XT,NOWDT,PUT,NOPROTECT,BROWNOUT,NOLVP

#use delay(clock=4000000)

#include "MOD_lcd.c"

#define LED1 pin_C0
#define LED2 pin_C2

#define TIMER0_CONFIG RTCC_INTERNAL | RTCC_DIV_1

#define ONE_MIN 1675

#define ONE_MAX 1925

#define ZERO_MIN 1075

#define ZERO_MAX 1325

int16 irframes[13];

int8 ircount = 0;

int1 irdone = FALSE;

#int_ext

void ext_isr()
{

if (irdone) return;

irframes[ircount] = get_timer0();

if (ircount >= 13)

irdone = TRUE;

ircount++;

set_timer0(0);



}

int1 decode_ir(int8 &addr, int8 &cmd)
{

int8 i;

int8 mask;

int8 bits[13];

addr = 0;

cmd = 0;

for (i=1; i<=12; i++)
{

if ((ONE_MIN <= irframes[i]) && (irframes[i] <= ONE_MAX))

bits[i] = 0x01;

else

if ((ZERO_MIN <= irframes[i]) && (irframes[i] <= ZERO_MAX))

bits[i] = 0x00;

else // Error

return FALSE;

}

mask = 0x01;

for (i=1; i<=7; i++)
{

if (bits[i])

cmd = cmd | mask;

mask <<= 1;

}

mask = 0x01;

for (i=8; i<=12; i++)
{

if (bits[i])

addr = addr | mask;

mask <<= 1;

}

return TRUE;

}

void start_ir()
{


memset(irframes, 0X00, sizeof(irframes));

ircount = 0;

irdone = FALSE;

set_timer0(0);

}

void main()
{

int8 addr, cmd;

int1 ok;

addr=0;cmd=0;

setup_timer_0(TIMER0_CONFIG);

ext_int_edge(L_TO_H);

enable_interrupts(INT_EXT);

enable_interrupts(GLOBAL);

lcd_ini();

delay_ms(133);

start_ir();

while(1)
{

if (irdone)
{

ok = decode_ir(addr, cmd);

lcd_pos_xy(1, 2);
printf (lcd_escreve,"\fCmd %3u\ nAddr %3u", cmd, addr);

if (!ok)
{

lcd_pos_xy(1, 2);
printf (lcd_escreve,"ERROR");

output_high(led1);
delay_ms(200);
output_low(led1);
}
if (ok)
{
output_high(led1);
delay_ms(200);
output_low(led1);
}

start_ir();

}

}

}

O programa esta lendo o sinal em RB0, ja olhei no Scope e o sinal esta normal, ao ler o codigo nao exibe os dados e exibe no lcd ^erro^ toda vez que le um codigo.
Agradeco toda a ajuda possivel!

MensagemEnviado: 19 Abr 2011 14:26
por jandom
//////////////////////////////////////////////////////////////////////
//
// File: 16F88_Infrared_decoder.c
//
// Author: J F Main.
//
// Description:
//
// Infrared decoder using RB0 interrupt pin.
//
// Outputs decoded data to RS232 as a data stream
// so it can decode any rs232 signal using suitable
// software at the PC.
//
// Compiler : mikroC, mikroElektronika C compiler
// for Microchip PIC microcontrollers
// Version: 5.0.0.3
//
// Note Testing:
//
// Tested on 16F88
//
// Requirements:
//
// Photodiode 5V receiver module with built in demodulator.
// - one of those 3 pin IR decoders.
//
// 8MHz (intenal oscillator) - for accurate baud rate.
//
// Target : 16F88
//
// Notes :
//
// Version:
// 1.00 01/Mar/06 - Initial release.
//
// Copyright : Copyright © John Main 2006
// http://www.best-microcontroller-projects.com
// Free for non commercial use as long as this entire copyright notice
// is included in source code and any other documentation.
//
//////////////////////////////////////////////////////////////////////
#include "bit.h"

//////////////////////////////////////////////////////////////////////
// macros / defines - comment out to remove the definition.
//#define DEBUG_UIR

//////////////////////////////////////////////////////////////////////
// File scope variables:

//////////////////////////////////////////////////////////////////////
void init(void)
{

OSCCON = 0x70; // b6..4 = 110 = 4MHz 111=8MHz

ANSEL = 0x01; // (0) ADC pins to digital I/O - RA0 enabled as input
}

//////////////////////////////////////////////////////////////////////
void init_ports(void) {

PORTA = 0;
TRISA = 0x01; // (0)=o/p (1)-I/P RA5-b5

PORTB = 0;
TRISB = 0x01; // 0=o/p Receive on RB0.
}

//////////////////////////////////////////////////////////////////////
void enable_interrupts(void) {

// RB0
OPTION_REG = (1<<INTEDG); // RB0 interrupt rising edge.

// RB0
INTCON &= ~(1<<INTF); // Clear RB0 interrupt flag

// Global interrupt enable and RB0 INT - rising edge
INTCON |= (1<<GIE) | (1<<INTE) ; // enable global & peripheral
}

//////////////////////////////////////////////////////////////////////
void disable_interrupts(void) {
INTCON &= ~(1<<GIE); // disable global
}

//////////////////////////////////////////////////////////////////////
void sample_bits(void) {

unsigned short val,valo=1; // Current,old value of decoded IRu
unsigned int c=0;

// Measure period from each edge
// Note input value is inverted so invert back to normal
// every time the port is read.
valo = !testBit(PORTB,0); // initalise old value - ignores 1st period.

while (1) {

delay_us(40); // time the loop.

val = !testBit(PORTB,0); // Get current input (inverted as above).

// Detect change and report.
if (val!=valo) { // Found a change in the input.
USART_Write(c);
c = 0; // reset period counter.
valo = val; // store latest input value.

} else c++; // NO change

// Exit if input is inactive and have a gap
if (val==0 && c++>=200) break; // 200 x 50us (approx loop time) = 10ms

} // while

delay_ms(100);

return;
}

//////////////////////////////////////////////////////////////////////
void main() {

init_ports();
init();

USART_Init(57600);
// Essential initialisation for accurate baud at 8MHz
TXSTA |= (1<<BRGH); // Set BRGH = 1 - re-initilisation for accurate baud.
SPBRG = 8; // Set SPBRG = 8

delay_ms(300);

enable_interrupts();

#ifndef DEBUG_UIR
// Non debug code - normally executed
while (1) { ; } // wait for interrupt - interrupt calls sample_bits
#endif

#ifdef DEBUG_UIR
disable_interrupts(); // don't want any more!
sample_bits();
#endif
}

////////////////////////////////////////////////////////////////////////
void interrupt(void) {

#ifndef DEBUG_UIR
if (INTCON & (1<<INTF) ) {
INTCON &= ~(1<<INTF); // Clear RB0 interrupt flag

sample_bits();

}
#endif // DEBUG_UIR

//Re-enable - note GIE set at exit from interrupt routine.
INTCON |= (1<<INTE);
}

Aqui vai outro exemplo para Mikro C usando PIC 16f88, mas ao compila-lo, da varios erros.
Alguem ja testou o outro para CCS, ate agora nao consegui nada!

MensagemEnviado: 19 Abr 2011 15:48
por tcpipchip
Fiz em BASIC (PICBASIC PRO MELABS)

Funciona bem!

Código: Selecionar todos
' BNU 12-11-1998
' Biblioteca usado pelo receptor infravermelho
' Include "ModeDefs.bas"

' Oscilador utilizado
DEFINE OSC              20

' Configurações para a porta serial
DEFINE HSER_RCSTA       90h   'Configura RX
DEFINE HSER_TXSTA       24h   'Configura TX
DEFINE HSER_BAUD        9600  'Baud Rate
DEFINE HSER_CLROERR           'Limpa bit OERR automaticamente (Overrun)

'Declaração de variáveis usadas na comunicação infravermelho RC5
Vet_Bits    var bit[194]  'Amostras de níveis do pacote RC5
Vet_DupBits var bit[28]   'Duplas de bits do pacote RC5
Pac_RC5      var   Word     'Pacote RC5 final de 12 bits
indRC5      var byte      'Auxiliar na construção de Vet_Bits   
indRC52     var byte      'Auxiliar na construção de Vet_DupBits
qtniveis    var byte      'Auxiliar da decodificação de Vet_Bits
IR_Com      var byte     'Código do botão pressionado
IR_Sis      var   byte     'Código do sistema atual
IR_Ctr      var byte      'Código do controle
IR_Sensor   var   PORTB.0     'Entrada física do sinal IR RC5
ind_pauseir var word      'Auxiliar na temporização de recepção IR

'Rotina de tratamento da recepção IR RC5. Retorna os dados de controle,
'sistema e comando. Se houve erro retorna 255 em IR_Ctr
Atualiza_IR:
       if (IR_Sensor = 1) then return
        for indRC5 = 0 to 193         'Neste looping recolhe amostras
         Vet_Bits[indRC5] = IR_Sensor 'do pacote RC5 e grava no array
         PauseUs 110                  'Vet_Bits para ser decodificado.
        next indRC5                   'Amostras em tempos de 110us
                                               
        indRC52 = 0                   'Inicialização de variáveis 
        qtniveis = 1                  'Define seqüências de 00 e 11 
        for indRC5 = 0 to 27          'Limpa Vet_Dups
         Vet_DupBits[indRC5] = 0
        next indRC5
        Vet_DupBits[indRC52] = Vet_Bits[0] 'Decodificação de Vet_Bits
        for indRC5 = 1 to 193      'Varre Vet_Bits por intervalos de 0 e 1
         if Vet_Bits[indRC5]=Vet_DupBits[indRC52] then
          qtniveis = qtniveis + 1
         else
          select  case (qtniveis/5)    'Identifica seqüências de 00 ou 11   
           case 1 :             'se 1 então período de 888us de 1 ou 0
            indRC52 = indRC52 + 1
            Vet_DupBits[indRC52] = Vet_Bits[indRC5]
            qtniveis = 1
           case 2, 3 : 'se 2 ou 3 período então período de 1,67ms de 11 ou 00
            indRC52 = indRC52 + 1     
            Vet_DupBits[indRC52] = Vet_Bits[indRC5-1]
            indRC52 = indRC52 + 1
            Vet_DupBits[indRC52] = Vet_Bits[indRC5]
            qtniveis = 1
           case else
            return
          end select   
         endif        'Agora Vet_DupBits possui as duplas de bits que
        next indRC5   'irão constituir o pacote final RC5
       
       indRC52 = 0    'Inicio da criação do pacote RC5.Se erro, então abortar
       if not(not Vet_DupBits[indRC52] and Vet_DupBits[indRC52+1]) then return
       For indRC5 = 11 to 0 step -1
        indRC52 = indRC52 + 2
        'Vare Vet_DupBits por duplas de bits e associa a 1 ou 0 para
        'carregar no pacote. 00=0 01=1 10=0 11=1
        if (not Vet_DupBits[indRC52] and not Vet_DupBits[indRC52+1]) then Pac_RC5.0[indRC5] = 0
        if (not Vet_DupBits[indRC52] and Vet_DupBits[indRC52+1]) then Pac_RC5.0[indRC5] = 1
        if (Vet_DupBits[indRC52] and not Vet_DupBits[indRC52+1]) then Pac_RC5.0[indRC5] = 0
        if (Vet_DupBits[indRC52] and Vet_DupBits[indRC52+1]) then Pac_RC5.0[indRC5] = 1
      Next indRC5
      'Agora  o pacote RC5 está formando com 12 bits. 
       
'Desmembra pacote. 6 bits para comando, 5 para sistema e 1 para controle
   IR_Com=Pac_RC5 & %00111111
    IR_Sis=(Pac_RC5 >>6) & %00011111
    IR_Ctr=(Pac_RC5 >>11)& %00000001
   
'Executa o comando recepcionado
    if (Ir_ctr) then
     if (Ir_sis = 0) then
      select case Ir_com
       case 16: hserout["l"] 'Volume +
       case 17: hserout["o"] 'Volume -
      end select                   
     endif
     if Ir_sis = 5 then
      select case Ir_com
       case 12: 'Liga/Desliga PC
       case 50: hserout["w"] 'Previous
       case 52: hserout["f"] 'Next
       case 53: hserout["y"] 'Play
       case 41: hserout["e"] 'Pause
       case 54: hserout["p"] 'Stop
      end select
     endif
    endif
    IR_Ctr = 255
    ind_pauseir = 0
    for ind_pauseir = 1 to 4000
     pauseus 100
    next ind_pauseir
    return

'Inicialização geral de variáveis
inits:
        clear
        TRISB = 1

'Inicio do programa principal
loop:   
       
        gosub atualiza_ir
       
        goto loop
end

MensagemEnviado: 19 Abr 2011 17:30
por jandom
Obrigado Miguel!

Tenho saudades de usar Basic, qdo programava os velhos TRS80. TKs e Apples da vida(bem passada!).
Mas a ideia com esse programa, e ler um codigo que estao sendo enviado pelo transmissor e que tipo de codigo e: RC5/6, SIRC ou outro padrao. Trabalho com equipamentos que testam Ar condicionado, e volta e meia, chega uns chineses que nao sabemos que codigo usam.
Modifiquei o programa para CCS, ele esta lendo os Frames, mas seus valores estao mudando, toda vez que aperto o mesmo botao! sera que a frequencia do PIC tem alguma coisa a ver?

MensagemEnviado: 20 Abr 2011 13:52
por diogo_18sp
da uma olhada neste site fala sobre o protocolo rc5



http://eletronicaoob.blogspot.com/2010/ ... emoto.html

MensagemEnviado: 25 Abr 2011 11:37
por jandom
Olhem este site! achei interessante! da para pesquisar varios tipos de codigos de IR.

http://www.compendiumarcana.com/irwidget/

Mas continuo testando outros programas para PIC em C CCS. Alguem testou
o codigo do inicio?