Arduino Uno Input Capture!!!

Hi Guys, i would like to thank you in advance for helping with this problem that i m having getting input capture working in arduino uno. I have read all the post there is in most of the forums and haven’t come to a solution yet.
GOAL: The main purpose of the project that i m working on is to capture the time between two events. I m using timer1 and pin 8 on the arduino uno. This is what i have…

#include <avr/io.h>
#include <avr/interrupt.h>
volatile uint16_t T1Ovs1, T1Ovs2;//OVERFLOW COUNTERS 
volatile uint16_t Capt1, Capt2, Capt3;//VARIABLES TO HOLD TIMESTAMPS 
volatile uint8_t Flag;//CAPTURE FLAG
#define icpPin 8
/*--------------------------------------------------------------------------------------------------
INTIALIZING TIMER
---------------------------------------------------------------------------------------------------*/
void InitTimer1(void)
{
    TCNT1=0;//SETTING INTIAL TIMER VALUE
    TCCR1B|=(1<<ICES1);//SETTING FIRST CAPTURE ON RISING EDGE
    TIMSK1|=(1<<ICIE1)|(1<<TOIE1);//ENABLING INPUT CAPTURE AND OVERFLOW INTERRUPTS 
}
/*--------------------------------------------------------------------------------------------------
STARTING TIMER
---------------------------------------------------------------------------------------------------*/
void StartTimer1(void)
{
    TCCR1B|=(1<<CS11);//STARTING TIMER WITHOUT PRESCALER
    sei();//ENABLING GLOBAL INTERRUPTS 
}
/*--------------------------------------------------------------------------------------------------
CAPTURE ISR
---------------------------------------------------------------------------------------------------*/
ISR(TIMER1_CAPT_vect)
{
  TCNT1 = 0;
  if (Flag==0)
      {
        Capt1=ICR1;//SAVING CAPTURED TIMESTAMP
        TCCR1B&=~(1<<ICES1);//CHANGE CAPTURE ON FALLING EDGE
        T1Ovs2=0;//RESETING OVERFLOWS
        //digitalWrite(13, HIGH);   // set the LED on
        //delay(100);              // wait for a second
      }
  if (Flag==1)
      {
        Capt2=ICR1;//SAVING CAPTURED TIMESTAMP
        TCCR1B|=(1<<ICES1);//CHANGING CAPTURE ON RISING EDGE
        T1Ovs1=T1Ovs2;//SAVING FIRST OVERFLOW COUNTER
        //digitalWrite(13, LOW);   // set the LED off
        //delay(100);              // wait for a second
      }
  if (Flag==2)
      {
        Capt3=ICR1;//SAVING CAPTURED TIMESTAMP
        TIMSK1&=~((1<<ICIE1)|(1<<TOIE1));//STOP INPUT CAPTURE AND OVERFLOW INTERRUPTS
        //digitalWrite(13, HIGH);   // set the LED on
        //delay(100);              // wait for a second
      }
    Flag++;//INCREMENTING FLAG
}
/*--------------------------------------------------------------------------------------------------
OVERFLOW ISR
---------------------------------------------------------------------------------------------------*/
ISR(TIMER1_OVF_vect)
{
      T1Ovs2++;//INCREMENTING OVERFLOW COUNTER
}
/*--------------------------------------------------------------------------------------------------
MAIN FUNCTION
---------------------------------------------------------------------------------------------------*/
int main(void)
{
       volatile uint8_t FINALTIME;//VARIABLE TO HOLD THE FINAL TIME 
       pinMode(icpPin,INPUT);
       digitalWrite(icpPin,HIGH);//pull up
      // pinMode(13, OUTPUT); 
       InitTimer1();//CALLING FUNCTION INITTIMER1 TO INITIALIZE TIMER 1
       StartTimer1();//CALLING FUNCTION STARTTIMER1 TO START TIMER 1
        while(1)
        {
            //calculate duty cycle if all timestamps captured
            if (Flag==3)
            {
                    
                    Serial.begin(9600);
                    Serial.print("\r");
                    Serial.print("<Capture1>:");
                    Serial.print(Capt1);    
                    Serial.print("<Capture2>:");
                    Serial.print(Capt2);     
                    Serial.print("<Capture3>:");
                    Serial.print(Capt3); 
                    Serial.print("\n");            
                    Serial.print("<FINAL TIME>:");               
                    Serial.print((Capt2-Capt1)*0.000125);
                    Serial.print(" Millisecond");
                    Serial.print("\n"); 
                    Flag=0;//CLEARING FLAG
                    T1Ovs1=0;//CLEARING OVERFLOW COUNTERS 
                    T1Ovs2=0;
                    TIFR1=(1<<ICF1)|(1<<TOV1);//CLEARING INTERRUPT FLAGS TO AVOID ANY PENDING INTERRUPTS 
                    TIMSK1|=(1<<ICIE1)|(1<<TOIE1);//ENABLING INPUT CAPTURE AND OVERFLOW INTERRUPTS 
            }
        }
}

