i want to read frequency realtime

this code its from techone, but this only read the frequency of one second, but its there a possible way to read
“real time”, for example and oscillospe reads the frequency realtime, without counting it, like this code… im not making oscilloscope but its an example, i want to read frequency to make an inertial dyno… but i need the reading of angular velocity(rev per second) on real time(may be a delay)… hope anyone could help me clear this out

byte freqpin = 2;

unsigned long timeone;

unsigned int frequency;
unsigned int timediff;

unsigned int tcount=0;

// sample time of 1 second or 1000 ms.
unsigned int sampletime=1000;

volatile unsigned int count=0;

void setup()
{
 pinMode(freqpin, INPUT);
 attachInterrupt(0,freqinput,RISING);
 // set interrupt pin 2 and use rising ( from gnd to +5 ) 
  Serial.begin(9600); 
} 

void loop()
{
 /* Use while() loop and use millis(). 
    Calculate the time difference and compare the 
    value with the sample time. 
 */
 // activate the interrupt
 tcount=0;
 count=0;
 timediff=0;
 attachInterrupt(0,freqinput,RISING);

 timeone=millis();
 while(timediff<sampletime)
 {
  tcount=count;
  timediff=millis()-timeone; 
 }
 // de-activated the interrupt
 detachInterrupt(0);
 
 // Calculated frequency
frequency=tcount; 
 
 // Display frequency
 Serial.print("Test while - ");
 Serial.print("Frequency : ");
 Serial.println(frequency,DEC);
 delay (3000);
 
}  

// The interrupt routine
void freqinput ()
{
  count++;
}

What do you mean when you say "real time"?

i mean that every milisecond i get the real frequency of what i am meassuring an not just the counting of the frequency in a given time...

ok for me to explain just take a look in the code the code just counts the frequency so if a reduce the semple time to 500miliseconds and i imput a frequency of 10khz, arduino will print to serial only 5khz.... i dont want that, i want tha every 100miliseconds o maybe less arduino prints 10khz.... so i want the real frequency in serial always......

If you truly want or need 'real-time' frequency measurements then you have to leave the world of digital and build it in the analog world. There have been true F-to-V analog chips that output a DC measurement value proportional to the frequency of the input signal. However you are going to have to come up with requirement specifications before running off to find proper components and chips.

Frequency range, what is the minimum and maximum frequency to be measured. That is the minimum and maximum amplitude voltage of the input signal. What is wave form shape of the input signal. What DC measurement range do you require.

Now back to reality, frequency measurements are best done in the digital world and have been for a pretty long time. Just define how fast an update time you require and state the input frequency range to be measured, What measurement resolution you require and then see if there is not a digital solution to the problem. You know you don't have to count for a full second to measure the frequency of a signal?

Lefty

retrolefty: You know you don't have to count for a full second to measure the frequency of a signal?

Lefty

thats what i dont know how to program, the measureing of a frequency without countig for a full second for now in the code i just change the sampletime to 1 mili and before print just multiply by 1000 but it gives me a hugh error in the measuring.... for now "real time" i know its impossible to get. and probebly i dont need it i just need a faster update of the real frequency

copachino:

retrolefty:
You know you don’t have to count for a full second to measure the frequency of a signal?

Lefty

thats what i dont know how to program, the measureing of a frequency without countig for a full second for now in the code i just change the sampletime to 1 mili and before print just multiply by 1000 but it gives me a hugh error in the measuring… for now “real time” i know its impossible to get. and probebly i dont need it i just need a faster update of the real frequency

Well I will only give you a hint how the big boy frequency counters measure in much shorter update windows. Instead of counting the input signal for a fixed period, they something take a high speed fixed oscillator, say 10mhz, and let the input signal define the gate time for counting the those fixed frequency pulses. So say you have a 60hz input signal to be measured. You start counting the 50mhz pulses at the zero crossing of the 60hz signal and stop counting at the next zero crossing. You then end up with the number of 100nsec counts for a 8.333millisecond period. A little math and you will have a new measurement in well under 10millsec time span.

I’m sure the same principles can be applied to an arduino using it’s built in timers, proper commands and calculations. However again until you define your specific specifications of the input signal it’s hard to start.

Lefty

thanks for replying...... i am reading an analog sensor which was adapted for a square signal needed for hardware interrupts, the are measuring speed of an engine, in an oscilloscope readings are 10,680hz, and if a use the code from above it oscilates in that frequency but if a change sample time to reduce it and then multiply the output if gives likes 20% error....

the signal its square from 5v to 0v

