Jump to content
aam

Frequency Measurement

Recommended Posts

Hello everybody,

 

I would like to measure the speed rotation of a motor. For this, i use a photodiode. The signal waveform is given by the picture.

I want to measure this signal frequency using the MSP430F5529 and Energia and display it in the serial monitor.

 

I know i have to use the Timer A in Capture/Compare mode but I don't know how. I saw a lot of codes but they use CCS and the MSP430g2553 and it is not clear for me.

 

How can I proceed to measure the frequency of my signal ? The frequency can vary from 50Hz to 500Hz.

 

Thank you for your help.

post-49371-0-59438300-1473957190_thumb.jpg

Share this post


Link to post
Share on other sites

Hi @@aam,

 

A while back I posted some Energia projects that were to be used as lessons for High School students.  You can find them here:  http://forum.43oh.com/topic/8766-energia-sensor-code-and-library-examples/

 

Keep in mind that these were written by a self taught hobbyist (me) for Energia beginners so expect simple concepts and demonstrations only.  In any event, there is one that uses a photoelectric sensor as a tachometer that you might want to look at:  https://github.com/fmilburn3/Tachometer_CNY70

 

Also, see CounterLib which is well written and documented and counts pulses.  It uses timers, is written for Energia, but would be easy to use in CCS also.

Share this post


Link to post
Share on other sites

Although you don't mention the resolution, the update rate, your experience level, and your application, you may want to consider this....

 

For low frequencies such as yours, you can measure the period between rising edges of the signal, then calculate it's reciprocal.

 

Many commercial frequency counters will do this. You'll get better resolution and faster update rate. And averaging is easier, to remove noise. Just mentioning this in the spirit of presenting an alternative.

 

Due to other activities at the moment, I don't have time to code an example, but it would go something like this, in Energia:

 

... Define a pin interrupt to trigger on the rising edge, using 'microseconds', get the time delay from the previous interrupt. (Or poll the pin for the transition).

 

... Optionally, average several samples.

 

... Calculate the inverse of the period to get the frequency.

 

... And output it on the serial port.

 

Hope this helps, if it's not what you're looking for, then the other methods mentioned on the forum are your best bet.

 

Cheers.

Share this post


Link to post
Share on other sites

Hello everybody,

 

Thank you for all your responses.

 

@@veryalive I have started to use energia two month ago for a project. So, i consider myself a beginner.

I have a BLDC motor and I would like to measure its speed rotation for a given current using a photodiode and a laser. The laser is constantly emitting the light on the photodiode. The propeller blade cuts the light periodically. Thus, it gives me a signal with a frequency. So, if I can measure this frequency i will be able to determine the speed rotation. I want a resolution of 0.1Hz if possible and an update rate of 1s.

 

@@jazz Thank you for this topic; unfortunately I don't familiarize with the assembly language and the sixth post. He uses the MSP430G2 do you you know how can use this sketch with an MSP430F5529 ?

 

@@Fmilburn Many thanks for all these examples. I tried both but I have some problem.

- Using the timer, I cannot measure frequencies below 1kHz, it displays 0kHz. I tried to change the formula to measure less high frequencies. I wrote this one:

void setup()
{
  Serial.begin(115200);
  MyCounter.start();   // start counter, divide clock by 16
}

void loop()
{
  MyCounter.reset();           // reset counter to zero
  delay(10);                  // wait 200 milliseconds
  Serial.print(((MyCounter.read()))*100);  // read counter, calculate kHz
  Serial.println(" kHz");
  delay(1000);                 // wait one second
}

 

However the resolution is horrible. For a 500Hz frequency, it measures a value between 200 and 600Hz.

Is it possible to measure an accurate frequency below 1kHz using this method ?

 

- The second using the ADC works but the update rate is too fast. I cannot see properly the frequency and when I increase the delay, the program is not capable of measuring the right frequency.

How can I do ?

 

Thank you

post-49371-0-70778900-1474274637.jpg

Share this post


Link to post
Share on other sites

@@jazz Thank you for this topic; unfortunately I don't familiarize with the assembly language and the sixth post. He uses the MSP430G2 do you you know how can use this sketch with an MSP430F5529 ?

 

It is same thing related to timers, MSP430G2 or MSP430F5529. Frequency meter on this topic is based on MSP430F5510, but firmware also can be uploaded to MSP430F5529 with 24 MHz XT2. Connect your input to TA0CLK or TA1CLK pin. You can try it, and if it is not what you want, find another solution for your project.

Share this post


Link to post
Share on other sites

Sorry @jazz  but I don't know how can I use these sketch in this topic http://forum.43oh.co...requency-meter/

There is no Energia sketch and when I upload the sketch in the sixth post, I have this error message

 

