Shop OBEX P1 Docs P2 Docs Learn Events
How to measure frequency using smart pins ? — Parallax Forums

How to measure frequency using smart pins ?

BeanBean Posts: 8,129
edited 2018-10-01 14:29 in Propeller 2
In preparation for getting a P2 chip, my first project will be to very accurately measure the frequency of an input signal.
The input signal will be a square wave from 900Hz to 1100Hz measured for 1 second.

Looking at the smartpin docs, I assume I would use mode %10101 = For periods in X+ clock cycles, count time

But it appears this returns the total period, but how do I know how many cycles occurred within that total period ?

Basically I need to know how many cycles of the input occurred in how many clocks of the P2.
For example if the input was exactly 1000Hz, and the P2 is running at 200MHz and I sampled for 1 second,
I would expect to get the the values: 1000 and 200_000_000.

Do I need to use two smartpins ?

Any clarification would be appreciated.

Thanks, Bean

Comments

  • jmgjmg Posts: 15,148
    Chip needs to do some examples, but yes, for true reciprocal counters you use 2 pin cells, muxed onto the same pin.
    One cell captures cycles, the other captures time. This has a very wide dynamic range.

    For a narrow known range, you might be able to use that X+ set fixed to 1000, and get a time result (sysclks) in 900 to 1100ms
    An example is needed for that case too.
  • BeanBean Posts: 8,129
    edited 2018-10-22 13:04
    If you use an adjacent pin cell to measure cycles, can that hardware pin still be bit-banged and/or the state read by code ? Or is it totally unusable ?

    The problem I run into on the P1 is that if one of the inputs fails (doesn't change state), then the WAITPNE and WAITPEQ commands stop everything.
    I think I remember hearing that the P2 has time-outs on these. Is that true ? That would help a lot.

    Bean
  • For the WAITxxx instructions the following applies.
    By doing a SETQ right before one of these instructions, you can supply a future CT target value which will be used to end the wait prematurely, in case the event-occurred flag never went high before the CT target was reached. When using SETQ with ‘WAITxxx WC’, C will be set if the timeout occurred before the event; otherwise, C will be cleared.
  • Bean wrote: »
    In preparation for getting a P2 chip, my first project will be to very accurately measure the frequency of an input signal.
    The input signal will be a square wave from 900Hz to 1100Hz measured for 1 second.

    Looking at the smartpin docs, I assume I would use mode %10101 = For periods in X+ clock cycles, count time

    But it appears this returns the total period, but how do I know how many cycles occurred within that total period ?

    Basically I need to know how many cycles of the input occurred in how many clocks of the P2.
    For example if the input was exactly 1000Hz, and the P2 is running at 200MHz and I sampled for 1 second,
    I would expect to get the the values: 1000 and 200_000_000.

    Do I need to use two smartpins ?

    Any clarification would be appreciated.

    Thanks, Bean

    I think the mode you want is %01110 (Count A-input positive edges), at least for the 1000 part. I don't understand why you'd use a smart pin to get back the 200_000_000 part.
  • evanhevanh Posts: 15,192
    edited 2018-10-22 16:21
    Hi Bean,
    Lots of choices for how:
    - You could very precisely do that just with inline WAITSE1 and GETCT duo, respectively, looping for each interval until you've got enough data. There is plenty of time between pulse periods to make decisions and even emit progress for monitoring. Each new interval reading is referenced to first edge detection, so fully retained information extending out as long as you like. An extended version of this - https://forums.parallax.com/discussion/169129/increasing-the-resolution-of-pulse-timing


    - Smartpins have multiple modes that can cover it. Many of them would be configured to report each pulse duration. Not really any different to the GETCT above. The ones of note would be:

    %10010 AND !Y[2] = Time X A-input highs/rises/edges: This one you specify how many pulses you want to count and it'll tell you how long that took. I'm unsure but I guess using rise setting will start timing on first rise so will give back precise rise to rise measurement.

    %10011 = For X periods, count time: Same as above (rise to rise setting) I think.


    EDIT: I just read your follow-up about lost signal. Right, so the software solution won't be good enough. The smartpins should be good for this. They can be monitored and reset at will.

  • evanhevanh Posts: 15,192
    edited 2018-10-22 16:34
    If you want to use smartpins to collect adjoining pulse intervals, same data as the software version but avoiding any WAITxxx instructions, then those same modes can be set to measure one pulse duration at a time. No missing information.

  • BeanBean Posts: 8,129
    I want to measure multiple frequencies with one cog.
    I also need "zero-dead-time", so there can't be any skipped cycles.
    This is why the frequency is so low (1KHz), so there is time to get the values from multiple pins.

    The way I do it with the P1 is to wait for an edge, then record CNT and the hardware counters count the cycles while I'm not looking.
    The measurements might include an extra cycle or two, but that doesn't matter as long as none are missed.

    Bean
  • evanhevanh Posts: 15,192
    edited 2018-10-22 16:56
    So there is gaps/missing pulses that you need extra detail about? ie: when and how long for.

    EDIT: Ah, you mean you want no gaps in the measuring. Yep, easy-pees.

    Here's a rough example:
    		dirl    #tpin
    		wrpin   #%10011_0, #tpin        'For X periods, count time.  (A == B == tpin)
    		wypin   #%00, #tpin             'A-input rise to B-input rise
    		wxpin   ##1000, #tpin           'measure time of 1000 pulses
    		dirh    #tpin                   'start now, hopefully first rise is measurement start
    
    		...
    checkcompletion
    		testp   #tpin         wz        'check for completion of pulse counting
    if_z		rdpin   ticks, #tpin            'grab total time of pulses
    if_nz		jmp     #checkcompletion
    		...
    
    
  • evanhevanh Posts: 15,192
    edited 2018-10-22 17:23
    BTW: That example doesn't stop with the first reading. It continues gapless into the next 1000 pulses. EDIT: So, you can keep adding the readings together to increase precision. And, because of this detail, you can also chop it up into smaller pieces for faster updates.

    The only restriction is you must be quick enough to read the current measurement before the next one arrives or it will be overwritten.

  • jmgjmg Posts: 15,148
    Bean wrote: »
    I want to measure multiple frequencies with one cog.
    I also need "zero-dead-time", so there can't be any skipped cycles.
    This is why the frequency is so low (1KHz), so there is time to get the values from multiple pins.

    The way I do it with the P1 is to wait for an edge, then record CNT and the hardware counters count the cycles while I'm not looking.
    The measurements might include an extra cycle or two, but that doesn't matter as long as none are missed.
    With the HW, you should be able to capture 60+ channel, on one COG, easily, in the capture X whole periods modes.
    They will all start within ~1ms windows, and you have 0.9~1.1s before the next capture arrives on that same channel.

    The 1-pin polling loop evanh coded above would change to be a test for any pin ready, then a store that pin 2-step.
    evanh wrote: »
    .... I'm unsure but I guess using rise setting will start timing on first rise so will give back precise rise to rise measurement.
    Yes, for the measure whole cycles modes, they queue once armed, and wait for a valid before starting.
    evanh wrote: »
    BTW: That example doesn't stop with the first reading. It continues gapless into the next 1000 pulses.
    IIRC some also have a clear-on-capture ability, and for those, Chip added a smarter clear, so that if an edge was arriving on the same edge as clear, it instead loads with 1.
    (that 0/1 choice should be clear of the -1 bug?)

    That means it should be both gapless and have zero missing/added edges.

    Seems Chip should send evanh & Bean P2 boards, so they can test the code snippets ?

    It would be great to see these Smart Pin capture/count modes verified in silicon, up to the same MHz the code appears to run to :)
    evanh wrote: »
    The only restriction is you must be quick enough to read the current measurement before the next one arrives or it will be overwritten.
    Is there any hardware overflow signal, to catch such an overwrite ? How do users know they have not missed a reading ?

  • evanhevanh Posts: 15,192
    jmg wrote: »
    How do users know they have not missed a reading ?

    By not being lazy farts. Code for real time operation and the problem goes away. The Prop is not a general computing platform where IRQ's commonly go to never-never-land.

  • jmgjmg Posts: 15,148
    edited 2018-10-22 19:40
    evanh wrote: »
    jmg wrote: »
    How do users know they have not missed a reading ?

    By not being lazy farts. Code for real time operation and the problem goes away. The Prop is not a general computing platform where IRQ's commonly go to never-never-land.

    Easy enough to say, but rather harder to prove to the management that you have a black-box that can 100% confirm no-missed-readings.
    That's why other MCUs often/usually have such overflow flags. It's because customers expect & make use of them.

    Take the example above, where someone has 60 channels ticking away..

    Now imagine because the COG is mostly idling, and other COGs are busy, they add some maths and serial reporting code, then the boss wants faster reporting rates...

    Things easily get incrementally more complex, but it passes all the bench tests.... and hey, we think we "Code for real time operation" so it will be fine ?

    Addit: Looking at the above, you could emulate an overflow flag in software, with more complex polling, and 60 poll-count variables that check you did have at least one empty poll between same channel readings. Perhaps those 60 can pack into 60 booleans, as you only need a >0 test ?
  • evanhevanh Posts: 15,192
    edited 2018-10-22 19:52
    It's too late if you've missed it, the failure will happen even if you know you've missed it. Knowing about it afterwards might help debug the buggy code, but, in the end you still have to make the code behave in realtime.

    You can still do your reports with realtime behaviour. You don't need any debug hand holding for that.

  • evanhevanh Posts: 15,192
    edited 2018-10-22 20:13
    Here's some tested code. It reports 11 exactly equal readings. So, the good news is the measuring does start from first rising edge.
    'setup measuring
    		dirl    tpin
    		wrpin   ##%0001_0001_000_0000000000000_00_10011_0, tpin   'For X periods, count time.  (A == B == tpin+1)
    		wypin   #%00, tpin              'A-input rise to B-input rise
    		wxpin   ##1000, tpin            'measure time of 1000 pulses
    		dirh    tpin                    'start now, hopefully first rise is measurement start
    
    'produce some pulses
    		add     tpin, #1
    		dirl    tpin
    		wrpin   #%01_00101_0, tpin      'transition output
    		wxpin   ##(clock_freq/2000), tpin           '0.5 ms at 20 MHz
    		dirh    tpin                    'start now, actually at next transition period
    		wypin   ##22222, tpin           '2000 toggles = 1.0 seconds
    		sub     tpin, #1
    
    'check for readings
    		mov     bcdlen, #8
    .pintestloop
    		testp   tpin         wz         'check for completion of pulse counting
    if_z		rdpin   parm, tpin              'grab total time of pulses
    if_z		call    #itod
    		waitx   sec
    		mov     char, #"."
    		call    #putch
    		jmp     #.pintestloop
    
    
    PS: The waitx sec instruction is actually only 1/4 second.


    Here is actual output at the terminal (Using 20MHz sysclock):
    .....  20000000...  20000000....  20000000....  20000000....  20000000....  20000000....  20000000....  20000000....  20000000....  20000000....  20000000........................
    
    The leading spaces are because my integer print routine is fixed length.
  • Bean wrote: »
    I want to measure multiple frequencies with one cog.
    I also need "zero-dead-time", so there can't be any skipped cycles.
    This is why the frequency is so low (1KHz), so there is time to get the values from multiple pins.

    The way I do it with the P1 is to wait for an edge, then record CNT and the hardware counters count the cycles while I'm not looking.
    The measurements might include an extra cycle or two, but that doesn't matter as long as none are missed.

    Bean

    This still sounds like mode %01110 (Count A-input positive edges). If you want to do it the P1 way, you could run it in continuous mode (interval=0). However, if you use a non-zero interval, then you don't have to bother with capturing CNT anymore (or correcting the captured counter value). You specify the precise number of clock cycles to count for (in this case 200_000_000). When the interval is reached, the counter value is stored (to Z) and the counting starts over again for the same interval. True zero-dead-time. As long as you pull the value from Z before the next interval expires, you have in infinite series of precisely-measured edge counts (and therefore frequency).
  • jmgjmg Posts: 15,148
    evanh wrote: »
    Here's some tested code. It reports 11 exactly equal readings.
    So it does clear Z on capture ? Chip's docs are unclear on that mode.

  • evanhevanh Posts: 15,192
    edited 2018-10-22 20:53
    Yep, I think most counting modes do.

    EDIT: Modes that can be configured for continuous accumulation won't reset Z count.

  • evanhevanh Posts: 15,192
    Having the hardware not reset for each measurement is one way to carry on, in a corrective manner, in the event of missed events. It's certainly how I coded the wrapping machines because it was on PC hardware and DOS was the loader.

    If I remember rightly, I even raised this point when we were working on polishing the smartpins.

  • jmgjmg Posts: 15,148
    edited 2018-10-22 21:04
    evanh wrote: »
    Having the hardware not reset for each measurement is one way to carry on, in a corrective manner, in the event of missed events. It's certainly how I coded the wrapping machines because it was on PC hardware and DOS was the loader.

    If I remember rightly, I even raised this point when we were working on polishing the smartpins.
    My suggestion was that Chip make the reset optional, but I think he likes the easier-use aspect of a clear, and the 0/1 starting avoids a pitfall other MCUs have.

    Even without reset, in some modes you cannot quite simply 'carry on, in a corrective manner' - eg here, you would report twice the dT* for what you thought was 1000 cycles, but was actually 2000. If you are lucky, and a 2:1 range is not needed, you can use a value sanity check, but many systems have very wide dynamic ranges.
    * I'm assuming the next capture simply replaces the last one.

    I'm interested to see how a Reciprocal Counter works on real silicon, as there you need two pin-cells working in sync, to capture dT and dC.
  • evanhevanh Posts: 15,192
    For positional readings, it very much helps to know the extra. But really, missing events is just bad and your system is broken.

  • jmgjmg Posts: 15,148
    edited 2018-10-22 21:16
    Seairth wrote: »
    This still sounds like mode %01110 (Count A-input positive edges). If you want to do it the P1 way, you could run it in continuous mode (interval=0). However, if you use a non-zero interval, then you don't have to bother with capturing CNT anymore (or correcting the captured counter value). You specify the precise number of clock cycles to count for (in this case 200_000_000). When the interval is reached, the counter value is stored (to Z) and the counting starts over again for the same interval. True zero-dead-time. As long as you pull the value from Z before the next interval expires, you have in infinite series of precisely-measured edge counts (and therefore frequency).

    I think Bean is chasing high precision here, so he is less interested in 'counting to 1000' than he is in timing exactly* how long 1000 cycles took,
    and also wants to do that over many pins.
    The P1 approach falls down, when you hope to do many pins. You run out of COGs or counters...

    P2 in mode %10011 = For X periods, count time can manage 60 or more pins, all from a single COG, because the hardware does all the heavy lifting.

    * eg 200MHz resolves to 5 micro-hertz in 1 second, and a P2 PLL locked to a ppb timebase can ensure these are genuine Hz
    1000*5n*(200M+1) = 1000.000005
    1000*5n*(200M-1) = 999.999995

  • evanhevanh Posts: 15,192
    edited 2018-10-22 21:14
    Doing a little reading - The quadrature counting mode is a good example of what Chip has done. It serves both periodic capture with Z count reset, and also continuous accumulation with no capture and no reset. So I guess most bases are covered. :)

  • evanhevanh Posts: 15,192
    edited 2018-10-22 22:03
    I did monitor for loss of servo timer IRQ on the wrappers. It even kept a running total of losses I think, was for debug to make sure I hadn't messed up.

    There was no special hardware assigned for the job. The method was simple enough, check ISR interval against a generic timer chip. So it easily knew if, say, a hundred consecutive IRQ's had been missed.

  • BeanBean Posts: 8,129
    Wow. Thanks for all the info guys.

    Our current setup with the P1 measures 8 channels and we can specify either an exact number of cycles to measure, or a total time to measure. The advantage of the exact cycles is that you don't need to store the number of cycles. So there is only one number to worry about.

    But some test require a certain gate time (+0 or +1 cycle). It totals until a rise time exceeds the limit, then returns cycles and clocks.

    We currently use 4 propellers in a 1U chassis to measure 32 channels. It would be great if one P2 could do that (and with better resolution). 240MHz would give us three times the resolution we have with the P1. And a much larger buffer to store readings.

    So if I follow evanh's code, you are only using one smart-pin cell ?

    Bean
  • evanhevanh Posts: 15,192
    Bean wrote: »
    So if I follow evanh's code, you are only using one smart-pin cell ?
    Correct.

  • jmgjmg Posts: 15,148
    edited 2018-10-23 06:00
    Bean wrote: »
    Our current setup with the P1 measures 8 channels and we can specify either an exact number of cycles to measure, or a total time to measure. The advantage of the exact cycles is that you don't need to store the number of cycles. So there is only one number to worry about.

    But some test require a certain gate time (+0 or +1 cycle). It totals until a rise time exceeds the limit, then returns cycles and clocks.

    We currently use 4 propellers in a 1U chassis to measure 32 channels. It would be great if one P2 could do that (and with better resolution). 240MHz would give us three times the resolution we have with the P1. And a much larger buffer to store readings.

    One P2 could easily manage 32 channels of the exact number of cycles to measure, as a single number consumes a single Smart Pin Cell.

    Getting 32 channels of returns cycles and clocks is tighter, as you need pins to boot the P2, but you also need 64 Smart Pin Cells, for the dual-capture info.

    Serial boot would use 2 pins, and there is a nearby-pin mapping ability in the smart pins, thus
     %AAAA:  ‘A’ input selector
                 0xxx = true (default)
                 1xxx = inverted
                 x000 = this pin’s read state (default)
                 x001 = relative +1 pin’s read state
                 x010 = relative +2 pin’s read state
                 x011 = relative +3 pin’s read state
                 x100 = this pin’s OUT bit from cogs
                 x101 = relative -3 pin’s read state
                 x110 = relative -2 pin’s read state
                 x111 = relative -1 pin’s read state
    
    That can skip-over 2 UART pins ok, but if you want SPI and UART and 32 channels of pair-captures, some external MUX help looks to be needed.

Sign In or Register to comment.