# Measure square wave frequency

I'm working with the Arduino Due ans I used the following code:

``````// period of pulse accumulation and serial output, milliseconds
#define MainPeriod 100
long previousMillis = 0; // will store last time of the cycle end
volatile unsigned long duration=0; // accumulates pulse width
volatile unsigned int pulsecount=0;
volatile unsigned long previousMicros=0;

void setup()
{
Serial.begin(19200);
attachInterrupt(6, myinthandler, RISING);
}

void loop()
{
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= MainPeriod)
{
previousMillis = currentMillis;
// need to bufferize to avoid glitches
unsigned long _duration = duration;
unsigned long _pulsecount = pulsecount;
duration = 0; // clear counters
pulsecount = 0;
float Freq = 1e6 / float(_duration);
Freq *= _pulsecount; // calculate F
// output time and frequency data to RS232
Serial.print(currentMillis);
Serial.print(" "); // separator!
Serial.print(Freq);
Serial.print(" ");
Serial.print(_pulsecount);
Serial.print(" ");
Serial.println(_duration);
}
}

void myinthandler() // interrupt handler
{
unsigned long currentMicros = micros();
duration += currentMicros - previousMicros;
previousMicros = currentMicros;
pulsecount++;
}
``````

to measure the frequency.

I can measure frequencies higher than 1.5kHz accurately, but I can't seem to measure lower frequencies.

How can I measure lower frequencies, say 400Hz and above?

Thanks.

• What is the output on a 400mHz wave? Just 0 and 0? Or wildly varying results? Jul 28 '14 at 20:30

It seems you have a problem of concurrent access to `duration` and `pulsecount` variables which are inter-related; with your code, it is possible that (and I guarantee that it will):

1. `loop()` reads `duration` value (in line `unsigned long _duration = _duration;`) but gets interrupted before executing the next line
2. `myinthandler()` changes both `duration` and `pulsecount` (it cannot be interrupted as it is already triggered by an interrupt)
3. `loop()` proceeds to where it was interrupted (after `myinthandler()` returns) and executes line `unsigned long _pulsecount = pulsecount;`: the values in `_duration` and `_pulsecount` do not match anymore!

To protect the access to `pulsecount` and `duration` variables, you have to disable interrupts inside `loop()` just for the time you get their values:

``````void loop() {
...
// Disable interrupts while we get and reset duration and pulsecount
cli();
unsigned long _duration = duration;
unsigned long _pulsecount = pulsecount;
duration = 0; // clear counters
pulsecount = 0;
// Now we can re-enable interrupts again
sei();
...
}
``````