Arduino, Featured, Members, Tutorials
comments 4

Small, Programmable, Wearable and Cheap – Enjoying the ATTiny85 Tutorial

tinythumb
Joshua Noble is a Developer/Writer/Designer from Cascadia and author of Programming Interactivity book. He is available at thefactoryfactory or at @fctry2

tinycover

Ok, so let’s talk cheap and tiny: programmable computers needn’t be large precious things, they can be tiny things that we can leave behind, let go, abandon to the cruel world. I’m not advocating being overly irresponsible or wasteful, but I do think that the world and the things that you can make in it gets a lot more interesting if you don’t have to worry inordinately about protecting your project. An Arduino or Raspberry Pi, wonderful tools that they are, are not cheap, somewhat demanding of battery life, and as such we usually need to protect our controller and modify our project to fit their form factors. As a teacher, I can’t count the number of times I’ve seen an Arduino used to listen for a button press or wait for a door to open.

attiny85Wouldn’t it would be nice to have something small, programmable, cheap, and power efficient that could do *some* of what an Arduino can do and had the same easy tools to use with it? Well there is: the ATTiny85! In the DIP configuration, that is, with the little breadboardable pins that we’re used to working with like the one that’s shown here, the ATTiny85 (which I’m going to call the Tiny85 from here on out) is about 9mm x 9mm, can be programmed using the Arduino IDE, runs on as low as 3.3V at pretty tiny amperages (think watch batteries), and can be bought for around $0.70USD (picture courtesy of SparkFun).

Before we dig into the technical details, I want to talk a bit about why little microcontrollers like this are important.

Boards, Pads, and Dust

Back in 1988 Mark Weiser, one of the godfathers of HCI, proposed three kinds of devices that would make up the range of computing platforms that people would engage with in ubiquitous computing:

1) tabs: wearable centimetre sized devices, think of a FitBit or a small wearable computer
2) pads: hand-held decimetre-sized devices, think of a smart phone or a
3) boards: metre sized devices, like a laptop or TV

So, that’s about the limit of things that we commonly think of, but there’s another category of things that are just emerging, that we could just call “dots”: millimeter-ish things that allow for simple interactions, don’t require a screen, and don’t do a whole ton of things (or even multiple things) but are really good at the thing they do. Now, the thing about the Tiny85 is that, even taking into account the Sifteo, it’s probably the smallest thing we in the creative code community have easy access to and it offer us up a lot of different ways of thinking about the nature of things that we create and how they can in the world. When we’re working with Arduinos or Raspberry Pi’s or Linux laptops or ubiquitous MacBooks, all of these things are of course exponentially more portable than the computer of 20 years ago, but they’re definitely not Dots, nor are they dispable. Let’s be honest, nothing *should* be disposable, I’m not talking about things that are meant to be thrown away, I mean more things that *can* be damaged or lost without breaking the bank or running your final grade in a class, losing your job, or anything else generally “horrible”. The real strength of the Tiny is threefold: it has a tiny form factor, you fit it anywhere; it requires very little power, you can run it on a watch battery; it is extremely low-cost. It is the last of these that accentuates the first two: tiny, low power things that you can lose, let go, let be in the world without interference. The real world, filled with water, birds, janitors, clumsy children, it’s all quite cruel to electronics. If we want to be honest, we should let things be mean to our machines. Ok, that’s my little soapbox out of the way, now onto making things.

Introducing the Tiny85: a cheap and fast way to make tiny smart things. The chips themselves can be bought for between $0.45 USD and $1.25 depending on where you’re buying them from. As with many things, the more that you buy, the cheaper they get. Typically you program them with the AVR programmer, but with their renewed popularity there are multiple options for programming your controller, the most convenient of which has to be the Arduino Cores from the High Low Tech group at the MIT Media Lab headed by David Melis, a member of the Arduino core team. Because this is so much easier than the other ways of doing this, we’re going to focus on how you use this way of programming the chip. There are other options that I’ll point you after walking through the easiest way.

The Tiny has 8 pins, shown in the diagram below:

ATtiny45-85