Your problem is the counts in the sample time. For example, if you sample for 1 mS then the number of counts would be:

.001 / (1 / 10680) = 10.68

In other words, it will count either 10 or 11 maybe. My tests of a frequency of 10680 bear this out:

Frequency: 11000
Frequency: 10000
Frequency: 11000
Frequency: 11000
Frequency: 10000

If you count for 2 mS you will get:

.002 / (1 / 10680) = 21.36

That is, 21 or 22 counts.

We are now closer:

Frequency: 10500
Frequency: 10500
Frequency: 10500
Frequency: 10500
Frequency: 10500
Frequency: 11000
Frequency: 11000
Frequency: 11000

So you have the trade-off, of faster results vs. lower accuracy.

Frequency is a time domain phenomenon, that does not exist instantaneously.

If you know a whole lot about the signal (what the waveform is, what the amplitude is, what the likely frequency range is, etc), then you can take a few quick samples of the signal, and fit those samples to your model of the waveform, to estimate the frequency. However, that's always an application-specific "tunable" process, not a "true" frequency measurement.

A good middle ground mostly-well-behaved signals is to measure the time between zero crossings -- typically in one particular direction (say, negative to positive). Keep the time of the last zero crossing, and the next time it happens, subtract that time from the current time. Invert, to get an estimate of frequency. You can keep multiple samples of zero crossings in a FIFO to measure across more cycles, and get more stability but slower response time to changes.

[quote author=Nick Gammon link=topic=91219.msg684985#msg684985 date=1328843491] Your problem is the counts in the sample time. For example, if you sample for 1 mS then the number of counts would be:

.001 / (1 / 10680) = 10.68

In other words, it will count either 10 or 11 maybe. My tests of a frequency of 10680 bear this out:

Frequency: 11000
Frequency: 10000
Frequency: 11000
Frequency: 11000
Frequency: 10000

If you count for 2 mS you will get:

.002 / (1 / 10680) = 21.36

That is, 21 or 22 counts.

We are now closer:

Frequency: 10500
Frequency: 10500
Frequency: 10500
Frequency: 10500
Frequency: 10500
Frequency: 11000
Frequency: 11000
Frequency: 11000

So you have the trade-off, of faster results vs. lower accuracy. [/quote] well i will have to guest how many samples per second are needed for a good test graph.......and also get good frequency reads..... any filter o something else could be possible applied to get the nearest possible to real frequency??

retrolefty:
Well I will only give you a hint how the big boy frequency counters measure in much shorter update windows. Instead of counting the input signal for a fixed period, they something take a high speed fixed oscillator, say 10mhz, and let the input signal define the gate time for counting the those fixed frequency pulses.

Based on Lefty’s suggestion I have adapted my earlier timing sketch to use this method.

// Frequency timer
// Author: Nick Gammon
// Date: 10th February 2012

volatile boolean first;
volatile boolean triggered;
volatile unsigned long overflowCount;
volatile unsigned long startTime;
volatile unsigned long finishTime;

// here on rising edge
void isr () 
{
  unsigned int counter = TCNT1;  // quickly save it
  
  // wait until we noticed last one
  if (triggered)
    return;

  if (first)
    {
    startTime = (overflowCount << 16) + counter;
    first = false;
    return;  
    }
    
  finishTime = (overflowCount << 16) + counter;
  triggered = true;
  detachInterrupt(0);   
}  // end of isr

// timer overflows (every 65536 counts)
ISR (TIMER1_OVF_vect) 
{
  overflowCount++;
}  // end of TIMER1_OVF_vect


void prepareForInterrupts ()
  {
  // get ready for next time
  EIFR = _BV (INTF0);  // clear flag for interrupt 0
  first = true;
  triggered = false;  // re-arm for next time
  attachInterrupt(0, isr, RISING);     
  }  // end of prepareForInterrupts
  

void setup () {
  Serial.begin(115200);       
  Serial.println("Frequency Counter");
  
  // reset Timer 1
  TCCR1A = 0;
  TCCR1B = 0;
  // Timer 1 - interrupt on overflow
  TIMSK1 = _BV (TOIE1);   // enable Timer1 Interrupt
  // zero it
  TCNT1 = 0;     
  // start Timer 1
  TCCR1B =  _BV (CS20);  //  no prescaling

  // set up for interrupts
  prepareForInterrupts ();   
  
} // end of setup

void loop () 
  {

  if (!triggered)
    return;
 
  unsigned long elapsedTime = finishTime - startTime;
  float freq = 1.0 / ((float (elapsedTime) * 62.5e-9));  // each tick is 62.5 nS
  
  Serial.print ("Took: ");
  Serial.print (elapsedTime);
  Serial.print (" counts. ");

  Serial.print ("Frequency: ");
  Serial.print (freq);
  Serial.println (" Hz. ");

  // so we can read it  
  delay (500);

  prepareForInterrupts ();   
}   // end of loop

This sets up Timer 1 as a high-resolution timer, that is, it ticks every clock cycle, namely every 62.5 nS.

We connect our input to D2 and look for rising interrupts (so from one rising pulse to the next is the period). By counting how many lots of 62.5 nS we got we can work out the period. Take the inverse and we have the frequency. Like this, for 10,680 Hz:

Took: 1499 counts. Frequency: 10673.78 Hz. 
Took: 1499 counts. Frequency: 10673.78 Hz. 
Took: 1499 counts. Frequency: 10673.78 Hz. 
Took: 1499 counts. Frequency: 10673.78 Hz. 
Took: 1497 counts. Frequency: 10688.04 Hz. 
Took: 1499 counts. Frequency: 10673.78 Hz. 
Took: 1501 counts. Frequency: 10659.56 Hz. 
Took: 1500 counts. Frequency: 10666.67 Hz. 
Took: 1499 counts. Frequency: 10673.78 Hz. 
Took: 1499 counts. Frequency: 10673.78 Hz. 
Took: 1497 counts. Frequency: 10688.04 Hz. 
Took: 1497 counts. Frequency: 10688.04 Hz. 
Took: 1499 counts. Frequency: 10673.78 Hz. 
Took: 1501 counts. Frequency: 10659.56 Hz. 
Took: 1499 counts. Frequency: 10673.78 Hz. 
Took: 1502 counts. Frequency: 10652.46 Hz. 
Took: 1501 counts. Frequency: 10659.56 Hz.

This sketch seems to work up to about 90 KHz, after which it can’t keep up.

1 Like

amazing, ive just uploaded and seems to be a lot more stable than the old one.... probably with a low-pass filter this could be more accurate.......... but this code need all arduino speed right??? so wont be enable to process a filter???

Well you can do whatever you want. :)

