Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Algorithm to determine the effective "phase difference" between two signals with different frequencies?

The quick version:

What algorithm could I use to determine the "phase difference" between two square wave signals with different frequencies, if the only information that I have is the time at which each rising edge occurs?

The detailed version:

I'm working on an embedded software project, and I have run across an interesting problem. I am collecting data from two hall-effect speed sensors, which are each aimed at one of two meshed gears, as shown in the following diagram:

meshed gears and pulse signals

note:
As Jaime pointed out, the signals in this diagram would actually have identical frequencies. The real hardware has several more gearing stages between the two target gears, some of which are connected by shafts instead of meshed teeth, so I do end up with two square waves that have different frequencies, and the ratio between them is still a constant. I wanted to simplify the diagram to get to the meat of the matter, but it looks like I simplified it too much!
/note

The speed sensors output a square wave signal whose frequency is directly proportional to the rotational speed of each gear. The rising (and falling) edges of the square wave occur when the leading (and trailing) edges of a single gear tooth pass by the sensor.

I know how many teeth are on each gear, and based on this information I am able to accurately measure the rotational speed of each gear based on the frequency of the square wave signals.

To measure the frequencies, I have each speed sensor signal connected to a high-speed capture timer pin on the embedded controller. The capture timers automatically detect the rising edges of the square wave signal, load a register with a value that represents the time at which the transition occurred, and trigger an interrupt. The capture points for each signal are indicated in yellow on the diagram. The interrupt service routine looks something like this:

struct
{
    long previousTime;
    int frequency;
}
sensors[2];

void CaptureTimer_Interrupt(int channel, long transitionTime)
{
    long timeDifference = transitionTime - sensors[channel].previousTime;
    sensors[channel].frequency = CONVERSION_FACTOR / timeDifference;
    sensors[channel].previousTime = transitionTime;
}

What I would like to do:

I would like to be able to detect small differences in the relative timing of these two square wave signals. I call this the "phase difference" for lack of a better term. If the two signals had the exact same frequency, this would be straightforward, and phase difference would be the correct term to use.

Here's what I'm getting at: If I were to record the two signals over a long period of time, and then artificially slow down (or "stretch out") the high speed (blue) signal by a factor of 16/9, it would have the exact same frequency as the lower speed (red) signal, and the two signals would have some measurable phase difference, i.e. the time difference between a red signal interrupt and a blue signal interrupt. I would like to compute this same time difference (or something equivalent) without having to record the signals over a long period of time. Resources are limited on the embedded controller, so storing large arrays of past transition times is not an option.

Has anyone run into this before? The actual project has several such gear and sensor arrangements, so I'm looking for an elegant algorithm that I can reuse. Thanks in advance!

like image 540
e.James Avatar asked Jul 21 '09 07:07

e.James


People also ask

How do you find the phase difference between two signals?

An oscilloscope's timing markers (Figure 1 ) offer the simplest technique to measure the phase between two signals. The time difference between two corresponding points on the signals represents the phase in units of time. Multiplying the ratio of this value to the period of the signals calculates the phase in degrees.

What is the formula which can be used for finding phase difference between two signals on CRO?

In CRO we can measure the phase difference by X-Y mode operation. At a phase shift ϕ = 0° or 360°, the pattern indicated by CRO is a diagonal straight line making 45° with the X-axis. At a phase shift of ϕ = 90°, the pattern indicated by CRO is a clockwise rotating circle.

Can two signals at different frequencies be in phase?

To be "in phase", the angular velocity of the two signals must be the same. The only way to do that is to have both frequencies the same.

What is the relationship between frequency and phase difference?

The time interval for 1° of phase is inversely proportional to the frequency. If the frequency of a signal is given by f, then the time tdeg (in seconds) corresponding to 1° of phase is tdeg = 1 / (360f) = T / 360. Therefore, a 1° phase shift on a 5 MHz signal corresponds to a time shift of 555 picoseconds.


3 Answers

The overall signal, i.e. the signal that you get when you add the red and the blue, has a phase length of 16 times the blue and 9 times the red signal. You could measure the time difference between every 16th blue and every 9th red rising flank.

I guess that what you want to measure is the wear on the gears. I think that this measurement might be influenced (introducing noise) by the gears' tolerance, if there is no uniform traction.

like image 125
Svante Avatar answered Sep 24 '22 15:09

Svante


Since we are talking about "phase", then it seems reasonable to measure the "beat" which occurs when the two waveforms reinforce each other.

Something like this, perhaps:

void cog_phase_monitor2( int cog, int t )
{
    static int last_a, last_b, last_beat, last_beat_delta = 0;;
    int beat = 0;
    if( cog == 1 ) {
        if( t - last_b < 1 )
            beat = 1;
        last_a = t;
    }
    if( cog == 2 ) {
        if( t - last_a < 1 )
            beat = 1;
        last_b = t;
    }
    if( beat ) {
        printf("**** delta beat %d \n",t-last_beat);
        if( last_beat_delta ) {
            if( last_beat_delta != t-last_beat ) {
                printf("!!!Warning beat just changed !!!\n");
                last_beat_delta = 0;
            }
        } else {
            last_beat_delta = t-last_beat;
        }
        last_beat = t;
    }

}

Now if we plug this into a simulation of two cogs, one of 9 teeth and one of 16 teeth, both turning at 10 revs per second

B at 6 msecs
A at 11 msecs
B at 12 msecs
B at 18 msecs
A at 22 msecs
B at 24 msecs
B at 30 msecs
A at 33 msecs
B at 36 msecs
B at 42 msecs
A at 44 msecs
B at 48 msecs
B at 54 msecs
A at 55 msecs
B at 60 msecs
A at 66 msecs
B at 66 msecs
**** delta beat 66
B at 72 msecs
A at 77 msecs
B at 78 msecs
B at 84 msecs
A at 88 msecs
B at 90 msecs
B at 96 msecs
A at 99 msecs
B at 102 msecs
B at 108 msecs
A at 110 msecs
B at 114 msecs
B at 120 msecs
A at 121 msecs
B at 126 msecs
A at 132 msecs
B at 132 msecs
**** delta beat 66
B at 138 msecs
A at 143 msecs
B at 144 msecs
B at 150 msecs
A at 154 msecs
B at 156 msecs
B at 162 msecs
A at 165 msecs
B at 168 msecs
B at 174 msecs
A at 176 msecs
B at 180 msecs
B at 186 msecs
A at 187 msecs
B at 192 msecs
A at 198 msecs
B at 198 msecs
**** delta beat 66

And now if we add a delay of 1 msec to one of the cogs:

B at 6 msecs
A at 11 msecs
B at 12 msecs
B at 18 msecs
A at 22 msecs
B at 24 msecs
B at 30 msecs
A at 33 msecs
B at 36 msecs
B at 42 msecs
A at 44 msecs
B at 48 msecs
B at 54 msecs
A at 55 msecs
B at 60 msecs
A at 66 msecs
B at 66 msecs
**** delta beat 66
B at 72 msecs
A at 77 msecs
B at 78 msecs
B at 84 msecs
A at 88 msecs
B at 90 msecs
B at 96 msecs
A at 99 msecs
B delayed at 102 msecs
B at 103 msecs
B at 109 msecs
A at 110 msecs
B at 115 msecs
A at 121 msecs
B at 121 msecs
**** delta beat 55
!!!Warning beat just changed !!!
B at 127 msecs
A at 132 msecs
B at 133 msecs
B at 139 msecs
A at 143 msecs
B at 145 msecs
B at 151 msecs
A at 154 msecs
B at 157 msecs
B at 163 msecs
A at 165 msecs
B at 169 msecs
B at 175 msecs
A at 176 msecs
B at 181 msecs
A at 187 msecs
B at 187 msecs
**** delta beat 66
B at 193 msecs
A at 198 msecs
B at 199 msecs
B at 205 msecs

This seems like a hopeful beginning :-)

like image 26
ravenspoint Avatar answered Sep 21 '22 15:09

ravenspoint


I think it is even simpler than that.

Every 16*9 samplings(of the big cog) the wheels are in the exact same spot they started.

So what you do is the following:

  • pick any point in time with a sampling on the big cog. Measure the amount of time before you sample the small cog too. Remember this value.

  • every 16*9 samplings of the big cog (why does this sound dubious?) do the same measurement again and compare it to your base value. When the timing begins to shift, you have a problem.

R

like image 39
Toad Avatar answered Sep 22 '22 15:09

Toad