Sunday, February 28, 2010

AVR Programming on Mac

Yes, you can program your Atmel ATmega-based Orangutan with your Mac! I'm using a Pololu Orangutan LV-168 to control Pokey the robot and programming it with the Pololu USB programmer. Works great! I recently updated the AVR toolchain / programming environment on my Intel-based MacBook running OS X 10.5 "Leopard" and so I've updated this article. Here's the play by play.

Huge thanks to Dennis Clark for guidance and setting me on this path in the first place!!!

Updated Feb 28, 2010 for Mac OS X 10.5 "Leopard" and OS X 10.6 "Snow Leopard"

Step 1.0: AVR Toolchain

The toolchain software needed for programming your ATmega includes the following:
  • avr-binutils
  • avr-gcc
  • avr-libc
  • avrdude
  • simulavr
I suggest obtaining the tools in the form of CrossPack for AVR from Objective Development. It will support the new Orangutan library (libpololu-avr) and the new ATmega328P-based controllers.  The latest version of CrossPack AVR as of this writing is 2010-01-15 and includes avr-gcc 4.3.3, avr-libc 1.6.7, avrdude 5.8, and simulavr 0.9. It's based on WinAVR 20100110. The old Mac OS X AVR is no longer available and MacPorts' avr toolchain is a couple years out of date.

The CrossPack AVR suite comes as a disk image with a Mac OS X package installer.  It's a matter of opening the disk image then double-clicking the package and going through the prompts.  Tremendously simple, way more so than MacPorts ever was. Both avrdude and simulavr are also included. Neato!

