Thursday, 31 January 2013

Web-based IR Remote on the Raspberry Pi

There are many devices that use infrared remote controls - TV's, DVD players, cameras, power sockets. So getting a Raspberry Pi to be able to send remote control signals opens up many possibilities for projects. Combining the GPIO pins with a web server on the Raspberry Pi means that we can create a web UI to control these devices.

Installing LIRC on the Raspberry Pi

One of the great things about running a Linux operating system on the Raspberry Pi is that it provides access to a wealth of software projects that can run on the device. One of these is the Linux Infrared Remote Control (LIRC) project that provides a way of receiving and transmitting IR signals from many remote controls. LIRC provides a method of recording signals from a remote control and storing them in a configuration file, so that they can be sent directly from the Raspberry Pi.

Installing LIRC on the Raspberry Pi needs the latest firmware to be on the Raspberry Pi. One of the clearest guides I've found on the process of updating your firmware and installing LIRC is on Alex Bain's site. That walks you through the process of installing LIRC and getting the initial configuration done.

IR Receiver and Transceiver Circuits

Once LIRC is set up, we need to set up an infrared receiver and transmitter circuit.

IR Receiver

The receiver circuit is the simplest to set up. I've used a TSOP382, but check the data sheet for your IR receiver as the pins for ground and Vcc are sometimes the other way round. If you connect those pins incorrectly you could fry the IR receiver. Also, note that I'm connecting the Vcc pin to 3.3V as the TSOP382 works fine on that voltage.

The Adafruit site has a great walkthrough of testing and using an IR receiver.

IR Transmitter

The IR transmitter circuit is a bit more complex as the current output from the Raspberry Pi GPIO pins will only give you a very weak signal from the IR transmitter LED. If you search on the Internet you'll find a number of different circuits that you can use to amplify the signal so that you can get a few meters distance of signal from your IR LED.

I'm sure sure what the IR LED I've used as I rescued it from a Sony DVD remote control. In terms of the components to use for the circuit, you'll find a number of options. I used the components that I had available (Q1=BC547 transistor, R1=220ohm, R2=omitted as I didn't have a low enough resistor). Though I haven't measured the range of the signal, it works fine from 4m away from the devices.


Web-Controlled Remote

Once LIRC is setup and you can configured at least one remote, sending commands to through the IR LED is as simple as:
 #                device command  
 irsend SEND_ONCE Humax  KEY_POWER  

Of course, we don't want limit people to controlling the TV by ssh-ing into the Raspberry Pi to change the channel. So we need a web-based UI that people can access through a computer, tablet or smart phone. I got my 11-year old son to work on a design using Inkscape so that I'd have an SVG image that I could use as the web interface on an HTML5 web page. After a few iterations on the design, we came up with this:

The advantage of using an SVG file is that it will scale naturally with the device that it is viewed one, so should work well on a smartphone's 4-inch screen as well as on a 20-inch monitor.

Flask Web Application

The web application has been written using the Flask micro-framework, similar to my previous post. This time, the application reads the LIRC config file (/etc/lirc/lircd.conf) and gets the names of the devices that have been configured, and presents them to the user.
The web page uses JQuery Mobile to make it look good on smaller devices. Once the user selects the relevant device, the remote control is shown and the user can press a button on the touchscreen to operate the remote. Each button is configured to send a different operation e.g. pressing V+ will send KEY_VOLUMEUP. As we've seen previously, LIRC's irsend command only needs the device name and the operation command code to send the signal to the LED. With Flask, this can be done in less than 50 lines of code:
 #!/usr/bin/env python  
   
 from lirc.lirc import Lirc  
 from flask import Flask  
 from flask import render_template  
 from flask import request, redirect, url_for  
   
 BASE_URL = ''  
   
 app = Flask(__name__)  
   
 # Initialise the Lirc config parser  
 lircParse = Lirc('/etc/lirc/lircd.conf')  
   
   
 @app.route("/")  
 @app.route("/<device>")  
 def index(device=None):  
   # Get the devices from the config file  
   devices = []  
   for dev in lircParse.devices():  
     d = {  
       'id': dev,  
       'name': dev,  
     }  
     devices.append(d)  
     
   return render_template('remote.html', devices=devices)  
   
 @app.route("/device/<device_id>")  
 def device(device_id=None):  
   d = {'id':device_id}      
   return render_template('control.html', d=d)  
   
   
 @app.route("/device/<device_id>/clicked/<op>")  
 def clicked(device_id=None, op=None):  
   # Send message to Lirc to control the IR  
   lircParse.send_once(device_id, op)  
     
   return ""  
   
   
 if __name__ == "__main__":  
   app.debug = True  
   app.run('0.0.0.0')  
   

The only complexity that we come across of parsing the LIRC config file to get the names of the devices. Unfortunately, they have not used a standard format like YAML for their config file, so the parser may run into problems if you add comments on the same line as your commands. However, sending the command to LIRC is straightforward using a shell command to irsend:
 from subprocess import call  
   
 ...  
   
 def send_once(self, device_id, message):  
      """  
      Send single call to IR LED.  
      """  
      call(['irsend', 'SEND_ONCE', device_id, message])  
   

