How to roll your own programmable Arduino/AVR board

How to roll your own programmable Arduino/AVR board

Arduinos are perfect for development: you just plug them into a USB port and all the old hassles of dealing with AVR chips (crystals for clocking, hooking up comm lines, regulating power…) are handled for you.  But sometimes you need to roll your own custom solution.

Barebones "FTDI" circuit for programing of, and communication with Arduino.

Barebones “FTDI” circuit for programing of, and communication with Arduino.

In real life–whether because of size, cost or power related constraints–it often pays to get rid of unnecessary fluff like the USB connection and move things over to a custom designed board.  On occasion, I’ll use an Ardweeny or the like and be content with hooking up an FTDI-type connector to its header for eventual firmware updates.

When you’re going really minimalist–say you want to use an ATTiny or just wish to have everything on a single PCB (rather than something like the stacked Ardweeny)–it’s still very useful to be able to update the microprocessor while it’s in-circuit.  Here are the two ways I go about this, with some example circuits and the some hints on how to decide which way to go.

The circuits here both assume a Mega168 (or ‘328) which have the standard Arduino microprocessor pin-outs, though you could use similar arrangements with many kinds of MCUs.

In both cases we’re creating our own board rather than relying on a pre-built Arduino, which means we need a few support components: a resonator (or crystal and caps) to clock the microprocessor and a capacitor to stabilize power.  I like to use a 3-pin 16MHz resonator, rather than a crystal and caps, because it just works and reduces the part count.

USB (using USB-to-TTL/FTDI-type cable) Programming/Communication

Easy and closest to the classic Arduino Experience(tm).

Pros Cons
  • Acts and is programmed just like a regular Arduino
  • Use the regular Serial.print() and serial monitor to interact with the device, through USB (FTDI).
  • Power the circuit from the USB port
  • You need a USB-to-TTL FTDI-type cable/adaptor
    a regular Arduino
  • Only works with Arduino, or chips with a similar bootloader that handles communication and programming through the UART.


Supporting this functionality is very simple and the fact you can power the entire circuit through the USB port is cool, especially for projects that involve lots of communication with a host over USB.

Barebones "FTDI" circuit for programing of, and communication with Arduino.

Barebones “FTDI” circuit for programing of, and communication with Arduino.

You may download an Eagle schematic of this circuit, if you like.

The main thing to be careful with here is marking your board so you avoid inserting the cable/breakout the wrong way.

Unless you need access to low-level stuff, the only real downside of this approach is the requirement for an external FTDI connector.  They’re not very expensive, and you can get by with just one cable by hooking up to the 6-pin header when needed.

USB-to-TTL breakout, based on FTDI, used to program and communicate with Arduino, etc.

USB-to-TTL breakout, used to program and communicate with Arduino, etc.


In-Circuit Serial Programming (using an ISP)

ICSP is really useful when you want low-level control of the device, are using an AVR that isn’t Arduino compatible and/or you want to be able to hook into the SPI lines.

Pros Cons
  • Can program Arduino or “bare metal” AVR chips (can install Arduino bootloader)
  • Can manipulate microprocessor flash, eeprom and fuses (special control registers)
  • Provides easy access to SPI lines
  • You need an ISP programmer (which you can easily build using an Arduino, or simply purchase)
  • You must power the circuit independently
  • the Arduino USB “serial communication” functionality doesn’t happen through the ISP header

Though some ISP devices can provide power to the circuit, the standard setup has the ISP header ground and VCC actually sourcing current into the programmer.  This means you need to provide a steady voltage to the circuit yourself, so the example above includes some pads for connecting the power source, a jumper to allow for a switch or other method of selecting whether or not to allow current to flow and a small 7805 voltage regulator to ensure we don’t fry the ‘mega.

Barebones In-System Programming (ISP) circuit, with a sample layout.

Barebones In-Circuit Serial Programming schematic, with a sample layout.

You may download an Eagle schematic of this circuit, if you like.

There are actually two versions of the standard AVR ISP header: a 10-pin and a 6-pin version.  Other than taking up more space on the board, the 10 pin ISP header has no additional functionality (just a bunch of extra grounded pins), so I prefer to use the 6 pin (2×3) version.  Either way, either use a socket which forces cables to line up correctly, or find a way to clearly mark pin 1 so you don’t connect the programmer upside down.

When I started playing with this, I pulled out my old AVR development stuff (and STK500 board and an ISP programmer).  Both expect the terminal to communicate with them using the serial port and, oddly enough, I couldn’t find such a port on my laptop (or most of the machines at my disposal, for that matter).  Hmmm.

Thankfully, there are a number of USB-RS232 cables available (often for less than $5).  The other issue was that the ISP programmer had a cable for the 10pin ISP header.  There are 10-6pin adaptors available online, but a little peak inside the Atmel ISP programmer’s plastic shell revealed a nice surprise: support for both 10 and 6 pin cables.  Yay!  A quick cable switch and it was good to go.

Atmel ISP programmer (with a nice surprise inside) and USB-to-Serial cable used to access the old device.

Atmel ISP programmer (with a nice surprise inside) and USB-to-Serial cable used to access the old device.

The final thing was actually programming Arduinos.  I love Arduino but find the IDE hides way too much stuff under the hood, which causes a bunch of problems for edge cases (and it would seem I spend a great deal of time out on the edge).

Because my serial ISP is pretty oldschool, the arduino IDE couldn’t figure out how to talk to it and kept spewing out synchronization errors, even though I’d selected “AVR ISP” as the programmer.  The problem was resolved by using avrdude manually.

If you locate the compiled Intel hex file (in the temporary directory /tmp/buildSOMESTRING.tmp/, under Linux), you can run avrdude on the command line by specifying the correct port (-P), part (-p), programmer (-c) and operation (-U).  For me, this was:

$ avrdude  -P /dev/ttyUSB0  -p m328p -c stk500v1 -U flash:w:MyCode.cpp.hex

Which says: connect to the stk500v1 programmer on /dev/ttyUSB0 and write to the Mega328P’s program memory (“flash”) using the contents of file “MyCode.cpp.hex”.

An interesting use of avrdude through the ISP is terminal mode, where you can interact with the chip directly.  To enter terminal mode, replace the -U option with a -t:

$ avrdude  -P /dev/ttyUSB0  -p m328p -c stk500v1 -t

Once connected, type help and avrdude will provide some info on what you can do.  The most interesting of these commands are “part” to display the current part settings and parameters, “dump” to examine the memory (flash ROM, eeprom, fuses…), and “write” to set bytes in any of the memory blocks.  See the avrdude man page for more info.

Hopefully, the above will be helpful in selecting the best method to move to your own custom circuit boards while preserving the ability to program the microcontrollers.  Please don’t hesitate to get in touch if you have any comments or questions.

Have fun!

Leave a Reply