Sei sulla pagina 1di 135

MC interrupts

http://www.gammon.com.au/interrupts
Intro
This article discusses interrupts on the Arduino Uno (Atmega328) and similar processors,
using the Arduino IDE. The concepts however are very general. The code examples
provided should compile on the Arduino IDE (Integrated Development Environment).

TL;DR :
When writing an Interrupt Service Routine (ISR):

Keep it short
Don't use delay ()
Don't do serial prints
Make variables shared with the main code volatile
Variables shared with main code may need to be protected by "critical
sections" (see below)
Don't try to turn interrupts off or on
What are interrupts?
Most processors have interrupts. Interrupts let you respond to "external" events while
doing something else. For example, if you are cooking dinner you may put the potatoes
on to cook for 20 minutes. Rather than staring at the clock for 20 minutes you might set
a timer, and then go watch TV. When the timer rings you "interrupt" your TV viewing to
do something with the potatoes.

What interrupts are NOT

Interrupts are not for simply changing your mind and doing something different. For
example:

I interrupted my television viewing to take a bath.


I was reading a book when visitors arrived and interrupted me. We then went to
the movies.
The user pressed a red button to interrupt the robot walking around.

The above are examples of doing something different. They should not be done in an
interrupt routine. The most that an interrupt (service) routine might do would be to
remember that the red button was pressed. This fact would then be tested in the main
program loop.

Example of interrupts

const byte LED = 13;


const byte BUTTON = 2;

// Interrupt Service Routine (ISR)


void pinChange ()
{
if (digitalRead (BUTTON) == HIGH)
digitalWrite (LED, HIGH);
else
digitalWrite (LED, LOW);
} // end of pinChange

void setup ()
{
pinMode (LED, OUTPUT); // so we can update the LED
digitalWrite (BUTTON, HIGH); // internal pull-up resistor
attachInterrupt (0, pinChange, CHANGE); // attach interrupt handler
} // end of setup

void loop ()
{
// loop doing nothing
}

This example shows how, even though the main loop is doing nothing, you can turn the
LED on pin 13 on or off, if the switch on pin D2 is pressed.

To test this, just connect a wire (or switch) between D2 and Ground. The internal pullup
(enabled in setup) forces the pin HIGH normally. When grounded, it becomes LOW. The
change in the pin is detected by a CHANGE interrupt, which causes the Interrupt Service
Routine (ISR) to be called.

In a more complicated example, the main loop might be doing something useful, like
taking temperature readings, and allow the interrupt handler to detect a button being
pushed.

Available interrupts

Below is a list of interrupts, in priority order, for the Atmega328:

1 Reset
2 External Interrupt Request 0 (pin D2) (INT0_vect)
3 External Interrupt Request 1 (pin D3) (INT1_vect)
4 Pin Change Interrupt Request 0 (pins D8 to D13) (PCINT0_vect)
5 Pin Change Interrupt Request 1 (pins A0 to A5) (PCINT1_vect)
6 Pin Change Interrupt Request 2 (pins D0 to D7) (PCINT2_vect)
7 Watchdog Time-out Interrupt (WDT_vect)
8 Timer/Counter2 Compare Match A (TIMER2_COMPA_vect)
9 Timer/Counter2 Compare Match B (TIMER2_COMPB_vect)
10 Timer/Counter2 Overflow (TIMER2_OVF_vect)
11 Timer/Counter1 Capture Event (TIMER1_CAPT_vect)
12 Timer/Counter1 Compare Match A (TIMER1_COMPA_vect)
13 Timer/Counter1 Compare Match B (TIMER1_COMPB_vect)
14 Timer/Counter1 Overflow (TIMER1_OVF_vect)
15 Timer/Counter0 Compare Match A (TIMER0_COMPA_vect)
16 Timer/Counter0 Compare Match B (TIMER0_COMPB_vect)
17 Timer/Counter0 Overflow (TIMER0_OVF_vect)
18 SPI Serial Transfer Complete (SPI_STC_vect)
19 USART Rx Complete (USART_RX_vect)
20 USART, Data Register Empty (USART_UDRE_vect)
21 USART, Tx Complete (USART_TX_vect)
22 ADC Conversion Complete (ADC_vect)
23 EEPROM Ready (EE_READY_vect)
24 Analog Comparator (ANALOG_COMP_vect)
25 2-wire Serial Interface (I2C) (TWI_vect)
26 Store Program Memory Ready (SPM_READY_vect)

Internal names (which you can use to set up ISR callbacks) are in brackets.

Warning: If you misspell the interrupt vector name, even by just getting the capitalization
wrong (an easy thing to do) the interrupt routine will not be called, and you will not get a
compiler error.

Summary of interrupts

The main reasons you might use interrupts are:

To detect pin changes (eg. rotary encoders, button presses)


Watchdog timer (eg. if nothing happens after 8 seconds, interrupt me)
Timer interrupts - used for comparing/overflowing timers
SPI data transfers
I2C data transfers
USART data transfers
ADC conversions (analog to digital)
EEPROM ready for use
Flash memory ready

The "data transfers" can be used to let a program do something else while data is being
sent or received on the serial port, SPI port, or I2C port.
Wake the processor

The "low" pin interrupts, pin-change interrupts, and the watchdog timer interrupt, can
also be used to wake the processor up. This can be very handy, as in sleep mode the
processor can be configured to use a lot less power (eg. around 10 microamps). A "low
pin" interrupt can be used to wake up a gadget (eg. if you press a button on it), or a
"watchdog timer" interrupt might wake it up periodically (eg. to check the time or
temperature).

Pin-change interrupts could be used to wake the processor if a key is pressed on a


keypad, or similar.

The processor can also be awoken by a timer interrupt (eg. a timer reaching a certain
value, or overflowing) and certain other events, such as an incoming I2C message.

[EDIT] 15/Dec/2013 : We now believe that all external interrupts (not just LOW ones) will
wake the processor from sleep. This seems more consistent with the fact that pin change
interrupts can wake the processor.

Enabling / disabling interrupts

The "reset" interrupt cannot be disabled. However the other interrupts can be
temporarily disabled by clearing the interrupt flag.

Enable interrupts
You can enable interrupts with the function call "interrupts" or "sei" like this:

interrupts (); // or ...


sei (); // set interrupts flag

Disable interrupts
If you need to disable interrupts you can "clear" the interrupt flag like this:

noInterrupts (); // or ...


cli (); // clear interrupts flag
Either method has the same effect, using "interrupts" / "noInterrupts" is a bit easier to
remember which way around they are.

The default in the Arduino is for interrupts to be enabled. Don't disable them for long
periods or things like timers won't work properly.

Why disable interrupts?

There may be time-critical pieces of code that you don't want interrupted, for example
by a timer interrupt.

Also if multi-byte fields are being updated by an ISR then you may need to disable
interrupts so that you get the data "atomically". Otherwise one byte may be updated by
the ISR while you are reading the other one.

For example:

noInterrupts ();
long myCounter = isrCounter; // get value set by ISR
interrupts ();

Temporarily turning off interrupts ensures that isrCounter (a counter set inside an ISR)
does not change while we are obtaining its value.

Warning: if you are not sure if interrupts are already on or not, then you need to save
the current state and restore it afterwards. For example, the code from the millis()
function does this:

unsigned long millis()


{
unsigned long m;
uint8_t oldSREG = SREG;

// disable interrupts while we read timer0_millis or we might get an


// inconsistent value (e.g. in the middle of a write to timer0_millis)
cli();
m = timer0_millis;
SREG = oldSREG;

return m;
}
Note the lines in bold save the current SREG (status register) which includes the interrupt
flag. After we have obtained the timer value (which is 4 bytes long) we put the status
register back how it was.

What is interrupt priority?

Since there are 25 interrupts (other than reset) it is possible that more than one
interrupt event might occur at once, or at least, occur before the previous one is
processed. Also an interrupt event might occur while interrupts are disabled.

The priority order is the sequence in which the processor checks for interrupt events. The
higher up the list, the higher the priority. So, for example, an External Interrupt Request
0 (pin D2) would be serviced before External Interrupt Request 1 (pin D3).

Can interrupts occur while interrupts are disabled?

Interrupts events (that is, noticing the event) can occur at any time, and most are
remembered by setting an "interrupt event" flag inside the processor. If interrupts are
disabled, then that interrupt will be handled when they are enabled again, in priority
order.

What are "volatile" variables?

Variables shared between ISR functions and normal functions should be declared
"volatile". This tells the compiler that such variables might change at any time, and thus
the compiler must reload the variable whenever you reference it, rather than relying
upon a copy it might have in a processor register.

For example:

volatile boolean flag;

// Interrupt Service Routine (ISR)


void isr ()
{
flag = true;
} // end of isr

void setup ()
{
attachInterrupt (0, isr, CHANGE); // attach interrupt handler
} // end of setup

void loop ()
{
if (flag)
{
// interrupt has occurred
}
} // end of loop

How do you use interrupts?

You write an ISR (interrupt service routine). This is called when the interrupt
occurs.
You tell the processor when you want the interrupt to fire.

Writing an ISR

Interrupt Service Routines are functions with no arguments. Some Arduino libraries are
designed to call your own functions, so you just supply an ordinary function (as in the
examples above), eg.

// Interrupt Service Routine (ISR)


void pinChange ()
{
flag = true;
} // end of pinChange

However if a library has not already provided a "hook" to an ISR you can make your own,
like this:

volatile char buf [100];


volatile byte pos;

// SPI interrupt routine


ISR (SPI_STC_vect)
{
byte c = SPDR; // grab byte from SPI Data Register

// add to buffer if room


if (pos < sizeof buf)
{
buf [pos++] = c;
} // end of room available
} // end of interrupt routine SPI_STC_vect

In this case you use the "ISR" define, and supply the name of the relevant interrupt
vector (from the table earlier on). In this case the ISR is handling an SPI transfer
completing. (Note, some old code uses SIGNAL instead of ISR, however SIGNAL is
deprecated).

Connecting an ISR to an interrupt

For interrupts already handled by libraries, you just use the documented interface. For
example:

void receiveEvent (int howMany)


{
while (Wire.available () > 0)
{
char c = Wire.receive ();
// do something with the incoming byte
}
} // end of receiveEvent

void setup ()
{
Wire.onReceive(receiveEvent);
}

In this case the I2C library is designed to handle incoming I2C bytes internally, and then
call your supplied function at the end of the incoming data stream. In this case
receiveEvent is not strictly an ISR (it has an argument) but it is called by an inbuilt ISR.

Another example is the "external pin" interrupt.

// Interrupt Service Routine (ISR)


void pinChange ()
{
// handle pin change here
} // end of pinChange

void setup ()
{
attachInterrupt (0, pinChange, CHANGE); // attach interrupt handler
} // end of setup

In this case the attachInterrupt function adds the function pinChange to an internal
table, and in addition configures the appropriate interrupt flags in the processor.

Configuring the processor to handle an interrupt

The next step, once you have an ISR, is to tell the processor that you want this particular
condition to raise an interrupt.

As an example, for External Interrupt 0 (the D2 interrupt) you could do something like
this:

EICRA &= ~3; // clear existing flags


EICRA |= 2; // set wanted flags (falling level interrupt)
EIMSK |= 1; // enable it

More readable would be to use the defined names, like this:

EICRA &= ~(bit(ISC00) | bit (ISC01)); // clear existing flags


EICRA |= bit (ISC01); // set wanted flags (falling level interrupt)
EIMSK |= bit (INT0); // enable it

EICRA (External Interrupt Control Register A) would be set according to this table from
the Atmega328 datasheet (page 71).

That defines the exact type of interrupt you want:

0: The low level of INT0 generates an interrupt request (LOW interrupt).


1: Any logical change on INT0 generates an interrupt request (CHANGE interrupt).
2: The falling edge of INT0 generates an interrupt request (FALLING interrupt).
3: The rising edge of INT0 generates an interrupt request (RISING interrupt).

EIMSK (External Interrupt Mask Register) actually enables the interrupt.

Fortunately you don't need to remember those numbers because attachInterrupt does
that for you. However that is what is actually happening, and for other interrupts you
may have to "manually" set interrupt flags.

Can ISRs be interrupted?

In short, no, not unless you want them to be.

When an ISR is entered, interrupts are disabled. Naturally they must have been enabled
in the first place, otherwise the ISR would not be entered. However to avoid having an
ISR itself be interrupted, the processor turns interrupts off.

When an ISR exits, then interrupts are enabled again. The compiler also generates code
inside an ISR to save registers and status flags, so that whatever you were doing when
the interrupt occurred will not be affected.

However you can turn interrupts on inside an ISR if you absolutely must, eg.

// Interrupt Service Routine (ISR)


void pinChange ()
{
// handle pin change here
interrupts (); // allow more interrupts

} // end of pinChange
Normally you would need a pretty good reason to do this, as another interrupt now
could result in a recursive call to pinChange, with quite possibly undesirable results.

How long does it take to execute an ISR?

According to the datasheet, the minimal amount of time to service an interrupt is 4 clock
cycles (to push the current program counter onto the stack) followed by the code now
executing at the interrupt vector location. This normally contains a jump to where the
interrupt routine really is, which is another 3 cycles.
Then an ISR routine (declared with the ISR define) does something like this:

// SPI interrupt routine


ISR (SPI_STC_vect)
118: 1f 92 push r1 (2) // save R1 - the "zero" register
11a: 0f 92 push r0 (2) // save register R0
11c: 0f b6 in r0, 0x3f (1) // get SREG (status register)
11e: 0f 92 push r0 (2) // save SREG
120: 11 24 eor r1, r1 (1) // ensure R1 is zero
122: 8f 93 push r24 (2)
124: 9f 93 push r25 (2)
126: ef 93 push r30 (2)
128: ff 93 push r31 (2)
{

That's another 16 cycles (the cycles are in brackets). So from the moment the interrupt
occurs, to the first line of code being executed, would be 16 + 7 cycles (23 cycles), at 62.5
nS per clock cycle, that would be 1.4375 S. That's assuming a 16 MHz clock.

Then to leave the ISR we have this code:

} // end of interrupt routine SPI_STC_vect


152: ff 91 pop r31 (2)
154: ef 91 pop r30 (2)
156: 9f 91 pop r25 (2)
158: 8f 91 pop r24 (2)
15a: 0f 90 pop r0 (2) // get old SREG
15c: 0f be out 0x3f, r0 (1) // restore SREG
15e: 0f 90 pop r0 (2) // now put old R0 register back
160: 1f 90 pop r1 (2) // restore old value of R1
162: 18 95 reti (4) // return from interrupt, turn interrupts back on

That's another 19 clock cycles (1.1875 S). So in total, an ISR using the ISR define will
take you 2.625 S to execute, plus whatever the code itself does.

However the external interrupts (where you use attachInterrupt) do a bit more, as
follows:

SIGNAL(INT0_vect) {
182: 1f 92 push r1 (2)
184: 0f 92 push r0 (2)
186: 0f b6 in r0, 0x3f (1)
188: 0f 92 push r0 (2)
18a: 11 24 eor r1, r1 (1)
18c: 2f 93 push r18 (2)
18e: 3f 93 push r19 (2)
190: 4f 93 push r20 (2)
192: 5f 93 push r21 (2)
194: 6f 93 push r22 (2)
196: 7f 93 push r23 (2)
198: 8f 93 push r24 (2)
19a: 9f 93 push r25 (2)
19c: af 93 push r26 (2)
19e: bf 93 push r27 (2)
1a0: ef 93 push r30 (2)
1a2: ff 93 push r31 (2)
if(intFunc[EXTERNAL_INT_0])
1a4: 80 91 00 01 lds r24, 0x0100 (2)
1a8: 90 91 01 01 lds r25, 0x0101 (2)
1ac: 89 2b or r24, r25 (2)
1ae: 29 f0 breq .+10 (2)
intFunc[EXTERNAL_INT_0]();
1b0: e0 91 00 01 lds r30, 0x0100 (2)
1b4: f0 91 01 01 lds r31, 0x0101 (2)
1b8: 09 95 icall (3)
}
1ba: ff 91 pop r31 (2)
1bc: ef 91 pop r30 (2)
1be: bf 91 pop r27 (2)
1c0: af 91 pop r26 (2)
1c2: 9f 91 pop r25 (2)
1c4: 8f 91 pop r24 (2)
1c6: 7f 91 pop r23 (2)
1c8: 6f 91 pop r22 (2)
1ca: 5f 91 pop r21 (2)
1cc: 4f 91 pop r20 (2)
1ce: 3f 91 pop r19 (2)
1d0: 2f 91 pop r18 (2)
1d2: 0f 90 pop r0 (2)
1d4: 0f be out 0x3f, r0 (1)
1d6: 0f 90 pop r0 (2)
1d8: 1f 90 pop r1 (2)
1da: 18 95 reti (4)

I count 82 cycles there (5.125 S in total at 16 MHz) as overhead plus whatever is


actually done in the supplied interrupt routine. That is, 2.9375 S before entering your
interrupt handler, and another 2.1875 S after it returns.

How long before the processor starts entering an ISR?

This various somewhat. The figures quoted above are the ideal ones where the interrupt
is immediately processed. A few factors may delay that:

If the processor is asleep, there are designated "wake-up" times, which could be
quite a few milliseconds, while the clock is spooled back up to speed. This time
would depend on fuse settings, and how deep the sleep is.

If an interrupt service routine is already executing, then further interrupts cannot


be entered until it either finishes, or enables interrupts itself. This is why you
should keep each interrupt service routine short, as every microsecond you spend
in one, you are potentially delaying the execution of another one.

Some code turns interrupts off. For example, calling millis() briefly turns interrupts
off. Therefore the time for an interrupt to be serviced would be extended by the
length of time interrupts were turned off.

Interrupts can only be serviced at the end of an instruction, so if a particular


instruction takes three clock cycles, and has just started, then the interrupt will be
delayed at least a couple of clock cycles.

An event that turns interrupts back on (eg. returning from an interrupt service
routine) is guaranteed to execute at least one more instruction. So even if an ISR
ends, and your interrupt is pending, it still has to wait for one more instruction
before it is serviced.

Since interrupts have a priority, a higher-priority interrupt might be serviced


before the interrupt you are interested in.

Performance considerations

Interrupts can increase performance in many situations because you can get on with the
"main work" of your program without having to constantly be testing to see if switches
have been pressed. Having said that, the overhead of servicing an interrupt, as discussed
above, would actually be more than doing a "tight loop" polling a single input port. If you
absolutely need to respond to an event within, say, a microsecond, then an interrupt
would be too slow. In that case you might disable interrupts (eg. timers) and just loop
looking for the pin to change.

How are interrupts queued?

There are two sorts of interrupts:

Some set a flag and they are handled in priority order, even if the event that
caused them has stopped. For example, a rising, falling, or changing level interrupt
on pin D2.

Others are only tested if they are happening "right now". For example, a low-level
interrupt on pin D2.

The ones that set a flag could be regarded as being queued, as the interrupt flag remains
set until such time as the interrupt routine is entered, at which time the processor clears
the flag. Of course, since there is only one flag, if the same interrupt condition occurs
again before the first one is processed, it won't be serviced twice.

Something to be aware of is that these flags can be set before you attach the interrupt
handler. For example, it is possible for a rising or falling level interrupt on pin D2 to be
"flagged", and then as soon as you do an attachInterrupt the interrupt immediately fires,
even if the event occurred an hour ago. To avoid this you can manually clear the flag. For
example:

EIFR = 1; // clear flag for interrupt 0


EIFR = 2; // clear flag for interrupt 1

Or, for readability:

EIFR = bit (INTF0); // clear flag for interrupt 0


EIFR = bit (INTF1); // clear flag for interrupt 1
However the "low level" interrupts are continuously checked, so if you are not careful
they will keep firing, even after the interrupt has been called. That is, the ISR will exit,
and then the interrupt will immediately fire again. To avoid this, you should do a
detachInterrupt immediately after you know that the interrupt fired. An example of this
is going into sleep mode:

#include <avr/sleep.h>

// interrupt service routine in sleep mode


void wake ()
{
sleep_disable (); // first thing after waking from sleep:
} // end of wake

void sleepNow ()
{
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
sleep_enable (); // enables the sleep bit in the mcucr register
attachInterrupt (0, wake, LOW); // wake up on low level
sleep_mode (); // here the device is actually put to sleep!!
detachInterrupt (0); // stop LOW interrupt
} // end of sleepNow

