Release 2017.10.8 / Update 2018.5.26

Using IR Remote

Previously, I tried to control DSLR’s shutter with IR. This time, I’m going to use “IR Remote” library which is available on Arduino IDE. This library is very useful and easy.

I used to make IR pulse by myself, but I don’t have to do that if I use this library. You can get IR binary from consumer electronics easily and send any IR commands.

Preparation

Electronic parts

  • Arduino
  • Infrared receiver module
  • Infrared LED & Resistance
  • home electronics remote control
  • tact switch × 2
  • Normal LED & Resistance — if you have

I recommend you to use 3.3V arduino because most of IR LED is works on lower voltage than 5V. But, several site uses 5V arduino unintentionally and it doesn’t seem to be a problem. So you may check its work with 5V if you don’t care that it may destroy those parts.

This set need to be a pair if you want to try the last sample sketch.

The “home electronics remote control” on this article is Sony’s Blu-ray player remote control.

I used IR receiver module ‘GP1UXC41QS‘ and ‘OSRB38C9AA‘. But there are no big differences in pins between similar modules, I think.

On this part’s data seat, they recommend to use 47 ohm resistor and 47μF capacitor. Make it check your own.

Wiring

The resistance value of the LED may not be proper. Sorry.
  • D03 pin : IR LED
  • D07 pin : tact switch
  • D11 pin : IR Reciever
  • D13 pin : normal LED

There are three pins, VCC, GND, and signals on receiver module. Please be aware that the pin arrangement differs depending on the object.

On the “IR Remote” example sketches, D11 pin is used for infrared signal reception and D3 pin is for infrared transmission (PWM). So this wiring is followed it.

Also, normal LED isn’t needed if you can satisfy with LED(D13) on Arduino board.

Using “IR Remote”

The most easy way to learn IR remote is to use its example sketches.

Monitoring received IR data

Checking data of home electronics remote control is very easy with IR remote. Just open example “IRrecvDump”.

‘File’ menu → ‘example’ → ‘IRremote’ → ‘IRrecvDump’

Open the serial monitor (9600 kbps), press the button on the home appliance remote control, then the data will be acquired and displayed.

First line is the actual data (HEX notation). The next line is name of the manufacturer of the remote control. IR Remote will identify the manufacturer name somehow from the contents of the data.

The infrared transmission format has differences on concrete method with different manufacturer although it has standard rules in a part. You can learn the difference on here.

And the last line means duration of each binary. In short, these are times of IR signal inversion from last one.

Functions of “IR Remote”

Explains its functions with example ‘IRrecvDump’. Check here for more detail.

IRrecv ~(pin number);

Create an object to use for reception. In this example, ‘irrecv’ is the name of object, and ‘pin number’ is digital pin number on arduino.

int RECV_PIN = 11;

IRrecv irrecv(RECV_PIN);

~.enableIRIn();

Starting infrared reception by interrupt with created object.

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
}

decode_results ~~;

Making object which to contains received IR data.

decode_results results;

The received data is stored in this created “results”. There are multiple pieces of information in it, you can specify and obtain arbitrary information.

name explanation
decode_type name of manufacturer
value command code (received byte data)
bits Number of bits of command code (received byte data)
rawbuf[] Array of times (μsec) for every infrared changing on or off.
rawlen size of the ‘rawbuf[]’ array.

You can easily get command code. For example,

long recv_data = results.value;

By the way, the name of manufacturer are defined. You can see the characters by the ‘KEYWORD’ file which is in library folder.

~.decode(&~~);

This function confirms whether it has been received. It returns ‘true’ when IR data is received, and ‘false’ is “not received”. It is same as “serial.available” of serial communication.

void loop() {
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    dump(&results);
    irrecv.resume(); // Receive the next value
  }
}

~.resume();

It reset the return value of “.decode ()”. If you don’t use this function after received IR data, you can’t catch next data.

void loop() {
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    dump(&results);
    irrecv.resume(); // Receive the next value
  }
}

Remember that “.decode()” and “.resume()” are a pair.