After all, we are reading an almost-instantaneous frequency (by measuring a single period). So you can do whatever, and then measure another one.

I added a simple counter, like this:

unsigned long foo;

And then in loop:

void loop () 
  {

  foo++;
  
  if (!triggered)
    return;

// .. and the rest of it

At 10680 Hz foo got up to around 41, so you could add up 41 things while it was actually counting.

probably could try something to improve those jumps in frequency but im testing 10khz as signal and thats a lot more than i need in fact so for less speed i supposed there are more accuracy.... ill try with 1khz an see if it goes well than i wont use anything to try to improve this, if its needed probably youll se me asking for help here again.....

thanks so much for sharing the code

My pleasure. At 1 KHz I got a pretty accurate reading:

Took: 16015 counts. Frequency: 999.06 Hz. 
Counted up to: 520
Took: 16015 counts. Frequency: 999.06 Hz. 
Counted up to: 522
Took: 16017 counts. Frequency: 998.94 Hz. 
Counted up to: 521
Took: 16017 counts. Frequency: 998.94 Hz. 
Counted up to: 521
Took: 16016 counts. Frequency: 999.00 Hz. 
Counted up to: 518
Took: 16016 counts. Frequency: 999.00 Hz.

That's only 0.1% out.

still this is to much speed for a car wheel, so this code is more than perfect for my aplicattion, whta ar you using to inject the signal to arduino??

A Rigol function generator. Lets me dial up any frequency between about 1 Hz and 5 MHz, sine waves, square waves, etc.

pretty good jeeje e im using a ne555 but frequency its not always 1khz..... but this week i will try with the sensor from and see how it behaves.... probably not so accurate due an engine never have constants speed but reasonable accurate...... thanks for all the help

greets

Nick, you are an arduino software god in my eyes. :wink:

Aww, thanks Lefty! But it was your description that got me started. I suppose that is how scopes measure frequency too. You have on the screen a signal and it computes the period and thus the frequency, as long as you have at least one sample.

Anyway, I am hoping to improve the accuracy. After watching Dave Jones' video about surplus Rubidium Frequency Standards available on eBay cheap, I've ordered one. That is supposed to deliver a super-accurate 10 MHz signal. By using that as the source for Timer 1 rather than the internal clock you should be able to get a very accurate count (within the resolution that 10 MHz gives you).