Open Hardware and the Penguin: using Linux as an Arduino development platform
By Tom Parkin
Introduction
Linux is one of the more scalable Operating Systems in existence today, equally at home on tiny embedded single-board-computers as it is on supercomputing clusters. However there will always be some computing applications for which Linux doesn't fit; indeed for which any OS at all is something of an unnecessary overhead. Devices fitting this niche are many and varied, ranging from low-powered PIC devices to more capable microprocessors (such as those based around Intel's venerable 8051 chip). Typically each device or device family comes with its own software stack and development environment, and until recently, all the options for development at this level held one thing in common: proprietary designs, and proprietary software.
Enter the Arduino
This is beginning to change. Although hardly as vibrant and diverse as the Open Source software ecosystem, a nascent Open Source hardware movement is quietly developing open-licensed hardware designs for a wide range of applications. At the most fundamental level, the Open Cores project aims to develop Open Source hardware designs for chips themselves, ranging from memory controllers to full-blown processor designs. Moving up a layer of abstraction, projects such as The Open Graphics Project are developing hardware board designs using off-the-shelf components. Sitting somewhere inbetween the two, the Arduino project aims to provide a general-purpose microcontroller platform, integrating an Open Source board design with Open Source software development tools.
The Arduino was conceived in 2005 by academics at an Italian design school who had become frustrated with the paucity of simple, powerful platforms for their students to use as a base for projects. In classic open-source style they decided to build their own, and in a few days of creative hacking the embryonic Arduino was born. Since then it has grown from being a teaching aid to become rapid prototyping and hobbyist platform with a global community of users.
At its heart the Arduino consists of an 8-bit microcontroller from Atmel's megaAVR range of chips, which is supplemented with I/O headers and a USB or RS232 connection for uploading of code. It is a simple design which retains a shallow learning curve and provides remarkable flexibility. Properties which, in conjunction with the open-source licensing of the device's circuit design and software stack, have led to an impressive diversity of applications. Not only are Arduino hackers exploring such traditional geek territory as a Wii-nunchuk controller for a trainset, they're also developing exceedingly practical projects along the lines of a controller for a beer fridge, not to mention pushing the boundaries of computer-music creativity with a laser MIDI "harp".
Arduino development under Linux
In keeping with the Arduino's open-source heritage, all of the tools required to develop Arduino code will run on a Linux platform, and the remainder of this article will provide a tutorial for getting started with Arduino hacking.
This tutorial has been tested using a 32-bit Crunchbang Linux system, which is based on Ubuntu 9.04. Where possible the instructions have been written to be transferable to other distributions with minimal effort.
1. Obtain an Arduino board
First of all, it is necessary to source the Arduino hardware itself. Although it is possible to build an Arduino by hand using widely available components, it is best to buy a pre-built board from one of the many hobbyist websites which stock them. This avoids the need for potentially error-prone soldering or bread-board assembly at the early stages of Arduino development. Pre-built Arduino boards can be sourced from the websites linked from the Arduino project's website, and are relatively cheap. At the time of writing, the going rate is around 20 GBP or 25 USD.
2. Install the development environment
Once an Arduino board has been obtained, it is time to create a development environment on a Linux host PC. The simplest way to do this is by using the Arduino Integrated Development Environment (IDE). This is a Java application which will provide support for source code editing and compilation, binary image upload to the Arduino, and a serial communications terminal, all within a single application.
2.1 Download the Arduino IDE from the Arduino website
The latest release of the Arduino IDE at the time of writing was version 0018. It is recommended that the latest version of the IDE is used.
# Create a new directory to store the IDE in mkdir arduino cd arduino # Download the IDE tarball from the web wget http://arduino.googlecode.com/files/arduino-0018.tgz # Untar the IDE tarball tar -xzf arduino-0018.tgz
2.2 Install the necessary supporting packages for the IDE
Since the Arduino IDE is a Java program a suitable Java Runtime Environment must be installed on a host PC. In addition, the IDE relies on some further software packages: GCC for code compilation, binutils and libc for the creation of a runnable image for the Arduino microprocessor, and avrdude for communication between the host PC and the Arduino board.
Super-user privileges will be required to install these software packages on the host PC: for the purposes of this demonstration, sudo is used.
# Install Sun's JRE sudo aptitude install sun-java6-jre # Install the AVR compiler and runtime tools sudo aptitude install gcc-avr binutils-avr avr-libc # Install the AVR communications tool sudo aptitude install avrdude
2.3 Unprivileged user access to /dev/ttyUSB0
Contemporary Arduino boards such as the Duemilanove communicate with the host PC via a USB-serial connection. In order to access this device node as a normal user on the host PC, it may be necessary to add your user to a group with access rights to the node.
# First, connect the Arduino board to the host PC via. a USB cable, # then check dmesg output on the host PC dmesg | grep -i "usb serial" [ 1054.569782] USB Serial support registered for generic [ 1054.569860] usbserial: USB Serial Driver core [ 1054.594282] USB Serial support registered for FTDI USB Serial Device [ 1054.594433] ftdi_sio 2-1:1.0: FTDI USB Serial Device converter detected [ 1054.594651] usb 2-1: FTDI USB Serial Device converter now attached to ttyUSB0 # dmesg output suggests that the device is connected to ttyUSB0, # so check the access rights on that device node ls -l /dev/ttyUSB0 crw-rw---- 1 root dialout 188, 0 2010-03-09 22:13 /dev/ttyUSB0 # The group "dialout" has access to /dev/ttyUSB0, so add user "tom" to that group. # You should replace "tom" with your own login name, of course! sudo usermod -a -G dialout tom
3. Launch the IDE and connect the Arduino board
With the supporting software installed and access to the Arduino USB-serial device node configured, the IDE can be launched:
cd arduino-0018 ./arduino
The Arduino Duemilanove board is powered from the USB bus. All that should be required to get this up and running is to plug it into your Linux PC, via a USB cable.
4. Test your setup with an example project
The Arduino IDE is fairly intuitive and easy to use. To illustrate the basic procedures required to build and upload code, we'll use a simple demonstration project which uses the in-build LED on the Arduino Duemilanove board to flash a message in Morse code.
4.1 Example code
/* * morse.pde * * An Arduindo Morse code blinkenlight example for Linux Gazette * * Tom Parkin, March 2010 * tom.parkin@gmail.com */ /* Digital I/O pin 13 is an LED on the Duemilanove board */ static const int ledPin = 13; /* Encapsulates letter / code associations for Morse code */ struct { char letter; char *code; } morse_letter_t; /* * Morse code encoding specification, refer to wikipedia for more info: * http://en.wikipedia.org/wiki/Morse_code */ #define DOTLEN 250 #define DOT ( pulseLed(ledPin, DOTLEN) ) #define DASH ( pulseLed(ledPin, 3*DOTLEN) ) #define SYMBOLSPACE ( delay(DOTLEN) ) #define LETTERSPACE ( delay(3*DOTLEN) ) #define WORDSPACE ( delay(7*DOTLEN) ) morse_letter_t alphabet[] = { { 'A', ".-" }, { 'B', "-..." }, { 'C', "-.-." }, { 'D', "-.." }, { 'E', "." }, { 'F', "..-." }, { 'G', "--." }, { 'H', "...." }, { 'I', ".." }, { 'J', ".---" }, { 'K', "-.-" }, { 'L', ".-.." }, { 'M', "--" }, { 'N', "-." }, { 'O', "---" }, { 'P', ".--." }, { 'Q', "--.-" }, { 'R', ".-." }, { 'S', "..." }, { 'T', "-" }, { 'U', "..-" }, { 'V', "...-" }, { 'W', ".--" }, { 'X', "-..-" }, { 'Y', "-.--" }, { 'Z', "--.." }, { 0, NULL } }; /* The setup function for the Arduino */ void setup() { pinMode(ledPin, OUTPUT); } /* Turn the LED attached to 'pin' on for 'milliseconds' ms */ void pulseLed(int pin, unsigned int milliseconds) { digitalWrite(pin, HIGH); delay(milliseconds); digitalWrite(pin, LOW); } /* Flash 'letter' in Morse on the LED, based on 'alphabet' lookup */ bool encodeLetter(char letter, morse_letter_t *alphabet) { int i; char *code = NULL; /* Lookup the specified letter in the alphabet */ for (i=0; alphabet[i].letter != 0; i++) { if (alphabet[i].letter == letter) { code = alphabet[i].code; } } if (!code) return false; /* Display the letter */ for (i=0; i < strlen(code); i++) { if (code[i] == '.') { DOT; } else { DASH; } SYMBOLSPACE; } return true; } /* Flash 'word' in Morse on LED, based on 'alphabet' lookup */ bool encodeWord(char *word, morse_letter_t *alphabet) { int i; for (i=0; i < strlen(word); i++) { encodeLetter(word[i], alphabet); LETTERSPACE; } return true; } /* Arduino 'main' loop */ void loop() { delay(5000); encodeWord("LINUX", alphabet); WORDSPACE; encodeWord("GAZETTE", alphabet); WORDSPACE; }
There are a couple of points to note about this simple Arduino "sketch" (n.b. a "sketch" is the Arduino term for a project). Firstly, although it looks like C code, perceptive readers will have noticed that it isn't actually a complete program. That's because the Arduino IDE provides a lot of basic functionality behind the scenes, leaving the programmer to focus on the task at hand rather than the intricacies of driving a given I/O pin high, for example.
A full reference to the Arduino environment is available via the Arduino website. Essentially it boils down to a library of utility functions (for example delay(), which delays program execution for the specified number of milliseconds), and two callbacks which the core Arduino code calls to allow a given sketch to do its work. As shown above, these callbacks are setup() for initial configuration, and loop() for the main event loop of the program.
4.2 Create a new Arduino sketch
To import this code into the Arduino IDE, launch the IDE then click File -> New to create a new sketch. Copy and paste the code into the editor window, then save it (File -> Save) with a sensible filename.
4.3 Configuring the IDE
Now configure the IDE to talk to your Arduino board.
First, instruct the IDE to use the serial port that your Arduino is attached to by clicking Tools -> Serial Port and selecting the serial port that we determined previously (this was /dev/ttyUSB0, in our example). Depending on your distribution you may need the Arduino to be connected for this port to show up.
With that done, set the IDE to compile code for your specific Arduino device by clicking Tools -> Board. In your author's case the correct choice is Arduino Duemilanove or Nano w/ATMega328, which is the most recent Arduino board at the time of writing.
4.4 Compile and run: the moment of truth
Finally, to compile and upload the code to the Arduino, click Sketch -> Verify/Compile, and then File -> Upload to I/O board. Simple!
If everything has gone according to plan, the Arduino IDE should load the compiled morse code application to the board. Look for the TX and RX lights flashing on the board to indicate communications in progress. The board should immediately run the program. After a few seconds, the Arduino should start blinking its green LED to flash a Morse code message.
What next?
At this stage, you should be well on your way to getting to grips with the fundamentals of Arduino development, and hopefully you'll already be envisaging how you could use the platform in an exciting new project.It's not working!
As with any computer-related activity, Arduino development has its fair share of pitfalls and sticking points to negotiate. Although the IDE and the example code above provide a simple introduction, once you set out on your own you'll inevitably hit a problem at some point. Happily the Arduino project provides many avenues for support, including the Arduino forums and IRC channel. In addition, the Arduino and its IDE have been widely blogged about, and a small amount of work with a search engine will yield a lead on most of the widely-encountered issues.What if I don't want to use the IDE?
Although the Arduino IDE is a great tool, some developers may wish to use their favourite editor for generating code instead. This is made easily possible using Kimmo Kulovesi's excellent arduino_make.sh script, which leverages the internal build files used by the IDE to perform the basic Arduino compilation and upload processes from the commandline.
Conclusion
The Open Source Hardware movement is increasingly demonstrating that the power of open development is not limited to the software domain. The Arduino project leverages the best of both Open Source hardware and software to deliver a great multi-purpose microcontroller platform. Whether you're a software hacker looking for an easy entry into the world of embedded devices, a teacher seeking a device to base an electronics course around, or a seasoned hardware designer looking for a quick prototyping environment, you owe it to yourself to give the Arduino a look.
[ For an amusing bit of synchronicity this month, take a careful look at our XKCD comic strip. Arduino is the hot new thing! :) -- Ben ]
Talkback: Discuss this article with The Answer Gang
Tom Parkin has been fascinated by the inner workings of digital technologies ever since his father brought home a VIC-20 sometime in the mid-eighties. Having spent most of his childhood breaking computers in a variety of inventive ways he decided to learn how to fix them again, a motivation which lead him to undertake an MEng degree in Electronic Systems Engineering in 2000. Since graduating he has pursued a career in embedded software engineering, and now feels that he has probably been responsible for more working computers than broken ones.
Tom was introduced to Linux when a friend lent him a thick stack of Mandriva installation CDs, and he has been using Open Source software ever since. Like most Linux users, Tom has tried many different distributions but is currently settled with Fedora at work and Crunchbang on his home machine.
When not tinkering with computers and Linux, Tom enjoys exploring the great outdoors on bike or on foot, and making music.