time count (***edit resolution<1usec) between 2 signals

Hello,
I admit that although there was some reading, finally can't figure it out
The problem:
In one Mega2560 there are 2 signals going to digital pins, let say 40, 45.
Signal on pin 40 is "Referense" .

Want to measure the time between 40 rising and 45 rising. Don;t care which is leading/lagging

Expexted measurements : from 1 to 2500 microsec (resolution better than or equal to 1usec)

Any small example, link etc is gracefully accepted

thank you

micros()

Your title suggests nanoseconds, your description suggests otherwise.

@ aarg : micros() dont give < 1msec (they give >4) I know that
@ TheMemberFormerlyKnownAsAWOL:

Sorry, I dont see that.
title : time count (<1usec) between 2 signals
description : range 1-2500usec, (resolution better than or equal to 1usec)
Perhaps there is "misinterpretation" of <1usec)
In any case Sorry for misunderstanding

Anyway. I think its needed something like:

//# include <????>
boolean MeasurementStarted = false;
boolean MeasurementEnded = false;
unsigned long result = 0;
attachInterrupt(pin( ?? ), ISR1);
attachInterrupt(pin( ?? ), ISR2);


void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:
  if (MeasurementEnded) {
    Serial.println(result);
    MeasurementStarted = false;
    MeasurementEnded = false;
  }
}
ISR1( ?? ? ) {
  if (MeasurementStarted == false) && MeasurementEnded = false) {
    MeasurementStarted = true;
    //clear timer????
  }
}

ISR2( ?? ? ) {
  if (MeasurementStarted == true) && MeasurementEnded = false) {
    MeasurementEnded = true;
    //result=????
  }
}

but I dont know a suitable library

That is what Im asking for

Which processor are you using? Because you will need one with two input capture pins. The 328p has only one.

If you use pins 48 and 49 you could use the input capture function of Timer 5 and Timer 4 respectively.

aarg:
Which processor are you using? Because you will need one with two input capture pins.

In one Mega2560 there are 2 signals going to digital pins, let say 40, 45.

(ok, 40 and 45 are not valid for interrupts. )

Well, you can't use the 'micros()' function because it only has 4-microsecond resolution (Timer0 is set for a prescale of 64 to get an overflow about every millisecond).

If you use the two Input Capture signals then this code might be of some help. It's designed for Timer1 on an UNO but can be adapted for timers 4 and 5 on the Mega. You will probably have to synchronize the two timers to get correct relative times from the two separate timers. It can give you relative times measured in 16ths of a microsecond and since the timing is done in hardware it doesn't depend on interrupt latency.

// Measures the HIGH width, LOW width, frequency and duty-cycle of a pulse train
// on Arduino UNO Pin 8 (ICP1 pin).


// Note: Since this uses Timer1, Pin 9 and Pin 10 can't be used for
// analogWrite().


void setup()
{
  Serial.begin(115200);
  while (!Serial);


  // For testing, uncomment one of these lines and connect
  // Pin 3 or Pin 5 to Pin 8
  // analogWrite(3, 64);  // 512.00, 1528.00, 2040.00, 25.10%, 490.20 Hz
  analogWrite(5, 64);  // 260.00, 764.00, 1024.00, 25.39%, 976.56 Hz


  noInterrupts ();  // protected code
  // reset Timer 1
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;
  TIMSK1 = 0;


  TIFR1 |= (1 << ICF1); // clear Input Capture Flag so we don't get a bogus interrupt
  TIFR1 |= (1 << TOV1); // clear Overflow Flag so we don't get a bogus interrupt


  TCCR1B = _BV(CS10) | // start Timer 1, no prescaler
           _BV(ICES1); // Input Capture Edge Select (1=Rising, 0=Falling)


  TIMSK1 |= _BV(ICIE1); // Enable Timer 1 Input Capture Interrupt
  TIMSK1 |= _BV(TOIE1); // Enable Timer 1 Overflow Interrupt
  interrupts ();
}


volatile uint32_t PulseHighTime = 0;
volatile uint32_t PulseLowTime = 0;
volatile uint16_t Overflows = 0;


ISR(TIMER1_OVF_vect)
{
  Overflows++;
}


ISR(TIMER1_CAPT_vect)
{
  static uint32_t firstRisingEdgeTime = 0;
  static uint32_t fallingEdgeTime = 0;
  static uint32_t secondRisingEdgeTime = 0;


  uint16_t overflows = Overflows;


  // If an overflow happened but has not been handled yet
  // and the timer count was close to zero, count the
  // overflow as part of this time.
  if ((TIFR1 & _BV(TOV1)) && (ICR1 < 1024))
    overflows++;


  if (PulseLowTime == 0)
  {
    if (TCCR1B & _BV(ICES1))
    {
      // Interrupted on Rising Edge
      if (firstRisingEdgeTime)  // Already have the first rising edge...
      {
        // ... so this is the second rising edge, ending the low part
        // of tghe cycle.
        secondRisingEdgeTime = overflows;
        secondRisingEdgeTime = (secondRisingEdgeTime << 16) | ICR1;
        PulseLowTime = secondRisingEdgeTime - fallingEdgeTime;
        firstRisingEdgeTime = 0;
      }
      else
      {
        firstRisingEdgeTime = overflows;
        firstRisingEdgeTime = (firstRisingEdgeTime << 16) | ICR1;
        TCCR1B &= ~_BV(ICES1); // Switch to Falling Edge
      }
    }
    else
    {
      // Interrupted on Falling Edge
      fallingEdgeTime = overflows;
      fallingEdgeTime = (fallingEdgeTime << 16) | ICR1;
      TCCR1B |= _BV(ICES1); // Switch to Rising Edge
      PulseHighTime = fallingEdgeTime - firstRisingEdgeTime;
    }
  }
}