Moderator edit:
</mark> <mark>[code]</mark> <mark>

</mark> <mark>[/code]</mark> <mark>
tags added.

The main purpose of the project that i m working on is to capture the time between two events.

Between what two events? What time frame are you talking about? Nano-seconds or weeks?

This is what i have...

And? Does it compile? Does it capture the time between the two events correctly? Is it causing the Arduino to smoke?

Sorry about not clarifying the specs: Yes, the program complies and the time i m looking is about a second and i m using the 5 volts source in the arduino board to triggered the input capture. I tried to verify if i am even getting to the ISR by having the program to turn on and off led when it reached ISR, but it doesnt seem to do that, which made me thinkg that i m not even getting to ISR.I was getting the counter to count yesterday, but it was randomly triggering the event without any input to the capture pin. I m getting multiples results when tried triggering just one event, which i really dont understand. do i need to use the pull up resistor? I have verified my setup many times and read the user manual plenty. Your help is appreciated. Thank you

That code seems awfully complicated for measuring the time between two events that are that far apart in time.

Polling the pin would be plenty fast enough - no interrupts, no diddling with timers.

Sorry i m not that familiar with arduino, but wont you need clock or counter of some sort to do the timestamp? How would you do that without that?

but wont you need clock or counter of some sort to do the timestamp?

Use the millis() Luke

i will try that thank you

Hello together,
I tested the proposal from ballistics and made some changes. Now it seems to work. Nice code
Andreas

