| 
	
	|  |  |  
	
		| 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
 
 |