Arduino IR Send, no output on IR pin

[NOTE: This issue was resolved! If you’re using the IR library I used, you may have to use a pin other than pin 3, despite what the comments in the code say! I had to use pin 9 on my Arduino Mega 2560. Read the entire topic for the whole story.]

I’m using this IR library (GitHub) to receive and transmit infrared signals using my Arduino MEGA 2560.

The receive functionality is working great! I pushed the power button on a (nonstandard) remote and got an NEC value of 0xFFA25D. Next, I wanted to send that code from the Arduino, so I modified the send demo to this:

/*
 * IRremote: IRsendDemo - demonstrates sending IR codes with IRsend
 * An IR LED must be connected to Arduino PWM pin 3.
 * Version 0.1 July, 2009
 * Copyright 2009 Ken Shirriff
 * http://arcfn.com
 */

#include <IRremote.h>

IRsend irsend;

void setup()
{
  Serial.begin(9600);
}

void loop() {
  if (Serial.read() != -1) {
    irsend.sendNEC(0xFFA25D, 24);
    delay(40);
  }
}

Notice that I put my NEC code in the send command. Every time the Arduino receives ANY serial input, it should transmit the IR signal for “power” on the infrared LED on pin 3.

But it doesn’t.

If I point the Arduino-controlled LED at my device and “transmit” the signal, it does not turn on. The remote works just fine, but the Arduino one does nothing.

I’ve checked things that might be common problems. First, I verified that the IR LED works. If I connect the + to 5V instead of pin 3 (to make the IR LED stay on constantly) and point a camera at it, I see the blueish / purple glow. Next, I pointed the camera at the actual remote (not Arduino). When I push the power button on the remote I can see the led flashing, sending the signal. On my Arduino-controlled LED, there is nothing but darkness in the camera viewfinder.

Then I thought to put a visible light LED instead and see if I could see flashes with my eyes. I chose a nice bright yellow one, and verified that it worked. When I connected this to pin 3, I saw no light when the Arduino was supposedly “transmitting”. Even in complete darkness there wasn’t a flicker.

So the LED isn’t broken and my camera can detect infrared, so it seems the only other possible option is that the Arduino isn’t sending anything at all. Why could this be? I read some stuff about various “timers” and why port 3 is used, but I don’t really understand all of it. I read something that mentioned different timers are connected to different ports on different Arduino models. Should I be using a different port on my Arduino MEGA? The sketch comment just says pin 3. I don’t have another Arduino to try.

Any suggestions?

Thanks!

(The only circuit involved in transmission is an LED and a 20 ohm resistor. The Arduino pin 3 connects to the 100 ohm resistor which connects to the LED which connects back to ground.)

20ohm (~60-65mA) could kill the output pin.

I wouldn't go any lower than 100ohm.

Better to drive the LED with a small mosfet (e.g. 2N7000) or transistor with that LED current.
Use two LEDs in series for more range. IR LEDs drop ~1.2volt.
Leo..

Hi, gfrung4

Two suggestions:

  1. Try sending the IR command in the setup() without any kind of trigger. Like this:
/*
 * IRremote: IRsendDemo - demonstrates sending IR codes with IRsend
 * An IR LED must be connected to Arduino PWM pin 3.
 * Version 0.1 July, 2009
 * Copyright 2009 Ken Shirriff
 * http://arcfn.com
 */

#include <IRremote.h>

IRsend irsend;

void setup()
{
  Serial.begin(9600);
  delay(3000); // 3 sec delay to let you set up direction of IR properly - reduce or increase as desired
  irsend.sendNEC(0xFFA25D, 24);
  delay(40);
}

void loop() {
}

If that works then see Suggestion 2 below. If it doesn’t work and assuming your NEC IR code is correct, then your hardware/connection is at fault.

  1. Your original code is reading the serial buffer continuously through the loop() without checking if anything is available. This might be affecting your results and not triggering the send command as expected. If you look at the examples on the relevant Arduino pages, there’s always a check on Serial.available() prior to calling Serial.read().