Note that the interrupt is detached immediately after we wake up. However we should
be cautious about putting the detachInterrupt actually inside the "wake" ISR, because it
is possible the interrupt might fire between attaching the interrupt and going to sleep, in
which case we would never wake up.

Correction:

The improved version below solves this problem by disabling interrupts before doing the
attachInterrupt call. Since you are guaranteed that one instruction will be executed after
re-enabling interrupts, we are sure that the sleep_cpu call will be done before the
interrupt occurs.

#include <avr/sleep.h>

// interrupt service routine in sleep mode


void wake ()
{
sleep_disable (); // first thing after waking from sleep:
detachInterrupt (0); // stop LOW interrupt
} // end of wake

void sleepNow ()
{
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
noInterrupts (); // make sure we don't get interrupted before we sleep
sleep_enable (); // enables the sleep bit in the mcucr register
attachInterrupt (0, wake, LOW); // wake up on low level
interrupts (); // interrupts allowed now, next instruction WILL be executed
sleep_cpu (); // here the device is put to sleep
} // end of sleepNow

These examples illustrates how you can save power with a LOW interrupt, because the
LOW interrupt is activated even if the processor is asleep (whereas the other ones -
RISING, FALLING, CHANGE - are not). (Amended 15 Dec 2013 : We now believe all four
external interrupt types will wake the processor).

Hints for writing ISRs

In brief, keep them short! While an ISR is executing other interrupts cannot be
processed. So you could easily miss button presses, or incoming serial communications, if
you try to do too much. In particular, you should not try to do debugging "prints" inside
an ISR. The time taken to do those is likely to cause more problems than they solve.

A reasonable thing to do is set a single-byte flag, and then test that flag in the main loop
function. Or, store an incoming byte from a serial port into a buffer. The inbuilt timer
interrupts keep track of elapsed time by firing every time the internal timer overflows,
and thus you can work out elapsed time by knowing how many times the timer
overflowed.

Remember, inside an ISR interrupts are disabled. Thus hoping that the time returned by
millis() function calls will change, will lead to disappointment. It is valid to obtain the
time that way, just be aware that the timer is not incrementing. And if you spend too
long in the ISR then the timer may miss an overflow event, leading to the time returned
by millis() becoming incorrect.

A test shows that, on a 16 MHz Atmega328 processor, a call to micros() takes 3.5625 S.
A call to millis() takes 1.9375 S. Recording (saving) the current timer value is a
reasonable thing to do in an ISR. Finding the elapsed milliseconds is faster than the
elapsed microseconds (the millisecond count is just retrieved from a variable). However
the microsecond count is obtained by adding the current value of the Timer 0 timer
(which will keep incrementing) to a saved "Timer 0 overflow count".

Warning: Since interrupts are disabled inside an ISR, and since the latest version of the
Arduino IDE uses interrupts for Serial reading and writing, and also for incrementing the
counter used by "millis" and "delay" you should not attempt to use those functions
inside an ISR. To put it another way:

Don't attempt to delay, eg: delay (100);


You can get the time from a call to millis, however it won't increment, so don't
attempt to delay by waiting for it to increase.
Don't do serial prints (eg. Serial.println ("ISR entered"); )
Don't try to do serial reading.

Pin change interrupts

There are two ways you can detect external events on pins. The first is the special
"external interrupt" pins, D2 and D3. These general discrete interrupt events, one per
pin. You can get to those by using attachInterrupt for each pin. You can specify a rising,
falling, changing or low-level condition for the interrupt.

However there are also "pin change" interrupts for all pins (on the Atmega328, not
necessarily all pins on other processors). These act on groups of pins (D0 to D7, D8 to
D13, and A0 to A5). They are also lower priority than the external event interrupts. You
could make an interrupt handler to handle changes on pins D8 to D13 like this:

ISR (PCINT0_vect)
{
// one of pins D8 to D13 has changed
}

Clearly extra code is needed to work out exactly which pin changed (eg. comparing it to a
"before" value).

Pin change interrupts each have an associated "mask" byte in the processor, so you could
actually configure them to only react to (say) D8, D10 and D12, rather than a change to
D8 to D13. However you still then need to work out which of those changed.

Example of watchdog timer interrupt


#include <avr/sleep.h>
#include <avr/wdt.h>

#define LED 13

// interrupt service routine for when button pressed


void wake ()
{
wdt_disable(); // disable watchdog
} // end of wake

// watchdog interrupt
ISR (WDT_vect)
{
wake ();
} // end of WDT_vect

void myWatchdogEnable (const byte interval)


{
noInterrupts (); // timed sequence below

MCUSR = 0; // reset various flags


WDTCSR |= 0b00011000; // see docs, set WDCE, WDE
WDTCSR = 0b01000000 | interval; // set WDIE, and appropriate delay
wdt_reset();

byte adcsra_save = ADCSRA;


ADCSRA = 0; // disable ADC
power_all_disable (); // turn off all modules
set_sleep_mode (SLEEP_MODE_PWR_DOWN); // sleep mode is set here
sleep_enable();
attachInterrupt (0, wake, LOW); // allow grounding pin 2 to wake us
interrupts ();
sleep_cpu (); // now goes to Sleep and waits for the interrupt
detachInterrupt (0); // stop LOW interrupt

ADCSRA = adcsra_save; // stop power reduction


power_all_enable (); // turn on all modules
} // end of myWatchdogEnable
void setup ()
{
digitalWrite (2, HIGH); // pull-up on button
} // end of setup

void loop()
{
pinMode (LED, OUTPUT);
digitalWrite (LED, HIGH);
delay (5000);
digitalWrite (LED, LOW);
delay (5000);

// sleep bit patterns:


// 1 second: 0b000110
// 2 seconds: 0b000111
// 4 seconds: 0b100000
// 8 seconds: 0b100001

// sleep for 8 seconds


myWatchdogEnable (0b100001); // 8 seconds

} // end of loop

The above code, running on a "bare bones" board (that is, without voltage regulator, USB
interface etc.) uses the following:

With LED lit: 19.5 mA


Awake, with LED off: 16.5 mA
Asleep: 6 uA (0.006 mA)

You can see that using the watchdog timer combined with sleep mode, you can save a
considerable amount of power during times when the processor might not be needed.

It also illustrates how you can recover from sleep in two different ways. One is with a
button press (ie. you ground pin D2), the other is waking up periodically (every 8
seconds), although you could make it every 1, 2 4, or 8 seconds (or even shorter if you
consult the data sheet).
Warning: after being woken the processor might need a short time to stabilize its clock.
For example, you may see "garbage" on a serial comms port while things are
synchronizing. If this is a problem you may want to build in a short delay after being
woken.

Note re brownout detection: The figures measured above are with brownout detection
disabled. To generate a reference voltage for the brownout detection takes a bit of
current. With it enabled, the sleep mode uses closer to 70 uA (not 6 uA). One way of
turning off the brownout detection is to use avrdude from the command line, like this:

avrdude -c usbtiny -p m328p -U efuse:w:0x07:m

That sets the "efuse" (extended fuse) to be 7, which disables brownout detection. This
example assumes you are using the USBtinyISP programmer board.

You are probably using interrupts anyway ...

A "normal" Arduino environment already is using interrupts, even if you don't personally
attempt to. The millis() and micros() function calls make use of the "timer overflow"
feature. One of the internal timers (timer 0) is set up to interrupt roughly 1000 times a
second, and increment an internal counter which effectively becomes the millis()
counter. There is a bit more to it than that, as adjustment is made for the exact clock
speed.

Also the hardware serial library uses interrupts to handle incoming serial data (and in the
more recent library versions, outgoing serial data as well). This is very useful as your
program can be doing other things while the interrupts are firing, and filling up an
internal buffer. Then when you check Serial.available() you can find out what, if anything,
has been placed in that buffer.

Executing the next instruction after enabling interrupts

After a bit of discussion and research on the Arduino forum, we have clarified exactly
what happens after you enable interrupts. There are three main ways I can think of that
you can enable interrupts, which were previously not enabled:

sei (); // set interrupt enable flag


SREG |= 0x80; // set the high-order bit in the status register
reti ; // assembler instruction "return from interrupt"
In all cases, the processor guarantees that the next instruction after interrupts are
enabled (if they were previously disabled) will always be executed, even if an interrupt
event is pending. (By "next" I mean the next one in program sequence, not necessarily
the one physically following. For example, a RETI instruction jumps back to where the
interrupt occurred, and then executes one more instruction).

This lets you write code like this:

sei ();
sleep_cpu ();
If not for this guarantee, the interrupt might occur before the processor slept, and then
it might never be awoken.

Empty interrupts

If you merely want an interrupt to wake the processor, but not do anything in particular,
you can use the EMPTY_INTERRUPT define, eg.

EMPTY_INTERRUPT (PCINT1_vect);
This simply generates a "reti" (return from interrupt) instruction. Since it doesn't try to
save or restore registers this would be the fastest way to get an interrupt to wake it up.

More information about interrupts, timers, etc. can be obtained from the data sheet for
the processor.

http://atmel.com/dyn/resources/prod_documents/8271S.pdf
Example code of a pump timer
This was posted on the Arduino forum (by me) of an example of how to make a pump
timer. The hardware consisted of a switch (the on/cancel switch) connected to D2 and a
"pump time" rotary switch (not a rotary encoder) connected to pins 3 to 11. For
example, if the switch was in the 3rd position you would get the pump running for 10
minutes.

The pump was connected to pin 13 via a transistor/relay.

// Pump timer
// Author: Nick Gammon
// Date: 7th January 2012
// Released into the public domain.

#include <avr/sleep.h>

const int pumpPin = 13; // output pin for the pump and solenoid (goes to the relay)
const int buttonPin = 2; // input pin (for a pushbutton switch)
const int firstSwitch = 3; // first switch pin for time rotary button
const int lastSwitch = 11; // last switch pin
const int debounceTime = 20; // debounce in milliseconds
const unsigned long delayTime [] = { 2, 5, 10, 15, 20, 30, 45, 46, 120}; // Pump run times
in minutes
unsigned long startPumpTime = 0; // when pump started
unsigned long pumpTime; // how long to run pump
volatile boolean buttonPressed; // set when button pressed

// interrupt service routine in sleep mode


void wake ()
{
sleep_disable (); // first thing after waking from sleep:
} // end of wake

// interrupt service routine when awake and button pressed


void buttonDown ()
{
buttonPressed = true;
} // end of buttonDown
void sleepNow ()
{
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
sleep_enable (); // enables the sleep bit in the mcucr register
attachInterrupt (0, wake, LOW);
sleep_mode (); // here the device is actually put to sleep!!
detachInterrupt (0); // stop LOW interrupt
} // end of sleepNow

void deBounce ()
{
unsigned long now = millis ();
do
{
// on bounce, reset time-out
if (digitalRead (buttonPin) == LOW)
now = millis ();
}
while (digitalRead (buttonPin) == LOW ||
(millis () - now) <= debounceTime);

} // end of deBounce

void setup()
{
pinMode(pumpPin, OUTPUT);
digitalWrite (buttonPin, HIGH); // pull-up on button
for (int i = firstSwitch; i <= lastSwitch; i++)
digitalWrite (i, HIGH); // pull-up on switch
} // end of setup

void loop ()
{

// if pump is running, see if time to turn it off


if (digitalRead (pumpPin) == HIGH)
{
if ((millis () - startPumpTime) >= pumpTime || buttonPressed)
{
digitalWrite (pumpPin, LOW);
deBounce ();
buttonPressed = false;
}
return; // not time to sleep yet
} // end of pump running

// ------ here if pump not running -----

// pump not running? sleep then


sleepNow ();

// pump is not running and we woke up, work out how long to run it

deBounce ();
pumpTime = 0;

EIFR = 1; // cancel any existing falling interrupt (interrupt 0)


attachInterrupt (0, buttonDown, FALLING); // ready for button press

for (int i = firstSwitch; i <= lastSwitch; i++)


if (digitalRead (i) == LOW)
pumpTime = delayTime [i - firstSwitch];

if (pumpTime == 0)
return; // no time selected

// start pump
startPumpTime = millis ();
digitalWrite (pumpPin, HIGH);

pumpTime *= 60000UL; // convert minutes to milliseconds

// pumpTime = 5000; // FOR TESTING - 5 seconds

} // end of loop

Of interest is the deBounce function - that handles the inevitable "bounces" of switch
contacts as you open or close them. Without some sort of debouncing handler you might
interpret a single button press as 20 presses, making it very hard to actually do anything.
Above is an image of a switch bouncing, captured on the logic analyzer. You can see from
the above, that a simple keypress might result in a dozen or so transitions. On the image
each bounce is around 5 mS apart. So we really need to wait for a longer interval to
elapse, in which the switch doesn't open/close again.

The debounce handler above waits for 20 milliseconds for the switch to stop bouncing,
and if the switch closes again, resets the time interval so it waits another 20 milliseconds.
This seemed to work quite well.

The code also demonstrates putting the processor to sleep if it isn't needed (eg. at
midnight) so it uses less power. It also shows how the "low" interrupt can be used to
wake it up, and the falling interrupt to notice if the switch is pressed while the pump is
running (eg., you have watered your plants enough already).
Timer interrupts

The "normal" Arduino IDE uses timer 0 to provide a "clock" being a number that is
incremented, and adjusted, to give you a count per millisecond. You can read that by
doing something like this:

unsigned long nowMs = millis ();

You can also find a more accurate timer value by using micros (), which takes the current
value from the millis counter, and adds in the current reading from timer 0 (thus
correcting for "right now"). eg.

unsigned long nowUs = micros ();

However you can make your own interrupts, say using Timer 1, like this:

const byte LED = 13;

ISR(TIMER1_COMPA_vect)
{
static boolean state = false;
state = !state; // toggle
digitalWrite (LED, state ? HIGH : LOW);
}

void setup() {
pinMode (LED, OUTPUT);

// set up Timer 1
TCCR1A = 0; // normal operation
TCCR1B = bit(WGM12) | bit(CS10); // CTC, no pre-scaling
OCR1A = 999; // compare A register value (1000 * clock speed)
TIMSK1 = bit (OCIE1A); // interrupt on Compare A Match
} // end of setup

void loop() { }
This uses CTC (Clear Timer on Compare), so it counts up to the specified value, clears the
timer, and starts again. This toggles pin D13 faster than you can see (once every 62.5 S).
(It turns on every second toggle, that is every 125 S, giving a frequency of 1/0.000125 =
8 KHz).

Note: The counter is zero-relative. So if the counter is 1, then it actually counts two times
the clock_speed/pre-scaler (0 and 1). So for an interval of 1000 slower than the internal
clock, we need to set the counter to 999.

If you change the prescaler it toggles every 64 mS, slow enough for you to see it flashing.
(That is, the LED lights every 128 mS, being 1/0.128 = 7.8125 Hz).

const byte LED = 13;

ISR(TIMER1_COMPA_vect)
{
static boolean state = false;
state = !state; // toggle
digitalWrite (LED, state ? HIGH : LOW);
}

void setup() {
pinMode (LED, OUTPUT);

// set up Timer 1
TCCR1A = 0; // normal operation
TCCR1B = bit(WGM12) | bit(CS10) | bit (CS12); // CTC, scale to clock / 1024
OCR1A = 999; // compare A register value (1000 * clock speed / 1024)
TIMSK1 = bit (OCIE1A); // interrupt on Compare A Match
} // end of setup

void loop() { }

And even more simply, you can output a timer result without even using interrupts:

const byte LED = 9;


void setup() {
pinMode (LED, OUTPUT);

// set up Timer 1
TCCR1A = bit (COM1A0); // toggle OC1A on Compare Match
TCCR1B = bit(WGM12) | bit(CS10) | bit (CS12); // CTC, scale to clock / 1024
OCR1A = 4999; // compare A register value (5000 * clock speed / 1024)
} // end of setup

void loop() { }

Plug an LED (and resistor in series, say 470 ohms) between D9 and Gnd, and you will see
it toggle every 320 mS. (1/(16000000 / 1024) * 5000).

More information on timers here:

http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=50106
Ignition timing timing with timers and interrupts

Below is another example of interrupts and timers from the Arduino forum. The basic
problem was to turn something on when an interrupt occurred (eg. on pin D2) but after a
delay. The code below uses an interrupt to start the process, sets a timer for 0.5 mS (as
an initial delay). Then when that timer fires, the spark is turned on for a different interval
(2 mS) and then when that time is up, the spark is turned off, and the process resumes.

It's an interesting example of pin interrupts, timers and timer interrupts.

// Timer with an ISR example


// Author: Nick Gammon
// Date: 13th January 2012
// Modified: 19 October 2014

#include <digitalWriteFast.h>

const byte FIRE_SENSOR = 2; // note this is interrupt 0


const byte SPARKPLUG = 9;

volatile unsigned int sparkDelayTime = 500; // microseconds


volatile unsigned int sparkOnTime = 2000; // microseconds

// allow for time taken to enter ISR (determine empirically)


const unsigned int isrDelayFactor = 4; // microseconds

// is spark currently on?


volatile boolean sparkOn;

void activateInterrupt0 ()
{
EICRA &= ~(bit(ISC00) | bit (ISC01)); // clear existing flags
EICRA |= bit (ISC01); // set wanted flags (falling level interrupt)
EIFR = bit (INTF0); // clear flag for interrupt 0
EIMSK |= bit (INT0); // enable it
} // end of activateInterrupt0

void deactivateInterrupt0 ()
{
EIMSK &= ~bit (INT0); // disable it
} // end of deactivateInterrupt0

// interrupt for when time to turn spark on then off again


ISR (TIMER1_COMPA_vect)
{

// if currently on, turn off


if (sparkOn)
{
digitalWriteFast (SPARKPLUG, LOW); // spark off
TCCR1B = 0; // stop timer
TIMSK1 = 0; // cancel timer interrupt
activateInterrupt0 (); // re-instate interrupts for firing time
}
else
// hold-off time must be up
{
digitalWriteFast (SPARKPLUG, HIGH); // spark on
TCCR1B = 0; // stop timer
TCNT1 = 0; // count back to zero
TCCR1B = bit(WGM12) | bit(CS11); // CTC, scale to clock / 8
// time before timer fires (zero relative)
// multiply by two because we are on a prescaler of 8
OCR1A = (sparkOnTime * 2) - (isrDelayFactor * 2) - 1;
}

sparkOn = !sparkOn; // toggle

} // end of TIMER1_COMPA_vect

// ISR for when to fire


ISR (INT0_vect)
{
sparkOn = false; // make sure flag off just in case

// set up Timer 1
TCCR1A = 0; // normal mode
TCNT1 = 0; // count back to zero
TCCR1B = bit(WGM12) | bit(CS11); // CTC, scale to clock / 8
// time before timer fires - zero relative
// multiply by two because we are on a prescaler of 8
OCR1A = (sparkDelayTime * 2) - (isrDelayFactor * 2) - 1;
TIMSK1 = bit (OCIE1A); // interrupt on Compare A Match

deactivateInterrupt0 (); // no more interrupts yet


} // end of ISR (INT0_vect)

void setup()
{
TCCR1A = 0; // normal mode
TCCR1B = 0; // stop timer
TIMSK1 = 0; // cancel timer interrupt

pinMode (SPARKPLUG, OUTPUT);


pinMode (FIRE_SENSOR, INPUT_PULLUP);

activateInterrupt0 ();
} // end of setup

void loop()
{
// read sensors, compute time to fire spark

if (false) // if we need to change the time, insert condition here ...


{
noInterrupts (); // atomic change of the time amount
sparkDelayTime = 500; // delay before spark in microseconds
sparkOnTime = 2000; // spark on time in microseconds
interrupts ();
}
} // end of loop

The graphic shows (ignore the switch bounce) that after the switch is closed there is a
delay of 500 S (between the green flags) and then a delay of 1999 S while the spark is
"on".
[EDIT] Changes made on 19th October 2014.

The sketch uses the digitalwritefast library to do quick writes to the spark pin. It also uses
the ISR (INT0_vect) function rather than attachInterrupt, because attachInterrupt takes
longer to run.

https://code.google.com/p/digitalwritefast/

There is a tweaking figure of 4 S (isrDelayFactor) which you can determine empirically


(by measuring) to compensate for the few microseconds that it takes to enter the ISR. By
subtracting that from the required timer interval, the timing is more accurate.
Camera shutter speed example
This example detects how long a camera shutter is open by using a change interrupt. At
the first transition it gets the time, and at the second one it gets the new time.

