understanding attachinterrupt in a pulse counter

Hi, The programme i have has been sourced from another forum member after googling the task at hand which is counting the pulses from a slot interrupt counter on a drive shaft. it works well, but unfortunately my brain doesn't and a key part of the programme is a mystery to me:
When a rising voltage is detected, the interrupt service routine function is jumped to ISRcount and the pilse is added to the integer 'count'. What I don't understand is what happens then, because if the loop resumes, then count=0 is set and then copycount is printed - I don't understand how the pulses are being added to integer count several times (about 200/sec in my case). So my specific question is what is the path of the programme from the first pulse being detected being added to integer count and then the next one being added to count and so on... how does this happen before the count is reset to zero ?
Would someone be able to walk through the path of the programme?

//https://forum.arduino.cc/index.php?topic=401987.0
// count encoder pulses on a motor

volatile unsigned long  count = 0;              // +1 each time interrupt calls ISR
unsigned long copyCount = 0;                    // accumulates the interrupt count, after 
unsigned long lastRead = 0;
unsigned long interval = 100;                   // interval must be set <= delay (eg 100, 100) set in the loop otherwise rps becomes amplified upwards
unsigned long speed = 0;

void setup()
{
  Serial.begin(9600);

  pinMode(2, INPUT_PULLUP);                   // set pin 2 as input and high when no input
  attachInterrupt(0, isrCount, RISING);       // interrupt programme when signal to pin 2 detected (0 = pin 2 and 1 = pin 2)
                                              // count when rising, call ISR function when happens (irs = interupt service routine)

//  pinMode(21, INPUT);                                            //  ?
//  attachInterrupt(digitalPinToInterrupt(21), speed, FALLING);    //  ?
}

void loop()
{
  if (millis() - lastRead >= interval)      // read interrupt count every 0.1 second (100 ms). NB ~30 loops per milli sec
  {
    lastRead  += interval;                  // add interval int to lastRead int
                                            // disable interrupts,make copy of count,reenable interrupts
    noInterrupts();                         // don't interrrupt to count on pin while copying count
    copyCount = count;
    count = 0;                              // reset count to 0
    interrupts();                           // switch on interrrupts again

    Serial.println(copyCount);              
   Serial.println(millis());                

  }
}

void isrCount()
{
  count++;                              // put pulses in here
}

if the loop resumes, then count=0 is set and then copycount is printed

This only happens every 100 milliseconds because it is controlled by

  if (millis() - lastRead >= interval)      // read interrupt count every 0.1 second (100 ms). NB ~30 loops per milli sec

The code inside the

if (millis() - lastRead >= interval)

only runs once every 100 millisecs.

During that interval every time an ISR is triggered the value in the variable count is incremented.

At the end of the interval the accumulated value is copied into the variable copyCount and the value of count s set back to zero ready to be incremented again during the next interval.

So what gets printed by the line

Serial.println(copyCount);

is the number of counts in the most recent 100 millisecs.

Does that help?

...R

Thanks. I kind of understand, but when I write out what's happening, I get stuck at the end, so let's start at the loop:

loop (let's assume a change in state detected while in IF part of loop, so millis has just ticked over to 100...)

if
100 - 0 >= 100 (YES, go ahead - it looped 1000s of times before millis got up to 100 ms)

then add interval to lastRead ( 0 + 100 = 100, new val of lastRead )

stop interrupt while counting

put val of count in copyCount ( 0, at the moment)

start interrupt ability again

lets assume encoder ticks.... as it would if motor spinning at 230 rps (6 v)... the programme interrupts and ISR
isrCount is called: integer count is increased by +1 then loop starts again:

100.01 - 100 >= 100 (NO, so don't go into IF loop.... assume it tool 10 micro sec to get through the programme loop)

So if the IF loop doesn't run how does the ISR function get to be called and so add more pulses to the count integer ??

The ISR will be called at any time the trigger condition is met whether that is inside the if or not as long as interrupts are enabled

Just to add -
That's the point of an interrupt.

Whatever the code is doing - as long as that interrupt is enabled - the trigger event will 'interrupt' the current instruction sequence, and then return to the same spot in code when the ISR has completed.

You don't have to do anything special to receive an interrupt - as long as you return from the ISR as quickly as possible - ready for another/next event.

mechengncl:
if
100 - 0 >= 100 (YES, go ahead - it looped 1000s of times before millis got up to 100 ms)

[....]

put val of count in copyCount ( 0, at the moment)

If the Arduino has been running for 100 millisecs I don't understand your thinking when you assume that the value in the variable count will be zero?

If you explain your thinking it will be easier to help.

...R

Robin2:
If the Arduino has been running for 100 millisecs I don't understand your thinking when you assume that the value in the variable count will be zero?

If you explain your thinking it will be easier to help.

...R

Yes I don't know why this is so hard either as I am fairly intelligent (!) but programming is simply not my forte, to put it mildly...

My (flawed) thinking:

Before I start, there a couple of things I realised: 2 counts per rev on the encoder and so a readout of 20, 20, 20, etc means 20/2 = 10 pulses per 100 ms i.e. 100 per sec and so 6000 rpm

Lets say the motor starts (~6000 rpm, which is ~100 revs/sec (200 pulses/sec), or 20 per 0.1 sec) and the encoder starts ticking, the first pulse means the IRS is called and a count is incremented in integer 'count'.

As someone said above, the programme returns to the last place it left in the if loop so as the loop is running so quickly then I assume it must get to the point where the count = 0 is set before the ISR is triggered again as the loop runs faster than the encoder triggering... obviously this is wrong, but I don't get why, I just can't 'see' what the controller is 'thinking'.

Hope you can help walk through hat logic.

mechengncl:
as the loop is running so quickly then I assume it must get to the point where the count = 0 is set before the ISR is triggered again

NO.

This line of code prevents that from happening

 if (millis() - lastRead >= interval)

The code inside that IF clause will only be activated once every 100 millisecs even though loop() might have repeated a 100 times in that period.

A good way to figure out how a computer program works is to get a pencil and paper and work through the program line by line writing down the results of each line as you go - using your brain as the microprocessor.

...R