Shop OBEX P1 Docs P2 Docs Learn Events
measuring external pulse width and time intervals - what is the best resolution? — Parallax Forums

measuring external pulse width and time intervals - what is the best resolution?

JBealeJBeale Posts: 25
edited 2012-08-28 07:30 in Propeller 1
I do not yet have a Propeller system, I'm trying to find out if it is useful for my purposes. I read the data sheet but I have not yet understood enough to be able to answer my question below.

I want to be able to make high-resolution pulse width and time interval measurements. That is, say I have two signals, each connected to an input pin. Let's say there is a rising edge on pin A and about 10 microseconds later, there is a rising edge on pin B. Using the propeller chip and one or more cogs (?) what is the best resolution with which I can measure the time interval between the edges on pin A and B? Do I get the resolution of the system clock at 80 MHz (=> 12.5 nsec) or is it something slower due to some hub-synchronization requirements? Does the cog timer have direct hardware edge-capture, or do I need to poll the pin state in software, meaning I have at least a few clock cycles of uncertainty?

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2010-12-30 18:59
    JBeale wrote: »
    Using the propeller chip and one or more cogs (?) what is the best resolution with which I can measure the time interval between the edges on pin A and B? Do I get the resolution of the system clock at 80 MHz (=> 12.5 nsec) or is it something slower due to some hub-synchronization requirements? Does the cog timer have direct hardware edge-capture, or do I need to poll the pin state in software, meaning I have at least a few clock cycles of uncertainty?

    You can get system clock resolution with the usual off by one cycle uncertainty wrt when the edge/transition is sampled. While edge-capture is available in h/w it only applies to edge counting modes which isn't useful for your scenario. You may want to look at LOGIC counter modes like A != B. While both your inputs are low nothing happens. Then A has a low/high transition which enables the counter (A != B) and it's disabled again once B transitions to high. Whatever has now accumulated in the phsx register is your timing interval.

    That said, while counters can do lots of things without s/w support there are certain things they can't do without help. It'd be a good idea to get the requirements sorted beforehand. And feel free to ask more (specific) questions when you get there.
  • AmaralAmaral Posts: 176
    edited 2010-12-30 19:01
    Right on the money. 80Mhz will give you an 12.5 nsec.
    Yeap - the cog can capture a change of state of any pin. no clock cycles missing here !

    The only problem of the propeller is that it can cause addiction, than all the others 517 hobbies that you have will have to wait for implementations with the prop chip. !

    It's an stunting piece of infinite solutions !

    have fun !

    Amaral
  • AribaAriba Posts: 2,690
    edited 2010-12-31 00:10
    There are 2 special instructions which waits for a certain pin state: WAITPEQ WAITPNE.
    They work with system clock resolution.
    Here are possible code snippets in Assembly:
    ..
      waitpeq pinA,pinA   'delta between 2 pulses
      mov temp1,cnt       '___-_______A
      waitpeq pinB,pinB   '______-____B
      mov temp2,cnt
      sub temp2,temp1
      ..
    
      ..
      waitpeq pinA,pinA   'pulswidth ___----___
      mov temp1,cnt
      waitpne pinA,pinA
      mov temp2,cnt
      sub temp2,temp1
      ..
    
    Andy
  • RinksCustomsRinksCustoms Posts: 531
    edited 2012-07-06 21:39
    Have you looked at the propeller education labs? Pdf available in the download section.. They go into depth about using the counters to measure things like pulse width, duty cycle and others using nco mode and more. I'm on my Droid razr maxx right now so don't be mad if this copy paste link is broken. http://Www.parallax.com/Portals/0/Downloads/docs/prod/prop/PEKitLabs-v1.2.pdf
  • jmgjmg Posts: 15,185
    edited 2012-07-07 04:18
    JBeale wrote: »
    Does the cog timer have direct hardware edge-capture, or do I need to poll the pin state in software, meaning I have at least a few clock cycles of uncertainty?

    Sadly, the Prop 1 does not have external capture, but it does have the WAIT opcodes mentioned above, and they are 'auto-stretching' opcodes, that will add as many SysCLKS as needed - so yes, they do resolve to 12.5ns.

    There IS a fish-hook in this, however, in that the WAIT opcodes are LEVEL based, and not TRUE edge based.

    So in your example, Provided PinB is low for the whole time from PinA rise, to the needed Pin B rise, Two WaitUntilHI will work.
    If Pin B can ever be Hi at the Pin A trigger, then Two WaitUntilHI will fail, as the PinB one will fire instantly.
    You can add a third line to emulate edge

    Wait Until Pin A Low << safety, ensures next line is waiting.
    Wait Until Pin A Hi
    Capture StartTime
    Wait Until Pin B Low << usually immediate, but safely allows B to be high at A rise.
    Wait Until Pin B Hi
    Capture EndTime

    This has a minimum resolvable time A-B, and the safe step also needs that B is low for some of the time.

    A true hardware capture would not have these 'level handshake' issues, and could capture down to coincident timing (0ns)

    If you can add a D-FF, and sample two pins, then you can get closer to true EDGE based.
  • JBealeJBeale Posts: 25
    edited 2012-08-16 13:21
    Thank you all for the helpful information. It's been a while, but I came back to this. My first Propeller board is now on its way, so I'll be able to try out the suggestions. The post from 'jmg' makes some good points which I had not considered at first. As it happens the level vs edge-sensitive behavior is OK for me. I managed to make a CPLD design ( http://www.bealecorner.org/best/measure/time/CPLD-TIC/CPLD-TIC1-schematic.pdf ) to do this function, but I'm still not comfortable with VHDL and I am hoping the Prop will be easier to work with, and maybe overall cheaper per-channel as well. And few CPLDs come in DIP packages :-). I have read the Prop can even be overclocked to 100 MHz (10 ns resolution is a nice number) ...that is impressive compared with some PIC and Atmel parts.
  • cavelambcavelamb Posts: 720
    edited 2012-08-16 14:40
    Bean,
    This is one chip you have to play with to really get to know and love.

    Pick up a QuickStart board at Radio Shack.
  • Mark_TMark_T Posts: 1,981
    edited 2012-08-16 16:43
    You can even use the chip as a full-resolution logic analyser sampling all the pins every cycle, at the cost of 5 cogs - and display the output at 1024x768 VGA (2 more cogs)...
  • JBealeJBeale Posts: 25
    edited 2012-08-26 21:49
    Ok, I got the Radio Shack Propeller Schmartboard module, then found I had to order the Prop chip separately. Did so; soldered it together, and it works. So far, so good. I'm overclocking with a 6.25 MHz crystal so I can run at 100 MHz and have 10 ns timing resolution. I wrote a small Spin program to measure the time interval between rising edges of a 1-pulse-per-second input signal. Here's the relevant code section:
    ' sigin is the pin number of the input 1-pulse-per-second signal
    
      waitpeq(0, |< sigin, 0)         ' wait for sigin pin to be low
      waitpeq(|< sigin, |< sigin, 0)  ' wait for sigin pin to be high
      t1 := cnt
    
      repeat
        waitpeq(0, |< sigin, 0)         ' wait for sigin pin to be low
        waitpeq(|< sigin, |< sigin, 0)  ' wait for sigin pin to be high
        t2 := cnt                       ' capture system clock at rising edge
        delta := (t2-t1)  - 100_000_000   ' difference from 1 sec in 10nsec units
        serial.Dec(delta)                 ' print timing value on serial output                                          
        PrintNewLine 
        t1 := t2
    


    And below is a sample of the output. Apparently my PPS signal is about 14.5 microseconds too long relative to the Prop clock, which is ok, but my concern is that I thought I would have 10 ns resolution. It looks like I've got a granularity of 16 clock cycles. Does this have something to do with waiting for main memory, and the hub access mechanism? Can I get edge to edge timing with true 10 ns granularity in any way? Do I need to use assembly? [EDIT: just found that Spin code is always executed out of hub ram, so that explains the 16 cycle granularity.]
    1456
    1440
    1456
    1440
    1456
    1440
    1440
    1456
    
  • kuronekokuroneko Posts: 3,623
    edited 2012-08-26 21:57
    Yes, yes and nyes. Given the pulse count however, I'd suggest you go the PASM route for this one (see [post=964528]post #4[/post] for an example). For lower frequencies you could still measure high/low pulse widths (POS/NEG counter modes) and derive the delta from their sum (in SPIN that is).
  • JBealeJBeale Posts: 25
    edited 2012-08-26 23:43
    Ok, I figured out a little bit of Prop assembly. In case of interest, here's what I got working:
    {{
    Object file:    JPB-Timing1.spin  Version:        0.1
    Date:           August 26 2012    Author:         John Beale
    Company:        bealecorner.com   Licensing:      public domain
    
    Purpose: measure difference in timing between sucessive input pulses which are
    nominally 1 second apart. No output when delay unchanged. 10 ns resolution
    
    Pin 27: input 1PPS signal
    Pin 28: Prop serial TX line
    Pin 29: Prop serial RX line
    }}
    
    CON
      _clkmode = xtal1 + pll16x    'Set up the clock mode  
      _xinfreq = 6_250_000 '6.25 MHz clock * 16x PLL = 100 MHz system clock speed
    
    VAR
      LONG time1            ' hub ram location of delta-T timing result
      LONG oldtime
      LONG diftime
      LONG sec              ' elapsed time in seconds
    
    OBJ
       serial        : "FullDuplexSerial"
    
    PUB jpbMain
    
      dira[27] := %0                         ' make PortA bit 27 input
    
      serial.Start(29, 28, %0000, 230_400)    '  serial I/O launches into new cog
      serial.Str(STRING("JPB Timing 1  --  Aug. 26 2012"))
      serial.Tx($0D)                ' newline: ASCII 13 = carriage return   
    
      oldtime := 0                            ' initialize history
      sec := 0
      COGNEW(@pinWatch, @time1)               ' launch assy timing routine               
      
      REPEAT
        waitcnt(cnt + clkfreq)      ' wait one second
        sec := sec + 1
        if (time1 <> oldtime)                 ' has the time value changed?
          diftime := time1 - 100_000_000
          serial.Dec(sec)
          serial.Str(STRING(","))
          serial.Dec(diftime)                 ' print timing value on serial output
          serial.Tx($0D)     ' newline: ASCII 13 = carriage return  
          oldtime := time1
    
    ' ===================================================================== 
    DAT
    
      ORG   0
    pinWatch
    
      waitpne pinA,pinA   ' wait for input pin to be low
      waitpeq pinA,pinA   ' rising edge #1
      mov tstart,cnt       ' capture system clock as 'start' time
    :loop
      waitpne pinA,pinA   ' wait for input pin to be low
      waitpeq pinA,pinA   ' rising edge #2
      mov tend,cnt       ' capture system timer  as 'end' time
      mov temp,tend      ' copy into temporary variable
      sub temp,tstart    ' subtract start time from end time
      WRLONG temp, PAR     ' write result to hub ram loc. set in PARAMETER
      mov tstart,tend       ' copy 'end' clock into start clock value
      JMP #:loop            ' ...and do it all again
    
    pinA LONG $01<<27       ' portA pin to monitor for input signal
    tstart LONG 0           ' clock time at start of pulse: Tstart
    tend LONG 0             ' clock time at end of pulse: Tend
    temp LONG 0             ' temporary var for difference (Tend - Tstart)
    
    ' =========================================================
    

    sample output:
    112,1448
    113,1447
    115,1448
    119,1449
    120,1448
    121,1449
    124,1450
    126,1449
    127,1450
    128,1451
    129,1450
    130,1451
    135,1452
    137,1451
    138,1453
    139,1452
    
  • CircuitsoftCircuitsoft Posts: 1,166
    edited 2012-08-27 00:31
    I notice the number is gradually climbing. I would attribute this to the crystal warming up. Depending on the precision you need, you may want to invest in a TCXO/OCXO.
  • JBealeJBeale Posts: 25
    edited 2012-08-27 07:40
    My external PPS signal is from an OCXO. I put my finger on the Prop's 6.25 MHz crystal to warm it up a bit, then I removed my finger. The data I posted shows that the crystal frequency is increasing as it cools off, here the net delta-F is somewhat less than 10 ppb per second. I may end up running the prop from an external OCXO-based synthesized clock, but for now I'm just in the initial "playing around with it" stage.
  • Tracy AllenTracy Allen Posts: 6,666
    edited 2012-08-27 13:04
    The other method that Kuroneko mentioned for high-resolution measurement of period uses the cog counter modules POSDET and NEGDET. Here is demo to show how that works. This demo works for signals up to about 500Hz when the display baud rate is 115200...
    [FONT=courier new][SIZE=1]CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000              ' 80 MHz clkfreq
    
      MYPIN = 0
    
    
    OBJ
      debug : "fullduplexserial"
    
    PUB countHighLow | hightime
      debug.start(31,30,0,9600)
      waitcnt(clkfreq/10+cnt)
      ctra := %01000 << 26 + MYPIN    ' POSDET
      ctrb := %01100 << 26 + MYPIN    ' NEGDET
      frqa := 1
      frqb := 1
      waitpeq(|< MYPIN, |< MYPIN, 0)       ' sync to input
      waitpeq(0, |< MYPIN, 0)
      phsa := 0                            ' ready for POSDET phase
      waitpne(|< MYPIN, |< MYPIN, 0)
      repeat
        phsb := 0                            ' pin is high, POSDET phsa advancing, phsb not
        waitpeq(0 , |< MYPIN, 0)             ' pin goes low, phsa stops, phsb starts
        hightime := phsa                     ' capture the time pin was high
        phsa := 0                            ' pin is low, NEGDET phsb advancing, phsa not
        waitpeq(|< MYPIN, |< MYPIN, 0)       ' pin goes high, phsb stops, phsa starts
        debug.dec((phsb + hightime)*10/8)           ' total is high plus low times
        debug.tx(13)                    ' note conversion to [/SIZE][/FONT][FONT=courier new][SIZE=1]units of ns*10[/SIZE][/FONT]
    
  • RickInTexasRickInTexas Posts: 124
    edited 2012-08-27 13:56
    I notice the number is gradually climbing. I would attribute this to the crystal warming up. Depending on the precision you need, you may want to invest in a TCXO/OCXO.

    eBay has real, non-GPS dependant atomic clocks in a board-mount package for under $100.

    http://www.ebay.com/sch/i.html?_nkw=atomic+standard&_sacat=0&_odkw=atomic+electronic&LH_BIN=. _lncat=0&_sac=1&_osacat=0
  • JBealeJBeale Posts: 25
    edited 2012-08-28 07:30
    Yes, I think the surplus FE-5680A (rubidium atomic clock) is still a good value although the prices have been going up a bit. I have three of them. They do draw 10 watts of power, while my OCXOs are more like 1 watt. If you get one, check out the FAQ on that subject here: http://www.ko4bb.com/dokuwiki/doku.php?id=precision_timing:fe5680a_faq
Sign In or Register to comment.