I have a square wave (0-1.8V) with a varying sampling frequency (from a circuit simulator). It is also not a perfect square wave (the high and low signal could be very close to but not precisely zero or 1 Volt) and the fall time is slightly slower than the rise time.

Another factor is that I will retake the data and the period (and possibly duty cycle as well) will change when I alter another parameter, so I am not working with a fixed number of cycles per window.

I tried autocorrelation but it seems that it gave me double or so the actual period. And fft seems to need a fixed sampling rate. What would be the best solution to finding the period of this square wave?

enter image description here

  • $\begingroup$ Can you add more details about the autocorrelation giving you double the actual period? $\endgroup$
    – MBaz
    Mar 14, 2019 at 16:42
  • $\begingroup$ @Mbaz it seems that when I autocorrelate the signal my guess is that it might be counting the period as a positive edge going to negative edge, as opposed to positive edge going to the next positive edge. However, since I am almost sure duty cycle will always be 50% I can just divide by 2. However, MATLAB records the distance between peaks in the acorrelated signal as a vector and for some reason the first and last elements are smaller than the middle ones, so I just end up clipping those edges out $\endgroup$
    – user P520
    Mar 14, 2019 at 18:01
  • $\begingroup$ When you shift the signal by half a period, so that the rising edge of the original matches the falling edge of the shifted signal, the correlation should be zero, shouldn't it? $\endgroup$
    – MBaz
    Mar 14, 2019 at 19:08

1 Answer 1


Pick a nice center value, say 1.0, scan across looking for crossings from down to up (or the reverse). Mark the spot of your first crossing, count up some fixed number of crossings, call the count N. Take your system timer value at your first crossing and your last crossing. Divide the time interval by N and you'll have a very good estimate of the period. How uneven the crossings are in the interval is immaterial. If you can assure the two crossing that you are timing happen in "the same state", you will lose one more level of uncertainty.

You can't do it much simpler than that. Increased accuracy will come from interpolating the crossing point rather than taking the closest sample's time.


Follow up

You'll have to figure the Interpolate routine out yourself. It's not that hard.

The logic is very straightforward and significantly less computationly heavy than an auto-correlation technique. More accurate in this case too.


    FirstIndex = -1
    N = 0

    For i = 0 to PointCount
      If signal[i] <= 1.0 and signal[i+1] > 1.0 Then
         If FirstIndex < 0 Then
            T1A = System.Time(i)
            T1B = System.Time(i+1)
            FirstIndex = i
            TNA = System.Time(i)
            TNB = System.Time(i+1)
            LastIndex = i
            N += 1
         End If
      End If

    T1 = Interpolate( T1A, T1B, Signal[FirstIndex], Signal[FirstIndex+1] )
    TN = Interpolate( TNA, TNB, Signal[LastIndex], Signal[LastIndex+1] )

    Period = ( TN - T1 ) / N

You may not need to interpolate, (TNA - T1A)/N may be accurate enough.

  • $\begingroup$ I really like this idea. When a line is drawn through the points it definitely gives the illusion they intersect on every rising and falling edge. However, since they are discrete points and very close together I dont see how to add in a threshold to get exactly one crossing point through that reference line. Any thoughts? @CedronDawg $\endgroup$
    – user P520
    Mar 17, 2019 at 0:40
  • $\begingroup$ @userP520, See my followup. $\endgroup$ Mar 17, 2019 at 1:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.