Shop OBEX P1 Docs P2 Docs Learn Events
Frequency Counter with decimal — Parallax Forums

Frequency Counter with decimal

DigitalBobDigitalBob Posts: 1,513
edited 2015-02-19 17:02 in Propeller 1
Greetings All

Does anyone have a spin solution for a frequency counter that will read in decimal. Example 200.3 hertz or 1200.7 hertz, nothing high frequency maybe 10-20 KHz tops.
Thanks in advance

Bob

Comments

  • kwinnkwinn Posts: 8,697
    edited 2015-02-19 15:00
    Take a look at these objects. May not be exactly what you want but one of them should be a good starting point.

    http://obex.parallax.com/object/118
    http://obex.parallax.com/object/241
    http://obex.parallax.com/object/478
  • BeanBean Posts: 8,129
    edited 2015-02-19 15:38
    Here is one I wrote in PropBasic (spin files are included, but they are PASM).

    http://forums.parallax.com/showthread.php/123170

    Bean
  • localrogerlocalroger Posts: 3,451
    edited 2015-02-19 16:02
    You're not going to be able to do that with raw counting because you'd have to accumulate for 10 seconds. You'll have to measure the period and divide into CLKFREQ. At 20 KHz one cycle is 4,000 80 MHz clocks, so to get 200,000 clocks (for 0.1 Hz accuracy) you would need to time the period of 500 cycles. At 1 KHz this will take half a second, so you'd probably want to sample a single cycle and then use that estimate to figure out how long a train to count for fine accuracy. I suspect measuring the period of a train of N pulses is something the counter-timers can do but I haven't worked with them enough to know how. I'd probably just do it in PASM by using WAITPEQ in a countdown loop. That way it would be extremely simple.
  • edited 2015-02-19 17:02
    DigitalBob wrote: »
    Greetings All

    Does anyone have a spin solution for a frequency counter that will read in decimal. Example 200.3 hertz or 1200.7 hertz, nothing high frequency maybe 10-20 KHz tops.
    Thanks in advance

    Bob

    I recently had a similar problem. I knew the wavelength in clock ticks but needed an accurate frequency to three decimal places for display purposes. Note the use of the modulas operator ( // ) in line 3.

    clkfreq: 80_000_000 ticks
    wavelength : 1_340_005 ticks
    clkfreq / wavelength = 59.701
    WaveLength := 1340005
    WholeFreq := clkfreq / WaveLength                '59
    FractionalFreq := clkfreq // WaveLength          '939_705
    FractionalFreq := FractionalFreq * 1000          '939_705_000
    FractionalFreq := FractionalFreq / WaveLength    '701
    

    I then displayed the two variables ( WholeFreq and FractionalFreq ) seperated by a decimal point.

    Sandy
  • Problem Solved

    I received some good tips but no cigar. I saw this post written by someone and tweeked it to give the desired output. It works good for my needs I'm only interested in the low end 400 hz , 1800 hz. etc.. I gets it a little sloppy above 2000 hz. You can tweek the math and waitcnt to give the desired output.

    { Frequency Counter






    }


    CON

    _xinfreq = 5_000_000
    _clkmode = xtal1 + pll16x


    LCD_Pin = 1 'The LCD is connected to pin A0.
    LCD_Baud = 19_200 'Baud
    LCD_Lines = 2 'The number of lines on this LCD
    In = %0
    On = 1
    Off = 0
    G=0.1


    CountPin = 5 'Input Pin for counter




    Obj


    LCD : "debug_lcd" 'Creates the object LCD from "debug_lcd"
    F : "FloatMath"
    FS : "FloatString"



    Var

    long Cog
    long PNCount[2] '0 is posicount 1 is neg count
    Long Frequency
    long X1
    long X2

    Pub Main | TotCnt , freq




    Cog := cognew(@entry, @PNCount[0] ) + 1











    If LCD.init(LCD_Pin, LCD_Baud, LCD_Lines) 'Initialize the LCD object LCD.Cursor(Off) 'Set cursor off
    LCD.Backlight(True) 'Set backlight on
    LCD.Cls

    Repeat


    LCD.Gotoxy(0,0)
    LCD.str(string("pos")) 'Positive Count
    LCD.dec( PNCount[0] )
    ' LCD.out($0D)
    LCD.Gotoxy(8,0)
    LCD.str(string("neg="))
    Lcd.dec( PNCount[1] )



    TotCnt := (PnCount[0] *100) / (PnCount[0] + PnCount[1])

    LCD.Gotoxy(8,1)
    Lcd.str(string("Dec")) '% Positive
    Lcd.str( x2 ) 'Displays float string



    Freq := (12000 * 5556 ) / ( (PnCount[0] + PnCount[1]) ) 'Tweek the math for desire reading


    X1:= F.FFloat(freq) ' Converts Freq to a float

    X2:=(FS.FloatToString(F.FMul(x1,g))) 'Converts float to string

    LCD.Gotoxy(0,1)
    Lcd.str(string("frq="))
    Lcd.dec( Freq )




    waitcnt(clkfreq * 1 + cnt )

    lcd.cls
    LCD.Backlight(True) 'Set backlight on


    PUB stop

    if Cog
    cogstop(Cog~ - 1)










    DAT

    org 0
    entry

    {
    '
    Debugger Kernel add this at Entry (Addr 0)
    long $34FC1202,$6CE81201,$83C120B,$8BC0E0A,$E87C0E03,$8BC0E0A
    long $EC7C0E05,$A0BC1207,$5C7C0003,$5C7C0003,$7FFC,$7FF8
    '
    }
    '


    muxz dira , PinMask ' Configure Pin as inputs (0) as Z is zero

    mov addr , par 'par has address of first variable to write back which is PosCnt
    add addr, #$4 'This is address of second variable to write back NegCnt

    :MainLoop mov PosCnt ,#0 'set counters to zero
    mov NegCnt ,#0 wc 'set counters to zero c set to zero
    waitpne PinMask , PinMask 'waits for negative on input ina
    waitpeq PinMask , PinMask 'waits for positive on input


    :PosLoop Add PosCnt , #1 'adds 1 to positive count
    Test PinMask , ina wz 'tests and sets z= 0 if both = 1
    'if both are = 1 then result is 1 and z = 0

    if_NZ jmp #:Posloop 'stays in loop as long as input is high z=0


    :NegLoop Add NegCnt , #1 'adds 1 to positive count
    Test PinMask , ina wz 'tests and sets z= 0 if both = 1
    'if both are = 1 then result is 1 and z = 0

    if_Z jmp #:Negloop 'stays in loop as long as input is low z=1

    Wrlong PosCnt , par
    Wrlong NegCnt , addr

    jmp :MainLoop




    ' VARIABLES

    PosCnt Long 0
    NegCnt Long 0
    PinMask long |< CountPin 'This creates a pin mask with a 1 and CountPin zeros to the right


    PinState res 1
    addr res 1 'register for sending data to main program




  • DigitalBob,

    Please see my note in your other post about how to post code in the forum.

    Thanks,
    -Phil
Sign In or Register to comment.