|
|
View previous topic :: View next topic |
Author |
Message |
VanHauser
Joined: 03 Oct 2005 Posts: 88 Location: Ploiesti, Romania
|
Infrared receiver for SONY remotes |
Posted: Sun Mar 05, 2006 6:09 am |
|
|
I've seen some requests for infrared receivers on this forum, so here is my code. It works flawlessly with a remote from a SONY KV-21T3K television and cheap cloned remotes. The range is very good.
Code: | /******************************************************************/
/* */
/* Infrared Receiver for SONY 12-bit protocol (SIRC) */
/* */
/* Compiler: CCS PCH 3.242 */
/* Processor: PIC18F452 @ 32MHz */
/* IR Sensor: TSOP1738 */
/* Circuit: Standard from TSOP1738 Datasheet, OUT to RB0 */
/* Requires LCD on port D, LED+resistor on RC2 */
/* LED blinks when a command is recognised. */
/* Author: Aurelian Nichita aurelian.info@gmail.com */
/* Based on: http://www.xs4all.nl/~sbp/knowledge/ir/sirc.htm */
/* */
/******************************************************************/
#define CLKSPEED 32000000
#include <18F452.h>
#fuses H4,NOPROTECT,NOOSCSEN,BROWNOUT,BORV45,NOWDT,WDT128,PUT,NOSTVREN,NODEBUG,NOLVP,WRT,NOCPB,WRTB,WRTC,NOCPD,NOWRTD,NOEBTR,NOEBTRB
#use delay(clock=CLKSPEED)
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)
#use fast_io(E)
#ignore_warnings none
#zero_ram
/* TIMER0 configuration */
#define TIMER0_CONFIG RTCC_INTERNAL | RTCC_DIV_1
/* Interrupt rate: */
/* 4/32000000*65536*1 = 8.192 ms */
/* */
/* Start: 3.0 ms (ignored) */
/* "1": 1.8 ms (14400) */
/* "0": 1.2 ms (9600) */
#define ONE_MIN 13400
#define ONE_MAX 15400
#define ZERO_MIN 8600
#define ZERO_MAX 10600
#include "lcd.c"
/* irframes[0] (start) will be garbage, ignore it... */
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;
set_timer0(0);
enable_interrupts(INT_TIMER0);
}
#int_timer0
void timer0_isr() {
disable_interrupts(INT_TIMER0);
}
#separate
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;
}
void main() {
int8 addr, cmd;
int1 ok;
delay_ms(100);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
set_tris_a(0b11111111);
set_tris_b(0b11111111);
set_tris_c(0b11111011); // PIN_C2 used for the LED
set_tris_d(0b00000000); // LCD
set_tris_e(0b11111111);
setup_spi(FALSE);
setup_wdt(WDT_OFF);
lcd_init();
output_bit(PIN_C2, 0);
delay_ms(100);
lcd_putc("\fWaiting...");
setup_timer_0(TIMER0_CONFIG);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED, 255, 1);
setup_timer_3(T3_DISABLED | T3_DIV_BY_1);
ext_int_edge(0, L_TO_H);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
start_ir();
#ignore_warnings 203
while(TRUE) {
#ignore_warnings NONE
if (irdone) {
ok = decode_ir(addr, cmd);
printf(lcd_putc, "\fCmd %3u\nAddr %3u", cmd, addr);
if (!ok)
lcd_putc(" ERROR");
else
output_bit(PIN_C2, 1);
delay_ms(50);
output_bit(PIN_C2, 0);
start_ir();
}
}
} |
Last edited by VanHauser on Wed Aug 24, 2016 4:24 am; edited 1 time in total |
|
|
HOHOHAHA
Joined: 13 Apr 2007 Posts: 24
|
|
Posted: Tue Jan 01, 2008 11:11 am |
|
|
great work ... |
|
|
Lucidan
Joined: 05 Feb 2008 Posts: 7
|
Thanks! |
Posted: Fri Feb 08, 2008 12:00 pm |
|
|
Thanks! I've been looking for something like this for a while....I'll let you know whether it works with my Sony remotes (VCR, CD players, Amplifier, minidisc). Or is it supposed to work with ANY Sony remote? |
|
|
HTAluvBeBeo
Joined: 23 Feb 2008 Posts: 35
|
|
Posted: Thu Jul 03, 2008 9:22 pm |
|
|
I converted this code for 16F877A and send data to rs232
but there is something wrong.
Plz help me to check the code, sory if it was too long.
Code: |
#include <16F877A.h>
#include <def_877a.h>
#FUSES NOWDT, HS, NOPUT, NOPROTECT, NODEBUG, BROWNOUT, NOLVP, NOCPD, NOWRT
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
/* TIMER0 configuration */
#define TIMER1_CONFIG T1_INTERNAL | T1_DIV_BY_1
/* Interrupt rate: */
/* 4/20000000*65536*1 = 13.1 ms */
/* */
/* Start: 3.0 ms (ignored) */
/* "1": 1.8 ms (9000) */
/* "0": 1.2 ms (6000) */
#define ONE_MIN 8000
#define ONE_MAX 10000
#define ZERO_MIN 5000
#define ZERO_MAX 7000
//#include "lcd.c"
/* irframes[0] (start) will be garbage, ignore it... */
int16 irframes[13];
int8 ircount = 0;
int1 irdone = FALSE;
#int_ext
void ext_isr() {output_bit(PIN_A5, 0);
if (irdone) return;
irframes[ircount++] = get_timer0();
if (ircount >= 13)
irdone = TRUE;
set_timer0(0);
enable_interrupts(INT_TIMER1);
}
#int_timer1
void timer_isr() {
disable_interrupts(INT_TIMER1);
}
#separate
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;
}
void main() {
int8 addr, cmd;
int1 ok;
delay_ms(100);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
set_tris_a(0x00);
set_tris_b(0b11111111);
set_tris_c(0b11111011); // PIN_C2 used for the LED
set_tris_d(0b00000000); // LCD
set_tris_e(0b11111111);
setup_spi(FALSE);
output_bit(PIN_A5, 1);
//lcd_init();
//output_bit(PIN_C2, 0);
delay_ms(100);
//lcd_putc("\fWaiting...");
setup_timer_1(TIMER1_CONFIG);
setup_timer_2(T2_DISABLED, 255, 1);
ext_int_edge(0, L_TO_H);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
delay_ms(100);
start_ir();
while(TRUE) {
if (irdone) {
ok = decode_ir(addr, cmd);
printf("%u", cmd);
printf("%u", addr);
if (!ok){
printf("1111");}
else
output_bit(PIN_A5, 0);
delay_ms(50);
output_bit(PIN_A5, 1);
start_ir();
}
}
} |
|
|
|
HTAluvBeBeo
Joined: 23 Feb 2008 Posts: 35
|
|
Posted: Thu Jul 03, 2008 9:34 pm |
|
|
I think the problem may be in here
my code
Code: | #include <16F877A.h>
#include <def_877a.h>
#FUSES NOWDT, HS, NOPUT, NOPROTECT, NODEBUG, BROWNOUT, NOLVP, NOCPD, NOWRT
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
/* TIMER0 configuration */
#define TIMER1_CONFIG T1_INTERNAL | T1_DIV_BY_1
/* Interrupt rate: */
/* 4/20000000*65536*1 = 13.1 ms */
/* */
/* Start: 3.0 ms (ignored) */
/* "1": 1.8 ms (9000) */
/* "0": 1.2 ms (6000) */
#define ONE_MIN 8000
#define ONE_MAX 10000
#define ZERO_MIN 5000
#define ZERO_MAX 7000 |
maybe I am wrong when calculate some value with timer ???
I calculated based on value of "1" : 1.8ms and "0" : 1.2 ms ???
original with 18F
Code: | #define CLKSPEED 32000000
#include <18F452.h>
#fuses H4,NOPROTECT,NOOSCSEN,BROWNOUT,BORV45,NOWDT,WDT128,PUT,NOSTVREN,NODEBUG,NOLVP,WRT,NOCPB,WRTB,WRTC,NOCPD,NOWRTD,NOEBTR,NOEBTRB
#use delay(clock=CLKSPEED)
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)
#use fast_io(E)
#ignore_warnings none
#zero_ram
/* TIMER0 configuration */
#define TIMER0_CONFIG RTCC_INTERNAL | RTCC_DIV_1
/* Interrupt rate: */
/* 4/32000000*65536*1 = 8.192 ms */
/* */
/* Start: 3.0 ms (ignored) */
/* "1": 1.8 ms (14400) */
/* "0": 1.2 ms (9600) */
#define ONE_MIN 13400
#define ONE_MAX 15400
#define ZERO_MIN 8600
#define ZERO_MAX 10600 |
|
|
|
Pan0ramix
Joined: 06 Apr 2008 Posts: 2
|
|
Posted: Wed Jul 16, 2008 6:27 pm |
|
|
if i try to change the clock to 48mhz i posted my calculations on the code below.
my pic is the 18f2550.
why does he use the fast_io(a) to e? he doesnt use them all i think?
my pic only has 3 ports from what i can see and then i need to adapt the SET_TRIS to my 3 ports im i wrong?
he got this:
Code: |
setup_spi(FALSE); -> but i use SPI on my LCD, will this be a problem?
setup_wdt(WDT_OFF);
|
I posted my code below where i changed the lcd settings to my lcd.
to PCM_Programmer thank you for your answer to my previous post but i couldnt adapt that stuff to my pic so im trying this one (newbie :( )
thanks a lot guys
here is my code at the moment:
Code: |
#define CLKSPEED 48000000
#include <18F2550.h>
#include <string.h>
#fuses NOPROTECT,BROWNOUT,NOWDT,WDT128,PUT,NOSTVREN,NODEBUG,NOLVP,WRT,NOCPB,WRTB,WRTC,NOCPD,NOWRTD,NOEBTR,NOEBTRB,HSPLL,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=CLKSPEED)
#define RS_LCD PIN_A0
#define CSB_LCD PIN_A1
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
//#use fast_io(D)
#use fast_io(E)
#ignore_warnings none
#zero_ram
/* TIMER0 configuration */
#define TIMER0_CONFIG RTCC_INTERNAL | RTCC_DIV_1
/* Interrupt rate: */
/* 4/48000000*65536*1 = 5.461 ms */
/* */
/* Start: 3.0 ms (ignored) */
/* "1": 1.8 ms (21601) */
/* "0": 1.2 ms (14400) */
#define ONE_MIN 20601
#define ONE_MAX 22601
#define ZERO_MIN 13400
#define ZERO_MAX 15400
char string[16];
void lcd_write_byte(unsigned char data,int1 rs){
setup_spi(SPI_MASTER|SPI_H_TO_L|SPI_XMIT_L_TO_H|SPI_CLK_DIV_64);
output_low(CSB_LCD);
if(rs==1)
output_high(RS_LCD); /* envia data */
else
output_low(RS_LCD); /*envia comando*/
delay_us(50);
spi_write(data);
delay_us(10);
output_high(CSB_LCD);
}
void lcd_clear(void){
lcd_write_byte(0x01,0);
delay_ms(1);
}
void lcd_linha(int8 line){
if(line==1) //linha 1
lcd_write_byte(0x80,0);
if(line==2) //linha 2
lcd_write_byte(0xC0,0);
}
/*programa para escrever uma string*/
void lcd_string(void){
int i;
for(i=0;;i++)
if(string[i]!='\0')
lcd_write_byte(string[i],1);
else
return;
}
void lcd_setup(void){
LCD_write_byte(0x39,0); // Function set; 8 bit Datenlänge, 2 Zeilen, Instruction table 1
delay_us(30); // mehr als 26,3µs warten
LCD_write_byte(0x1C,0); // Bias Set; BS 1/5; 2 zeiliges Display /1d
delay_us(30); // mehr als 26,3µs warten
LCD_write_byte(0x52,0); // Kontrast C3, C2, C1 setzen /7c
delay_ms(200); // mehr als 200 ms warten
LCD_write_byte(0x69,0); // Booster aus; Kontrast C5, C4 setzen /50
delay_us(30); // mehr als 26,3µs warten
LCD_write_byte(0x74,0); // Spannungsfolger und Verstärkung setzen /6c
delay_ms(200); // mehr als 200ms warten !!!
LCD_write_byte(0x0C,0); // Display EIN, Cursor EIN, Cursor BLINKEN /0f
delay_us(30); // mehr als 26,3µs warten
LCD_write_byte(0x01,0); // Display löschen, Cursor home
delay_ms(200); // mehr als 200ms warten !!!
LCD_write_byte(0x06,0); // Cursor auto increment
delay_us(30); // mehr als 26,3µs warten
}
/* irframes[0] (start) will be garbage, ignore it... */
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;
set_timer0(0);
enable_interrupts(INT_TIMER0);
}
#int_timer0
void timer0_isr() {
disable_interrupts(INT_TIMER0);
}
#separate
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;
}
void main() {
int8 addr, cmd;
int1 ok;
delay_ms(100);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
set_tris_a(0b11111111);
set_tris_b(0b11111111);
set_tris_c(0b11111011); // PIN_C2 used for the LED
//set_tris_d(0b00000000); // LCD
set_tris_e(0b11111111);
setup_spi(FALSE);
setup_wdt(WDT_OFF);
lcd_setup();
output_bit(PIN_C2, 0);
delay_ms(100);
lcd_linha(1);
lcd_clear();
sprintf(string,"\fWaiting...");
setup_timer_0(TIMER0_CONFIG);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED, 255, 1);
setup_timer_3(T3_DISABLED | T3_DIV_BY_1);
ext_int_edge(0, L_TO_H);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
start_ir();
#ignore_warnings 203
while(TRUE) {
#ignore_warnings NONE
if (irdone) {
ok = decode_ir(addr, cmd);
lcd_linha(1);
lcd_clear();
sprintf(string, "\fCmd %3u\nAddr %3u", cmd, addr);
if (!ok){
lcd_linha(1);
lcd_clear();
sprintf(string, " ERROR");}
else
output_bit(PIN_C2, 1);
delay_ms(50);
output_bit(PIN_C2, 0);
start_ir();
}
}
} |
|
|
|
Rohit de Sa
Joined: 09 Nov 2007 Posts: 282 Location: India
|
SIRC modified |
Posted: Fri Aug 15, 2008 9:15 am |
|
|
Hey all, just tried out the code in the first post of this discussion. It's good for a start, but I had my share of problems with it. One of the things I did was to get it to work with a 12F675. Another problem I had was that the TSOP is an active low device; so I dont really think that configuring the edge triggered interrupt as L_to_H would work properly. I've modified it suitably in my code. But in doing so (ie making it trigger as H_to_L) I had to make the array irframes with 14 int16's. However, I managed to reduce bits[13] from an int8 to a more compact int1.
Hardware: TSOP1738 on GP2; LEDs on GP4 and GP5; internal osc.
It works perfectly (or so I think) with a Sony RM952 remote. I suppose it'll work with most other Sony remotes. I used the PICKit2 Logic Analyser software to verify IR codes. Man! I love Microchip!...and CCS :-)
Two issues:
-I had to add a reset_cpu() statement (in bold below) in the while loop of the main function. This was because the PIC seemed to 'get out of sych' with the IR after a while.It would receive the first few (about 50) codes really well, and then it would 'lose' IR bits. Don't know why.
-Second problem:
I had to comment out the memset statement in start_ir(). When compiled memset kept putting a CLRF GPIO into the assembly code. Why is this happening? Ideas? Suggestions? (CCS compiler v4.057)
Please excuse the undocumented code....didnt really have time...will add documentation shortly.
(code edited...next post please :-) ) |
|
|
Rohit de Sa
Joined: 09 Nov 2007 Posts: 282 Location: India
|
|
Posted: Sun Aug 17, 2008 9:29 am |
|
|
Hey all, below is documented code. Hope the brief explanations help.
Cheers,
Rohit
Code: |
// This is code for an IR remote control decoder
// using the 12 bit SIRC protocol. Based on code
// by Aurelian Nichita.
// Hardware - TSOP1738 to GP2 of 12F675. Two LEDs
// on GP4 and GP5 as indicators.
// Sample signal at TSOP data output (taken using
// PICKit2 as a logic analyzer):
//
// ֿֿֿֿֿֿ\________/ֿֿ\__/ֿֿ\__/ֿֿ\__/ֿֿ\__/ֿֿ\__/ֿֿ\__/ֿֿ\__/ֿֿ\____/ֿֿ\__/ֿֿ\__/ֿֿ\__/ֿֿ\__/ֿֿֿֿֿ
// (idle)| (start) | bit0| bit0| bit0|bit0| bit0| bit0| bit0| bit1 | bit0| bit0| bit0|bit0|(idle)
//
// example for remote button "1"
//
// TSOP data is inverted; it idles high.
// [ֿֿ\_ : negative going edge; _/ֿֿ : positive going edge]
//
// Rohit de Sa
// 15Aug08
// v1.0
#include <12f675.h>
#fuses INTRC_IO,NOWDT,NOCPD,NOPROTECT,PUT,NOMCLR,NOBROWNOUT
#use delay(clock=4000000)
#use fast_io(a)
#zero_ram
#define one_min 1450 //no of counts to safely detect bit1
#define one_max 2200 //optimal @4 MHz is 1800
#define zero_min 600 //no of counts to safely detect bit0
#define zero_max 1440 //optimal @4 MHz is 1200
int16 irframes[14]; //holds incoming IR data
int8 ircount =0; //counts no if bits received
int1 irdone=false; //flag bit
#int_timer1 //(is this isr necessary? I dont really know)
void timer1_isr()
{
disable_interrupts(int_timer1);
}
#int_ext //IR bits detected by edge triggering
void ext_isr()
{
if(irdone) return;
irframes[ircount++]=get_timer1();
if(ircount>=13) //if 13 triggers(ie 12 bits+start) found
irdone=true; //set "done" flag
set_timer1(0); //restart timer for new bit
enable_interrupts(int_timer1); //(is this necessary? I dont really know)
}
int1 decode_ir(int8 &addr,int8 &cmd) //IR decoding function
{
int8 i;
int8 mask;
int1 bits[12];
addr=0;
cmd=0;
irframes[13]=1200; //last bit is always zero
for(i=2;i<=13;i++)
{
if((one_min<=irframes[i])&&(irframes[i]<=one_max))
bits[i-2]=0x01; //if the sampled signal lies within limits
else //set to 1
if((zero_min<=irframes[i])&&(irframes[i]<=zero_max))
bits[i-2]=0x00; //if the sampled signal lies within limits
else //set to 0
return false; //otherwise clear flag
}
mask=0x01; //format command
for (i=0;i<=6;i++)
{
if (bits[i])
cmd=cmd|mask;
mask<<=1;
}
mask=0x01; //format address
for (i=7;i<=11;i++)
{
if(bits[i])
addr=addr|mask;
mask<<=1;
}
return true; //set flag
}
void start_ir()
{
ircount=0;
// memset(irframes,0x00,sizeof(irframes));
irdone=false;
}
void main()
{
int8 addr, cmd;
int1 ok;
delay_ms(100); //setting up PIC
setup_adc_ports(no_analogs);
setup_adc(adc_off);
set_tris_a(0b00000100);
delay_ms(100);
//timer prescaler dependent on oscillator speed
setup_timer_1(t1_internal|t1_div_by_1);
ext_int_edge(0,h_to_l);
enable_interrupts(int_ext);
enable_interrupts(global);
start_ir();
while(1)
{
if (irdone)
{
ok= decode_ir(addr,cmd);
if(!ok) //if bad bits or out of synch, reset processor
reset_cpu(); //(can I avoid this?)
else
{
if (addr==1)
{
switch (cmd)
{
case (0x07)://Remote button "8"
{
output_high(pin_a5);
output_low(pin_a4);
break;
}
case (0x04)://Remote button "5"
{
output_high(pin_a4);
output_low(pin_a5);
break;
}
case (0x01)://Remote button "2"
{
output_high(pin_a5);
output_high(pin_a4);
break;
}
default: //any other button
{
output_a(0x00);
break;
}
}
}
}
start_ir();
}
}
}
|
|
|
|
pyu
Joined: 04 Feb 2009 Posts: 51
|
|
Posted: Sat Feb 21, 2009 11:08 am |
|
|
Is the last program really working? |
|
|
longtdbk
Joined: 17 Apr 2010 Posts: 1
|
|
Posted: Sat Apr 17, 2010 10:42 am |
|
|
Thanks Vanhaser, Rohit! Your posts help me so much! |
|
|
deperkin
Joined: 04 Feb 2009 Posts: 83 Location: PA
|
16F877a - sony remote |
Posted: Mon Jul 05, 2010 10:20 am |
|
|
I have the same questions as HTAluvBeBeo above...
I have tried his code and get nothing.
In fact when I replace main with:
Code: |
void main () {
while(1){
output_high(pin_b1);
}
}
|
and place an led/res on b1 I still get nothing.
Could it be placed continually in reset or something odd with this code?
I am using a 16F877A and a TSOP1138. When I put an LED on the output pin of the TSOP1138 I do see flashing, so I know that this works... but I get no interrupt. |
|
|
07ee17
Joined: 04 Jul 2010 Posts: 1
|
|
Posted: Tue Jul 13, 2010 11:40 am |
|
|
Hi!
I tried the code given by Rohit de Sa. Code is same except some minor changes. My problem is same as of Rohit de Sa. It looks like PIC freezes after receiving some bits. Does anybody able to solve this?
If I uncomment memset() command PIC seems to decode fine but then it automatically clears the output even if I remove reset_cpu()??? Plz help me with this.
I am not pasting the code because it is given above as in Rohit De Sa's post.
Edit:
I think the problem might lies in timeout. I am unable to develop reset irframes[14] functions within interrupts in case of TIMEOUT. |
|
|
Rohit de Sa
Joined: 09 Nov 2007 Posts: 282 Location: India
|
|
Posted: Tue Jul 13, 2010 8:33 pm |
|
|
07ee17:
I was initially having that problem. Once I added a 4k7 pullup on the TSOP output, it started behaving itself. I have not had any problems till now.
Quote: | I had to comment out the memset statement in start_ir(). When compiled memset kept putting a CLRF GPIO into the assembly code. |
Regarding the memset() issue, I haven't really spent much time on it. It seemed like a compiler issue to me at that time. I will check it out and let you know (umm, forum heavyweights, please help here :-P) Maybe its been resolved in compiler updates.
Rohit |
|
|
sahu77
Joined: 08 Sep 2011 Posts: 202
|
|
Posted: Sun Oct 09, 2011 12:35 pm |
|
|
Rohit de Sa wrote: | Hey all, below is documented code. Hope the brief explanations help.
Cheers,
Rohit
Code: |
// This is code for an IR remote control decoder
// using the 12 bit SIRC protocol. Based on code
// by Aurelian Nichita.
.
.
.
|
|
I want change this code with RC5 code pl help me... _________________ sahu |
|
|
umairnaeem
Joined: 13 Nov 2011 Posts: 1
|
Changing interrupt from EXT_INT to int_rb |
Posted: Sun Nov 13, 2011 11:58 am |
|
|
I am trying to change your code from external interrupt to interrupt on
change but it is not working or doing nothing at all. I need ext_int for
zero-crossing so I need ext_int free for that. Help me! Thanks. My code is:
Code: |
#include <16f877A.h>
#fuses HS,NOWDT,NOCPD,NOPROTECT,PUT,NOBROWNOUT
#use delay(clock=4M)
//------------------------------------------------------------------------------
#use fast_io(A)
#use fast_io(B)
#zero_ram
//-----------------------------------------------------------------------------------#define one_min 1450 //no of counts to safely detect bit1
#define one_max 2200 //optimal @4 MHz is 1800
#define zero_min 600 //no of counts to safely detect bit0
#define zero_max 1440 //optimal @4 MHz is 1200
//-----------------------------------------------------------------------------------int16 irframes[14]; //holds incoming IR data
int8 ircount =0; //counts no if bits received
int1 irdone=false; //flag bit
//-----------------------------------------------------------------------------------#int_timer1 //(is this isr necessary? I dont really know)
void timer1_isr()
{disable_interrupts(int_timer1);
}
//-----------------------------------------------------------------------------------#int_ext
void ext_isr()
{
if(irdone) return;
irframes[ircount++]=get_timer1();
if(ircount>=13) //if 13 triggers(ie 12 bits+start) found
irdone=true; //set "done" flag
set_timer1(0); //restart timer for new bit
enable_interrupts(int_timer1); //(is this necessary? I dont really know)
}
//-----------------------------------------------------------------------------------#int_rb
void rb_isr()
{
if(irdone) return;
irframes[ircount++]=get_timer1();
if(ircount>=13) //if 13 triggers(ie 12 bits+start) found
irdone=true; //set "done" flag
set_timer1(0); //restart timer for new bit
enable_interrupts(int_timer1); //(is this necessary? I dont really know)
}
//------------------------------------------------------------------------------
int1 decode_ir(int8 &addr,int8 &cmd) //IR decoding function
{
int8 i;
int8 mask;
int1 bits[12];
addr=0;
cmd=0;
irframes[13]=1200; //last bit is always zero
for(i=2;i<=13;i++)
{
if((one_min<=irframes[i])&&(irframes[i]<=one_max))
bits[i-2]=0x01; //if the sampled signal lies within limits
else //set to 1
if((zero_min<=irframes[i])&&(irframes[i]<=zero_max))
bits[i-2]=0x00; //if the sampled signal lies within limits
else //set to 0
return false; //otherwise clear flag
}
mask=0x01; //format command
for (i=0;i<=6;i++)
{
if (bits[i])
cmd=cmd|mask;
mask<<=1;
}
mask=0x01; //format address
for (i=7;i<=11;i++)
{
if(bits[i])
addr=addr|mask;
mask<<=1;
}
return true; //set flag
}
//------------------------------------------------------------------------------
void start_ir()
{
ircount=0;
// memset(irframes,0x00,sizeof(irframes));
irdone=false;
}
//------------------------------------------------------------------------------void main()
{
int8 addr, cmd;
int1 ok;
set_tris_b(0b11111111);
set_tris_c(0b00000000);
setup_timer_1(t1_internal|t1_div_by_1); //timer prescaler dependent on oscillator speed
enable_interrupts(INT_RB);
enable_interrupts(INT_EXT);
enable_interrupts(global);
ext_int_edge(0,h_to_l);
//delay_ms(10);
port_b_pullups(true); // Parameter is a bitmask (for bit 4)
delay_us(10);
//----------------------------------------------------------------------------- start_ir();
while(true)
{
if (irdone)
{
ok= decode_ir(addr,cmd);
if(!ok) //if bad bits or out of synch, reset processor
reset_cpu(); //(can I avoid this?)
else
{
if (addr==1)
{
switch (cmd)
{
case (0x00)://Remote button "1"
{
output_toggle(pin_c0);
delay_ms(1000);
break;
}
case (0x01)://Remote button "2"
{
output_toggle(pin_c1);
delay_ms(100);
break;
}
case (0x02)://Remote button "3"
{
output_toggle(pin_c2);
delay_ms(100);
break;
}
case (0x03)://Remote button "4"
{
output_toggle(pin_c3);
delay_ms(1000);
break;
}
default: //any other button
{
output_c(0x00);
break;
}
}
}
}
start_ir();
}
}
} |
|
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|