IR Library Receiver deactivation issue (Ken Shirrif IR)

hey there, I'm using Ken Shirrif's famous IR interfacing library and its working great. (If you are not familiar with it here is the website)

This is a question to anyone who has previously used it before as i'm not seeming to get any response from the author or on the blog.

I'm basically trying to make two arduino boards communicate over IR and create an IR handshake.

So: 1. Arduino A sends. 2. Ardunio B receives, then replies. 3. Ardunio A receives.

The challenge i'm having is when I start the "irrecv.enableIRIn();" in setup and then I try:

irsend.sendSony(code, 12);

It's basically sending rubbish over the LED - except if I remove "irrecv.enableIRIn();" then it works perfectly.

What i'm basically looking for - is there a way to completely remove the affect of "irrecv.enableIRIn();" such as a "irrecv.disableIRIn();" so I can switch it off and get back to sending mode.

I have tried "irsend.enableIROut(38);" but it doesn't do anything to solve the issue.

I believe it may be something in the C coding of the actual library or something I don't know how to call to reverse its effects ( as I believe the sending and receiving functions use the same timer)

Thanks in advance to anyone who can help!

The library can not send and recieve IR codes at the same time.

So what you want is: Arduino A sends the message and then call "irrecv.enableIRIn()" Arduino B needs to call "irrecv.enableIRIn()" and then stop the reciever after the message has arrived and then send the reply.

The problem is, I don't know if the library has a "irrecv.disableIRIn()" command (I am pretty sure it doesn't). So I don't know how to turn the reciever off. Possibly worth emailing Ken.

Wow I didn't expect such a fast reply - Targettio you are 100% correct that is EXACTLY the situation I'm in. I've emailed Ken a few days ago but had no response yet - I wonder if I posted the EnableIRin code from the c code if with some help here If we could basically undo all the changes it is making and allocate the resources back for sending - so effectively make our own disabler?

Here is the code with the IRenabler function, are there are great coders out there who know how to remove the effects of this enableIRin function?

