View previous topic :: View next topic |
Author |
Message |
smiles
Joined: 20 Feb 2008 Posts: 33
|
Frequency counter |
Posted: Wed Mar 05, 2008 2:35 am |
|
|
My next work with PIC is count the frequency, could you tell me how to measure the frequency of a sine wave or even not sine wave, and which part of the PIC will contribute a lot in this measurement ?
Thanks so much !!! |
|
|
barata
Joined: 07 Feb 2008 Posts: 6 Location: Portugal
|
EX_FREQC.C |
Posted: Wed Mar 05, 2008 3:43 am |
|
|
Hi,
there are many ways to make this, here are two of them:
You can use a zero crossing detection like in the EX_FREQC.C in the examples of the compiler. this code works good i try it some years ago.
Other way is use a f/v conveter, is a IC how convert frequency in voltage, to can measure is ADC of the pic, is a simple hardware. |
|
|
smiles
Joined: 20 Feb 2008 Posts: 33
|
|
Posted: Thu Mar 06, 2008 7:19 am |
|
|
Hi thanks ! I read the example, I think coding now is not my big problem
The problem here is I don't understand so good about how to measure frequency with a PIC
I imagine quite simply that you put your signal to a pin, but what if that signal is negative at one time (pin receives negative voltage), what if that signal is high amplitude (like 220VAC), what are the components that can create frequency signal, is frequency measurement applied for synchronous signal and can we with our specified circuit just measure one range of frequency ?
Hope you answer me, thanks so much ! |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
|
Posted: Thu Mar 06, 2008 7:41 am |
|
|
smiles wrote: | ...I imagine quite simply that you put your signal to a pin, but what if that signal is negative at one time (pin receives negative voltage), what if that signal is high amplitude (like 220VAC), what are the components that can create frequency signal, ... |
You cannot connect any old signal to a PIC pin and just "measure its frequency". When people talk about using a PIC to measure frequency, they are usually thinking about a clean logic-level signal. Clean means just two logic transitions per cycle - one going high and one going low. If you have a high-amplitude signal, like 220 vac, then you must use a circuit to convert that signal into a clean logic signal.
If your signal is not clean, then there are several ways to clean it up. One is to use a comparator with hysteresis to ignore a little bit of noise that might be riding on top of the signal. Another method is to use time filtering - a one-shot for example, which ignores all transitions for a given period of time after a recognized transition. For this to work you need to know in advance approximately what the measured frequency must be so you can set the one-shot time period. Finally, for the case where the signal is really buried in lots of noise, like trying to detect the pitch of a flute in an orchestral recording, you will need to use very sophisticated signal processing methods, like the Fourier Transform, to isolate the frequency of interest.
Robert Scott
Real-Time Specialties |
|
|
smiles
Joined: 20 Feb 2008 Posts: 33
|
|
Posted: Fri Mar 07, 2008 2:48 am |
|
|
Thanks so much, I got some ideas !
Now I want to ask which pins is the best for receiving that signal (the signal for measuring frequency purpose) ? |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
|
Posted: Fri Mar 07, 2008 6:01 am |
|
|
smiles wrote: | ..which pins is the best for receiving that signal (the signal for measuring frequency purpose) ? |
Use a CCP pin. That will allow you to capture the value of Timer 1 on every rising edge of the signal being measured. If you subtract two of those captured Timer 1 values, you get the period between cycles. Count for several cycles to get an average value that is more accurate.
Robert Scott
Real-Time Specialties |
|
|
smiles
Joined: 20 Feb 2008 Posts: 33
|
|
Posted: Fri Mar 07, 2008 7:22 am |
|
|
Thanks Scott, I will simulate with Proteus first ! |
|
|
smiles
Joined: 20 Feb 2008 Posts: 33
|
|
Posted: Mon Mar 10, 2008 3:03 am |
|
|
Hi, this is my test circuit on Proteus (crystal 4MHz) http://img81.imageshack.us/img81/3371/88568235ij7.jpg, I put a pulse generator (100Hz,5V high and 0V low) to CCP1 pin, write the code as below but the value of frequency I got on LCD is <50 Hz always, what wrong with my code ?
(I will use probe of real oscilloscope to create pulse and applied to pin CCP1 on my real hardware, so try to test on simulate tool first)
Code: |
// GUIDED WORDS AND VARIABLES
int i=0;
int32 sum;
int16 pulseWidth[5],period,freq;
char words[]="THE VALUE OF FREQUENCY: ";
char words1[]=" >=50Hz";
char words2[]=" <50Hz";
....
#int_ccp1
void isr()
{
int16 currentCCP;
static int16 oldCCP = 0;
currentCCP=CCP_1;
pulseWidth[i]=currentCCP-oldCCP;
sum=sum+pulseWidth[i];
i++;
if(i==5)
{
period=sum/5; //average value of period
freq=1000000/period; //frequency value
disable_interrupts(GLOBAL);
disable_interrupts(INT_CCP1);
setup_timer_1(T1_DISABLED);
}
}
//**********************
void main()
{
// TODO: USER CODE!!
InitPic();
InitLcd();
Speech(words,0x00);
setup_ccp1(CCP_CAPTURE_RE); // Configure CCP1 to capture rise
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1); // Start timer 1
enable_interrupts(INT_CCP1); // Setup interrupt on falling edge
enable_interrupts(GLOBAL);
do
{
}
while(i!=5);
if(freq<50)
Speech(words2,0x80 + 0x40);
if(freq>=50)
Speech(words1,0x80 + 0x40);
do
{
}
while(1);
}
....
|
|
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
|
Posted: Mon Mar 10, 2008 5:30 am |
|
|
Are you sure sum is initialized to zero? It would be helpful if you could display some information - something more than just "<50" or ">50". For example, it would be interesting to see exactly what pulseWidth[0]...pulseWidth[4] are. Do it for several know frequency settings of your pulse generator. Then perhaps you can see a pattern that will lead you to the answer.
Robert Scott
Real-Time Specialties |
|
|
smiles
Joined: 20 Feb 2008 Posts: 33
|
|
Posted: Tue Mar 11, 2008 3:18 am |
|
|
Follow your advice and finally try this and it works (on simulation)
Thanks again !!!
Code: |
#int_ccp1
void isr()
{
int16 currentCCP;
if(start==1)
{
currentCCP=CCP_1;
pulseWidth=currentCCP-oldCCP;
freqNum=(float)1000000/pulseWidth;
freqRes=ceil(freqNum);
disable_interrupts(GLOBAL);
disable_interrupts(INT_CCP1);
setup_timer_1(T1_DISABLED);
i=1;
}
if(start==0)
{
oldCCP=CCP_1;
start=1;
}
}
|
|
|
|
|