After a few years using Arduino Pro Minis and now recently ATmega328P-PU chips, I have started playing with the ATtiny85/84. As as programmer this was very confusing. I just assumed I could program the ATtiny the same way as the ATmega328. Oh, was I wrong. I spent countless hours trying to get things to work. I didn't find much info online for my problems either.
My biggest mistake was to start a project using external interrupts. Turned out others have the same problem I had. After an interrupt, the ATtiny just restarted instead of executing the intended code. Still looking for a solution to the problem. In the meanwhile, I found a library for the ATtiny that did the job.
But don't let this scare you! Hooking everything up and run a simple program takes less than 30 minutes. And it's well worth the time.
After a while I released that I had to think like an assembler programmer to get this to work. I used to program the Zilog Z80 CPU back in the 80s, so I wasn't totally lost here, but thats a long time ago. The ATtiny uses a lot of registers and masks that needs bit manipulations and after 30 years programming in high level languages this was hard to (re)grasp. You get stubborn when you get older...
What's the difference?
Apart from the obvious package size, the programming is a bit different. Both physically and coding. The ATtiny uses one port (PORTB), also called a register, for all in/out pins. The correct name is Port B Data Register. This port is one byte, 8 bits. So where you would use digitalWrite(pin3, HIGH); on the ATmega, you use DDRB |= (1 << PB3); on the ATtiny, to set bit 3 "on". These bits are named PB0 to PB5.
You may use digitalWrite(pin3, HIGH); on the ATTiny as well, but I ran into a lot of problems using this in conjunction with external interrupts. digitalWrite is also a lot slower than setting individual bits.
To program an ATtiny you need a separate programmer or you can use an Arduino Uno as the programmer. You will find a lot of tutorials out there on how to do this. You can have a look at the data sheet here.
Ports, registers and addresses
If you have ever done any assembler programming, you will be familiar with these terms. Anyway, I have included some of the names used in conjunction with the ATtiny:
DDRB – Port B Data Direction Register
PORTB – Port B Data Register
PINB – Port B Input Pins Address
MCUCR – MCU Control Register
GIMSK – General Interrupt Mask Register
PCMSK – Pin Change Mask Register
GIFR – General Interrupt Flag Register
Setting, clearing and reading bits
I usually go for quick solutions, so here you have a few easy to remember macros.
#define bitGet(p,m) ((p) & (m)) // Get the value of a bit, like bitGet(PORTB, BIT(5));
#define bitSet(p,m) ((p) |= (m)) // Set the value of a bit (set it to 1), like bitSet(PORTB, BIT(2));
#define bitClear(p,m) ((p) &= ~(m)) // Clear a bit (set it to 0), like bitClear(PORTB, BIT(2));
#define bitFlip(p,m) ((p) ^= (m))
#define bitWrite(c,p,m) (c ? bit_set(p,m) : bit_clear(p,m))
#define BIT(x) (0x01 << (x))
#define LONGBIT(x) ((unsigned long)0x00000001 << (x))
I think the code is much easier to read when I, at a glance, can see what is going on. The above macros is much easier to read than PORTB = PORTB | 0x01; or PORTB = PORTB & ~0x01;
Smaller is better?
Using Arduino Pro Minis (8MHz, 3.3V) for most of my projects teached me that it takes "a lot" of space. Not only the board itself, but also the batteries. I have used both a standard battery pack consisting of 2xAA 1.5V batteries and a big 3V "coin cell" battery (CR2477). Not much room for improvement here.
A plain ATmega328P-PU chip (the same as on the Arduino Uno), with 32K of memory, may have a new bootloader burnt, that enables it to run on an internal 8MHz clock, without a crystal. Going down to 8MHz also has the benefit of using less power. The disadvantage here is that the DIP package has 28 legs, making it "very" long. It runs fine on a 3V coin cell battery, but it usually stops when the battery voltage is below 2.7V.
The ATtiny85 has only 8 legs, and obviously fewer I/O pins, and usually runs at 16MHz without a crystal. Also it only has 8K of memory. Burning a new bootloader can make it run at 8MHz and it can be powered all the way down to 1.8V (ATtiny85-V-10PU).
Then there is the ATtiny84 with its 14 legs. It has more I/O pins but only 8K, same as the ATtiny85. Same advantages as the ATTiny85, can run on voltage down to 1.8V.
In my quest of having things smaller and use less power, I'm now going for the ATtiny's in DIP packages. I will not yet bother with even smaller surface mounted devices. Not yet...