1 Introduction
2 Logging
3 Exceptions
exn:  fail:  roomba
exn:  fail:  roomba:  io
exn:  fail:  roomba:  mode
exn:  fail:  roomba:  unsupported
4 Protocols
roomba-protocol?
roomba-sci
roomba-roi
roomba-coi
5 Models
decode-roomba-manufacturing-code
roomba-model?
make-roomba-model
current-number-to-roomba-model-hash
current-default-roomba-model
6 Roomba Object
roomba?
get-roomba-name
current-roomba
7 Opening and Closing
current-default-roomba-device
open-roomba
close-roomba
with-roomba
8 Modes
roomba-mode?
get-roomba-mode
set-roomba-mode
9 Stock Behaviors
9.1 Cleaning
start-roomba-spot-clean
start-roomba-clean
start-roomba-max-clean
9.2 Docking
start-roomba-seek-dock
9.3 Demos
start-roomba-demo
stop-roomba-demo
10 Driving
set-roomba-drive
set-roomba-wheels
11 Motors
set-roomba-motors
12 Lights
set-roomba-leds
13 Sound
roomba-song-language?
roomba-song-number?
compiled-roomba-song?
compile-roomba-song
store-song-on-roomba
play-song-on-roomba
14 Sensors
read-roomba-sensors
14.1 Sensor Packets
14.2 Sensor Utilities
roomba-infrared-byte->name
15 Cargo Bay Connector
set-roomba-digital-outputs
set-roomba-pwm-low-side-drivers
send-roomba-ir-byte
16 Cables
17 Association List Primer
18 Troubleshooting
19 Known Issues
20 History
21 Legal
1:4

roomba: iRobot Roomba/Create Interface for Racket

Neil Van Dyke

 (require (planet neil/roomba:1:4))

1 Introduction

This package implements a Racket interface for controlling many models of the iRobot Roomba robot vacuum cleaner, and the iRobot Create educational/hobby robot platform. This package currently runs on GNU/Linux and possibly on Apple Mac OS X.
One reason to control a Roomba using Racket is constructionist learning opportunities for children. Another reason is various hobby projects, getting the robot hardware to do useful or amusing things other than clean one’s floor, perhaps as a small piece of something much bigger. Another reason is the principle among engineer-types that it is good to be able to modify, experiment with, and improve things that you own.
Using this package requires first using a special cable or hardware interface to connect the computer running your Racket program with the Roomba. (If you don’t already have such a cable or hardware interface, see section Cables of this document.) This package implements the protocol that is used over that hardware connection. You then write your program using the definitions provided by this package.
Obligatory Cautions: Roomba hacking is not without risks; please don’t sue us. Also, this package is not produced by iRobot Corp.; please don’t bother them about this package.

2 Logging

This package sends logging messages to the Racket logger, naming the messages as “roomba”. This includes debug level messages for each use of most of this package’s API. You can see these messages in the usual Racket ways, such as by using the -W argument to the command-line racket program, or via the DrRacket Log window.

3 Exceptions

struct

(struct exn:fail:roomba exn:fail (roomba))

  roomba : roomba?
Supertype for exceptions related to the Roomba.

struct

(struct exn:fail:roomba:io exn:fail:roomba ())

Exception due to I/O problem with communication link with the Roomba.

struct

(struct exn:fail:roomba:mode exn:fail:roomba (expected actual))

  expected : (listof symbol?)
  actual : symbol?
Exception due to attempting to use a command on the Roomba when it is not believed to be in the proper mode for that command.

struct

(struct exn:fail:roomba:unsupported exn:fail:roomba ())

Exception due to attempting an operation not supported on this particular Roomba. For example, attempting start-roomba-demo on a Roomba 400 rather than on an iRobot Create.

4 Protocols

This package supports a few different Roomba protocols.

procedure

(roomba-protocol? any/c)  boolean?

  any/c : x
Predicate for a roomba-protocol object.

value

roomba-sci : roomba-protocol?

SCI, the protocol used by the Roomba second generation, especially the 400 series, described by iRobot Roomba Serial Command Interface (SCI) Specification, dated 2005.
Note that not all second generation Roombas shipped with firmware that supports SCI, but reportedly all of them can be upgraded with 2.1 firmware. If the Roomba was not manufactured after October 2005, then search the Web for “roomba firmware update” for your particular model number. The update process will likely involve an iRobot OSMO dongle, or using the iRobot Scheduler Remote with a special cable). If you need help determining the model number or manufacturing date, see section Models of this document.

value

roomba-roi : roomba-protocol?

ROI, the protocol used by the Roomba 500 and 600 series, described by iRobot Roomba 500 Open Interface (OI) Specification.

value

roomba-coi : roomba-protocol?

COI, the protocol used by the iRobot Create, described by iRobot Create Open Interface (OI) Specification.
Note that we say “roomba” even though it’s for a Create rather than a Roomba, due to the identifier naming convention of this package. And also, as Billy Joel might put it, to the tune of “Always a Woman”:

It can talk with a beep, it has wall-sensing eyes
It can ruin your day with low-batt’ry surprise
But it brings out the best that your programs can be
Oh, it doesn’t clean floors, but it’s always a Roomba to me

5 Models