void loop()
{
  noInterrupts();
  uint32_t pulseHighTime = PulseHighTime;
  uint32_t pulseLowTime = PulseLowTime;
  interrupts();


  // If a sample has been measured
  if (pulseLowTime)
  {
    // Display the pulse length in microseconds
    Serial.print("High time (microseconds): ");
    Serial.println(pulseHighTime / 16.0, 2);
    Serial.print("Low time (microseconds): ");
    Serial.println(pulseLowTime / 16.0, 2);


    uint32_t cycleTime = pulseHighTime + pulseLowTime;
    Serial.print("Cycle time (microseconds): ");
    Serial.println(cycleTime / 16.0, 2);


    float dutyCycle = pulseHighTime / (float)cycleTime;
    Serial.print("Duty cycle (%): ");
    Serial.println(dutyCycle * 100.0, 2);


    float frequency = (float)F_CPU / cycleTime;
    Serial.print("Frequency (Hz): ");
    Serial.println(frequency, 2);
    Serial.println();


    delay(1000);  // Slow down output


    // Request another sample
    noInterrupts();
    PulseLowTime = 0;
    interrupts();
  }
}

OP, please don't go back and edit previous posts... it makes the replies hard to decipher. What is your skill level? This project is expert level.

Here is a version that should compare arrival times of rising edges on ICP4 (Pin 49) and ICP5 (Pin 48).

// Measures time between rising edges on two input pins: 
//  Pin 49 (ICP4) and Pin 48 (ICP5).


void setup()
{
  Serial.begin(115200);
  while (!Serial);


  noInterrupts ();  // protected code
  // Set up Timer 4
  TCCR4A = 0;
  TCCR4B = 0;
  TCNT4 = 0;
  TIMSK4 = 0;


  TIFR4 |= (1 << ICF4); // clear Input Capture Flag so we don't get a bogus interrupt
  TIFR4 |= (1 << TOV4); // clear Overflow Flag so we don't get a bogus interrupt


  TCCR4B = _BV(CS40) | // start Timer 4, no prescaler
           _BV(ICES4); // Input Capture Edge Select: Rising


  TIMSK4 |= _BV(ICIE4); // Enable Timer 4 Input Capture Interrupt
  TIMSK4 |= _BV(TOIE4); // Enable Timer 4 Overflow Interrupt




  // Set up Timer 5
  TCCR5A = 0;
  TCCR5B = 0;
  TCNT5 = 0;
  TIMSK5 = 0;


  TIFR5 |= (1 << ICF5); // clear Input Capture Flag so we don't get a bogus interrupt


  TCCR5B = _BV(CS50) | // start Timer 5, no prescaler
           _BV(ICES5); // Input Capture Edge Select: Rising


  TIMSK5 |= _BV(ICIE5); // Enable Timer 5 Input Capture Interrupt


  interrupts ();
}


volatile uint32_t Timer4CapturedTime = 0;
volatile uint32_t Timer5CapturedTime = 0;
volatile uint16_t Overflows = 0;


ISR(TIMER4_OVF_vect)
{
  Overflows++;


  // Let's try to synchronize the two timers here. Because of the 
  // instructions cycles needed to fetch the value from TCNT4
  // and write it to TCNT5 there will probably be a fixed offset
  // between the two.  That offset can be removed by adding a few
  // cycles to the TCNT4 value before setting TCNT5. Try jumpering
  // both ICP pins together to see how many microseconds difference
  // you see on a rising edge.  Multiply by 16 to get clock cycles 
  // and adjust the value below until the difference is usually 
  // 0.00 microseconds.
  TCNT5 = TCNT4 + 6;
}


ISR(TIMER4_CAPT_vect)
{
  uint16_t overflows = Overflows;


  // If an overflow has happened but has not been handled yet
  // (the interrupt flag is still set) and the timer count was 
  // close to zero (overflow was recent), count the
  // overflow as part of this time.
  if ((TIFR4 & _BV(TOV4)) && (ICR4 < 1024))
    overflows++;


  if (Timer4CapturedTime == 0)
  {
    Timer4CapturedTime = overflows;
    Timer4CapturedTime <<= 16;
    Timer4CapturedTime |= ICR4;
  }
}


ISR(TIMER5_CAPT_vect)
{
  uint16_t overflows = Overflows;


  // If an overflow has happened on Timer4 but has not been 
  // handled yet (the interrupt flag is still set) and the 
  // Timer4 count is low (overflow was recent), count the
  // overflow as part of this time.
  if ((TIFR4 & _BV(TOV4)) && (ICR4 < 1024))
    overflows++;


  if (Timer5CapturedTime == 0)
  {
    Timer5CapturedTime = overflows;
    Timer5CapturedTime <<= 16;
    Timer5CapturedTime |= ICR5;
  }
}


void loop()
{
  // Get local copies of the volatile variables
  noInterrupts();
  uint32_t timer4Time = Timer4CapturedTime;
  uint32_t timer5Time = Timer5CapturedTime;
  interrupts();


  // If both input captures have been triggered
  if (timer4Time && timer5Time)
  {
    long int interval = timer4Time - timer5Time;


    Serial.println(interval / 16.0);  // Positive means Timer4 triggered first


    delay(1000);  // Slow down output


    // Request another sample
    noInterrupts();
    Timer4CapturedTime = 0;
    Timer5CapturedTime = 0;
    interrupts();
  }
}

@johnwasser:
thank you very much.
I will try it in the next few days (because missing of some interface components)