Using ATtiny Chips for Arduino-Like Projects

The Arduino platform is great for prototyping. Its easy-to-use shield architecture, readily identifiable pin numbering scheme, and beginner friendly IDE and software library has created a large and loyal following. In the life of many projects, however, there comes a time when the project is to be permanently deployed. When that time comes, leaving a precious Arduino in the field is often not the best option. Instead, a specialized board with either an ATmega chip or even an ATtiny chip is the best choice.

When cost or space is a factor an ATtiny chip is an attractive alternative to the ATmega for simpler projects. Thanks to the Arduino-Tiny project, an ATtiny can be used as a drop-in replacement for most Arduino projects. This initiative provides ATtiny chip configurations as upload board choices in the standard Arduino IDE. By following the instructions described in my previous article – Program an ATtiny Using an Arduino – your Arduino sketch can be uploaded as easily to an ATtiny board as it can be to an Arduino one.

More recently, the ATtiny has gained semi-official support given the variants posted by David Mellis on Github. Please note that this new firmware specification has a different pinout than the one used by the Arduino Tiny project. It is therefore best to base your projects on this newer version.

In response to that article, there has been considerable interest in the differences between the ATmega based Arduino compatible boards and ones based on ATtiny chips.  There has also been some confusion over these differences as well. This article is meant to address those differences and clear up any confusions.

The Arduino Language

On the official Arduino website, the following is proclaimed:

The microcontroller on the board is programmed using the Arduino programming language (based on Wiring) and the Arduino development environment (based on Processing).

The phrase Arduino programming language is an unfortunate choice of words and is the cause of considerable confusion among newcomers to the platform. By following the link provided, the official Wiring site says it better:

Wiring is an open-source programming framework for microcontrollers.

Since the aforementioned is probably still confusing, permit me to state the matter plainly. The Arduino is programmed using the language C++, and makes use of the framework library Wiring. There is no Arduino programming language. What the Arduino IDE (integrated development environment) does is hide the complexities of C++ compilation and linking via the Processing IDE. Behind the scenes it uses the GNU GCC compiler for C++, and links internally to both the AVR Libc library and the Wiring library.

C and C++

Beginners may be put off by the idea of programming in C++ due to its reputation for being a complicated language. This fear is unfounded. It is due to the power of C++ that makes programming the Arduino much more simple than more conventional AVR techniques using C. For an example, look at this string concatenation example:

// concatenating two strings:String str1 =  String("This is a string");
String  str2 =  String(str1 + " with more");
// prints "This is a string with more":
Serial.println(str2);

Try doing that using straight C code. and you’ll see how much easier using C++ is. C++ can be complicated when trying to create complex class constructs, overloading operators, etc., but when using existing library code, it is as easy as Java or any other simplified object oriented language.

You may also read in various sources that the Arduino is programmed in C. That is not entirely correct either. Using the previous example to illustrate, it is heavily dependent on the object oriented capabilities of C++. Since C++ was designed to be backward compatible with the C language, the two terms are often thrown about interchangeable today. When it comes to programming micro-controllers however, straight C is often used because of its extreme efficiency. It is also a major point of departure with the Arduino in its use of C++. While you are free to use any of the more primitive C constructs such as you’ll find in most non-Arduino AVR programs, Arduino sketches have the distinction of using the more powerful features offered by C++. It is this use of C++ that makes the Arduino so much easier to program than traditional methods using just C.

Wiring Framework

The Wiring Framework is the other feature that sets programming the Arduino apart from other common micro-processor projects. Another minor point of distinction is worth mentioning here as well. The Wiring Framework, is not much of a framework. It is mainly just a library. A framework is a superstructure library that sits above your code, where a library is a set of already written code that you call when needed. The bulk of Wiring is mainly its extensive library. The framework portion is limited to two functions: setup and loop. Rather than calling these functions, your sketch implements them and the framework calls them. For example:

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

