Using Counter Mods to determine frequency offset between two inputs.
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
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
Lawson
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 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.
Thanks for the reply. I'll take a look at your suggestion.
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
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
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
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).
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]
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
can be replaced by
...
waitpeq (0, mask, 0)
This will wait until ina, anded with mask equals zero -- IOW until pin goes low.
Conversely,
can be replaced by
...
waitpeq (mask, mask, 0)
This will wait until ina, anded with mask equals mask -- IOW until pin goes high.
-Phil
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.
Thanks. I am currently working on this project and I will try out your suggestions.
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
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