Monday, May 2, 2016

Learning Embedded Electronics with the ATtiny104 XNANO

In this post I will document a small add-on board that I designed for the Atmel ATtiny104 Xplained NANO. I have also created a series of lessons that use the ATtiny104 XNANO with the add-on board to provide a basic introduction to embedded electronics and programming.

The ATTiny104 XNANO next to the small add-on board I designed to
enable a series of lessons on embedded development.


In a previous post I examined the new ATtiny104 microcontroller from Atmel and checked out their evaluation board for it, the ATtiny104 Xplained NANO. I was very impressed by this little board. It has a programmer/debugger built in, allowing it to integrate seamlessly with Atmel Studio 7. You simply connect it to your computer with a USB cable to power the board, develop programs and connect to the USART. It is a great bargain at less than $5 USD.

It is not only suitable for evaluating the ATtiny104 but also for learning and teaching embedded electronics and programming. Certainly there are numerous Arduino and Arduino-like boards available for that task as well. This is just one more option that might be interesting if you need a very low-cost board that integrates with Atmel Studio for programming in standard C.

I designed a small add-on board for the ATtiny104 XNANO that includes a 5mm LED, a trimpot, and a photoresistor. The LED goes to one of the PWM-capable pins on the microcontroller, and the outputs of the trimpot and photoresistor circuit can be read using the ADC. These components combined with the on-board push button and LED allow for many lessons and projects to be completed. It's a very small and low-cost combo for learning or teaching embedded development.

The add-on board connected to the ATtiny104 Xplained Nano.


To support the use of the add-on board, I have created a 28-page guide with eight lessons on basic embedded programming. The lessons walk you through using various features of the microcontroller and add-on board, including: digital inputs and outputs, the ADC, PWM output, USART, and interrupts. They are designed for someone that knows a little about electronics and programming, probably with an Arduino, and wants to get a feel for programming in Atmel Studio in standard C.

The guide to support the add-on board includes eight lessons on basic embedded development.

Add-On Board Kits

The add-on board makes for a very nice first soldering kit. The PCB is cheap ($6 USD for three copies from OSHPark) and the parts are very common, through-hole components. You probably already have all of this stuff on hand. The part outlines and resistor values are shown in the silk screen of the board so you don't even need to consult a schematic while assembling it.

ATtiny104 Xplained NANO boards can be acquired from distributors such as Digikey and Mouser. The PCBs can be ordered from OSHPark. Finally, the parts can be ordered from an online vendor such as Sparkfun

Lesson #1 in the guide is soldering together your add-on board kit!


Let me say now that this is not a Kickstarter or anything like that. I'm not planning to sell these kits or make any money off of the guide. The add-on board is Open Source Hardware, and the guide is released under the Creative Commons Attribution-Share Alike 3.0 license. I hope that the board and guide are useful for learning a little bit about programming microcontrollers and embedded design, whether that is for an individual reading this blog or someone that might use the board for a workshop or class. Feel free to modify and redistribute the guide to suit your needs, as long as you attribute and share it back to the community under the same license. I have also shared the Eagle files for the add-on board if you'd like to customize it.

Check out the guide to learn more about the lessons and what you can do with this add-on board.

Shared as Open Source Hardware (OSHW)

ATtiny104 Xplained NANO Add-On Board: Order PCBs on OSHpark!

Eagle Files and Lesson Guide: Shared on Github

Schematic for the ATtiny104 XNANO Add-On Board

Parts list:
  • 10kΩ trimpot with knob
  • Small photoresistor (5mm width)
  • 5mm LED (color of your choice)
  • 470Ω resistor, 1/4 watt, 5%
  • 10kΩ resistor, 1/4 watt, 5%
  • (2) 12-pin 0.1” female headers (snap off from a strip of breakaway headers)
  • (2) 12-pin 0.1" male headers for the XNANO board

Note: There are no component IDs in the silkscreen, but the outlines and resistor values are shown to clearly indicate where the parts go.