There’s a limited subset of the Arduino functionality that will work on the Tiny. A quick list of what will work: pinMode(), digitalWrite(), digitalRead(), analogRead(), analogWrite(), shiftOut(), pulseIn(), millis(), micros(), delay(), delayMicroseconds(), SoftwareSerial. A quick list of what will not: Serial() and pretty much any library that you’re used to using. There are libraries that will allow you to work with I2C and SPI, but theres not nearly as many as there are for the ATmega based Arduinos, unfortunately. However, the Tiny85 is really meant to be used on small stuff, not larger complex projects like those that are done with the larger Arduino. Alright, on to the actual doing of things.

10uF_50V_Radial_Electrolytic_CapacitorFirst things first, you need a 10 micro-farad polarized capacitor. This will probably look like this:

Note the white stripe on the side of the capacitor, this is the grounded side of the capacitor and it needs to connected to the ground of your Uno. Your capacitor may be with blue with a black stripe, but the stripe is still the ground.

You’ll also need a breadboard and shielded wires to connect the ATTiny85 to the Arduino Uno, these can be jumper wires or just 22 or 24 guage shielded wire. So, assuming that you have breadboard, wire, a capactior and a Tiny85 and an Uno, you can turn the Arduino into a programmer for the Tiny.

Step 0 Installing the Cores

First things first, you need to run through the following checklist:

A) Do you have Arduino installed? No? Please go install it.
B) Do you have an Arduino Uno? No? Em, go get one.
C) Set up your Arduino home directory.
D) In your Arduino home directory, make a folder called “hardware”.
E) Download the High-Low-Tech “cores” here and drop them in the hardware folder you just made.
F) Open up the Arduino IDE and look at the Boards. Does it look like this? Yes? You’re good to go.

 

Step 1 Making a Programmer out of the Uno

boardsThe first thing you need to do before writing any code for the Tiny85 is to put the program that will load the programs you write onto the Tiny. This is the “programmer” for the Tiny and it’s what takes the compiled bits from your computer and places them on the Tiny. Because the Arduino has a USB port, you don’t need a programmer for the Arduino. Because the Tiny doesn’t have a USB port, you do need one, hence the need to turn the Arduino into something that can translate the bits of your compiled program into electrical pulses that the Tiny can understand. So the first step is to load the programmer onto the Uno.

In the download from the High Low Tech group you should see a project file called ArduinoISP. You need to get your Uno attached to your computer like you would for any other Arduino sketch and then load the sketch onto your Uno. Now it’s time to attach the capacitor that you have the Ground and Reset pins of your Uno. This keeps the Uno from resetting while it resets the Tiny85, turning it from a regular Arduino into an Arduino as ISP. It should look like this:

capacitor

Note that the stripe is connected to ground, that’s important.

Step 2 Burning the Bootloader

Now you can “burn the bootloader” on the Tiny (we’ll explain this in a minute). This diagram (made with the marvelous fritzing) shows how you connect the Tiny to the Arduino so that you can program the Tiny and you need to do this before you “burn the bootloader”. Burning the bootloader is simply defining what all the different pins on the Tiny are going to do and giving the Tiny some simple instructions on how to initialize the code that it’s going to receive from the Arduino IDE through the Arduino Uno. This is an important step because by default the pins and initialization sequence in the Tiny aren’t configured correctly to allow the Arduino software to run correctly on the Tiny. As I said though, before you burn the bootloader though we’ll need to connect the Tiny to the Uno. The dot in the corner of the ATTiny will help you orient the ATTiny correctly.

wire_programming

ATtiny Pin 2 to Arduino Pin 13
ATtiny Pin 1 to Arduino Pin 12
ATtiny Pin 0 to Arduino Pin 11
ATtiny Reset Pin to Arduino Pin 10

Next connect a 10 uF capacitor between reset and ground on the Arduino board as shown in the diagram. The capacitor prevents the Arduino board from resetting (which starts the bootloader), thus ensuring that the Arduino IDE talks to the ArduinoISP (not the bootloader) during the upload of sketches.

1) Select which core you want to use. If you’re using the MIT cores you have three options: 1Mhz, 8Mhz, or a 20Mhz using an external timing crystal. You’ll probably want to use the 8Mhz mode to begin with. This is important because it tells the Arduino which bootloader you’re going to burn onto the chip.

2) Select what you’re going to use as a programmer. In this case you’re using the Arduino Uno as the programmer, so you’ll select “Arduino as ISP” from the programmer drop down:

select_as_isp

3) Now, you burn the bootloader (which you’ve selected in the first step) using the programmer (which you’ve selected in the second step). And that’s the third step. It should take about 1-3 seconds.

burn_bootloader

Ok, now you’re ready to load some code.

Step 3 Helloworld = Blinking an LED

Alright, you’re ready to put some code on your Tiny. The blinking of an LED is pretty much the Hello World of physical computing, so let’s go ahead and do that. The code should be familar:

int led = 0;

void setup() {
// set pin as output
pinMode(led, OUTPUT);
}

void loop() {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}

There is one important change though: int led = 0. Because the Tiny only has 5 pins that you can use, the default of 13 isn’t going to work here, but 0 – 4 will work just fine as long as you remember to configure them as output pins, using the pinMode() method.

You can wire the Tiny85 to draw power from your Arduino Uno just by connecting the 5V out and ground from your Uno to the VCC pin and ground of your Tiny85. Or you can use a watch battery to power the Tiny85 though be aware that the lower power that you use, the slower the mC will operate. Beware when you’re buying batteries though as anything over 6V can damage your Tiny, anything under 3.3V and it won’t run properly. My preference is get find 2 3V batteries and tape them together in series or use a single 6V one with wires that can be attached to a breadboard or to the Tiny.

3Vpower

Step 4: Analog IO

ADC – ADC is the process of turning an analog signal into a digital one, turning a voltage range into an integer value. The Tiny85 actually has 3 pins that can process an analog signal and turn it into a digital value: 2, 3, and 4. This means you can attach a potentiometer or rotary encoder at any one of those pins, as long as you’re sure to call set the mode of the pin using the pinMode() method. Anything that can operate on a PWM signal, be it an LED or a motor, can be attached to the Tiny85. One thing to keep in mind though: larger motors pull a lot of current and power and that’s something that you’ll probably want to avoid while working with the Tiny85 unless you have an external power source. Watch batteries can run a vibration motors for quite a while but they aren’t going to last long if you’re trying to power something larger like a servo motor or a DC motor. If you’re able to use an external power source though or willing to hook up some AAA batteries or a PowerSwitch Tail connected to a wall outlet of course you’ll be fine. Anyways, we’ll look at an LED, because, as you probably know, the basic principles of controlling a DC motor or an LED are more or less the same.

If you’ve already worked with the Arduino you’ve probably heard of Pulse Width Modulation (PWM), which is how the Arduino, a device that can’t actually create a variable analog out signal, simulates that. If you’re looking for more information, the [Arduino site](http://arduino.cc/en/Tutorial/PWM) is a great place to learn more about it. We’ll skip right to the important part: the Tiny85 has 2 pins that can create a PWM signal: 0 and 1. To fade an LED, we’ll connect an LED with a resistor to pin 0 and a potentiometer to pin 2.

const int led = 0; // 0 or 1
const int pot = 2;

void setup() {
pinMode(led, OUTPUT); // set output explicitly w/the Tiny
pinMode(pot, INPUT);
}

void loop()
{
// read the pot, divide by 4, and then fade (ignoring the actual illumination curve of the LED for now)
analogWrite(analogRead(pot)/4, fadeValue);
}

And here’s the wiring (you’ll need to wire it up after you load the code onto the Tiny85), yippee!

wire_led

Step 5: Talking to other things

The 433 Mhz radio is a tiny, lightweight, low power, low overhead way to send and receive information. It’s how a lot of remote control cars, garage door openers, toys, and other low power and low overhead devices communicate with one another. Being able to communicate with other devices is an absolute revelation for an ATTiny, radio is the holy grail for the Tiny85. Putting a radio on a Tiny lets it communicate what’s going on in its world. So, what do we mean by a RF radio? Well, here’s a transmitter – left (picture courtesy Sparkfun):

10534-01a10532-01

and here’s a receiver – right (picture courtesy Sparkfun):

Ok, so what we’re going to do with them is send button presses from one, to the other, using these guys. To prove that this is working properly, we’re going to use two buttons and two LEDs. This proves that we’re not lying :) The wiring looks like this here:

rfwiring