Then the main loop shows the difference.

Of course this general concept could be applied to anything where you want to time a
brief pulse. Tested down to a 50 S pulse, but it could probably go a bit shorter, as it
takes around 5 S to enter and leave an ISR.

// Camera shutter speed timer


// Author: Nick Gammon
// Date: 15th January 2012

volatile boolean started;


volatile unsigned long startTime;
volatile unsigned long endTime;

// interrupt service routine


void shutter ()
{
if (started)
endTime = micros ();
else
startTime = micros ();

started = !started;

} // end of shutter

void setup ()
{
Serial.begin (115200);
Serial.println ("Shutter test ...");
attachInterrupt (0, shutter, CHANGE);
} // end of setup
void loop ()
{

if (endTime)
{
Serial.print ("Shutter open for ");
Serial.print (endTime - startTime);
Serial.println (" microseconds.");
endTime = 0;
}

} // end of loop
Robot race timer example

Another example uses a laser beam to shine on a LDR (light dependent resistor). The
laser is so powerful this simple circuit seemed to work OK:

The sketch below times intervals between RISING interrupts (the resistance goes up
when less light shines on the LDR):

// Robot race timer


// Author: Nick Gammon
// Date: 1st February 2012

unsigned long lastTriggerTime;


volatile unsigned long triggerTime;
volatile boolean triggered;

void isr ()
{
// wait until we noticed last one
if (triggered)
return;
triggerTime = micros ();
triggered = true;
} // end of isr

void setup()
{
digitalWrite (2, HIGH); // pull-up
attachInterrupt(0, isr, RISING);
Serial.begin (115200);
Serial.println ("Started timing ...");
} // end of setup

void loop()
{
if (!triggered)
return;

unsigned long elapsed = triggerTime - lastTriggerTime;

if (elapsed < 1000000L)


{
triggered = false;
return; // ignore if less than a second
}

lastTriggerTime = triggerTime;
triggered = false; // re-arm for next time

Serial.print ("Took: ");


Serial.print (elapsed);
Serial.print (" microseconds. ");

unsigned long minutes, seconds, ms;

minutes = elapsed / (1000000L * 60);


elapsed -= minutes * (1000000L * 60);

seconds = elapsed / 1000000L;


elapsed -= seconds * 1000000L;
ms = elapsed / 1000;
elapsed -= ms * 1000;

Serial.print (minutes);
Serial.print ("m ");
Serial.print (seconds);
Serial.print ("s ");
Serial.print (ms);
Serial.println ("ms.");
} // end of loop

Example output:

Started timing ...


Took: 3375112 microseconds. 0m 3s 375ms.
Took: 1577852 microseconds. 0m 1s 577ms.
Took: 1267868 microseconds. 0m 1s 267ms.
Took: 1293936 microseconds. 0m 1s 293ms.
Took: 2013680 microseconds. 0m 2s 13ms.
Took: 3785196 microseconds. 0m 3s 785ms.
Took: 12562240 microseconds. 0m 12s 562ms.

I shone a cheap 1 mW laser pointer onto the LDR. The resistance is low with the light on
it (I read about 1.9V on pin D2) which registers as a LOW input. When you break the
beam the resistance is high and the pin gets about 3V (being a HIGH). Thus the beam is
broken on a RISING interrupt.

The code times the intervals between rising interrupts and reports them to the serial
monitor. Of course you could use a LCD or something. There is a test for short intervals
(which might be the light passing through a part of the robot) so that if the time is less
than a second it doesn't start timing again.
Read the Analog-to-Digital converter asynchronously

The code example below demonstrates reading the ADC converter (pin A0 in this case)
whilst doing something else at the same time.

Each ADC conversion takes around 104 uS, and since that would be 1664 clock cycles
(something like 832 instructions) it would be useful to do something (like process the
previous reading) while you are doing it.

const byte adcPin = 0;


volatile int adcReading;
volatile boolean adcDone;
boolean adcStarted;

void setup ()
{
Serial.begin (115200);
// set the analog reference (high two bits of ADMUX) and select the
// channel (low 4 bits). this also sets ADLAR (left-adjust result)
// to 0 (the default).
ADMUX = bit (REFS0) | (adcPin & 0x07);

} // end of setup

// ADC complete ISR


ISR (ADC_vect)
{
byte low, high;

// we have to read ADCL first; doing so locks both ADCL


// and ADCH until ADCH is read. reading ADCL second would
// cause the results of each conversion to be discarded,
// as ADCL and ADCH would be locked when it completed.
low = ADCL;
high = ADCH;

adcReading = (high << 8) | low;


adcDone = true;
} // end of ADC_vect

void loop ()
{
// if last reading finished, process it
if (adcDone)
{
adcStarted = false;

// do something with the reading, for example, print it


Serial.println (adcReading);
delay (500);

adcDone = false;
}

// if we aren't taking a reading, start a new one


if (!adcStarted)
{
adcStarted = true;
// start the conversion
ADCSRA |= bit (ADSC) | bit (ADIE);
}

// do other stuff here

} // end of loop

Once the reading has started you continue to execute the main loop, checking to see if it
completed in the ISR. Once it does you can process it, print it, or whatever.
Sleep during ADC conversion

Another approach is to go to sleep during the reading. In this case, of course, you cannot
do other things, but being asleep reduces digital noise inside the chip, leading to a better
analog conversion. The code below is similar to the above, but adds in a
"SLEEP_MODE_ADC" sleep for a better conversion.

// Example of taking ADC reading while asleep


// Author: Nick Gammon
// Date: 23 June 2012

#include <avr/sleep.h>

const byte adcPin = 0;


volatile int adcReading;
volatile boolean adcDone;
boolean adcStarted;

void setup ()
{
Serial.begin (115200);
// set the analog reference (high two bits of ADMUX) and select the
// channel (low 4 bits). this also sets ADLAR (left-adjust result)
// to 0 (the default).
ADMUX = bit (REFS0) | (adcPin & 0x07);

} // end of setup

// ADC complete ISR


ISR (ADC_vect)
{
byte low, high;

// we have to read ADCL first; doing so locks both ADCL


// and ADCH until ADCH is read. reading ADCL second would
// cause the results of each conversion to be discarded,
// as ADCL and ADCH would be locked when it completed.
low = ADCL;
high = ADCH;
adcReading = (high << 8) | low;
adcDone = true;
} // end of ADC_vect

void loop ()
{
// if last reading finished, process it
if (adcDone)
{
adcStarted = false;

// do something with the reading, for example, print it


Serial.println (adcReading);
delay (500);

adcDone = false;
}

// if we aren't taking a reading, start a new one


if (!adcStarted)
{
adcStarted = true;
// start the conversion
ADCSRA |= bit (ADSC) | bit (ADIE);

set_sleep_mode (SLEEP_MODE_ADC); // sleep during sample


sleep_mode ();

// do other stuff here

} // end of loop

Also consider putting a 0.1 uF capacitor between the AREF and GND pins (adjacent to
each other on the Uno board) to reduce noise in the analog reference voltage.
Pin Change Interrupts
Pin change interrupts let you detect changes to any of the Arduino pins. However they
are a bit more fiddly to use than the external interrupts because they are grouped into
batches. So if the interrupt fires you have to work out in your own code exactly which pin
caused the interrupt.

Example code:

ISR (PCINT0_vect)
{
// handle pin change interrupt for D8 to D13 here
} // end of PCINT0_vect

ISR (PCINT1_vect)
{
// handle pin change interrupt for A0 to A5 here
} // end of PCINT1_vect

ISR (PCINT2_vect)
{
// handle pin change interrupt for D0 to D7 here
} // end of PCINT2_vect

void setup ()
{
// pin change interrupt (example for D9)
PCMSK0 |= bit (PCINT1); // want pin 9
PCIFR |= bit (PCIF0); // clear any outstanding interrupts
PCICR |= bit (PCIE0); // enable pin change interrupts for D8 to D13
}

To handle a pin change interrupt you need to:

Specify which pin in the group. This is the PCMSKn variable (where n is 0, 1 or 2
from the table below). You can have interrupts on more than one pin.
Enable the appropriate group of interrupts (0, 1 or 2)
Supply an interrupt handler as shown above
Table of pins -> pin change names / masks
D0 PCINT16 (PCMSK2 / PCIF2 / PCIE2)
D1 PCINT17 (PCMSK2 / PCIF2 / PCIE2)
D2 PCINT18 (PCMSK2 / PCIF2 / PCIE2)
D3 PCINT19 (PCMSK2 / PCIF2 / PCIE2)
D4 PCINT20 (PCMSK2 / PCIF2 / PCIE2)
D5 PCINT21 (PCMSK2 / PCIF2 / PCIE2)
D6 PCINT22 (PCMSK2 / PCIF2 / PCIE2)
D7 PCINT23 (PCMSK2 / PCIF2 / PCIE2)
D8 PCINT0 (PCMSK0 / PCIF0 / PCIE0)
D9 PCINT1 (PCMSK0 / PCIF0 / PCIE0)
D10 PCINT2 (PCMSK0 / PCIF0 / PCIE0)
D11 PCINT3 (PCMSK0 / PCIF0 / PCIE0)
D12 PCINT4 (PCMSK0 / PCIF0 / PCIE0)
D13 PCINT5 (PCMSK0 / PCIF0 / PCIE0)
A0 PCINT8 (PCMSK1 / PCIF1 / PCIE1)
A1 PCINT9 (PCMSK1 / PCIF1 / PCIE1)
A2 PCINT10 (PCMSK1 / PCIF1 / PCIE1)
A3 PCINT11 (PCMSK1 / PCIF1 / PCIE1)
A4 PCINT12 (PCMSK1 / PCIF1 / PCIE1)
A5 PCINT13 (PCMSK1 / PCIF1 / PCIE1)

Interrupt handler processing

The interrupt handler would need to work out which pin caused the interrupt if the mask
specifies more than one (eg. if you wanted interrupts on D8/D9/D10). To do this you
would need to store the previous state of that pin, and work out (by doing a digitalRead
or similar) if this particular pin had changed.

Example of waking from sleep with a Pin Change Interrupt

#include <avr/sleep.h>

const byte LEDLOOP = 8;


const byte LEDWAKE = 9;

ISR (PCINT1_vect)
{
// handle pin change interrupt for A0 to A5 here
// toggle LED
digitalWrite (LEDWAKE, !digitalRead (LEDWAKE));
} // end of PCINT1_vect

void setup ()
{
pinMode (LEDWAKE, OUTPUT);
pinMode (LEDLOOP, OUTPUT);
digitalWrite (A0, HIGH); // enable pull-up

// pin change interrupt


PCMSK1 |= bit (PCINT8); // want pin A0
PCIFR |= bit (PCIF1); // clear any outstanding interrupts
PCICR |= bit (PCIE1); // enable pin change interrupts for A0 to A5

} // end of setup

void loop ()
{

set_sleep_mode (SLEEP_MODE_PWR_DOWN);
sleep_mode ();

// flash to indicate we got out of sleep


digitalWrite (LEDLOOP, HIGH);
delay (100);
digitalWrite (LEDLOOP, LOW);
delay (100);
} // end of loop
Critical sections ... accessing volatile variables

There are some subtle issues regarding variables which are shared between interrupt
service routines (ISRs) and the main code (that is, the code not in an ISR).

Since an ISR can fire at any time when interrupts are enabled, you need to be cautious
about accessing such shared variables, as they may be being updated at the very
moment you access them.

First ... when do you use "volatile" variables?

A variable should only be marked volatile if it is used both inside an ISR, and outside one.

Variables only used outside an ISR should not be volatile.


Variables only used inside an ISR should not be volatile.
Variables used both inside and outside an ISR should be volatile.

Eg.

volatile int counter;

Marking a variable as volatile tells the compiler to not "cache" the variables contents into
a processor register, but always read it from memory, when needed. This may slow down
processing, which is why you don't just make every variable volatile, when not needed.

Atomic access

Consider this code:

volatile byte count;

ISR (TIMER1_OVF_vect)
{
count = 10;
}
void setup ()
{
}

void loop ()
{
count++;
}

The code generated for count++ (add 1 to count) is this:

14c: 80 91 00 02 lds r24, 0x0200


150: 8f 5f subi r24, 0xFF <<---- problem if interrupt occurs before this
is executed
152: 80 93 00 02 sts 0x0200, r24 <<---- problem if interrupt occurs before
this is executed

(Note that it adds 1 by subtracting -1).

There are two danger points here, as marked. If the interrupt fires after the lds (load
register 24 with the variable "count"), but before the sts (store back into the variable
"count") then the variable might be changed by the ISR (TIMER1_OVF_vect),
however this change is now lost, because the variable in the register was used instead.

We need to protect the shared variable by turning off interrupts briefly, like this:

volatile byte count;

ISR (TIMER1_OVF_vect)
{
count = 10;
} // end of TIMER1_OVF_vect

void setup ()
{
} // end of setup

void loop ()
{
noInterrupts ();
count++;
interrupts ();
} // end of loop

Now the update of "count" is done "atomically" ... that is, it cannot be interrupted.

Multi-byte variables

Let's make "count" a 2-byte variable, and see the other problem:

volatile unsigned int count;

ISR (TIMER1_OVF_vect)
{
count++;
} // end of TIMER1_OVF_vect

void setup ()
{
pinMode (13, OUTPUT);
} // end of setup

void loop ()
{
if (count > 20)
digitalWrite (13, HIGH);
} // end of loop

OK, we are not changing count any more, so is there still a problem? Sadly, yes. Let's look
at the generated code for the "if" statement:

172: 80 91 10 02 lds r24, 0x0210


176: 90 91 11 02 lds r25, 0x0211 <<---- problem if interrupt occurs before
this is executed
17a: 45 97 sbiw r24, 0x15
17c: 50 f0 brcs .+20
Imagine that count was 0xFFFF and was about to "wrap around" back to zero. We load
0xFF into one register, but before we load the second 0xFF the variable changes to 0x00.
Now we think count is 0x00FF which is neither the value it had before (0xFFFF) or now
(0x0000).

So again we have to "protect" the access to the shared variable, like this:

void loop ()
{
noInterrupts ();
if (count > 20)
digitalWrite (13, HIGH);
interrupts ();
} // end of loop

What if you are not sure interrupts are on or off?

There is a final "gotcha" here. What if interrupts might be off already? Then turning them
back on afterwards is a Bad Idea.

In that case you need to save the processor status register like this:

unsigned int getCount ()


{
unsigned int c;
byte oldSREG = SREG; // remember if interrupts are on or off

noInterrupts (); // turn interrupts off


c = count; // access the shared variable
SREG = oldSREG; // turn interrupts back on, if they were off

return c; // return copy of shared variable


} // end of getCount

This "safe" code saves the current status of interrupts, turns them off (they may already
be off), gets the shared variable into a temporary variable, turns interrupts back on if
they were off, and then returns the copy of the shared variable.

Summary

Code may "appear to work" even if you don't take the above precautions. That is
because the chances of the interrupt occurring at the exact wrong moment is fairly low
(maybe 1 in 100, depending on the code size). But sooner or later it will happen at the
wrong moment, and your code will either crash, or occasionally return the wrong
results.

So for reliable code, pay attention to protecting access to shared variables.


Interrupt names to pin mappings
The various models of Arduino have somewhat confusing mappings of interrupt numbers
to pins, and the correlation between attachInterrupt (0) is not always to INT0.

The table below shows the ways they are mapped in the internal libraries:
ATtiny85 sleep mode and wake on pin change

The sketch below illustrates putting the ATtiny85 to sleep, and then waking on a pin-
change interrupt on D4 (pin 3 on the chip). The pin is put into input-pullup mode so all
you have to do is ground the pin to wake the chip.

Also see http://www.gammon.com.au/forum/?id=11497&reply=6#reply6 for an example


of similar code which also wakes up on a watchdog timer event.

// ATtiny85 sleep mode, wake on pin change interrupt demo


// Author: Nick Gammon
// Date: 12 October 2013

// ATMEL ATTINY 25/45/85 / ARDUINO


//
// +-\/-+
// Ain0 (D 5) PB5 1| |8 Vcc
// Ain3 (D 3) PB3 2| |7 PB2 (D 2) Ain1
// Ain2 (D 4) PB4 3| |6 PB1 (D 1) pwm1
// GND 4| |5 PB0 (D 0) pwm0
// +----+

#include <avr/sleep.h> // Sleep Modes


#include <avr/power.h> // Power management

const byte LED = 3; // pin 2


const byte SWITCH = 4; // pin 3 / PCINT4

ISR (PCINT0_vect)
{
// do something interesting here
}

void setup ()
{
pinMode (LED, OUTPUT);
pinMode (SWITCH, INPUT);
digitalWrite (SWITCH, HIGH); // internal pull-up

// pin change interrupt (example for D4)


PCMSK |= bit (PCINT4); // want pin D4 / pin 3
GIFR |= bit (PCIF); // clear any outstanding interrupts
GIMSK |= bit (PCIE); // enable pin change interrupts

} // end of setup

void loop ()
{
digitalWrite (LED, HIGH);
delay (500);
digitalWrite (LED, LOW);
delay (500);
goToSleep ();
} // end of loop

void goToSleep ()
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
ADCSRA = 0; // turn off ADC
power_all_disable (); // power off ADC, Timer 0 and 1, serial interface
sleep_enable();
sleep_cpu();
sleep_disable();
power_all_enable(); // power everything back on
} // end of goToSleep

With the brownout disable turned off, the above sketch uses 500 nA of current when
asleep, as predicted by the datasheet, page 183:
Fuses were:

Signature = 0x1E 0x93 0x0B


Processor = ATtiny85
Flash memory size = 8192 bytes.
LFuse = 0xE2
HFuse = 0xDF
EFuse = 0xFF
Lock byte = 0xFF
Clock calibration = 0x9A
Timing an interval

I have seen example code suggesting you count things for a second by turning interrupts
off for a second and then on again. I don't recommend this, because for one thing, you
can't do serial prints if interrupts are off.

Example (not recommended):

volatile unsigned long events;


const unsigned long INTERVAL = 1000; // 1 second

void eventISR ()
{
events++;
} // end of eventISR

void setup ()
{
Serial.begin(115200);
attachInterrupt (0, eventISR, FALLING);
} // end of setup

void loop ()
{
events = 0; // reset counter
interrupts (); // allow interrupts
delay (INTERVAL); // wait desired time
noInterrupts(); // stop interrupts

Serial.print ("I counted ");


Serial.println (events);
} // end of loop

That may work for simple situations, but turning interrupts off means that the Serial
prints won't work until they are turned on again (which they may not be in a more
complex sketch).

It is better to use the millis() result and just detect when the time limit is up.
Improved sketch:

volatile bool counting;


volatile unsigned long events;

unsigned long startTime;


const unsigned long INTERVAL = 1000; // 1 second

void eventISR ()
{
if (counting)
events++;
} // end of eventISR

void setup ()
{
Serial.begin (115200);
Serial.println ();
attachInterrupt (0, eventISR, FALLING);
} // end of setup

void showResults ()
{
Serial.print ("I counted ");
Serial.println (events);
} // end of showResults

void loop ()
{
if (counting)
{
// is time up?
if (millis () - startTime < INTERVAL)
return;
counting = false;
showResults ();
} // end of if

noInterrupts ();
events = 0;
startTime = millis ();
EIFR = bit (INTF0); // clear flag for interrupt 0
counting = true;
interrupts ();
} // end of loop

In loop() here we wait for the interval (1 second in this case) to be up, otherwise we
return, effectively doing nothing. You could of course do other things instead of just
returning.

If the time is up we display the count.

If counting is not currently active (and presuming we want it to be active) we remember


the start time, reset the counter to zero, and let it start counting up.

That code seemed to work OK up to 100 kHz, although the counts were getting a bit
inaccurate. You can do more precise timings by using the hardware counters / timers.

Details here:

The Atmega328 (as on the Arduino Uno) has three timers/counters on-board the chip.

Timer 0 is set up by the init() function (which is automatically called by the code
generated by the IDE, before setup() is called). This is used to count approximately every
millisecond. This provides you with the figure that the millis() function returns.

You can use these timers easily enough by using the analogWrite function - that just
generates a PWM (pulse width modulated) output on the various pins that the timer
hardware supports.

But for a more in-depth analysis, let's look at using the timers/counters in our own way.

The example code below provides a "frequency counter" which counts the number of
events which cause a rising edge on digital pin D5 during a specified interval.