Headers on XNANO: I have noticed that one of the capacitors on the ATtiny104 XNANO board is a little too close to the header pins. Male headers might not seat all the way flush against the board. Luckily there is an easy fix. Use a file to slightly round the bottom corner of the header where it hits the capacitor. Just a few swipes with the file will allow it to seat fully. Also, I used male headers on the XNANO board and female headers for the add-on board, but you can reverse that if you like.

After you finish the lessons and remove the add-on board, many additional
projects can be completed with the ATtiny104 XNANO.

Wrap Up

I hope that you find this small add-on board for the ATtiny104 XNANO and the lesson guide useful. If you assemble one and work through the lessons, or use them in a class or workshop, please let me know. Also, please post any questions and comments down below.

Thanks for reading!

- Dan W.


  1. Nice write-up, Dan. Wish I could have found such a useful, condensed intro to uC's when I was starting out.

  2. This is perfect! I am an experienced embedded developer already, but I was looking for some examples that would show me what could be done with the ATtiny104, given that it has so little RAM. Great examples.

    1. Glad you found the code snippets useful! Yes it's a nice little chip despite the limited memory. I'm hoping distributors get them in stock soon.

  3. This is very well done. I'm sure it will be perfect for those who wish to get started working with embedded systems. As usual Dan, you have done excellent work. I may use some of your lessons for an introductory course in microprocessors that I teach. Thanks for making this available to me and my future students

  4. Hi Dan,

    I have a technical question for you about the 104. I'm not sure whether you have gotten an interrupt to trigger based on a GPIO pin change, but that's the trouble I'm having.

    I can get the pin read using the example in your little book, in a while loop. That's not a problem.

    But I'm trying to configure the same pin to trigger an interrupt and it does not seem to be working.

    I'm defining an ISR which should just clear the bit:

    PORTA = ( PORTA ^ ( 1 << PORTA5 ) );

    Then for my main, I'm just setting up the pushbutton and LED right on the nano board:

    int main(void)
    PUEB |= ( 1 << PORTB1 );
    PORTB |= ( 1 << PORTB1 );
    DDRA |= ( 1 << PORTA5 );
    DDRB &= ~( 1 << PORTB1 );
    PCMSK1 |= ( 1 << PORTB1 );
    PCICR |= PCIE1;
    while ( 1 )

    It doesn't look like my interrupt routine is ever called.

    Examples on how to use the 104 seem to be scarce... it is pretty new. I will examine the datasheet again... I'm probably missing something obvious. Any ideas?

    I have a custom application where I want to read from an encoder and send SPI commands to a DAC. I have the SPI commands going out via bit-banging OK. Now I need to add the encoder reading. It's an interesting challenge to fit the code into such a small part! 32 bytes of RAM is not much!



    1. Hi Paul,
      Change the PCICR line to "PCICR |= (1<<PCIE1);". I would also add a bit of debounce for the button. You may or may not need that in your final application depending on how clean the signal is. Here is a code snippet that I tested and works:

      int main(void)
      // Input and Pullup on Button (PB1)
      PUEB |= (1 << PORTB1);
      DDRB &= ~(1 << PORTB1);
      PORTB |= (1 << PORTB1);
      // LED (PA5) Output and turn off LED
      DDRA |= (1 << DDRA5);
      PORTA |= (1<<PORTA5);
      // Enable Pin Change Interrupt
      PCMSK1 |= (1 << PCINT9);
      PCICR |= (1 << PCIE1);

      while ( 1 ) { }

      _delay_ms(20); // Debounce
      PORTA ^= ( 1 << PORTA5 );

      Also, if you only need one external interrupt, you can use INT0 instead (also on PB1). It can do edge, low level, and change detection. Much more robust than the PCINTs. But sadly you only have one.

      Hope that helps.


    2. Thanks, Dan! I will try it out ASAP. I think I just need one interrupt, on any of several pin state changes. This will be for a rotary encoder so I have some different debounce and direction detect algorithms to experiment with.

  5. My silly thinkographical error setting PCICR is fixed and the ISR is working! Thanks again.