I have recorded a square wave with scope(bit, controlling some unit).
I want to measure rise/fall time, the time while the bit is on and off using python. I thought of using the 'derrivetive' np.diff
, but the wave is a bit noisy. I wonder if there is some efficient technique to achieve my goal.
Thank you, dear community!
1 Answer
If it was necessary to get a low noise high quality estimate of the rise and fall time, one idea is to generate an eye diagram and from that create an averaged transition from which we could then accurately with minimized noise compute the 10%/90% rise and fall time (or whatever criteria for settling).
Otherwise is the signal itself is not noisy, a simple approach of determining the min and max signals and 10% and 90% thresholds and establishing times of transition through the thresholds can be done using numpy.where
.
Below is my own code for an eye diagram appraoch with modulated waveforms that can be easily used with a train of pulses:
"""
Created on Mon May 20 19:34:28 2019
Eye Diagram Utility
@author: Dan Boschen
"""
import numpy as np
import scipy.signal as sig
import matplotlib.pyplot as plt
def eye(waveform, samp_per_sym, sym_per_win, windows, oversamp=64, plot=True):
'''
waveform: data
samp_per_sym: # of samples per symbol
sym_per_win: # of symbols to display in eye diagram
windows: # of sweeps
oversamp: oversampling ratio (default = 64)
plot: will create eyediagram plot if True (real data only)
returns:
xaxis: xaxis time values
eye: eye diagram magnitudes
'''
# resample data to emulate continuous waveform
resamp = int(np.ceil(oversamp/samp_per_sym))
tx_resamp = sig.resample(waveform, len(waveform) * resamp)
samp_per_win = oversamp * sym_per_win
# divide by number of samples per win and then
# pad zeros to next higher multiple using tx_eye = np.array(tx_shaped),
# tx_eye.resize(N)
# N is total number of windows possible
N = len(tx_resamp)//samp_per_win
tx_eye = np.array(tx_resamp)
tx_eye.resize(N * samp_per_win)
grouped = np.reshape(tx_eye, [N, samp_per_win])
eye = np.real(grouped.T)
# create an xaxis in samples np.shape(eye) gives the
# 2 dimensional size of the eye data and the first element
# is the interpolated number of samples along the x axis
nsamps = np.shape(eye)[0]
xaxis = np.arange(nsamps)/resamp
if plot:
plt.figure()
# plot showing continuous trajectory of
plt.plot(xaxis, eye[:, :windows])
# actual sample locations
plt.plot(xaxis[::resamp], eye[:, :windows][::resamp], 'b.')
plt.title("Eye Diagram")
plt.xlabel('Samples')
plt.grid()
plt.show()
return xaxis, eye
Alternatively there is open source code available here that is a little more complicated but results in a nice looking plot with persistent intensity:
image source: https://scipy-cookbook.readthedocs.io/_static/items/attachments/EyeDiagram/eye-diagram3.png