For example, if you put a 5 kHz signal on pin D5, and time it for one second, the count
will be 5000. You could also time it for 1/10 of a second (giving you a count of 500) and
then multiply the result by 10, again giving you a figure of 5 kHz.

A longer timing period will give higher accuracy, and also average out any small
variations during the sample time. However, of course, a longer timing period takes
longer to execute.
Counter 1 - used to count pulses

In the code below Timer 1 is configured to count the number of times that a leading edge
(rising pulse) is detected on D5. Each event increments the internal counter in the timer.
When the 16-bit timer overflows an overflow interrupt is executed which counts the
number of overflows.

When the time is up, the number of counts is the current counter contents of timer 1,
plus the number of overflows multiplied by 65536.

Timer 2 - used to work out a timing interval

The counts are meaningless unless we know over what interval they occurred, which is
what we use Timer 2 for. It is set up to take the internal clock (normally 16 MHz on a
Uno), and "pre-scale" it by dividing it by 128. The pre-scaled clock will then "tick" every 8
microseconds (since the clock itself runs with a period of 1/16000000 or 62.5 nS).

So we configure Timer 2 to count up to 125 and then generate an interrupt. This


interrupt gives us a chance to see if our counting period is up. Since 8 S times 125 gives
1000 S, that means we get interrupted exactly every 1 mS.

Note that Timer 2 has a higher priority than Timers 0 and 1, so neither the millis() timer,
nor the Timer 1 counter will take precedence over this interrupt.

In the Timer 2 interrupt we see if time is up (basically whether the required number of
milliseconds is up). Is not, we just keep going. If time is up, we turn off both Timers 1 and
2, calculate the total count (by multiplying the number of overflows by 65536 and adding
in the remaining counts) and exit.

Frequency Counter sketch for Atmega328

// Timer and Counter example


// Author: Nick Gammon
// Date: 17th January 2012

// Input: Pin D5

// these are checked for in the main program


volatile unsigned long timerCounts;
volatile boolean counterReady;

// internal to counting routine


unsigned long overflowCount;
unsigned int timerTicks;
unsigned int timerPeriod;

void startCounting (unsigned int ms)


{
counterReady = false; // time not up yet
timerPeriod = ms; // how many 1 mS counts to do
timerTicks = 0; // reset interrupt counter
overflowCount = 0; // no overflows yet

// reset Timer 1 and Timer 2


TCCR1A = 0;
TCCR1B = 0;
TCCR2A = 0;
TCCR2B = 0;

// Timer 1 - counts events on pin D5


TIMSK1 = bit (TOIE1); // interrupt on Timer 1 overflow

// Timer 2 - gives us our 1 mS counting interval


// 16 MHz clock (62.5 nS per tick) - prescaled by 128
// counter increments every 8 S.
// So we count 125 of them, giving exactly 1000 S (1 mS)
TCCR2A = bit (WGM21) ; // CTC mode
OCR2A = 124; // count up to 125 (zero relative!!!!)

// Timer 2 - interrupt on match (ie. every 1 mS)


TIMSK2 = bit (OCIE2A); // enable Timer2 Interrupt

TCNT1 = 0; // Both counters to zero


TCNT2 = 0;

// Reset prescalers
GTCCR = bit (PSRASY); // reset prescaler now
// start Timer 2
TCCR2B = bit (CS20) | bit (CS22) ; // prescaler of 128
// start Timer 1
// External clock source on T1 pin (D5). Clock on rising edge.
TCCR1B = bit (CS10) | bit (CS11) | bit (CS12);
} // end of startCounting

ISR (TIMER1_OVF_vect)
{
++overflowCount; // count number of Counter1 overflows
} // end of TIMER1_OVF_vect

//******************************************************************
// Timer2 Interrupt Service is invoked by hardware Timer 2 every 1ms = 1000 Hz
// 16Mhz / 128 / 125 = 1000 Hz

ISR (TIMER2_COMPA_vect)
{
// grab counter value before it changes any more
unsigned int timer1CounterValue;
timer1CounterValue = TCNT1; // see datasheet, page 117 (accessing 16-bit registers)
unsigned long overflowCopy = overflowCount;

// see if we have reached timing period


if (++timerTicks < timerPeriod)
return; // not yet

// if just missed an overflow


if ((TIFR1 & bit (TOV1)) && timer1CounterValue < 256)
overflowCopy++;

// end of gate time, measurement ready

TCCR1A = 0; // stop timer 1


TCCR1B = 0;

TCCR2A = 0; // stop timer 2


TCCR2B = 0;

TIMSK1 = 0; // disable Timer1 Interrupt


TIMSK2 = 0; // disable Timer2 Interrupt

// calculate total count


timerCounts = (overflowCopy << 16) + timer1CounterValue; // each overflow is 65536
more
counterReady = true; // set global flag for end count period
} // end of TIMER2_COMPA_vect

void setup ()
{
Serial.begin(115200);
Serial.println("Frequency Counter");
} // end of setup

void loop ()
{
// stop Timer 0 interrupts from throwing the count out
byte oldTCCR0A = TCCR0A;
byte oldTCCR0B = TCCR0B;
TCCR0A = 0; // stop timer 0
TCCR0B = 0;

startCounting (500); // how many mS to count for

while (!counterReady)
{ } // loop until count over

// adjust counts by counting interval to give frequency in Hz


float frq = (timerCounts * 1000.0) / timerPeriod;

Serial.print ("Frequency: ");


Serial.print ((unsigned long) frq);
Serial.println (" Hz.");

// restart timer 0
TCCR0A = oldTCCR0A;
TCCR0B = oldTCCR0B;

// let serial stuff finish


delay(200);
} // end of loop

Accuracy
Pumping in a 5 MHz signal from a signal generator, the sketch outputs around 5001204
(give or take a couple of counts). The error (assuming the signal generator is accurate) is
therefore 1204/500000 or about 0.02% error.

Trying with a 5 kHz signal, the sketch outputs around 5000 to 5002, an error of 2/5000 or
0.04% error.

So, pretty accurate. Tests on my Arduino clock showed that the clock itself was around
0.2% wrong, so we can't really expect better accuracy than that.

Range

I measured up to 8 MHz with about 0.5% error. At 5 MHz the error was down to 0.02% as
described above. At the other end of the scale, it measured down to 10 Hz without any
obvious error. Below that errors crept in, particularly as the sample period is only 500
mS.

Frequency Counter sketch for Atmega2560

// Timer and Counter example for Mega2560


// Author: Nick Gammon
// Date: 24th April 2012

// input on pin D47 (T5)

// these are checked for in the main program


volatile unsigned long timerCounts;
volatile boolean counterReady;

// internal to counting routine


unsigned long overflowCount;
unsigned int timerTicks;
unsigned int timerPeriod;

void startCounting (unsigned int ms)


{

counterReady = false; // time not up yet


timerPeriod = ms; // how many 1 mS counts to do
timerTicks = 0; // reset interrupt counter
overflowCount = 0; // no overflows yet

// reset Timer 2 and Timer 5


TCCR2A = 0;
TCCR2B = 0;
TCCR5A = 0;
TCCR5B = 0;

// Timer 5 - counts events on pin D47


TIMSK5 = bit (TOIE1); // interrupt on Timer 5 overflow

// Timer 2 - gives us our 1 mS counting interval


// 16 MHz clock (62.5 nS per tick) - prescaled by 128
// counter increments every 8 S.
// So we count 125 of them, giving exactly 1000 S (1 mS)
TCCR2A = bit (WGM21) ; // CTC mode
OCR2A = 124; // count up to 125 (zero relative!!!!)

// Timer 2 - interrupt on match (ie. every 1 mS)


TIMSK2 = bit (OCIE2A); // enable Timer2 Interrupt

TCNT2 = 0;
TCNT5 = 0; // Both counters to zero

// Reset prescalers
GTCCR = bit (PSRASY); // reset prescaler now
// start Timer 2
TCCR2B = bit (CS20) | bit (CS22) ; // prescaler of 128
// start Timer 5
// External clock source on T4 pin (D47). Clock on rising edge.
TCCR5B = bit (CS50) | bit (CS51) | bit (CS52);

} // end of startCounting

ISR (TIMER5_OVF_vect)
{
++overflowCount; // count number of Counter1 overflows
} // end of TIMER5_OVF_vect

//******************************************************************
// Timer2 Interrupt Service is invoked by hardware Timer 2 every 1ms = 1000 Hz
// 16Mhz / 128 / 125 = 1000 Hz

ISR (TIMER2_COMPA_vect)
{
// grab counter value before it changes any more
unsigned int timer5CounterValue;
timer5CounterValue = TCNT5; // see datasheet, (accessing 16-bit registers)

// see if we have reached timing period


if (++timerTicks < timerPeriod)
return; // not yet

// if just missed an overflow


if (TIFR5 & TOV5)
overflowCount++;

// end of gate time, measurement ready

TCCR5A = 0; // stop timer 5


TCCR5B = 0;

TCCR2A = 0; // stop timer 2


TCCR2B = 0;

TIMSK2 = 0; // disable Timer2 Interrupt


TIMSK5 = 0; // disable Timer5 Interrupt

// calculate total count


timerCounts = (overflowCount << 16) + timer5CounterValue; // each overflow is 65536
more
counterReady = true; // set global flag for end count period
} // end of TIMER2_COMPA_vect

void setup () {
Serial.begin(115200);
Serial.println("Frequency Counter");
} // end of setup

void loop () {

// stop Timer 0 interrupts from throwing the count out


byte oldTCCR0A = TCCR0A;
byte oldTCCR0B = TCCR0B;
TCCR0A = 0; // stop timer 0
TCCR0B = 0;

startCounting (500); // how many mS to count for

while (!counterReady)
{ } // loop until count over

// adjust counts by counting interval to give frequency in Hz


float frq = (timerCounts * 1000.0) / timerPeriod;

// restart timer 0
TCCR0A = oldTCCR0A;
TCCR0B = oldTCCR0B;

Serial.print ("Frequency: ");


Serial.println ((unsigned long) frq);

// let serial stuff finish


delay(200);

} // end of loop

Timer ready reckoner

To help work out what prescaler/count you need for setting up timers, consult this table:
All these figures assume a 16 MHz clock, and thus a clock period of 62.5 nS.

The "count" column is the number of counts you use for the Output Compare Register
(eg. for OCR2A, OCR2B and so on) when counting up to a "compare" value. The count of
256 can also be used to see how long until Timer 0 and Timer 2 overflow (Timer 1 is a 16-
bit timer and overflows after 65536 counts).

Remember that the count registers are zero-relative, so to get 100 counts, you actually
put 99 into the register.

So for example, with a prescaler of 64, Timer 0 will overflow every 1.024 mS (which in
fact it normally does for use by the millis() function).

To set some other frequency choose a prescaler which appears reasonably close, and
then apply this formula:

count = frequency_from_table / target_frequency


For example, if we wanted to flash an LED at 50 Hz using a prescaler of 1024:

count = 15625 / 50 = 312.5


Since 312.5 is greater than 256 we could only do that with Timer 1 which is a 16-bit
timer. Note that 312.5 has a decimal place, and therefore the flash would not occur
every 50 Hz (as it would be rounded down). You could choose a prescaler of 256 instead:

count = 62500 / 50 = 1250

Now, we have a whole number, so the frequency would be accurate.

Bear in mind, too, that if you are using the hardware to toggle a pin, it needs to get
toggled at twice the target frequency (because 100 Hz is counting 100 times a complete
cycle, not half a cycle).

Timer hardware input/output

The table below shows the relationship between various pins (with the Arduino pin
number in brackets) and the respective timers.
For example, to count an external source with Timer 1, you connect that to Arduino pin
D5 (pin 11 on the Atmega328).

Timer 0

input T0 pin 6 (D4)

output OC0A pin 12 (D6)


output OC0B pin 11 (D5)

Timer 1

input T1 pin 11 (D5)

output OC1A pin 15 (D9)


output OC1B pin 16 (D10)

Timer 2

output OC2A pin 17 (D11)


output OC2B pin 5 (D3)
Another frequency counter

The frequency counter below works a bit differently. The one in the earlier post used a
timer to count the number of "ticks" in a given interval, so it was literally counting the
frequency.

The sketch below turns that around, and uses a timer to work out the interval between
two consecutive rising edges on pin D2. This time we use a "rising" interrupt on D2 to
notice the leading edge. We also set up a high-precision timer (Timer 1) which is a 16-bit
timer.

By using no prescaler, Timer 1 counts 1 for every clock cycle (say, every 62.5 nS at 16
MHz). By multiplying the number of counts between the leading edges by 62.5, and then
taking the inverse, we can deduce the frequency.
The advantage of this method is that we get a very quick calculation. For example, at 10
kHz the period is 1/10000, namely 100 S, so we get our result 100 S later.

// Frequency timer
// Author: Nick Gammon
// Date: 10th February 2012

// Input: Pin D2

volatile boolean first;


volatile boolean triggered;
volatile unsigned long overflowCount;
volatile unsigned long startTime;
volatile unsigned long finishTime;

// here on rising edge


void isr ()
{
unsigned int counter = TCNT1; // quickly save it

// wait until we noticed last one


if (triggered)
return;

if (first)
{
startTime = (overflowCount << 16) + counter;
first = false;
return;
}

finishTime = (overflowCount << 16) + counter;


triggered = true;
detachInterrupt(0);
} // end of isr

// timer overflows (every 65536 counts)


ISR (TIMER1_OVF_vect)
{
overflowCount++;
} // end of TIMER1_OVF_vect

void prepareForInterrupts ()
{
// get ready for next time
EIFR = bit (INTF0); // clear flag for interrupt 0
first = true;
triggered = false; // re-arm for next time
attachInterrupt(0, isr, RISING);
} // end of prepareForInterrupts

void setup ()
{
Serial.begin(115200);
Serial.println("Frequency Counter");

// reset Timer 1
TCCR1A = 0;
TCCR1B = 0;
// Timer 1 - interrupt on overflow
TIMSK1 = bit (TOIE1); // enable Timer1 Interrupt
// zero it
TCNT1 = 0;
overflowCount = 0;
// start Timer 1
TCCR1B = bit (CS20); // no prescaling

// set up for interrupts


prepareForInterrupts ();

} // end of setup

void loop ()
{

if (!triggered)
return;

unsigned long elapsedTime = finishTime - startTime;


float freq = F_CPU / float (elapsedTime); // each tick is 62.5 nS at 16 MHz
Serial.print ("Took: ");
Serial.print (elapsedTime);
Serial.print (" counts. ");

Serial.print ("Frequency: ");


Serial.print (freq);
Serial.println (" Hz. ");

// so we can read it
delay (500);

prepareForInterrupts ();
} // end of loop

Note that due to the time taken to service the interrupts on the data's leading edges, the
maximum achievable frequency you can sample is around 100 kHz (which would mean
the ISR is taking around 10 S).
Timer setup

Below are some namespaces for easily setting up timers. They can be a bit tedious to get
the various bit combinations right for the various modes.

The sketch has three "namespaces" (Timer0, Timer1, Timer2) which inside have a table
of modes, and some enums for the various settings).

So for example, to set Timer 1 into mode 4 (CTC, top = OCR1A) with a prescaler of 1 (ie.
no prescaler) and clearing timer output port 1A on compare you would do this:

Timer1::setMode (4, Timer1::PRESCALE_1, Timer1::CLEAR_A_ON_COMPARE);

That is a lot easier than setting up a lot of bit patterns.

/*
Timer Helpers library.

Devised and written by Nick Gammon.


Date: 21 March 2012
Version: 1.0
Licence: Released for public use.

See: http://www.gammon.com.au/forum/?id=11504

Example:

// set up Timer 1
TCNT1 = 0; // reset counter
OCR1A = 999; // compare A register value (1000 * clock speed)

// Mode 4: CTC, top = OCR1A


Timer1::setMode (4, Timer1::PRESCALE_1, Timer1::CLEAR_A_ON_COMPARE);

TIFR1 |= bit (OCF1A); // clear interrupt flag


TIMSK1 = bit (OCIE1A); // interrupt on Compare A Match

*/

#ifndef _TimerHelpers_h
#define _TimerHelpers_h

#if defined(ARDUINO) && ARDUINO >= 100


#include "Arduino.h"
#else
#include "WProgram.h"
#endif

/* ---------------------------------------------------------------
Timer 0 setup
--------------------------------------------------------------- */

namespace Timer0
{
// TCCR0A, TCCR0B
const byte Modes [8] [2] =
{

{ 0, 0 }, // 0: Normal, top = 0xFF


{ bit (WGM00), 0 }, // 1: PWM, Phase-correct, top = 0xFF
{ bit (WGM01), 0 }, // 2: CTC, top = OCR0A
{ bit (WGM00) | bit (WGM01), 0 }, // 3: Fast PWM, top = 0xFF
{ 0, bit (WGM02) }, // 4: Reserved
{ bit (WGM00), bit (WGM02) }, // 5: PWM, Phase-correct, top = OCR0A
{ bit (WGM01), bit (WGM02) }, // 6: Reserved
{ bit (WGM00) | bit (WGM01), bit (WGM02) }, // 7: Fast PWM, top = OCR0A

}; // end of Timer0::Modes

// Activation
// Note: T0 is pin 6, Arduino port: D4
enum { NO_CLOCK, PRESCALE_1, PRESCALE_8, PRESCALE_64, PRESCALE_256,
PRESCALE_1024, T0_FALLING, T0_RISING };

// what ports to toggle on timer fire


enum { NO_PORT = 0,

// pin 12, Arduino port: D6


TOGGLE_A_ON_COMPARE = bit (COM0A0),
CLEAR_A_ON_COMPARE = bit (COM0A1),
SET_A_ON_COMPARE = bit (COM0A0) | bit (COM0A1),

// pin 11, Arduino port: D5


TOGGLE_B_ON_COMPARE = bit (COM0B0),
CLEAR_B_ON_COMPARE = bit (COM0B1),
SET_B_ON_COMPARE = bit (COM0B0) | bit (COM0B1),
};

// choose a timer mode, set which clock speed, and which port to toggle
void setMode (const byte mode, const byte clock, const byte port)
{
if (mode < 0 || mode > 7) // sanity check
return;

// reset existing flags


TCCR0A = 0;
TCCR0B = 0;

TCCR0A |= (Modes [mode] [0]) | port;


TCCR0B |= (Modes [mode] [1]) | clock;
} // end of Timer0::setMode
} // end of namespace Timer0

/* ---------------------------------------------------------------
Timer 1 setup
--------------------------------------------------------------- */

namespace Timer1
{
// TCCR1A, TCCR1B
const byte Modes [16] [2] =
{

{ 0, 0 }, // 0: Normal, top = 0xFFFF


{ bit (WGM10), 0 }, // 1: PWM, Phase-correct, 8 bit, top = 0xFF
{ bit (WGM11), 0 }, // 2: PWM, Phase-correct, 9 bit, top = 0x1FF
{ bit (WGM10) | bit (WGM11), 0 }, // 3: PWM, Phase-correct, 10 bit, top = 0x3FF
{ 0, bit (WGM12) }, // 4: CTC, top = OCR1A
{ bit (WGM10), bit (WGM12) }, // 5: Fast PWM, 8 bit, top = 0xFF
{ bit (WGM11), bit (WGM12) }, // 6: Fast PWM, 9 bit, top = 0x1FF
{ bit (WGM10) | bit (WGM11), bit (WGM12) }, // 7: Fast PWM, 10 bit, top = 0x3FF
{ 0, bit (WGM13) }, // 8: PWM, phase and frequency correct, top =
ICR1
{ bit (WGM10), bit (WGM13) }, // 9: PWM, phase and frequency correct,
top = OCR1A
{ bit (WGM11), bit (WGM13) }, // 10: PWM, phase correct, top = ICR1A
{ bit (WGM10) | bit (WGM11), bit (WGM13) }, // 11: PWM, phase correct, top =
OCR1A
{ 0, bit (WGM12) | bit (WGM13) }, // 12: CTC, top = ICR1
{ bit (WGM10), bit (WGM12) | bit (WGM13) }, // 13: reserved
{ bit (WGM11), bit (WGM12) | bit (WGM13) }, // 14: Fast PWM, TOP = ICR1
{ bit (WGM10) | bit (WGM11), bit (WGM12) | bit (WGM13) }, // 15: Fast PWM, TOP =
OCR1A

}; // end of Timer1::Modes

// Activation
// Note: T1 is pin 11, Arduino port: D5
enum { NO_CLOCK, PRESCALE_1, PRESCALE_8, PRESCALE_64, PRESCALE_256,
PRESCALE_1024, T1_FALLING, T1_RISING };

// what ports to toggle on timer fire


enum { NO_PORT = 0,

// pin 15, Arduino port: D9


TOGGLE_A_ON_COMPARE = bit (COM1A0),
CLEAR_A_ON_COMPARE = bit (COM1A1),
SET_A_ON_COMPARE = bit (COM1A0) | bit (COM1A1),

// pin 16, Arduino port: D10


TOGGLE_B_ON_COMPARE = bit (COM1B0),
CLEAR_B_ON_COMPARE = bit (COM1B1),
SET_B_ON_COMPARE = bit (COM1B0) | bit (COM1B1),
};

// choose a timer mode, set which clock speed, and which port to toggle
void setMode (const byte mode, const byte clock, const byte port)
{
if (mode < 0 || mode > 15) // sanity check
return;

// reset existing flags


TCCR1A = 0;
TCCR1B = 0;

TCCR1A |= (Modes [mode] [0]) | port;


TCCR1B |= (Modes [mode] [1]) | clock;
} // end of Timer1::setMode

} // end of namespace Timer1

