In avr-gcc, there is a macro called ISR() which takes the
interrupt vector as an input; the documentation for avr-gcc
tells the vector names, but you can just as easily find the
interrupt vector name by looking at and using the Atmel
ATmega 168 datasheet in section 11.4: Interrupt Vectors
in ATMega 168 which lists vector 11 “TIMER1 CAPT.”
Modify this name like this: TIMER1_CAPT_vect and you
have the vector to pass to the ISR() macro. Our ISR needs
to handle both the interrupt for the rising edge of the pulse
and the interrupt for the falling edge of the servo pulse.
You will notice that on the rising edge I clear the 16-bit
TCNT register; this allows our timing to start at zero. I then
say that the next interrupt will occur on the falling edge by
clearing the ICES1 bit. When the servo signal drops, the
else clause of the ISR is used. This gets the value of the
ICR1 register which is the value of the TCNT register at the
time of the interrupt. I then
flip the ICES1 bit to again
interrupt on a rising edge and
the cycle starts over again.
When you use an ISR to
set or change a variable in
your program, you need to let
the compiler know this. This is
because an ISR is never called
from within your program so
the compiler does not know
when the variables that the ISR
Now let’s look at the main() code where we actually
use the value of the gyro that we are measuring. In Listing
4, we see the very short code section that determines the
pulse value has changed and prints it out.
Notice that the code just assumes that the value is
there in the pulse variable. Our ISR handles the dirty work
and our code just uses the value. This loop tracks the
previous pulse value and only prints something when it
changes significantly. This keeps our display from filling up
and blasting by us, and makes the changes easier to detect.
Speaking of which, Figure 3 shows my terminal window. I
am a hard-core Mac user, so if you are a Windows user,
Listing 4: Main code loop.
waitms(100); // once every 100ms
if ((abs(pulse - lastPulse)) > 100)
lastPulse = pulse;
printf(“%u\r”,pulse);// print out the pulse value
Figure 3. Gyro readings.
Figure 4. Test setup.
16 SERVO 01.2011