5

I am looking for a way to choose a pin on the Arduino Uno. This pin will be used to send the signal of an IR LED. I am using the IRremote library.

e.g.

Below is the IR send demo which uses pulse width modulation pin 3 to send the IR signal. I want to change that pin to any other pin.

Any pointers will make me very happy thanks.

/*
 * 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()
{
}

void loop() {
    for (int i = 0; i < 3; i++) {
        irsend.sendSony(0xa90, 12);
        delay(40);
    }
    delay(5000); //5 second delay between each signal burst
}
2
  • Is the pin hardcoded into the library then? I recently had the same problem with the USB Host library. It is annoying when you can't define the pin yourself, although the authours of the library probably have their reasons for doing so. The line to change, for the Uno, seems to be line 138 in boarddefs.h, but I'm trying to find where IR_USE_TIMER2 is defined... Jan 19, 2017 at 7:06
  • Line 195 in boarddefs.h you could try changing the 3 to another pin. It might work. I'll compose an answer out of these two comments. Jan 19, 2017 at 7:19

2 Answers 2

2

As the pin does not appear to be able to be defined when creating an object from the IRsend class, it seems as if you will have to modify the IRremote library itself.

I recently had the same problem with the USB Host library, see Change select pin of USB Host library. It is annoying when you can't define the pin(s), that a particular library uses, yourself... However, the authors of the library probably have their reasons for doing so.

Looking through the various headers of the library, I found in boarddefs.h on lines 134-138:

// Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, Nano, etc
// ATmega48, ATmega88, ATmega168, ATmega328
#else
    //#define IR_USE_TIMER1   // tx = pin 9
    #define IR_USE_TIMER2     // tx = pin 3

So, the line to change, for the Uno, would seem to be line 138 in boarddefs.h

    #define IR_USE_TIMER2     // tx = pin 3

However, it is not, as that merely states that for the Arduino Uno IR_USE_TIMER2 is used...

Looking further down to where the Timers are defined, you will see the section for Timer 2, on line 146. In that section the transmit pin, for a number of versions of the Arduino, is defined as TIMER_PWM_PIN on lines 189-197:

#elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \
|| defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \
|| defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \
|| defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \
|| defined(__AVR_ATmega164P__)
#   define TIMER_PWM_PIN  14             // MightyCore
#else
#   define TIMER_PWM_PIN  3              // Arduino Duemilanove, Diecimila, LilyPad, etc
#endif                                   // ATmega48, ATmega88, ATmega168, ATmega328

You will have to change this line in the library, Line 196 in boarddefs.h:

#   define TIMER_PWM_PIN  3              // Arduino Duemilanove, Diecimila, LilyPad, etc

You could try changing the 3 so that you can use another pin. It might work. For example to use pin 5, en lieu of pin 3, change the 3 to a 5, like so:

#   define TIMER_PWM_PIN  5              // Arduino Duemilanove, Diecimila, LilyPad, etc

Be careful not to choose a pin that is used by something else, AND I think that the pin will need to be PWM capable.

Note that the definitions that are in boarddefs.h used to be in RemoteInt.h, in earlier versions of the library. See this comment at the very top:

// This file contains all board specific information. It was previously contained within
// IRremoteInt.h

So, make sure that you have the latest version of the IRremote library.


The above hack should also work for the Mega2560 as is uses the same timer, Timer 2, see lines 68-71:

// Arduino Mega
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
    //#define IR_USE_TIMER1   // tx = pin 11
    #define IR_USE_TIMER2     // tx = pin 9

Other boards are also defined in this file. If you have another type of board, the timer may be different, but the process to find which line to change would be very similar...

3
  • Note that I have not tried this, so I would be interested to hear if it works or not. Jan 19, 2017 at 7:33
  • Thanks for your answer. I have two questions: How do I know when a pin is being used by something else? Will I be able to choose more than one pin to do a task? e.g at the moment only pin 3 sends IR signal however, I would like pin3, pin 5 and pin6 to send IR signals.
    – MALKAVIAN
    Jan 20, 2017 at 7:57
  • 1) Your code will tell you if a pin is being used. W.R.T. the IRremote library, the documentation will tell you which pins it is using. 2) Looking at the library it seems that you can not, or at least not without further modification. Maybe you could activate another Timer, by uncommenting out another line, and then use the pin of that timer (as each timer, appears to use its own separate pin - from looking at that header file). I am not sure. If you really want to do that, then ask/post a separate (related) question, as it is significantly different from your original question.. :-) Jan 20, 2017 at 8:14
2

I tried to find where the pin is defined and gave up, I ended up swapping to pin9 by commenting out timer2, like this:

#define IR_USE_TIMER1   // tx = pin 9
//#define IR_USE_TIMER2     // tx = pin 3

Not ideal since I needed 9 also and I will add how annoying this library is that although I only need to receive signals and never send...it still takes up a pin for sending.

ANyway, the posts above helped me at least get my motor shield working, thanks guys.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.