[Nano RP2040] Frequency counter problem

Hello, I'm new to Arduino, and I want to build a frequency counter to read the 5V 50% duty cycle at frequencies ranging from 1Hz to 500Hz. After completing my literature review, I found a decent program that fulfills my requirements. So, I am using a signal generator to produce the square wave and a Nano RP2040 to do the job. However, when I try to increase the refresh rate to 100ms, the reading accuracy is very poor. Below is the Arduino program. Could anyone please suggest a solution to increase the refresh rate? Thank you.

//freq counter reads sine, square, and triangle waves
unsigned long currentMillis; // current time in milliseconds
unsigned long lastMillis; // time of the last reading in milliseconds
unsigned long duration; // duration between readings in milliseconds
int pulseHigh; // flag for detecting a high pulse
int pulseLow; // flag for detecting a low pulse
long halfCycles; // count of half cycles
long cycles; // count of full cycles
int in = LOW; // input pin state

void setup () {
  pinMode(3, INPUT); // set pin 3 as input
  Serial.begin(9600); // initialize serial communication
  Serial.println("The frequency is displayed in Hertz"); // print message to serial monitor
}

void loop () {
  lastMillis = millis(); // get the current time

  // Read input and measure pulse duration
  do {
    in = digitalRead(3); // read the state of pin 3
    currentMillis = millis(); // get the current time
    duration = currentMillis - lastMillis; // calculate the duration since the last reading

    // Check if the input is high
    if (in == HIGH) {
      pulseHigh = 1; // set the high pulse flag
    }

    // Check if the input is low
    if (in == LOW) {
      pulseLow = 1; // set the low pulse flag
    }

    // Check if both high and low pulses occurred
    if (pulseHigh == 1 && pulseLow == 1) {
      halfCycles = halfCycles + 1; // increment the half cycle count
      pulseHigh = 0; // reset the high pulse flag
      pulseLow = 0; // reset the low pulse flag
    }
  } while (duration < 1000); // repeat until 1 second has elapsed (looking for cycles per second)

  cycles = halfCycles / 2; // divide by two, as there are two half cycles in a full cycle

  Serial.println(cycles); // print the frequency in Hertz

  cycles = 0; // reset the cycle count
  halfCycles = 0; // reset the half cycle count

  delay(1000); // delay for 1 second before taking the next reading
}

Where in your program do you set the refresh rate?
Why do you want it faster than 100ms?
That is about as fast your eyes can see... so you will not win much...

The program wasn't made by me. I expected that changing the "duration<1000" and "delay(1000)" would increase the refresh rate; however, it seems that it does not...

I also don't understand why you are need so quick to refresh. Have you tried increasing the speed on the serial communication though? For example, instead of 9600 it is 115200 or even more.

What accuracy do you expect?
If you have 1 Hz and take 100ms to measure, it does not surprise me if it is 10% off...

I want to make a digital speedometer for my motorcycle. The MCU will output the engine revolution in terms of frequency, within a range around the maximum frequency of 500Hz, which equals 15,000rpm. I am using the Nano RP2040 to project the frequency onto an LCD display. However, a refresh rate of 1 second is quite low for my application.

I have tried increasing the baud rate, but it had no effect. Therefore, I am seeking advice on how to increase the refresh rate.

My expectation of accuracy is up to 1Hz, actually the operating frequecy range would be 30Hz - 300Hz.


If the refresh rate is too low, it will miss some details.

Hello 6n_fighter

Welcome to the worldbest Arduino forum ever.

Measure the time between two rising edges and derive the frequency.

Have a nice day and enjoy coding in C++.

If the frequency is 300Hz and you want to count 300 pulses, then it will take 1second to do - you can't get round that.

If you don't want to wait for a full second, then the thing to do is measure the period of the signal instead and use:

frequency = 1/ period

to calculate what the frequency is.
Do the timing over several cycles to get an average period.

Now you have a refresh every 2 sec.
Why not remove delay(1000)?
That will speed up things by a factor 2....

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.