/* ---------------------------------------------------------------
Timer 2 setup
--------------------------------------------------------------- */

namespace Timer2
{
// TCCR2A, TCCR2B
const byte Modes [8] [2] =
{

{ 0, 0 }, // 0: Normal, top = 0xFF


{ bit (WGM20), 0 }, // 1: PWM, Phase-correct, top = 0xFF
{ bit (WGM21), 0 }, // 2: CTC, top = OCR2A
{ bit (WGM20) | bit (WGM21), 0 }, // 3: Fast PWM, top = 0xFF
{ 0, bit (WGM22) }, // 4: Reserved
{ bit (WGM20), bit (WGM22) }, // 5: PWM, Phase-correct, top = OCR2A
{ bit (WGM21), bit (WGM22) }, // 6: Reserved
{ bit (WGM20) | bit (WGM21), bit (WGM22) }, // 7: Fast PWM, top = OCR2A

}; // end of Timer2::Modes

// Activation
enum { NO_CLOCK, PRESCALE_1, PRESCALE_8, PRESCALE_32, PRESCALE_64,
PRESCALE_128, PRESCALE_256, PRESCALE_1024 };

// what ports to toggle on timer fire


enum { NO_PORT = 0,

// pin 17, Arduino port: D11


TOGGLE_A_ON_COMPARE = bit (COM2A0),
CLEAR_A_ON_COMPARE = bit (COM2A1),
SET_A_ON_COMPARE = bit (COM2A0) | bit (COM2A1),

// pin 5, Arduino port: D3


TOGGLE_B_ON_COMPARE = bit (COM2B0),
CLEAR_B_ON_COMPARE = bit (COM2B1),
SET_B_ON_COMPARE = bit (COM2B0) | bit (COM2B1),
};

// choose a timer mode, set which clock speed, and which port to toggle
void setMode (const byte mode, const byte clock, const byte port)
{
if (mode < 0 || mode > 7) // sanity check
return;

// reset existing flags


TCCR2A = 0;
TCCR2B = 0;

TCCR2A |= (Modes [mode] [0]) | port;


TCCR2B |= (Modes [mode] [1]) | clock;
} // end of Timer2::setMode
} // end of namespace Timer2

#endif

The above can be downloaded from:

http://gammon.com.au/Arduino/TimerHelpers.zip

Just unzip and put the TimerHelpers folder into your libraries folder.

Example of use:

#include <TimerHelpers.h>

/* ---------------------------------------------------------------
Test sketch
--------------------------------------------------------------- */

const byte SHUTTER = 9; // this is OC1A (timer 1 output compare A)

void setup() {
pinMode (SHUTTER, INPUT);
digitalWrite (SHUTTER, HIGH);

} // end of setup

ISR(TIMER1_COMPA_vect)
{
TCCR1A = 0; // reset timer 1
TCCR1B = 0;
} // end of TIMER1_COMPA_vect

void loop() {
delay (250); // debugging

TCCR1A = 0; // reset timer 1


TCCR1B = 0;

digitalWrite (SHUTTER, HIGH); // ready to activate


pinMode (SHUTTER, OUTPUT);

// set up Timer 1
TCNT1 = 0; // reset counter
OCR1A = 999; // compare A register value (1000 * clock speed)

// Mode 4: CTC, top = OCR1A


Timer1::setMode (4, Timer1::PRESCALE_1, Timer1::CLEAR_A_ON_COMPARE);

TIFR1 |= bit (OCF1A); // clear interrupt flag


TIMSK1 = bit (OCIE1A); // interrupt on Compare A Match

} // end of loop

One-shot timer

The example code above demonstrates a one-shot timer. This sets up Timer 1 to activate
a camera shutter for 62.5 uS (1000 x the clock speed of 62.5 nS), and then the interrupt
service routine cancels the timer, so the shutter is only activated once.
Operation modes of Timer 0
Every time I go to use the Arduino (Atmega328) timers I wonder what the heck is the
difference between the various modes. Do I want normal? CTC? PWM? Fast PWM?

Below are the results of investigating what each mode does, for timer 0.

I'm guessing that Timer 2 (which is also an 8-bit timer) works in a similar way.

Timer 0, mode 0 (Normal mode)

This mode just counts to the maximum (0xFF) and wraps around. An interrupt can be set
to go off at the wrap-around point.

The counters (OCR0A and OCR0B) control at what point in the counting sequence the
pins are toggled.

#include <TimerHelpers.h>

// Timer 0

// input T0 pin 6 (D4)


// output OC0A pin 12 (D6)
// output OC0B pin 11 (D5)

const byte timer0Input = 4;


const byte timer0OutputA = 6;
const byte timer0OutputB = 5;

void setup() {
pinMode (timer0OutputA, OUTPUT);
pinMode (timer0OutputB, OUTPUT);
TIMSK0 = 0; // no interrupts
Timer0::setMode (0, Timer0::PRESCALE_1, Timer0::TOGGLE_A_ON_COMPARE |
Timer0::TOGGLE_B_ON_COMPARE);
OCR0A = 150;
OCR0B = 200;
} // end of setup

void loop() {}

The period here was 16 uS which is 256 * 62.5 nS. Since I set the output pin to toggle on
compare, it toggled every 16 uS.

Timer 0, mode 1 (PWM phase correct mode, top at 255)

This mode counts up to the maximum and then down again. On the first cycle (counting
up) and if you have CLEAR_A_ON_COMPARE set, then the output is initially high for
OCR0A/255 of the period (in the example: 150/255 which is a duty cycle of 58.82%), and
then goes low. For the second cycle (counting down) it stays low, and flips back to high
when the count is reached.

#include <TimerHelpers.h>

// Timer 0

// input T0 pin 6 (D4)


// output OC0A pin 12 (D6)
// output OC0B pin 11 (D5)

const byte timer0Input = 4;


const byte timer0OutputA = 6;
const byte timer0OutputB = 5;

void setup() {
pinMode (timer0OutputA, OUTPUT);
pinMode (timer0OutputB, OUTPUT);
OCR0A = 150;
OCR0B = 200;
TIMSK0 = 0; // no interrupts
Timer0::setMode (1, Timer0::PRESCALE_1, Timer0::CLEAR_A_ON_COMPARE |
Timer0::CLEAR_B_ON_COMPARE);
} // end of setup

void loop() {}
The total period here is 32 uS (and the duty cycle of the A output is 58.824%, that is:
150/255).

This could be regarded as "slow PWM" because an entire cycle takes 512 clock cycles
(256 up, 256 down). All you get to adjust is the point in that cycle where the output is
toggled.

If you change CLEAR to SET then the output is inverted, like this:

Now, the higher the counter, the longer the output is low (because it is set when the
counter is reached).

Timer 0, mode 2 (CTC mode)

This mode lets you control the timer frequency. CTC is Clear Timer on Count.

Modes 0 and 1 simply counted up to 256 or 512 respectively, thus giving a fixed
frequency output. You could only alter the frequency by changing the timer prescaler.

However in CTC mode the timer resets when it reaches the count. In the example, the
period is 151 * 62.5 nS which is 9.438 uS. You multiply by 151 and not 150 because the
timer is zero-relative (the first count is zero).

#include <TimerHelpers.h>
// Timer 0
// input T0 pin 6 (D4)
// output OC0A pin 12 (D6)
// output OC0B pin 11 (D5)

const byte timer0Input = 4;


const byte timer0OutputA = 6;
const byte timer0OutputB = 5;

void setup() {
pinMode (timer0OutputA, OUTPUT);
pinMode (timer0OutputB, OUTPUT);
TIMSK0 = 0; // no interrupts
Timer0::setMode (2, Timer0::PRESCALE_1, Timer0::TOGGLE_A_ON_COMPARE |
Timer0::TOGGLE_B_ON_COMPARE);
OCR0A = 150;
OCR0B = 200;
} // end of setup

void loop() {}

Notice that setting the B pin to toggle does not seem to work. I presume the timer can
only count to one value, and that is the A match value.
Also note that you need to set the counter after starting the timer (as shown above) or
you get rather strange results like this:

The timer for the above screenshot was started like this:

OCR0A = 150;
OCR0B = 200;
Timer0::setMode (2, Timer0::PRESCALE_1, Timer0::TOGGLE_A_ON_COMPARE |
Timer0::TOGGLE_B_ON_COMPARE);

Notice that the period of the timer seems to be just 62.5 nS (the processor clock cycle).

Timer 0, mode 3 (fast PWM mode, top at 255)

This mode counts up to the counter and toggles it when reached. In the example:
151/256 which is a duty cycle of 58.984%.

#include <TimerHelpers.h>

// Timer 0

// input T0 pin 6 (D4)


// output OC0A pin 12 (D6)
// output OC0B pin 11 (D5)
const byte timer0Input = 4;
const byte timer0OutputA = 6;
const byte timer0OutputB = 5;

void setup() {
pinMode (timer0OutputA, OUTPUT);
pinMode (timer0OutputB, OUTPUT);
TIMSK0 = 0; // no interrupts
Timer0::setMode (3, Timer0::PRESCALE_1, Timer0::CLEAR_A_ON_COMPARE |
Timer0::CLEAR_B_ON_COMPARE);
OCR0A = 150;
OCR0B = 200;
} // end of setup

void loop() {}

Notice that compared to the phase correct mode the frequency is doubled (it only counts
up, not down again). Thus for a prescaler of 1, the period is going to be 256 * 62.5 nS,
namely 16 uS. Also note how channel A and B are lined up, compared to how the pulses
are centered in phase-correct mode.

Timer 0, mode 5 (PWM phase correct mode, top at OCR0A)

This mode counts up to the value in OCR0A and then down again. On the first cycle
(counting up) and if you have CLEAR_A_ON_COMPARE set, then the output is initially
high for OCR0B/OCR0A of the period (in the example: 150/255 which is a duty cycle of
75%), and then goes low. For the second cycle (counting down) it stays low, and flips
back to high when the count is reached.

#include <TimerHelpers.h>

// Timer 0

// input T0 pin 6 (D4)


// output OC0A pin 12 (D6)
// output OC0B pin 11 (D5)

const byte timer0Input = 4;


const byte timer0OutputA = 6;
const byte timer0OutputB = 5;

void setup() {
pinMode (timer0OutputA, OUTPUT);
pinMode (timer0OutputB, OUTPUT);
TIMSK0 = 0; // no interrupts
Timer0::setMode (5, Timer0::PRESCALE_1, Timer0::CLEAR_A_ON_COMPARE |
Timer0::CLEAR_B_ON_COMPARE);
OCR0A = 200; // number of counts for a cycle
OCR0B = 150; // duty cycle within OCR0A
} // end of setup

void loop() {}
Note that OCR0A sets the frequency of the timer - since it counts up to that figure and
back again. So you can use this to make a timer with a frequency other than simply 256
times the clock period. Of course the lower OCR0A is, the less resolution you have for the
PWM duty cycle.

The overall frequency in this example was 40 kHz (period of 25 uS) because that is 200 *
62.5 nS * 2 (you multiply by two because it counts up and back down again).

Timer 0, mode 7 (fast PWM mode, top at OCR0A)

This mode counts up to OCR0B and toggles it when reached. It then counts (the rest of
the way) up to OCR0A. This is the fast PWM version of mode 5.

#include <TimerHelpers.h>

// Timer 0

// input T0 pin 6 (D4)


// output OC0A pin 12 (D6)
// output OC0B pin 11 (D5)

const byte timer0Input = 4;


const byte timer0OutputA = 6;
const byte timer0OutputB = 5;

void setup() {
pinMode (timer0OutputA, OUTPUT);
pinMode (timer0OutputB, OUTPUT);
TIMSK0 = 0; // no interrupts
Timer0::setMode (7, Timer0::PRESCALE_1, Timer0::CLEAR_A_ON_COMPARE |
Timer0::CLEAR_B_ON_COMPARE);
OCR0A = 200;
OCR0B = 150;
} // end of setup

void loop() {}
Because it counts up to 200 the period is 200 * 62.5 nS (12.5 uS) and the duty cycle is
now 75.5% (151/200).

Timer helpers library

The TimerHelpers.h file can be downloaded from:

http://gammon.com.au/Arduino/TimerHelpers.zip

More information

Some more useful information about PWM here, including some nice graphics that show
how the phase-correct PWM works:

What is PWM?

Also this write-up by Ken Shirriff:

Secrets of Arduino PWM


Modulating 38 kHz signal
This question seems to come up a few times on the Arduino forum: How to modulate a
38 kHz signal?

The code below uses Timer 1 to generate a 38 kHz pulse using fast PWM mode (mode
15). It then modulates the duty cycle from 0% to 100% based on a figure read from a
potentiometer connected to A0.

// Example of modulating a 38 kHz frequency duty cycle by reading a potentiometer


// Author: Nick Gammon
// Date: 24 September 2012

const byte POTENTIOMETER = A0;


const byte LED = 10; // Timer 1 "B" output: OC1B

// Clock frequency divided by 38 kHz frequency desired


const long timer1_OCR1A_Setting = F_CPU / 38000L;

void setup()
{
pinMode (LED, OUTPUT);

// set up Timer 1 - gives us 38.005 kHz


// Fast PWM top at OCR1A
TCCR1A = bit (WGM10) | bit (WGM11) | bit (COM1B1); // fast PWM, clear OC1B on
compare
TCCR1B = bit (WGM12) | bit (WGM13) | bit (CS10); // fast PWM, no prescaler
OCR1A = timer1_OCR1A_Setting - 1; // zero relative
} // end of setup

void loop()
{
// alter Timer 1 duty cycle in accordance with pot reading
OCR1B = (((long) (analogRead (POTENTIOMETER) + 1) * timer1_OCR1A_Setting) /
1024L) - 1;

// do other stuff here


}
Modulating a 38 kHz carrier with a 500 Hz signal
Similar to the above, the sketch below generates a 38 kHz signal and then turns that
carrier on and off with a 500 Hz signal (generated by Timer 2) with a variable duty cycle
controlled by a potentiometer. The 500 Hz duty cycle is output on pin 3 which causes a
pin change interrupt which is used to turn pin 9 on and off.

// Example of modulating a 38 kHz carrier frequency at 500 Hz with a variable duty cycle
// Author: Nick Gammon
// Date: 24 September 2012

const byte POTENTIOMETER = A0;


const byte LED = 9; // Timer 1 "A" output: OC1A

// Clock frequency divided by 500 Hz frequency desired (allowing for prescaler of 128)
const long timer2_OCR2A_Setting = F_CPU / 500L / 128L;

ISR (PCINT2_vect)
{

// if pin 3 now high, turn on toggling of OC1A on compare


if (PIND & bit (3))
{
TCCR1A |= bit (COM1A0) ; // Toggle OC1A on Compare Match
}
else
{
TCCR1A &= ~bit (COM1A0) ; // DO NOT Toggle OC1A on Compare Match
digitalWrite (LED, LOW); // ensure off
} // end of if

} // end of PCINT2_vect

void setup() {
pinMode (LED, OUTPUT);
pinMode (3, OUTPUT); // OC2B

// set up Timer 1 - gives us 38.095 kHz


TCCR1A = 0;
TCCR1B = bit(WGM12) | bit (CS10); // CTC, No prescaler
OCR1A = (F_CPU / 38000L / 2) - 1; // zero relative

// Timer 2 - gives us our 1 mS counting interval


// 16 MHz clock (62.5 nS per tick) - prescaled by 128
// counter increments every 8 uS.
// So we count 250 of them, giving exactly 2000 uS (2 mS period = 500 Hz frequency)
TCCR2A = bit (WGM20) | bit (WGM21) | bit (COM2B1); // Fast PWM mode
TCCR2B = bit (WGM22) | bit (CS20) | bit (CS22) ; // prescaler of 128
OCR2A = timer2_OCR2A_Setting - 1; // count up to 250 (zero relative!!!!)

// pin change interrupt


PCMSK2 |= bit (PCINT19); // want pin 3
PCIFR |= bit (PCIF2); // clear any outstanding interrupts
PCICR |= bit (PCIE2); // enable pin change interrupts for D0 to D7

} // end of setup

void loop()
{
// alter Timer 2 duty cycle in accordance with pot reading
OCR2B = (((long) (analogRead (POTENTIOMETER) + 1) * timer2_OCR2A_Setting) /
1024L) - 1;

// other stuff here


} // end of loop
Simple timer output
The code below outputs on pin 3 a square wave using fast PWM mode of the desired
frequency (constant "frequency").

This particular case uses a prescaler of 8 (hence the divide by 8 in the calculation of
OCR2A).

You could change the duty cycle in the calculation of OCR2B (divide by 3, for example).

const byte LED = 3; // Timer 2 "B" output: OC2B

const long frequency = 50000L; // Hz

void setup()
{
pinMode (LED, OUTPUT);

TCCR2A = bit (WGM20) | bit (WGM21) | bit (COM2B1); // fast PWM, clear OC2B on
compare
TCCR2B = bit (WGM22) | bit (CS21); // fast PWM, prescaler of 8
OCR2A = ((F_CPU / 8) / frequency) - 1; // zero relative
OCR2B = ((OCR2A + 1) / 2) - 1; // 50% duty cycle
} // end of setup

void loop()
{
// do other stuff here
}

With a 16 MHz clock, and with the prescaler of 8 you can generate frequencies in the
range 7813 Hz to 1 MHz.

With no prescaler the sketch looks like this:

const byte LED = 3; // Timer 2 "B" output: OC2B

const long frequency = 800000L;


void setup()
{
pinMode (LED, OUTPUT);

TCCR2A = bit (WGM20) | bit (WGM21) | bit (COM2B1); // fast PWM, clear OC2A on
compare
TCCR2B = bit (WGM22) | bit (CS20); // fast PWM, no prescaler
OCR2A = (F_CPU / frequency) - 1; // zero relative
OCR2B = ((OCR2A + 1) / 2) - 1; // 50% duty cycle
} // end of setup

void loop()
{
// do other stuff here
}

With a 16 MHz clock, this can generate frequencies in the range 62.5 kHz to 4 MHz (8
MHz ought to work but has artifacts on the measured output).
Frequencies and periods for various counter values
Below is a table of values for OCR2A (n) which shows the period and frequency you get
for each possible value and prescaler, assuming a 16 MHz clock rate. The same figures
apply to Timers 0 and 1 with the same prescalers. Note that the value in the first column
is already zero-relative. This is what you plug into OCR2A to get this frequency. Thus the
value of 255, for example, actually counts to 256.

The value in OCR2B controls the duty cycle. It must be less than the counter number. For
example, if you count to 3 (which is really a count of 4 because the 3 is zero-relative)
then for a 50% duty cycle you would want to put 1 (really a count of 2) into OCR2B.

n -- Prescale 1 -- -- Prescale 8 -- -- Prescale 64 -- -- Prescale 256 -- -- Prescale 1024--


