Two quick questions:
- Has anyone successfully used a TSOP1838 IR received with any of the following?....
a Sony TV controller, a Sony radio controller, a Pioneer digibox controller, or a Panasonic radio controller? Would your software allow connecting the sensor on any of: analog 0-6, aka digital 14-19? What software are you using?
- Has anyone got the nuelectronics.com IR command receiver working with the nuelectronics shield?
Thanks for any help! I keep messing up the things the IR controllers are usually used for while working on this... going mad. And now (first time ever), the insertion point cursor had died in this frame, and typing this is pushing me further from sanity!
=====
And, finally, one long question...
I recently bought a TSOP1838 based sensor. With it, I am supposed to be able to send commands to my Arduino from my ordinary TV, etc, remote control.
I put the software from nuelectronics into my Arduino. It compiles, and when I run it, the "IR remotr controller decode" message appears... but I can't get it to "see" messages from any of the controllers listed above.
I'm using a Diecimila... I wonder if the software needs a "tweak" somewhere to compensate for the clock frequency in that?? Have we "moved on" to faster CPUs?
Things I've already tried:
Checked that the controllers are emitting something. Most are in everyday use, and the others show up fine when pointed at my CCTV camera. (For others reading this: Some digital cameras and webcams, especially the cheaper ones, can "see" IR.)
Checked that SOMETHNG happens when I send an IR signal: At the input to my Arduino, the signal from an un-illuminated sensor is high (5v). When I send a command from one of the IR transmitters, the bar on my multimeter "flickers", and the voltage drops. Not to zero, but it drops. (I'm hoping that I'm seeing multiple brief lows on a signal that is usually high.) (Maybe I need to work up that digital logic analyzer that I was thinking of doing with my Arduino!)
Investigated the question of what channel the sensor should be on. This could well be where the problem lies. The code below is what is on nuelectronics.com, which is where I bought the sensor. I thought that "#define IR_PIN PORTC1" would be where the pin used was defined. When I made that "#define IR_PIN 16", and plugged the sensor in to that connector: no joy. (That the pin is working. Well... it worked for analog input, a moment ago). When, just after "Serial.println("IR remotr controller decode");" in setup() I inserted a "Serial.println(PORTC1,DEC);", I got "1"... which is strange, as the shield the sensor is sold to go with doesn't bring pin 1 to the edge of the board... but I must admit that the "stuff" in the code depending upon IR_PIN isn't clear to me... most of it is in the setup() routine, by the way, with one line about half way through the code (in "in_range", just after loop()) asking...
if ((PINC & (1<<IR_PIN)) == (trigger_edge<<IR_PIN))
.
Ideas would be welcome!!!
/* rc_nec_ppm -- remote controller NEC PPM protocol */
/* ppm protocol referenfe -- http://www.necel.com/faq/en/mi_com/f_com_remo.html#0007 */
#include <avr/io.h>
#include <avr/interrupt.h>
#define IR_PIN PORTC1
// time definition @ TIMER1 interval @ 16us
#define TIME_9MS 562
#define TIME_4_5MS 281
#define TIME_2_25MS 141
#define TIME_0_56MS 35
#define TIME_1_69MS 106
#define TOLERANCE 10
#define FRAME_TIMEOUT 12500 // timeout 200ms
typedef enum{
FRAME_IDLE = 0,
FRAME_START1,
FRAME_START2,
FRAME_REPEAT,
FRAME_DAT1,
FRAME_DAT2
} IR_FRAME_STATE;
volatile unsigned char bit_count;
volatile unsigned char ir_dat[4];
volatile unsigned int t_start, t_high, t_low;
volatile IR_FRAME_STATE frame_state = FRAME_IDLE;
volatile byte ir_data_ready , ir_data_repeat;
byte trigger_edge; // 1- rising edge; 0 - falling edge
void setup(){
// setup timer1
TCCR1A = 0; // normal mode
TCCR1B = 0x4; // Timer1 frequency = 16MHz / 256 = 62.5KHz (16us)
TCCR1C = 0;
// enable Port change interrrupt on IR_PIN
DDRC &=~(1<<IR_PIN);
PCICR |= (1<<PCIE1);
PCMSK1 |= (1<<IR_PIN);
trigger_edge = 0; // start with falling edge
SREG|=1<<SREG_I;
// initialize
bit_count = 0;
ir_dat[0]=ir_dat[1]=ir_dat[2]=ir_dat[3]=0;
ir_data_ready = 0;
ir_data_repeat = 0;
Serial.begin(19200);
Serial.println("IR remotr controller decode");
}
void loop()
{
if( (frame_state != FRAME_IDLE)&& (TCNT1-t_start>FRAME_TIMEOUT)){
frame_state = FRAME_IDLE;
trigger_edge = 0;
}
if(ir_data_ready){
ir_data_ready =0;
if(ir_dat[2]^ir_dat[3]== 0xff){
Serial.println(ir_dat[2], HEX);
}
}
if(ir_data_repeat){
ir_data_repeat =0;
Serial.println("REPEAT");
}
}
byte in_range(unsigned int t1, unsigned int t2, unsigned int time_range)
{
unsigned int t_diff;
t_diff = t1- t2;
if( (t_diff >= (time_range - TOLERANCE)) && (t_diff <= (time_range + TOLERANCE)))
return 1;
else
return 0;
}
ISR(PCINT1_vect)
{
if ((PINC & (1<<IR_PIN)) == (trigger_edge<<IR_PIN)){
// IR NEC PPM state machine
switch(frame_state)
{
case FRAME_IDLE:
t_start = TCNT1;
frame_state = FRAME_START1;
trigger_edge = 1;
break;
case FRAME_START1:
t_high = TCNT1;
if(in_range(t_high, t_start, TIME_9MS)){
frame_state = FRAME_START2;
trigger_edge = 0;
}
else{
frame_state = FRAME_IDLE;
trigger_edge = 0;
}
break;
case FRAME_START2:
t_low = TCNT1 ;
trigger_edge = 1;
if(in_range(t_low, t_high, TIME_4_5MS)){
frame_state = FRAME_DAT1; // start state finished, now if dat state
bit_count = 0;
ir_dat[0]=0;
ir_dat[1]=0;
ir_dat[2]=0;
ir_dat[3]=0;
}
else if(in_range(t_low, t_high, TIME_2_25MS))
frame_state = FRAME_REPEAT;
else
frame_state = FRAME_IDLE;
break;
case FRAME_DAT1:
t_high = TCNT1;
trigger_edge = 0;
if(in_range(t_high, t_low, TIME_0_56MS))
frame_state = FRAME_DAT2;
break;
case FRAME_DAT2:
t_low = TCNT1;
if(in_range(t_low, t_high, TIME_0_56MS)){
ir_dat[bit_count>>3] &= ~( 1<< (bit_count&0x7));
bit_count++;
}
else if(in_range(t_low, t_high, TIME_1_69MS)){
ir_dat[bit_count>>3] |= ( 1<< (bit_count&0x7));
bit_count++;
}
if(bit_count>=32){
ir_data_ready = 1;
frame_state = FRAME_IDLE;
trigger_edge = 0;
}
else{
frame_state = FRAME_DAT1;
trigger_edge = 1;
}
break;
case FRAME_REPEAT:
ir_data_repeat = 1;
frame_state = FRAME_IDLE;
trigger_edge = 0;
break;
default:
frame_state = FRAME_IDLE;
trigger_edge = 0;
break;
}
}
}