void loop()
{
  digitalWrite(WLED, HIGH);  // set the LED on
  delay(1000);               // wait for a second
  digitalWrite(WLED, LOW);   // set the LED off
  delay(1000);               // wait for a second
}

While the Wiring framework part is pretty basic, its two simple functions provide an excellent starting point for organizing and writing an Arduino sketch. In this example, you can see the library functions: pinMode, digitalWrite and delay. These replace complex C-based register manipulations that make micro-processor programs difficult to write, difficult to debug, and difficult to understand. It is this wonderful, high-level interface to the AVR chip that makes the Arduino such a compelling platform, and is probably what lends so much weight to the idea that it is its own language when it is really C++ with a great abstraction library.

Library Compatibility with ATtiny

Another area of concern when substituting ATtiny chips for an Arduino is whether the sketch will run correctly on the ATtiny due to differences in the library. Since the same sketch is compiled using the exact same framework/library, the concern becomes not so much a library compatibility issue, but whether the underlying chip supports the given library function. Here are some of the major differences between ATmega series chips and ATtiny ones:

Pins

Each AVR chip supports a different number of digital and analog pins. Mapping from AVR registers to Arduino numbered pins is done by the code from David Mellis github repo, and extended to support 20-pin chips in the forked version over at ProvideYourOwn’s github repo. That mapping will be covered in the next section. The following table compares the number of GPIO (general purpose IO) pins and the number of analog pins supporting analog to digital conversion.

AVR IC #GPIO pins #Analog Pins #PWM pins INT Pins
ATmega48/88/168/328 20 6 6 2
ATtiny25/45/85 5 4 4* 1
ATtiny24/44/84 11 8 4 1
ATtiny87/167 15 10 3** 2
ATtiny2313/4313 17 0 4 2
ATtiny13 5 4 2 1
ATtiny261/461/861 15 10 3 1

NOTE: The number of available ouput pins reflect those not available due to being the RESET pin, and supporting clock crystals in the case of the ATmega serias.

* While the ATtiny x5 series of chips support 4 PWM pins in hardware, the current variant definition does not.

** Two of the PWM timer outputs can actually drive up to 4 pins each. Each of these 4 pins would have the same PWM output waveform of course.

GPIO pins can be used for digitalRead() and digitalWrite(). Since all analog pins support GPIO, they are a subset of the total number of GPIO pins. For example, in the basic Arduino, it is often considered that there are 14 digital pins, numbered 0 – 13. There are actually 20, numbered 0 – 19. The last 6 pins are analog pins. For sake of clarity, digital pin number 14 is the same as analog pin number A0. Either constant can be used in calls to digitalRead() and digitalWrite(). To obtain the number of pins exclusively for digital I/O, simply subtract the number of pins supporting ADC (analog input) from the number of GPIO pins.

Another popular feature of the Arduino is PWM (pulse modulated output), expressed in the Arduino library as analogWrite. As you look at the table, there is not a lot of difference between the various chips. All the ATtinys (except the tiny13, tinyX61 & tinyX7) feature 4 PWM outputs, while the ATmega has 6.

Support for ATtiny13 & ATtinyx61 series

One last item to mention is the fact that there currently is no variant support for ATtiny13 series. The tiny13 is very similar to the ATtinyx5 series, so it would not be difficult to add the necessary code.

The tinyx61 series and tinyx7 series chips are well worth considering. With their whopping 10 analog pins, they are a real sensing powerhouse. While Provide Your Own’s github supplies these variants, they are currently untested.

Interrupts

AVR chips support two kinds of interrupts – a multi-state interrupt and a pin-change interrupt. The Arduino library only supports the multi-state interrupt through the functions attachInterrupt() and detachInterrupt(). There are only two pins supporting the multi-state interrupt on most Arduino boards, and are designated by INT0 or INT1. Most ATtinys sport only one of these interrupt pins (Int0) as seen in the previous table.

The pin change interrupt is usually available on all GPIO pins for AVR chips. While the Arduino language doesn’t support it, there are community supplied libraries that do. The PinChangeInt library is an excellent one that makes attaching interrupts to any pin desired a breeze.

Timers

The ATmega series has a total of 3 timers. Each timer has its own special set of features. For most applications, the explicit use of the timers is not required, and when they are, the spec sheets for the chip in question can always be consulted.

One of the primary uses for timers is to perform the PWM function. The number of pins supporting PWM is twice the number of timers. Each timer expresses its output on two pins – one pin is always low, while the other pin is high. In the Arduino library, except for PWM, only one timer is used – Timer 2.

On the Ardunio, Timer 0 is used for basic timing operations unrelated to PWM output. The Arduino functions that make use of this timer are: pulseIn(), millis(), micros(), delay(), and delayMicroseconds(). Timer 1 is used for the tone() function. That leaves Timer 2 free for custom timing operations. The various ATtiny chips (except for the ATtiny13) have only two timers, which provide for the exact same functionality offered in the Arduino library as the ATmega series does.

The variant file for each of these chips maps these timing functions to the appropriate timer for each ATtiny chip used. You normally won’t need to worry about which timer is used unless you need to change the timer frequency or make some other use of the timer. You can see which timer is used for these functions in the file core_build_options.h.

Oscillator

The basic Arduino boards make use of either a quartz oscillator or a ceramic resonator to keep accurate time. In most ATtiny projects, neither of these devices are used, leaving the two pins they use free for other types of I/O. In my previous table on the number of pins available, this practice was taken into account in the table. Both the ATmega series as well as the ATtiny series chips have both internal oscillators and can make use of more accurate external ones.

The use of an oscillator makes little difference in the code of your projects, other than the reduction of available pins by two. A factor that does make a difference is the clock speed your chip is running at. The default clock speed (as shipped from Atmel) for both the ATmega series chips as well as the ATtiny ones is the 8MHz internal clock with a prescaler of 1/8, which yields an actual clock speed of 1MHz. These settings can be changed my setting the necessary fuses. Most Arduino boards have them changed to use an external 16MHz clock with a prescale factor of 1.

Unless you change the fuse settings, your ATtiny projects will be running at 1MHz, and you need to make sure you select the board running at 1MHz when uploading your sketch. If you accidently choose the 8MHz board, your timing will be off by a factor of 8. If you see your LED blinking really slowly, then you will know what you did wrong.

Analog Reference

Like the ATmega series, the ATtiny series of chips offer three choices in analog reference selection – external, internal Vcc and internal 1.1v. The ATtinyx5 series offers an additional internal reference of 2.56 volts. The standard Arduino library provides support for each of these choices. In review, they are:

  • DEFAULT: the default analog reference of Vcc
  • INTERNAL: an built-in reference, depending on the chip (not supported by the ATtiny version of the Arduino library – use Internal1v1 instead)
  • INTERNAL1V1: a built-in 1.1V reference (not available for the ATmegax8 series – use Internal instead)
  • INTERNAL2V56: a built-in 2.56V reference (only supported by the ATtinyx5, ATtinyx7 & tinyx61 series)
  • EXTERNAL: the voltage applied to the AREF pin (0 to 5V only) is used as the reference.

One of these constants as passed as the parameter to the analogReference(type) function.

Communications

While the ATtiny series implement many of the same protocols as the ATmega series chips, there are some limitations. These limitations are manifest when trying to use some of the Arduino libaries. Here is an overview of each one:

  • Ethernet – this library is for connecting to the internet using the Arduino Ethernet Shield. Since it uses the SPI hardware that is part of all Atmel chips, it should work with no problem on ATtiny series chips.
  • Firmata – for communicating with applications on the computer using a standard serial protocol. Since all the ATtiny chips except for the ATtinyx313 series lack a hardware based serial I/O, I doubt this library will be usable.
  • SPI – for communicating with devices using the Serial Peripheral Interface (SPI) Bus. This library should work on all Atmel chips.
  • SoftwareSerial – for serial communication on any digital pins. This is a software implementation of serial communications. Since most of the ATtiny series chips lack the hardware for a serial interface, this library will no doubt be useful for many ATtiny based projects.
  • Wire – Two Wire Interface (TWI/I2C) for sending and receiving data over a net of devices or sensors. The ATtiny series chips support I2C/TWI, so one would think this library would work without any problems. However, this thread seems to indicate that it needs modification for the ATtiny chips. One of the contributors has provided a ported version of the Arduino library.