Freq (Hz) Per (uS) Freq (Hz) Per (uS) Freq (Hz) Per (uS) Freq (Hz) Per (uS) Freq (Hz)
Per (uS)
1: 8,000,000* 0.125 1,000,000 1.000 125,000 8.000 31,250 32.000 7,813
128.000
2: 5,333,333 0.188 666,667 1.500 83,333 12.000 20,833 48.000 5,208
192.000
3: 4,000,000 0.250 500,000 2.000 62,500 16.000 15,625 64.000 3,906
256.000
4: 3,200,000 0.313 400,000 2.500 50,000 20.000 12,500 80.000 3,125
320.000
5: 2,666,667 0.375 333,333 3.000 41,667 24.000 10,417 96.000 2,604
384.000
6: 2,285,714 0.438 285,714 3.500 35,714 28.000 8,929 112.000 2,232
448.000
7: 2,000,000 0.500 250,000 4.000 31,250 32.000 7,813 128.000 1,953
512.000
8: 1,777,778 0.563 222,222 4.500 27,778 36.000 6,944 144.000 1,736
576.000
9: 1,600,000 0.625 200,000 5.000 25,000 40.000 6,250 160.000 1,563
640.000
10: 1,454,545 0.688 181,818 5.500 22,727 44.000 5,682 176.000 1,420
704.000
11: 1,333,333 0.750 166,667 6.000 20,833 48.000 5,208 192.000 1,302
768.000
12: 1,230,769 0.813 153,846 6.500 19,231 52.000 4,808 208.000 1,202
832.000
13: 1,142,857 0.875 142,857 7.000 17,857 56.000 4,464 224.000 1,116
896.000
14: 1,066,667 0.937 133,333 7.500 16,667 60.000 4,167 240.000 1,042
960.000
15: 1,000,000 1.000 125,000 8.000 15,625 64.000 3,906 256.000 977
1024.000
16: 941,176 1.063 117,647 8.500 14,706 68.000 3,676 272.000 919
1088.000
17: 888,889 1.125 111,111 9.000 13,889 72.000 3,472 288.000 868
1152.000
18: 842,105 1.187 105,263 9.500 13,158 76.000 3,289 304.000 822
1216.000
19: 800,000 1.250 100,000 10.000 12,500 80.000 3,125 320.000 781
1280.000
20: 761,905 1.313 95,238 10.500 11,905 84.000 2,976 336.000 744
1344.000
21: 727,273 1.375 90,909 11.000 11,364 88.000 2,841 352.000 710
1408.000
22: 695,652 1.438 86,957 11.500 10,870 92.000 2,717 368.000 679
1472.000
23: 666,667 1.500 83,333 12.000 10,417 96.000 2,604 384.000 651
1536.000
24: 640,000 1.562 80,000 12.500 10,000 100.000 2,500 400.000 625
1600.000
25: 615,385 1.625 76,923 13.000 9,615 104.000 2,404 416.000 601
1664.000
26: 592,593 1.688 74,074 13.500 9,259 108.000 2,315 432.000 579
1728.000
27: 571,429 1.750 71,429 14.000 8,929 112.000 2,232 448.000 558
1792.000
28: 551,724 1.813 68,966 14.500 8,621 116.000 2,155 464.000 539
1856.000
29: 533,333 1.875 66,667 15.000 8,333 120.000 2,083 480.000 521
1920.000
30: 516,129 1.938 64,516 15.500 8,065 124.000 2,016 496.000 504
1984.000
31: 500,000 2.000 62,500 16.000 7,813 128.000 1,953 512.000 488
2048.000
32: 484,848 2.062 60,606 16.500 7,576 132.000 1,894 528.000 473
2112.000
33: 470,588 2.125 58,824 17.000 7,353 136.000 1,838 544.000 460
2176.000
34: 457,143 2.188 57,143 17.500 7,143 140.000 1,786 560.000 446
2240.000
35: 444,444 2.250 55,556 18.000 6,944 144.000 1,736 576.000 434
2304.000
36: 432,432 2.313 54,054 18.500 6,757 148.000 1,689 592.000 422
2368.000
37: 421,053 2.375 52,632 19.000 6,579 152.000 1,645 608.000 411
2432.000
38: 410,256 2.438 51,282 19.500 6,410 156.000 1,603 624.000 401
2496.000
39: 400,000 2.500 50,000 20.000 6,250 160.000 1,563 640.000 391
2560.000
40: 390,244 2.563 48,780 20.500 6,098 164.000 1,524 656.000 381
2624.000
41: 380,952 2.625 47,619 21.000 5,952 168.000 1,488 672.000 372
2688.000
42: 372,093 2.687 46,512 21.500 5,814 172.000 1,453 688.000 363
2752.000
43: 363,636 2.750 45,455 22.000 5,682 176.000 1,420 704.000 355
2816.000
44: 355,556 2.812 44,444 22.500 5,556 180.000 1,389 720.000 347
2880.000
45: 347,826 2.875 43,478 23.000 5,435 184.000 1,359 736.000 340
2944.000
46: 340,426 2.938 42,553 23.500 5,319 188.000 1,330 752.000 332
3008.000
47: 333,333 3.000 41,667 24.000 5,208 192.000 1,302 768.000 326
3072.000
48: 326,531 3.063 40,816 24.500 5,102 196.000 1,276 784.000 319
3136.000
49: 320,000 3.125 40,000 25.000 5,000 200.000 1,250 800.000 313
3200.000
50: 313,725 3.188 39,216 25.500 4,902 204.000 1,225 816.000 306
3264.000
51: 307,692 3.250 38,462 26.000 4,808 208.000 1,202 832.000 300
3328.000
52: 301,887 3.313 37,736 26.500 4,717 212.000 1,179 848.000 295
3392.000
53: 296,296 3.375 37,037 27.000 4,630 216.000 1,157 864.000 289
3456.000
54: 290,909 3.437 36,364 27.500 4,545 220.000 1,136 880.000 284
3520.000
55: 285,714 3.500 35,714 28.000 4,464 224.000 1,116 896.000 279
3584.000
56: 280,702 3.562 35,088 28.500 4,386 228.000 1,096 912.000 274
3648.000
57: 275,862 3.625 34,483 29.000 4,310 232.000 1,078 928.000 269
3712.000
58: 271,186 3.688 33,898 29.500 4,237 236.000 1,059 944.000 265
3776.000
59: 266,667 3.750 33,333 30.000 4,167 240.000 1,042 960.000 260
3840.000
60: 262,295 3.813 32,787 30.500 4,098 244.000 1,025 976.000 256
3904.000
61: 258,065 3.875 32,258 31.000 4,032 248.000 1,008 992.000 252
3968.000
62: 253,968 3.938 31,746 31.500 3,968 252.000 992 1008.000 248
4032.000
63: 250,000 4.000 31,250 32.000 3,906 256.000 977 1024.000 244
4096.000
64: 246,154 4.063 30,769 32.500 3,846 260.000 962 1040.000 240
4160.000
65: 242,424 4.125 30,303 33.000 3,788 264.000 947 1056.000 237
4224.000
66: 238,806 4.188 29,851 33.500 3,731 268.000 933 1072.000 233
4288.000
67: 235,294 4.250 29,412 34.000 3,676 272.000 919 1088.000 230
4352.000
68: 231,884 4.313 28,986 34.500 3,623 276.000 906 1104.000 226
4416.000
69: 228,571 4.375 28,571 35.000 3,571 280.000 893 1120.000 223
4480.000
70: 225,352 4.437 28,169 35.500 3,521 284.000 880 1136.000 220
4544.000
71: 222,222 4.500 27,778 36.000 3,472 288.000 868 1152.000 217
4608.000
72: 219,178 4.563 27,397 36.500 3,425 292.000 856 1168.000 214
4672.000
73: 216,216 4.625 27,027 37.000 3,378 296.000 845 1184.000 211
4736.000
74: 213,333 4.688 26,667 37.500 3,333 300.000 833 1200.000 208
4800.000
75: 210,526 4.750 26,316 38.000 3,289 304.000 822 1216.000 206
4864.000
76: 207,792 4.813 25,974 38.500 3,247 308.000 812 1232.000 203
4928.000
77: 205,128 4.875 25,641 39.000 3,205 312.000 801 1248.000 200
4992.000
78: 202,532 4.938 25,316 39.500 3,165 316.000 791 1264.000 198
5056.000
79: 200,000 5.000 25,000 40.000 3,125 320.000 781 1280.000 195
5120.000
80: 197,531 5.062 24,691 40.500 3,086 324.000 772 1296.000 193
5184.000
81: 195,122 5.125 24,390 41.000 3,049 328.000 762 1312.000 191
5248.000
82: 192,771 5.188 24,096 41.500 3,012 332.000 753 1328.000 188
5312.000
83: 190,476 5.250 23,810 42.000 2,976 336.000 744 1344.000 186
5376.000
84: 188,235 5.312 23,529 42.500 2,941 340.000 735 1360.000 184
5440.000
85: 186,047 5.375 23,256 43.000 2,907 344.000 727 1376.000 182
5504.000
86: 183,908 5.438 22,989 43.500 2,874 348.000 718 1392.000 180
5568.000
87: 181,818 5.500 22,727 44.000 2,841 352.000 710 1408.000 178
5632.000
88: 179,775 5.563 22,472 44.500 2,809 356.000 702 1424.000 176
5696.000
89: 177,778 5.625 22,222 45.000 2,778 360.000 694 1440.000 174
5760.000
90: 175,824 5.687 21,978 45.500 2,747 364.000 687 1456.000 172
5824.000
91: 173,913 5.750 21,739 46.000 2,717 368.000 679 1472.000 170
5888.000
92: 172,043 5.813 21,505 46.500 2,688 372.000 672 1488.000 168
5952.000
93: 170,213 5.875 21,277 47.000 2,660 376.000 665 1504.000 166
6016.000
94: 168,421 5.937 21,053 47.500 2,632 380.000 658 1520.000 164
6080.000
95: 166,667 6.000 20,833 48.000 2,604 384.000 651 1536.000 163
6144.000
96: 164,948 6.063 20,619 48.500 2,577 388.000 644 1552.000 161
6208.000
97: 163,265 6.125 20,408 49.000 2,551 392.000 638 1568.000 159
6272.000
98: 161,616 6.188 20,202 49.500 2,525 396.000 631 1584.000 158
6336.000
99: 160,000 6.250 20,000 50.000 2,500 400.000 625 1600.000 156
6400.000
100: 158,416 6.313 19,802 50.500 2,475 404.000 619 1616.000 155
6464.000
101: 156,863 6.375 19,608 51.000 2,451 408.000 613 1632.000 153
6528.000
102: 155,340 6.438 19,417 51.500 2,427 412.000 607 1648.000 152
6592.000
103: 153,846 6.500 19,231 52.000 2,404 416.000 601 1664.000 150
6656.000
104: 152,381 6.562 19,048 52.500 2,381 420.000 595 1680.000 149
6720.000
105: 150,943 6.625 18,868 53.000 2,358 424.000 590 1696.000 147
6784.000
106: 149,533 6.688 18,692 53.500 2,336 428.000 584 1712.000 146
6848.000
107: 148,148 6.750 18,519 54.000 2,315 432.000 579 1728.000 145
6912.000
108: 146,789 6.813 18,349 54.500 2,294 436.000 573 1744.000 143
6976.000
109: 145,455 6.875 18,182 55.000 2,273 440.000 568 1760.000 142
7040.000
110: 144,144 6.938 18,018 55.500 2,252 444.000 563 1776.000 141
7104.000
111: 142,857 7.000 17,857 56.000 2,232 448.000 558 1792.000 140
7168.000
112: 141,593 7.063 17,699 56.500 2,212 452.000 553 1808.000 138
7232.000
113: 140,351 7.125 17,544 57.000 2,193 456.000 548 1824.000 137
7296.000
114: 139,130 7.187 17,391 57.500 2,174 460.000 543 1840.000 136
7360.000
115: 137,931 7.250 17,241 58.000 2,155 464.000 539 1856.000 135
7424.000
116: 136,752 7.313 17,094 58.500 2,137 468.000 534 1872.000 134
7488.000
117: 135,593 7.375 16,949 59.000 2,119 472.000 530 1888.000 132
7552.000
118: 134,454 7.437 16,807 59.500 2,101 476.000 525 1904.000 131
7616.000
119: 133,333 7.500 16,667 60.000 2,083 480.000 521 1920.000 130
7680.000
120: 132,231 7.563 16,529 60.500 2,066 484.000 517 1936.000 129
7744.000
121: 131,148 7.625 16,393 61.000 2,049 488.000 512 1952.000 128
7808.000
122: 130,081 7.687 16,260 61.500 2,033 492.000 508 1968.000 127
7872.000
123: 129,032 7.750 16,129 62.000 2,016 496.000 504 1984.000 126
7936.000
124: 128,000 7.813 16,000 62.500 2,000 500.000 500 2000.000 125
8000.000
125: 126,984 7.875 15,873 63.000 1,984 504.000 496 2016.000 124
8064.000
126: 125,984 7.938 15,748 63.500 1,969 508.000 492 2032.000 123
8128.000
127: 125,000 8.000 15,625 64.000 1,953 512.000 488 2048.000 122
8192.000
128: 124,031 8.063 15,504 64.500 1,938 516.000 484 2064.000 121
8256.000
129: 123,077 8.125 15,385 65.000 1,923 520.000 481 2080.000 120
8320.000
130: 122,137 8.188 15,267 65.500 1,908 524.000 477 2096.000 119
8384.000
131: 121,212 8.250 15,152 66.000 1,894 528.000 473 2112.000 118
8448.000
132: 120,301 8.313 15,038 66.500 1,880 532.000 470 2128.000 117
8512.000
133: 119,403 8.375 14,925 67.000 1,866 536.000 466 2144.000 117
8576.000
134: 118,519 8.438 14,815 67.500 1,852 540.000 463 2160.000 116
8640.000
135: 117,647 8.500 14,706 68.000 1,838 544.000 460 2176.000 115
8704.000
136: 116,788 8.563 14,599 68.500 1,825 548.000 456 2192.000 114
8768.000
137: 115,942 8.625 14,493 69.000 1,812 552.000 453 2208.000 113
8832.000
138: 115,108 8.688 14,388 69.500 1,799 556.000 450 2224.000 112
8896.000
139: 114,286 8.750 14,286 70.000 1,786 560.000 446 2240.000 112
8960.000
140: 113,475 8.812 14,184 70.500 1,773 564.000 443 2256.000 111
9024.000
141: 112,676 8.875 14,085 71.000 1,761 568.000 440 2272.000 110
9088.000
142: 111,888 8.938 13,986 71.500 1,748 572.000 437 2288.000 109
9152.000
143: 111,111 9.000 13,889 72.000 1,736 576.000 434 2304.000 109
9216.000
144: 110,345 9.063 13,793 72.500 1,724 580.000 431 2320.000 108
9280.000
145: 109,589 9.125 13,699 73.000 1,712 584.000 428 2336.000 107
9344.000
146: 108,844 9.188 13,605 73.500 1,701 588.000 425 2352.000 106
9408.000
147: 108,108 9.250 13,514 74.000 1,689 592.000 422 2368.000 106
9472.000
148: 107,383 9.313 13,423 74.500 1,678 596.000 419 2384.000 105
9536.000
149: 106,667 9.375 13,333 75.000 1,667 600.000 417 2400.000 104
9600.000
150: 105,960 9.437 13,245 75.500 1,656 604.000 414 2416.000 103
9664.000
151: 105,263 9.500 13,158 76.000 1,645 608.000 411 2432.000 103
9728.000
152: 104,575 9.563 13,072 76.500 1,634 612.000 408 2448.000 102
9792.000
153: 103,896 9.625 12,987 77.000 1,623 616.000 406 2464.000 101
9856.000
154: 103,226 9.688 12,903 77.500 1,613 620.000 403 2480.000 101
9920.000
155: 102,564 9.750 12,821 78.000 1,603 624.000 401 2496.000 100
9984.000
156: 101,911 9.813 12,739 78.500 1,592 628.000 398 2512.000 100
10048.000
157: 101,266 9.875 12,658 79.000 1,582 632.000 396 2528.000 99
10112.000
158: 100,629 9.938 12,579 79.500 1,572 636.000 393 2544.000 98
10176.000
159: 100,000 10.000 12,500 80.000 1,563 640.000 391 2560.000 98
10240.000
160: 99,379 10.062 12,422 80.500 1,553 644.000 388 2576.000 97
10304.000
161: 98,765 10.125 12,346 81.000 1,543 648.000 386 2592.000 96
10368.000
162: 98,160 10.188 12,270 81.500 1,534 652.000 383 2608.000 96
10432.000
163: 97,561 10.250 12,195 82.000 1,524 656.000 381 2624.000 95
10496.000
164: 96,970 10.313 12,121 82.500 1,515 660.000 379 2640.000 95
10560.000
165: 96,386 10.375 12,048 83.000 1,506 664.000 377 2656.000 94
10624.000
166: 95,808 10.438 11,976 83.500 1,497 668.000 374 2672.000 94
10688.000
167: 95,238 10.500 11,905 84.000 1,488 672.000 372 2688.000 93
10752.000
168: 94,675 10.563 11,834 84.500 1,479 676.000 370 2704.000 92
10816.000
169: 94,118 10.625 11,765 85.000 1,471 680.000 368 2720.000 92
10880.000
170: 93,567 10.687 11,696 85.500 1,462 684.000 365 2736.000 91
10944.000
171: 93,023 10.750 11,628 86.000 1,453 688.000 363 2752.000 91
11008.000
172: 92,486 10.813 11,561 86.500 1,445 692.000 361 2768.000 90
11072.000
173: 91,954 10.875 11,494 87.000 1,437 696.000 359 2784.000 90
11136.000
174: 91,429 10.938 11,429 87.500 1,429 700.000 357 2800.000 89
11200.000
175: 90,909 11.000 11,364 88.000 1,420 704.000 355 2816.000 89
11264.000
176: 90,395 11.063 11,299 88.500 1,412 708.000 353 2832.000 88
11328.000
177: 89,888 11.125 11,236 89.000 1,404 712.000 351 2848.000 88
11392.000
178: 89,385 11.188 11,173 89.500 1,397 716.000 349 2864.000 87
11456.000
179: 88,889 11.250 11,111 90.000 1,389 720.000 347 2880.000 87
11520.000
180: 88,398 11.312 11,050 90.500 1,381 724.000 345 2896.000 86
11584.000
181: 87,912 11.375 10,989 91.000 1,374 728.000 343 2912.000 86
11648.000
182: 87,432 11.438 10,929 91.500 1,366 732.000 342 2928.000 85
11712.000
183: 86,957 11.500 10,870 92.000 1,359 736.000 340 2944.000 85
11776.000
184: 86,486 11.563 10,811 92.500 1,351 740.000 338 2960.000 84
11840.000
185: 86,022 11.625 10,753 93.000 1,344 744.000 336 2976.000 84
11904.000
186: 85,561 11.688 10,695 93.500 1,337 748.000 334 2992.000 84
11968.000
187: 85,106 11.750 10,638 94.000 1,330 752.000 332 3008.000 83
12032.000
188: 84,656 11.813 10,582 94.500 1,323 756.000 331 3024.000 83
12096.000
189: 84,211 11.875 10,526 95.000 1,316 760.000 329 3040.000 82
12160.000
190: 83,770 11.937 10,471 95.500 1,309 764.000 327 3056.000 82
12224.000
191: 83,333 12.000 10,417 96.000 1,302 768.000 326 3072.000 81
12288.000
192: 82,902 12.063 10,363 96.500 1,295 772.000 324 3088.000 81
12352.000
193: 82,474 12.125 10,309 97.000 1,289 776.000 322 3104.000 81
12416.000
194: 82,051 12.188 10,256 97.500 1,282 780.000 321 3120.000 80
12480.000
195: 81,633 12.250 10,204 98.000 1,276 784.000 319 3136.000 80
12544.000
196: 81,218 12.313 10,152 98.500 1,269 788.000 317 3152.000 79
12608.000
197: 80,808 12.375 10,101 99.000 1,263 792.000 316 3168.000 79
12672.000
198: 80,402 12.437 10,050 99.500 1,256 796.000 314 3184.000 79
12736.000
199: 80,000 12.500 10,000 100.000 1,250 800.000 313 3200.000 78
12800.000
200: 79,602 12.562 9,950 100.500 1,244 804.000 311 3216.000 78
12864.000
201: 79,208 12.625 9,901 101.000 1,238 808.000 309 3232.000 77
12928.000
202: 78,818 12.688 9,852 101.500 1,232 812.000 308 3248.000 77
12992.000
203: 78,431 12.750 9,804 102.000 1,225 816.000 306 3264.000 77
13056.000
204: 78,049 12.813 9,756 102.500 1,220 820.000 305 3280.000 76
13120.000
205: 77,670 12.875 9,709 103.000 1,214 824.000 303 3296.000 76
13184.000
206: 77,295 12.938 9,662 103.500 1,208 828.000 302 3312.000 75
13248.000
207: 76,923 13.000 9,615 104.000 1,202 832.000 300 3328.000 75
13312.000
208: 76,555 13.062 9,569 104.500 1,196 836.000 299 3344.000 75
13376.000
209: 76,190 13.125 9,524 105.000 1,190 840.000 298 3360.000 74
13440.000
210: 75,829 13.187 9,479 105.500 1,185 844.000 296 3376.000 74
13504.000
211: 75,472 13.250 9,434 106.000 1,179 848.000 295 3392.000 74
13568.000
212: 75,117 13.313 9,390 106.500 1,174 852.000 293 3408.000 73
13632.000
213: 74,766 13.375 9,346 107.000 1,168 856.000 292 3424.000 73
13696.000
214: 74,419 13.438 9,302 107.500 1,163 860.000 291 3440.000 73
13760.000
215: 74,074 13.500 9,259 108.000 1,157 864.000 289 3456.000 72
13824.000
216: 73,733 13.563 9,217 108.500 1,152 868.000 288 3472.000 72
13888.000
217: 73,394 13.625 9,174 109.000 1,147 872.000 287 3488.000 72
13952.000
218: 73,059 13.687 9,132 109.500 1,142 876.000 285 3504.000 71
14016.000
219: 72,727 13.750 9,091 110.000 1,136 880.000 284 3520.000 71
14080.000
220: 72,398 13.812 9,050 110.500 1,131 884.000 283 3536.000 71
14144.000
221: 72,072 13.875 9,009 111.000 1,126 888.000 282 3552.000 70
14208.000
222: 71,749 13.938 8,969 111.500 1,121 892.000 280 3568.000 70
14272.000
223: 71,429 14.000 8,929 112.000 1,116 896.000 279 3584.000 70
14336.000
224: 71,111 14.063 8,889 112.500 1,111 900.000 278 3600.000 69
14400.000
225: 70,796 14.125 8,850 113.000 1,106 904.000 277 3616.000 69
14464.000
226: 70,485 14.188 8,811 113.500 1,101 908.000 275 3632.000 69
14528.000
227: 70,175 14.250 8,772 114.000 1,096 912.000 274 3648.000 69
14592.000
228: 69,869 14.312 8,734 114.500 1,092 916.000 273 3664.000 68
14656.000
229: 69,565 14.375 8,696 115.000 1,087 920.000 272 3680.000 68
14720.000
230: 69,264 14.437 8,658 115.500 1,082 924.000 271 3696.000 68
14784.000
231: 68,966 14.500 8,621 116.000 1,078 928.000 269 3712.000 67
14848.000
232: 68,670 14.563 8,584 116.500 1,073 932.000 268 3728.000 67
14912.000
233: 68,376 14.625 8,547 117.000 1,068 936.000 267 3744.000 67
14976.000
234: 68,085 14.688 8,511 117.500 1,064 940.000 266 3760.000 66
15040.000
235: 67,797 14.750 8,475 118.000 1,059 944.000 265 3776.000 66
15104.000
236: 67,511 14.813 8,439 118.500 1,055 948.000 264 3792.000 66
15168.000
237: 67,227 14.875 8,403 119.000 1,050 952.000 263 3808.000 66
15232.000
238: 66,946 14.937 8,368 119.500 1,046 956.000 262 3824.000 65
15296.000
239: 66,667 15.000 8,333 120.000 1,042 960.000 260 3840.000 65
15360.000
240: 66,390 15.062 8,299 120.500 1,037 964.000 259 3856.000 65
15424.000
241: 66,116 15.125 8,264 121.000 1,033 968.000 258 3872.000 65
15488.000
242: 65,844 15.188 8,230 121.500 1,029 972.000 257 3888.000 64
15552.000
243: 65,574 15.250 8,197 122.000 1,025 976.000 256 3904.000 64
15616.000
244: 65,306 15.313 8,163 122.500 1,020 980.000 255 3920.000 64
15680.000
245: 65,041 15.375 8,130 123.000 1,016 984.000 254 3936.000 64
15744.000
246: 64,777 15.438 8,097 123.500 1,012 988.000 253 3952.000 63
15808.000
247: 64,516 15.500 8,065 124.000 1,008 992.000 252 3968.000 63
15872.000
248: 64,257 15.562 8,032 124.500 1,004 996.000 251 3984.000 63
15936.000
249: 64,000 15.625 8,000 125.000 1,000 1000.000 250 4000.000 63
16000.000
250: 63,745 15.687 7,968 125.500 996 1004.000 249 4016.000 62
16064.000
251: 63,492 15.750 7,937 126.000 992 1008.000 248 4032.000 62
16128.000
252: 63,241 15.812 7,905 126.500 988 1012.000 247 4048.000 62
16192.000
253: 62,992 15.875 7,874 127.000 984 1016.000 246 4064.000 62
16256.000
254: 62,745 15.937 7,843 127.500 980 1020.000 245 4080.000 61
16320.000
255: 62,500 16.000 7,813 128.000 977 1024.000 244 4096.000 61
16384.000

