Shop OBEX P1 Docs P2 Docs Learn Events
Precise calculation of frequencies? — Parallax Forums

Precise calculation of frequencies?

Oldbitcollector (Jeff)Oldbitcollector (Jeff) Posts: 8,091
edited 2010-09-07 18:54 in Propeller 1
I've got a project I'm working on which requires some very
precise toggling of an I/O line. Naturally I've done delays with waitcnt, but never anything this accurate.

Here's what I'm playing with... (at 80mhz of course.)
4.672 hertz
2.336 hertz
1.168 hertz
.586 hertz
.292 hertz
.146 hertz
.073 hertz

Can someone guide me into how I to calculate pin toggling this precise?
Is this even possible?

Thanks!
OBC

Comments

  • lonesocklonesock Posts: 917
    edited 2010-09-07 11:52
    Even at 50ppm crystal tolerance, you can get to the precision you requested. Unless you are asking how to calculate the # clocks? With those kinds up update speeds, you could use the SPIN-only float library, calculating between each pulse, and still have plenty of time to spare [8^). The 0.073 Hz is nearing the maximum wait time, though (53 seconds being your max, of course...though it's easy to daisy-chain a few waitcnts).

    Jonathan
  • HarleyHarley Posts: 997
    edited 2010-09-07 11:59
    I don't know all your requirements, but

    80,000,000 Hz/4.672 Hz = 17123287.67; round up to 17123288

    80,000,000/17123288 = 4.6719999 Hz

    Would that be too far off? And is this to be a square wave or just a pulse of some width?
  • Mike GreenMike Green Posts: 23,101
    edited 2010-09-07 11:59
    First you have to calculate # system clocks per toggle from the frequency.

    # system clocks per toggle = (# system clocks per second / frequency in Hz) / 2

    You'll need to do this on paper to keep as much precision as you can.

    Since the Spin overhead per toggle is fixed, you could just use this number first, time some large number of toggles, and then adjust the # system clocks per toggle to adjust for the fixed overhead.
    loopWait := cnt
    repeat
       !out[pinNumber]
       waitcnt(loopWait += clocksPerToggle)
    
  • pjvpjv Posts: 1,903
    edited 2010-09-07 13:21
    Hi OBC;

    I have a very simple answer for you, provided the timing application can be run in assembler. With this approach you can precisely time pulses to 1 uSec granularity, and to 1 clock cycle accuracy.

    I have another (again, assembler only) approach that will time any (reasonable) pulsewidth to 1 clock granularity as well as accuracy.

    Your app code required is simply:

    ======================================
    V1Pulser long uSecTicks <<9 + Pulser ,1 'two longs here

    Pulser xor outa,#PortBit
    jmp #KernelPause
    ======================================

    and the kernel takes care of the rest.

    This can also run concurrently with other kernel scheduled co-operative assembler programs in the same cog, such as serial I/O ar butto-push scanners.

    Let me know if this is interesting to you, and I'll send you the kernel.


    Cheers,

    Peter (pjv)
  • ericballericball Posts: 774
    edited 2010-09-07 18:24
    Let's see what can be done with the counters...
    In NCO mode the output frequency = (FRQA / 2^32) * system frequency, or the reverse:
    FRQA = 2^32 * output frequency / system frequency.
    4.672	Hz	FRQA := 251	(4.675Hz)
    2.336	Hz	FRQA := 125	(2.328Hz)
    1.168	Hz	FRQA :=  63	(1.173Hz)
    0.586	Hz	FRQA :=  31	(0.577Hz)
    0.292	Hz	FRQA :=  16	(0.298Hz)
    0.146	Hz	FRQA :=    8	(0.149Hz)
    0.073	Hz	FRQA :=    4	(0.075Hz)
    

    The PLL modes require a FRQA frequency of 4-8MHz and the smallest multiplier is 1/8 FRQA. For 0.073Hz you'd need a 2^-25 multiplier, or 2^-22 beyond the PLL divisor. You could use the video generator, but you would need to periodically WAITVID to reload the pixel shifter.
  • KyeKye Posts: 2,200
    edited 2010-09-07 18:54
    Look into using NCO mode with the counter modules. Low numbers can get you speeds slower than 1 pulse per second.
Sign In or Register to comment.