0

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

  • 3
    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. – Gerben Jan 8 '18 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 '18 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. – Majenko Jan 8 '18 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 '18 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 '18 at 11:07
0

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 '18 at 11:39
  • Sure, if that's what they are doing requires them to do... – Majenko Jan 8 '18 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 '18 at 12:08
  • You mean besides the one I already show in my answer? – Majenko Jan 8 '18 at 12:09
  • yes, it would help – Jim Jan 8 '18 at 12:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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