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 Answer
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()
.
precisely count time delays
... please defineprecisely