Now, we need a library to do this properly, and the usual Arduino libraries for working with the Arduino are not going to work with the Tiny85. Luckily though, enough people are starting to work with the Tiny that libraries for doing things like working with RF, i2c, and so on, are starting to pop up. Thanks to mchr3k we have a Manchester encoding library that plays nice with the Tiny85, right here. Download that, plop it into your Arduino/libraries folder, and you’re ready to program your Tiny85.

Sending is reasonably straightforward, pick a pin to send on in the setup() and tell it what to send. In this case, we’re using button presses to determine what to send and when to send it.

#include <Manchester.h>
int ls;

void setup()
{
pinMode(1, INPUT);
pinMode(2, INPUT);
MANCHESTER.SetTxPin(4);
ls = 0;
}

void loop()
{
// button press handling code, highly non-optimized
if(digitalRead(1)) {
unsigned char data[1];
data[0] = 2;
MANCHESTER.TransmitBytes(1, &data[0]);
delay(1000);
}
if(digitalRead(2)) {
unsigned char data[1];
data[0] = 1;
MANCHESTER.TransmitBytes(1, &data[0]);
delay(1000);
}
}

Receiving is slightly more complex, but not overly so. You’ll see the calls to set up the receiving: which pin it’s using, a setup() method for the receiver (which just sets up the interrrupt we’ll use to listen for data) and then the MANRX_BeginReceiveBytes(), which actually listens for data on the RF Receiver.



#include <Manchester.h>
unsigned char bufferSize = 1;
unsigned char *bufferData;

int whichLight;
int lightCount;

void setup()
{
// set up the pins that we're going to use
pinMode(4, OUTPUT);
pinMode(2, OUTPUT);
pinMode(1, OUTPUT);

lightCount = 0; // we're just using a simple counter, to avoid messing with timers
whichLight = 0;

bufferData = (unsigned char*) malloc(1);
// Set digital TX pin
MANRX_SetRxPin(3);
// Prepare interrupts
MANRX_SetupReceive();
// Begin receiving data
MANRX_BeginReceiveBytes(1, bufferData);
}

void loop()
{
// if we have a light lit already, then just wait for our time to be up
if(lightCount != 0)
{
lightCount = lightCount + 1;
if(lightCount > 1000)
{
lightCount = 0;
digitalWrite(whichLight, LOW);
// start listening for data
MANRX_BeginReceiveBytes(1, bufferData);
}
}
// if we have something already, then process it
if (MANRX_ReceiveComplete())
{
unsigned char receivedSize = 1;
// you need to know how many bytes you're expecting
MANRX_GetMessageBytes(&receivedSize, &bufferData);

// if they pressed the first button
if(bufferData[0] == 1 ) {
bufferData[0] = 0;
whichLight = 1;
digitalWrite(whichLight, HIGH);
lightCount = 1;
}

 // if they pressed the second button
if( bufferData[0] == 2 ) {
bufferData[0] = 0;
whichLight = 2;
digitalWrite(whichLight, HIGH);
lightCount = 1;
}
}
}

And that’s about it. You can always have an Arduino, Raspberry Pi, or really anything that can have a 433Mhz receiver attached to it, be the receiver for your Tiny. You might be asking: so they can only talk one way? Well, sort of. I have another tutorial that I’m putting together that uses the RFM12B, a transceiver aka a receiver+transmitter, so that you can make a straight up node on a network (albeit a cheap, somewhat unreliable, and short distance network). That’ll be the Part Two of this and we’ll look we’ll also look at the ATTiny84, a very similiar chip with slightly more pins for you to work with. See you soon ;)

  • David

    Hi,
    Great article! I Thanks for all the time you must have spent on it.

    I downloaded the Manchester library but found that the program would not compile for the Attiny85. It would for the UNO so I think that I need to upgrade my Core file. I havettried doing this but it made no difference. Can you advise?

    Many thanks,

    David.

  • Juan Mol

    sketch_oct30a.cpp:50:49: error: ‘MANRX_GetMessageBytes’ was not declared in this scope

    try maaaaany times, clean all downloaded libs and hardware, try again … try again …

  • Gustav

    Hi there

    I have the same problem I have downloaded and the Manchester script is not compiling for me. I get this error “error: ‘MANRX_GetMessageBytes’ was not declared in this scope” Please can you help.

    Love your work!!!

    Kind Regards

    Gustav

  • robson

    i am having the same problem of it not compiling