RAD: The first step towards Ruby on Robots

23 July, 2007

Note: I'll be presenting RAD at FOSCON this coming Tuesday at 7:30pm at Holocene in Portland, Oregon!

About a year ago, I started learning microcontroller programming. Microcontrollers are the tiny computers that act as the brains of electronic devices: they run your alarm clock, your Wiimote, your cockroach controlled mobile robot. I'd gotten interested in them after becoming a fan of the the cinematic miniatures of Jennifer and Kevin McCoy and other similar work conducted at NYU's Interactive Telecommunications Program.

I acquired an Arduino, an integrated open source hardware and software system that provides everything you need from the microcontroller itself to the connectors for plugging in electronic circuits to the code libraries for accessing the chip's capabilities. I gathered a group of similar-minded friends and we started doing some experimenting. We built a working prototype of a a Simon-style pattern matching game, we played with motors, and, eventually, I had an idea.

My idea was: why was I wrestling with ugly and low level C/C++ code, when I spent my days writing with the beautiful and near-infinitely flexible Ruby? Why couldn't programming Arduino be as beautiful as programming Rails? Why couldn't 'hello world', which was 10 lines of "void", "int", and curly braces look like this instead:

class MySketch :led
def loop
blink led, 500

And further, why couldn't I have all the developer tools I'd grown used to in Rails? Where was the testing, the platform independence, the metaprogramming?

So, I set out to do something about it: I started working on a system for programming Arduino in Ruby. And, today, I'm proud to announce the first release of the resulting project: RAD: Ruby Arduino Development. RAD converts Ruby scripts (like the one above) written using a set of Rails-like conventions and helpers into C/C++ source code which can be compiled and run on the Arduino microcontroller. It also provides a set of Rake tasks for automating the compilation and upload process.

Start by downloading the Arduino software tools. Then, you can install RAD in the usual way:

$ sudo gem install rad

RAD depends on Ruby2C, which seems immune to the normal gem requirement techniques, so, if you don't already have it, you'll need to install that as well:
$ sudo gem install Ruby2C

Once, you've got in installed, you create your new Arduino sketch just like you would a new Rails project:

$ rad my_sketch

That'll generate a new directory containing a blank ArduinoSketch file, a config directory with files for telling RAD about the relevant hardware and software constants (the location in which you installed the Arduino software tools and the path to your serial port), and a vendor directory with all of the RAD helper code. Next, make sure that the Arduino software tools are in your path:

export PATH=<path to arduino install root>/tools/avr/bin:$PATH

Now, you're ready to write code. To start with you could emulate my example above. It's the classic 'hello world' script for microcontrollers: it flashes a single LED twice a second.

RAD provides class methods for setting up your Arduino: output_pin and input_pin which take an integer representing a pin number between 1 and 14 and an optional :as argument which lets your refer to that pin through a method named after the given symbol. There are also equivalent methods for setting up multiple pins at once (output_pins and input_pins) each of which take an array of integers. In my example code, you can see I'm setting up pin 7 as an output pin and creating a method for referring to it as "led"

The other main element of your ArduinoSketch will be the "loop" method. That's where you write the code you want the Arduino to actually run repeatedly on the microcontroller. The example I've got here is pretty straight forward. It tells the Arduino to turn the LED on, to wait 500ms, to turn the LED off, and then to wait 500ms (blink is just a built in RAD-macro for the digitalWrite and delay commands in the Arduino library). Repeat that over and over and you've got a blinking LED.

Obviously, to make this work you've got to have the corresponding circuit actually hooked up to your Arduino. In this case, that would be a 220ohm resistor and an LED connected in series between the the Arduino board's pin 7 and its ground pin. (If you don't have a resistor or LED handy, you could test this out with pin 13, which is connected to the built-in test light that comes with the Arduino, just change the output_pin number above.)

Once you've got your circuit wired up, your configuration complete, and your Ruby code written, run:
$ rake make:upload
This will:

  • generate the correct Arduino C/C++ code from your sketch
  • dynamically prepare a localized version of the default Arduino makefile
  • compile your script
  • prompt you to hit the reset button on your Arduino
  • upload your compiled binary onto your Arduino

If everything goes smoothly, a wave of hex output will flow from your terminal, the yellow lights on the Arduino will flicker, and, after a second or two, your LED will start blinking! Now, all you've got to do to iterate on your script is write changes, save them, and run the rake command again.

With the exception of the still-experimental Serial interface, most of the Arduino software API should be working correctly at this point. Documentation for the Ruby versions of the methods is forthcoming, but it is mostly what you'd expect: methods with identical names and arguments to their Arduino counterparts with the exception of using 'true' and 'false' for HIGH and LOW (RAD uses Ruby2C to translate your 'loop' method into C).

As mentioned above, full compatibility with the Arduino API is just the beginning for RAD. The long term goal for RAD is to provide developer tools like testing, an interactive console for communicating with the Arduino over serial, metaprogramming facilities, and, eventually, even platform independence, i.e. the option to transform your Ruby code to work with other non-Arduino PIC and AVR microcontroller platforms.

In order to accomplish any of these lofty goals, many discipline-crossing skills will be required. So, I need your help! Have you written lots of sketches exploring the obscure depths of the Arduino library? Do you run the Arduino development tool chain on an obscure (i.e., non-OS X) platform? Do you develop for other AVR or PIC microcontrollers? Are you a C/C++ ninja? Or even C/C++ competent? If so, and you're interested in getting involved with the glamorous world of microcontroller metaprogramming, get in touch. You can visit the RAD homepage on Rubyforge for svn access and email me with questions, suggestions, comments, criticism, and patches.

Tagged: , , , , , , ,