Tuesday, 12 November 2013

Raspberry Pi IR blaster and Roomba IR codes

When I finally bought an iRobot vacuum cleaner, I went for the Roomba 620 which is the current entry model. This version doesn't come with any accessories like the "Virtual Walls" (infrared barriers), an infrared remote control, or handy features like scheduling.

However, all of the above ought in principle to be possible by transmitting infrared (IR) signals from a DIY circuit... or a Raspberry Pi? For example, with older model Roombas people have used LIRC and an IR Blaster to tell their Roomba to start cleaning by mimicking the remote control - with the computer handling the scheduling.

Raspberry Pi Infrared Blaster,
using a P2N2222A NPN transistor,
and two IR LEDs in series with 3.3V

Roomba InfraRed Signals

iRobot sell simple IR remote controls which cover the basic commands (like start cleaning) and even let you steer it. The IR codes are emitted at 940nm using a form of pulse-width modulation (PWM), modulated with a carrier frequency around 38KHz. Each code consists of a sequence of eight bits, encoded as:
  • Bit 0 - 1ms on, 3 ms off
  • Bit 1 - 3ms on, 1 ms off
and terminated with ~4ms off. That means in total the code and the pause is about 36ms. The IR control codes are published in the iRobot Create Open Interface v2 (PDF), and see also my last blog post on recording the Roomba IR codes.

Raspberry Pi IR Blaster

I recently setup an infrared receiver in my Raspberry Pi, but this time I need to hook up an infrared LED under GPIO control. And if you want to mimic a Roomba docking station, you would need three separate independently controllable IR LEDs.

According to the source code (see original pull request and the lirc_rpi homepage), the default Raspberry Pi LIRC settings use GPIO18 (pin 12) for input and GPIO17 (pin 11) for output:

/* set the default GPIO input pin */
static int gpio_in_pin = 18;
/* set the default GPIO output pin */
static int gpio_out_pin = 17;

So, to make life simple, I used GPIO17 (pin 11) to connect my IR transmitter. Since I didn't have any resistors handy I improvised and uses two IR LEDs in series and the 3.3V supply (pushing the LEDs a little over the rating but it works for now in my solder-free test rig).

LIRC Codes

Some kind soul posted a LIRC configuration for the Roomba Remote Control (dated Oct 2007), with codes for clean, spot, max, power, and pause. Here's a cut down version showing just the clean button (the most important button).

# Excerpt from a config file which was automatically generated
# using lirc-0.8.2(default) on Sun Oct  7 19:28:15 2007
#
# brand:                       iRobot
# model no. of remote control: Standard Roomba Remote
# devices being controlled by this remote: Roomba Discovery/400 Series
#

begin remote

  name   iRobot_Roomba
  flags RAW_CODES|CONST_LENGTH
  eps            30
  aeps          100

  ptrail          0
  repeat     0     0
  gap    91790

      begin raw_codes

          name clean
             2831     886     972    2709     944    2711
              943    2710    2743     893     958    2723
              931    2722     927   19304    2811     897
              954    2726     927    2726     927    2726
             2747     889     966    2714     942    2710
              941

      end raw_codes

end remote

The LIRC Configuration File Format Technical Details tells us these numbers are in micro-seconds, so we'd expect to see patterns of 3000 (3ms) and 1000 (1ms) but what was measured were on average ~2740 and ~930 instead. Was the calibration slightly off?

We expect each code to send eight bits, each either 3ms on 1ms off or the other way round (then an off pause) which would be 15 numbers (16 if you include the final off). However, all the button recordings had 31 numbers so clearly this captured double signals - with a gap of about 19000 (or 19ms) in between.

$ sudo mv /etc/lirc/lircd.conf /etc/lirc/lircd_original.conf
$ wget http://lirc.sourceforge.net/remotes/irobot/Roomba
$ sudo mv Rooma /etc/lirc/lircd.conf
$ sudo modprobe lirc_rpi
$ sudo /etc/init.d/lirc start
[ ok ] Loading LIRC modules:.
[ ok ] Starting remote control daemon(s) : LIRC :.
$ irsend LIST "" ""
irsend: iRobot_Roomba

$ irsend send_once iRobot_Roomba CLEAN
(watch flash via IR camera!)

A single send didn't work. Four or five (in a quick loop) do. Range 4m+ (although harder to get the line of sight).

