Trouble with IR beam-breaks

Hi -
I'm working on a project involving infrared transmission across a room. I'm trying to achieve two things with (hopefully) the same equipment:

1. Set up an IR LED across from an IR receiver for a beam-break scenario. I hope to achieve a distance of about 25 ft.

The parts I have currently are:
IR LED - Osram SFH 4545 : http://www.digikey.com/product-search/en?vendor=0&keywords=475-2919-ND
550mW @ 100mA - 940nm wavelength
IR Receiver - Vishay TSOP38338 : http://www.digikey.com/product-search/en?vendor=0&keywords=TSOP38338
2 x Arduino Leonardos

**2.**Use the same or similar IR receivers to detect IR codes sent from wearable Arduino/IR LED devices that are moving around the room.

So basically, I'm trying to get beam-breaks and IR codes to work at a distance with the same equipment (not simultaneously, just reusing the same equipment).

The trouble I'm having is that I can detect IR codes accurately with this equipment from a distance of ~40 ft, but when I switch to the beam break scenario, I get a max distance of about 3 ft.

I'm basing my code off the Adafruit IR sensor tutorial:

For the Beam Breaks, here's my Transmitter code:

// Derived from IR Nikon intervalometer tutorial at http://www.ladyada.net/learn/sensors/ir.html

//CODE is length of pulse to send in usecs
#define CODE 2000
 
int IRledPin =  3;    // LED connected to digital pin 13 

 
 
// The setup() method runs once, when the sketch starts
 
void setup()   {                
  // initialize the IR digital pin as an output:
  pinMode(IRledPin, OUTPUT);      
 
  Serial.begin(9600);
}
 
void loop() {
  
  Serial.println("Sending 10 groups of IR code");

  for (int i=0;i<10;i++){
    
    //send 5 pulses of CODE usecs
    
    //mark 1
    pulseIR(200);
    delayMicroseconds(200);  }
}
 
// This procedure sends a 38KHz pulse to the IRledPin 
// for a certain # of microseconds. We'll use this whenever we need to send codes
void pulseIR(long microsecs) {
  // we'll count down from the number of microseconds we are told to wait
 
  cli();  // this turns off any background interrupts
 
  while (microsecs > 0) {
   // 38 kHz is about 13 microseconds high and 13 microseconds low
   digitalWrite(IRledPin, HIGH);  // this takes about 3 microseconds to happen
   delayMicroseconds(10);         // hang out for 10 microseconds, you can also change this to 9 if its not working
   digitalWrite(IRledPin, LOW);   // this also takes about 3 microseconds
   delayMicroseconds(10);         // hang out for 10 microseconds, you can also change this to 9 if its not working
   // so 26 microseconds altogether
   microsecs -= 26;
  }
 
  sei();  // this turns them back on
}

