Introduction: Arduino IR Receiver Control Computer

About: I'm an embedded ICT student.

In this tutorial I'm going to explain how to use an arduino as IR receiver, how to connect it to a computer and how to activate functions with the IR remote.

I'll also connect 3 LED's for showing the status of CAPS LOCK, NUM LOCK and SCROLL LOCK.

Let's get started!

Step 1: Parts

For this tutorial you'll need several parts.

This is the part list:

- An arduino (I have this one. It works perfect, was fast shipped and is half the price of the official one)

- An IR receiver and remote control (I had one laying around, but you can pick one you like)

- Three led's (I had them on the same PCB as the IR receiver, but all led's should do)

- Three 220 ohm resistors for the led's

- A few jumper wires

- A breadboard

Step 2: Circuit

Now we are going to connect everything to the arduino.

So first connect the IR receiver.
Negative connection to ground, positive connection to 5V and signal to pin 2. I've used pin 2 because we'll need this pin for an interrupt.

Now connect the LED's to the arduino. The red LED is connected to pin 22, the green LED is connected to pin 23 and the yellow LED is connected to pin 24.

Step 3: Arduino Sketch

No we'll look at the code which is running on the arduino. I've commented as much as possible, but if you don't understand a thing please let me know in the comments.

What this code does:

Read the IR receiver and send it over serial connection to the PC.

Read the serial connection from the PC and change the LED's.

uint8_t situation = 0; // 3 > 1 or 0 received | 2 > Repeat previous code
uint8_t START = 0;     // Detect if the transmission is started
uint8_t x = 0;
uint8_t BIT = 0;       // Which bit is send (1/0)
uint8_t Id = 0;        // What's the remote ID
uint8_t Id_inv = 0;
uint8_t Data = 0;      // Which key is pressed on the remote
uint8_t Data_back = 0; // Backup of the key for repeat
uint8_t Data_inv = 0;
uint8_t Repeat = 0;    // pass first repeat

/* Variables for the pulse measurement */
uint16_t Time_old = 0;
uint16_t Time = 0;
uint16_t TimeDelta = 0;

/* Data received from the computer */
/* 1 > Caps lock changed           */
/* 2 > Num lock changed            */
/* 3 > Scroll lock changed         */
uint8_t incomingByte = 0;

/* LED pins */
#define caps 24
#define numl 22
#define scrl 23
 
void setup(void) {
  /* Interrupt for reading the IR code */
  attachInterrupt(0, IR_Read, FALLING);

  /* Serial connection to the computer software */
  Serial.begin(9600);

  /* Led pins as output */
  pinMode(caps, OUTPUT);
  pinMode(numl, OUTPUT);
  pinMode(scrl, OUTPUT);

  /* Led's out */
  digitalWrite(caps, LOW);
  digitalWrite(numl, LOW);
  digitalWrite(scrl, LOW);
  
}
 
void loop(void) {
  /* If something from the computer is received */
  if (Serial.available() > 0) {

    /* Read the incomming data */
    incomingByte = Serial.read();
    switch(incomingByte){
      case 1:  /* If 1 */
        /* Caps Lock led on/off > off/on */
        digitalWrite(caps, !digitalRead(caps));
        break;
      case 2:  /* If 2 */
        /* Num Lock led on/off > off/on */
        digitalWrite(numl, !digitalRead(numl));
        break;
      case 3:  /* If 3 */
        /* Scroll Lock led on/off > off/on */
        digitalWrite(scrl, !digitalRead(scrl));
        break;
      default:
        break;
    }
  }
}

/* Function for reading the IR receiver using interrupts */
/* YOU DON'T NEED TO CHANGE ANYTHING HERE */
void IR_Read(void) {
  Time = micros();
  if (Time_old != 0) {
    TimeDelta = Time - Time_old;
    if ((TimeDelta > 12000)&&(TimeDelta < 14000)) {
      START = 1;
      x = 0;
      situation = 1;
      Id = 0;
      Id_inv = 0;
      Data = 0;
      Data_inv = 0;
    } else if ((TimeDelta > 10000)&&(TimeDelta < 12000)) {
      situation = 2; // repeat
    } else if ((TimeDelta > 1500)&&(TimeDelta < 2500)) {
      situation = 3; //"1"
      BIT = 1;
    } else if ((TimeDelta > 1000)&&(TimeDelta < 1500)) {
      situation = 3; //"0"
      BIT = 0;
    } else situation = 5; 
    if (situation == 3) {
      if (x < 8) {
        Id |= BIT;
        if (x < 7) Id <<= 1;  
        x++;
      } else if (x < 16) {
        Id_inv |= BIT;
        if (x < 15) Id_inv <<= 1;
        x++;
      } else if (x < 24) {
        Data |= BIT;
        if (x < 23) Data <<= 1;
        x++;
      } else if (x < 32) {
        Data_inv |= BIT;
        if (x < 31) {
          Data_inv <<= 1;
        } else {
          Serial.println(Data);
          Data_back = Data;
          Repeat = 0;
        }
        x++;
      }
    } else if (situation == 2) {
      if(Repeat == 1) {
        /* Send received data to the computer */
        Serial.println(Data_back);
      } else {
        Repeat = 1;
      }
    }
  }
  Time_old = Time;
}