//
//  http://arduino.cc/forum/index.php/topic,97451.0.html
//
#include <io.h>
#include <interrupt.h>
volatile uint16_t T1Ovs1, T1Ovs2;       //OVERFLOW COUNTERS 
volatile uint16_t Capt1, Capt2, Capt3;  //VARIABLES TO HOLD TIMESTAMPS 
volatile uint8_t Flag;                  //CAPTURE FLAG
float deltatime;
#define icpPin 8                        // PB0 ICP D8  Interrupt input
/*--------------------------------------------------------------------------------------------------
INTIALIZING TIMER
---------------------------------------------------------------------------------------------------*/
void InitTimer1(void)
{
    TCNT1=0;                         //SETTING INTIAL TIMER VALUE
    TCCR1B|=(1<<ICES1);              //SETTING FIRST CAPTURE ON RISING EDGE ,(TCCR1B = TCCR1B | (1<<ICES1)
    TIMSK1|=(1<<ICIE1)|(1<<TOIE1);   //ENABLING INPUT CAPTURE AND OVERFLOW INTERRUPTS 
}
/*--------------------------------------------------------------------------------------------------
STARTING TIMER
---------------------------------------------------------------------------------------------------*/
void StartTimer1(void)
{
//    TCCR1B|=(1<<CS11)|(1<<CS10);    //STARTING TIMER WITH PRESCALER 64
    TCCR1B|=(1<<CS12);              //STARTING TIMER WITH PRESCALER 256
//    TCCR1B|=(1<<CS12)|(1<<CS10);    //STARTING TIMER WITH PRESCALER 1024
    sei();                          //ENABLING GLOBAL INTERRUPTS 
}
/*--------------------------------------------------------------------------------------------------
CAPTURE ISR
---------------------------------------------------------------------------------------------------*/
ISR(TIMER1_CAPT_vect)
{
//  TCNT1 = 0;
  if (Flag==0)
      {
        Capt1=ICR1;           //SAVING CAPTURED TIMESTAMP
        TCCR1B&=~(1<<ICES1);  //CHANGE CAPTURE ON FALLING EDGE
        T1Ovs2=0;             //RESETING OVERFLOWS
        //digitalWrite(13, HIGH);   // set the LED on
        //delay(100);              // wait for a second
      }
  if (Flag==1)
      {
        Capt2=ICR1;            //SAVING CAPTURED TIMESTAMP
        TCCR1B|=(1<<ICES1);    //CHANGING CAPTURE ON RISING EDGE
        T1Ovs1=T1Ovs2;         //SAVING FIRST OVERFLOW COUNTER
        //digitalWrite(13, LOW);   // set the LED off
        //delay(100);              // wait for a second
      }
  if (Flag==2)
      {
        Capt3=ICR1;                       //SAVING CAPTURED TIMESTAMP
        TIMSK1&=~((1<<ICIE1)|~(1<<TOIE1)); //STOP INPUT CAPTURE AND OVERFLOW INTERRUPTS
        //digitalWrite(13, HIGH);   // set the LED on
        //delay(100);              // wait for a second
      }
    Flag++;                          //INCREMENTING FLAG
}
/*--------------------------------------------------------------------------------------------------
OVERFLOW ISR
---------------------------------------------------------------------------------------------------*/
ISR(TIMER1_OVF_vect)
{
      T1Ovs2++;//INCREMENTING OVERFLOW COUNTER
}
/*--------------------------------------------------------------------------------------------------
MAIN FUNCTION
---------------------------------------------------------------------------------------------------*/
int main(void)
{
       volatile uint8_t FINALTIME;          //VARIABLE TO HOLD THE FINAL TIME 
       pinMode(icpPin,INPUT);
       digitalWrite(icpPin,HIGH);           //pull up
                                            // pinMode(13, OUTPUT); 
       InitTimer1();                        //CALLING FUNCTION INITTIMER1 TO INITIALIZE TIMER 1
       StartTimer1();                       //CALLING FUNCTION STARTTIMER1 TO START TIMER 1
        while(1)
        {
                                            //calculate duty cycle if all timestamps captured
            if (Flag==3)
            {
                    
                    
                    Serial.begin(115200);
                    Serial.print("\r");
                    Serial.print("  <Capture1>:");
                    Serial.print(Capt1);    
                    Serial.print("  <Capture2>:");
                    Serial.print(Capt2);     
                    Serial.print("  <Capture3>:");
                    Serial.print(Capt3); 
                    Serial.print("  <OVL1>:");
                    Serial.print(T1Ovs1); 
                    Serial.print("  <OVL2>:");
                    Serial.print(T1Ovs2); 
                    Serial.print("\n");            
                    Serial.print("<FINAL TIME>:");
//                    deltatime = (Capt3-Capt1)*0.004; // Prescaler 64
                    deltatime = (Capt3-Capt1)*0.016; // Prescaler 256
                    Serial.print((float)deltatime);
                    Serial.print(" Millisecond");
                    Serial.print("\n"); 
                    Flag=0;                          //CLEARING FLAG
                    T1Ovs1=0;                        //CLEARING OVERFLOW COUNTERS 
                    T1Ovs2=0;
                    TIFR1=(1<<ICF1)|(1<<TOV1);      //CLEARING INTERRUPT FLAGS TO AVOID ANY PENDING INTERRUPTS 
                    TIMSK1|=(1<<ICIE1)|(1<<TOIE1);  //ENABLING INPUT CAPTURE AND OVERFLOW INTERRUPTS 
                    TCNT1 = 0;
            }
        }
}

Moderator edit:
</mark> <mark>[code]</mark> <mark>

</mark> <mark>[/code]</mark> <mark>
tags added.

AJG059: Hello together, I tested the proposal from ballistics and made some changes. Now it seems to work. Nice code Andreas

That code is hideously complicated for such a simple task, and you don't see to be making [u]any[/u] use of the Arduino development environment or runtime library.

Why don't you just poll the input until you see the first event, record the start time, poll the input until you see the second time, record the end time. Subtract start from end to get the elapsed time and then calculate and print whatever it is you're deriving from this. If the events were happening at very high frequency you might have needed to use interrupts to respond to them quickly enough, but when you're looking for very long intervals like this it hardly seems necessary.

As a general note - when posting code, please enclose it in [ CODE ] [ /CODE ] tags to prevent the forum software from munging it.

Agree… waaaay too complicated.

…poll the input until you see the first event, record the start time, poll the input until you see the second time, record the end time. Subtract start from end to get the elapsed time…

This works just fine. Each millis() returns a long int with the current number of milliseconds since the board was powered. When you subtract two event times, the answer is the time difference in milliseconds.

Wouldnt Pulse In work here? http://arduino.cc/en/Reference/PulseIn

i have confuse during rising edge and falling edges on input capture nethod, please any one expalin during rising edge what values are stored in ICR1. it can store upto 0 to 65535 for rising edge only if its than what values are stored during falling edges. how timer values are detecting the edges