My goal is to be able to send/receive IR messages in my own custom format and send messages ~10 bytes long. My message object will get serialized down to individual bits, which are transmitted by turning the IR LED on/off at specific timings of my choosing to represent logical ones and zeros. From what I've seen, an IR LED can be turned on/off in either a while loop or as a PWM signal in order to transmit the message. I'm under the assumption the only thing gained by using a PWM signal is that the work there is done on a timer callback and let other code run seemingly simultaneously. For simplicity, I opted for the while loop approach.
The issue I am seeing is one of two. Either the receiver is not reading the timings right, or the transmitter is not turning the LED on/off as fast as I would expect.
For the example code below, the IR LED is turned on for 600 microseconds, and off for 300. (Eventually, my custom messages will be built up using something along these lines.) However, as you can see in the Sample Outputs below the receiver is not seeing the IR signal as on or off for anywhere near that amount of time.
Not sure if this is a setup issue, or something else. The two Arduino boards I'm using are both Arduino Pro ATmega328p boards. For the board sending the IR signal, Pin 6 goes to a 330 Ohm resistor, then to the LED, then to ground. The IR Receiver on the other board has no resistors, just direct connections to pins. When reading the IR signals, I hold the receiver a few centimeters away from the LED.
My questions are:
- Is this a viable setup? Should this work? Or am I all wrong in my assumptions and need to look some other way of doing this?
- Is my assumption about turning the LED on/off with a while loop vs. a PWM signal true? Or should I remove the loop concept and only use a PWM signal.
IR Transmit Code:
#define IRpin 6
void setup() {
pinMode(IRpin, OUTPUT);
}
void loop() {
//LED On
PORTD |= (1 << IRpin);
delayMicroseconds(600);
//LED Off
PORTD &= ~(1 << IRpin);
delayMicroseconds(300);
}
IR Receive Code (taken from an online example, only modifications are to output text):
#define IRpin_PIN PIND
#define IRpin 2
// the maximum pulse we'll listen for - 65 milliseconds is a long time
#define MAXPULSE 65000
#define RESOLUTION 20
uint16_t pulses[300][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!");
}
void loop(void) {
uint16_t highpulse, lowpulse; // temporary storage timing
highpulse = lowpulse = 0; // start out with no pulse length
while (IRpin_PIN & (1 << IRpin)) {
// count off another few microseconds
highpulse++;
delayMicroseconds(RESOLUTION);
// If the pulse is too long, we 'timed out' - either nothing
// was received or the code is finished, so print what
// we've grabbed so far, and then reset
if ((highpulse >= MAXPULSE) && (currentpulse != 0)) {
printpulses();
currentpulse = 0;
return;
}
}
// we didn't time out so lets stash the reading
pulses[currentpulse][0] = highpulse;
// same as above
while (! (IRpin_PIN & _BV(IRpin))) {
// pin is still LOW
lowpulse++;
delayMicroseconds(RESOLUTION);
if ((lowpulse >= MAXPULSE) && (currentpulse != 0)) {
Serial.println("Breaking - Hit max Pulse Low");
printpulses();
currentpulse = 0;
return;
}
}
pulses[currentpulse][1] = lowpulse;
// we read one high-low pulse successfully, continue!
currentpulse++;
}
void printpulses(void) {
uint32_t totalMicroseconds = 0;
for (uint8_t i = 0; i < currentpulse - 1; i++) {
Serial.print("On(");
Serial.print(pulses[i][1] * RESOLUTION , DEC);
Serial.print(");");
Serial.println("");
Serial.print(" Off(");
Serial.print(pulses[i + 1][0] * RESOLUTION , DEC);
Serial.println(");");
totalMicroseconds += pulses[i][1] * RESOLUTION;
totalMicroseconds += pulses[i + 1][0] * RESOLUTION;
if (i % 8 == 0) {
Serial.println("");
}
}
Serial.print("On(");
Serial.print(pulses[currentpulse - 1][1] * RESOLUTION, DEC);
Serial.print(");");
totalMicroseconds += pulses[currentpulse - 1][1] * RESOLUTION;
Serial.println("");
Serial.print("Total Microseconds: ");
Serial.println(totalMicroseconds, DEC);
}
Sample Outputs:
Ready to decode IR!
On(20);
Off(62064);
On(0);
Off(12060);
On(360);
Off(1860);
On(440);
Off(8940);
On(20);
Off(15460);
On(80);
Off(25672);
On(40);
Total Microseconds: 127016
On(40);
Off(6740);
On(300);
Off(6740);
On(20);
Off(8520);
On(40);
Off(6740);
On(1540);
Off(15720);
On(40);
Off(34860);
On(20);
Total Microseconds: 81320
On(3000);
Off(35384);
On(40);
Off(14180);
On(1220);
Off(54440);
On(980);
Total Microseconds: 109244
On(200);
Total Microseconds: 200
On(20);
Off(29160);
On(60);
Off(26700);
On(60);
Off(22880);
On(20);
Off(2928);
On(20);
Total Microseconds: 81848