And for the IR receiver code:
(This code is a slapdash mix of an IR decoder and beam break setup - sorry it's a little messy)

#define IRpin_PIN PIND
#define IRpin 2
#define LEDpin 13


// the maximum pulse we'll listen for - 65 milliseconds is a long time
#define MAXPULSE 65000

// what our timing resolution should be in microseconds, larger is better
// as its more 'precise' - but too large and you wont get
// accurate timing
#define RESOLUTION 20

// we will store up to 100 pulse pairs (this is -a lot-)
uint16_t pulses[100][2]; // pair is high and low pulse
uint8_t currentpulse = 0; // index for pulses we're storing

void setup(void) {
  Serial.begin(9600);
  Serial.println("Ready to decode IR!");
  pinMode(LEDpin, OUTPUT);      
}

void loop(void) {
  uint16_t highpulse, lowpulse; // temporary storage timing
  highpulse = lowpulse = 0; // start out with no pulse length
  
    while (IRpin_PIN & (1 << IRpin)) {
     // pin is still HIGH, LED is off

     // count off another few microseconds
     highpulse += RESOLUTION;
     delayMicroseconds(RESOLUTION);

     // If the pulse is too long, we have a beam break
     if (highpulse >= MAXPULSE) {
       beambreak();
       printpulses();
       currentpulse=0;
       return;
     }

     //if we reached our max storage amount, reset
     if (currentpulse == 99) {
       printpulses();
       currentpulse=0;
       return;
     }
  }
  // we didn't time out so lets stash the reading
  pulses[currentpulse][0] = highpulse;
  
  // same as above, but for LED ON
  while (! (IRpin_PIN & _BV(IRpin))) {
     // pin is still LOW, LED is on
     
     lowpulse += RESOLUTION;
     delayMicroseconds(RESOLUTION);
     
     //if we timed out...
     if ((lowpulse >= MAXPULSE) && (currentpulse != 0)) {
       printpulses();
       currentpulse=0;
       return;
     }
     if (currentpulse == 99) {
       printpulses();
       currentpulse=0;
       return;
     }
  }
  pulses[currentpulse][1] = lowpulse;

  // we read one high-low pulse successfully, continue!
  currentpulse++;
}

void beambreak(void) {
  
     digitalWrite(LEDpin, HIGH);
  
     while (IRpin_PIN & (1 << IRpin)) {
     // pin is still HIGH, LED is off
     //hang out
     }

     digitalWrite(LEDpin, LOW);
     return;
}

void printpulses(void) {
  Serial.println("\n\r\n\rReceived: \n\rOFF \tON");
  for (uint8_t i = 0; i < currentpulse; i++) {
    Serial.print(pulses[i][0], DEC);
    Serial.print(" usec, ");
    Serial.print(pulses[i][1], DEC);
    Serial.println(" usec");
  }
  
  // print it in a 'array' format
  Serial.println("int IRsignal[] = {");
  Serial.println("// ON, OFF (in microseconds)");
  for (uint8_t i = 0; i < currentpulse-1; i++) {
    Serial.print("\t"); // tab
    Serial.print(pulses[i][1], DEC);
    Serial.print(", ");
    Serial.print(pulses[i+1][0], DEC);
    Serial.println(",");
  }
  Serial.print("\t"); // tab
  Serial.print(pulses[currentpulse-1][1], DEC);
  Serial.print(", 0};");
}

I decided not to use the various IR Libraries as they're overly complicated for my needs.
Any suggestions as to why I would only get a few feet of distance in the beam break scenario?

When I use this code for the transmitter:

(A Nikon camera remote control code transmitted every few seconds)

and this code for the receiver:

(A raw IR decoder sketch)

I get perfect transmission at long distance.

Any ideas?

That sounds strangely similar to this post:

http://forum.arduino.cc/index.php?topic=235433.new;topicseen#new

Have you checked the frequency you are getting from the transmitter? You need a scope. Any miss match in frequency is going to affect the receiver's sensitivity.

It looks a very poor way of generating a pulse. I would normally use timers rather than use a whole processor.

You're sending pulses for 200 microseconds, each pulse 26 microseconds, so that's 8 pulses. You then similarly delay for another 200 microseconds afterwards. From the Vishay datasheet: "After each burst of length 6 to 70 cycles a gap time is required of >= 10 cycles". Per the spec you need more gap time.

Grumpy_Mike:
Have you checked the frequency you are getting from the transmitter? You need a scope. Any miss match in frequency is going to affect the receiver's sensitivity.

I didn't really investigate it but in my experience I never noticed any difference in range due to frequency mismatch. Putting that another way, I built 8 transmitters using 555 timers and only bothered to set the frequency initially and never noticed any difference in range between my transmitters. Towards the end of my builds I was setting the pot for frequency adjustment simply by estimating and was still getting the same results.

It seems like you are using different code for the beam breaking system than you are for the other stuff. Why?

This Thread may be of interest.

...R

Chagrin:
You're sending pulses for 200 microseconds, each pulse 26 microseconds, so that's 8 pulses. You then similarly delay for another 200 microseconds afterwards. From the Vishay datasheet: "After each burst of length 6 to 70 cycles a gap time is required of >= 10 cycles". Per the spec you need more gap time.

Thanks! This is all very helpful. I'm very new to electronics and Arduino so just learning as I go. I had a feeling it had something to do with the duty cycle. I think you're spot on.

This is a dumb question, but just to clarify: a cycle in this context is one 26 microsecond "pulse" (i.e. one full 38kHz wavelength)? So I could send 8 pulses (208 microseconds) and then pause for >= 260 microseconds and I should be fine.

Also, I do think that timers would make more sense than using an Arduino but since I'm new to electronics I opted for something more in my comfort zone at the moment. And if I'm sending complex IR codes, I will need to use an Arduino. For the beam breaks, timers would likely suffice. I just don't know how they work yet.

(i.e. one full 38kHz wavelength)?

Wavelength is the wrong thing here.
Period is how long it takes for one cycle, that is the signal to go high to low to just high again. Frequency is the number of times it does this in a second. 1 / the period gives the frequency and 1 / the frequency gives the period.

So for 38 KHz the period is 26.3uS, that will be 13.15 uS high and 13.15 uS low.

You should be using a TSSP4038 or TSSP58038. With those receivers you don't need a gap time thus it's pretty straightforward to build an IR emitter with just a single 555 timer.

Grumpy_Mike:
Wavelength is the wrong thing here. Period is how long it takes for one cycle

Thanks for the explanation - I had a feeling that wavelength was the incorrect term.

Chagrin:
You should be using a TSSP4038 or TSSP58038. With those receivers you don't need a gap time thus it's pretty straightforward to build an IR emitter with just a single 555 timer.

Thanks for the tip! That's perfect - I will use one of those receivers instead.