Reading IR controller with TSOP1838

Two quick questions:

  1. 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?

  1. Has anyone got the 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, 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 -- */

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

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
      // initialize 
      bit_count = 0;
      ir_data_ready = 0;
      ir_data_repeat = 0;

  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;
            ir_data_ready =0;
      if(ir_dat[2]^ir_dat[3]== 0xff){
                Serial.println(ir_dat[2], HEX);
            ir_data_repeat =0;

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;
            return 0;


if ((PINC & (1<<IR_PIN)) == (trigger_edge<<IR_PIN)){

// IR NEC PPM state machine
      case FRAME_IDLE:
            t_start = TCNT1;
            frame_state = FRAME_START1;
            trigger_edge = 1;
      case FRAME_START1:
            t_high = TCNT1;
            if(in_range(t_high, t_start, TIME_9MS)){
                  frame_state = FRAME_START2;
                  trigger_edge = 0;  
                  frame_state = FRAME_IDLE;
                  trigger_edge = 0;  
      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;
            else if(in_range(t_low, t_high, TIME_2_25MS))
                  frame_state = FRAME_REPEAT;
                  frame_state = FRAME_IDLE;
      case FRAME_DAT1:
            t_high = TCNT1;
            trigger_edge = 0;
            if(in_range(t_high, t_low, TIME_0_56MS))
                  frame_state = FRAME_DAT2;
      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));
            else if(in_range(t_low, t_high, TIME_1_69MS)){
                  ir_dat[bit_count>>3] |= ( 1<< (bit_count&0x7));
                  ir_data_ready = 1;
                  frame_state = FRAME_IDLE;
                  trigger_edge = 0;
                  frame_state = FRAME_DAT1;
                  trigger_edge = 1;
      case FRAME_REPEAT:
            ir_data_repeat = 1;
            frame_state = FRAME_IDLE;
            trigger_edge = 0;
            frame_state = FRAME_IDLE;
            trigger_edge = 0;

If that TSOP1838 is anything like TSOP2438 (which is what I have tried, and I imagine it is), I really recommend the IRremote library by Ken Shirrif: It's a really excellent IR library. According to that page, it supports NEC, Sony SIRC, Philips RC5, Philips RC6, and raw protocols. If your IR remote is not supported, chances are you can use raw codes anyway, to use it. No guarantee though, as there are more protocolls out there.

EDIT: I see my answer might be somewhat off-topic for what you ask, but I thought it may be of some help.

More edits: As for inputs, I believe the receiver can be connected to any pin. If you want to use it for sending IR, it has to be pin 3 (the IR LED that is..).

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

No the TSOP1838 is a receiver only you can't send anything with it.

Did you mean to say:-

I recently bought a TSOP1838 based emitter.

If so I can't see how an emitter is TSOP1838 based.

Sorry! I can see how Mike read what I posted the way he did.

What I have…

Ordinary remote control, to transmit IR signals to my TV, etc… and, I hope, eventually, my Arduino.

TSOP1838 connected to Arudino as a sensor, not as an emitter

What I hope: When I press buttons on the remote control, the Arduino+sensor will “see” the commands I’ve sent from the control.

Thank you Raron… I will certainly try that avenue if “the easy” answer (?!) doesn’t work out.

Thank you again, Raron... I tried the site you mentioned, and, in about 10 minutes, had my IR receiver working fine with all of the units I mentioned earlier. The code... at least the "surfaced" parts of it... extremely clear, simple. Not sure what is being done within the library. I wonder (no answer needed!) if it is also "messing with" timers and interrupts... but that may be NECESSARY for any decent IR reader.

I was amazed at the signals my little, inadequately respected, remotes were putting out! Pressing "1" on the Pioneer seems to give rise to a (consistent) 8 byte burst! (16 digits of hex)

The Shirriff libary also gives you what you need to have the Arduino SEND IR codes, if you have an IR LED on one of your Arduino's pins, and a good page "all about" IR signalling...


Fully worked up "How To" now online at...

(Useful to anyone wanting to do IR remote code sending or receiving, not just users of datalogging shield.)