Step 4: Python Code on PC

On the PC I'll use python to receive the commands from the arduino and translate it to key-presses.

On your PC you'll need to install python 2.7, the win32 library and the pySerial library.

Recieve.pyw

I'm using the .pyw extension, so it's running in the background.

import serial  #The library for communicating with the arduino
import serial.tools.list_ports  #The library for finding the arduino on the PC

import os
import thread  #The library multiple processes on the same time
from time import sleep  #The library for delays

# Libraries for simulating key-presses and getting th status of functions
from win32gui import *	
from win32api import *
from win32con import *

#The config file you'll make for your remote
from config_ir import *

#The name of the arduino you like to connect
name = "Arduino Mega 2560"

#Get the port the arduino is connected to
ports = list(serial.tools.list_ports.comports())
for p in ports:
    if(p[1][:len(name)] == name):
        port = p[0]

#Connect to the arduino
ser = serial.Serial(port, 9600)

#function to get the lock key's and send if they change
def lock():
	caps_old = 0
	numl_old = 0
	scrl_old = 0
	
	sleep(1)
	
	while 1:
		caps = GetKeyState(VK_CAPITAL) & 0x0001
		numl = GetKeyState(VK_NUMLOCK) & 0x0001
		scrl = GetKeyState(VK_SCROLL) & 0x0001
		
		if(caps != caps_old):
			ser.write(chr(1))
		caps_old = caps

		if(numl != numl_old):
			ser.write(chr(2))
		numl_old = numl
			
		if(scrl != scrl_old):
			ser.write(chr(3))
		scrl_old = scrl
		sleep(0.1)

#Function for reading the remote data and bind it to a key-press		
def read_serial():
	while 1:
		data = 0
		#get the data
		data = int(ser.readline())
		
		#Determine which key it was and what it should do
		if(data == int(Mute)):
			keybd_event(VK_VOLUME_MUTE, 0,0,0) #Mute
		elif(data == int(Vol_up)):
			keybd_event(VK_VOLUME_UP, 0,0,0) #Vol +
		elif(data == int(Vol_down)):
			keybd_event(VK_VOLUME_DOWN, 0,0,0) #Vol -
		elif(data == int(Back)):
			keybd_event(VK_BROWSER_BACK, 0,0,0) #Back
		elif(data == int(Play)):
			keybd_event(VK_MEDIA_PLAY_PAUSE, 0,0,0) #Play/Pause
		elif(data == int(My_media)):
			os.system('start C:\Users\Laurens\Videos') #My Media
		elif(data == int(Up)):
			keybd_event(VK_UP, 0,0,0) #Up
		elif(data == int(Right)):
			keybd_event(VK_RIGHT, 0,0,0) #Right
		elif(data == int(Down)):
			keybd_event(VK_DOWN, 0,0,0) #Down
		elif(data == int(Left)):
			keybd_event(VK_LEFT, 0,0,0) #Left
		elif(data == int(OK)):
			keybd_event(VK_RETURN, 0,0,0) #OK
		else:
			pass

#Main loop
try:
	#Start multiple threads
	thread.start_new_thread(lock,())
	thread.start_new_thread(read_serial,())
except:
	print "treading not working"

#Do nothing
while 1:
	pass

IR_codes.py

In this file you need to change the "button" array to all the buttons you want. After you've done that you just need to run this script.

! Attention !

When pressing a key you need to press short, otherwise it'll take the same command for the next key name.

import serial  #Communication library
import serial.tools.list_ports

inp = []

print "Starting connection"

#Device to connect to
name = "Arduino Mega 2560"

ports = list(serial.tools.list_ports.comports())
for p in ports:
    if(p[1][:len(name)] == name):
        port = p[0]

ser = serial.Serial(port, 9600)

#The buttons you like to map in the software. 
#Add or remove the key's you want, but THEY MAY NOT CONTAIN SPACES!
button = ["Power", "Mute", "Vol_up", "Vol_down", "ch_up", "ch_down", "OK", "Up", "Down", "Left", "Right", "Back", "Play", "Home", "My_media", "Rewind", "Forward", "Next", "Previous", "Stop", "Exit", "Info", "TV_guide"]

#Insert every button
for i in range(0, len(button)):
	inp.append(0)
	print "Press the %(button)s button" % {"button": button[i]}
	inp[i] = ser.readline().replace('\n', '').replace('\r', '')

print ""	

ser.close()
config = open("config_ir.py", 'w')

#write the buttons to the config file
for i in range(0,len(button)):
	line = button[i] + "= '" + inp[i] + "'"
	print line
	config.write(line)
	config.write("\n")

config.close()
#wait for enter
raw_input()
If you have any questions feel free to ask.

Step 5: Resume

In this instructables I showed you how to connect an IR remote to an Arduino and how to communicate between a PC and an Arduino. I also showed you how to simulate key-presses using python and win32.

For all functions of win32api I would like to redirect you here.

If you have any questions feel free to ask and I will see if I can answer them.

If you have recommendations or something you would like to see done, please let me know in the comments or by Private Message.

Laurens