# Arduino ISR timing question

Im trying to understand how the Arduino ISR keeps track of timing between pulses stored in a variable, if that variable is latter used.

Say, for example, you have a magnet mounted on a circular object, that passes a reed switch. Using this to trigger the ISR that calls a function that would have something like counts++ in it, then storing that value in a variable.

If that varible is used latter to turn on a motor, for example, according to the count capture, how does the arduino MCU know the freq or timing to output the count or pulses of the magnet passing the reed switch, at the same frequency that the counts were received? For example, a magnet mounted on a 2 inch dia shaft would turn slower past a reed switch than one mounted on a .5 inch shaft, or one could vary the speed of the magnet past the reed as they wish. So how does counter++ keep track of this freq? is it reading the attachinterupt pin (or is the function that is being called, keeping track) or does the ISR time stamp each pulse it receives and store that interval in the declared variable? so when the variable is used again, it has this interval stored in it?

To be more clear, if it takes one second for the magnet to complete one revolution, how does the MCU know it took one second and store this, along with the counts of the revolutions?

Thanks for any help

• It doesn't know that. You'd have to code that yourself. You could indeed have the ISR store the `millis()` value. Even better would be to have the ISR (locally) store the millis() value of the last time the ISR was called. Then when the ISR is called the next time, it could calculate the time that has passed since the last ISR call. If the motor is running faster, this method can get a bit less accurate. In that case you could have the main `loop` measure the time it takes for the counter to increase by e.g. 20 (i.e. 20 revolutions). The it can calculate the average RPM. Jan 8, 2018 at 10:45
• so when people use for ex. the interupt, to call a function, for ex. void Revolutions(){ rev++; }; and then have an if statement with varibles like if { revA = rev; rev=0; to store revolutions, and use that again in another if statement like if revA>rev, analogWrite(motor) the duration of the value stored in revA is not stored? if not, then what is stored?
– Jim
Jan 8, 2018 at 10:51
• @Jim When people just count revolutions like that they introduce the concept of time at a later stage. For instance, they will look at (and reset) that count once a second, giving the number of revolutions in that one second window, and hence the number of revolutions per second. Jan 8, 2018 at 10:55
• "they will look at (and reset) that count once a second, giving the number of revolutions in that one second window, and hence the number of revolutions per second" so your saying the "one second" is an arbutrary value? Im just trying to understand what, for ex. counter++ or rev+1 etc is tied too? the interupt calls the function, then 1,2,3,4.....counts pass, its stored, then output according to what time?
– Jim
Jan 8, 2018 at 11:02
• perhaps the key thing Im missing is "reset", the interupt is used, calls its function, then resets so that time frame of all the sets/resets corresponds to the amount of total times it took to capture the time you want to turn on a motor, for ex. meaning that if it took 1 minute to capture 500 set/resets, then you could approx. capture that in a variable?
– Jim
Jan 8, 2018 at 11:07

All the interrupt does is count. It has no concept of time. For instance:

``````volatile uint32_t revolutions = 0;
void count() {
revolutions++;
}
....
attachInterrupt(0, count, FALLING);
``````

will just count up 1 every time the interrupt triggers.

To be able to convert that count into something meaningful you have to manually introduce the concept of time - that is, the count of "revolutions" (for example) between two points in time. And it's up to your sketch to implement that.

The simplest way may be:

``````// For anything more than an 8 bit value on an 8 bit machine
// make a critical section to save and reset the count
cli();
uint32_t savedResolutions = revolutions;
revolutions = 0;
sei();

Serial.print(savedRevolutions);
Serial.println(F(" revolutions per second"));

// Introduce the concept of time - this will
// make it get the count once a second.
delay(1000);
``````

Of course, instead of `delay()` you can use `millis()` in much the same way as the `BlinkWithoutDelay` example in the IDE.

It is possible (as long as you're not counting too fast) to incorporate the time element into the interrupt routine by keeping track of the time in a variable:

``````volatile uint32_t rps = 0;

void count() {
static uint32_t revolutions = 0;
static uint32_t timestamp = millis();

revolutions++;

if (millis() - timestamp >= 1000) {
timestamp = millis();
rps = revolutions;
revolutions = 0;
}
}
....
attachInterrupt(0, count, FALLING);
``````

Then you can just reference the `rps` variable at any time to get the revolutions per second. Again it should really be queried inside a critical section to prevent the value being changed while you're actively reading it...

``````cli();
uint32_t myRPS = rps;
sei();

Serial.print(myRPS);
Serial.println(F(" revolutions per second"));
``````
• Ive seen people use a variable++ or +1 in a function called by the ISR, without any millis or time reference, then use that variable against another variable to capture a peak value, use that to turn something on for that duration, for example.
– Jim
Jan 8, 2018 at 11:39
• Sure, if that's what they are doing requires them to do... Jan 8, 2018 at 12:04
• "like that they introduce the concept of time at a later stage" could you explain what you mean by this perhaps with an example? I dont quite get it
– Jim
Jan 8, 2018 at 12:08
• You mean besides the one I already show in my answer? Jan 8, 2018 at 12:09
• they were comparing 2 variables and saving the larger count, then using that condition to turn on a motor, so it wasnt timed to anything, just when one became larger than the other, save that, and that condition became true, turn on the motor... As for nested "if" statements, if you have an if then a nested if, that is equilivant to an AND, correct? but an if, then an if else is equilivant to a NOT, correct?
– Jim
Jan 18, 2018 at 3:20