// initialization
void IRrecv::enableIRIn() {
  // setup pulse clock timer interrupt
  TCCR2A = 0;  // normal mode

  //Prescale /8 (16M/8 = 0.5 microseconds per tick)
  // Therefore, the timer interval can range from 0.5 to 128 microseconds
  // depending on the reset value (255 to 0)

  //Timer2 Overflow Interrupt Enable


  sei();  // enable interrupts

  // initialize state machine variables
  irparams.rcvstate = STATE_IDLE;
  irparams.rawlen = 0;

  // set pin modes
  pinMode(irparams.recvpin, INPUT);

The libraries link for more information

Unfortuantly modifying the library is beyond my skill but hopefully someone can help. It’s something I would be interested in as I want to make an ir repeater which would require receiving and. then sending.

I have had a little look into this, and 90% of it is going well over my head. But I think I know why it isn't possible to send and recieve at the same time.

Arudino has 3 timers (timer0, timer1 and timer2), each of which controls 2 PWM pins (to get 6 PWM pins). Ken has used pins 3 and 11 which are both on timer2. So the reciver and transmitter functions are interfering with each other (as they are both changing settings within timer2).

There maybe a way to write a 'turn off reciever' and 'turn off transmitter' functions that re-defaults the timers settings, but that is beyond me.

One other solution is to change either the reciever or transmitter to another pwm pin and therefore a different timer. This would require re-writing the library as it is currently all written around timer2. But as far as I understand, each of the 3 timers on the chip behave slightly differently, so it might not work on another timer.

Great work mate!

I've found this from Ken's Blog

"Ken Shirriff said... As some people mentioned above, the library uses timer2 so it will conflict with other software that uses timer2. Timer0 is used by the Arduino framework for millis() and delay(), so the library can't easily use timer0. Timer1 is a 16-bit timer, so it's not directly compatible with timer2. I'm looking into modifying the library to use timer1.

January 18, 2010 9:57 AM"

Heres another interesting post

Ken Shirriff said... TiStyle: running 30-50 independent receivers sounds like a lot! It sounds like an interesting project; do you want to give more details? To outline what you'd need to do to support multiple independent IR receivers... The code currently uses a single irparams global structure to keep track of the received code. The timer 2 interrupt code checks the status of the input pin and updates the irparams structure. You'd need a separate irparams structure for each pin. You could have an array of them, or maybe have irparams part of the IRrecv class. The array would make it easier for the interrupt handler, but putting it in the class would be architecturally cleaner. Then the interrupt code would need to loop through all of them, updating each one according to the input. Then the decoding routines would need to process a particular irparams structure, rather than the global one. I'm not sure how many inputs you could process before you'd run out of time in the interrupt handler.?

Maybe we should try something along the lines of this?

CaptainTuna said…
Hey guys. I modified the library a little, so that it can send IR in the background. Still have to test it out. Here is what i’ve done so far:

void IRsend::sendSony(unsigned long data, int nbits) {

if(irparams.bitstx == 0) { //if IDLE then transmit
irparams.timertx=0; //reset timer
irparams.resettx=48; //initial header pulse is 2400us long. 2400/50us ticks =

irparams.bitstx=nbits + 1; //bits left to transmit, including header
irparams.datatx=data << (32 - bitstx); //unsigned long is 32 bits. data gets

shifted so that the leftmost (MSB) will be the first of the 32.
irparams.spacetx = false;
TCCR2A |= _BV(COM2B1); // Enable pin 3 PWM output for transmission of header




if(irparams.bitstx != 0) { //if we have got something to transmit

if(irparams.timertx == irparams.resettx) { //if reset value is reached
if(irparams.spacetx){ //it was a space that has just been sent thus a

total “set” (bit + space) so…
irparams.spacetx = false; //we are not going to send a space now
irparams.bitstx = irparams.bitstx - 1; //we got 1 less bit to send
irparams.datatx <<= 1; //shift it so MSB becomes 1st digit
if(irparams.datatx & TOPBIT) {
irparams.resettx = 24;
TCCR2A |= _BV(COM2B1); //activate pin 3 PWM (MARK)
else {
irparams.resettx = 12;
TCCR2A &= ~(_BV(COM2B1)); //disable pin 3 PWM (SPACE)
else { //we sent the bit, now we have to “send” the space
irparams.spacetx = true; //we are sending a space
irparams.resettx = 12; //600us/50us = 12
TCCR2A &= ~(_BV(COM2B1));

…continues with the rest of the ISR routine.

this goes in the IRremoteInt.h

// information for the interrupt handler
typedef struct {
uint8_t recvpin; // pin for IR data from detector
uint8_t rcvstate; // state machine
uint8_t blinkflag; // TRUE to enable blinking of pin 13 on IR processing
unsigned int timer; // state timer, counts 50uS ticks.
unsigned int timertx; // timer for counting 50us ticks (Tx)
unsigned int resettx; // reset value for above timer (Tx)
unsigned int bitstx; // number of bits left to send (Tx)
unsigned long datatx; // data to be transmitted (Tx)
boolean spacetx // true if space has been sent (Tx)
unsigned int rawbuf[RAWBUF]; // raw data
uint8_t rawlen; // counter of entries in rawbuf

July 5, 2010 10:18 AM

ben said...
Awesome code, Ken. Thanks! 
I thought I would add my twist: I need to send IR to 2 different applicances (TV and cable set top box). So I need to send IR out on pin 3 (as you do) and another pin. This means of course using another timer (Timer 1 for me). 
My result is below for pin 9. It works, but it's hacked together and I would appreciate anyone improving it! 

void IRsend::enableIROutNine(int khz) {
TIMSK1 &= ~_BV(TOIE1); // clears the timer (Timer1) overflow interrupt enable bit

pinMode(9, OUTPUT); // New output pin nine
digitalWrite(9, LOW); // When not sending PWM, we want it low

// Alternative, hacked together from the arduino eg (
TCCR1A = _BV(WGM13) | _BV(WGM11) | _BV(WGM10);
TCCR1A = _BV(COM1A0); //start the timer 
TCCR1A &= ~(_BV(COM1A0)); // Disable pin 9 PWM output
TCCR1B = ( _BV(WGM12) | 1); //set the predivide, in this case 1 = 001 means no prescaling

OCR1A = SYSCLOCK / 2 / khz / 1000;
OCR1B = OCR1A / 3; // 33% duty cycle

void IRsend::markNine(int time) {
// Sends an IR mark for the specified number of microseconds.
// The mark output is modulated at the PWM frequency.
//TCCR2A |= _BV(COM2B1); // Enable pin 3 PWM output
TCCR1A |= _BV(COM1A0); // Enable pin 9 PWM output

/* Leave pin off for time (given in microseconds) */
void IRsend::spaceNine(int time) {
// Sends an IR space for the specified number of microseconds.
// A space is no output, so the PWM output is disabled.
//TCCR2A &= ~(_BV(COM2B1)); // Disable pin 3 PWM output
TCCR1A &= ~(_BV(COM1A0)); // Disable pin 9 PWM output

sorry about the intense amount of posts: but there is a word limit on the amount of code we can post.

I THINK i've found it!!

#define TOPBIT 0x80000000
int timertx=0;
int resettx=0;
int bitstx=0;
int elapsed=0;
unsigned long datatx=0;
boolean spacetx = false;

void setup(){
  //set PWM: FastPWM, OC2A as top, OC2B sets at bottom, clears on compare
  //COM2B1=1 sets PWM active on pin3, COM2B1=0 disables it
  pinMode(3, OUTPUT);
  pinMode(11, OUTPUT);
  TCCR2A = _BV(COM2A0) | _BV(WGM21) | _BV(WGM20);
  TCCR2B = _BV(WGM22) | _BV(CS21);
  OCR2A = 49;
  OCR2B = 24;
  TIMSK2 |= _BV(TOIE2);

void loop(){
  SonyIR(0xa90, 12);

boolean SonyIR(unsigned long data, int nbits) {
  if(bitstx == 0) { //if IDLE then transmit 
    timertx=0; //reset timer
    resettx=96; //initial header pulse is 2400us long. 2400/25us ticks = 96
    spacetx = false;  
    datatx=data << (32 - (nbits + 1)); //unsigned long is 32 bits. data gets   shifted so that the leftmost (MSB) will be the first of the 32.
    TCCR2A |= _BV(COM2B1); // Enable pin 3 PWM output for transmission of header
    bitstx=nbits + 1; //bits left to transmit, including header
    return true;
  else {
    return false;


  if(bitstx != 0) {  //if we have got something to transmit

    if(timertx >= resettx) {  //if reset value is reached
      if(spacetx){  //it was a space that has just been sent thus a total "set" (bit + space) so..  
        spacetx = false; //we are not going to send a space now  
        bitstx = bitstx - 1;  //we got 1 less bit to send
        datatx <<= 1;  //shift it so MSB becomes 1st digit
        TCCR2A |= _BV(COM2B1);  //activate pin 3 PWM (ONE)
          if((datatx & TOPBIT)&&(bitstx != 0)) {  
            resettx = 48;
          else if(!(datatx & TOPBIT)&&(bitstx != 0)){
            resettx = 24;
            TCCR2A &= ~(_BV(COM2B1));  //deactivate pin 3 PWM (ONE)
      else {  //we sent the bit, now we have to "send" the space
        spacetx = true;  //we are sending a space
        resettx = 24; //600us/25us = 24
        TCCR2A &= ~(_BV(COM2B1));

This is from:

Try it out - i will probably this weekend when I get some time - flat out this week

I was looking at the lazer tag example you found and was confused as that guy hasn't made any reall changes so I looked at the examples and I am not sure how I missed this, but it seems you can send and recieve in the same sketch.

Checkout IRrecord.pde, it is an example within the library and basically it records an IR code and when you press a button it replays that code.

The IRrecv class performs the decoding, and is initialized with enableIRIn(). The decode() method is called to see if a code has been received; if so, it returns a nonzero value and puts the results into the decode_results structure. (For details of this structure, see the examples/IRrecvDump sketch.) Once a code has been decoded, the resume() method must be called to resume receiving codes. Note that decode() does not block; the sketch can perform other operations while waiting for a code because the codes are received by an interrupt routine.

Re-reading that, IRrecv basically turns itself off after receiveing a code, and will only restart when Resume or enableIRIn is called.

So going back to your original problem: * On Arduino A you need send the message and then enable the IR in. * On Arduino B you need to enable the IR in at the begining of the sketch but without calling resume. Then send the reply.

Bare in mindthat the code isn't blocking so you need to include some short delays after sending a message before restarting the reciever

I hear you and my code already performs that same function.

Arduino A sends a code- then enablesIRin to hear If a code has been sent back. Then it loops and sends again - it's that when it loops the code being sent now is garbled and non decipherable by Arduino B. I understand the EnableIRin must always be called after irsend but I think the fact they both use the same timer causes some serious issues. I might try one of these methods ASAP

Targettio did this solve your problem? I still haven't had an opportunity to test it as I've been focused on other projects

I gave up on my IR project for a long time, but decided to have another look yesterday and found:,50728.msg366980.html#msg366980

It seems, for some reason you can't do what you want (or what I want), at least not with the newest version of the library.

That's a real annoying pain aye!

I've decided to change the direction of how I wanted to solve this problem now, which isn't ideal, but basically it involves only one way communication which the library supports to reduce complexity

Least then I'll be sure it works! And the hardware requirement can also be halved.

Thanks for your research mate - to those who read this in the future it's still questionable if it's possible, perhaps the answer lies in the previously referenced links.

I had another stab at this over the weekend and managed to get the original library (linked on the blog) to send and receive from the same sketch, so I started using that but soon found it was missing some features (like hash decoding for raw codes and less protocols).

So I started taking features from the newest library and adding it to the old version (checking that it would still send AND receive after each change) and then uploaded it onto git:

I believe it is either the support for extra boards, the multiple receivers or ability to use different timers that breaks the sending and receiving, so I haven't added any of them yet. But will mess around with it some more (as I would like to use it on a mega2560).

hey Targettio nice one!

I've just been flat out and its taken till now to put the circuit back together to try out your library.

I was soo excited!! :D and it works!!! its amaaaazing!!!!!!! cheers mate! Now to finish this project haha

Have you thought of using something other than IR remote control protocols? Could you hook your IR receiver to a serial input?

I have loads of remotes all with volume control but only one of them actually can change the volume of my home theatre (the amp remote). So I wanted to make a device that would receive the volume commands from all my remotes and send a volume command to the amp. So I needed to be able to send and receive commands.

I also have a ethernet net shield as a secondary interface (so I can control my HT stuff from my computer/phone).

Omg! Targettio thank you so much, your modified library is amazing! :smiley: :smiley: