IR Remote Controller Library - Interrupt based rather than polled

IR Remote controllers for Arduino are super cheap and quite useful. Unfortunately all the libraries I've seen used polling, which makes them tough to use in a project. So, I wrote an interrupt driven IR remote library. This makes it really easy to have your project doing all sorts of activities and still be able to receive IR remote controls. It uses PCINT, so the IR controller can be on any interrupt handling pin (including support for PCINT on Mega 2560). You can download the lib from here: http://www.zbotic.com/index.php/download/

Note that zipfile includes other libraries - for just the remote control, only unzip IRController, Device, and PCInterrupt. Also, this has codes for one type of remote - you will likely have to replace the codes with your remote's codes.

Sample usage

#include "PCInterrupt.h"
#include "Device.h"
#include "irController.h"

IRController irController; 

// Note: modify myHardware.h in libraries\device and add change IR_PIN to the value of the pin you have your IR controller on.
void setup()
{
  Serial.begin(9600);
  Serial.println("Started");

   int res = irController.begin(IR_PIN, OTHER_DEVICE);
   if (res != SUCCESS) {Serial.println("error="); Serial.println(res);}
}

void loop(){
  int val = irController.read(); // Returns negative value if no new command rcvd
  if (val >0) Serial.println(val);
  delay(500);
}

awesome! thanks for this.

What IR code types does it understand?

For example RC-6? Panasonic?

I'll have to check it out!

This is the one I used (no idea what type it is) IR_Kit_SKU_DFR0107_-DFRobot

I think/hope that it's just a matter of changing the key mapping section for other remotes (shown below).

//! Decode specific remote-control keys - override this with routine for your Remote
int IRController::decode(int rawCmd)
{
    switch (rawCmd)
    {
    case 32640:  // turns on/off power
        return(POWER_BUTTON);
        break;
    case 32385:  // FUNC/STOP
        return(FUNC_BUTTON);
        break;
    case 32130:  // |<<
        return(BACK_BUTTON);
        break;
    case 32002:  // >||
        return(PLAY_BUTTON);
        break;
    case 31875:  // >>|
        return(FORWARD_BUTTON);
        break;
    case 32512:  // VOL+
        return(VLMUP_BUTTON);
        break;
    case 31492:  // VOL-
        return(VLMDOWN_BUTTON);
        break;
    case 31620:  // v scroll down
        return(DOWN_BUTTON);
        break;
    case 31365:  // ^ scroll up
        return(UP_BUTTON);
        break;
    case 30982:  // EQ
        return(EQ_BUTTON);
        break;
    case 30855:  // ST/REPT
        return(REP_BUTTON);
        break;
    case 31110:  // 0
        return(0);
        break;
    case 30600:  // 1
        return(1);
        break;
    case 30472:  // 2
        return(2);
        break;
    case 30345:  // 3
        return(3);
        break;
    case 30090:  // 4
        return(4);
        break;
    case 29962:  // 5
        return(5);
        break;
    case 29835:  // 6
        return(6);
        break;
    case 29580:  // 7
        return(7);
        break;
    case 29452:  // 8
        return(8);
        break;
    case 29325:  // 9
        return(9);
        break;
    default:
        errorCode = ERROR_UNKNOWN_RSP;
        return(key);  // Set errorCode code but return unrecognized raw key
        break;
    }
}

It supports NEC protocol remotes. If you need other protocols, let me know.

Using:
Arduino 1.0
ATMega328P
Pin2
Infrared Remote
Infrared Receiver
IRController Library
Devices Library
PCInterrupt Library

So I'm trying to use this library, but I can only get one keypress and then it won't receive any more. I modified the example code loop function to this:

void loop(){
  int val = irController.read(); 
  if (val == 0) Serial.println(val);
}

The output comes out like this on the Serial Monitor