Example code which uses a prescaler of one (no prescaler):

const byte OUTPUT_PIN = 3; // Timer 2 "B" output: OC2B

const byte n = 224; // for example, 71.111 kHz

void setup()
{
pinMode (OUTPUT_PIN, OUTPUT);

TCCR2A = bit (WGM20) | bit (WGM21) | bit (COM2B1); // fast PWM, clear OC2A on
compare
TCCR2B = bit (WGM22) | bit (CS20); // fast PWM, no prescaler
OCR2A = n; // from table
OCR2B = ((n + 1) / 2) - 1; // 50% duty cycle
} // end of setup

void loop() { }

Example code which uses a prescaler of 8:

const byte OUTPUT_PIN = 3; // Timer 2 "B" output: OC2B

const byte n = 224; // for example, 8.89 kHz

void setup()
{
pinMode (OUTPUT_PIN, OUTPUT);

TCCR2A = bit (WGM20) | bit (WGM21) | bit (COM2B1); // fast PWM, clear OC2A on
compare
TCCR2B = bit (WGM22) | bit (CS21); // fast PWM, no prescaler
OCR2A = n; // from table
OCR2B = ((n + 1) / 2) - 1; // 50% duty cycle
} // end of setup

void loop() { }

Example code which uses a prescaler of 64:

const byte OUTPUT_PIN = 3; // Timer 2 "B" output: OC2B

const byte n = 224; // for example, 1.111 kHz

void setup()
{
pinMode (OUTPUT_PIN, OUTPUT);
TCCR2A = bit (WGM20) | bit (WGM21) | bit (COM2B1); // fast PWM, clear OC2A on
compare
TCCR2B = bit (WGM22) | bit (CS22); // fast PWM, prescaler of 64
OCR2A = n; // from table
OCR2B = ((n + 1) / 2) - 1; // 50% duty cycle
} // end of setup

void loop() { }

Example code which uses a prescaler of 256:

const byte OUTPUT_PIN = 3; // Timer 2 "B" output: OC2B

const byte n = 224; // for example, 278 Hz

void setup()
{
pinMode (OUTPUT_PIN, OUTPUT);

TCCR2A = bit (WGM20) | bit (WGM21) | bit (COM2B1); // fast PWM, clear OC2A on
compare
TCCR2B = bit (WGM22) | bit (CS21) | bit (CS22); // fast PWM, prescaler of 256
OCR2A = n; // from table
OCR2B = ((n + 1) / 2) - 1; // 50% duty cycle
} // end of setup

void loop() { }

Example code which uses a prescaler of 1024:

const byte OUTPUT_PIN = 3; // Timer 2 "B" output: OC2B

const byte n = 224; // for example, 69 Hz

void setup()
{
pinMode (OUTPUT_PIN, OUTPUT);

TCCR2A = bit (WGM20) | bit (WGM21) | bit (COM2B1); // fast PWM, clear OC2A on
compare
TCCR2B = bit (WGM22) | bit (CS20) | bit (CS21) | bit (CS22); // fast PWM, prescaler
of 1024
OCR2A = n; // from table
OCR2B = ((n + 1) / 2) - 1; // 50% duty cycle
} // end of setup

void loop() { }

Additional frequencies and periods for Timer 2

Timer 2 also offers the prescalers of 32 and 128. On timers 0 and 1 these "clock source"
settings are used for an external clock (rising or falling edge).

n -- Prescale 32 -- -- Prescale 128 --


Freq (Hz) Per (uS) Freq (Hz) Per (uS)
1: 250,000 4.000 62,500 16.000
2: 166,667 6.000 41,667 24.000
3: 125,000 8.000 31,250 32.000
4: 100,000 10.000 25,000 40.000
5: 83,333 12.000 20,833 48.000
6: 71,429 14.000 17,857 56.000
7: 62,500 16.000 15,625 64.000
8: 55,556 18.000 13,889 72.000
9: 50,000 20.000 12,500 80.000
10: 45,455 22.000 11,364 88.000
11: 41,667 24.000 10,417 96.000
12: 38,462 26.000 9,615 104.000
13: 35,714 28.000 8,929 112.000
14: 33,333 30.000 8,333 120.000
15: 31,250 32.000 7,813 128.000
16: 29,412 34.000 7,353 136.000
17: 27,778 36.000 6,944 144.000
18: 26,316 38.000 6,579 152.000
19: 25,000 40.000 6,250 160.000
20: 23,810 42.000 5,952 168.000
21: 22,727 44.000 5,682 176.000
22: 21,739 46.000 5,435 184.000
23: 20,833 48.000 5,208 192.000
24: 20,000 50.000 5,000 200.000
25: 19,231 52.000 4,808 208.000
26: 18,519 54.000 4,630 216.000
27: 17,857 56.000 4,464 224.000
28: 17,241 58.000 4,310 232.000
29: 16,667 60.000 4,167 240.000
30: 16,129 62.000 4,032 248.000
31: 15,625 64.000 3,906 256.000
32: 15,152 66.000 3,788 264.000
33: 14,706 68.000 3,676 272.000
34: 14,286 70.000 3,571 280.000
35: 13,889 72.000 3,472 288.000
36: 13,514 74.000 3,378 296.000
37: 13,158 76.000 3,289 304.000
38: 12,821 78.000 3,205 312.000
39: 12,500 80.000 3,125 320.000
40: 12,195 82.000 3,049 328.000
41: 11,905 84.000 2,976 336.000
42: 11,628 86.000 2,907 344.000
43: 11,364 88.000 2,841 352.000
44: 11,111 90.000 2,778 360.000
45: 10,870 92.000 2,717 368.000
46: 10,638 94.000 2,660 376.000
47: 10,417 96.000 2,604 384.000
48: 10,204 98.000 2,551 392.000
49: 10,000 100.000 2,500 400.000
50: 9,804 102.000 2,451 408.000
51: 9,615 104.000 2,404 416.000
52: 9,434 106.000 2,358 424.000
53: 9,259 108.000 2,315 432.000
54: 9,091 110.000 2,273 440.000
55: 8,929 112.000 2,232 448.000
56: 8,772 114.000 2,193 456.000
57: 8,621 116.000 2,155 464.000
58: 8,475 118.000 2,119 472.000
59: 8,333 120.000 2,083 480.000
60: 8,197 122.000 2,049 488.000
61: 8,065 124.000 2,016 496.000
62: 7,937 126.000 1,984 504.000
63: 7,813 128.000 1,953 512.000
64: 7,692 130.000 1,923 520.000
65: 7,576 132.000 1,894 528.000
66: 7,463 134.000 1,866 536.000
67: 7,353 136.000 1,838 544.000
68: 7,246 138.000 1,812 552.000
69: 7,143 140.000 1,786 560.000
70: 7,042 142.000 1,761 568.000
71: 6,944 144.000 1,736 576.000
72: 6,849 146.000 1,712 584.000
73: 6,757 148.000 1,689 592.000
74: 6,667 150.000 1,667 600.000
75: 6,579 152.000 1,645 608.000
76: 6,494 154.000 1,623 616.000
77: 6,410 156.000 1,603 624.000
78: 6,329 158.000 1,582 632.000
79: 6,250 160.000 1,563 640.000
80: 6,173 162.000 1,543 648.000
81: 6,098 164.000 1,524 656.000
82: 6,024 166.000 1,506 664.000
83: 5,952 168.000 1,488 672.000
84: 5,882 170.000 1,471 680.000
85: 5,814 172.000 1,453 688.000
86: 5,747 174.000 1,437 696.000
87: 5,682 176.000 1,420 704.000
88: 5,618 178.000 1,404 712.000
89: 5,556 180.000 1,389 720.000
90: 5,495 182.000 1,374 728.000
91: 5,435 184.000 1,359 736.000
92: 5,376 186.000 1,344 744.000
93: 5,319 188.000 1,330 752.000
94: 5,263 190.000 1,316 760.000
95: 5,208 192.000 1,302 768.000
96: 5,155 194.000 1,289 776.000
97: 5,102 196.000 1,276 784.000
98: 5,051 198.000 1,263 792.000
99: 5,000 200.000 1,250 800.000
100: 4,950 202.000 1,238 808.000
101: 4,902 204.000 1,225 816.000
102: 4,854 206.000 1,214 824.000
103: 4,808 208.000 1,202 832.000
104: 4,762 210.000 1,190 840.000
105: 4,717 212.000 1,179 848.000
106: 4,673 214.000 1,168 856.000
107: 4,630 216.000 1,157 864.000
108: 4,587 218.000 1,147 872.000
109: 4,545 220.000 1,136 880.000
110: 4,505 222.000 1,126 888.000
111: 4,464 224.000 1,116 896.000
112: 4,425 226.000 1,106 904.000
113: 4,386 228.000 1,096 912.000
114: 4,348 230.000 1,087 920.000
115: 4,310 232.000 1,078 928.000
116: 4,274 234.000 1,068 936.000
117: 4,237 236.000 1,059 944.000
118: 4,202 238.000 1,050 952.000
119: 4,167 240.000 1,042 960.000
120: 4,132 242.000 1,033 968.000
121: 4,098 244.000 1,025 976.000
122: 4,065 246.000 1,016 984.000
123: 4,032 248.000 1,008 992.000
124: 4,000 250.000 1,000 1000.000
125: 3,968 252.000 992 1008.000
126: 3,937 254.000 984 1016.000
127: 3,906 256.000 977 1024.000
128: 3,876 258.000 969 1032.000
129: 3,846 260.000 962 1040.000
130: 3,817 262.000 954 1048.000
131: 3,788 264.000 947 1056.000
132: 3,759 266.000 940 1064.000
133: 3,731 268.000 933 1072.000
134: 3,704 270.000 926 1080.000
135: 3,676 272.000 919 1088.000
136: 3,650 274.000 912 1096.000
137: 3,623 276.000 906 1104.000
138: 3,597 278.000 899 1112.000
139: 3,571 280.000 893 1120.000
140: 3,546 282.000 887 1128.000
141: 3,521 284.000 880 1136.000
142: 3,497 286.000 874 1144.000
143: 3,472 288.000 868 1152.000
144: 3,448 290.000 862 1160.000
145: 3,425 292.000 856 1168.000
146: 3,401 294.000 850 1176.000
147: 3,378 296.000 845 1184.000
148: 3,356 298.000 839 1192.000
149: 3,333 300.000 833 1200.000
150: 3,311 302.000 828 1208.000
151: 3,289 304.000 822 1216.000
152: 3,268 306.000 817 1224.000
153: 3,247 308.000 812 1232.000
154: 3,226 310.000 806 1240.000
155: 3,205 312.000 801 1248.000
156: 3,185 314.000 796 1256.000
157: 3,165 316.000 791 1264.000
158: 3,145 318.000 786 1272.000
159: 3,125 320.000 781 1280.000
160: 3,106 322.000 776 1288.000
161: 3,086 324.000 772 1296.000
162: 3,067 326.000 767 1304.000
163: 3,049 328.000 762 1312.000
164: 3,030 330.000 758 1320.000
165: 3,012 332.000 753 1328.000
166: 2,994 334.000 749 1336.000
167: 2,976 336.000 744 1344.000
168: 2,959 338.000 740 1352.000
169: 2,941 340.000 735 1360.000
170: 2,924 342.000 731 1368.000
171: 2,907 344.000 727 1376.000
172: 2,890 346.000 723 1384.000
173: 2,874 348.000 718 1392.000
174: 2,857 350.000 714 1400.000
175: 2,841 352.000 710 1408.000
176: 2,825 354.000 706 1416.000
177: 2,809 356.000 702 1424.000
178: 2,793 358.000 698 1432.000
179: 2,778 360.000 694 1440.000
180: 2,762 362.000 691 1448.000
181: 2,747 364.000 687 1456.000
182: 2,732 366.000 683 1464.000
183: 2,717 368.000 679 1472.000
184: 2,703 370.000 676 1480.000
185: 2,688 372.000 672 1488.000
186: 2,674 374.000 668 1496.000
187: 2,660 376.000 665 1504.000
188: 2,646 378.000 661 1512.000
189: 2,632 380.000 658 1520.000
190: 2,618 382.000 654 1528.000
191: 2,604 384.000 651 1536.000
192: 2,591 386.000 648 1544.000
193: 2,577 388.000 644 1552.000
194: 2,564 390.000 641 1560.000
195: 2,551 392.000 638 1568.000
196: 2,538 394.000 635 1576.000
197: 2,525 396.000 631 1584.000
198: 2,513 398.000 628 1592.000
199: 2,500 400.000 625 1600.000
200: 2,488 402.000 622 1608.000
201: 2,475 404.000 619 1616.000
202: 2,463 406.000 616 1624.000
203: 2,451 408.000 613 1632.000
204: 2,439 410.000 610 1640.000
205: 2,427 412.000 607 1648.000
206: 2,415 414.000 604 1656.000
207: 2,404 416.000 601 1664.000
208: 2,392 418.000 598 1672.000
209: 2,381 420.000 595 1680.000
210: 2,370 422.000 592 1688.000
211: 2,358 424.000 590 1696.000
212: 2,347 426.000 587 1704.000
213: 2,336 428.000 584 1712.000
214: 2,326 430.000 581 1720.000
215: 2,315 432.000 579 1728.000
216: 2,304 434.000 576 1736.000
217: 2,294 436.000 573 1744.000
218: 2,283 438.000 571 1752.000
219: 2,273 440.000 568 1760.000
220: 2,262 442.000 566 1768.000
221: 2,252 444.000 563 1776.000
222: 2,242 446.000 561 1784.000
223: 2,232 448.000 558 1792.000
224: 2,222 450.000 556 1800.000
225: 2,212 452.000 553 1808.000
226: 2,203 454.000 551 1816.000
227: 2,193 456.000 548 1824.000
228: 2,183 458.000 546 1832.000
229: 2,174 460.000 543 1840.000
230: 2,165 462.000 541 1848.000
231: 2,155 464.000 539 1856.000
232: 2,146 466.000 536 1864.000
233: 2,137 468.000 534 1872.000
234: 2,128 470.000 532 1880.000
235: 2,119 472.000 530 1888.000
236: 2,110 474.000 527 1896.000
237: 2,101 476.000 525 1904.000
238: 2,092 478.000 523 1912.000
239: 2,083 480.000 521 1920.000
240: 2,075 482.000 519 1928.000
241: 2,066 484.000 517 1936.000
242: 2,058 486.000 514 1944.000
243: 2,049 488.000 512 1952.000
244: 2,041 490.000 510 1960.000
245: 2,033 492.000 508 1968.000
246: 2,024 494.000 506 1976.000
247: 2,016 496.000 504 1984.000
248: 2,008 498.000 502 1992.000
249: 2,000 500.000 500 2000.000
250: 1,992 502.000 498 2008.000
251: 1,984 504.000 496 2016.000
252: 1,976 506.000 494 2024.000
253: 1,969 508.000 492 2032.000
254: 1,961 510.000 490 2040.000
255: 1,953 512.000 488 2048.000

Example code which uses a prescaler of 32:

const byte OUTPUT_PIN = 3; // Timer 2 "B" output: OC2B

const byte n = 224; // for example, 2.222 kHz

