Playing with the ATtiny85 I was struck by how simple the circuit was. Sure, I'd made a homemade Arduino on a breadboard; but with the crystal and all the extra capacitors and resistors it ends up seeming like a lot of parts and wires. If an ATtiny can use a built-in clock and not need all those extra parts, couldn't I use an Atmega328 the same way?
Wiring a bare Atmega chip is easy. You'll want to keep a good pinout diagram handy, like this Arduino ATmega328 Pinout from HobbyTronics.
For the initial wiring, all you need is two power and two ground lines, the pins marked - and +, plus a pullup resistor on RST (something large, like 10kΩ). The excellent tutorial From Arduino to a Microcontroller on a Breadboard is a good guide if you need additional details: the third section shows a circuit without external clock.
Add an LED and resistor on pin 13 (atmega pin 19, called SCK) so you can test it using a blink program.
Now you need to set up the software.
Set up a hardware profile for a bare Arduino
To program it with the Arduino libraries, you'll need a hardware definition for an atmega328 chip with an internal clock. I used the download from the last section of the excellent tutorial, From Arduino to a Microcontroller on a Breadboard. (Keep that page up: it has good wiring diagrams.)
For Arduino 1.8.5, download breadboard-1-6-x.zip and unpack it in your ~/sketchbook/hardware/ directory, making a directory there called breadboard. Then you'll need to make one change: the 1.6 directory is missing a file called pins_arduino.h", so if you try to compile with this hardware definition, you'll get an error like:
mkdir -p build-atmega328bb-atmega328 /usr/local/share/arduino/hardware/tools/avr/bin/avr-g++ -x c++ -include Arduino.h -MMD -c -mmcu=atmega328p -DF_CPU=8000000L -DARDUINO=185 -DARDUINO_ARCH_AVR -D__PROG_TYPES_COMPAT__ -I/usr/local/share/arduino/hardware/arduino/avr/cores/arduino -I/home/akkana/sketchbook/hardware/breadboard/avr/variants/standard -Wall -ffunction-sections -fdata-sections -Os -fpermissive -fno-exceptions -std=gnu++11 -fno-threadsafe-statics -flto blink.ino -o build-atmega328bb-atmega328/blink.ino.o In file included from :0:0: /usr/local/share/arduino/hardware/arduino/avr/cores/arduino/Arduino.h:257:26: fatal error: pins_arduino.h: No such file or directory #include "pins_arduino.h" ^ compilation terminated. /usr/share/arduino/Arduino.mk:1251: recipe for target 'build-atmega328bb-atmega328/blink.ino.o' failed make: *** [build-atmega328bb-atmega328/blink.ino.o] Error 1
The problem is that it's including these directories:
but the actual file is in:
You can fix that by making a link from the "standard" directory in your Arduino install to breadboard/avr/variants/standard. On Linux, that would be something like this (Mac and Windows people can substitute their local equivalents):
ln -s /usr/local/share/arduino/hardware/arduino/avr/variants/standard ~/sketchbook/hardware/breadboard/avr/variants/
Now your hardware definition should be ready to go. To check, fire up
the IDE and look in Tools->Board for
ATmega328 on a breadboard (8 MHz internal clock).
Or if you use Arduino-mk, run
ALTERNATE_CORE=breadboard make show_boards
and make sure it lists
atmega328bb ATmega328 on a breadboard (8 MHz internal clock).
Reprogram the Fuses and Bootloader for an Internal Clock
The next trick is that an Atmega chip programmed with the Arduino bootloader is also fused to use an external, 16MHz clock. If you wire it to use its internal 8MHz clock, you won't be able to talk to it with either an ISP or FTDI.
You'll definitely run into this if you pull the CPU out of an Arduino. But even if you buy new chips you may see it: many Atmega328s come pre-programmed with the Arduino bootloader. After all, that's what most people want.
The easiest way to reprogram the fuses is to use the hardware definition you just installed to burn a new bootloader, which resets the fuse settings at the same time. So you need an In-System Programmer, or ISP. You can use an Arduino as an ISP, but I'm told that this tends to be flaky and isn't recommended. After I had problems using an Arduino I ordered a cheap USBtinyUSP, which works fine.
Regardless of which ISP you use, if you wire up your atmega without an external clock when it's fused for one, you won't be able to burn a bootloader. A typical error:
[ ... ] Reading | ################################################## | 100% 0.02s avrdude: Device signature = 0x000000 (retrying) Error while burning bootloader. Reading | ################################################## | 100% 0.02s avrdude: Device signature = 0x000000 avrdude: Yikes! Invalid device signature. Double check connections and try again, or use -F to override this check.
The solution is to burn the bootloader using an external clock. You can add a crystal and two capacitors to your breadboard circuit if you have them. If not, an easy solution is to pull the chip out of the breadboard, plug it into the socket in an Arduino and burn it there. (Note: if you're using an Arduino as your ISP, you'll need a second Arduino.)
Plug your ISP into the Arduino's ISP header: on an Uno, that's the header labeled ICSP at the end of the chip farthest away from the USB plug. It's a six-pin connector (2x3), it's easy to plug in backward and you can't depend on either the Arduino's header or the ISP's cable being labeled as to direction; if in doubt, use a multimeter in continuity mode to see which pin is ground on each side, then make sure those pins match. Once you're sure, mark your connector somehow so you'll know next time.
In the Arduino IDE, set Tools->Board to ATmega328 on a breadboard (8 MHz internal clock), set Programmer to whatever ISP you're using. then run Tools->Burn Bootloader.
If you're using Arduino-mk instead of the IDE, set up a Makefile that looks like this:
ALTERNATE_CORE = breadboard BOARD_TAG = atmega328bb ISP_PROG = usbtiny include /usr/local/share/Arduino-Makefile/Arduino.mkSubstitute your ISP, if different, and your location for Arduino.mk. Then type
Once you're wired, you should be able to program it either with an FTDI board or an ISP, as I discussed in homemade Arduino, Part 1. You should be able to use your minimal Atmega328 to run anything you can run on a normal Arduino (albeit at half the clock speed).
I plan to make a little board with a ZIF socket and connectors for
both the USBtinyISP and the FTDI Friend so I don't have to plug in
all those wires again each time.