The ATtiny85 is a lovely chip for relatively simple applications. More than enough flash, 512 byte SRAM, 5 usable pins, cheap (half the cost of ATmega328 – 10 cost me £10) and most importantly a small form factor (8 pin chip).
Datasheet: http://electronics.arunsworld.com/?attachment_id=116
Google provides an Arduino core for the ATtiny85. Located here. I have it installed and use it when I need some functions like millis rather than write it myself. However, I have also setup my own core that is absolutely barebones and effectively lets me use the Arduino IDE to write & upload sketches using nothing more than AVR Libc.
All the core contains is a main.cpp that calls setup and loop. It also includes one header file: WProgram.h and I have an Arduino.h that is simply including WProgram.
Below is a BareMinimum sketch that doesn’t do anything but can be used as a template to start a sketch. It includes power saving features that can be tweaked based on what’s needed in the sketch. The sketch compiles to only 150 bytes.
#include <avr/wdt.h> #include <avr/sleep.h> void setup() { // Turn off unnecessary peripherals MCUSR = 0; wdt_disable(); // watch dog timer ACSR |= _BV(ACD); // Disable analog comparator ADCSRA &= ~_BV(ADEN); // Ensure ADC is indeed disabled PRR |= _BV(PRTIM0) | _BV(PRTIM1) | _BV(PRUSI) | _BV(PRADC); // shut down timers, USI, ADC set_sleep_mode(SLEEP_MODE_PWR_DOWN); // do something - enable interrupts, whatever } void loop() { cli(); sleep_enable(); sei(); sleep_cpu(); sleep_disable(); }
Useful registers on the ATtiny85:
Register | Bits | Purpose |
---|---|---|
PRR | PRTIM1 PRTIM0 PRUSI PRADC |
Writing a logic 1 shuts down power to Timer1, Timer0, USI & ADC. Note: Google core uses Timer1 to implement delay, millis, micros etc. |
MCUCR | ICS01 ICS00 |
Controls the logic to drive the external interrupt 0 (INT0) |
GIMSK | INT0 PCIE |
INT0: Enables interrupt on INT0 (by writing 1) PCIE: Enables pin change interrupt (PCINT[5:0]). Before setting PCIE though remember to set PCMSK. |
PCMSK | PCINT5 PCINT4 … PCINT0 |
Selects whether pin change interrupt enabled on that pin. |
PORTB | PORTB5 PORTB4 … PORTB0 |
Set PORT to 0 or 1 to control an output pin. Set 1 on an input pin to enable pull-up. |
DDRB | DDB5 DDB4 … DDB0 |
Set 1 to make a pin an output pin. 0 for input. |
PINB | PINB5 PINB4 … PINB0 |
Use to read value of pin. Write 1 to toggle the value, especially if it’s an output pin. |
TCCR0A | WGM01 WGM00 |
WGM00, WGM01 and WGM02 control the timer mode. eg. Normal, CTC, PWM Normal implies it counts up to counter overflow. CTC: clear timer on compare match. |
TCCR0B | WGM02 CS02 CS01 CS00 |
CS: clock select – sets the pre-scaler No prescaling, 8, 64, 256 & 1024. |
OCR0A | Value: Output compare register A. | |
TCNT0 | Value: Timer/Counter register. | |
TIMSK | OCIE0A OCIE0B TOIE0 |
OCIE: Output compare match interrupt enable. (write 1). TOIE0: overflow interrupt enable (write 1) |
ADCSRB | ACME | Write ACME bit to logic 0 to apply AIN1 as negative input to analog comparator. Write logic 1 with ADC off to use ADC multiplexer to comparator |
ACSR | ACD ACBG ACIE ACIS[1:0] |
ACD: analog comparator disable (write 1 to disable) ACBG: use band gap voltage as positive input. If cleared use AIN0. ACIE: Interrupt enable (write 1). ACIS: Logic to determine whether interrupt based on toggle, falling or rising edge. |
ADMUX | REFS[2:0] ADLAR |
REFS: Voltage ref selection. Vcc, AREF (PB0), 1.1V, 2.56V ADLAR: ADC Left Adjust Result. |
ADCSRA | ADEN ADSC ADATE ADIE ADPS[2:0] |
ADEN: ADC Enable (write 1 to enable or 0 to disable). ADSC: start conversion. In free running, this starts the conversion. ADATE: auto-trigger enable. Trigger set by ADTS in ADDSRB. ADIE: Interrupt enable. ADPS: pre-scaler |
ADCSRB | ADTS[2:0] | Choice of: Free Running Mode Analog Comparator Ext. interrupt 0, Timer/Counter CTC or overflow, Pin Change request. |
ADCL, ADCH | Value: depending on ADLAR either left or right justified 10 bits. | |
USIDR | Value of USI data. Copy also available at USIBR. | |
USIBR | Loaded here when transfer completed. | |
USICR | USISIE USIOIE USIWM[1:0] USICS[1:0] USICLK USITC |
USISIE: enables interrupt on start condition (write 1). USIOIE: counter overflow interrupt enable. 4 bit counter USIWM: wire mode selection: 3-wire mode, 2-wire mode. USITC: toggle clock port pin. USICLK: clock strobe. |
List of interrupts available:
Interrupt | description |
---|---|
INT0_vect | External Interrupt 0 |
PCINT0_vect | Pin change Interrupt Request 0 |
TIMER1_COMPA_vect | Timer/Counter1 Compare Match 1A |
TIMER1_OVF_vect | Timer/Counter1 Overflow |
TIMER0_OVF_vect | Timer/Counter0 Overflow |
ANA_COMP_vect | Analog comparator |
ADC_vect | ADC Conversion ready |
TIMER1_COMPB_vect | Timer/Counter1 Compare Match B |
TIMER0_COMPA_vect | Timer/Counter0 Compare Match A |
TIMER0_COMPB_vect | Timer/Counter0 Compare Match B |
USI_START_vect | USI START |
USI_OVF_vect | USI Overflow |
Defining a board for the ATtiny85 so it shows up on the boards list:
Setting up a board helps set the fuses (via Burn Bootloader) and also in calling the appropriate core and then uploading to chip.
Here are my settings in boards.txt under hardware/tiny/
attiny85at8.name=ATtiny85 @ 8 MHz attiny85at8.upload.using=arduino:arduinoisp attiny85at8.upload.maximum_size=8192 attiny85at8.bootloader.low_fuses=0xE2 attiny85at8.bootloader.high_fuses=0xDE attiny85at8.bootloader.extended_fuses=0xFF attiny85at8.bootloader.path=empty attiny85at8.bootloader.file=empty attiny85at8.build.mcu=attiny85 attiny85at8.build.f_cpu=8000000L attiny85at8.build.core=tiny ################################################ attiny85at8ab.name=ATtiny85 @ 8 MHz w/ ABTiny Core attiny85at8ab.upload.using=arduino:arduinoisp attiny85at8ab.upload.maximum_size=8192 attiny85at8ab.bootloader.low_fuses=0xE2 attiny85at8ab.bootloader.high_fuses=0xDE attiny85at8ab.bootloader.extended_fuses=0xFF attiny85at8ab.bootloader.path=empty attiny85at8ab.bootloader.file=empty attiny85at8ab.build.mcu=attiny85 attiny85at8ab.build.f_cpu=8000000L attiny85at8ab.build.core=abtiny
Installation of cores and boards
This can be done in the folder that has the sketches (eg. ~/Documents/Arduino/) under a folder called hardware.
Folder structure:
- hardware/tiny/ <– root folder for the files for ATTiny85
- boards.txt (under root folder above)
- cores/ <– under root folder it contains the cores
- cores/tiny <– contains the google core
- cores/abtiny <– contains my core (main.cpp, WProgram.h etc.)