View previous topic :: View next topic |
Author |
Message |
pyu
Joined: 04 Feb 2009 Posts: 51
|
TSOP 1740 & pic 16F887 |
Posted: Sat Feb 21, 2009 5:32 pm |
|
|
Hi.
I have a ir sensor on my pickit2 board, but it isn't working.
The code I used:
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 <16f887.h>
#fuses INTRC_IO,NOWDT,NOCPD,NOPROTECT,PUT,NOMCLR,NOBROWNOUT
#use delay(clock=4000000)
#use fast_io(B)
#zero_ram
#include "Flex_LCD.c"
#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_RB //IR bits detected by edge triggering
void ext_isr()
{
if(irdone) return;
for(ircount=0;ircount<=13;ircount++)
{
irframes[ircount]=get_timer1();
}
//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_b(0b00000011);
lcd_init();
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_RB1);
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();
}
}
} |
The problem is here:
Code: | 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 |
It always return false.
Here are some print's debugging.
[/img] |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Sun Feb 22, 2009 3:25 pm |
|
|
The code - as shown in the listing and the debug dump - can't work, cause it fills irframes in a loop following a single interrupt.
Don't know, if you also tried a meaningful bittime measurement? If so, you should dump the irframes array for debug purposes rather than complaining that it does not met some expected criterion. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Feb 22, 2009 3:44 pm |
|
|
Also, in your #INT_RB function, you need to read Pin B1 to clear the
"mismatch" condition. The "mismatch" condition is what generates
the INT_RB interrupt. You need to clear it so the PIC will be ready
to detect the next "change" (edge) tha occurs on pin B1. It's cleared
by reading the pin. Add the lines shown in bold below.
Quote: |
#INT_RB
void ext_isr()
{
int8 temp;
if(irdone) return;
for(ircount=0;ircount<=13;ircount++)
{
irframes[ircount]=get_timer1();
}
//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);
temp = input(PIN_B1);
} |
I didn't look at your code and try to figure out what you're doing.
I just wanted to mention this one thing. |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Mon Feb 23, 2009 3:23 am |
|
|
Yes, a very important hint by PCM Programmer. I wrongly assumed, you would be using an external edge sensitive interrupt. Cause you are actually using RB interrupt, do you intend to detect both edges? If not, the code has to be corrected to ignore the other edge for timing measurement. |
|
|
pyu
Joined: 04 Feb 2009 Posts: 51
|
|
Posted: Mon Feb 23, 2009 4:07 am |
|
|
Thanks for reply FvM and PCM programmer
Quote: | You need to clear it so the PIC will be ready
to detect the next "change" (edge) tha occurs on pin B1. It's cleared
by reading the pin. |
I had made some corrections in my code.
Code: |
#INT_RB //IR bits detected by edge triggering
void ext_isr()
{
int8 temp;
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)
temp = input(PIN_B1);
}
|
The result is better than the first time.
Quote: | Cause you are actually using RB interrupt, do you intend to detect both edges? If not, the code has to be corrected to ignore the other edge for timing measurement. |
Yes, I want to detect both edges, from tsop1740 ir sensor.
Now, I have some timing problems. irframes[2], irframes[3] are bigger than expected, and irframes[8], irframes[9], irframes[10] and irframes[11] are smaller. I don't know why this is happening, I will do some research.
|
|
|
pyu
Joined: 04 Feb 2009 Posts: 51
|
|
Posted: Wed Feb 25, 2009 1:32 am |
|
|
Doesn't anybody know why I get this timers?
Because I use TSOP1740 and the source code was for 1738? My timer is not set correct? |
|
|
pyu
Joined: 04 Feb 2009 Posts: 51
|
|
Posted: Sun Mar 08, 2009 9:20 am |
|
|
Anyone? |
|
|
|