Incidentally if you see the following error (compiling with the new Pololu library), it is most likely because you're running a version of avr-gcc that is too old (4.0.2 in my case):
main.o: In function `main':
main.c:(.text+0xa): undefined reference to `serial_set_mode'
main.c:(.text+0x16): undefined reference to `serial_set_baud_rate'
main.c:(.text+0x3c): undefined reference to `serial_send'
main.c:(.text+0x44): undefined reference to `delay_ms'
main.o: In function `serial_get_next_line':
main.c:(.text+0x50): undefined reference to `serial_get_received_bytes'
The new versions included in CrossPack AVR will make the above errors go bye-bye.

Step 1.1: Configuring Your Environment

CrossPack AVR installs in the directory /usr/local/CrossPack-AVR.You'll want to set up some environment variables to make sure everything works properly when you compile the libpololu-avr libraries.

First, edit your ~/.profile and add /usr/local/CrossPack-AVR/bin: to your PATH environment variable in front of /opt/local/bin or wherever your old avr-gcc was installed. Like this:
export PATH=/usr/local/CrossPack-AVR/bin:/opt/local/bin:/opt/local/sbin:/usr/local/bin:/usr/local/sbin:$PATH
While we're at it, let's set up the MANPATH too.
export MANPATH=/usr/local/CrossPack-AVR/man:/usr/local/man:/opt/local/man:/sw/man:/usr/share/man:$MANPATH
And, we'll want to set up the C include path.
export C_INCLUDE_PATH=/usr/local/CrossPack-AVR/include:$C_INCLUDE_PATH
We could try to set up the LIBRARY_PATH but the CrossPack AVR linker seems to ignore this environment variable.

Close your current shell and open a new shell window for these changes to take effect.

Step 1.2 Enable ATmega328P Support

You can skip this step if you don't plan on programming an Atmel ATmega328P microcontroller.  The version of avrdude that comes with CrossPack-AVR doesn't support the ATmega328P out of the box so you need to edit the config file and add a section defining it.  This link describes the process. Edit /usr/local/CrossPack-AVR/etc/avrdude.conf and add the text in this link at the end of the file.

Step 2.0: Pololu Software

You'll need to download the Orangutan USB programmer drivers for OS X as well as the new library for Orangutan controllers (libpololu-avr) from Pololu's website.
The drivers come as a .dmg disk image file.  Download the disk image and open it. After the disk image mounts, double-click the "Pololu Installer" icon and follow the directions from there. You'll need to restart your computer when the installation is done.

If you are using a different programmer, you'll have to follow the manufacturer's instructions for getting it ready to use for downloading code.

The Pololu library comes as a ZIP archive.  After you download and unzip libpololu-avr into some convenient directory, you'll need to edit its Makefile to specify where to install the includes and static libraries.  The section of the Makefile you're looking for talks about setting INCLUDE_POLOLU and LIB.  When you're done that section should look like this:
# You can override this behavior by inserting a line below that manually
# sets INCLUDE_POLOLU and LIB to a directory of your choice.
# For example, you could uncomment these lines:
#   LIB := /usr/lib/avr/lib
#   INCLUDE_POLOLU := /usr/lib/avr/include
LIB := /usr/local/CrossPack-AVR/lib
INCLUDE_POLOLU := /usr/local/CrossPack-AVR/include/pololu
Optionally, you can compile the Pololu library from scratch using the command  make clean to wipe everything and then make to recompile using CrossPack AVR's avr-gcc 4.3.3.

Next, install the libraries with the command sudo make install. Enter your password when prompted.

The compilation succeed with no errors.  (Note, version 4.0.2 gave me numerous errors and warnings compiling these libraries as mentioned above).

Step 3.0 Configuring AVR Makefiles

Let's try compiling one of the Pololu examples that come with libpololu-avr. Before we can do that, we have to edit the Makefile.  You'll need to do this with any Makefile you create.

First, we need to fix the linker's search path. As mentioned the linker ignores the LIBRARY_PATH environment variable, so edit the Makefile to add the CrossPack AVR directory to the library search path. Set (or add to) the LIBDIRS variable, which is used to list -L switches which add the specified path to the linker's search path.
LIBDIRS = -L/usr/local/CrossPack-AVR/lib
To include the  microcontroller-specific library, you'd use, for example, -lpololu_atmega168 (or whatever microcontroller you have) when linking objects together.  Set (or add to) the LIBS variable:
LIBS = -lpololu_$(MCU)
Find (or add) the MCU assignment to specify the device (atmega168, atmega328P, etc)
MCU = atmega168
Instead, if there's a DEVICE specified, make that atmega168 (etc).  The example I looked at uses an AVRDUDE_DEVICE set to m168.  Note that the CrossPack-AVR avrdude will recognize the device atmega168 so you can simplify your project makefiles by using a single variable (like MCU) for both the avr-gcc and avrdude command lines.

Now that you have all the preliminaries set up, time to ensure that the linking command includes the LIBS and LIBDIRS variables. Add $(LIBDIRS) and $(LIBS) to your link command in the correct order, LIBDIRS first, LIBS second, appearing after the list of objects, like this:
The order of command line flags is really important.  You must first list your object file, then list the library directory, then list your library, as above. If you list the library first and the search path second you'll probably see an error like this:

/usr/local/CrossPack-AVR-20100115/lib/gcc/avr/4.3.3/../../../../avr/bin/ld: cannot find -lpololu_atmega168
Make sure the avrdude command is correct (we'll revisit this momentarily), something like this:

    avrdude -q -p $(MCU) -P $(SERIAL) -c avrispv2 -e -U flash:w:$(PROJECT).hex

or like this:
$(AVRDUDE) -p $(AVRDUDE_DEVICE) -c avrisp2 -P $(PORT) -U flash:w:$(TARGET).hex
The variable SERIAL or PORT should be defined in the Makefile as /dev/tty.Pololu.

Also, be sure your Makefiles are using the correct avr-gcc.  Just specify avr-gcc as the compiler with no path:
Then make sure that the CrossPack AVR version of avr-gcc is in your path via the command which avr-gcc and if not, did you set up the path variable correctly from Step 1.1?  Did you open a new shell window?

One other thing. If you compile and link the static pololu library but you aren't using all the functions, then you're adding a lot of unnecessary code onto your AVR that is doing nothing but taking up space. To tell the linker to prune out everything except what's actually used, add the option -Wl,-gc-sections to your LDFLAGS like so:

Here's what I got when I did all of the above then compiled the libpololu-avr's lcd1 test program:

$ pwd
$ ls
Makefile    lcd1.aps    test.c
$ make
avr-gcc -g -Wall -mcall-prologues -mmcu=atmega168 -Os   -c -o test.o test.c
avr-gcc -g -Wall -mcall-prologues -mmcu=atmega168 -Os test.o -Wl,-gc-sections -L/usr/local/CrossPack-AVR/lib -lpololu_atmega168 -Wl,-relax -o test.obj
avr-objcopy  -R .eeprom -O ihex test.obj test.hex
rm test.obj
Step 4.0: Programming the Orangutan ATmega

You're ready to download some code to your Orangutan! Here's Pololu's user guide entry on using avrdude with their USB serial programmer (on Windows):

The correct command should already be set up in the Makefile for the Pololu library examples and the demo code. You should be able to simply issue the command make program. For what it's worth, the avrdude command should look something like this:

avrdude -p atmega168 -P /dev/tty.Pololu -c avrispv2 -e -U flash:w:test.hex

The argument following the -p is the part number and should be atmega168 (or m168), atmega48 (m48), etc.  Note that this version of avrdude doesn't support the ATmel ATmega328P microcontroller out of the box, see Step 1.2 after which you can specify atmega328p (m328p) as a part. The argument following the -P is the serial port; On Mac OS X, do an ls of /dev/tty* and you will see the Pololu serial device driver of your Orangutan USB programmer (it should be /dev/tty.Pololu). The programmer ID is specified using the -c option and should be avrispv2. The -e option results in a chip erase and the -U option is used for writing, reading, or verifying flash, EEPROM, fuses, or lock bits. In this example we are using -U to write test.hex to flash.

Running make program with the programmer plugged in but without plugging it into the Orangutan, or leaving the Orangutan off, you will see flashy red/green lights as the software attempts to find the microcontroller, then:
$ make program
avrdude -q -p atmega168 -P /dev/tty.Pololu -c avrispv2 -e -U flash:w:servo.hex

avrdude: stk500v2_command(): command failed
avrdude: stk500v2_command(): unknown status 0xc9
avrdude: stk500v2_program_enable(): cannot get connection status
avrdude: initialization failed, rc=-1
         Double check connections and try again, or use -F to override
         this check.

avrdude done.  Thank you.

make: *** [program] Error 1
If you plug in and turn on the Orangutan, the program should be written into the microcontroller's flash memory. Note that the avrdude command includes the -q option which suppresses the progress indicator hashmarks.  Use this switch when using Emacs.
$ make program
avrdude -q -p atmega168 -P /dev/tty.Pololu -c avrispv2 -e -U flash:w:servo.hex

avrdude: AVR device initialized and ready to accept instructions
avrdude: Device signature = 0x1e9406
avrdude: erasing chip
avrdude: reading input file "servo.hex"
avrdude: input file servo.hex auto detected as Intel Hex
avrdude: writing flash (7944 bytes):
avrdude: 7944 bytes of flash written
avrdude: verifying flash memory against servo.hex:
avrdude: load data flash data from input file servo.hex:
avrdude: input file servo.hex auto detected as Intel Hex
avrdude: input file servo.hex contains 7944 bytes
avrdude: reading on-chip flash data:
avrdude: verifying ...
avrdude: 7944 bytes of flash verified

avrdude: safemode: Fuses OK

avrdude done.  Thank you.

Step 5.0: Integrated Development Environment

Now that you can compile code and download compiled binaries, you need to be able to write code so you need an editor or IDE. But... which editor to choose?

I have been an Emacs geek for 20 years (yikes, I'm old!) so needless to say it is my Integrated Development Environment (IDE) of choice. But it is all text-based. Yes, it is an IDE; you can make / compile code, step through errors, run software, and do anything else you can think of (since it is readily extensible), all within the editor. It is fast and very lightweight (thanks to Moore's Law).

It's old school, but if you learn it well it's quick to use (hey kids, you may not remember the days before menus and mouses, but there are some things that are much faster using keyboard shortcuts). Here's a reference card with emacs key combinations:

Fortunately, you'll find emacs on your Mac but working with many files at once is challenging. Instead, may I suggest you try my preference, Aquamacs, a try: It's Emacs with an Aqua interface. It's quite decent and it puts each file (module, header, etc.) in a separate OS X window. I found this tool really improved my productivity -- and protected my sanity.

Configuring Emacs is pretty simple. To make it as useful as possible, I set up the ability to compile programs within Emacs, as well as stepping through compile errors, by editing / creating the .emacs preferences file to include the following key bindings:

(global-set-key "\C-xc" 'compile)
(global-set-key "\C-xn" 'next-error)

Another option is the Xcode editor. David Beck's Blog has some good information in setting up an Xcode project template with CrossPack-AVR.

And still another option is to use Eclipse, a fantastic, popular, open source, java-based, GUI IDE. It's a pretty big application, takes a while to launch on slower systems, but it is extremely flexible, very nice to use, and powerful. They offer a version with C/C++ plugins that you'll probably want to use for AVR.

One of the folks in a local Colorado robotics club, Dennis Clark, has configured Eclipse to handle both the coding and downloading/programming for AVR. I have the plugins installed but would like to configure it for programming the AVR at the press of a button as Dennis did. Still working on this.

That's All

So there you are. If you go through the above you should be good to go in programming your Atmel ATmega, whether an Orangutan like I'm using, or whatever else. Happy Atmel AVR programming!

Big thanks to Mike Seeman's guide on AVR software for Mac OS X. It's a good guide and you should have a peek. Since I needed to get my environment set up for the Orangutan anyway, I wanted to document the experience and provide an updated, simpler guide using MacPorts, in case it helps someone out there, someday.

Friday, February 19, 2010

Pokey Broke

Pokey's broken. The heat of firefighting competition a couple years ago--accidentally bashing into walls at full speed in particular--left Pokey's otherwise excellent Tamiya Double Gearbox in sad, noisy shape. A quick exploratory surgery revealed that both plastic 8-tooth (8T) pinion gears are cracked. Rats.

Pokey in pieces; broken, purple pinion gear

Pinion gear crack is on left, runs parallel to shaft

Fortunately, Tamiya has an inexpensive replacement set of plastic and metal pinion gears, TAM15289,  Mini 4WD 8T Metal and Plastic Pinion Gear Set.  Cool.  The set I ordered arrived a few days ago and after installation, Pokey's geartrain is restored to full, smooth, silent health. Next up, equipping the plucky little robot with bluetooth remote control and telemetry capability. Articles to follow.

Incidentally, there are other pinion gear alternatives. You'd need a 48 pitch, 8T pinion gear for 2mm shaft. I don't know how to measure pressure angle or pitch diameter, so I guess you'd have to experiment such as with gears from this web store or maybe this one.

Friday, February 12, 2010

Heathkit IO-12 Tube Oscilloscope

I'm happy to report that I got my Heathkit IO-12 vacuum tube oscilloscope working!  It probably needs some additional tweaking, but I learned what I needed to learn about reviving vacuum tube (valve) gear.

Why start with an oscilloscope? I was already familiar with how they work and they are sort of self-diagnosing, unlike audio gear. What displays on the screen gives pretty good clues to the problems.  So troubleshooting was much easier than it would have been on less familiar equipment.

SAFETY: before doing anything with this unit, I made darned sure I played it safe with the literally deadly voltages inside. Most of the supplies range from 100V to 370V, with the video filament driven by a 1500V supply!! Always make sure the machine is unplugged and capacitors drained before working on it. Use one hand behind your back if you must work on the machine when it is on. You don't want electricity going in one hand, through your heart, and out the other hand. Do your own research to be sure you are taking appropriate safety precautions.

The process I took was to follow the schematic an first replace all the old capacitors with new ones from (they happened to have a big enough selection that I could order everything from them). I had to track down a bunch of tubes and got some from friends, and quite a few from eBay. When I finished replacing capacitors and installing tubes, I had some troubleshooting to do. Supply voltages were too high.

The schematic calls for 117V supply but AC here at the house is 125V. This scope like many vacuum tube machines use tube diodes and primitive resistor-capacitor networks to rectify and regulate voltage. So high mains voltage means high internal supply voltages which can burn up tubes and cause other trouble. (See the power supply circuit below; AA through GG are the supplies; 1V2, EZ81, and 6C4 are all vacuum tube rectifiers).

One can use a bucking transformer configuration or zener diodes of appropriate wattage to drop the AC input voltage to ensure the supply voltages are within spec. I happened to have bought some 5W, 10V zeners, and they dropped the voltage to an appropriate level. I then had to try a couple different tubes in the vertical section but pretty quickly got the trace above.

Left: a 6J6 and two 12AU7 tubes glow in the sync-sweep-blanking circuit;
Right: using my capacitor test harness as a signal source for the IO-12

There's little chance of this device replacing my solid state oscilloscopes, and there's not really any practical application of vacuum tube circuits to robotics... but it was a fun project and a good way for me to dip my toes into the wonderful world of tube circuits. The next tube project is a Heathkit frequency generator. After that, a couple of amplifiers.

Monday, February 1, 2010

Playing with Xcode and AppleScript

In case you noticed a post about PDFopener and were curious, I've been playing with Xcode, the Mac OS X development environment. And AppleScript. I guess either could be useful if I ever build a robot with a Mac brain. I wonder how hard it would be to use Xcode to develop for ATmega MCUs. At any rate, the reason for the PDFopener project was that I got sick of problems downloading USPS shipping labels so I dove in and fixed it.

set text item delimiters to ".LabelGenerationServlet"
set stripOther to first text item of fileName
if stripOther is not equal to fileName then

AppleScript is somewhat bizarre to me, an outgrowth of HyperCard's HyperTalk language (anyone remember that?), sort of a pseudo-English programming language. It's a bit mind-boggling for a dude used to C and Perl. I didn't spend any time really learning the language fundamentals but was able to slog my way to making a functional program, chipping away at it little by little with a lot of searching on Trying to do too much at once and it would all fall apart. Like building a house of cards. That's not unlike my robotic coding experiences thus far, actually.