Introduction: Tiny Programmer

If you're into Arduino-and you should be-then you know that there are applications for which you don't use all the processing power or in and outputs.  For these applications, $30 seems like a lot to spend on a project.  Luckily, ATMel, the company that makes the "brains" in most Arduinos, has a solution: The AT Tiny line of microprocessors.  There are several models in different configurations with varying pinouts and memory levels.  The great news is that you can use your Arduino to program these units without having to permanently dedicate your Arduino board to the project.  This is referred to as using your Arduino as an "In System Programmer" or ISP, which is what that "ArduinoISP" sketch in your sketch folder is all about.

The engineers over at MIT's High-Low Tech have a great set of tutorials that get into the nitty gritty of this process based on breadboarding and jumper wires.  This tutorial will focus on a more permanent solution for those who find themselves using the AT Tinys more frequently.  It also assumes a non-beginner level of experience with soldering technique, but you don't have to be a robot in a Shenzhen to make it work.

AT Tinys are available through most of the usual suspects when it comes to mail-order semiconductor suppliers and sometimes in lots  on eBay.  When ordering, make sure to get the DIP version.  If you order the surface mount variety, you're out of luck when it comes to this tutorial.

We'll be limiting the discussion to the AT Tiny 45/85 and 2313 because these units have similar enough pinouts to minimize components and they represent a wide range of the memory and in/out configurations.  (Since I first encountered the AT Tinys, I've gone through projects using about a half dozen Tiny 45's and I'm not a professional engineer.)  If you look at the second image, you'll see the pin configurations for these two units.  The important pins here are Vcc, Ground, Reset, MISO (Master In/Slave Out), MOSI (Master Out/Slave In) and SCL or SCK (which are two ways of saying "Serial Clock.")  Notice that almost all these pins are in the same place on the two packages with the exception of ground, which on the 45/85 is at pin 4 and on the 2313 is on pin 10.  In a permanent solution, if you ran pin 4 to ground on the 2313, it would be hooked up to the pins set aside for the external clock, which could cause problems.  We're going to solve this problem by using a jumper.