A model refers to a particular manufactured model of Roomba or similar robot, such as the iRobot Create. This package defines a number of specific Roomba models, and you can also define your own.
If you don’t know which model of Roomba you have, or you need to know the manufacturing date, look for the serial number barcode label on the Roomba or the box. Given a serial number label like, for example, “JEN 04000 090620 08 00999”, the model number is given by the “04000”, and the date is in the second group of digits: year 2009 (09 + 2000), month 06, day of month 20. The decode-roomba-manufacturing-code procedure can do this for you.
As suggested in section Protocols, this package works with most Roombas from the second generation, 500 series, and 600 series, as well as with the Create.
This package does not presently work on the Roomba 700 series, since iRobot has not documented the protocol for that series, unlike for the 400, 500, and Create. However, a 700 user reported that it seems to provide a serial protocol similar to SCI, ROI, and COI, but somewhat different, in a non-backward-compatible way. So, given access to a 700, the protocol might not be too hard to understand and support in a future version of this package. Realistically, someone who can afford a 700 series can probably also afford a $50 used 400 for hobby purposes, so 700 support seems a low priority. All that said, the author of this package welcomes expensive gifts at any time of year.
Note that this package does not work on iRobot Scooba, even though the Scooba looks similar to a Roomba and has a mini-DIN connector, since the Scooba reportedly uses a different protocol than the Roombas and the Create. The Scooba’s protocol might not even be for control, but only for firmware updating. The main reason we imagine for controlling a Scooba from Racket would be to make a robot puppy that uses the Scooba’s liquid bladder.

procedure

(decode-roomba-manufacturing-code str)

  (listof (cons/c symbol? any/c))
  str : string?
Decodes a manufacturing code from a barcode label found on the Roomba and its box, returning the information as a human-readable alist. For example:

> (decode-roomba-manufacturing-code "JEN041100610060012345")

  '((manufacturer . jetta)
    (status       . new)
    (model        . 4110)
    (date         . #(2006 10 6))
    (rev          . 0)
    (serial       . 12345))
The decoding is based on information from a 2006-12-29 robotreviews.com post by newmom.

procedure

(roomba-model? x)  boolean?

  x : any/c
Predicate for a Roomba model.

procedure

