PDA

View Full Version : Measure Frequency



Travin77
- 1st July 2006, 16:45
Hello all,

I have been searching through the forum looking for a way to measure frequency. I found the Pulsin command but it may not be fast enough. I am using a 16f876a @ 20mhz. I will need to measure 2 seperate frequency streams ranging from 9490 hz to 8225 hz. It seems pulsin at 20 mhz can only see 1000 hz? Can someone suggest another solution or will pulsin work for me. Thanks

Travin

dhouston
- 1st July 2006, 17:18
Look at the COUNT command.

mister_e
- 1st July 2006, 22:37
Or use a internal counter... wich i tend to use now as it can work in background allowing to do something else in meantime.

mister_e
- 2nd July 2006, 01:49
quick example of it


'
' Pic Configuration
' =================
DEFINE LOADER_USED 1
DEFINE OSC 20

'
' Hardware configuration
' ======================
TRISA = 255 ' PORTA : all input
CMCON = 7 ' disable analog comparator
ADCON1 = 7 ' disable ADCs
OPTION_REG = %11100001 ' TMR0 clock source = T0CKI (RA.4)
' Source edge : low to high
' Prescaller assign to TMR0
' rate 1:4

'
' Serial Communication definition
' ===============================
DEFINE HSER_RCSTA 90h
DEFINE HSER_TXSTA 24h
DEFINE HSER_SPBRG 129 ' 9600 Bauds

'
' Variables definition
' ===================
Frequency var word
TMR0IF var INTCON.2

'
' ------------------------[Program Start Here]--------------------------
'
Start:
TMR0=0 ' clear TMR0
IF PORTA.4=1 THEN START ' wait 'till T0CKI goes to low
PAUSE 100 ' sampling time
Frequency=TMR0<<2 ' multiply result to compensate the 1:4 rate
if tmr0if then ' Overflow? frequency over 256*4=1.024 Khz
hserout ["Overflow Happened",13,10] '
tmr0if=0 ' clear overflow flag
else
hserout ["Frequency:",dec Frequency dig 2,".",_ ' display results
dec Frequency dig 1,_
dec Frequency dig 0," KHZ",13,10]
endif

goto start

Travin77
- 3rd July 2006, 00:44
Thanks for the help. I am going to try them both to see which is better for me. I appreciate it a lot.

Travin

Brock
- 4th July 2006, 06:42
How accurate does it have to be? If it can be off by a few Hz, then you could
try my method. I don't have the code on this computer, so I'll try to explain it.

Use an interupt input such as INT0 and INT1. Create a subroutine to measure
the frequency of each pin seperately and disable interupts, set the appropriate
edge type and configure a timer such as Timer 1.

First clear the interupt flag. Then, in a tight loop, poll the interupt flag until you
see it, then clear it again and start the timer. Then, in another tight loop, poll
the interupt flag until you see it. Then read the timer register and turn the
timer off. You should also add a count function in the loops that will time out
after a while and let the program continue if there is no pulse on the input. I'll
post an example when I get a chance.

Keep commands in the measuring loop to a minimum to reduce the latency. This
still may not be fast enough for the frequencies that you are talking about,
but it seems to work pretty good at lower frequencies.

mister_e
- 4th July 2006, 07:42
there's tons of different ways... CCP in capture mode is another one. The Microchip CCP Tips and Trick is a great source of 'how to'.

The main advantage of the RA.4 T0CKI is that it's simple to use, effort less and plah plah.

Clear Timer
Do your sampling time
Read Timer

That's it. Now you can do it much complex and cross connect an INT pin to detect the rising or falling edge of your signal to do it automatically for you in background. In conjunction with a TIMER interrupt... things are just perfect. Somewhere in your INT routine, you may use a NewFrequencyAvailable to be poll in the main. Uneless this flag is not clear, it will never redo the frequency count.

This allow also an interesting feature... with the cross connect pin stuff you may also measure the period of a pulse and adjust the prescaller and/or the sampling time to be sure to don't overflow the counter. I think the microchip Frequency Counter example (a while back) use something like that.

Some PIC allow another pin and a 16 Bit Timer when you need it. T1CKI is often the name used for. Playing with the sampling time will give you the accuracy you need within the range you need.

1Sec Sampling time give you an accuracy of +/- 1Hz for a max of 65.536 KHZ
100mSec :655.36 KHZ +/- 10HZ
and so on.

Now.. i'm really asking myself why i did as much explanation... bah if this could be handy for somebody...

Brock
- 5th July 2006, 01:27
Try mister_e's method... mine sucks in that frequency range. It works fine
below 1 kHz, which works for my application.