The first thing to do, as always, is to gather your materials.  For this Instructable, you'll need the following:
-An Arduino board.  Unos, Megas and Duemillanoves should all work but I use an Uno.  It's the only one I know will work for sure here.
-An Arduino Protoshield (About $18 at RadioShack with varying prices around the interwebs.)  This is a great tool for one-off shield building. It's about half way between a bread board and a custom PCB combining the best aspects of both.  (I suppose you could use an off-the-shelf perf-punched PCB with header pins, but there are problems with orientation if you do that.  I won't go into the mechanics of this approach.)  See the third image.
-One 20 Pin DIP socket  (also in the third image.)
-One more DIP socket (pin number isn't important here, as long as there are at least two on each side-you'll sacrifice this.) Alternatively, an off-the-shelf header pin jumper will work
-At least two break-off header pins, non-stacking.
-1 10 Microfarad capacitor.
-Hook up wire.  (I prefer to use the kind that electricians used to wire telephone lines in the walls of your home back when people still used land lines.  It's about the right gauge and lets you color-code your work consistently.)

Tools:
-Low wattage soldering iron and of course resin-core solder.  (I like to use extra resin when I work.)
-Diagonal Snipping pliers/wire stripper (may be two separate tools)
-Heat sink
-A needle nose pliers may also come in handy
0
Begin by soldering the 20 Pin DIP socket into place on the Proto Shield, as in the 4th image.  Try to be neater about it that I was.  (I was reusing the shield from another project and had some solder bridges across connected perfs that took a while to clean out).  Make sure you don't bridge any adjacent perfs.

Next, add your hook-up wire as in the 5th and 6th images.  As I mentioned, I like to color-code things,  so red goes from pin 20 (Vcc) to the Arduino +5v, black goes from Pin 10 (Gnd on the 2313) to Arduino Gnd, Yellow goes from Pin 1 (Reset) to Arduino 10, green wires go from Pin 17 (MOSI) to Arduino 11, Pin 18 (MISO) to Arduino 12 and from Pin 19 (Serial Clock) to Arduino 13.  Also, hook up an extra black wire to the second open perf on pin 10 and run it to the outer unconnected perf hole adjacent to pin 5, leaving a little more lead than normal, but don't solder it in yet-just strip the end and run it through that hole.

Now we'll put the jumper, which is the two snap-off header pins, in at pin 4 (Gnd on the ATtiny 45/85) and to the outer unconnected perf hole adjacent to pin 4.  Insert the header pins so that the long metal ends stick upwards, not downwards through the board like the other stacking headers pre-attached to the board.  Solder the pin that attaches to the pin 4 trace first, then bend the ground wire sticking through the unconnected perf hole at pin 5 over to contact the remaining header-pin.  Solder these two together as in image 7.

Add the reset 10 Microfarad capacitor across the Arduino Reset and the remaining ground pin on that side, making sure to note the polarity ("-" to Gnd) as in image 8.  Use the heat sink between the board and the body of the cap so you don't fry it while soldering it.  (The smell of burnt electrolytics is just awful.)

At this point, you'll want to make your jumper connector if you didn't buy one or have it laying around.  To make a quick and dirty jumper connector, take your "sacrificial" DIN socket and bend the last two pins on a row over so they touch and solder them together (also in image 8, on the left side.)  Then take your snips and cut out the center rail of the DIP from the end you worked, then separate the two pins from the socket by cutting it at the third pin from the end, which should leave your soldered pins in tact.  Slide your jumper connector down over the two header pins that stick up out of the board as in image 1 (yes, 1-it's more or less complete at this point so I used that as the main image.)  This jumper is just to be used when programming AT Tiny 45/85 chips, so remove it when you program an ATTiny 2313. 

Now, for the programming part.

I'll assume that you know what you're doing with an Arduino here.  The first step in this phase is to download the following two files:
one for the 2313 and one for the 45/85.  The first also has cores for the AT Tiny 84/44 chips, but this programmer WILL NOT WORK WITH THESE TWO VARIETIES.  The pinouts are way too different.  If you try to plug one into this you'll get results from nothing to confusing to a tiny little fire on your workbench.

Once you've downloaded and unzipped these "cores" as they're called, open the file on your computer that contains your Arduino sketchbook and create a folder called "Hardware" if one doesn't already exist and copy these unzipped files into your hardware folder: the entire attiny folder and from the folder arduino-tiny-0100-0010 the subfolder tiny.  (NOTE: I like to keep these on my desktop and copy them in one at a time as I need them.  Otherwise the submenu you'll be selecting them from gets long and headachey.)  If you were running the Arduino environment when you installed the cores, you probably should have known better, but no harm done.  Quit it and relaunch.  If you weren't, just launch it.  (We'll assume you've already got the board installed and running.)  Once the environment is running, just for the heck of it, look under "Tools>Board>" and you should see a bunch of options that were never there before.  For the time being, just leave the actual Arduino board you're using selected (or if for some reason the wrong one is selected, select the correct one.)

Now, sit the AT Tiny IC into the 10 Pin socket you soldered into the shield earlier.  Pin 1 on this IC is marked by a little divot on the top of the chip.  Seat the IC so that this pin is closest to the reset switch.  (I'll be using an AT Tiny 85 for this Instructable.)

For the next part of the tutorial, it's important to do things in the order specified or else you'll get some weird errors as you try to program your AT Tiny.

Now we're going to do something neat that actually cuts the functionality of the Arduino down to a fraction of its capacity.  By using the board as an in-system programmer, you're pretty much bypassing the processor built into the Arduino (actually it's like using it as a switchboard to route signals, but that's really kind of a menial job for the what an Arduino can do.)  In the Arduino environment, open "File>Examples>ArduinoISP" and upload it to your Arduino board.  

Then carefully insert the shield into your Arduino board (See image 9.)

Next, open a new sketch and copy and paste the following code it:


/*
TinyBreather
"Sleep Light" effect for one LED somewhat similar to a computer monitor power indicator when it goes into Sleep mode.
This example code is in the public domain.
*/
int brightness = 0;    // how bright the LED is
void setup()  {
  pinMode(0, OUTPUT);
}

void loop ()
{
  delay(10);
  // set the brightness of pin 0:
  for (int brightness=0; brightness<255; brightness++){
    analogWrite(0, brightness);
    delay (5);
  }    
  // wait for 30 milliseconds to see the dimming effect   
  delay(30);
  for (int brightness=255; brightness>0; brightness--){
    analogWrite(0, brightness);
    delay (5); 
  }    
  // wait for 30 milliseconds to see the dimming effect   
  delay(30); 
  delay(10);
}

// stop copying the sketch here

Once you have this new sketch inserted in the environment, select "Tools>Board>AT Tiny85(w/ Arduino as ISP)" and compile the sketch.  It should work without incident.  Once you have a clean compile, upload the sketch (this will actually be through the Arduino to the AT Tiny, not to the Arduino.)  I can almost guarantee you'll get the following error message:
avrdude: please define PAGEL and BS2 signals in the configuration file for part ATtiny85

Twice in a row, in fact.  Don't worry, that's actually a good sign.  Now we'll test it by taking an LED and placing it in the shield with the positive (longer) lead in socket 11 and the negative lead in Gnd on the same side.  (Note: Best practices would probably dictate that you put a current-limiting resistor somewhere between the LED and the circuit but I have enough of them lying around that I don't mind risking the smokeshow for this demonstration.)  The results should be pretty much what you see in the video here:
http://youtu.be/zlhP15mu9Bo

To run the same circuit independent of the shield/Arduino, you'd just run a regulated power source (+5v) to pin 8 of your programmed IC with ground to 4 and connect the LED across pin 5 and ground.  Just like the Arduino, the AT Tiny will maintain the last program you load into it for quite a while.

The process is much the same for the AT Tiny 45 except of course you'd select "AT Tiny 45 (w/ Arduino as ISP)" as the board to program.  If you were to select the AT Tiny 2313 for your project, the process would be pretty much the same except we'd want to remove the jumper connector, make sure the correct set of cores is installed in the "Hardware" folder and change the pin assignments in the sketch from "0" to "5" -e.g.analogWrite(0, brightness): becomesanalogWrite(5, brightness); see image 2 to make sense of this.

Most of the control commands you would use for the Arduino are available to the AT Tiny, but some of the higher-function commands (things like taking control of the Output Control Registers and the internal clocks) don't quite port directly because the timers and of course outputs aren't the same.)  According to High-Low Tech, the following Arduino commands should be supported:

pinMode()
digitalWrite()
digitalRead()
analogRead()
analogWrite()
shiftOut()
pulseIn()
millis()
micros()
delay()
delayMicroseconds()
SoftwareSerial (has been updated in Arduino 1.0)

I've used all of these and others.  Tone() for example seems to work without any problems.

So the next time you have a great Arduino project but don't want to permanently assign your Arduino to, say, an open door alert or a flashing greeting card, consider the AT Tiny line and if you get addicted, it will be worth the time to make this hardware programmer rather than wear out your breadboard.

Arduino Challenge

Participated in the
Arduino Challenge