Programming ATtiny13 with USBtinyISP – Ubuntu
I made a tutorial on how to program your ATtiny13 (or other ATtiny) on windows with USBtinyISP, here. This post will be a quick tutorial on how to do it on Ubuntu (9.10).
For me it was a lot of work, because it took a while before I knew what for programs to install (and how to do that). Anyway, this is how you can do it.
First we need a program to convert your code (C-code in this case) to hex. For this I use avr-gcc, to get this working we need to install three things:
- gcc-avr
- binutils-avr
- avr-libc
The easiest way to install this on Ubuntu is below. Put these commands in the terminal. You can find that under the programs list, then pocketknife and then it looks like a punched eye on a rectangle face, haha:
sudo apt-get install gcc-avr
sudo apt-get install binutils-avr
sudo apt-get install avr-libc
To make a hex file (that your micro-controller can "read") from your C-code we need to feed avr-gcc three instructions (don't ask me why for installing it is called gcc-avr and now avr-gcc). These instructions look like so (adjust to your need, in this case the C-code is demo.c):
avr-gcc -g -Os -mmcu=attiny13 -c demo.c
avr-gcc -g -mmcu=attiny13 -o demo.elf demo.o
avr-objcopy -j .text -j .data -O ihex demo.elf demo.hex
To get the hex code onto the micro-controller we will use avrdude that can work with USBtinyISP. Pretty simple to install it:
sudo apt-get install avrdude
To really get the hex on the chip we need to send the following instruction (still using demo as name):
sudo avrdude -c usbtiny -p attiny13 -U flash:w:demo.hex
There is sudo in front of this terminal command because else it simply won't work.
Pufff.... All this typing/copying every time to program is a lot of work, fortunately it can be automated. I think you can do this with makefiles on Ubuntu, but I don't understand those, so I do it with bash (.bat files).
This is how my bash file looks. Just make a new file in the same folder as your C-code and name it whatever-you-like.bat, give it this text, save it and run it with bash whatever-you-like.bat in the terminal
project="demo"
chip="attiny13"
clear
echo Hi, ...working on the stuff
avr-gcc -g -Os -mmcu=$chip -c $project.c
avr-gcc -g -mmcu=$chip -o $project.elf $project.o
avr-objcopy -j .text -j .data -O ihex $project.elf $project.hex
sudo avrdude -c usbtiny -p $chip -U flash:w:$project.hex
rm $project.elf
rm $project.o
The first two lines are variables, you can change them to your needs. For example, if your C-code file is named blink.c, you just change demo to blink. Please keep in mind that there may never be spaces between the is-sign. So this: project = "blink" is wrong and should be project="blink".
The last two lines delete the .elf and .o files, I believe these contain information on how the compiling/converting went (the code in assembly), but I so far never used them.
That's it!
Perhaps you want some test C-code to see if it works? Sure, below is a blink / blinking / pulsing / oscillator that you can use with a LED:
#define F_CPU 1200000UL
#include <avr/io.h>
#include <util/delay.h>
#define output_low(port,pin) port &= ~(1<<pin)
#define output_high(port,pin) port |= (1<<pin)
#define set_input(portdir,pin) portdir &= ~(1<<pin)
#define set_output(portdir,pin) portdir |= (1<<pin)
#define LED PB4
void delay_ms(uint16_t millis) {
uint16_t loop;
while ( millis ) {
_delay_ms(1);
millis--;
}
}
int main(void) {
DDRB |= 1<< LED; // PB4 output
while(1) {
// turn on the LED for 200ms
output_high(PORTB, LED);
delay_ms(200);
// now turn off the LED for another 200ms
output_low(PORTB, LED);
delay_ms(200);
}
return 0;
}
You can download all the files from above here.
Some small tips:
- Once you have entered the command to use the bash file (bash name-of-bash.bat) and you programmed the chip, but noticed a mistake, you don't need to retype the line in the terminal, just press the up-arrow key.
- If you use the ATtiny2313 instead of the 13, you probably need to change PB4 (or another port number) to PD4.
- The ATtiny13 can run faster than 1200000UL (1.2 MHz), but this is the factory default.
- The USBtinyISP can be deliver the required power to run the blinking (of the LED). That is where the jumper is for.
Differences
Often you find a transistor, IC or other electronic part and there are some small naming differences, like ATtiny13 and ATtiny13a. You start to wonder what differences are and go to google it. On this page I'm going to post most of the differences I encounter for easy access. Got something to add?, please comment.
ATtiny's
ATtiny13 -
ATtiny13v - Like the 13, but max. 10Mhz and can run on 1.8 Volt instead of 2.7 Volt;
ATtiny13a - Replaces ATtiny13 and ATtiny13v, can run on 1.8 Volt and 20Mhz.
See this image below for an overview with the differences between the Attiny13, Attiny2313, Attiny24, Attiny25, Attiny26, Attiny45, Attiny84 and Attiny85. (data from Feb. 2009)
Transistors
NPN - not pointing in
PNP - pointing in
In front of the transistor means (like BC549):
B - Silicon
BC - Small signal transistor ("allround")
BF - High frequency, many MHz (low power)
BD - Withstands higher current and power
SMD transistors, see this code book: http://www.marsport.org.uk/smd/mainframe.htm
Resistors

SMT/SMD Resistors work on three digits or four digits. The last one is always the power to amount. One with a zero is just a connector (no resistance). Resistances less than 10 ohms have 'R' to indicate the position of the decimal point.
Like so:
1R2 is 1.2 ohms
330 is 33 x 1 = 33 ohms (not 330 ohms)
221 is 22 x 10 = 220 ohms
474 is 47 x 10000 = 470.000 ohms
http://en.wikipedia.org/wiki/Transistor | http://en.wikipedia.org/wiki/Resistor | Quick Reference Guide ATMEL, February 2009 | http://www.intellecta.net/ (resistor code image)
De-soldering
Yesterday I have been de-soldering (or desoldering) a lot. I use for this a special soldering iron with a pump in it. I really advise you to buy one too when you do a lot of de-soldering. It is so much easier with such a tool. You have a 'free hand' to hold the circuit-board which you else need to use to hold the pump and they simply 'suck' better, haha, because the tin is still fluid. These de-soldering irons don't have to be expensive. Mine was like 10 euro (with shipping).
A free hint from me is that you wait 1-2 seconds so all the tin is fluid and then suck it away. To know if it is all fluid I press against the pins in one direction until it moves. I mostly use this technique with IC's. Althought the de-solder iron is awesome it does not work on all circuit-boards. Some of the newer circuit-boards have very precise holes and so little room between the pins and the board, it is difficult to get the tin away from there when you fail the first time. Perhaps a reader has a hint how to do that?, please comment.
So say goodbye to this one:

And say hello to your new friend when it comes to de-soldering:
The electronic items that I collected are a lot and some are very nice. I took them from old phone circuit-boards, old computer mice and some other things. Here is the most of it (click-able):
During the de-soldering I broke some parts, which isn't nice, but it is a nice chance to see how the components look from the inside.
Here is a diode (click-able):
Nikon D40 infrared remote DIY
For my images I use the Nikon D40, but never used the infrared remote function. After google'ing I found some websites on the subject. Here and here. Thanks to these great detailed websites I went to work to make my own Nikon ML-L3 remote control.
The code for getting the triggering to work took some time. The problem eventually was the wrong calculated timings by me. Fortunately, VMLAB showed me the mistakes and I got it working. There is also a short tutorial on VMLAB on this website.
The complete code is below. Note that this is only for the triggering part (no waiting on button or stuff like that) and repeats constantly.
Sorry for little commenting on the code, but those other websites already explain a lot. The code is written in Assembly, perhaps if I did it in C I finished it faster, but where is the fun in that.
Maybe I'll post a C version later on.
You can also download a zipped version here, D40 IR Remote
; Hello - warning dutch
; Attempt for D40 IR Control
; 2000 us ON
; 27830 us OFF
; 390 us ON
; 1580 us OFF
; 410 us ON
; 3580 us OFF
; 400 us ON
; repeat after 63200 us (OFF)
; bij 9.6Mhz / 8 is 0,83333.... us per tik.
.include "tn13def.inc"
.def mp = r16
.def t1 = r17
.def t2 = r18
.def blinktime = r19
RJMP main
delay130:
nop
nop
nop
nop
nop
ret ; 4 tik + rcall 3
main:
ldi mp,0b00001101
out DDRB,mp
loop:
;(Start pulse) 2000 us ON
ldi blinktime,77 ; (13.0 uS * 2 ) * 77 = 2002 uS
startpulse1:
LDI mp,0x00 ; Led on
OUT PORTB,mp
rcall delay130 ; Wait 13 uS
LDI mp,0xFF ; Led off
OUT PORTB,mp
rcall delay130 ; wait 13 uS
dec blinktime
brne startpulse1
;27830 us OFF
clr t1
ldi t2, 44
pauze1:
dec t1
brne pauze1
dec t2
brne pauze1
; 390 us ON
ldi blinktime,15
startpulse2:
LDI mp,0x00 ; Led on
OUT PORTB,mp
rcall delay130 ; Wait 13 uS
LDI mp,0xFF ; Led off
OUT PORTB,mp
rcall delay130 ; wait 13 uS
dec blinktime
brne startpulse2
; 1580 us OFF
clr t1
ldi t2, 3
pauze2:
dec t1
brne pauze2
dec t2
brne pauze2
; 410 us ON
ldi blinktime,15
startpulse3:
LDI mp,0x00 ; Led on
OUT PORTB,mp
rcall delay130 ; Wait 13 uS
LDI mp,0xFF ; Led off
OUT PORTB,mp
rcall delay130 ; wait 13 uS
dec blinktime
brne startpulse3
; 3580 us OFF
clr t1
ldi t2, 6
pauze3:
dec t1
brne pauze3
dec t2
brne pauze3
; 400 us ON
ldi blinktime,15
startpulse4:
LDI mp,0x00 ; Led on
OUT PORTB,mp
rcall delay130 ; Wait 13 uS
LDI mp,0xFF ; Led off
OUT PORTB,mp
rcall delay130 ; wait 13 uS
dec blinktime
brne startpulse4
; repeat after 63200 us (OFF)
clr t1
ldi t2, 99
pauze4:
dec t1
brne pauze4
dec t2
brne pauze4
rjmp loop
Basics Programming ATtiny13
When you want to program a microcontroller like the ATtiny13 there are some basic things you need to know. I will discuss them here. If I forgot something, please post in the comments. This page is a tutorial slash reference page.
Please make sure you have downloaded the datasheet of the ATtiny13. You can download it from the Atmel website: download first link (176 pages)
The ATtiny13 has three types of memory. Flash memory, SRAM and EEPROM. The Flash memory is where you put the code for the microcontroller (like the HDD in a PC) and has a maximum of 1K Bytes. The ATtiny45 has 4K of memory. SRAM and EEPROM are like little boxes where the microcontroller works from and with, also called registers. You could compare those with the RAM in a PC. If you turn the microcontroller off the data in SRAM is gone, but Flash and EEPROM not. Why different types of memory? This is because of the differences in maximum rewrites, costs, speed and power consumption. Flash for example cannot handle that much rewrites as SRAM or EEPROM. More info on wiki.
A microcontroller works on 0101101001, called binary, and because this is hard to remember we make use of a programming language. For microcontrollers there are two main languages you can pick from; 'C' and 'Assembly'. There are some important differences between these two. The biggest difference is that C is more 'general', this means you can also run it, often with little adjustment, on other microcontrollers. Assembly will really only work on the specific microcontroller. The disadvantage of this more general approach of C is that the code is often unnecessary big(ger) than Assembly. Microcontrollers don't have that much memory so that could cause problems.
Which language is better is hard to say, some people prefer one above the other. I would suggest to know them both, this is because on the web you will be looking for example code and sometimes that is in Assembly and other times in C. In this tutorial I will first use Assembly (later on C), because I do think it will give a better understanding of how the microcontroller works.
Before we begin, it is important to know that the ATtiny works with 8-bit. This means that the zero's and ones that the microcontroller uses are stored in 8 numbers of only an 0 or a 1. Like so: 00000000 or 11111111 or any combination in between. This also means that the maximum real number/decimal is 256 (2 to the power 8). You could sometimes use two 8 bit registers in the memory for a 16 bit number (max 65536), but you often just work in the 0 to 256 range. Note that I say to and not including 256. You see, zero als counts for something. So to say it correctly, you can use the decimal numbers from 0 up to and including 255. Also for the microcontroller 255+1 = 0. Huh? Yeah, after you reached/got to 256 the microcontroller will start at 0 again, because it can't go higher. This starting over at 0 can be very useful for counters in delays, I will discuss that later on.
The 8-bit is also used to enable or disable certain parts of the microcontroller. Let's get the datasheet, go to page 56 and I'll show you what I mean. On this page you will see at the bottom this:
Often your first program will be flashing a LED and to let this work you need to make sure the microcontroller knows which pins will be used for sending the pulse/flash. To do this you need to change the DDRB register in the register of the chip, which *happens* to be an 8-bit register. It says 0 to 7, that is 8 in total of course. So when you make DDRB into 00000001, only DDB0 will be able to send the pulse. Often you write this as 0b00000001, where 0b stands for binary. What is DDB0? That is your PORTB pin, also in short that is PB. You can find your PORTB pin on your microcontroller in the datasheet on page 2 (or look here below). In this case it is PB0 because it is DDB0 and that is pin 5. This pin can also do other things as you can see, like PCINT0, I will discuss this another time.
To make a LED flash we are not done yet, we only told the microcontroller which pin will be used for sending, we are not sending anything yet. To do this we need to change another register in the microcontroller, the PORT B Data register. You can find this also on page 56. When you set this bit to 0b00000001, you will generate a signal/voltage across PB0, which is pin 5. If you change it back to 0b00000000 there will be no signal, so it is OFF. This is a start for a flash/blink program with a LED.
Okay, I'll post some Assembly code here and than explain what it does. (Please note that this code won't let your LED flash, because the delay time is too short.)
.include "tn13def.inc"
.def mp = r16
rjmp main
main:
ldi mp,0b00001000 ;this is PB3
out DDRB,mp
loop:
LDI mp,0x00
OUT PORTB,mp
nop
LDI mp,0xFF
OUT PORTB,mp
nop ; this is a comment
rjmp loop
The include line is always there, it links to a file where the compiler (the one that changes Assembly to 011001, binary) gets information to translate everything correctly. In this case it's "tn13def.inc", which is for the ATtiny13.
The microcontroller has 32 registers in the memory (if you don't believe me see page 1 in datasheet) and these can be used to store numbers (remember max is 255). These registers are actually called general purpose registers, because they are quickly accessible for the microcontroller. These 32 registers also each have a name, like R6 or R20, but because this isn't very clear when making a program, you can define a different name. That is where the ".def mp = r16" stands for. It says, mp is register 16. This part of the code does nothing yet, it is only for the compiler again. Why r16 and not r1 you might ask. This is because r1 up to and including r15 are different type of registers. Later on I'll tell what the difference is.
rjmp main, ah yes, our first real command to the microcontroller. These things are actually called instructions and the microcontroller knows around 120 of them. There is .pdf or an online page from Atmel where you can find them all, here, I suggest to bookmark this page. One thing you need to remember right away is that an instruction takes up a 'cycle'. This cycle is like a 'tick' or 'tock' from the microcontroller and takes time to perform. How much time? This depends on the speed of the microcontroller.
The factory default is 9.6 Mhz for the ATtiny13 (ATtiny2313 is 8Mhz). You can change this speed. Hz means how often something happens in a second. So 1 Hz means, for example, 1 tick in a second. 3 Hz means 3 ticks in second. This also means that: 1 second / 3 ticks = 0.333... seconds for each tick. So now get our 9.6 Mhz (where M stands for Million), we get 1 / 9600000 = 1.04e-7 seconds for one cycle. That is very fast, to be precise, 0.10416 µs (micro seconds, more info) for a cycle. Too bad this is not correct. The microcontroller also has a divider, which is default on 8. So 9.6Mhz / 8 = 1.2 Mhz. Which is 1 / 1.2 = 0.83333... µs for one cycle.
So this 'rjmp main' instruction takes 0.83 µs to perform, right? No sorry, if you look at the online instructions page you can find that it takes 2 cycles to perform, which mean 1.67 µs. These timings might look unimportant now, but when you for example want to make an infrared remote, they need to be very precise, which you luckily now can calculate.
On the online instruction page you might also have found what the instruction 'rjmp main' does, it is very simple. It jumps to the label 'main', which is a bit further down in the program code and looks like "main:". Oh wait, it is right below it... haha. That's no really useful, because the code when run by the microcontroller goes from top to bottom, so it automatically gets to label main. You can safely remove rjmp main. However you will see later on that rjmp is a very useful instruction.
"main:" is just a label where the microcontroller can jump to when running the code. You can name these labels how you like, but only use normal words. In this main label we will find the line "ldi mp, 0b00001000". You might by now recognize the 8 bit here with the 0b (for binary) in front of it. The ldi means to store the value after the comma (,) to the register mp (which is actually r16). So after this line is run by the microcontroller (which takes one cycle, 0.83 µs) your little microcontroller memory register has a new value of 00001000. Yeah!
The next line is where we meet our DDRB again. "out DDRB, mp" means put the value mp (00001000) in DDRB register. As you notice, instruction for ATtiny go from right to left. The right value or register (after the comma ,) goes to the left register. Why not directly put 00001000 into DDRB? Like "ldi DDRB, 00001000"?, because it just cannot work. Your little microcontroller first needs to 'know' this value before it can use it. 00001000 means DDB3, which is PB3, just check page 56 in the datasheet.
We arrived at the next label "loop". In this label we meet a new friend the ldi. However this time it's written as LDI, this is no problem for the compiler, you can use lower or higher case. What this line does is giving the register mp (r16) a new value of 0x00. What is that? The 0x means hex and stands for hexadecimal notation. Which is a bit too much to explain here. However I do want to mention that we now have had two ways of giving a value to a register. With binary and with hex. There is however a third one, simply with a number from 0 - 255. To convert a value from hex to decimal or the other way around, you can use the Windows calculator. Make sure that scientific option is turned on in the menu and after you entered a value (like 95) you press hex. Which gives you 5F. Cool, I just found out that it can do binary also. It is called bin on the calculator. Try it! Also try to change 255 and 256 (decimal) to binary and see what happens.
The next line "out portb, mp" makes the line before it more clearly. We are going to write the value of register mp (in binary, hex, decimal - 0b0000000, 0x00, 0) to PORTB. This means actually zero or that nothing will happen at all, haha. What a *great* instruction you might think, but this is required to make the LED blink. Turn on and off, this is the off part. If you see the next line "nop" and after that the other two instructions you will see that the PORTB will be put ON (high value). 0xff is 255.
The "nop" instruction is like what it sounds like, 'nope', 'nothing'. The microcontroller does nothing for a whole cycle. You wasted 0.83 µs of the microcontrollers time, al thought in timers it can sometimes be useful. Later on I will discuss a way to make a delay here instead of the nop and make the LED really blink.
The last nop has "; this is a comment" behind it. Whenever you use this character (;) everything behind it on the same line will be skipped by the compiler. Please use this often, if you don't comment your code and look at it again a month later on it won't make sense any more.
"rjmp loop" is the same as the "rjmp main" but now it is more useful, it will actually put the microcontroller in a loop by jumping to label loop, as you can see.
Readers that are paying good attention will notice that giving PORTB a value of 0xff (0b11111111 or 255) is a bit unnecessary. Only 0b00001000 is necessary, because this responds to port 3, which we also set in DDRB register. Well done!
Now let's replace those nop delays with a real delay that will give you a clear blink. To do this, we need to let the microcontroller do something else, for few (mili)seconds, when the LED is turned on or off to get a nice blink. We could place thousands of nop's in the code, but that is not really smart and takes way too much Flash memory. We will create another loop, but this time the microcontroller will just count. You need to place this code at the top, but under .def. Also you need to replace the nop's with rcall delay. Which brings me to quickly explaining the rcall instruction. What it does is the same as rjump, but it will return to where it jumped from after reading ret. However it won't work good, because now the microcontroller will start at delay, you need to add the line rjmp main back in the code. I think you can figure out where it needs to be put.
delay:
clr t1
clr t2
ldi temp, 100
delaywalk:
;dec t2 ;
;brne delaywalk ; uncomment these for longer delay
dec t1 ; 256 x 100 x 3 = 76800 cycles
brne delaywalk ; standard ATtiny13 clock is 9.6Mhz
dec temp ; 9.6Mhz/8 (divider) = 1.2Mhz a cycle
brne delaywalk ; total delay time = +/- 6 ms (with temp on 10)
ret ; go back to where you came from
clr is short for clear and all it does is clear the register to zero. But wait, what is t1 or t2? That's just a name I made up for a register, but I haven't defined it yet. So what you need to do is add the following line at the top of your code, under the other .def.
.def t1 = r17
.def t2 = r18
.def temp = r19
You can search the other instruction if you don't understand them, but I do want to tell you what happens in the delay code. First the registers are cleared and register temp gets a value of 100, next we go to label delaywalk and there we decrease the register t1 with one (not t2, because it's commented out). The register was cleared, which means it is zero and if you subtract one of zero you get 255. brne means 'branch if not equal' and that means if the previous instruction is not equal (or zero) it branches. Branches means it goes to the label defined after brne and that is delaywalk. The instruction dec takes 1 cycle and brne when true (not a zero as result) it will take 2 cycles, so a total of 3 cycles. This means in total 256 x 100 x 3 = 76800 cycles. With 0.83 µs per cycle that is 63.744 µs, that is 64 ms. Of course this is not completely correct, because ldi, out and rcall also take up cycles, but not that much time.
You can get the total Assembly code here, The Code
C
Work in progress...



