There are lots of proto boards for the AVR microcontroller, and lots of programmers. This post presents my approach, which features easy assembly, off-the-shelf PCB, extremely low parts cost and a built-in USB-based programmer. Circuit, PCB and firmware are all completely Open Source. Read on after the jump for details.
Overview
I haven’t really invented anything new here; I’m just putting together components that other people have developed. Consider this a roadmap to getting to a prototyping system easily and cheaply, so you have more time and money left over for the inventive part.
So what is all this? I started with an ATmega328P, a handful of inexpensive components and a business-card-sized proto board from Evil Mad Scientist Laboratories. With these, I implemented something very much like the Metaboard circuit. The microcontroller has the USBaspLoader firmware in the top 2K of memory as a bootloader.
What does it do? It’s a USB target device; plug it in to a host and it will be powered from the bus. If a jumper (shorting PD7 to ground) is closed at boot time, it will mimic a USBasp programmer, and you can program the microcontroller as normal. After programming is done (or if the device is booted or reset without the jumper), whatever application code you flashed runs normally.
Advantages: Super-cheap, low parts count and self-contained. This plus some free software is a complete development environment. You can use the circuitry already in place for your own USB target applications. Easy to make: no PCB etching or surface-mount soldering, and all components are easy to get. Bootloader firmware is write-protected so you can’t clobber it by mistake. Some prototyping space available on the board.
Disadvantages: You need some other programming device to load the firmware to begin with. Uses PD4 and INT0 pins (for USB) and PD7 (for jumper detection). Requires an external crystal (thus you can’t use XTL1, XTL2 for IO). Not the neatest layout in the world. This isn’t a “real” USB target device (it doesn’t fully comply with the standard) though it does interoperate fine with all USB hosts I’ve tried. 2K (out of 32K) of flash is taken up by the bootloader, and not available for your application.
Parts List
All prices are in US dollars, omitting tax and shipping, current at the time this post was written. Vendors are listed as a convenience only; no endorsement is implied (except for Evil Mad Science, who are awesome). Update: Note that prices are for new parts in single-unit quantities from a big-name retailer; if you buy in bulk or shop around, you can get much lower prices. The PCB is the only thing that isn’t a commodity part.
- (1) ATmega328P microcontroller (Mouser, $4.28)
- (1) ATmegaXX8 Target Board (Evil Mad Science, $3.00 ea. or $11.50 for five)
- (1) 28-pin DIP socket
- (1) 12.000 MHz crystal (Mouser, $0.22)
- (2) 20pF capacitor (Mouser, $0.07 ea.)
- (1) 0.1μF capacitor (Mouser, $0.09)
- (1) 10μF electrolytic capacitor (Mouser, $0.09)
- (1) 1MΩ resistor (Mouser, $0.05)
- (1) 1.5KΩ resistor (Mouser, $0.05)
- (2) 68Ω resistor (Mouser, $0.05 ea.)
- (2) 3.6V Zener diode, 1N5227B or close equivalent (Mouser, $0.06 ea.)
- (1) NO pushbutton switch
- (1) 2-pin 2.54mm breakaway header (Mouser, $0.16)
- (1) jumper block to fit breakaway header
- (1) cable USB “A” to pigtails
- about 10cm of hookup wire
Any microcontroller in the ATmegaXX8(P) family should work, though if you’re going to go to the trouble of building this, spending a few tens of cents on extra flash memory seems like a prudent idea. A DIP socket is, strictly speaking, optional, but not having it is a genuinely bad idea. (Update: a 28-pin DIP socket is a bit of an oddball size. If you don’t have one handy, you can substitute a 20-pin socket plus an 8-pin socket.)
The resistors can be the regular old 5% 1/4W metal film kind from the spare parts bin.
The 20pF caps are for loading the crystal. The cheap dipped ceramic kind work fine. You might be able to get away with 22pF if that’s what you have on hand (but make sure they match!). If you pick a different crystal speed, check the specs to find the right loading capacitor value.
The 0.1μF and 10μF caps are just there to bypass high-frequency noise on the power supply. The values aren’t critical, so long as you’re in the ballpark.
The crystal can be 12, 15, 16 or 20MHz. (Make sure you get one with at least five significant digits, e.g. 12.000.) You might also be able to substitute a three-pin crystal oscillator for the crystal and loading caps.
The Zener diodes are there to clamp the USB D+ and D- voltages to 3.6V (rather than the native 5V) when the AVR is driving the data lines. Most modern USB hosts deal with 5V on the data lines just fine, but some older ones do not. Not just any 3.6V Zener diode will do; the high-current ones switch too slowly and distort the USB waveform too much. Get the 1N5227B rated for 20mA Zener current.
The pushbutton switch is for reset. It’s totally optional, but convenient. Use any junk-box normally-open switch you like. (I salvaged mine from a broken stereo receiver.)
The breakaway header should fit the kind of jumper you see on computer motherboards and hard disks. The jumper is there to let you select if the bootloader or application runs when power is first applied. You could use an SPST toggle switch instead if you like.
The least expensive source I found for the USB cable was to buy a USB “A” to “B” cable at the dollar store, then hack off the “B” end. I tied the cable to the circuit card with a zip tie for strain relief.
The version in the picture has a six-pin ISP header. You can certainly add one if you like, though it probably won’t be much use unless you’re developing new bootloader firmware or doing in-circuit debugging or something.
Update: Everything except the PCB, microcontroller, crystal and Zener diodes I was able to supply from my (very modest) stock of parts and salvage bin.
Construction
Start by having a look at the Metaboard schematic (link goes to original Metalab site). My circuit is essentially the same, but without the provision for a separate power source, and none of the extra headers.
There are many similar circuits around the ‘net, and variety is good. However, I’m not fond of the designs that regulate the USB +5V down to 3.3V (using a couple diodes or a low-drop voltage regulator). My understanding is that the ATmega328P needs a Vcc of +5V for clock speeds over 10MHz.
The picture at the top of the article shows the layout I used, which certainly works but isn’t really ideal. (I’m especially offended by how I routed the D+ line — the white wire — under a resistor lead.) It would probably be improved by swapping the vertical columns used by the D+ and D- stuff.
The USB D+ line must be connected to a hardware interrupt (INT0 or INT1). USB D- and the jumper detect can go to any (two different) general-purpose IO lines. (Out of the box, the USBaspLoader software expects PD4 and PD7 respectively, so that’s what I used.)
Having a hardware reset line is optional, but makes the development cycle a lot more convenient. (You can flash, test, reset instead of flash, test, unplug, re-plug). If you need one more IO pin really badly, you can always disable reset in the fuses and use PC6 instead.
I used small lengths of recycled component leads to jumper AGND to ground, AREF to Vcc, AVCC to Vcc and the four eight-pin rails in the prototyping areas to whichever of ground or Vcc was nearest. This should be a good choice for most applications, but feel free to alter as needed.
If you’re the careful sort, plug the newly-assembled board into a cheap USB power supply first, before risking an expensive computer. If something gets hot, smells bad, emits smoke, catches fire or explodes: that’s not part of the design. Check your wiring.
Firmware
The 2010-07-27 version of the USBaspLoader firmware works just great for me with no major changes. (Earlier versions could be something of a hassle if you had an ATmega328P, GCC 4.x and/or certain crystal speeds.)
You’ll need to edit the Makefile to set the correct values for clock speed, device type, bootloader address, fuse bits and programmer.
If you have changed any of the pin assignments during construction, edit bootloaderconfig.h to reflect your choices.
Also in bootloaderconfig.h, I edited the bootLoaderInit() function to remove the check for external reset. (I found it more convenient to have the board run the bootloader code at power-up if the jumper was set.)
When you build, make sure the result is smaller than 2K. (I made it with 4 bytes to spare!) If you really need more space, the 328P supports a 4K bootloader (but you’ll need to change the fuse bits, and you give up 2K of flash your application could otherwise use).
Obviously, you need some other programmer to get the firmware on there in the first place. (If a friend or a local hacker space has a programmer, you’re all set — you should only need it once at build time, not for subsequent development.) If you need to buy one, I’ve had great success with Lady Ada’s USBtinyISP (available as a nice kit for $22.00). The AVR Dragon (about $50.00, needs some additional parts) is more expensive but very capable; see my article about it here on SGS.
When you’re loading the microcontroller, remember to double-check the fuse bits before you do anything, and to set fuses, flash and set lock bits in that order.
How to Use
Close the jumper. Make sure the board isn’t sitting on anything conductive. Plug it in to a USB host. Use as you would a real USBasp programmer connected to a proto board via ISP headers.
After any use of the programmer (even if you just query the device signature or something), it will jump to your application code.
To go back to being a programmer, press the reset button.
If you open the jumper, it will run your application (immediately, and after any power-up or reset). It is safe to move the jumper without disconnecting the board from the USB host.
If you are using the avrdude command-line utility for programming, use the option “-c usbasp” to specify programmer type. (You need not specify the port.) For UNIX-alikes: if the avrdude command gives you permissions-related errors when run as a non-root user (but works fine when run as root), you may need to set different group, owner and/or permissions for the device node. (This can be done automatically at device insertion time, but the specifics depend on distribution and version.)
It is possible to use this board with the Aduino IDE, but doing so is beyond the scope of this post. See the Metaboard page (Metaboard for Arduino Users section) for details.
Note that you will be unable to read or modify fuses or lock bits, you can’t do a chip erase, and you can’t write to the top 2K of flash.
Troubleshooting
For troubleshooting, I’m going to assume you’re using a Linux system of recent vintage (because that’s what I have). While you can certainly use this design with various other OSen, I don’t know enough about how the low-level USB stuff works on any of them to give out advice.
Throughout, I’m going to use “sudo” as generic shorthand for “you probably need to be root in order for the following command to work”. On Debian-alikes (like Ubuntu), then the “sudo” is literally correct. Other distros may have different preferred ways to do privilege escalation. (If you don’t have root, then what are you doing plugging experimental hardware into the box?!)
Start with the jumper in place and the board disconnected. Run “sudo dmesg -c” to clear the kernel message ring buffer.
Plug in the board. If your machine shuts down, there’s probably a short between Vcc and ground, and that’s bad. Assuming you’re still up and running, try “lsusb”. You should see output like this:
Bus 002 Device 020: ID 16c0:05dc VOTI USBasp AVR Programmer
The bus and device numbers may vary, but the ID and text string should be as described. You can also look at the output of “sudo dmesg” which should be include something like this:
usb 2-2: new low speed USB device using uhci_hcd and address 20 usb 2-2: configuration #1 chosen from 1 choice
If you see the above, try “sudo avrdude -c usbasp -p atmega328p -v” and see if you get a chip description. If so, congratulations: it’s working. (Remember that it jumped into application space as soon as it got done handling a single programmer command. Hit reset to get back to programmer mode.)
If you don’t see the above, check the jumper, wiring and component values. Try a different USB port or a different computer.
Still no joy? Double-check that you selected the correct device type, clock speed, fuse bits and bootloader offset when you built USBaspLoader. (A 2K bootloader on the 328P should go at address 0x7800.) Did you “make fuse” then “make flash” then “make lock” ? Did you look carefully to see if any of those steps yielded an error message? If you read back the flash contents and fuse bits, do you get something that matches what you think you put there?
Using another programmer, try loading some plain vanilla VUSB application and see if it works with the board. If not, it’s the circuit or components. If so, the bootloader firmware is wrong.
Have a ‘scope? See if the crystal is in oscillation, and if the USB waveform looks tidy.
Credits
Thanks to the Objective Development crew, and especially to Christian Starkjohann for the patient, prompt and extremely helpful responses to my email. The new USBaspLoader release is all shiny.
Thanks to Metalab for the idea that got me started, and for the Metaboard circuit design and schematic.
Thanks to Evil Mad Science and Lady Ada for lowering the barrier to entry by making stuff that’s cheap, easy and works.
Thanks to the cast of thousands involved in creating the Open Source operating system, cross-development tools, text editors, file utilities, web browser and every other bit of free software I used in the process of getting this to work.
Thanks to everyone in the AVR homebrew community who took the time to put example code, circuits and useful clues on the ‘net.
Thanks to JDA and WBD for being beta testers.
Fine Print
All information is presented as-is, with no warranty either expressed or implied. If you build or do anything based on the information from this post, all consequences are your sole responsibility.
Wear eye protection when soldering, when cutting component leads and when doing anything else that flings nasty bits of stuff through the air. Solder and soldering tools get hot. Solder is toxic (even when not molten).
Never hack hardware you can’t afford to destroy.
Full disclosure: I have no relationship to any of the businesses mentioned here other than possibly as a customer.
All trademarks and copyrights are acknowledged as the properties of their respective owners, and nothing herein is intended as a challenge to that status.
[Edited 16 August 2010 by DGH to make small corrections and add additional notes about parts sourcing.]