Shop OBEX P1 Docs P2 Docs Learn Events
Using Counter Mods to determine frequency offset between two inputs. — Parallax Forums

Using Counter Mods to determine frequency offset between two inputs.

RME2000RME2000 Posts: 12
edited 2012-12-12 05:51 in Propeller 1
I have a turning shaft with two sensors generating two squarewave signals of the same frequency, but which are out of phase. I have these coming into two seperate pins on the Prop chip. It is very simple to measure the frequency of each. I want to measure the phase offset of the two waveforms. Any suggestions?

Comments

  • BeanBean Posts: 8,129
    edited 2012-12-05 10:12
    Are you using spin or pasm ?

    What is the frequency of the inputs ?

    Are the input 50% duty cycle ?

    I don't think you can measure phase offset directly with the counters. I think you'll need to have your program wait for the rising edge of one signal, then wait for the rising edge of the other.

    Bean
  • LawsonLawson Posts: 870
    edited 2012-12-05 11:21
    You should be able to do this by putting a counter in XOR mode (%10110) and letting it count for a know number of cycles. The ratio of counts/full-count is related to the phase difference. (assuming close to 50% duty cycle anyway) You can do this from Spin if you're careful. (using two counters, one in XOR and one in XNOR (%11001) is also worth trying) http://en.wikipedia.org/wiki/Phase_comparator should be useful too.

    Lawson
  • jmgjmg Posts: 15,193
    edited 2012-12-05 11:54
    RME2000 wrote: »
    I have a turning shaft with two sensors generating two squarewave signals of the same frequency, but which are out of phase. I have these coming into two seperate pins on the Prop chip. It is very simple to measure the frequency of each. I want to measure the phase offset of the two waveforms. Any suggestions?

    Are you trying to check how close they are to 90' ? - or do you want the RPM ? or is this phase carefully modulated to carry information ?
    What is the time-between-edges range you need to work over ?

    Quadrature signals can encode information on each edge, so the usual approach is to capture the time of each edge, and then after a number of edges, you can calculate the Period, and the Phase.
  • RME2000RME2000 Posts: 12
    edited 2012-12-05 12:00
    Bean wrote: »
    Are you using spin or pasm ? spin

    What is the frequency of the inputs ? the inputs are up to 500 Hz

    Are the input 50% duty cycle ? yes

    I don't think you can measure phase offset directly with the counters. I think you'll need to have your program wait for the rising edge of one signal, then wait for the rising edge of the other.

    Bean
    I can read a stable frequency of each signal with ctra/ctrb using a 1 second waitcnt.

    I have already had some success without the counter mods using ina reads of pin states. That gives me a startcnt and stopcnt for each input. The difference divided into the clock freq gives frequency. If I subtract the startcnt of signal 2 from the startcnt of signal 1 I get what I want. The problem is that the frequencies determined by this method are not stable with time. They are running on a continuous loop and I suspect there is a cumulative error problem of some kind.

    repeat
    while ina[0]==1
    startcnt = cnt
    repeat
    while ina[0]==0
    repeat
    while ina[0]==1
    stopcnt :=cnt

    I think the code is correct, I'm writing from memory. Basically I repeat the same structure with the second pin and then subtract the second pin high start from the first pin high start. From comparing this time to a complete cycle I get a reading
    of the position of the second signal offset radially.
    Like I said, this approach has worked, but I cannot make my frequency stabilize. One day I'll be sitting on 400Hz with both signals when I look up and the rpm signal based, on a timing mark, is sitting at 465 Hz. If I switch to the program with the Counter Modules they read right on 400 Hz. The whole thing is on a Magnatek AC drive which reads out 400 Hz. So far I can't find the gremlin. Any ideas?

    Thanks.
  • RME2000RME2000 Posts: 12
    edited 2012-12-05 12:02
    Lawson wrote: »
    You should be able to do this by putting a counter in XOR mode (%10110) and letting it count for a know number of cycles. The ratio of counts/full-count is related to the phase difference. (assuming close to 50% duty cycle anyway) You can do this from Spin if you're careful. (using two counters, one in XOR and one in XNOR (%11001) is also worth trying) http://en.wikipedia.org/wiki/Phase_comparator should be useful too.

    Lawson

    Thanks for the reply. I'll take a look at your suggestion.
  • RME2000RME2000 Posts: 12
    edited 2012-12-05 12:16
    jmg wrote: »
    Are you trying to check how close they are to 90' ? - or do you want the RPM ? or is this phase carefully modulated to carry information ?
    What is the time-between-edges range you need to work over ?

    Quadrature signals can encode information on each edge, so the usual approach is to capture the time of each edge, and then after a number of edges, you can calculate the Period, and the Phase.

    I'm doing a balancing operation. The freq or rpms are read from a timing mark on a shaft. The vibration bump occurs at the same frequency, offset X degrees from the timing mark. It is this offset I need to quantify.

    See my answer to Bean for more details.

    Thanks
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-12-05 12:32
    Your Spin method would be more accurate if you used waitpeq rather than a repeat while construct. With the latter, there's too much uncertainty introduced by the interpreter overhead.

    -Phil
  • RME2000RME2000 Posts: 12
    edited 2012-12-05 14:13
    Your Spin method would be more accurate if you used waitpeq rather than a repeat while construct. With the latter, there's too much uncertainty introduced by the interpreter overhead.

    -Phil
    Thanks, Phil. I am very green at this, working towards an end, learning, but slowly. I noticed the waitpeq statement in the Propeller Edu Kit Section on Posedge/Negedge Counter Modules. I have looked at it, but do not yet have command of it. I will revisit this and see if I can get it working for me. Thanks for the tip.
  • jmgjmg Posts: 15,193
    edited 2012-12-05 15:52
    RME2000 wrote: »
    Like I said, this approach has worked, but I cannot make my frequency stabilize. One day I'll be sitting on 400Hz with both signals when I look up and the rpm signal based, on a timing mark, is sitting at 465 Hz. If I switch to the program with the Counter Modules they read right on 400 Hz. The whole thing is on a Magnatek AC drive which reads out 400 Hz. So far I can't find the gremlin. Any ideas?

    Can you easily slow down the RPM ? - that is a simple way to check if the software cannot quite keep up.
    If you want to measure phase, you need period and delay, so I think an alternating capture like this

    ChA _/=, ChB _/=, ChA =\_, ChB =\_
    (assumes rotation is known, and only one way)

    would capture a time stamp of each of 4 edges in a full period
    From there you calculate values, and note the leading edge needs a 5th wait as you may get back in any phase, & the Prop does not find true edges, just wait-until-hi

    So you have pseudo code something like this
    ; Assumes this quad signal
    ; ChA  ______/========\__________
    ; ChB  ___________/========\__________
    
          wait_Until_AeqL    ; edge resync, may arrive part way thru a hi
          wait_Until_AeqH
          Edge_AR=cnt
          wait_Until_BeqH
          Edge_BR=cnt
          wait_Until_AeqL
          Edge_AF=cnt
          wait_Until_BeqL
          Edge_BF=cnt
    ...
        Code here to work on the 4 capture values, 
    
  • RME2000RME2000 Posts: 12
    edited 2012-12-05 16:09
    RME2000 wrote: »
    Thanks for the reply. I'll take a look at your suggestion.

    I may have been misleading by using the word phase. What I need to know is the offset or delay between the two signals. I need to know the radial position of the vibration bump relative to the timing mark.

    Thanks
  • LawsonLawson Posts: 870
    edited 2012-12-05 16:20
    RME2000 wrote: »
    I may have been misleading by using the word phase. What I need to know is the offset or delay between the two signals. I need to know the radial position of the vibration bump relative to the timing mark.

    Thanks

    So it sounds like you have two pulses that you want to know the time delay between them? The XOR counter mode won't work then because it needs some overlap between the two pulses. (50% duty cycle insures this) In this case, using WAITxxx to capture CNT on the rising edge of both pulses should give plenty of resolution. Optionally, you could feed each pulse into an input of a RS flip-flop and measure the duty cycle of the output square wave with a counter. (the counter is set to count while an input pin is high in this case).

    Lawson
  • jmgjmg Posts: 15,193
    edited 2012-12-05 18:07
    RME2000 wrote: »
    I may have been misleading by using the word phase. What I need to know is the offset or delay between the two signals. I need to know the radial position of the vibration bump relative to the timing mark.

    How many edges per revolution, and what is the edge-edge time you need to measure, and how much resolution does that 'vibration bump' need to be seen ?

    You may need a variant of #10, where you store a whole revolution's worth of edges, then go looking for small variations.

    The limit will be the sensor noise (electrical and mechanical tooth style variation).
  • RME2000RME2000 Posts: 12
    edited 2012-12-06 08:58
    Lawson wrote: »
    So it sounds like you have two pulses that you want to know the time delay between them? The XOR counter mode won't work then because it needs some overlap between the two pulses. (50% duty cycle insures this) In this case, using WAITxxx to capture CNT on the rising edge of both pulses should give plenty of resolution. Optionally, you could feed each pulse into an input of a RS flip-flop and measure the duty cycle of the output square wave with a counter. (the counter is set to count while an input pin is high in this case).

    Lawson
    I have tried replacing:

    repeat while ina[pin]==1
    constant = cnt which seems to work,
    with: | < pin = a
    waitpeq(1, | < pin, 0) and waitpeq(%100000, | < pin, 0) and waitpeq(1, a, 0)
    constant = cnt constant = cnt constant = cnt


    None of which works for me. Obviously I an not doing something right!

    I find the "Explanation" of waitpeq in the manual confusing. I have tried to understand the statement:

    waitpeq(%0100, %1100, 0) 'Wait for P3 & P2 to be low & high
    outa[0] := 1 'Set P0 high

    [FONT=Times New Roman,Times New Roman][FONT=Times New Roman,Times New Roman]The above code pauses the cog until I/O pin 3 is low and I/O pin 2 is high, then sets I/O pin 0 high.

    It looks to me like %0100 must be P2, and %1100 P3. Where does it designate the pin state?

    Thanks for any enlightenment on this.


    [/FONT][/FONT]
  • RME2000RME2000 Posts: 12
    edited 2012-12-06 09:03
    Lawson wrote: »
    So it sounds like you have two pulses that you want to know the time delay between them? The XOR counter mode won't work then because it needs some overlap between the two pulses. (50% duty cycle insures this) In this case, using WAITxxx to capture CNT on the rising edge of both pulses should give plenty of resolution. Optionally, you could feed each pulse into an input of a RS flip-flop and measure the duty cycle of the output square wave with a counter. (the counter is set to count while an input pin is high in this case).

    Lawson
    Sorry about the scramble!

    I meant to show:

    repeat while ina[pin]==1
    constant = cnt, which works

    and
    waitpeq(%100000, | < pin, 0)
    constant + cnt

    waitpeq(1, | < pin, 0)
    constant + cnt

    a= | < pin
    waitpeq(1, a, 0)
    constant + cnt, which do not
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-12-06 09:21
    The statement,
    repeat while ina[pin] == 1 (equivalent to repeat while ina[pin] or repeat until ina[pin] == 0)

    can be replaced by
    mask := 1 << pin
    ...
    waitpeq (0, mask, 0)

    This will wait until ina, anded with mask equals zero -- IOW until pin goes low.

    Conversely,
    repeat while ina[pin] == 0 (equivalent to repeat until ina[pin])

    can be replaced by
    mask := 1 << pin
    ...
    waitpeq (mask, mask, 0)

    This will wait until ina, anded with mask equals mask -- IOW until pin goes high.

    -Phil
  • MagIO2MagIO2 Posts: 2,243
    edited 2012-12-06 10:27
    I'd do it like that:

    1. setup a counter to count the low-time of your second signal
    2, use one of the wait-instructions to wait for the first signal to go high
    3. set phsa to 0 and store actual:=cnt
    4. wait for the second signal to go high
    5. read phsa (phase_cnt:=phsa) and move actual to old ( old:=actual )

    Starting from second cycle you can calculate the frequency and the phase shift.
    frequency := clkfreq / (actual-old)
    phase_shift := phase_cnt*360/(actual-old)

    So, the only problem is the first value which would be wrong. Either you skip this or you unroll the loop for one cycle (which does not do the calculations) before entering the loop.
  • RME2000RME2000 Posts: 12
    edited 2012-12-06 12:12
    Phil,
    Thanks. I am currently working on this project and I will try out your suggestions.
  • RME2000RME2000 Posts: 12
    edited 2012-12-08 09:35
    The statement,
    repeat while ina[pin] == 1 (equivalent to repeat while ina[pin] or repeat until ina[pin] == 0)

    can be replaced by
    mask := 1 << pin
    ...
    waitpeq (0, mask, 0)

    This will wait until ina, anded with mask equals zero -- IOW until pin goes low.

    Conversely,
    repeat while ina[pin] == 0 (equivalent to repeat until ina[pin])

    can be replaced by
    mask := 1 << pin
    ...
    waitpeq (mask, mask, 0)

    This will wait until ina, anded with mask equals mask -- IOW until pin goes high.

    -Phil

    Reading the various pin states with waitxxx works great. My code appears to do exaxtly what I need it to do....but only for a period of maybe 20 to 30 minutes. I get it set up and start evaluating the system and I lose the frequency measurements from my two signals. The numbers tend to grow larger by about ten percent. To check the hardware/signals, I use the counter modules on posedge to measure freq on both inputs. The motor turning the shaft is on an AC freq controller with a freq readout. I monitor both signals with the o-scope The signals look clean and strong, and both of these checks stay on freq perfectly while the other method drifts.

    I want to run the code in a repeating loop. Generally the cycle is 1 second. I have tried moving up and down on the loop periods. I have also tried a single loop with each compile. When the code works, all the timing methods seem to work. I noticed cycles that are too short tendto make the LCD look a little uneven. I have also looked at the data with the Serial Terminal. It gives the same numbers my LCD does (with and without the LCD running).

    What do you all think is going on?
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-12-08 10:52
    RME2000 wrote:
    What do you all think is going on?
    Without seeing your entire program, it's impossible to say. Can you post it, please? (Be sure to paste it between [noparse]
    and
    
    [/noparse] tags, or just attach it.)

    -Phil
  • RME2000RME2000 Posts: 12
    edited 2012-12-12 05:51
    Without seeing your entire program, it's impossible to say. Can you post it, please? (Be sure to paste it between [noparse]
    and
    
    [/noparse] tags, or just attach it.)

    -Phil
    I believe I found the gremlin that has been causing my instability problems. I should have been more in tune with this problem, because I have been working with this rotating shaft system for years. But since I have been working for years, I am old and vulnerable to such lapses. The problem has to do with the frequency of the measurment and the rotational frequency of the shaft(timing mark). If they get in phase, ie if the measurement cycle lines up with any multiple of the rotation, it can screw up the measurement.

    When I lost stability at top speed, I noticed that it returned with a reduction in speed. Since I was using the pot control on the freq drive, it was only capable of relativly large speed changes. I wrongly concluded that the Prop and my spin code were executing too slowly for some reason. Later, while using the keypad to control controller Hz, I noticed that the instability problem went away with a change of only a few tenths of a Hz. Then it dawned on me what the problem is. With measuring regular signals you need to stay away from even multiples of the signal frequency with the sampling rate. While there has been limited eval time, it is looking good.

    Thanks for all the support.

    Thanks to
Sign In or Register to comment.