Then, I write a sketch with these functions from the beginning.

#include <IRremote.h>

IRrecv irrecv(11);
decode_results results;

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

void loop() {
  if (irrecv.decode(&results)) {
    if (results.decode_type == SONY) Serial.print("It's SONY!  ");
    Serial.println(results.value, HEX);
    irrecv.resume();
  }
}

Change code section of “SONY” for your situation.

Sometimes you may catch several data by one push. Solve the problem by setting ‘delay()’ before ‘.resume()’.

“decode_type” reference: numbers and its string

value character string
-1 UNKNOWN
0 UNUSED (estimation)
1 RC5
2 RC6
3 NEC
4 SONY
5 PANASONIC
6 JVC
7 SAMSUNG (estimation)
8 WHYNTER
9 AIWA_RC_T501
10 LG
11 SANYO (estimation)
12 MITSUBISHI (estimation)
13 DISH (estimation)
14 SHARP (estimation)
15 DENON (estimation)
16 PRONTO (estimation)
17 LEGO_PF (estimation)

Send Infrared data

Just make a object if you want to send IR data.

IRsend irsend;

However, you have to use different functions for each manufacturer.

irsend.sendNEC(data, bits)
irsend.sendSony(data, bits)
irsend.sendRC5(data, bits)
irsend.sendRC6(data, bits)

irsend.sendJVC(data, bits, repeat)
irsend.sendPanasonic(pre data, data)

irsend.sendRaw(data buf, length, hertz)

‘data’ is actual command code, and ‘bits’ are the size of the ‘data’.

Then I write a sample sketch that can read and transmit arbitrary data. Please change the line of “.send” according to your own manufacturer.

#include <IRremote.h>

#define SW  7
#define LED 13

IRrecv irrecv(11);
IRsend irsend;
decode_results results;

long cache_data;
byte cache_bits;
#define PUSH_SHORT 100

void setup()
{
  Serial.begin(9600);
  pinMode(SW, INPUT_PULLUP);
  pinMode(LED, OUTPUT);
  irrecv.enableIRIn();
}

void loop() {

  // capture IR signal
  if (irrecv.decode(&results))
  {
    // set values from IR
    cache_bits = results.bits;
    cache_data = results.value;

    // serial monitoring
    Serial.print("Memorized! ");
    SPRI();

    // LED flicker for check
    for (byte i = 0 ; i < 5 ; i++)
    {
      digitalWrite(LED, i % 2);
      delay(100);
    }

    // ready to next IR recieve
    irrecv.resume();
  }


  //----- pushed switch task -----

  int gauge;

  while (digitalRead(SW) == 0)
  {
    digitalWrite(LED, HIGH);
    gauge++;
  }

  // send IR data if switch is pushed
  if (gauge > PUSH_SHORT)
  {
    irsend.sendSony(cache_data, cache_bits);
    Serial.print("SEND! ");
    SPRI();
    irrecv.enableIRIn();  // restart IR recieve
  }
  digitalWrite(LED, LOW);
}


// Serial monitor display

void SPRI() {
  Serial.print("/ BITS:");
  Serial.print(cache_bits);
  Serial.print("  DATA:0x");
  Serial.print(cache_data, HEX);
  Serial.println();
}

This sketch keeps IR data to “cash_” and flashes LED of 13 pin when infrared data is received. Then, pressing the tact switch, IR LED will transmit the signal. You can check the command code values on serial monitor as well.

The most important thing is that ‘.enableIRIn();’ function is called after ‘.send’ function. This is because “enableRIn” has been stop by using “send”. You have to remember this if you want to use “receive” and “send” in a sketch.

Well, does it works? Directionality of IR LED is very narrow. So try several times by changing direction and distance. I had lost a lot of time to success of transmission.

Wireless communication

This is what most I wanted to mention. I mean,

You can make Arduino to wireless easily and in cheap by “IR remote”.

Although there are some problem in distance and direction at IR, it make it to instant wireless by few dollars.

So I write a sample sketch which get and send code by “IR Remote”.

