Periodically enabling interrupt 0


I have a rotary sensor with a reed switch, connected to an RC debounce circuit, finally connected to digital input 2 on a Duemilanove, like so:

  GND----o--<reed>----o-------> digital input 2
         |            |
         --| 100nF |---

In the sketch I'm using I attach an ISR to interrupt 0, wait a certain amount of time, detach the ISR and process the results. Within the ISR pulses are counted and some other stats gathered. In the testing I've done the frequency of the pulses is estimated to go up to about 10Hz. The outline of the sketch looks like this:

volatile uint16_t num_pulses;


    pinMode(2, INPUT);
    // Enable internal pull-up resistor
    digitalWrite(2, HIGH);    

    num_pulses = 0;
    // Clear any buffered interrupt 0
    EIFR = bit (INTF0);  
    attachInterrupt(0, isr, FALLING);    
    // Use num_pulses value, 
    // Compute some sutff,
    // Send some data over serial,
    // etc

    // Plus update some other statistics

The problem that I'm seeing is that with higher pulse frequencies the num_pulses counter contains wildly inaccurate values when accessed in loop() (much too high for the measurement time taken and feasible pulse rate).

One possibility is the RC debounce circuit is not adequate, but I'm also wondering about the structure of the sketch I'm using. From what I understand from Nick Gammon's pages on interrupts it would normally be necessary to protect access outside of an ISR to a value being updated in an ISR with a critical section in which interrupts are disabled, especially when a multi-byte value is updated, as I'm doing. However, the ISR here shouldn't be active when num_pulses is read, as detachInterrupt() has been called just before?

detach the ISR and process the results.

Don't do that just disable the interrupts.

One possibility is the RC debounce circuit is not adequate,

Yes that is what is causing you problems reed switches bounce more than a bucket full of frogs.

Use the millis timer so that you only update your counter after a specific time. The millis timer will not advance in an interrupt routine but it will be readable and you can store the results when you get an interrupt and ensure you don't count again until a certain time as passed.

Try changing the RC DEBOUNCE cap to 1 uF.