SD-card on Arduino

There are Arduino shields (like the modern Ethernet shield) that allow you to attach an SD card to your arduino. However if you are building a project that just needs a way to store data, then such a shield might be overkill.
It is possible to directly attacht an SD card to an Arduino and even then there is a cheap way and a more expensive elegant way.
The elegant way is to buy an SD card holder to solder on a circuitboard. These however come at a price.
Another way is to use the SD to microSD converter  that comes with most micro SD cards and use that one to solder to the circuitboard. Obviously that has a limitation as one then only can use micro SD cards and not the regular size SD cards.

SD card

The circuit in fact is pretty easy. other than ground and a powersupply line (3.3 V) you only need to connect 4 lines, 3 of which need a simple level adapter.

The Arduino SD library is very easy to use with easy to follow examples and it supports FAT16 and FAT32 file systems but note that it only supports one open file at a time and can only use short 8.3 file names.

For easy connection on a circuitboard consider soldering the pins to an angled header.

The resistors R1 – R7 can also be replaced by a 10k / 15k set and I have seen 1k8 and 3k3.
A better solution ofcourse would be to use a leveladaptor like a HEF4050 or an 74HC125 (such as in Lady Ada’s design)

With regard to Libraries that will work with this setup: There are 3 main libraries withint the Arduino development sphere:’SD’, ‘SDFat’ and ‘SDuFat’. These all should work. Just keep in mind that some of their examples still need the SSI pin (The chipselect) corrected because some boards will use pin 10, others will use pin 8 or pin 4.

If you are building this on breadboard and your connections might be a bit long, you may expect bus problems that will show up by e.g. problems with the initialization of the card. If that is the case. Try the example program of the SDuFat, as this library is one of the slowest. If that works, and the other library programs will still show problems, then at least you know that your card and connections are OK.

Then load the example sketch ‘SDinfo’  and find the line:

if (!card.init(SPI_HALF_SPEED, SdChipSelect)) {

change that to:

if (!card.init(SPI_SIXTEENTH_SPEED, SdChipSelect)) {


if (!card.init(SPI_QUARTER_SPEED, SdChipSelect)) {

and see if that will work. If it does, then your set up is OK but your wires are probably too long.


See also:


RS232 level converter for Arduino

The earlier circuit with an RS232 chip would have my preference  for connecting a self built Arduino to an RS232 port. However, if space is at a premium, a chip with 4 capacitors and a few resistors might just be too much. In that case a levelconverter made from discrete components might be a better choice.


Just to make clear: The TX and RX in the circuit refer to the microcontroller. The Tx signal from the Arduino gets fed to T2 and send to pin 2 of the DB9. That Pin 2 is the receive signal from the PC. The TX signal from the PC is available on Pin 3. This gets fed into T1 who then feeds it to the Rx of the Arduino.

There is a slightly fancier version available:

But the first circuit worked well for me.

Yet another circuit, looks as follows:

With regard to R5 that can be connected to TxD to borrow a negative voltage, but the circuit will only work half duplex then. It can also be connected to ground, which will probably work with most RS232 ports and that will allow Full duplex

One thing you have to keep in mind with these circuits: The RS232 does not trigger an automatic reset of your microcontroller anymore. If you still wish to have that, add another transistor, akin to what is build around T1 and attach that with it’s base side to the CTS and with its collector side to the Reset on the microcontroller, via a 100nF capacitor

Bluetooth for Arduino (or other)

Dealextreme offers a cheap Bluetooth module that can be used to add bluetooth to an Arduino/Atmel project.
Connecting it is really simple as you can see in the below circuit.
As it is on a 3.3 Volt supply, in connevting it to a generally 5 volt TTL UART, you need to keep a couple of things in mind:
Connecting the Tx line directly to the Rx line of the UART is no problem, but for the Tx line coming from the UART you need a voltage adapter that is formed by the 5k6 and 10k resistors.
In order to get the Bluetooth model to work properly, it needs a reset signal that is taken from the Vcc.
Pins that are not used should be left not connected. Though the module has 34 pins, you only really need to connect 8 pins to establish communication and 4 of those are connections to ground.


At first glance, soldering to the module may seem a bit daunting as it is real tiny. I decided to solder some small stiff wires to the cups that form the pins and stick these through some stripboard, raising the module a bit off of the stripboard. Another solution is to solder the module directly to the copperside of a PCB, but that needs some accurate etching. Just to make clear: Pin 3 and 4 don’t need to be connected to anything, but it might be handy to attach them to a 2 pin header that can be shorted in case that is needed.

Using the module is fairly simple: linvor
First establish if it actually works: after putting the circuit together, apply voltage supply and start up a bluetooth device such as a computer or a mobile phone and see if they can find it. It should come up as ‘linvor’  and asks for a pincode which is ‘1234’.

If you check the ‘services’  of the device it will report itself as a serial interface. The LED in the circuit is ON when there is a connection and it ‘blinks’ when there isn’t.
So if this all works, at least that is half of the worries done. Now you got to make sure if the serial interface is actually doing something. You can do that in various ways, but set your communication speed to 9600/8N1 Baud as that is the default baudrate of this chip:

  • Hook it up to a working arduino/atmel/pic controller and see if you can get connection (this one for instance). or
  • Hook it up to a computer’s serial port (but make sure you use a level adapter before you do that coz RS232 voltages will fry yr chip) and see if you can communicate (like sending AT commands). or
  • Connect the Rx and Tx of this circuit, establish a bluetooth connection through yr computer, use the Arduino IDE (select ‘no line ending) to send characters to the proper COM port and see if they get echoed. 

If any of these 3 work you are set to go.

The firmware
Though many of these models may look exactly the same (and in fact could be the same), they still may have different firmware. The Dealextreme module has linvor 1.5 firmware, als known as HC6. Other models may have HC5 firmware.
The HC5 firmware has a very limited AT instruction set:

It can check the settings, it can change the baudrate and parity and it can change the PIN code and the name:

Command Response Note
AT OK Just a check
AT+VERSION Linvor1.5 Firmware version
AT+BAUDx OKx Sets Baudrate
1 for 1200 baud
2 for 2400 baud
3 for 4800 baud
4 for 9600 baud
5 for 19200 baud
6 for 38400 baud
7 for 57600 baud
8 for 115200 baud
9 for 230400 baud
A for 460800 baud
B for 921600 baud
C for 1328400 baud
AT+NAMEstring OKsetname Set device name, 20 characters max
AT+PINxxxx OKsetpin Set PINcode. 1234 bij default
AT+Px OKsetparity Set the parity
N for None
E for even
O for Odd


With the HC6 firmware, there should be no LF or CR after the command. The module will interpret the command that is given within 1 second. As therefore you have 1 second to type the command, it might be better to cut and paste it from e.g. Notepad. Now how to get into AT setting is simple for the HC5 firmware. If the module has not paired with another bluetooth transceiver, it is in AT mode. You may need to connect the CTS and RTS pins and you may need to type ‘$$$’ first

HC5 Firmware
If you have a model with HC5 firmware, you need to do a bit more to get it in AT mode:

This firmware provides 2 ways to activate AT mode :

The first way:

  • set low level on PIN34
  • Supply power to the module
  • set high level on PIN34

Then the module will enter on AT mode with your configured baud rate (default : 9600 8N1)

The second way :

  • set high level on PIN34,
  • Supply power to the module

The module will ALWAYS enter in AT mode with a 38400 baud rate (8N1).
The second way is useful if you don’t remember your configured baud rate.
AT mode can be reached only when PIN34 is high.

Moreover sending AT commands is different from the HC06 firmware (Linvor). In HC05 firmware you have to send CR and LF after each command.

Sme useful AT commands :

  • AT\r\n AT test command should respond OK\r\n
  • AT+ROLE=1\r\n Set master mode
  • AT+ROLE=0\r\n Set slave mode
  • AT+VERSION?\r\n Get the firmware version
  • AT+UART=115200,1,2\r\n Set the baud rate to 115200
  • AT+PIO=10,1\r\n Set PIO10 to high level

Further information can be found in this documentation.



Simple Arduino

Arduino BasicAn arduino in its simplest form is an ATMEGA chip with bootloader, a crystal, 2 capacitors and reset switch. An LED on pin 13 and of course some possibilities to make easy connections are ‘nice to have’.

A simple circuit is found to the right. It is a small adaptation from Iñigo Zuluaga, who is a master in designing nifty circuits with a paper ‘silk screen’. Other people have done similar things like in the paperduino project van Guillherme Martins or the oomlaut arduino and also here.

The circuit is quite easy. Programs can be uploaded with either one of the many USB or serial connector boards or cables

The simple arduino, connected to a serial level converter

Serial connection for your Arduino / Atmega

A connection between a computer and a self build Arduino (or other microcontroller) is easy to make with a MAX232 chip. The figure below is an almost classic design. It is according to the october 2002 revision of the datasheet: C4 is connected between pin2 and earth, while in other designs it is connected between pin 2 and Vcc (kathode on Vcc). This circuit just worked for me. I guessed that if pin 2 has a higher potential than Vcc, it also has a higher potential than ground. In some circuits you will also find it connected between pin 2 and 6

In principle you could do with only 2 signals (Tx and Rd), but I have added a reset that is connected to the RTS signal on the subD connector (Via the Max232 of course) MAX232

Just for some clarification: Normally with a serial communication set up, the Tx signal of one device, is connected to the Rd pin of the other device. In this circuit, that is taken care of on the SubD connector: Pin 3 is the Tx signal, that goes to the RdIn (pin 8)  of the chip. It is converted in voltage in the chip, then goes to RdOut on pin 9. That pin –though called Rd-  then goes to the Rd pin on the Arduino/Atmega/Pic. The connection between Tx and Rd already has been made, no need to switch that again.
Same for the Tx signal of the microprocessor: It attaches to pin10 on the Max232, is converted and appears on pin 7 of the chip and then is brought to the Rd pin on the SubD connector. The DB9 plug in th epicture is a female plug looked at from the solder side.
If for any reason one would prefer to use an old SubD25 serial connector, the table below shows the corresponding pins between the two. To make things a bit confusing both pin 2 and 3 have exactly opposite functions on these connectors.

DB9 Signal DB25
1 DCD 8
2 Rd 3
3 Tx 2
4 DTR 20
5 SGnd 7
6 DSR 6
7 RTS 4
8 CTS 5
9 Ri 22

The LED’s and  resistors R3 and R4 are not really necessary, they just give a visual indication of the transmitting signals, choose a nice color.

R1 and R2 are in fact also not necessary, but they offer some form of protection should you wire up wrong (like connecting to the wrong pin on your microprocessor)

RS232 naar TTL op stripboard

Once the circuit is build, then first test it before you attach it to your Arduino. The easiest way to test it is to temporarily connect the Tx and Rd pin (so the ends of R1 and R2) with eachother. Apply 5 volts to the chip and connect your serial cable.

Open up the Arduino IDE, select the proper COM port under ‘Tools’, open up the serial monitor and type in some characters and click ‘Send’. The characters should be echo-ed back.

For me this worked with all baud-rates.

Then disconnect the temporary connection you just made and connect Tx and Rd to the corresponding pins on your board/chip.

If that has the bootloader installed, you should be able to upload a program to your board with this serial connection.

Worked like a charm

The finished circuit on stripboard. I opted for a 25DB connector rather than a 9DB connector because that fitted the serial cable I had. Don’t be confused by the double row of headers. Again, that is all I had but a single row would suffice
The serial interface, connected to a simple arduino board

Note: Many ‘modern’ computers that  still have a serial connector do in fact already not work with the high voltages that we know from true RS232 and then the MAX232 might not be needed, but one could use a levelshifter as e.g. Sparkfun is selling ($6.95) and try to build that yourself. It is not a big circuit, but in my idea, usung the MAX232 is just easier and the RS232Shifter board is actually a bit of a hack and does not seem as reliable.

Lots of RS232 info here. and here

Another one here, and here, and here, and here, and here, and here (Thai)

Max 232


Program an ATtiny with an Arduino Nano

Many sites already described how to use the Arduino as a programmer for the ATtiny series, but as some people still have some problems with it, it won’t hurt to share my experience in doing this with an Arduino Nano.

The connection between the Arduino and the ATtiny is in essence the same, regardless of what Arduino one has. One needs to connect the ISP hearder between both chips. But for the UNO and the Nano there is a little addition in the form of a capacitor between  ground and the reset pin:

Most circuits will show a 10uF electrolytic capacitor, but I used a 33uF elco and that worked perfectly.

In order to use the ATtiny 45 or 85 you need to download some software. For the Attiny13 there are other cores. If you are using the Attiny13 core you also need to create a boot.txt file
You will also find a core for the Attiny here. and a number of them here.

Now create a folder called ‘Hardware’ in the folder where your Arduino IDE saves it’s sketches. Unzip this file to the newly created hardware folder. If you had your Arduino IDE running, you need to close it and restart it so it can read the proper files.

Now do the following:

  • Connect Arduino Nano and Attiny85 as described above, but do not connect the capacitor yet.
  • Load the ‘Arduino as ISP sketch’
  • Disconnect USB
  • Insert capacitor
  • Reconnect USB
  • Load Attiny sketch of your choosing in the Arduino IDE (e.g. the ‘blink’ sketch)
  • Choose ‘ATtiny85 with Arduino as ISP’ in yr ‘Tools->boards’
  • Upload
  • Ignore the errors about PAGEL and BS2
  • Remove USB
  • Remove capacitor and at least the line to the reset of the Attiny (the one from pin 1)

Your sketch should now be correctly in your ATtiny.

Configuring the ATtiny to run at 8 MHz (for SoftwareSerial support)

By default, the ATtiny’s run at 1 MHz (the setting used by the unmodified “ATtiny45″, etc. board menu items). You need to do an extra step before the programming to configure the microcontroller to run at 8 MHz – necessary for use of the SoftwareSerial library. Once you have the microcontroller connected, select the appropriate item from the Boards menu (e.g. “ATtiny45 (8 MHz)”). Then, run the “Burn Bootloader” command from the Tools menu. This configures the fuse bits of the microcontroller so it runs at 8 MHz. Note that the fuse bits keep their value until you explicitly change them, so you’ll only need to do this step once for each microcontroller. (Note this doesn’t actually burn a bootloader onto the board; you’ll still need to upload new programs using an external programmer.)

With regard to writing a sketch for the ATtiny85, there is only a limited instruction set:

See also:

Programming an Attiny with Arduino 1.01.

TinyWireM & TinyWireS: Wire (I2C / TWI) library for the ATtiny85 (using USI)

Timer interrupts

This article will discuss AVR and Arduino timers and how to use them in Arduino projects or custom AVR circuits.

What is a timer?

Like in real life, in microcontrollers a timer is something you set to trigger an alert at a certain point in the future. When that point arrives, that alert interrupts the microprocessor, reminding it to do something, like run a specific piece of code.

Timers, like external interrupts, run independently from your main program. Rather than running a loop or repeatedly calling millis(), you can let a timer do that work for you while your code does other things.

So suppose you have a device that needs to do something –like blink an LED every 5 seconds. If you are not using timers but just conventional code techniques, you’d have to set a variable with the next time the LED should blink, then check constantly to see if that time had arrived. With a timer interrupt, you can set up the interrupt, then turn on the timer. The LED will blink perfectly on time, regardless of what your main program was just doing

How do timers work?

Timers work by incrementing a counter variable known as a counter register. The counter register can count to a certain value, depending on its size (usually 8 bits or 16 bits). The timer increments this counter one step at a time until it reaches its maximum value, at which point the counter overflows, and resets back to zero. The timer normally sets a flag bit to let you know an overflow has occurred. This flag can be checked manually, or you can have the timer trigger an interrupt as soon as the flag is set. And as with any other interrupt, you can specify an Interrupt Service Routine (ISR) to run your own code when the timer overflows. The ISR will automatically reset the overflow flag, so using interrupts is usually your best option for simplicity and speed.

To increment the counter value at regular intervals, the timer must have a clock source.  The clockprovides a consistent signal.  Every time the timer detects this signal, it increases its counter by one.

Since timers are dependent on the clock source, the smallest measurable unit of time will be the period of the clock.  If you provide a 16 MHz clock signal to a timer, the timer resolution (or timer period) is:

T = 1 / f  (f is the clock frequency)
T = 1 /(16* 10^6)
T = (0.0625 * 10^-6) s

The timer resolution thus is 0.0625 millionth of a second.

For 8 MHz this would be 0.125 millionth of a second

and for 1 MHz exactly one millionth of a second

You can supply an external clock source for use with timers, but usually the chip’s internal clock is used as the clock source. The 16 MHz crystal that is usually part of a setup for an Atmega328 can be considered as part of the internal clock.

Different timers

In the standard Arduino variants or the 8-bit AVR chips, there are several timers at your disposal.

The ATmega8, ATmega168 and ATmega328 have three timers: Timer0, Timer1, and Timer2. They also have a watchdog timer, which can be used as a safeguard or a software reset mechanism. The Mega series has 3 additional timers.


Timer0 is an 8-bit timer, meaning its counter register can record a maximum value of 255 (the same as an unsigned 8-bit byte). Timer0 is used by native Arduino timing functions such as delay() and millis(), so unless you know what you are doing, timer 0 is best left alone.


Timer1 is a 16-bit timer, with a maximum counter value of 65535 (an unsigned 16-bit integer). The Arduino Servo library uses this timer, so keep that in mind if you use this timer in your projects.


Timer2 is an 8-bit timer that is very similar to Timer0. It is used by the Arduino tone() function.

Timer3, Timer4, Timer5

The AVR ATmega1280 and ATmega2560 (found in the Arduino Mega variants) have an additional three timers.  These are all 16-bit timers, and function similarly to Timer1.

Configuring the timer register

In order to use these timers the built-in timer registers on the AVR chip that store timer settings need to be configured.  There are a number of registers per timer.  Two of these registers –the Timer/Counter Control Registers- hold setup values, and are called TCCRxA and TCCRxB, where x is the timer number (TCCR1A and TCCR1B, etc.).   Each register holds 8 bits, and each bit stores a configuration value.  The ATmega328 datasheet specifies those as follows:

Bit 7 6 5 4 3 2 1 0 TCCR1A
0x80 COM1A1 COM1A0 COM1B1 COM1B0 WGM11 WGM10
Initial Value 0 0 0 0 0 0 0 0
Bit 7 6 5 4 3 2 1 0 TCCR1B
0x81 ICNC1 ICES1 WGM13 WGM12 CS12 CS11 CS10
ReadWrite R/W R/W R R/W R/W R/W R/W R/w
Initial Value 0 0 0 0 0 0 0 0

The most important settings are the last three bits in TCCR1B, CS12, CS11, and CS10.  These determine the timer clock setting.  By setting these bits in various combinations, you can make the timer run at different speeds.  This table shows the required settings:

Clock Select bit description
CS12 CS11 CS10 Description
0 0 0 No clock source (Timer/Counter stopped)
0 0 1 clki/o/1 (No prescaling)
0 1 0 clki/o/8 (From Prescaler)
0 1 1 clki/o/64 (From Prescaler)
1 0 0 clki/o/256 (From Prescaler)
1 0 1 clki/o/1024 (From Prescaler)
1 1 0 External clock source on T1 pin. Clock on falling edge
1 1 1 External clock source on T1 pin. Clock on rising edge

By default, these bits are set to zero.  Suppose you want to have Timer1 run at clock speed, with one count per clock cycle.  When it overflows, you want to run an Interrupt Service Routine (ISR) that toggles a LED tied to pin 13 on or off. Below you will find the Arduino code for this example, for completeness I use avr-libc routines wherever they don’t make things overly complicated.

First, initialize the timer:

// avr-libc library includes
#include <avr/io.h>
#include <avr/interrupt.h>
#define LEDPIN 13

void setup()
// initialize Timer1
cli();         // disable global interrupts
TCCR1A = 0;    // set entire TCCR1A register to 0
TCCR1B = 0;    // set entire TCCR1B register to 0 
               // (as we do not know the initial  values) 

// enable Timer1 overflow interrupt:
TIMSK1 | = (1 << TOIE1); //Atmega8 has no TIMSK1 but a TIMSK register

// Set CS10 bit so timer runs at clock speed: (no prescaling)
TCCR1B |= (1 << CS10); // Sets bit CS10 in TCCR1B
// This is achieved by shifting binary 1 (0b00000001) // to the left by CS10 bits. This is then bitwise // OR-ed into the current value of TCCR1B, which effectively set // this one bit high. Similar: TCCR1B |= _BV(CS10); // enable global interrupts: sei(); }

The register TIMSK1 is the Timer/Counter1 Interrupt Mask Register. It controls which interrupts the timer can trigger. Setting the TOIE1 bit (=Timer1 Overflow Interrupt Enable) tells the timer to trigger an interrupt when the timer overflows. It can also be set to other bits to trigger other interrupts. More on that later.

When you set the CS10 bit, the timer is running, and since an overflow interrupt is enabled, it will call the ISR(TIMER1_OVF_vect) whenever the timer overflows.

Next define the ISR:


digitalWrite(LEDPIN, !digitalRead(LEDPIN));
// or use: PORTB ^= _BV(PB5);// PB5 =pin 19 is digitalpin 13

Now you can define loop() and the LED will toggle on and off regardless of what’s happening in the main program. To turn the timer off, set TCCR1B = 0 at any time.

How fast will the LED blink with this code?

Timer1 is set to interrupt on an overflow, so if you are using an ATmega328 with a 16MHz clock. Since Timer1 is 16 bits, it can hold a maximum value of (2^16 – 1), or 65535. At 16MHz, we’ll go through one clock cycle every 1/(16*10^6) seconds, or 6.25*10-8 s. That means 65535 timer counts will pass in (65535 * 6.25*10-8s) and the ISR will trigger in  about 0.0041 seconds. Then again and again, every four thousandths of a second after that. That is too fast to see it blink. If anything, we’ve created an extremely fast PWM signal for the LED that’s running at a 50% duty cycle, so it may appear to be constantly on but dimmer than normal. An experiment like this shows the amazing power of microprocessors – even an inexpensive 8-bit chip can process information far faster than we can detect.

Timer prescaling and preloading

To control this you can also set the timer to use a prescaler, which allows you to divide your clock signal by various powers of two, thereby increasing your timer period.  For example, if you want the LED blink at one second intervals. In the TCCR1B register, there are three CS bits to set a better timer resolution.  If you set CS10 and CS12 using:

TCCR1B |= (1 << CS10); and TCCR1B |= (1 << CS12);, the clock source is divided by 1024. This gives a timer resolution of 1/(16*10⁶ / 1024), or 0.000064 seconds (15625 Hz). Now the timer will overflow every (65535 * 6.4*10-5s), or 4.194s.

If you would set only CS12 using TCCR1B |=(1<<CS12); (or just TCCR1B=4), the clock source is divided by 256. This gives a timer resolution of 1/(16*10⁶/256), or 0.000016 sec (62500 Hz) and the timer will overflow every (65535 *0.000016=) 1.04856 sec.

Suppose you do not want an 1.04856 sec interval but a 1 sec interval. It is clear to see that if the counter wasn’t 65535 but 62500 (being equal to the frequency), the timer would be set at 1sec. The counter thus is 65535-62500=3035 too high. To have more precise 1 second timer we need to change only one thing – timer’s start value saved by  TCNT1 register (Timer Counter ). We do this with TCNT1=0x0BDB; BDB being the hex value of 3035. A Value of 34286 for instance would give 0.5 sec ((65535-34286)/62500)

The code looks as follows:

// avr-libc library includes
#include <avr/io.h> //  can be omitted
#include <avr/interrupt.h> // can be omitted
#define LEDPIN 13
/* or use
DDRB = DDRB | B00100000;  // this sets pin 5  as output                       // without changing the value of the other
                         // pins 
void setup()

// initialize Timer1
cli();         // disable global interrupts
TCCR1A = 0;    // set entire TCCR1A register to 0
TCCR1B = 0;    // set entire TCCR1A register to 0

// enable Timer1 overflow interrupt:
TIMSK1 |= (1 << TOIE1);
// Preload with value 3036
//use 64886 for 100Hz
//use 64286 for 50 Hz
//use 34286 for 2 Hz
// Set CS10 bit so timer runs at clock speed: (no prescaling)
TCCR1B |= (1 << CS12); // Sets bit CS12 in TCCR1B
// This is achieved by shifting binary 1 (0b00000001)
// to the left by CS12 bits. This is then bitwise
// OR-ed into the current value of TCCR1B, which effectively set
// this one bit high. Similar: TCCR1B |= _BV(CS12);
//  or: TCCR1B= 0x04;

// enable global interrupts:

digitalWrite(LEDPIN, !digitalRead(LEDPIN));
TCNT1=0x0BDC; // reload the timer preload

void loop() {}


But there’s another mode of operation for AVR timers. This mode is called Clear Timer on Compare Match, or CTC. Instead of counting until an overflow occurs, the timer compares its count to a value that was previously stored in a register. When the count matches that value, the timer can either set a flag or trigger an interrupt, just like the overflow case.

To use CTC, you need to figure out how many counts you need to get to a one second interval. Assuming we keep the 1024 prescaler as before, we’ll calculate as follows:

(target time) = (timer resolution) * (# timer counts + 1)

and rearrange to get


(# timer counts + 1) = (target time) / (timer resolution)
(# timer counts + 1) = (1 s) / (6.4e-5 s)
(# timer counts + 1) = 15625
(# timer counts) = 15625 - 1 = 15624

You have to add the extra +1 to the number of timer counts because in CTC mode, when the timer matches the desired count it will reset itself to zero. This takes one clock cycle to perform, so that needs to be factored into the calculations. In many cases, one timer tick isn’t a huge deal, but if you have a time-critical application it can make all the difference in the world.

Now the setup() function to configure the timer for these settings is as follows:

void setup()

pinMode(LEDPIN, OUTPUT); // you have to define the LEDPIN as say 13
                         // or so earllier in yr program
// initialize Timer1
cli();          // disable global interrupts
TCCR1A = 0;     // set entire TCCR1A register to 0
TCCR1B = 0;     // same for TCCR1B

// set compare match register to desired timer count:
OCR1A = 15624;

// turn on CTC mode:
TCCR1B |= (1 << WGM12);

// Set CS10 and CS12 bits for 1024 prescaler:
TCCR1B |= (1 << CS10);
TCCR1B |= (1 << CS12);

// enable timer compare interrupt:
TIMSK1 |= (1 << OCIE1A);
sei();          // enable global interrupts

And you need to replace the overflow ISR with a compare match version:


digitalWrite(LEDPIN, !digitalRead(LEDPIN));

The LED will now blink on and off at precisely one second intervals. And you are free to do anything you want in loop(). As long as you don’t change the timer settings, it won’t interfere with the interrupts. With different mode and prescaler settings, there’s no limit to how you use timers.

Here’s the complete example in case you’d like to use it as a starting point for your own project.

// Arduino timer CTC interrupt example
// avr-libc library includes
#include <avr/io.h>
#include <avr/interrupt.h>
#define LEDPIN 13
void setup()
// initialize Timer1
cli();          // disable global interrupts
TCCR1A = 0;     // set entire TCCR1A register to 0
TCCR1B = 0;     // same for TCCR1B

// set compare match register to desired timer count:
OCR1A = 15624;

// turn on CTC mode:
TCCR1B |= (1 << WGM12);

// Set CS10 and CS12 bits for 1024 prescaler:
TCCR1B |= (1 << CS10);
TCCR1B |= (1 << CS12);

// enable timer compare interrupt:
TIMSK1 |= (1 << OCIE1A);

// enable global interrupts:

void loop()
// main program

digitalWrite(LEDPIN, !digitalRead(LEDPIN));

Remember that you can use the built-in ISRs to extend timer functionality. For example, if you wanted to read a sensor every 10 seconds, there’s no timer set-up that can go this long without overflowing. However, you can use the ISR to increment a counter variable in your program once per second, then read the sensor when the variable hits 10. Using the same CTC setup as in our previous example, the ISR would look something like this:


if(seconds == 10)
seconds = 0;

For a variable to be modified within an ISR, it is good custom to declare it as volatile. In this case, you need to declare volatile byte seconds; or similar at the start of the program.

A word on the Atmega8

The Atmega8 seems to give people problems with use of the timers, one reason is that it doesn’t have a TIMSK1 register (in fact it doesnt have a TIMSKn register), it does have a TIMSK register though that is shared amongst the 3 timers. As I do not have an Atmega8 (like the early Arduino NG) I can not test it, but if you encounter problems, the following programs will help:

// this code sets up counter0 with interrupts enabled on an Atmega8
// beware, it may generate  errors in Arduino IDE 
// as 'milis' uses timer0 
#include <avr/io.h>
#include <avr/io.h>

void setup()
DDRD &= ~(1 << DDD4); // Clear the PD4 pin
// PD0 is now an input

PORTD |= (1 << PORTD4); // turn On the Pull-up
// PD4 is now an input with pull-up enabled

TIMSK |= (1 << TOIE0); // enable timer interrupt

TCCR0 |= (1 << CS02) | (1 << CS01) | (1 << CS00);
// Turn on the counter, Clock on Rise

void loop()
// Stuff

// interrupt just fired, do stuff

A 1 sec flasher using the timer 1 CTC mode for the Atmega 8 would look like this:


void setup()
/* or use:
DDRB = DDRB | B00100000;  // this sets pin 5  as output
                       // without changing the value of the other pins 
// Disable interrupts while loading registers
// Set the registers
TCCR1A = 0; //Timer Counter Control register
// Set mode
TCCR1B = (1 << WGM12); // turn on CTC mode
// Set prescale values (1024). (Could be done in same statement
// as setting the WGM12 bit.)
TCCR1B |= (1 << CS12) | (1 << CS10);
//Enable timer compare interrupt===> TIMSK1 for ATmega328, 
//TIMSK for ATmega8
TIMSK |= (1 << OCIE1A);
// Set OCR1A
OCR1A = 15624;
// Enable global interrupts
void loop(){}
   digitalWrite(13, !digitalRead(13));
   //PORTB ^= _BV(PB5); // as digitalWrite(13,x) is an Arduino 
   //function, direct writing to the port may be preferable

It is obvious that this is very akin to the CTC program presented earlier for the Atmega328 and in fact will work on the Atmega238 as well by renaming ‘TIMSK’ to ‘TIMSK1’

Other Atmega chips:

TCCR0 should be TCCR0A in ATmega164P/324P/644


The Attiny series has timer interrupts too. This code sets up a 50uS timer in CTC mode on the Attiny85 (pag 79 datasheet)

TCCR0A = (1 << WGM01);   //CTC mode. set WGM01
TCCR0B = (2 << CS00);    //divide by 8  sets 
OCR0A = F_CPU/8 * 0.000050 - 1;    // 50us compare value
TIMSK |= (1<<OCIE0A);              //set interrupt

                                   // code of choice!

I wrote a follow up with some practical examples.

More on timers here








pwm generation by timers

here (Atmega8)

Atmega8 Datasheet

Atmega328 Datasheet