DEV Community

Cover image for Arduino: How to Process Infrared Signals from a Remote Control
Sebastian
Sebastian

Posted on

Arduino: How to Process Infrared Signals from a Remote Control

Infrared remote controls are ubiquitous: TVs, IOT devices, toys. With an Arduino and an IR receiver, it is a matter of minutes to setup receiving IR commands and process them to control your Arduino application.

This blog posts show you the essential steps to process any IR commands from one of your remotes.

This article originally appeared at my blog admantium.com.

Setup

The Hardware requirements for this project are minimal:

  • Arduino Uno or variant
  • IR Remote Receiver Module
  • Any remote

To connect the devices, follow these instructions. To identify the right pins, see also Arduino Pin Layout.

  • Connect IR sensor Y Pin to any Arduino analog pin
  • Connect IR sensor R Pin to Arduino 5V power out
  • Connect IR sensor G Pin to any Arduino ground pin

Library Choice

Following my guideline, I checked the available libraries. For a basic ATmega328P Arduino Uno, the best library is Arduino-IRremote. It’s in active development, has good documentation, and you can find useful examples. I installed the library using the platform IO package manager.

Once installed, the first step is to identify the concrete protocol your remote uses.

Identify the Protocol

From the official example sketch, create the following program:

#include <Arduino.h>
#include <IRremote.h>

#define IR_PIN 3;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);

  Serial.begin(9600);   
  IrReceiver.begin(IR_PIN, ENABLE_LED_FEEDBACK);
}

void loop() {
  if (IrReceiver.decode()) {  
    IrReceiver.printIRResultShort(&Serial);
    Serial.println();
    IrReceiver.printIRResultAsCVariables(&Serial);
  }
  IrReceiver.resume();
}
Enter fullscreen mode Exit fullscreen mode

Then, upload the program, connect to the serial monitor and press some keys on your remote. You should see output like this:

Protocol=NEC Address=0x4 Command=0x11 Raw-Data=0xEE11FB04 32 bits LSB first

uint16_t address = 0x4;
uint16_t command = 0x11;
uint32_t data = 0xEE11FB04;
Enter fullscreen mode Exit fullscreen mode

In rare cases, the signal might not get processed correctly. In this case, try another remote control.

Receive and Process IR Commands

When you know the protocol, it’s time to create the real program. Start your source code file with the following statements, and be sure to define the protocol before including the Header file.

#define DECODE_NEC 1
#include <IRremote.h>

int IR_RECEIVE_PIN = 11;
Enter fullscreen mode Exit fullscreen mode

In the setup() part of your program, you initialize the IrReceiver event.

IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN);
Enter fullscreen mode Exit fullscreen mode

In the loop part, you wait for the IrReceiver.decode() interrupt to happen. Then, you can access the received data with type IRData. Its definition is this:

struct IRData {
    decode_type_t protocol;     ///< UNKNOWN, NEC, SONY, RC5, ...
    uint16_t address;           ///< Decoded address
    uint16_t command;           ///< Decoded command
    uint16_t extra;             ///< Used by MagiQuest and for Kaseikyo unknown vendor ID
    uint8_t numberOfBits; ///< Number of bits received for data (address + command + parity) - to determine protocol length if different length are possible (currently only Sony).
    uint8_t flags;              ///< See definitions above
    uint32_t decodedRawData;    ///< up to 32 bit decoded raw data, formerly used for send functions.
    irparams_struct *rawDataPtr; /// pointer of the raw timing data to be decoded
};
Enter fullscreen mode Exit fullscreen mode

To print out the relevant data, use this:

void loop() {
  if (IrReceiver.decode()) {
    Serial.print("COMMAND is ");
    Serial.println(IrReceiver.decodedIRData.command);
    Serial.print("ADDRESS is ");
    Serial.println(IrReceiver.decodedIRData.address);
    Serial.print("RAW DATA is ");
    Serial.println(IrReceiver.decodedIRData.decodedRawData);

    IrReceiver.resume();
  }
}
Enter fullscreen mode Exit fullscreen mode

You are almost done. Upload this program to your Arduino, then send commands from the remote. The output of the program will be similar to this:

COMMAND is 18
ADDRESS is 4
RAW DATA is 3977444100
COMMAND is 64
ADDRESS is 4
RAW DATA is 3208706820
Enter fullscreen mode Exit fullscreen mode

Now, use this program to test each key of the remote, and make a note of their command ID. For example, in the above example, the COMMAND 18 is recognized when I press the key 2, and the COMMAND 64 is the arrow up button.

Defining Application Logic

The final part is easy. Inside the loop() method, use IrReceiver.decode() to check if new IR commands were received:

void loop() {
   if (IrReceiver.decode()) {
    // handle cases
  }
}
Enter fullscreen mode Exit fullscreen mode

Inside the method body, you define the custom logic that is triggered. I suggest to use a switch statement that determines the currently pressed key, and then to handle each case with a dedicated case statements. The basic structure is as follows. Important: At the end of the statement, be sure to call IrReceiver.resume() in order to listen for new key events.

  switch (IrReceiver.decodedIRData.command) {
    case (17): {
      // handle key 17
      break;
    }
    case (18): {
     // handle key 18
      break;
    }
    IrReceiver.resume();
}
Enter fullscreen mode Exit fullscreen mode

In my case, I detect the various numbers of the remote control to print them on a screen. And I also process direction commands that are used to move a wheeled vehicle.

void processIR() {
  switch (IrReceiver.decodedIRData.command) {
    case (17): {
      printCharOnMatrix('1');
      break;
    }
    case (18): {
      printCharOnMatrix('2');
      break;
    }
    case (19): {
      printCharOnMatrix('3');
      break;
    }
    // ....
    default : {
      printCharOnMatrix('@');
      break;
    }
  } 
    IrReceiver.resume();
}
Enter fullscreen mode Exit fullscreen mode

Optimization

By default, all IR vendor protocol - see complete list of protocols - will be compiled into your program. If you know the exact protocol, just include this with a preprocessor directive like shown here:

#define DECODE_NEC 1

#include <Arduino.h>
#include <IRemote.h>
Enter fullscreen mode Exit fullscreen mode

And for fine tuning, there are many compile options activated by preprocessors definitions, see the official documentation.

Conclusion

Thanks to the excellent Arduino-IRremote library, parsing IR commands can be setup in minutes. This article showed you how to setup the library and start a program to sample the commands of your remote. We then saw how to implement custom control logic for each of the IR commands. Finally, I gave you some hints how to optimize the overall program by including only the required IR protocols.

Top comments (0)