1 Introduction
2 Logging
3 Exceptions
exn:  fail:  roomba
exn:  fail:  roomba:  io
exn:  fail:  roomba:  mode
4 Protocols
5 Models
6 Roomba Object
7 Opening and Closing
8 Modes
9 Stock Behaviors
9.1 Cleaning
9.2 Docking
10 Driving
11 Motors
12 Lights
13 Sound
14 Sensors
15 Cables
16 Troubleshooting
17 Known Issues
18 History
19 Legal

roomba: iRobot Roomba/Create Interface in Racket

Neil Van Dyke

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

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 PLTSTDERR environment variable, or via the DrRacket Log window.

3 Exceptions


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

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


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

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


(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.

4 Protocols

This package supports a few different Roomba protocols.


(roomba-protocol? any/c)  boolean?

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


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.


roomba-roi : roomba-protocol?

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


roomba-coi : roomba-protocol?

COI, the protocol used by the iRobot Create, described by iRobot Create Open Interface (OI) Specification. (We say “roomba” even though it’s for a Create rather than a Roomba, due to the identifier naming convention of this package.)

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.
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 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 has a mini-DIN connector, since it 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.


(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.


(roomba-model? x)  boolean?

  x : any/c
Predicate for a Roomba model.


(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.)



(hash/c (or/c exact-nonnegative-integer? symbol?)
(current-number-to-roomba-model-hash hasheqv)  void?
  hasheqv : 
(hash/c (or/c exact-nonnegative-integer? symbol?)
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.



  (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.


(roomba? x)  boolean?

  x : any/c
Predicate for the roomba object.


(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.


(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


(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/ttyS0", depending on the Racket platform.


(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.


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

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


(with-roomba maybe-name
             body ...+)
maybe-name = 
  | #:name string?
maybe-model = 
#:model (or/c roomba-model?
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.


(roomba-mode? x)  boolean?

  x : any/c
Predicate for mode.


(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).


(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


(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.


(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.


(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


(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.

10 Driving


(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.

11 Motors


(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


(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.








Dirt Detect, Dirt Alert, Debris


2nd, 500, 600















2nd, 500, 600





500, 600



Check Robot


500, 600


















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:




( note+ )







( frequency duration )






























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))


(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.


(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.


(compiled-roomba-song? x)  boolean?

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


(compile-roomba-song [#:roomba roomba 
  #:song-number song-number] 
  #:song-language song-language) 
  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.


(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.


(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


(read-roomba-sensors [#:roomba roomba 
  #:packet-code packet-code]) 
  (listof (cons/c symbol? any/c))
  roomba : roomba? = (current-roomba)
  packet-code : (or/c 0 1 2 3) = 0
Get sensor values for a packet code as an association list.
This will be documented better as soon as we add support for the new sensors protocol in ROI and COI. Currently, it only supports SCI requests, which are also supported by ROI and COI. In the interim, the below examples, evaluated in a with-roomba context, might be illustrative:

> (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))

15 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 may be able to disregard RS232 and simply use an ordinary USB cable between the Command Module and a PC. 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.

    • 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.

16 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 using "/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.

17 Known Issues

18 History

19 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.