Page 1 of 2

Frequency Measurement on digital input

Posted: Tue Jul 24, 2018 9:56 pm
by rodmcm
Enclosed is a program to measure the frequency of a square wave on a digital input. The program uses a free running timer/counter and digital interrupts. Hope this assists someone out there....


Code: Select all

/* 
Measures the frequency of a square wave appliet to a digital input
Uses a free running timer/counter for the period measurement
by: rodmcm
date: 25/7/2018
*/

const byte        interruptPin = 23;              // Assign the interrupt pin
volatile uint64_t StartValue;                     // First interrupt value
volatile uint64_t PeriodCount;                    // period in counts of 0.000001 of a second
float             Freg;                           // frequency     
char              str[21];                        // for printing uint64_t values
 
hw_timer_t * timer = NULL;                        // pointer to a variable of type hw_timer_t 
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;  // synchs between maon cose and interrupt?


// Digital Event Interrupt
// Enters on falling edge in this example
//=======================================
void IRAM_ATTR handleInterrupt() 
{
  portENTER_CRITICAL_ISR(&mux);
      uint64_t TempVal= timerRead(timer);         // value of timer at interrupt
      PeriodCount= TempVal - StartValue;          // period count between rising edges in 0.000001 of a second
      StartValue = TempVal;                       // puts latest reading as start for next calculation
  portEXIT_CRITICAL_ISR(&mux);
}


// Converts unit64_t to char for printing
// Serial.println(uintToStr( num, str ));
//================================================
char * uintToStr( const uint64_t num, char *str )
{
  uint8_t i = 0;
  uint64_t n = num;
  do
    i++;
  while ( n /= 10 );
  
  str[i] = '\0';
  n = num;
 
  do
    str[--i] = ( n % 10 ) + '0';
  while ( n /= 10 );

  return str;
}

// SetUp
//======================================
void setup() 
{
  Serial.begin(115200);
  pinMode(interruptPin, INPUT_PULLUP);                                            // sets pin high
  attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, FALLING); // attaches pin to interrupt on Falling Edge
  timer = timerBegin(0, 80, true);                                                // this returns a pointer to the hw_timer_t global variable
                                                                                  // 0 = first timer
                                                                                  // 80 is prescaler so 80MHZ divided by 80 = 1MHZ signal ie 0.000001 of a second
                                                                                  // true - counts up
  timerStart(timer);                                                              // starts the timer
}

void loop() 
  {
  portENTER_CRITICAL(&mux);
  Freg =1000000.00/PeriodCount;                       // PeriodCount in 0.000001 of a second
  portEXIT_CRITICAL(&mux);
  Serial.print("Frequency   ");Serial.println(Freg,2);
  delay(200);
  }
 

Re: Frequency Measurement on digital input

Posted: Thu Jul 26, 2018 3:41 pm
by Anderson_Oli
Good Morning.
I'm starting on ESP32, I see it's good with TIMER.
You could give an example of how I can use a timer, so that from a button I can turn on an LED and wait 500ms for the led to turn off.
but without the use of delay ().
If this help is possible, I thank you. :D

Re: Frequency Measurement on digital input

Posted: Fri Jul 27, 2018 1:18 am
by ESP_Sprite
@Anderson_Oli: For something like this, I suggest you use the esp_timer API. There's an example for this in esp-idf: esp-idf/examples/system/esp_timer

Re: Frequency Measurement on digital input

Posted: Fri Oct 19, 2018 10:18 am
by Don Warr
"Hope this assists someone out there...." Yes I'm sure, future google searchers like me will be happy you shared..
You never added what the top frequency you were able to achieve, or the amount of jitter (digit bobble) you got.. Can you share that, as slew and rise times are a big secret, and never talked about anywhere...

Re: Frequency Measurement on digital input

Posted: Fri Oct 19, 2018 11:31 am
by ESP_Sprite
Note that this possibly is not the best approach to do frequency measurement... there are other posts as well that use peripherals (MPWM or pulse counter, I don't remember) that get up to 40MHz, which in theory is the limit of anything going through the GPIO matrix. Those measurements should have a jitter of 1/40MHz. Not sure about slew rates.

Re: Frequency Measurement on digital input

Posted: Sat Oct 20, 2018 4:37 am
by Don Warr
Thank's For your input " ESP_Sprite" .. After decades with microchip, I am just now evaluating the ESP32,, What a wonderful little chip this is.. I threw together the code of "rodmcm"'s and saw it does work well.. Are you just guessing at 40Mhz, or did you hear this somewhere..?? Nowhere, do I see a ESP32 datasheet that specifies, the characteristic specs, like input rise times clock ppm etc.. But rodmcm code, does give me a proof of concept, so now I will checkout the "peripherals (MPWM or pulse counter" you suggested..
Thank's ...

Re: Frequency Measurement on digital input

Posted: Sat Oct 20, 2018 7:34 am
by ESP_Sprite
40MHz is because all peripherals as well as the GPIO matrix work at the APB frequency of 80MHz. They will sample the GPIO once per 80MHz clock tick, and as such 40MHz is the maximum they will be able to measure (without aliasing).

Re: Frequency Measurement on digital input

Posted: Mon Jul 15, 2019 5:57 am
by TinkerBearNZ
Wouldn't you get more accuracy by using a hardware signal to gate the counter?

Like... using a 5Hz signal from the LEDC, fed to a GPIO that's also used as the counter gate. Then it's just a matter of adding an interrupt routine on the negative edge of the gate signal to grab the count.

I've had to poke around in the GPIO matrix to avoid using a second GPIO pin, but this does actually work.

My one remaining problem is that sometimes the low-speed LEDC pwm channel I'm using as a gate signal doesn't start, depending on what other LEDC channels are running. I don't have a reliable workaround yet.

Re: Frequency Measurement on digital input

Posted: Thu Aug 29, 2019 12:37 am
by dfabro
Hello everyone.
I am working on a prototype device. It reads the speed of a gasoline engine from the ignition coil signal.
Dear TinkerBearNZ, I have no words to thank. You can't imagine how much it helped me. Thank you very much.
The world needs people like you. Selfless help.
Strong hug.

Re: Frequency Measurement on digital input

Posted: Thu Aug 29, 2019 3:28 pm
by dfabro
My previous thanks is to rodmcm.

Thanks for sharing the code Mr Rodmcm