Lab Guide: Software Environment

Your group should consult and decide on a development environment and source control system.  You can probably mix-and-match different IDEs but be wary of using significantly different toolchains.  There are several options for IDE:

  • Atmel Studio 6.1: Probably the “best” AVR IDE, unfortunately it’s based on Visual Studio so it’s Windows-only.  This is the easiest way to get a recent avr-gcc toolchain on Windows since Atmel poached the WinAVR guy.  Atmel Studio includes a decent AVR simulator for debugging, and also integrates debugging and programming tools like the JTAGICE mk2 very well.  (Arduino setup; follow step 5A, not 5B).
  • Eclipse for C/C++ Developers: (alternately, install the CDT module in Eclipse) Eclipse CDT has slowly been getting crummier and crummier.  It’s a decent multi-platform option if you can get it to resolve includes properly.  There exists a plugin for AVR development but you’ll need to install a toolchain separately. (Arduino setup)
  • Arduino IDE: Integrates nicely with Arduino (obviously), but pretty bad for coding, especially raw AVR coding.  If you like to write code in a text editor this may be a good option for you.  This is another way to get a recent avr-gcc toolchain, and also the best way to get the Arduino library source code release.

The lab computers have all the required software installed[edit: lab computers are currently off the network and you won’t be able to log in], but students usually prefer to use their own laptops.  Our lab has some of the worst computers in the building and we don’t have admin access to them which is a huge pain.

Getting Started

The details on how to get started depend on your choice of development environment, and are surely well-documented elsewhere.  The Arduino IDE is the easiest for getting started because it has everything included, but again it’s a bad IDE.  It also doesn’t play nicely with other development environments because it doesn’t use standard C++, it has an extra pre-processor that puts in its own main function and header includes to hide some details from novice programmers.  Generally the process for starting with a non-Arduino IDE is as follows:

  1. Create a new C++ project using the avr-gcc toolchain.  You’ll be writing C code, but it still has to be a C++ project because parts of the Arduino library are encapsulated in C++ classes.
  2. Add in the Arduino core library.  At first you can just import all the files that come with the Arduino IDE in the folder \hardware\arduino\cores\arduino\.  Be aware that there is a LOT of code in there that you don’t need, and it will get compiled into the binary that you upload to the microcontroller.  On the Arduino Uno, which only has 30 KB or so of available program memory, this will cause problems.  At that point you can compile the core library in a separate static library project and link your executable project against the static library.  That way your executable only takes from Arduino the code it needs.
  3. Make a main function that never returns.  Include Arduino.h from the Arduino core library, and call the init() function to initialize the Arduino stuff.  Then do whatever you want to do in the main function.  You can make it call a setup() function once and repeatedly call a loop() function, which is what Arduino’s default main() function does (see below).

Hardware Differences

We use two Arduino microcontrollers: the Seeeduino Mega (red ones with lots of pins) and the Arduino Uno (blue ones).  Here’s a summary of how they should be set up for compilation and programming:

Arduino UnoSeeeduino Mega
MCUATmega328PATmega1280
Bootloader Baud Rate11520057600
Program Memory~30 KB~126 KB
Clock Speed (F_CPU)16000000 Hz16000000 Hz
NotesCompatible with Arduino Mega 1280

Starting to Write Code

The Arduino language is a simplified version of C++ that I suggest you ignore.  There is nothing special about writing Arduino-based code for an Arduino microcontroller: it’s exactly the same as writing C/C++ code targeting any other AVR processor, with a core library of handy functions and classes that you can compile into your program.

You can follow the normal C++ routine of writing a main() function as the entry point to your program:

#include "Arduino.h"
int main()
{
    init();
 
    // your code here
 
    for (;;);
    return 0;
}
  • This should replace the main() function in the main.cpp file that came with the Arduino core library source code.  You can use the Arduino version if you like.
  • The Arduino.h header includes all the core Arduino headers; you need to include this to use Arduino functions.
  • The init() function initializes some Arduino functions (in particular the timing functions).  Be careful: calling this function might clobber your own configurations (or vice versa); check the init() definition in the Arduino source code to make sure it’s not overwriting registers that you’re using directly.
  • The infinite for loop is a guard to make sure that main() never returns.  The AVR instruction set doesn’t include a stop instruction, so the program must not return from main, or it will start doing weird stuff.
  • The return statement needs to be there to match the function prototype, even though the statement is not reachable.

See the Arduino Language Reference for information on what’s in the core library.  You already know the language definition, it’s just C++; the function list in the rightmost column tells you the core functions.

Non-Core Libraries

You’ll need to use some of the non-core libraries that are included with the Arduino distribution.  These are held in e.g. \arduino-1.0\libraries\.  For example, the I2C interface (also referred to as TWI) is held in the Wire folder.  Just copy the source files into your project folder and compile them along with your own code.  The Servo library can be used to control servo motors and brushless DC motors.

The Stepper library, used to control stepper motors, will probably not be good enough for you because it blocks program execution while the motor is spinning.  It’s better to copy the functional parts out of Stepper.cpp and use time-triggered scheduling to run them, so that your program can do other stuff while the motor is turning.

The Crazy Way Arduino Does It (Ignore This Section)

Arduino code is written in “sketches,” which are files with PDE extensions.  They’re archives containing the source code files.  The code in the PDE file is not compilable in a non-Arduino IDE, because the sketch doesn’t contain a main() function.  The Arduino main() looks something like this:

#include "Arduino.h"
int main()
{
    init();
    setup();
    for (;;)
        loop();
    return 0;
}

An Arduino sketch only defines the setup() and loop() functions, which are then called by the default main function that the IDE inserts when the sketch is compiled.

I don’t seriously mean to badmouth Arduino.  It’s great, and a lot of people love it and use it because it’s so simple and it hides a lot of the details of C/C++ programming.

Arduino and avr-gcc

Arduino is a microcontroller, an IDE, a “programming language,” and a library.

The Arduino library is a software layer built on the AVR C/C++ library, the latter of which implements a large part of standard C (and adds some AVR-specific stuff).  avr-gcc allows you to interact with microcontroller at a lower level than you get if you use Arduino.  I just have a couple things to add:

  • You might have to get down into the AVR code.  This is less true today that it was a couple years ago, but the Arduino library isn’t always flexible enough to do what you want, or do it as fast as you want.  Also you might need to read the Arduino code to find out what’s going on or to make sure what you’re doing won’t cause problems.
  • There are, like, three different, incompatible ways to refer to the same I/O pin.  This is really annoying.  When you’re writing raw AVR code you refer to pins as PXn, where X is the port designation and n is the pin number.  For example, PA5 refers to pin 5 of port A.  Each port contains 8 pins.  However, each pin also has a pin number that refers to its position on the physical AVR microcontroller chip, ranging e.g. from 0 to 39 for a 40-pin chip (this number is never used in code).  Furthermore, Arduino refers to pins with a different numbering system that is somewhat arbitrary.  I talk about this more in the section on Arduino hardware.

Things that Can Go Wrong

When uploading code, if you get an error that it cannot write to some memory, your program is probably too big.  The easiest way to solve the problem is to enable size optimizations in the Eclipse project settings.  This can reduce a 30 kB binary (too big for the Arduino Uno) down to less than 20 kB.  You could also put some code (especially the Arduino core library) into a separate project targeting a static library, so that only the code that your program actually uses is put into the final binary.

If you get out of synch errors when uploading, make sure that the Seeeduino is in automatic upload mode (the switch nearest the USB port) and, if you’re on your own computer, that you’re using an Arduino version of avrdude.