Skip to main content
weeooweeooo spelling police
Source Link
endolith
  • 29k
  • 24
  • 121
  • 184

If possible I'd suggest selecting a microcontroller that supports a counter operation using the timer inputs; rather than manually incrementing a counter inside an ISR (which at high frequencies quickly ends up saturating the microcontroller activity) you allow the hawrdwarehardware to handle the counting. At this point your code simply becomes a matter of waiting for your periodic interrupt then calculating the frequency.

To extend the range and make the frequency counter more generalised (removing the need for multiple ranges at the expense of a little more work for the MCU) you could use the following technique.

Select a periodic interrupt rate that allows for measurement accuracy at the highest input frequency; this should take into account your counter size (you need to select the timer period such that the timer counter will not overflow at the maximum input frequency). For this example I'll assume that the input counter value can be read from the variable "timer_input_ctr".

Include a variable for counting periodic interrupts (should be initialised to 0 at startup); for this example I'll refer to this variable as "isr_count". The interrupt period is contained in the constant "isr_period".

Your periodic interrupt should be implemented as (C pseudo-code):

void timer_isr()
{
  isr_count++;
  if (timer_input_ctr > 0)
  {
    frequency = timer_input_ctr / (isr_count * isr_period).
    timer_input_ctr = 0;
    isr_count = 0;
  }
}

Obviously this rough example relies on some floating point math that may not be compatible for low-end microcontrollers, there are techniques to overcome this but they are outside of the scope of this answer.

If possible I'd suggest selecting a microcontroller that supports a counter operation using the timer inputs; rather than manually incrementing a counter inside an ISR (which at high frequencies quickly ends up saturating the microcontroller activity) you allow the hawrdware to handle the counting. At this point your code simply becomes a matter of waiting for your periodic interrupt then calculating the frequency.

To extend the range and make the frequency counter more generalised (removing the need for multiple ranges at the expense of a little more work for the MCU) you could use the following technique.

Select a periodic interrupt rate that allows for measurement accuracy at the highest input frequency; this should take into account your counter size (you need to select the timer period such that the timer counter will not overflow at the maximum input frequency). For this example I'll assume that the input counter value can be read from the variable "timer_input_ctr".

Include a variable for counting periodic interrupts (should be initialised to 0 at startup); for this example I'll refer to this variable as "isr_count". The interrupt period is contained in the constant "isr_period".

Your periodic interrupt should be implemented as (C pseudo-code):

void timer_isr()
{
  isr_count++;
  if (timer_input_ctr > 0)
  {
    frequency = timer_input_ctr / (isr_count * isr_period).
    timer_input_ctr = 0;
    isr_count = 0;
  }
}

Obviously this rough example relies on some floating point math that may not be compatible for low-end microcontrollers, there are techniques to overcome this but they are outside of the scope of this answer.

If possible I'd suggest selecting a microcontroller that supports a counter operation using the timer inputs; rather than manually incrementing a counter inside an ISR (which at high frequencies quickly ends up saturating the microcontroller activity) you allow the hardware to handle the counting. At this point your code simply becomes a matter of waiting for your periodic interrupt then calculating the frequency.

To extend the range and make the frequency counter more generalised (removing the need for multiple ranges at the expense of a little more work for the MCU) you could use the following technique.

Select a periodic interrupt rate that allows for measurement accuracy at the highest input frequency; this should take into account your counter size (you need to select the timer period such that the timer counter will not overflow at the maximum input frequency). For this example I'll assume that the input counter value can be read from the variable "timer_input_ctr".

Include a variable for counting periodic interrupts (should be initialised to 0 at startup); for this example I'll refer to this variable as "isr_count". The interrupt period is contained in the constant "isr_period".

Your periodic interrupt should be implemented as (C pseudo-code):

void timer_isr()
{
  isr_count++;
  if (timer_input_ctr > 0)
  {
    frequency = timer_input_ctr / (isr_count * isr_period).
    timer_input_ctr = 0;
    isr_count = 0;
  }
}

Obviously this rough example relies on some floating point math that may not be compatible for low-end microcontrollers, there are techniques to overcome this but they are outside of the scope of this answer.

Source Link
timrorr
  • 1.7k
  • 10
  • 10

If possible I'd suggest selecting a microcontroller that supports a counter operation using the timer inputs; rather than manually incrementing a counter inside an ISR (which at high frequencies quickly ends up saturating the microcontroller activity) you allow the hawrdware to handle the counting. At this point your code simply becomes a matter of waiting for your periodic interrupt then calculating the frequency.

To extend the range and make the frequency counter more generalised (removing the need for multiple ranges at the expense of a little more work for the MCU) you could use the following technique.

Select a periodic interrupt rate that allows for measurement accuracy at the highest input frequency; this should take into account your counter size (you need to select the timer period such that the timer counter will not overflow at the maximum input frequency). For this example I'll assume that the input counter value can be read from the variable "timer_input_ctr".

Include a variable for counting periodic interrupts (should be initialised to 0 at startup); for this example I'll refer to this variable as "isr_count". The interrupt period is contained in the constant "isr_period".

Your periodic interrupt should be implemented as (C pseudo-code):

void timer_isr()
{
  isr_count++;
  if (timer_input_ctr > 0)
  {
    frequency = timer_input_ctr / (isr_count * isr_period).
    timer_input_ctr = 0;
    isr_count = 0;
  }
}

Obviously this rough example relies on some floating point math that may not be compatible for low-end microcontrollers, there are techniques to overcome this but they are outside of the scope of this answer.