Started
IRController: Pin=2 Success
[0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: ]
0
0
[2080: 1] [2084: 1] [1156: 0] [1108: 0] [1104: 0] [2108: 1] [1132: 0] [1108: 0] [2108: 1] [1104: 0] [1132: 0] [2108: 1] [1108: 0] [1104: 0] [1080: 0] [0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: ]
2
[2108: 1] [2080: 1] [2080: 1] [1160: 0] [1104: 0] [1108: 0] [2108: 1] [1132: 0] [1104: 0] [2108: 1] [1108: 0] [1132: 0] [2108: 1] [1104: 0] [1108: 0] [1080: 0] [0: 0: 1080: 0] [2160: 1] [2160: 1] [2184: 1] [1108: 0] [1052: 0] [1080: 0] [1160: 0] [1080: 0] [2160: 1] [2160: 1] [2184: 1] [1100: 0] [1060: 0] []
3588

After one keypress I can keep smashing buttons but nothing new will come in on the Serial Monitor.

I've tried with this code: http://www.sparkfun.com/datasheets/Components/General/Cheapo_IR_Control.pde
And it works fine, except that I can't use that code in my project because I need it to run in real-time.

Any ideas?

I have fixed the problem you reported. You can get the fix with v1.3 at http://www.zbotic.com/index.php/download/

Nice, Thanks!

Hi guys, I am getting a weird result in the Serial Monitor when receiving remote commands. On each button press, Raw Val is a different number! Also the Bits rcvd field seems to retain the bits long after I let go of the button. Is that supposed to happen? I'm reading over ircontroller.cpp but haven't quite understood it all yet. Thanks for any suggestions you have!

Here's the debug output:

Started
** IRController v1.3
     using pin=2
     Interrupt attached
Bits rcvd=2
Bits rcvd=2
Bits rcvd=2
Bits rcvd=2
Bits rcvd=2
Bits rcvd=9
Bits rcvd=18
Bits rcvd=28
Bits rcvd=33
Raw Val=16513
Unable to map.  Update IRMapping.h with the raw val above.
Bits rcvd=33
Raw Val=23077
Unable to map.  Update IRMapping.h with the raw val above.
Bits rcvd=39
Bits rcvd=2
Bits rcvd=2
Bits rcvd=2
Bits rcvd=2
Bits rcvd=5
Bits rcvd=13
Bits rcvd=24
Bits rcvd=33
Raw Val=259
Unable to map.  Update IRMapping.h with the raw val above.
Bits rcvd=30
Raw Val=23077
Unable to map.  Update IRMapping.h with the raw val above.
Bits rcvd=31
Raw Val=30568
Unable to map.  Update IRMapping.h with the raw val above.
Bits rcvd=9
Bits rcvd=11
Bits rcvd=20
Bits rcvd=32
Raw Val=1799
Unable to map.  Update IRMapping.h with the raw val above.
Bits rcvd=31
Raw Val=24480
Unable to map.  Update IRMapping.h with the raw val above.
Bits rcvd=33
Raw Val=20617
Unable to map.  Update IRMapping.h with the raw val above.
Bits rcvd=18
Bits rcvd=18
Bits rcvd=18
Bits rcvd=18
Bits rcvd=18
Bits rcvd=18
Bits rcvd=18

Doesn't seem to work for me neither.

The Ken Shirriff's library (A Multi-Protocol Infrared Remote Library for the Arduino) can decode my apple remote (NEC protocol) perfect. But here I'll get different values all the time (like capsid in the previous post).

I would like to try this one since it supports interrupts, but something seems to be broken.

When I try to compile IRRControllerTest code, I get these messages:

IRControllerTest.cpp:3:26: error: IRController.h: No such file or directory
IRControllerTest:7: error: 'IRController' does not name a type
IRControllerTest.cpp: In function 'void setup()':
IRControllerTest:11: error: 'controller' was not declared in this scope
IRControllerTest.cpp: In function 'void loop()':
IRControllerTest:19: error: 'controller' was not declared in this scope

How can I fix these problems?

This was exactly what I needed. Thanks so much!

I have the same problems, as well. The interrupt handling seems to be broken, it just polls an interrupt for every 2-3 touch. Beside that, it returns a random code, regardless of the pressed key.

Does this library work? i would like to try it but the download link seems to be broken, anyone know where else i can download it?