void setup()
{
pinMode (OUTPUT_PIN, OUTPUT);

TCCR2A = bit (WGM20) | bit (WGM21) | bit (COM2B1); // fast PWM, clear OC2A on
compare
TCCR2B = bit (WGM22) | bit (CS20) | bit (CS21); // fast PWM, prescaler of 32
OCR2A = n; // from table
OCR2B = ((n + 1) / 2) - 1; // 50% duty cycle
} // end of setup

void loop() { }

Example code which uses a prescaler of 128:

const byte OUTPUT_PIN = 3; // Timer 2 "B" output: OC2B

const byte n = 224; // for example, 556 Hz

void setup()
{
pinMode (OUTPUT_PIN, OUTPUT);

TCCR2A = bit (WGM20) | bit (WGM21) | bit (COM2B1); // fast PWM, clear OC2A on
compare
TCCR2B = bit (WGM22) | bit (CS20) | bit (CS22); // fast PWM, prescaler of 128
OCR2A = n; // from table
OCR2B = ((n + 1) / 2) - 1; // 50% duty cycle
} // end of setup

void loop() { }
Attiny85 example

The code below was developed in answer to a question on the Arduino forum. It shows
how you can have 3 x PWM outputs on an Attiny85 chip:

// For Attiny85
// Author: Nick Gammon
// Date: 29 November 2012

void setup()
{
pinMode (0, OUTPUT); // chip pin 5 // OC0A - Timer 0 "A"
pinMode (1, OUTPUT); // chip pin 6 // OC0B - Timer 0 "B"
pinMode (4, OUTPUT); // chip pin 3 // OC1B - Timer 1 "B"

// Timer 0, A side
TCCR0A = bit (WGM00) | bit (WGM01) | bit (COM0A1); // fast PWM, clear OC0A on
compare
TCCR0B = bit (CS00); // fast PWM, top at 0xFF, no prescaler
OCR0A = 127; // duty cycle (50%)

// Timer 0, B side
TCCR0A |= bit (COM0B1); // clear OC0B on compare
OCR0B = 63; // duty cycle (25%)

// Timer 1
TCCR1 = bit (CS10); // no prescaler
GTCCR = bit (COM1B1) | bit (PWM1B); // clear OC1B on compare
OCR1B = 31; // duty cycle (25%)
OCR1C = 127; // frequency
} // end of setup

void loop() { }

Timer 0 is set as fast PWM, counting up to 0xFF (255). Timer 1 is also PWM, counting up
to 127 (OCR1C). This means you can adjust the frequency of Timer 1.

Logic analyzer output on a processor running at 8 MHz:


Asynchronous timer example
You can clock timer 2 "asynchronously". What this means is, that if you use the internal
oscillator for the processor (ie. run at 8 MHz) then the clock input pins (XTAL1 and XTAL1,
which are pins 9 and 10 on the chip) can have a different crystal on them, as a clock
input. For example, a 32.768 kHz "clock" crystal.

The advantage of a 32.768 crystal is that, by dividing it by 32768, you get exactly one
second per timer firing (less or more by playing with the timer counter interval).

This lets you sleep for an accurate interval (more accurate than the watchdog timer), and
indeed, a long interval, like 8 seconds.

Whilst asleep, the processor uses very little power. In the example sketch I measured
1.46 A current consumption, when the output was LOW, if running from 5V power
supply, and 1.1 A if running from 3.3V power supply.

#include <avr/sleep.h>
#include <avr/power.h>

const byte tick = 3;

// interrupt on Timer 2 compare "A" completion - does nothing


EMPTY_INTERRUPT (TIMER2_COMPA_vect);

void setup()
{
pinMode (tick, OUTPUT);

// clock input to timer 2 from XTAL1/XTAL2


ASSR = bit (AS2);

// set up timer 2 to count up to 32 * 1024 (32768)


TCCR2A = bit (WGM21); // CTC
TCCR2B = bit (CS20) | bit (CS21) | bit (CS22); // Prescaler of 1024
OCR2A = 31; // count to 32 (zero-relative)

// enable timer interrupts


TIMSK2 |= bit (OCIE2A);

// disable ADC
ADCSRA = 0;

// turn off everything we can


power_adc_disable ();
power_spi_disable();
power_twi_disable();
power_timer0_disable();
power_timer1_disable();
power_usart0_disable();

// full power-down doesn't respond to Timer 2


set_sleep_mode (SLEEP_MODE_PWR_SAVE);

// get ready ...


sleep_enable();

} // end of setup

void loop()
{

// turn off brown-out enable in software


MCUCR = bit (BODS) | bit (BODSE);
MCUCR = bit (BODS);

// sleep, finally!
sleep_cpu ();

// we awoke! pulse the clock hand


digitalWrite (tick, ! digitalRead (tick));

} // end of loop
Tone library for timers
The small library below simplifies generating tones with the hardware timers. Unlike the
"Tone" library that comes with the Arduino this one directly uses the outputting
capability of the hardware timers, and thus does not use interrupts.

http://www.gammon.com.au/Arduino/TonePlayer.zip

Example of use on the Uno:

#include <TonePlayer.h>

TonePlayer tone1 (TCCR1A, TCCR1B, OCR1AH, OCR1AL, TCNT1H, TCNT1L); // pin D9


(Uno), D11 (Mega)

void setup()
{
pinMode (9, OUTPUT); // output pin is fixed (OC1A)

tone1.tone (220); // 220 Hz


delay (500);
tone1.noTone ();

tone1.tone (440);
delay (500);
tone1.noTone ();

tone1.tone (880);
delay (500);
tone1.noTone ();
}

void loop() { }

The library is written for the 16-bit timers, and supports Timer 1 on the Atmega328, and
Timers 1, 3, 4, 5 on the Atmega2560. Comments inside the library show how to set up
the other timers.
Timing an interval using the input capture unit
The code below is a modified version of the sketch above (in reply #1) that calculates a
frequency by inverting the period.

In other words, it can be used to time the interval between two consecutive pulses.

This one uses the "input capture" input to capture the value in Timer 1 at the moment an
event occurs. Since the hardware captures the timer value in a separate register, this
eliminates the delay caused by entering the interrupt routine (itself around 2 S).

// Frequency timer using input capture unit


// Author: Nick Gammon
// Date: 31 August 2013

// Input: Pin D8

volatile boolean first;


volatile boolean triggered;
volatile unsigned long overflowCount;
volatile unsigned long startTime;
volatile unsigned long finishTime;

// timer overflows (every 65536 counts)


ISR (TIMER1_OVF_vect)
{
overflowCount++;
} // end of TIMER1_OVF_vect

ISR (TIMER1_CAPT_vect)
{
// grab counter value before it changes any more
unsigned int timer1CounterValue;
timer1CounterValue = ICR1; // see datasheet, page 117 (accessing 16-bit registers)
unsigned long overflowCopy = overflowCount;

// if just missed an overflow


if ((TIFR1 & bit (TOV1)) && timer1CounterValue < 0x7FFF)
overflowCopy++;

// wait until we noticed last one


if (triggered)
return;

if (first)
{
startTime = (overflowCopy << 16) + timer1CounterValue;
first = false;
return;
}

finishTime = (overflowCopy << 16) + timer1CounterValue;


triggered = true;
TIMSK1 = 0; // no more interrupts for now
} // end of TIMER1_CAPT_vect

void prepareForInterrupts ()
{
noInterrupts (); // protected code
first = true;
triggered = false; // re-arm for next time
// reset Timer 1
TCCR1A = 0;
TCCR1B = 0;

TIFR1 = bit (ICF1) | bit (TOV1); // clear flags so we don't get a bogus interrupt
TCNT1 = 0; // Counter to zero
overflowCount = 0; // Therefore no overflows yet

// Timer 1 - counts clock pulses


TIMSK1 = bit (TOIE1) | bit (ICIE1); // interrupt on Timer 1 overflow and input capture
// start Timer 1, no prescaler
TCCR1B = bit (CS10) | bit (ICES1); // plus Input Capture Edge Select (rising on D8)
interrupts ();
} // end of prepareForInterrupts

void setup ()
{
Serial.begin(115200);
Serial.println("Frequency Counter");
// set up for interrupts
prepareForInterrupts ();
} // end of setup

void loop ()
{
// wait till we have a reading
if (!triggered)
return;

// period is elapsed time


unsigned long elapsedTime = finishTime - startTime;
// frequency is inverse of period, adjusted for clock period
float freq = F_CPU / float (elapsedTime); // each tick is 62.5 nS at 16 MHz

Serial.print ("Took: ");


Serial.print (elapsedTime);
Serial.print (" counts. ");

Serial.print ("Frequency: ");


Serial.print (freq);
Serial.println (" Hz. ");

// so we can read it
delay (500);

prepareForInterrupts ();
} // end of loop

The above code successfully counted a 200 kHz input. Output:

Took: 80 counts. Frequency: 200000.00 Hz.


Took: 80 counts. Frequency: 200000.00 Hz.
Took: 80 counts. Frequency: 200000.00 Hz.
Took: 80 counts. Frequency: 200000.00 Hz.
Took: 80 counts. Frequency: 200000.00 Hz.
Put another way, it captured an interval of 5 S (80 x 62.5 nS). Since it takes about 2.5 S
to enter and leave an ISR (interrupt service routine) then this sounds about right (you
need two interrupts to capture the interval: the "start of interval" interrupt and the "end
of interval" interrupt).
Measuring a duty cycle using the input capture unit
The sketch below is a variation on the frequency counter above. However this one
measures the width of the "on" portion of the duty cycle of a pulse. This could be useful
for decoding information from PWM style controls.

// Duty cycle calculation using input capture unit


// Author: Nick Gammon
// Date: 5 November 2013

// Input: Pin D8

volatile boolean first;


volatile boolean triggered;
volatile unsigned long overflowCount;
volatile unsigned long startTime;
volatile unsigned long finishTime;

// timer overflows (every 65536 counts)


ISR (TIMER1_OVF_vect)
{
overflowCount++;
} // end of TIMER1_OVF_vect

ISR (TIMER1_CAPT_vect)
{
// grab counter value before it changes any more
unsigned int timer1CounterValue;
timer1CounterValue = ICR1; // see datasheet, page 117 (accessing 16-bit registers)
unsigned long overflowCopy = overflowCount;

// if just missed an overflow


if ((TIFR1 & bit (TOV1)) && timer1CounterValue < 0x7FFF)
overflowCopy++;

// wait until we noticed last one


if (triggered)
return;

if (first)
{
startTime = (overflowCopy << 16) + timer1CounterValue;
TIFR1 |= bit (ICF1); // clear Timer/Counter1, Input Capture Flag
TCCR1B = bit (CS10); // No prescaling, Input Capture Edge Select (falling on D8)
first = false;
return;
}

finishTime = (overflowCopy << 16) + timer1CounterValue;


triggered = true;
TIMSK1 = 0; // no more interrupts for now
} // end of TIMER1_CAPT_vect

void prepareForInterrupts ()
{
noInterrupts (); // protected code
first = true;
triggered = false; // re-arm for next time
// reset Timer 1
TCCR1A = 0;
TCCR1B = 0;

TIFR1 = bit (ICF1) | bit (TOV1); // clear flags so we don't get a bogus interrupt
TCNT1 = 0; // Counter to zero
overflowCount = 0; // Therefore no overflows yet

// Timer 1 - counts clock pulses


TIMSK1 = bit (TOIE1) | bit (ICIE1); // interrupt on Timer 1 overflow and input capture
// start Timer 1, no prescaler
TCCR1B = bit (CS10) | bit (ICES1); // plus Input Capture Edge Select (rising on D8)
interrupts ();
} // end of prepareForInterrupts

void setup ()
{
Serial.begin(115200);
Serial.println("Duty cycle width calculator");
// set up for interrupts
prepareForInterrupts ();
} // end of setup

void loop ()
{
// wait till we have a reading
if (!triggered)
return;

// period is elapsed time


unsigned long elapsedTime = finishTime - startTime;

Serial.print ("Took: ");


Serial.print (float (elapsedTime) * 62.5e-9 * 1e6); // convert to microseconds
Serial.println (" uS. ");

// so we can read it
delay (500);

prepareForInterrupts ();
} // end of loop

Testing shows that the displayed pulse width is within 100 nS of the actual width (two
clock cycles basically) which isn't too bad.
Example strobe for car brake light
This example shows how we can use Timer 1 to strobe a brake light for a second, and
then settle down into a constant "on" light, until the brake pedal is released.

const byte LED = 10; // Timer 1 "B" output: OC1B


const byte PEDAL_PIN = 2;

const int ON_TIME = 1000; // This is the amount of time that the strobe will flash
before going solid
const int STROBE_FREQ = 100; // sets the delay between strobe pulses in milliseconds
const unsigned long countTo = (F_CPU / 1024) / (1000 / STROBE_FREQ);

volatile unsigned long whenPressed;


volatile bool pressed;

// ISR entered when brake pedal pressed


void brakePedal ()
{
bitSet (TCCR1A, COM1B1); // clear OC1B on compare
whenPressed = millis ();
pressed = true;
} // end of brakePedal

void setup()
{
pinMode (LED, OUTPUT);
pinMode (PEDAL_PIN, INPUT_PULLUP);

// Fast PWM top at OCR1A


TCCR1A = bit (WGM10) | bit (WGM11); // fast PWM
TCCR1B = bit (WGM12) | bit (WGM13) | bit (CS12) | bit (CS10); // fast PWM, prescaler
of 1024
OCR1A = countTo - 1; // zero relative
OCR1B = (countTo / 4) - 1; // 25% duty cycle

attachInterrupt (0, brakePedal, FALLING);


} // end of setup

void loop()
{
// switch from strobing to steady after ON_TIME
if (pressed && (millis () - whenPressed >= ON_TIME))
{
bitClear (TCCR1A, COM1B1);
digitalWrite (LED, HIGH); // turn light on fully
}

// if pedal up, make sure light is off


if (digitalRead (PEDAL_PIN) == HIGH)
{
bitClear (TCCR1A, COM1B1);
digitalWrite (LED, LOW); // turn light off
pressed = false;
}

// do other stuff here

} // end of loop
Example of flashing an LED with minimal code
This flashes D10 at a frequency of 2 Hz (off for one second, on for one second)

const int STROBE_FREQ = 2000; // sets the frequency in milliseconds


const unsigned long countTo = ((float) F_CPU / 1024.0) / (1000.0 / STROBE_FREQ);

int main (void)


{
// D10 to output
bitSet (DDRB, 2);

// Fast PWM top at OCR1A


TCCR1A = bit (WGM10) | bit (WGM11); // fast PWM
TCCR1B = bit (WGM12) | bit (WGM13) | bit (CS12) | bit (CS10); // fast PWM, prescaler
of 1024
OCR1A = countTo - 1; // zero relative
OCR1B = (countTo / 2) - 1; // 50% duty cycle
bitSet (TCCR1A, COM1B1); // clear OC1B on compare
} // end of main

Sketch size: 222 bytes on a Uno using IDE 1.0.6.


Secret Arduino Voltmeter Measure Battery Voltage
A little known feature of Arduinos and many other AVR chips is the ability to measure the
internal 1.1 volt reference. This feature can be exploited to improve the accuracy of the
Arduino function analogRead() when using the default analog reference. It can also be
used to measure the Vcc supplied to the AVR chip, which provides a means of monitoring
battery voltage without using a precious analog pin to do so.
I first learned of this technique from these articles Making accurate ADC readings on
the Arduino, and Secret Voltmeter. In this article, I have incorporated some additional
improvements.

Motivation
There are at least two reasons to measure the voltage supplied to our Arduino (Vcc). One
is if our project is battery powered, we may want to monitor that voltage to measure
battery levels. Also, when battery powered, Vcc is not going to be 5.0 volts, so if we wish
to make analog measurements we need to either use the internal voltage reference of
1.1 volts, or an external voltage reference. Why?

A common assumption when using analogRead() is that the analog reference voltage is
5.0 volts, when in reality it may be quite different. The official Arduino
documentation even leads us to this wrong assumption. The fact is the default analog
reference is not 5.0 volts, but whatever the current level of Vcc is being supplied to the
chip. If our power supply is not perfectly regulated or if we are running on battery power,
this voltage can vary quite a bit. Here is example code illustrating the problem:
double Vcc = 5.0; // not necessarily true
int value = analogRead(0);
double volt = (value / 1023.0) * Vcc; // only correct if Vcc = 5.0 volts
In order to measure analog voltage accurately, we need an accurate voltage reference.
Most AVR chips provide three possible sources an internal 1.1 volt source (some have a
2.56 internal voltage source), an external reference source or Vcc. An external voltage
reference is the most accurate, but requires extra hardware. The internal reference is
stable, but has about a +/- 10% error. Vcc is completely untrustworthy in most cases. The
choice of the internal reference is inexpensive and stable, but most of the time, we
would like to measure a broader range, so the Vcc reference is the most practical, but
potentially the least accurate. In some cases it can be completely unreliable!

How-To
Many AVR chips including the ATmega series and many ATtiny series provide a means to
measure the internal voltage reference. Why would anyone want to do so? The reason is
simple by measuring the internal reference, we can determine the value of Vcc. Heres
how:

1. First set the voltage reference to Vcc.


2. Measure the value of the internal reference.
3. Calculate the value of Vcc.
Our measured voltage is:

Vcc * (ADC-measurement) / 1023


which as we know is 1.1 volts. Solving for Vcc, we get:

Vcc = 1.1 * 1023 / ADC-measurement

Putting it altogether, heres the code:

long readVcc() {
// Read 1.1V reference against AVcc
// set the reference to Vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) ||
defined(__AVR_ATmega2560__)
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) ||
defined(__AVR_ATtiny84__)
ADMUX = _BV(MUX5) | _BV(MUX0);
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) ||
defined(__AVR_ATtiny85__)
ADMUX = _BV(MUX3) | _BV(MUX2);
#else
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif

delay(2); // Wait for Vref to settle


ADCSRA |= _BV(ADSC); // Start conversion
while (bit_is_set(ADCSRA,ADSC)); // measuring

uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
uint8_t high = ADCH; // unlocks both

long result = (high<<8) | low;

result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000


return result; // Vcc in millivolts
}

long readVcc() {
long result;
// Read 1.1V reference against AVcc
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
result = ADCL;
result |= ADCH<<8;
result = 1126400L / result; // Back-calculate AVcc in mV
return result;
}

void setup() {
Serial.begin(9600);
}

void loop() {
Serial.println( readVcc(), DEC );
delay(1000);
}

Usage

Checking Vcc or Battery Voltage


You can call this function readVcc(), if you want to monitor your Vcc. One example
would be for checking your battery charge level. You could also use it to determine if you
are connected to a power source or running from batteries.

Measuring Vcc for Analog Reference


You can also use it to get a correct value for Vcc to use withanalogRead() when using the
default (Vcc) voltage reference. Unless you are using a regulated supply, you cant be
sure Vcc is 5.0 volts or not. This function will provide the correct value to use. There is
one caveat though
One of the articles I cited earlier made the claim that this function could be used to
improve the accuracy of the analog measurement in cases where Vcc wasnt exactly 5.0
volts. Unfortunately, this procedure will not provide that result. Why? It is dependent on
the accuracy of the internal voltage reference. The spec sheet gives a nominal value of
1.1 volts, but states that it can vary from 1.0 to 1.2 volts. That means that any
measurement of Vcc could be off by as much as 10%. Such a measurement could be less
accurate than our power supply for the Arduino!

Improving Accuracy
While the large tolerance of the internal 1.1 volt reference greatly limits the accuracy of
this measurement, for individual projects we can compensate for greater accuracy. To do
so, simply measure your Vcc with a voltmeter and with our readVcc() function. Then,
replace the constant 1125300L with a new constant:

scale_constant = internal1.1Ref * 1023 * 1000


where

internal1.1Ref = 1.1 * Vcc1 (per voltmeter) / Vcc2 (per readVcc() function)


This calibrated value will be good for the AVR chip measured only, and may be subject to
temperature variation. Feel free to experiment with your own measurements.

Conclusion
You can do a lot with this little function. You can use a stable voltage reference close to
5.0 volts without having to rely on your Vcc actually being 5.0 volts. You can measure
your battery voltage or even see if you are running on battery or A/C power.

Lastly, the code provided will support all the Arduino variants, including the new
Leonardo, as well as the ATtinyX4 and ATtinyX5 series chips.

Please share any corrections in the comments below.

Potrebbero piacerti anche