Energia: 1.6.10E18 (Windows 7), Board: "MSP-EXP430F5529LP"
Speed_Measurement_1.40:1: error: expected constructor, destructor, or type conversion before ';' token
Speed_Measurement_1.40:6: error: expected constructor, destructor, or type conversion before ';' token
Speed_Measurement_1.40:11: error: '::main' must return 'int'
Speed_Measurement_1.40:1: error: ISO C++ forbids declaration of 'TimerA0_ISR' with no type [-fpermissive]
Speed_Measurement_1.40:3: error: 'R10' was not declared in this scope
Speed_Measurement_1.40:6: error: ISO C++ forbids declaration of 'TimerA1_ISR' with no type [-fpermissive]
Speed_Measurement_1.40:8: error: 'R11' was not declared in this scope
Speed_Measurement_1.40:11: error: '::main' must return 'int':
Speed_Measurement_1.40:23: error: 'R10' was not declared in this scope
Speed_Measurement_1.40:24: error: 'R11' was not declared in this scope
exit status 1
expected constructor, destructor, or type conversion before ';' token

Could you tell me me what can I do please ? I have some problems with the timer concept to measure frequency.

 

Thank you

Share this post


Link to post
Share on other sites

@@aam

 

RE:  use of CounterLib - your code is below

void setup()
{
  Serial.begin(115200);
  MyCounter.start();   // start counter, divide clock by 16
}

void loop()
{
  MyCounter.reset();           // reset counter to zero
  delay(10);                  // wait 200 milliseconds
  Serial.print(((MyCounter.read()))*100);  // read counter, calculate kHz
  Serial.println(" kHz");
  delay(1000);                 // wait one second
}

Let's say you are trying to measure 125 Hz, i.e something that has a period of 8 ms.  You have set the delay above in loop() to 10 ms.  Accordingly, the counter will trigger either 1 or 2 times in the 10 ms set by your code resulting in poor resolution.  The problem is that the window of time is not long enough to get sufficient samples at that low frequency so increase the delay.  You must also carefully choose the divider used by the clock to avoid overflow and yet get sufficient resolution.  Timers are fairly sophisticated devices which Energia/Arduino abstract away.  The other example I posted may be easier to start off with.

 

RE: use of the CNY70 Tachometer

 

I can't really tell what the problem is from what you have posted - could either be code or hardware.  Try getting it to work one piece at a time.  For example, turn your motor slowly by hand and see if it detects HIGH and LOW properly by adding print statements.  Next, check the code to see if it is timing the duration between HIGH and LOW properly.  Try and isolate the problem.

Share this post


Link to post
Share on other sites

Re CounterLib: The first example given in the documentation may be a good starting point.

https://github.com/astuder/CounterLib-Energia

Counter<> MyCounter;    // create counter that counts pulses on pin P1.0
void setup()
{
  Serial.begin(9600);
  MyCounter.start();    // start counter
}
void loop()
{
  MyCounter.reset();                // reset counter to zero
  delay(1000);                      // wait one second
  Serial.println(MyCounter.read()); // read number of pulses during the last second
  delay(1000);                      // wait another second
}

Share this post


Link to post
Share on other sites

Hi,

 

Many thanks @Fmilburn and @@chicken, I've put the first delay at 1s second and the measure works better. For my test I use an signal generator because it's easier to change the frequency and I'm sure of the frequency value.

I have just two questions concerning the sketch and the resolution.

 

I understood why I have to choose a higher delay in order to allow the counter to trig more often and then have a better resolution. But when I increase the delay, the frequency measurement increases too. Is it because the counter triggers too much times and then the value is higher ? Should I change the formula in Serial.println to adjust the frequency ?

 

For a given frequency, I observe a kind of "offset" which increase with the frequency.

The pictures show the measurements when the frequency is equal to 50Hz, 200Hz, 500Hz and 700Hz.

Do you know why there is an offset in the measure ?

 

Thank you.

 

 

post-49371-0-60932700-1474463083.jpg

post-49371-0-06058600-1474463091.jpg

post-49371-0-88600300-1474463097.jpg

post-49371-0-30566600-1474463105.jpg

Share this post


Link to post
Share on other sites

There are sources of error in any measurement and to get better precision and accuracy you need to examine and address the sources.  For example:

  • The duration of the measurement as already discussed
  • The accuracy of the clock - which one to use?  An external crystal?  Is the temperature fixed and stable?  How stable is the voltage source?  See for example the tolerances of the DCO in the datasheet.  A half % error due to this is entirely possible if not using an external crystal.
  • Latency in the code - for example, when the timer is stopped there are CPU clock cycles that elapse before the measurement stops.

If you see consistent offset then one way to address it is to add the offset and correct.  All said, less than half percent error at 500 Hz isn't bad though and you cannot expect better than 2% for 50 Hz being measured over 1 second.

Share this post


Link to post
Share on other sites

@@aam to your question about the measurement time vs result:

Note that the library just counts pulses (or more precisely how often a signal changes from high to low low to high). The frequency in Hertz is calculated by dividing the number of counted pulses by the measurement time in seconds. Measuring for 1 second is the most convenient as no additional math is required.

You will notice that there's a trade-off between responsiveness (i.e. fast update rate) and precision (long measurement time).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×