The full code is available on GitHub: https://github.com/slimjim777/web-irsend.


28 comments:

  1. This is great! I just completed a very similar project using NodeJS instead of Python. Here's how I solved it:

    http://alexba.in/blog/2013/02/23/controlling-lirc-from-the-web/

    ReplyDelete
    Replies
    1. NodeJS sounds a really interesting solution as well. Thanks for your post on setting up Lirc.

      Delete
  2. Hi James-
    Where are you getting the import lirc.lirc module from? I've tried pip and apt-get and continue to get "no module named" errors.

    ReplyDelete
  3. You need to update the Raspberry Pi firmware to the tip release. There is a tool to do this: https://github.com/Hexxeh/rpi-update

    ReplyDelete
  4. Hi James,
    I can't find TSOP382 in india could you please suggest me how to use IRM2638 instead of TSOP382.

    Thanks.

    ReplyDelete
  5. Awesome how-to blog. Now if only someone can create more hours in the day... or maybe make them go slower somehow so I can finish these projects!

    ReplyDelete
  6. NB: The pinouts of the IR receivers vary from model to model, so confirm th epinout before wiring.

    FYI........

    For anyone interested in IR protocols - we have just launched a Crowdfunding campaign on IndieGoGo for AnalysIR - IR Decoder & Analyzer (Arduino & Raspberry Pi). Currently we support 17 IR protocols and are looking for more to add as part of the campaign. Suggestions Welcome!

    You can find out more about the Campaign on http://bit.ly/1b7oZXH or Screenshot via www.AnalysIR.com

    ReplyDelete
  7. The Datasheets for many IR receivers call for a 0.1 uf capacitor to be connected between the Vcc and ground pins of the module. Often you can get away without this, but sometimes it is necessary to put one into the circuit to get good IR reception. So it is a good idea to use this capacitor to insure proper operation

    ReplyDelete
  8. Nice tutorial. I was able to get the transmitter circuit working. Waiting on the mail for IR receiver to try. Can you give some pointers on how you convert the svg file to html? I was able to use your remote interface but there are just not enough buttons map even the "mandatory" buttons for my cable dvr.

    ReplyDelete
    Replies
    1. Take a look at the source HTML that has the SVG code embedded: https://github.com/slimjim777/web-irsend/blob/master/templates/control.html

      The main thing to note is the 'onclick' event: onclick="clickedOp('{{ d.id }}','KEY_LEFT');"

      The onclick event sends the LIRC code (KEY_LEFT) to the IR transmitter. So you can simply replace the SVG file with a table with images or links and have a similar 'onclick' event.

      Delete
  9. The location of my AV Amp and TV makes it impracticable to find a position for an IR Transmitter that can see both at the same time - would it possible to connect two IR LEDs to the same cable (like you can with one wire temperature sensors) and simply stick them in front of the IR receivers on the TV and AV Amp)? I'm currently using an Iguana IR transceiver and it's having trouble communicating with them unless I put it right in the middle of the floor!

    If you can would any of the transistors be needed (as the required range would be ~1 cm)?

    If only I hadn't had a clear out and got rid of the old remote controls :(

    ReplyDelete
    Replies
    1. That should be possible. I'm not an electronics expert, so can't really advise on the best setup for the circuitry. I imagine that the best approach would be to use two transistors, but you may be able to get away with using just one (especially if you are looking at using a short transmission distance).

      Delete
  10. Hi James,

    I have a problem with irsend.
    I'm using raspbmc, on that lirc is being installed
    and I'm able to receive InfraRed Signals and save them into the lircd.conf with irrecord.

    The testing tool irw also shows me the content (e.g. ... KEY_POWER2 ...) of the lircd.conf by pressing the button of my remote control.

    Sending the command "irsend SEND_START FB KEY_POWER2" the infrared-diode remains off. But no errors occured. I tried also to control it manually with 'echo "1" > /sys/class/gpio/gpio24/value' and the diode turned constantly on.

    My /etc/lirc/hardware.conf:

    # /etc/lirc/hardware.conf
    #
    # Arguments which will be used when launching lircd
    LIRCD_ARGS="--uinput" # I set both, --uinput and --listen.

    #Don't start lircmd even if there seems to be a good config file
    #START_LIRCMD=false

    #Don't start irexec, even if a good config file seems to exist.
    #START_IREXEC=false

    #Try to load appropriate kernel modules
    LOAD_MODULES=true

    # Run "lircd --driver=help" for a list of supported drivers.
    DRIVER="default"

    # usually /dev/lirc0 is the correct setting for systems using udev
    DEVICE="/dev/lirc0"
    MODULES="lirc_rpi"

    # Default configuration files for your hardware if any
    LIRCD_CONF=""
    LIRCMD_CONF=""

    I also set lirc_rpi gpio_in_pin=18 gpio_out_pin=24

    Does anyone has a solution or idea for me?

    Tanks.

    ReplyDelete
  11. James, I'm working on something similar, and I just wanted to be clear on something. When you replied to a previous post about the"from lirc.lirc import Lirc" line, you said to update the firmware. I've gotten LIRC running and have used a Git-Hub module python3-lirc to interface with with python (but without an IRsend command). With just the base LIRC install (and dependencies) and updated firmware, should I be able to import lirc into python3?

    ReplyDelete
    Replies
    1. Not necessarily - that is probably a Python 3 wrapper for the command line application, lirc. You need to make sure that you have lirc installed:

      sudo apt-get install lirc

      If that command cannot find the lirc package, then you'll need to make sure that you have updated the firmware

      Delete
  12. Hi James,

    I have a problem with irsend.
    I'm using raspbmc, on that lirc is being installed
    and I'm able to receive InfraRed Signals and save them into the lircd.conf with irrecord.

    The testing tool irw also shows me the content (e.g. ... KEY_POWER2 ...) of the lircd.conf by pressing the button of my remote control.

    Sending the command "irsend SEND_START FB KEY_POWER2" the infrared-diode remains off. But no errors occured. I tried also to control it manually with 'echo "1" > /sys/class/gpio/gpio24/value' and the diode turned constantly on.

    My /etc/lirc/hardware.conf:

    # /etc/lirc/hardware.conf
    #
    # Arguments which will be used when launching lircd
    LIRCD_ARGS="--uinput" # I set both, --uinput and --listen.

    #Don't start lircmd even if there seems to be a good config file
    #START_LIRCMD=false

    #Don't start irexec, even if a good config file seems to exist.
    #START_IREXEC=false

    #Try to load appropriate kernel modules
    LOAD_MODULES=true

    # Run "lircd --driver=help" for a list of supported drivers.
    DRIVER="default"

    # usually /dev/lirc0 is the correct setting for systems using udev
    DEVICE="/dev/lirc0"
    MODULES="lirc_rpi"

    # Default configuration files for your hardware if any
    LIRCD_CONF=""
    LIRCMD_CONF=""

    I also set lirc_rpi gpio_in_pin=18 gpio_out_pin=24

    Does anyone has a solution or idea for me?

    Tanks.

    ReplyDelete
    Replies
    1. I think that pin 18 is the PCM_CLK, by default - that could be the issue. Try using different pins. I used the following setup:

      lirc_rpi gpio_in_pin=23 gpio_out_pin=22


      Delete
  13. What r2 value would you suggest?

    ReplyDelete
  14. hi, how can i install web-irsend ????

    ReplyDelete
    Replies
    1. Just download the files and copy them over to the Raspberry Pi using ssh. You should be able to google for tutorials on copying files over ssh.

      Delete
  15. hi, i am not an expert in this area.

    I have a device with infrared support. i would like to know is there any way to generate or fetch or see the configuration file. Or I should ask manufacturer to share conf file.

    If I know the conf file then I can execute those commands. Please correct me if am not correct.

    Also could you please share sample code(preferably in Java) to send a command and read the response.

    Thanks in advance.

    ReplyDelete
  16. You can use lirc to record the signals from a IR transmitter - see the irrecord command (http://www.lirc.org/html/irrecord.html).

    ReplyDelete
  17. Iv installed the necessary packages of lirc for python. Instead of sending a pulse from the cmd, i cannot figure out the syntax or program itself to run it as a code. pls help me out

    ReplyDelete
  18. Hi,
    I'm trying to write simple IR receiver code using pylirc in python but the function " Pylirc.nextcode(1)" always returns None !! What can i do ?

    PS: I made a test and everything is good, the terminal and the shell in python can detect the pressed button.

    ReplyDelete
  19. I'm working on something similar foto payudara , and I just wanted to be clear on something. When you replied to a previous post about the"from lirc.lirc import Lirc" line, you said to update the firmware. I've gotten LIRC running and have used a Git-Hub module python3-lirc to interface with with python (but without an IRsend command). With just the base LIRC install (and dependencies) and updated firmware, should I be able to import lirc into python3?

    ReplyDelete
  20. Hi,
    thank you for sharing this helpful code.

    I am trying to customise the remote control image for each remote, i.e. different remotes have different buttons :)
    I modified remote.py with the code below, it will try to load a control_.html and if it does not finds it then the default control.html is used. This works for me, I appreciate your opinion.


    @app.route("/device/")
    def device(device_id=None):
    d = {'id':device_id}
    try:
    return render_template('control_' + device_id + '.html', d=d)
    except:
    return render_template('control.html', d=d)

    ReplyDelete
  21. hello james,
    Great tutorial i'm going to try this this weekend

    can you please tell the ideal value for R2 resistor ?

    ReplyDelete
  22. Need some help. I understand that we can use RPi as a universal remote. The quesiton i am having is, if you need to control devices in your home, you would setup RPi in one place and need to control all the devices from there. Whereas, one of the requirement is to have the IR Transmitter to be close to the electric gadget.

    How we could achieve to have the RPi installed in one central place and have all devices get the IR Transmitter to control the electric equipment.

    ReplyDelete