Wawa:
20ohm (~60-65mA) could kill the output pin.

I wouldn’t go any lower than 100ohm.

Better to drive the LED with a small mosfet (e.g. 2N7000) or transistor with that LED current.
Use two LEDs in series for more range. IR LEDs drop ~1.2volt.
Leo…

Thanks for pointing that out! I don’t need that much power (it’s a tiny LED). I’ve replaced the 20 ohm resistor with a 100 ohm resistor and it still lights just fine.

Just to be sure, I checked both my LEDs (infrared and yellow) as well as the port 3 (using a blinking light sketch) to make sure everything still works, and it all seems to be fine. No blown out ports or components!

geeq:
Hi, gfrung4

Two suggestions:

  1. Try sending the IR command in the setup() without any kind of trigger. Like this:

  2. Your original code is reading the serial buffer continuously through the loop() without checking if anything is available. This might be affecting your results and not triggering the send command as expected. If you look at the examples on the relevant Arduino pages, there’s always a check on Serial.available() prior to calling Serial.read().

Thanks! I tried this, and still received no output on the pin. This did, however, lead me to something interesting.

The code in the library that sends the signals looks like this:

#define NEC_HDR_MARK	9000
#define NEC_HDR_SPACE	4500
#define NEC_BIT_MARK	560
#define NEC_ONE_SPACE	1690
#define NEC_ZERO_SPACE	560

#define TIMER_ENABLE_PWM     (TCCR2A |= _BV(COM2B1))
#define TIMER_DISABLE_PWM    (TCCR2A &= ~(_BV(COM2B1)))

void IRsend::sendNEC(unsigned long data, int nbits)
{
  enableIROut(38);
  mark(NEC_HDR_MARK);
  space(NEC_HDR_SPACE);
  for (int i = 0; i < nbits; i++) {
    if (data & TOPBIT) {
      mark(NEC_BIT_MARK);
      space(NEC_ONE_SPACE);
    } 
    else {
      mark(NEC_BIT_MARK);
      space(NEC_ZERO_SPACE);
    }
    data <<= 1;
  }
  mark(NEC_BIT_MARK);
  space(0);
}

void IRsend::mark(int time) {
  // Sends an IR mark for the specified number of microseconds.
  // The mark output is modulated at the PWM frequency.
  TIMER_ENABLE_PWM; // Enable pin 3 PWM output
  if (time > 0) delayMicroseconds(time);
}

/* Leave pin off for time (given in microseconds) */
void IRsend::space(int time) {
  // Sends an IR space for the specified number of microseconds.
  // A space is no output, so the PWM output is disabled.
  TIMER_DISABLE_PWM; // Disable pin 3 PWM output
  if (time > 0) delayMicroseconds(time);
}

This matches the NEC specification I found while searching around (here’s an example). I was able to fairly easily follow from the sendNEC function to see when delays should happen and when the signal should be transmitted.

But here’s the interesting part. If I change TIMER_ENABLE_PWM to digitalWrite(3, HIGH) and TIMER_DISABLE_PWM to digitalWrite(3, LOW), the LED blinks. Obviously this isn’t correct, because it’s no longer using PWM (just constant on), so it won’t actually work to send IR signals, but this indicates that the functions timings are all working just fine, and the issue lies in the timer enabling / disabling. These lines:

#define TIMER_ENABLE_PWM     (TCCR2A |= _BV(COM2B1))
#define TIMER_DISABLE_PWM    (TCCR2A &= ~(_BV(COM2B1)))

They’re not turning on / off the PWM.

The problem is I have no clue what that part means. Could someone explain that for me? It seems the first one is meant to turn on PWM on pin 3, and the second one is meant to turn it off, but in reality nothing happens at all. Without understanding these lines, I’m at a loss.

Thanks for all the help!

I found the issue!

Whoever wrote that comment didn't consider that not everyone is using the same Arduino model. I read this article to learn more about these timer things and discovered this chart:

For Arduino Mega: (tested on Arduino Mega 2560)
timer 0 (controls pin 13, 4)
timer 1 (controls pin 12, 11)
timer 2 (controls pin 10, 9)
timer 3 (controls pin 5, 3, 2)
timer 4 (controls pin 8, 7, 6)

The confusing bit in the code in my post above controls timer 2 (that's what the 2 in TCCR2A means). On Arduino Uno, pin 3 is controlled by timer 2. But according to the table above, on an Arduino Mega 2560, timer 2 controls pin 9 and 10, not pin 3.

Looking through the library's code farther revealed this bit:

#if defined(CORE_OC2B_PIN)
#define TIMER_PWM_PIN        CORE_OC2B_PIN  /* Teensy */
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define TIMER_PWM_PIN        9  /* Arduino Mega */
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
#define TIMER_PWM_PIN        14 /* Sanguino */
#else
#define TIMER_PWM_PIN        3  /* Arduino Duemilanove, Diecimila, LilyPad, etc */
#endif

This seems to indicate that different Arduino models use different pins. I plugged my LED into pin 9 and lo and behold it lights up. Sadly it still doesn't actually control the thing I'm trying to control, but it's sending something now, and that's better than before.

Kind of annoying that I had to search around the code for that, and that there's a blatant error right in the comment on top of the demo program. That's the first program a lot of people are going to run. What kind of first impression is that?

Documentation, documentation, documentation!

EDIT: I did get my device to work from the Arduino's IR signal about 3 minutes after I wrote this. Turns out that although the signal (0xFFA25D) is 24 bits long, you have to use 32 as the length. Changing the line to this:

irsend.sendNEC(0xFFA25D, 32);

worked like a charm! The device turned on when the Arduino sent the signal, and there was a little mini celebration!

1 Like

@gfrung4, you are right. For due board it was pin 7 :slight_smile:

Hi Guys,i have same problem and have arduino uno board.can you please send the full code and a little help for full circut?i`ll be thankful.
i have another question.what is the meaning of this line:
if (Serial.read() != -1)

Hi I Have the same problem, my Output IR not send. I have arduino mega 2560 but i connected pin 9 and work for led red (flashing led). But not send led IR and not flashing (i see eith my camara of phone).
Do you have a same problem?

Hi,

I just wanted to contribute, that I had the same problem with a Arduino Nano Every (AtMega4809).
The IRremote library didn't work on that.

I digged in the library, the AtMega4809 data sheet and esp. the technical note TB3214 from Microchip.

To get out TCB0 PWM at pin 6, as it is defined in the library, I had to edit the boarddefs.h file and add the TCB_CCMPEN bit to the bit masks for CTRLB register for the ATmega4809 TCB0:

#define TIMER_ENABLE_PWM (TCB0.CTRLB = TCB_CNTMODE_PWM8_gc | TCB_CCMPEN_bm)
#define TIMER_DISABLE_PWM (TCB0.CTRLB &= ~(TCB_CNTMODE_PWM8_gc | TCB_CCMPEN_bm))

#define TIMER_CONFIG_KHZ(val) ({
const uint8_t pwmval = SYSCLOCK / 2000 / 2 /(val);
TCB0.CTRLB = TCB_CNTMODE_PWM8_gc | TCB_CCMPEN_bm;
...

and add this line to my setup() function:

PORTMUX.TCBROUTEA |= 0x01; // TCB0 output on Alternate output PF4 = Arduino ~D6

Regards,
Gerhard

Hey,

I also just want to put my two cents in. I faced the exact same problem, I even wanted so send the exact same NEC code. The solution was very easy. I just replaced

irsend.sendNEC(0xFFA25D, 24);

with

irsend.sendNEC(0xFFA25D, 32);

I read in the NEC standard that a valid code consists of 16 or 32 bits, so 24 seems not to work, even when the code I want to send is 24 bits long.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.