If any of these communication protocols are confusing, please consult my earlier article that explains the various Atmel communication protocols and their support in various chips, including the ATtiny.

Other Libraries

There are some additional libraries provided for the Arduino IDE, that I have listed below. As none of these libraries make use of any special hardware other than the basic functionality of most AVR chips, they should all work without any problems when using ATtinys.

  • EEPROM – reading and writing to “permanent” storage
  • LiquidCrystal – for controlling liquid crystal displays (LCDs)
  • SD – for reading and writing SD cards
  • Servo – for controlling servo motors
  • Stepper – for controlling stepper motors

Pinout Differences

When either designing the hardware or writing the software to drive it, there is nothing more essential than a chart showing the pinouts of the chip being used. Please bear in mind that these pinouts have been revised by David Mellis and are different from the earlier ones used in the ATtiny project. The 20-pin chip pinouts have been assigned by yours truly, and as such are in no way official. Without further fanfare, here are those charts for each of the ATtiny chips:

ATtiny Pinouts-8 ATtiny Pinouts-14 ATtiny Pinouts-20x13 ATtiny Pinouts-20x61

Note – there is a minor error in the 861 pinout (above) – pin17 should be D3/AREF (not D10/AREF).

Since the ATtiny13 currently does not have a variant file, I am not including its pinout diagram.

Conclusion

We have clarified the term Arduino language. Since this language is ordinary C++, any language constructs mentioned in either the Arduino documentation or in C++ literature will be perfectly valid regardless of the Atmel chip you are using.

The basic Arduino library, consisting of calls such as digitalWrite(), digitalRead() and so forth have been fully implemented by the Arduino-Tiny project. You can use them without concern in your ATtiny projects.

The other libraries included in the Arduino IDE are supported for the ATtiny as well. The only one that is not – Firmata – is because except for the ATtiny x313 series, serial communications are not supported by the ATtiny hardware.

The advantages of the ATtiny series chips are numerous – small package size, big capability and ultra-low cost among them. The Arduino IDE and its associated libraries enjoy a high level of support for these chips. Programming them is as easy as any Arduino. There is no reason to not make full use of them in your projects.

Feel free to make any corrections, clarifications, and contribute your own knowledge in the comments below.

 

Using ATtiny Chips for Arduino-Like Projects by Provide Your Own is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

This entry was posted in Tech and tagged , . Section: . Bookmark the permalink. Both comments and trackbacks are currently closed.

