0

I am wondering how I can precisely count time delays between rise events happening on 4 different lines/pins using Input Capture of Arduino Mega 2560. How can I synchronize timer/counters? Appreciate your help and suggestions.

1
  • precisely count time delays ... please define precisely
    – jsotola
    Commented May 29 at 15:17

1 Answer 1

2

You can't. At least not without modifying the hardware.

The ATmega2560 microcontroller at the hearth of the Arduino Mega has four input capture units, wired to the input capture pins ICP[1345]. Unfortunately, only two of those pins are routed on the Arduino board. The table below list the four ICP pins, with their pin numbers on the TQFP package and on the Arduino board:

   pin     package  Arduino
───────────────────────────
ICP1/PD4     47        --
ICP3/PE7      9        --
ICP4/PL0     35        49
ICP5/PL1     36        48

Unless you manage to solder wires to the missing pins, you won't be able to use the four input capture units.

As for the synchronization, you have two options:

  • If you are using the prescaler (i.e. a prescaler factor larger than one), you should use its “prescaler reset” feature with the TSM bit (Timer/Counter Synchronization Mode) enabled. This will let you start the four timers simultaneouly when you clear the TSM bit. See the MCU datasheet for details.

  • If you are not using the prescaler, you can just start the four timers in quick succession, with interrupts disabled. They won't start quite at the same time, but you can compensate for this when setting their initial values.

As an example of the second option, the following function starts the four timers without prescaler and counting in sync:

void init_timers() {
    // Clear the timer configurations.
    TCCR1A = 0; TCCR1B = 0;
    TCCR3A = 0; TCCR3B = 0;
    TCCR4A = 0; TCCR4B = 0;
    TCCR5A = 0; TCCR5B = 0;

    // Set the initial values.
    TCNT1 = 0;
    TCNT3 = 2;
    TCNT4 = 4;
    TCNT5 = 6;

    // Start the timers.
    noInterrupts();
    TCCR1B = _BV(CS10);
    TCCR3B = _BV(CS30);
    TCCR4B = _BV(CS40);
    TCCR5B = _BV(CS50);
    interrupts();
}

The section that starts the timers compiles to this assembly:

cli              ; noInterrupts();
ldi r24, 0x01    ; r24 = _BV(CS10)
sts TCCR1B, r24  ; TCCR1B = r24
sts TCCR3B, r24  ; TCCR3B = r24
sts TCCR4B, r24  ; TCCR4B = r24
sts TCCR5B, r24  ; TCCR5B = r24
sei              ; interrupts();

As the sts instruction completes in two clock cycles, this delay will compensate for the offset in the initial timer values.

Now, if you don't care about microsecond-level accuracy, you can forget about the timers and use external interrupts (or pin change interrupts) and record the times with micros().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.