Generating a configuration file

Using this Python script I generated a complete set of Roomba IR codes for LIRC, based on the above example entry and the documented codes:

$ python make_roomba_lirc.py > Roomba_LIRC.conf
$ sudo cp Roomba_LIRC.conf /etc/lirc/lircd.conf
$ sudo /etc/init.d/lirc restart
[ ok ] Stopping remote control daemon(s): LIRC:.
[ ok ] Loading LIRC modules:.
[ ok ] Starting remote control daemon(s) : LIRC :.
$ irsend list iRobot_Roomba ""
irsend: 0000000000000001 left
irsend: 0000000000000002 forward
irsend: 0000000000000003 right
irsend: 0000000000000004 spot
irsend: 0000000000000005 maxdock
irsend: 0000000000000006 small
irsend: 0000000000000007 medium
irsend: 0000000000000008 largeclean
irsend: 0000000000000009 pause
irsend: 000000000000000a power
irsend: 000000000000000b forwardleft
irsend: 000000000000000c forwardright
irsend: 000000000000000d stop
irsend: 000000000000000e sendall
irsend: 000000000000000f seekdock
irsend: 0000000000000010 virtualwall

It isn't very easy, but pairs of commands like this worked to drive the Roomba:

$ irsend send_start iRobot_Roomba forward
$ irsend send_stop iRobot_Roomba ""
$ irsend send_start iRobot_Roomba forwardright
$ irsend send_stop iRobot_Roomba ""
$ irsend send_start iRobot_Roomba right
$ irsend send_stop iRobot_Roomba ""
$ irsend send_start iRobot_Roomba stop
$ irsend send_stop iRobot_Roomba ""

I can see why people have hooked this up to web interfaces to control their Roombas.

Anyway, with a careful positioning, and a cron job, I could use the Raspberry Pi IR blaster to automatically trigger the Roomba to clean the house on a rota. It would be an expensive way to do it, but I think the Raspberry Pi could also mimic a Roomba Virtual Wall as well.

5 comments:

  1. Kudos.
    Great work. Thank you.
    Although single signal did not work for me, sending it twice did the job.
    $ irsend send_once iRobot_Roomba seekdock -# 2

    ReplyDelete
  2. Hi,
    Thank you for a wonderful research, I was thinking to control my 760 using PI + Wifi. Possible for these commands above to integrate via HTTP. My idea to get simple web to control my 760. Cheers.


    ReplyDelete
  3. Thanks so much for such great work :) I am just about to buy a roomba 616 which is an updated model of the 620. Does the 620 receive IR commands out of the box? Where is the IR receiver located? I've read that people have but Irobot remotes and not been able to use them on these entry level roombas. Any info would be great as I need to research it more as I can't afford the higher end roombas so scheduling with my pi is a must! Thanks :)

    ReplyDelete
    Replies
    1. I assume the Roomba remote signals are detected using same IR sensor as used to detect the home base electrical charging point. There have been changes in the IR codes between different generations of the Roomba product line, so that might explain why some remotes wouldn't work?

      Having had the Roomba a year and a half, having it on a schedule where it cleans the house when we're out would require we be much more vigilant about keeping the floor clear of anything it might damage or get stuck on. Still, that might be a good thing ;)

      Delete
  4. Hi
    Please help me. I try to manage iroomba 770
    my file is :

    begin remote

    name myremote
    flags RAW_CODES|CONST_LENGTH
    eps 30
    aeps 100
    ptrail 0
    repeat 0 0
    gap 91790

    begin raw_codes

    name BTN_9
    3026 1022 996 3024 971 3023
    972 3022 2950 1026 992 3027
    968 3027 968 21157 3032 1023
    996 3024 973 3022 971 3023
    2950 1025 992 3029 965 3029
    968 21158 3029 1026 993 3028
    967 3027 967 3028 2954 1021
    998 3023 972 3022 975 21154
    3033 1018 1000 3021 966 3029
    964 3030 2954 1022 994 3026
    969 3026 971 21406 3024 1030
    999 3022 963 3031 964 3031
    2951 1024 995 3026 969 3026
    969 21157 3033 1022 997 3025
    970 3023 972 3023 2951 1024
    992 3028 967 3029 966

    end raw_codes

    end remote

    The IR LED works because i can manage my TV

    Unfortunatly nothing move
    Regards

    ReplyDelete