(make-roomba-model #:number number    
  #:generation generation    
  #:protocol protocol)  roomba-model?
  number : (or/c exact-nonnegative-integer? symbol?)
  generation : (or/c #f 1 2 3 4)
  protocol : roomba-protocol?
Make a new roomba-model object, for situations in which this package does not already provide an appropriate pre-defined object. (Perhaps you will also email the author/maintainer of this package, so that the model can be added for everyone else.)

parameter

(current-number-to-roomba-model-hash)

  
(hash/c (or/c exact-nonnegative-integer? symbol?)
        roomba-model?)
(current-number-to-roomba-model-hash hasheqv)  void?
  hasheqv : 
(hash/c (or/c exact-nonnegative-integer? symbol?)
        roomba-model?)
Parameter for a hash that maps Roomba model numbers to roomba-model objects. By default, it is populated with the following model numbers:
  • Second Generation — 'second-generation 1100 'series-4000 'series-400 4000 400 4100 410 4105 416 4110 'sagelike-4130 'discolike-4130 4150 4170 4188 4210 4220 4225 4230 4260

  • 500 Series — 'series-500 510 530 532 535 550 560 562 564 570 571 572 580 581

  • 600 Series — 'series-600 610 620 630 650 660

  • Create — 'create 4400 4418

Note that some second generations need a firmware update before they’ll work with this package. See the documentation for roomba-sci.
The list of model numbers is mostly based on the “List of models” section of the Wikipedia page on Roomba.

parameter

(current-default-roomba-model)

  (or/c roomba-model? exact-nonnegative-integer? symbol?)
(current-default-roomba-model model)  void?
  model : (or/c roomba-model? exact-nonnegative-integer? symbol?)
Parameter for the default roomba-model, which is used by open-roomba, with-roomba, and perhaps other procedures and syntax. The default value of this is 'create, meaning the iRobot Create platform in general. You might wish to change this parameter to something else, like 'second-generation or an exact model number.

6 Roomba Object

There is a roomba object that represents a connection to the robot. This can be an explicit argument to each operation on the robot, but there is also a current-roomba Racket parameter that is the default robot when it is not given as an argument.

procedure

(roomba? x)  boolean?

  x : any/c
Predicate for the roomba object.

procedure

(get-roomba-name [#:roomba roomba])  roomba-name?

  roomba : roomba? = (current-roomba)
Returns the current name of the roomba, as supplied by the optional #:name argument to a procedure like open-roomba.

parameter

(current-roomba)  roomba?

(current-roomba roomba)  void?
  roomba : roomba?
Parameter for the roomba that is the default for command procedures. This parameter is usually set automatically by open-roomba, but can also be set manually, like a normal Racket parameter.

7 Opening and Closing

parameter

(current-default-roomba-device)  path-string?

(current-default-roomba-device path)  void?
  path : path-string?
Parameter that is the default device, which is normally a special operating system device file for the serial port device through which the Roomba is accessed. This parameter defaults to a value like "/dev/ttyUSB0", depending on the Racket platform.

procedure

(open-roomba [#:name name    
  #:model model    
  #:device device    
  #:set-current? set-current?])  roomba
  name : (or/c #f string?) = #f
  model : (or/c roomba-model? exact-nonnegative-integer? symbol?)
   = (current-roomba-default-model)
  device : path-string? = (current-default-roomba-device)
  set-current? : boolean? = #true
Opens a connection to a Roomba, and returns an object for the connection. If set-current? is true, then current-roomba is also set to the object.

procedure

(close-roomba [#:roomba roomba])  void?

  roomba : roomba? = (current-roomba)
Closes the connection to the Roomba, if not already closed. Changes the mode to 'closed.

syntax

(with-roomba maybe-name
             maybe-model
             maybe-device
             body ...+)
 
maybe-name = 
  | #:name string?
     
maybe-model = 
  | 
#:model (or/c roomba-model?
              exact-nonnegative-integer?
              symbol?)
     
maybe-device = 
  | #:device string?
This is a convenience for calling open-roomba and close-roomba. In most cases, close-roomba will be called even if the body is exited due to an exception.

8 Modes

A Roomba mode is a general operating mode of the Roomba. The modes are identified in this package by a symbol:
  • 'off Powered off or sleeping, and you probably need to manually press a button to wake it up.

  • 'passive Sensors can be read, but cannot be controlled in this mode.

  • 'safe Can be controlled. Lift and cliff sensors, or plugging into charger, do trigger switch to 'passive mode. 'safe is the usual mode for most purposes.

  • 'full Can be controlled. Lift and cliff sensors, and charger plugging do not switch Roomba to 'passive mode. Switching to 'full mode also stops any battery charging. Don’t use 'full mode unless you’re sure you need to, and you can cover the safety risks other ways.

  • 'closed This connection with the Roomba is closed, so this connection does not know the mode. The mode is changed to this when close-roomba is called, when with-roomba exits, or when an I/O error occurs when attempting to talk with the Roomba.

procedure

(roomba-mode? x)  boolean?

  x : any/c
Predicate for mode.

procedure

(get-roomba-mode [#:roomba roomba])  roomba-mode?

  roomba : roomba? = (current-roomba)
Returns the current mode of the Roomba, as cached in the roomba object (without talking to the robot).

procedure

(set-roomba-mode [#:roomba roomba]    
  #:mode mode)  void?
  roomba : roomba? = (current-roomba)
  mode : (or/c 'safe 'full 'off)
Changes the mode of the Roomba. This sends mode change commands to the Roomba, not merely changes the believed mode in the roomba object. Works in modes: 'passive, 'safe, 'full.

9 Stock Behaviors

9.1 Cleaning

procedure

(start-roomba-spot-clean [#:roomba roomba])  void?

  roomba : roomba? = (current-roomba)
Like pressing the Spot button, starts a spot-cleaning, and switches to 'passive mode. Works in modes: 'safe, 'full.

procedure

(start-roomba-clean [#:roomba roomba])  void?

  roomba : roomba? = (current-roomba)
Like pressing the Clean button, starts a normal cleaning cycle, and switches to 'passive mode. Works in modes: 'safe, 'full.

procedure

(start-roomba-max-clean [#:roomba roomba])  void?

  roomba : roomba? = (current-roomba)
Like pressing the Max button, starts a maximum-time cleaning cycle, and switches to 'passive mode. Works in modes: 'safe, 'full.

9.2 Docking

procedure

(start-roomba-seek-dock [#:roomba roomba])  void?

  roomba : roomba? = (current-roomba)
Directs the Roomba to start seeking its dock. This might only work during some kind of cleaning cycle.

9.3 Demos

procedure

(start-roomba-demo [#:roomba roomba    
  #:demo demo])  void?
  roomba : roomba? = (current-roomba)
  demo : symbol? = #f
Start one of the iRobot Create demos, where demo is one of the symbols:

'cover

  

Drive around to cover room.

'cover-and-dock

  

Cover room, until see Home Base, then dock.

'spot-cover

  

Cover room with spiral.

'mouse

  

Follows walls.

'figure-eight

  

Drive in figure-eight.

'wimp

  

Flees when bumped.

'home

  

(See Create manual.)

'tag

  

(See Create manual.)

'pachelbel

  

Plays Pachelbel's Canon for cliff sensors.

'banjo

  

Plays notes for cliff and bump sensors.

Starting a demo changes mode to 'passive. Works in protocols: COI. Works in modes: 'passive, 'safe, 'full.

procedure

(stop-roomba-demo [#:roomba roomba])  void?

  roomba : roomba? = (current-roomba)
Stop the current iRobot Create demo that is playing. Works in modes: 'passive, 'safe, 'full.

10 Driving

procedure

(set-roomba-drive [#:roomba roomba]    
  #:velocity-mm/s velocity-mm/s    
  #:radius-mm radius-mm)  void?
  roomba : roomba? = (current-roomba)
  velocity-mm/s : integer?
  radius-mm : ((or/c #f integer?) #f)
Sets the drive speed and turning radius of the Roomba.
velocity-mm/s is the velocity in millimeters per second, with a range of -500 to 500, with negative numbers meaning to drive in reverse.
radius-mm is the turning radius in millimeters, with a range of -2000 to 2000, or #f, meaning straight. Works in modes: 'safe, 'full.

procedure

(set-roomba-wheels [#:roomba roomba]    
  #:left-mm/s left-mm/s    
  #:right-mm/s right-mm/s)  void?
  roomba : roomba? = (current-roomba)
  left-mm/s : integer?
  right-mm/s : integer?
Sets the drive speed of the left and right wheels of the Roomba. Each is specified in in millimeters per second, with a range of -500 to 500, and with negative numbers meaning to drive that wheel in reverse. This is a lower-level alternative to set-roomba-drive. Works in protocols: COI. Works in modes: 'safe, 'full.

11 Motors

procedure

(set-roomba-motors [#:roomba roomba    
  #:side-brush? side-brush?    
  #:vacuum? vacuum?    
  #:main-brush? main-brush?])  void?
  roomba : roomba? = (current-roomba)
  side-brush? : boolean? = #false
  vacuum? : boolean? = #false
  main-brush? : boolean? = #false
Sets the on/off states of each of the Roomba’s motors, other than the drive motors. When they keyword argument for a motor is not provided, the default is #false (i.e., off).

12 Lights

procedure

(set-roomba-leds [#:roomba roomba    
  #:debris? debris?    
  #:max? max?    
  #:clean? clean?    
  #:spot? spot?    
  #:dock? dock?    
  #:check? check?    
  #:play? play?    
  #:advance? advance?    
  #:status status    
  #:power-color power-color    
  #:power-intensity power-intensity])  void?
  roomba : roomba? = (current-roomba)
  debris? : boolean? = #false
  max? : boolean? = #false
  clean? : boolean? = #false
  spot? : boolean? = #false
  dock? : boolean? = #false
  check? : boolean? = #false
  play? : boolean? = #false
  advance? : boolean? = #false
  status : (or/c #f 'red 'green 'amber) = #false
  power-color : byte? = 0
  power-intensity : byte? = 0
Sets the states of all the LEDs on the Roomba at once.
The follow table shows which series of Roomba models support which variables, and how the corresponding LEDs are usually labeled. Note that not all models of a series have all LEDs that the series supports. Attempting to set a non-existent LED through this procedure has no effect, not even a warning.

Variable

  

Labels

  

Series

debris?

  

Dirt Detect, Dirt Alert, Debris

  

2nd, 500, 600

max?

  

Max

  

2nd

clean?

  

Clean

  

2nd

spot?

  

Spot

  

2nd, 500, 600

dock?

  

Dock

  

500, 600

check?

  

Check Robot

  

500, 600

play?

  

Play

  

Create

advance?

  

Advance

  

Create

status

  

Status

  

2nd

power-color,
power-intensity

  

Power (Clean)

  

2nd, 500, Create

The Boolean LEDs are self-explanatory.
status is one of 3 colors, or #f for off.
power-color is a value from 0 to 255, representing a color from green to red.
power-intensity is a value from 0 to 255, representing a range from off to full intensity.
Note that not all Roomba models have all these LEDs. The LEDs that they do have might be labeled differently between models.

13 Sound

The Roomba permits short songs by stored in numbered memory slots and then played back on command. The songs consist of single-voice notes with durations, and the volume is fixed.
This library provides a song language for describing songs to be stored, with the BNF grammar:

 

song-language

 ::= 

( note+ )

 

note

 ::= 

frequency

 

  |  

( frequency duration )

 

frequency

 ::= 

symbol?

 

  |  

number?

 

duration

 ::= 

whole

 

  |  

w

 

  |  

half

 

  |  

h

 

  |  

quarter

 

  |  

q

 

  |  

number?

For ‹frequency›, usually you will use a symbol like 'c4 or 'cs4, in the manner of Common Music Notation (CMN). You can also use single-letter note symbols, like 'c. If a number is given, it’s the frequency that this library tries to approximate on the Roomba.
For ‹duration›, symbols like 'whole and 'h denote whole and half notes, respectively. If the duration for a note is not given, a quarter note is assumed. If the duration is given as a number, it’s in 64ths of a second.
For example, here’s a start of Mary Had a Little Lamb:

'(b a g a b b (b h) a a (a h) b d (d h))

procedure

(roomba-song-language? x)  boolean?

  x : any/c
Predicate for song language. This predicate does not necessarily do a complete check of x, and is mainly here for documentation purposes.

procedure

(roomba-song-number? x)  boolean?

  x : any/c
Predicate for song number, which is an exact nonnegative integer in the range of 0 to 15. This is used to identify a song storage slot on the Roomba.

procedure

(compiled-roomba-song? x)  boolean?

  x : any/c
Predicate for the compiled roomba song as produced by compile-roomba-song.

procedure

(compile-roomba-song [#:roomba roomba 
  #:song-number song-number] 
  #:song-language song-language) 
  roomba-song?
  roomba : roomba? = (current-roomba)
  song-number : roomba-song-number? = 0
  song-language : roomba-song-language?
Compiles a song in the song language to a form that is more time-efficient to store with store-song-on-roomba. This may be useful for breaking up a long song into fragments that are stored during playback.
Note that such a compiled song has the song number compiled into it.

procedure

(store-song-on-roomba [#:roomba roomba    
  #:song-number song-number]    
  #:song song)  void?
  roomba : roomba? = (current-roomba)
  song-number : roomba-song-number? = 0
  song : (or/c roomba-song-language? compiled-roomba-song?)
Stores a song on the Roomba in a song number slot, to be played later using play-song-on-roomba. It replaces any song previously stored at that song number on the Roomba.
The longest song that can be stored in in a song number slot at a time is 16 notes. However, longer songs can be played by fragmenting among multiple slots, and/or storing fragments as they are needed during playback.

procedure

(play-song-on-roomba [#:roomba roomba    
  #:song-number number])  void?
  roomba : roomba? = (current-roomba)
  number : roomba-song-number? = 0
Plays song number number as stored using store-song-on-roomba.
Note that, in the current version of this package, song-number must agree with the song number under which the song was compiled.

14 Sensors

procedure

(read-roomba-sensors [#:roomba roomba 
  #:packet-code packet-code]) 
  (listof (cons/c symbol? any/c))
  roomba : roomba? = (current-roomba)
  packet-code : (or/c #f exact-nonnegative-integer?) = #f
Get sensor values for a packet code as an association list. The available packet codes and their association list pairs are documented in section Sensor Packets. If packet-code is #f, then the default will vary between Roomba protocols, to give a large number of sensors values (e.g., on a Roomba 400 would default to 0; iRobot Create, 6).
If you aren’t familiar with association lists, see section Association List Primer.
Some examples on a Roomba 400:

> (read-roomba-sensors #:packet-code 1)

  ((dirt-detect-right        . 0)
   (dirt-detect-left         . 0)
   (side-brush-overcurrent?  . #f)
   (vacuum-overcurrent?      . #f)
   (main-brush-overcurrent?  . #f)
   (drive-right-overcurrent? . #f)
   (drive-left-overcurrent?  . #f)
   (virtual-wall?            . #f)
   (cliff-right?             . #f)
   (cliff-front-right?       . #f)
   (cliff-front-left?        . #f)
   (cliff-left?              . #f)
   (wall?                    . #f)
   (bump-right?              . #f)
   (bump-left?               . #f)
   (wheeldrop-right?         . #f)
   (wheeldrop-left?          . #f)
   (wheeldrop-caster?        . #f))

> (read-roomba-sensors #:packet-code 2)

  ((angle                  . 0)
   (distance               . 0)
   (max-button?            . #f)
   (clean-button?          . #f)
   (spot-button?           . #f)
   (power-button?          . #f)
   (remote-control-command . 255))

> (read-roomba-sensors #:packet-code 3)

  ((battery-capacity       . 973)
   (battery-charge         . 889)
   (battery-temperature    . 30)
   (battery-current        . -176)
   (battery-voltage        . 13888)
   (battery-charging-state . not-charging))
An example with the default packet code on an iRobot Create:

> (read-roomba-sensors)

  ((requested-left-velocity  . 0)
   (requested-right-velocity . 0)
   (requested-radius         . 0)
   (requested-velocity       . 0)
   (number-of-stream-packets . 0)
   (song-playing?            . #f)
   (song-number              . 0)
   (oi-mode                  . safe)
   (internal-charger?        . #f)
   (home-base-charger?       . #f)
   (cargo-bay-analog-signal  . 0)
   (digital-input-0?         . #f)
   (digital-input-1?         . #f)
   (digital-input-2?         . #f)
   (digital-input-3?         . #f)
   (device-detect?           . #f)
   (cliff-right-signal       . 1029)
   (cliff-front-right-signal . 1276)
   (cliff-front-left-signal  . 960)
   (cliff-left-signal        . 1032)
   (wall-signal              . 0)
   (battery-capacity         . 2702)
   (battery-charge           . 2696)
   (battery-temperature      . 25)
   (battery-current          . -169)
   (battery-voltage          . 13554)
   (battery-charging-state   . not-charging)
   (angle                    . 0)
   (distance                 . 0)
   (max-button?              . #f)
   (clean-button?            . #f)
   (spot-button?             . #f)
   (power-button?            . #f)
   (remote-control-command   . 255)
   (infrared-byte            . 255)
   (dirt-detect-right        . 0)
   (dirt-detect-left         . 0)
   (side-brush-overcurrent?  . #f)
   (vacuum-overcurrent?      . #f)
   (main-brush-overcurrent?  . #f)
   (drive-right-overcurrent? . #f)
   (drive-left-overcurrent?  . #f)
   (virtual-wall?            . #f)
   (cliff-right?             . #f)
   (cliff-front-right?       . #f)
   (cliff-front-left?        . #f)
   (cliff-left?              . #f)
   (wall?                    . #f)
   (bump-right?              . #f)
   (bump-left?               . #f)
   (wheeldrop-right?         . #f)
   (wheeldrop-left?          . #f)
   (wheeldrop-caster?        . #f))

14.1 Sensor Packets

The first 7 packet codes are actually for group packets, that include all the contents of a range of other packets:

Packet Code

  

Contains Packets

  

Protocols

0

  

7 - 26

  

all

1

  

7 - 16

  

all

2

  

17 - 20

  

all

3

  

21 - 26

  

all

4

  

27 - 34

  

COI

5

  

35 - 42

  

COI

6

  

7 - 42

  

COI

The non-group packets are listed below.

Packet Code: 7    Protocols: all

  

bump-right?

  

boolean?

bump-left?

  

boolean?

wheeldrop-right?

  

boolean?

wheeldrop-left?

  

boolean?

wheeldrop-caster?

  

boolean?

Packet Code: 8    Protocols: all

  

wall?

  

boolean?

Packet Code: 9    Protocols: all

  

cliff-left?

  

boolean?

Packet Code: 10    Protocols: all

  

cliff-front-left?

  

boolean?

Packet Code: 11    Protocols: all

  

cliff-front-right?

  

boolean?

Packet Code: 12    Protocols: all

  

cliff-right?

  

boolean?

Packet Code: 13    Protocols: all

  

virtual-wall?

  

boolean?

Packet Code: 14    Protocols: all

  

side-brush-overcurrent?

  

boolean?

vacuum-overcurrent?

  

boolean?

main-brush-overcurrent?

  

boolean?

drive-right-overcurrent?

  

boolean?

drive-left-overcurrent?

  

boolean?

Packet Code: 15    Protocols: all

  

dirt-detect-left

  

boolean?

Packet Code: 16    Protocols: all

  

dirt-detect-right

  

boolean?

Packet Code: 17    Protocols: all

  

remote-control-command

  

byte?

infrared-byte

  

byte?

Packet Code: 18    Protocols: all

  

max-button?

  

boolean?

clean-button?

  

boolean?

spot-button?

  

boolean?

power-button?

  

boolean?

Packet Code: 19    Protocols: all

  

distance

  

exact-integer?

Packet Code: 20    Protocols: all

  

angle

  

exact-integer?

Packet Code: 21    Protocols: all

  

battery-charging-state

  

(or/c #f 'not-charging 'charging-recovery 'charging 'trickle-charging 'waiting 'charging-error)

Packet Code: 22    Protocols: all

  

battery-voltage

  

exact-nonnegative-integer?

Packet Code: 23    Protocols: all

  

battery-current

  

exact-integer?

Packet Code: 24    Protocols: all

  

battery-temperature

  

signed-byte?

Packet Code: 25    Protocols: all

  

battery-charge

  

exact-nonnegative-integer?

Packet Code: 26    Protocols: all

  

battery-capacity

  

exact-nonnegative-integer?

Packet Code: 27    Protocols: COI

  

wall-signal

  

exact-nonnegative-integer?

Packet Code: 28    Protocols: COI

  

cliff-left-signal

  

exact-nonnegative-integer?

Packet Code: 29    Protocols: COI

  

cliff-front-left-signal

  

exact-nonnegative-integer?

Packet Code: 30    Protocols: COI

  

cliff-front-right-signal

  

exact-nonnegative-integer?

Packet Code: 31    Protocols: COI

  

cliff-right-signal

  

exact-nonnegative-integer?

Packet Code: 32    Protocols: COI

  

digital-input-0?

  

boolean?

digital-input-1?

  

boolean?

digital-input-2?

  

boolean?

digital-input-3?

  

boolean?

device-detect?

  

boolean?

Packet Code: 33    Protocols: COI

  

cargo-bay-analog-signal

  

byte?

Packet Code: 34    Protocols: COI

  

internal-charger?

  

boolean?

home-base-charger?

  

boolean?

Packet Code: 35    Protocols: COI

  

oi-mode

  

(or/c 'off 'passive 'safe 'full byte?)

Packet Code: 36    Protocols: COI

  

song-number

  

byte?

Packet Code: 37    Protocols: COI

  

song-playing?

  

boolean?

Packet Code: 38    Protocols: COI

  

number-of-stream-packets

  

byte?

Packet Code: 39    Protocols: COI

  

requested-velocity

  

exact-integer?

Packet Code: 40    Protocols: COI

  

requested-radius

  

exact-integer?

Packet Code: 41    Protocols: COI

  

requested-right-velocity

  

exact-integer?

Packet Code: 42    Protocols: COI

  

requested-left-velocity

  

exact-nonnegative-integer?

14.2 Sensor Utilities

procedure

(roomba-infrared-byte->name infrared-byte)

  (or/c #f symbol? byte?)
  infrared-byte : byte?
Maps the 'infrared-byte sensor value to a symbol, or, if no infrared signal, to #f. If it cannot be mapped, then the original byte is returned.
The symbols that might be returned in the current version of this package are the following, (although note that later versions might return additional symbols, and your program should accommodate that possibility):

'left

'forward

'right

'spot

'max

'small

'medium

'large-or-clean

'pause

'power

'arc-forward-left

'arc-forward-right

'drive-setup

'send-all

'seek-dock

'force-field

'green-buoy

'green-buoy-and-force-field

'red-buoy

'red-buoy-and-force-field

'red-and-green-buoys

'red-and-green-buoys-and-force-field

Note that read-roomba-sensors does not do this mapping automatically because some applications might wish to use the infrared byte values for other purposes, such as for a 7-bit communication channel.

15 Cargo Bay Connector

This section lists operations specific to the iRobot Create’s Cargo Bay Connector. For the connector pinout, see iRobot Create Open Interface (OI) Specification, page 4.

procedure

(set-roomba-digital-outputs [#:roomba roomba 
  #:digital-out-0? digital-out-0? 
  #:digital-out-1? digital-out-1? 
  #:digital-out-2? digital-out-2?]) 
  void?
  roomba : roomba? = (current-roomba)
  digital-out-0? : boolean? = #false
  digital-out-1? : boolean? = #false
  digital-out-2? : boolean? = #false
Sets the digital output pins on the Cargo Bay Connector, where #true is high, and #false is low. For more information, see iRobot Create Open Interface (OI) Specification, page 10. Works in protocols: COI. Works in modes: 'safe, 'full.

procedure

(set-roomba-pwm-low-side-drivers 
  [#:roomba roomba 
  #:driver-0-voltage-fraction driver-0-voltage-fraction 
  #:driver-1-voltage-fraction driver-1-voltage-fraction 
  #:driver-2-voltage-fraction driver-2-voltage-fraction]) 
  void?
  roomba : roomba? = (current-roomba)
  driver-0-voltage-fraction : nonnegative-number? = 0
  driver-1-voltage-fraction : nonnegative-number? = 0
  driver-2-voltage-fraction : nonnegative-number? = 0
Set the variable voltage levels of the Create’s three low side drivers. Each is specified as number from 0.0 to 1.0, representing the fraction of battery voltage to use. For more information, see iRobot Create Open Interface (OI) Specification, page 10. Works in protocols: COI. Works in modes: 'safe, 'full.

procedure

(send-roomba-ir-byte [#:roomba roomba]    
  #:byte byte)  void?
  roomba : roomba? = (current-roomba)
  byte : byte?
Send a byte to the iRobot Create’s IR receiver. For more information, see iRobot Create Open Interface (OI) Specification, page 11. Works in protocols: COI. Works in modes: 'safe, 'full.

16 Cables

At time of this writing, if you do not already have a cable/adapter to connect PC to Roomba, your options are:
  • Obtain an iRobot Create, which is an educational/hobby platform variant of the Roomba, which does not include cleaning functionality, and use the included RS232-to-Roomba-mini-DIN cable. Then connect the RS232 cable to your PC, perhaps with an USB-to-RS232 adapter. Or, if you can obtain the no-longer-made iRobot Command Module for the Create, you might be able to disregard RS232 and rig up the microcontroller to let you use an ordinary USB cable between the Command Module and a PC (and please let us know if you do). The Create is available new, direct from iRobot (model 4400 without recharging for 130 USD, model 4418 with recharging for 220 USD). Note that neither of the Create models currently available new from iRobot contain the Command Module, although used ones often have it.

  • Attempt to obtain an off-the-shelf cable/adapter, probably on the used market, since few new ones are currently available:
    • iRobot RS232-to-Roomba-mini-DIN cable (model 4814). These were once sold individually by iRobot for, we believe, 20 USD, without having to buy a Create. Now they are sold new only with a Create, perhaps because iRobot would prefer that people just used the Create for education projects. If you can find one of these cables, to plug it into a modern PC, you most likely also want a USB-to-RS232 adapter (approx. 10 USD).

    • iRobot USB-to-Roomba-mini-DIN cable. We have seen a product photo of these, but they are not currently sold by iRobot.

    • RoboDynamics RooStick, a USB-to-Roomba-mini-DIN adapter. Note that we believe these are no longer available new because it seems that RoboDynamics was developing its own robot platform and seems to have gone on hiatus. RoboDynamics did Roomba business as Roomba Dev Tools.

    • RoboDynamics Roo232, an RS232-to-Roomba-mini-DIN adapter. Like the RooStick, new Roo232 units are not available.

    • RoboDynamics RooTooth, a Bluetooth-to-Roomba-mini-DIN adapter. Sparkfun has a small quantity of some version of these (Sparkfun item DEV-10980, 100 USD). Some changes to this package might be necessary to work with any version of RooTooth. If you have a RooTooth, please contact the package author.

    • Element Direct Bluetooth Adapter Module (BAM), which provides a Bluetooth interface for the iRobot Create, but not the Roomba. It appears to be available currently from Acroname Robotics (part number I19-10542, 60 USD).

    We’re working on getting a particular vendor to make some particular new off-the-shelf cables and adapters, but do not assume that these new products will appear soon. Please contact the author if you can help with this.

  • Make your own cable/adapter. A Web search will turn up many different examples of these that various people have made. To categorize these:
    • Make your own cable/adapter that plugs into the mini-DIN connector that is on most Roombas and on the iRobot Create. You can find the pinout for this in iRobot Roomba Serial Command Interface (SCI) Specification, in section “Physical Connections,” on page 2. Note that this uses 5V TTL logic levels, so you can’t just wire it up to an RS232 port. Your options for connecting this to a computer include:
      • Convert it to RS232, using a voltage level converter, and wiring up a 25-pin or 9-pin D-sub connector.

      • Convert it to USB, such as using an FTDI chip.

      • Hook it up directly to 5V I/O pins on a Rasperry Pi, Arduino, or other low-power computer. This is more an option if the computer is onboard the Robot; otherwise you probably want to go to RS232 or USB first.

    • Make your own cable/adapter that plugs into the Create’s Cargo Bay Connector, which is a 25-pin D-sub connector with a pinout that is specific to the Create. (Note that the same kind of connector traditionally is used for RS232 and for parallel printer port connectors on IBM PCs, but the connector on the Create is neither of those.) The Cargo Bay Connector is documented in document iRobot Create Owner’s Guide, in section “Cargo Bay Connector,” on page 10. Note that, in addition to providing a serial interface needed by this package, the Cargo Bay Connector also provides additional sensor inputs and considerable power, which could be used to power an onboard adapter or low-power computer. Options for using the Cargo Bay connector:
      • Build an RS232, USB, or Bluetooth interface for interfacing with an offboard or onboard PC. This is an option, but if you’re only going to use the serial interface, you might as well connect to the mini-DIN (see above) rather than the Cargo Bay Connector, so that your cable/adapter works with most Roombas rather than just the Create.

      • Build a serial-and-power interface for a Raspberry Pi, Arduino, or other low-power computer. We believe there is enough current to power a Pi plus USB devices like WiFi adapter, in addition to the Create itself. This onboard computer could then run your program on itself and/or provide a WiFi link to offboard computers.

Note that most of the above options have not yet been tested with this package, and a small number of them might require modifications to this package.
The excutive summary on cables/adapaters at the moment is that most people’s educational/hobby project lives would be easier if they can afford an iRobot Create. Especially if you can put a Raspberry Pi onboard the Create. But, with a little work or luck, you can also get an old Roomba hooked up to a computer for using this package. And hopefully a hobby-oriented electronics company will soon make things easier.
If you have any updates to the above information, please contact the author of this package.

17 Association List Primer

For returning values from read-roomba-sensors, this package use an association list (also known as an alist), which is an old-school Lisp way of representing small keyed-accessed sets, among other things. (In the future, there might be other, even more efficient, ways to access Roomba sensors from this package, but alists are a good initial method.) Since hobbyists and students new to Racket might be familiar with pairs and lists, but not with alists, here is a quick intro.
Let’s say you received an alist like this:

> (define result (read-roomba-sensors #:packet-code 3))

> result

  ((battery-capacity       . 973)
   (battery-charge         . 889)
   (battery-temperature    . 30)
   (battery-current        . -176)
   (battery-voltage        . 13888))
If you use the Racket assq procedure alone to look up the alist pair with the key 'battery-charge, you get the entire pair:
> (assq 'battery-charge result)
  (battery-charge . 889)
As you probably know from prior study of Racket pairs and lists, to get the right-hand side of the pair, which has the value for the key, you use the Racket cdr procedure:
> (cdr (assq 'battery-charge result))
  889
One difficulty is that, if assq doesn’t find the key, it will return #f rather than a pair. So, say that on some Roombas you get a 'battery-coolness sensor result, but on others you don’t. So, if you try to look up that key in our example alist:
> (assq 'battery-coolness result)
  #f

> (cdr (assq 'battery-coolness result))

cdr: contract violation expected: pair? given: #f

If you want your code to be robust against that, you can use this code pattern of cond and =>, which will give you either the value of the the alist pair for key 'battery-coolness, or a default value of 777:
> (cond ((assq 'battery-coolness result) => cdr)
        (else 777))
  777
You can also get fancier, such as adding a helpful error message and moving the code that uses the 'battery-coolness into a the cond, like so:
(cond ((assq 'battery-coolness result)
       => (lambda (battery-coolness)
            ...CODE-THAT-USES-BATTERY-COOLNESS-VALUE...))
      (else (error "Roomba has an uncool battery!")))
For most purposes, with Roomba sensor values, you’ll only need the code pattern (cdr (assq SYMBOL ALIST)), but cond is there if you need it.

18 Troubleshooting

Here are a few troubleshooting tips.
First things first:
  1. Ensure that the serial cable or other interface is firmly attached in all places it could become loose.

  2. If you built a serial interface using instructions found on the Web, be aware that some pinout diagrams for the mini-DIN were published with pins reversed. Double-check against different pinouts.

  3. If you’re connecting to an iRobot Create using the Command Module, make sure that you follow the boot-time procedures documentd in the iRobot Command Module Owners Manual. Also note that the developers of this package have not yet tested use through the Command Module.

If the PC’s serial port or other interface on the PC side is not working:
  1. Consider whether you have the right device file for your #:device argument. For example, if you’re specifying device "/dev/ttyS0", maybe the correct device is "/dev/ttyS1", "/dev/ttyUSB0", or something else.

  2. If you’re using a USB interface on the PC side, perhaps using a USB-to-RS232 adapter with an iRobot RS232-to-Roomba cable, check whether the USB device is actually recognized by the PC. On GNU/Linux, you can use the lsusb shell command to list recognized USB devices, and you can also check the syslog log files for the time that you plugged in the device.

  3. If the PC’s serial port is an RS232 port on a laptop dock, consider that a hardware or operating system bug might be causing the serial port to “disappeared”. This has been known to happen with a ThinkPad T60 plugged into a dock, for example, and the solution in that case is to reboot the laptop while plugged into the dock.

If the PC’s serial port or other interface on the PC side seems OK, but the Roomba is still not communicating:
  1. On at least some Roomba models (including the 400), the Clean or Power button should be solid green before the Roomba can be accessed via this package. If button is not solid green, try pressing it, in hopes of it turning solid green. Be prepared to lift up the Roomba if pressing the button starts a clean cycle.

  2. If the Roomba’s Clean or Power button is not solid green and pressing does not correct that, try removing and reattaching the cable from the Roomba’s serial port.

  3. If all else fails, try removing the cable from the Roomba’s mini-DIN, removing the Roomba’s battery, waiting a few seconds, reattaching the Roomba’s battery, and finally reattaching the cable to the Roomba’s mini-DIN.

  4. Consider that the Roomba is refusing to communicate because its battery desperately needs charging, even if it appears to have some charge left.

Please contact the author of this package with additional tips that should be mentioned here.

19 Known Issues

20 History

21 Legal

Copyright 2013 Neil Van Dyke. This program is Free Software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose. See http://www.gnu.org/licenses/ for details. For other licenses and consulting, please contact the author.