11 Comments

  1. Max van Ginkel
    Posted August 8, 2014 at 7:57 am | Permalink

    Hi there
    Have been trying to program a little AtTiny85 project with a Arduino Nano as ISP
    using
    Windows7 ,Arduino 1.5.6-r2

    loading the blink sketch to the Arduino works;
    loading the Arduino as ISP looks like it works, as I get the heart beat led flashing
    Adruino IDE sees the ATtiny board selections
    but if I load the blink sketch I get

    processing.app.debug.RunnerException’s

    and my java knowledge is all but entry level,
    would you be able to give me some direction here ?

  2. Alan Medina
    Posted October 22, 2014 at 3:49 pm | Permalink

    Hi! My name is Alan, Im trying to program ATtiny4313 project, using arduino with your ATtiny core, but i get the following error:

    In file included from /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/Arduino.h:213:0,
    from /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/wiring_private.h:33,
    from /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/wiring_digital.c:28:
    /Users/Alan/Documents/Arduino/hardware/attiny/variants/tiny20x13/pins_arduino.h:98:8: error: expected identifier or ‘(‘ before ‘int16_t’
    const (int16_t PROGMEM port_to_output_PGM[] =
    ^

    How i can fix this error?

    thanks

    • Posted November 13, 2014 at 1:04 am | Permalink

      You can try this programmer it claimes it can program ATtiny13/15/25/45/85 with these shield also. I found one here its very cheap and easy no jumpers and breadboard needed.
      http://tiny.cc/bg86ox

      • Alan Medina
        Posted November 15, 2014 at 12:45 pm | Permalink

        I get the error when I try to compile a program using your core

        any solution?

        thanks

        • Wolfgang
          Posted March 31, 2015 at 11:23 am | Permalink

          Hi

          there is a typo in the lib:
          const (int16_t PROGMEM port_to_output_PGM[] =

          should be:
          const uint16_t PROGMEM port_to_output_PGM[] =

          then the compile should work better.

          nevertheless I try to use the same on the ATtiny861 and got the following:

          In file included from /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/avr/cores/arduino/Tone.cpp:37:0:
          /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/avr/cores/arduino/Tone.cpp: In function ‘int8_t toneBegin(uint8_t)’:
          /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/avr/cores/arduino/Tone.cpp:159:26: error: ‘WGM01’ was not declared in this scope
          bitWrite(TCCR0A, WGM01, 1);
          ^
          /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/avr/cores/arduino/Arduino.h:104:49: note: in definition of macro ‘bitSet’
          #define bitSet(value, bit) ((value) |= (1UL << (bit)))
          ^
          /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/avr/cores/arduino/Tone.cpp:159:9: note: in expansion of macro 'bitWrite'
          bitWrite(TCCR0A, WGM01, 1);
          ^
          Fehler beim Kompilieren.

          • Wolfgang
            Posted April 16, 2015 at 2:00 pm | Permalink

            I copied the pins_arduino.h into an own github (https://github.com/jipp/attiny) and changed them.
            Using Arduino IDE > 1.6.3 (nighly build) ATtiny x61 is working – at least for my simple usage.

  3. Brian Bowlsby
    Posted December 24, 2014 at 6:10 pm | Permalink

    Great webpage, very informative, Thanks!

    I found the answer to my problem just by reading through the information on this page…

    “If you accidently choose the 8MHz board, your timing will be off by a factor of 8. If you see your LED blinking really slowly, then you will know what you did wrong.”

  4. Posted January 11, 2015 at 11:13 am | Permalink

    ATtinyx5 – in your pinout, you show pins PB0 and PB1 as supporting PWM. However, I have seen ‘other’ pinouts online which claim PB4 also supports PWM. Can you explain? thanks

    • edwin
      Posted May 18, 2015 at 6:57 am | Permalink

      I think he already explained that in the body of the article

  5. Praj
    Posted May 6, 2015 at 7:23 pm | Permalink

    I’ve got a modified version of John ‘smeezkitty’s Attiny13 core along with David Mellis’ Attiny cores working together and running without any bugs – so far – on Arduino 1.6.3. Feel free to check them out here on Github.

    Any suggestions and comments are welcome 🙂 I’m trying to get a single unified set of cores to work with as many ATtiny variants as I can.

  6. Posted November 2, 2015 at 3:13 pm | Permalink

    I maintain ATTiny cores supporting almost all of the interesting ATTiny’s (and some uninteresting ones too) for 1.6.x versions of the IDE – they’re available from my github here:
    https://github.com/SpenceKonde/arduino-tiny-841 (“Modern”)
    https://github.com/SpenceKonde/ATTinyCore (“Classic”)

    Or via board manager, add: http://drazzy.com/package_drazzy.com_index.json

    Supports ATTiny 84, 85, 861, 4313, 88, 167 and the smaller-flash versions in “classic” core, and 441, 841, 1634 and 828 in the “modern” core.