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?