Wiring

  • D03 pin : IR LED
  • D06 pin : tact switch 2
  • D07 pin : tact switch 1
  • D11 pin : IR Reciever
  • D13 pin : normal LED

Just add another tact switch from previous wiring. Prepare this system by two.

Sketch “IR Controller”

Received data is cached during push of each tact switch. Then it sends the command code by normal pushing.

Change code section of “SONY” for your situation.

#include <IRremote.h>

#define SW_1 6
#define SW_2 7
#define LED  13

IRrecv irrecv(11);
IRsend irsend;
decode_results results;

#define SW_SIZE 2
byte sw_pins [SW_SIZE] = {SW_1, SW_2};
long cache_data [SW_SIZE];
byte cache_bits [SW_SIZE];
#define PUSH_SHORT 100


void setup()
{
  Serial.begin(9600);
  for (byte i = 0 ; i < SW_SIZE; i++) pinMode(sw_pins[i], INPUT_PULLUP);
  pinMode(LED, OUTPUT);
  irrecv.enableIRIn();
  Serial.println("This is IR Controller!");
}


void loop() {

  // ----- send IR data if you pushed switches -----
  for (byte i = 0 ; i < SW_SIZE ; i++)
  {
    if (FUNC_SW(i) == true)
    {
      irsend.sendSony(cache_data[i], cache_bits[i]);

      Serial.print("SEND SW:");
      Serial.print(i + 1);
      Serial.print("! ");
      SPRI(i);
      delay(40);
      irrecv.enableIRIn();  // restart IR recieve function
    }
    digitalWrite(LED, LOW);
  }

  // -----  task for each recieving -----

  if (irrecv.decode(&results))
  {

    // --- Switch 1 reaction

    if (cache_data[0] == results.value)
    {
      Serial.print("Recieved! SW:1 ");
      SPRI(0);
      LED_FLICKER(20, 100);


      // --- Switch 2 reaction

    } else if (cache_data[1] == results.value) {
      Serial.print("Recieved! SW:2 ");
      SPRI(1);
      LED_FLICKER(10, 400);


      // --- non assigned switch reaction

    } else {
      Serial.print("no Assigned! ");
      Serial.print("/ BITS:");
      Serial.print(results.bits);
      Serial.print("  DATA:0x");
      Serial.println(results.value, HEX);
    }

    irrecv.resume();
    digitalWrite(LED, LOW);
  }
}


boolean FUNC_SW(byte pins) {
  int  gauge;
  bool pushed = true;

  while (digitalRead(sw_pins[pins]) == 0)
  {
    digitalWrite(LED, HIGH);
    if (pushed == true) gauge++;

    // capture IR signal
    if (irrecv.decode(&results))
    {
      // set values from IR
      cache_bits[pins] = results.bits;
      cache_data[pins] = results.value;

      // serial monitoring
      Serial.print("Memorized to SW:");
      Serial.print(pins + 1);
      Serial.print("! ");
      SPRI(pins);

      LED_FLICKER(5, 100);

      // ready to next IR recieve
      irrecv.resume();
      pushed = false;
      gauge  = 0;
    }
  }

  if (gauge < PUSH_SHORT) pushed = false;
  digitalWrite(LED, LOW);

  return pushed;
}


// LED flicker for check

void LED_FLICKER(byte times, short dur) {
  for (byte i = 1 ; i <= times ; i++)
  {
    digitalWrite(LED, i % 2);
    delay(dur);
  }
  digitalWrite(LED, LOW);
}


// Serial monitor display

void SPRI(byte pins) {
  Serial.print("/ BITS:");
  Serial.print(cache_bits[pins]);
  Serial.print("  DATA:0x");
  Serial.print(cache_data[pins], HEX);
  Serial.println();
}

On this sample, difference of each switch is just a variation of LED flash. But you can change it by rewrite section of “Switch 1~2 reaction”. And more, you will be able to send even values if you make the same rules in advance within both Arduino.

If there is a chance next time, I would like to make “Radio control car” by IR.

reference links

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA


This site uses Akismet to reduce spam. Learn how your comment data is processed.