DSPRelated.com
Forums

Detecting Frequency

Started by Sheva Forever April 12, 2004
Hi, I am trying to detect the frequency of an incoming signal (from another
DSP) by counting the number of zero crossing.
I have developped this code but something doesn't seem right and I can't
figure out exactly what. Can anybody help me?

for(;;){

     temp = (int)MCBSP_READ(PORT_0);
     incsig[n] = (float)temp;

     while (!incsig[n]){
       for (n=0; n<400; n++){
       refsample = incsig[n]*incsig[n+1];
       if(refsample <= 0){
        count += 1;
       }
       else{
        return;
       }
      }
     }


I couldn't really decipher exactly what you were trying to do in the
code.  But the bit about looking for a sign change is headed in the
right direction.  The idea is to look for how many samples occur
between sign changes, by performing a count of the samples that occur
between the sign changes.  You get even more accuracy if you
interpolate between the 2 samples that change signs, to the zero
point.

Once you know how many samples are between two consecutive zero
crossings, use that to divide into the sample rate, and multiply by 2
( since it's only 1/2 period between each zero cross ) to get the
frequency.

You might also apply some sort of averaging or filtering to the
results of your frequency calculations, to smooth our jitter.

Regards,

Robert

www.gldsp.com


"Sheva Forever" <sheva@hotmail.com> wrote:

>Hi, I am trying to detect the frequency of an incoming signal (from another >DSP) by counting the number of zero crossing. >I have developped this code but something doesn't seem right and I can't >figure out exactly what. Can anybody help me? > >for(;;){ > > temp = (int)MCBSP_READ(PORT_0); > incsig[n] = (float)temp; > > while (!incsig[n]){ > for (n=0; n<400; n++){ > refsample = incsig[n]*incsig[n+1]; > if(refsample <= 0){ > count += 1; > } > else{ > return; > } > } > } >
( modify address for return email ) www.numbersusa.com www.americanpatrol.com
On Mon, 12 Apr 2004 22:19:36 GMT, "Sheva Forever" <sheva@hotmail.com>
wrote:

>Hi, I am trying to detect the frequency of an incoming signal (from another >DSP) by counting the number of zero crossing. >I have developped this code but something doesn't seem right and I can't >figure out exactly what. Can anybody help me? > >for(;;){ > > temp = (int)MCBSP_READ(PORT_0); > incsig[n] = (float)temp; > > while (!incsig[n]){ > for (n=0; n<400; n++){ > refsample = incsig[n]*incsig[n+1]; > if(refsample <= 0){..
This is a really poor way to detect changes in sign. For one thing it is slow because it uses a multiply. For another thing, it will fail if one of the samples is exactly zero. Why not do something really simple, like if( (sig[n] < 0 && sig[n+1] >= 0) || ( (sig[n] >= 0 && sig[n+1] < 0) ) count++; -Robert Scott Ypsilanti, Michigan (Reply through this forum, not by direct e-mail to me, as automatic reply address is fake.)
Robert Scott wrote:
> On Mon, 12 Apr 2004 22:19:36 GMT, "Sheva Forever" <sheva@hotmail.com> > wrote: > > >>Hi, I am trying to detect the frequency of an incoming signal (from another >>DSP) by counting the number of zero crossing. >>I have developped this code but something doesn't seem right and I can't >>figure out exactly what. Can anybody help me? >> >>for(;;){ >> >> temp = (int)MCBSP_READ(PORT_0); >> incsig[n] = (float)temp; >> >> while (!incsig[n]){ >> for (n=0; n<400; n++){ >> refsample = incsig[n]*incsig[n+1]; >> if(refsample <= 0){.. > > > This is a really poor way to detect changes in sign. For one thing it > is slow because it uses a multiply. For another thing, it will fail > if one of the samples is exactly zero. Why not do something really > simple, like > > if( (sig[n] < 0 && sig[n+1] >= 0) || > ( (sig[n] >= 0 && sig[n+1] < 0) ) count++; > > > -Robert Scott > Ypsilanti, Michigan > (Reply through this forum, not by direct e-mail to me, as automatic reply address is fake.)
The simplest way I know is to XOR the two bit by bit and branch on sign. Assembler makes short work of it with two or three instructions if the operands are already in registers. Jerry -- Engineering is the art of making what you want from things you can get. &#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;
"Robert Scott" <no-one@dont-mail-me.com> wrote in message
news:407b5026.24142750@news.provide.net...
> On Mon, 12 Apr 2004 22:19:36 GMT, "Sheva Forever" <sheva@hotmail.com> > wrote: > > >Hi, I am trying to detect the frequency of an incoming signal (from
another
> >DSP) by counting the number of zero crossing. > >I have developped this code but something doesn't seem right and I can't > >figure out exactly what. Can anybody help me? > > > >for(;;){ > > > > temp = (int)MCBSP_READ(PORT_0); > > incsig[n] = (float)temp; > > > > while (!incsig[n]){ > > for (n=0; n<400; n++){ > > refsample = incsig[n]*incsig[n+1]; > > if(refsample <= 0){.. > > This is a really poor way to detect changes in sign. For one thing it > is slow because it uses a multiply. For another thing, it will fail > if one of the samples is exactly zero. Why not do something really > simple, like > > if( (sig[n] < 0 && sig[n+1] >= 0) || > ( (sig[n] >= 0 && sig[n+1] < 0) ) count++; >
Thank you everybody for the help. I appreciate it. Ok, so I have an incoming signal which is a sinusoid formed by DSP #1 with the following interrupt: #define pi 3.141592653589 #define PORT_0 0 #define sampling_rate 8000 #define left_f0 1000. //frequency of left sine wave #define right_f0 2000. //frequency of right sine wave #define twopi 2.0*pi #define fc 8000. //carrier frequency interrupt void tx_isr(void) { static float left_angle = 0; static float right_angle = 0; float left_sample = 15000.0*sin(left_angle); float right_sample = 15000.0*sin(right_angle); float sample = ((int)left_sample)<<16; float temp = ((int)right_sample) & 0x0000FFFF; sample += temp; while (!MCBSP_XRDY(PORT_0)); MCBSP_WRITE(0, sample); left_angle += (twopi*left_f0/fc); right_angle += (twopi*right_f0/fc); if(left_angle >= twopi) left_angle -= twopi; if(right_angle >= twopi) right_angle -= twopi; } for(;;) In DSP #2 I want to receive it, detect its frequency and if the frequency is the one I am expecting then send an acknoledgment back to DSP#1 (Transmitter). I will implement a similar interrupt that checks given the right frequency. How do I estimate the frequency? What am I doing wrong? How many times should the for loop for n run? Is deltat found like I did? Thank you. for(;;){ temp = (int)MCBSP_READ(PORT_0); incsig[n] = (float)temp; for (n=0; n<?; n++){ //How many times? refsample = incsig[n]*incsig[n+1]; if( (sig[n] < 0 && sig[n+1] >= 0) || ( (sig[n] >= 0 && sig[n+1] < 0) ) { zerocrossing += 1; } numberofperiods = (zerocrosssing/2); //calculate number of periods samplesperperiod = n/numberofperiods; //calculate number of samples per period } deltat = 1/sampling_rate; //Not sure this is the way to calculate deltat period = (deltat*samplesperperiod); //Find the period frequencyinc = 1/period; //Find frequency of incoming signal } }
There is another problem with merely detecting zero crossings.
Real-world signals always have some noise.  There may be times when a
single zero crossing appears as three zero crossings because of this
noise.  The solution that you apply depends on the nature of the noise
and the range of expected frequencies and amplitudes.  If you are
assured of some minimum amplitude, then you can implement hysteresis
in your detection, so that the signal needs to be above a certain
positive number to detect a rising edge and below a certain negative
number to detect a falling edge.  You may also want to implement a
minimum pulse time.  When a transition is detected, refuse to detect
the opposite transition for a certain length of time.  That time limit
would depend on the maximum frequency that needs to be detected.


-Robert Scott
 Ypsilanti, Michigan
(Reply through this forum, not by direct e-mail to me, as automatic reply address is fake.)
Robert Scott wrote:
> This is a really poor way to detect changes in sign. For one thing it > is slow because it uses a multiply.
I presume he's using a TI DSP since he's got a call with "MCBSP" in the function name. That means that a multiply takes a single cycle. I'd bet the farm that his original implementation with one multiply and one branch is faster than the suggestion you've provided:
> if( (sig[n] < 0 && sig[n+1] >= 0) || > ( (sig[n] >= 0 && sig[n+1] < 0) ) count++;
Which has up to four compares and who-knows-how-many branches. Branches are more expensive than multiplies because they flush pipelines. -- Jim Thomas Principal Applications Engineer Bittware, Inc jthomas@bittware.com http://www.bittware.com (703) 779-7770 Things could be a lot better around here, but worse is more likely - Calvin
On Tue, 13 Apr 2004 09:25:58 -0400, Jim Thomas <jthomas@bittware.com>
wrote:

>I'd >bet the farm that his original implementation with one multiply and one >branch is faster than the suggestion you've provided:.
...maybe. But it is also wrong because the multiply method fails if a single sample is exactly zero. -Robert Scott Ypsilanti, Michigan (Reply through this forum, not by direct e-mail to me, as automatic reply address is fake.)
Robert Scott wrote:

> On Tue, 13 Apr 2004 09:25:58 -0400, Jim Thomas <jthomas@bittware.com> > wrote: > > >>I'd >>bet the farm that his original implementation with one multiply and one >>branch is faster than the suggestion you've provided:. > > > ...maybe. But it is also wrong because the multiply method fails if a > single sample is exactly zero. > > > -Robert Scott > Ypsilanti, Michigan > (Reply through this forum, not by direct e-mail to me, as automatic reply address is fake.)
It's a "don't care" if a sample is zero, so no answer is wrong. Jerry -- Engineering is the art of making what you want from things you can get. &#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;
On Tue, 13 Apr 2004 12:00:48 -0400, Jerry Avins <jya@ieee.org> wrote:

>It's a "don't care" if a sample is zero, so no answer is wrong.
In the OP's multiply method, you get: 9 9 * 7 is not negative, so no edge detected 7 7 * 3 is not negative, so no edge detected 3 3 * 0 is not negative, so no edge detected 0 0 * -1 is not negative, so no edge detected -1 -1 * -3 is not negative, so no edge detected -3 -3 * -7 is not negative, so no edge detected -7 -7 * -10 is not negative, so no edge detected -10 ..etc. If he had changed the criterion to strictly positive, then that would not have worked either, because then the above sequence would have detected two edges when there was only one. -Robert Scott Ypsilanti, Michigan (Reply through this forum, not by direct e-mail to me, as automatic reply address is fake.)