doorbell, frequency domain,...

13
Doorbell, Frequency Domain, 003 Use DFT/FFT approximation to Fourier transform (FT) to estimate frequency domain parameters of the doorbell signal and to move it to baseband. In [1]: # Import the Python modules that we need import numpy as np import matplotlib.pyplot as plt from scipy.signal import lfilter In [2]: %matplotlib notebook fsz = (7, 4) # full figure size fsz2 = (fsz[0],fsz[1]/2.0) # half figure size In [3]: # Read the binary file of one button push (1 sec) and create a time axis name = 'doorbell_001_inclass_r1t' fname = name + '.bin' Fs = int(5e6) rt = np.fromfile(fname, dtype=np.complex64) L= len(rt) tt = np.arange(L)/float(Fs) # time axis in seconds print(L) 5000000 Doorbell_FreqDomain_003 http://localhost:8888/nbconvert/html/Doorbell_FreqDomain_003.ipynb... 1 of 13 10/4/2019, 9:28 AM

Upload: others

Post on 31-Dec-2020

16 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: Doorbell, Frequency Domain, 003ecee.colorado.edu/.../classnotes/python/Doorbell_FreqDomain_003.pdf · Doorbell, Frequency Domain, 003 Use DFT/FFT approximation to Fourier transform

Doorbell, Frequency Domain, 003

Use DFT/FFT approximation to Fourier transform (FT) to estimate frequency domain parameters of the doorbell signal and to

move it to baseband.

In [1]: # Import the Python modules that we needimport numpy as npimport matplotlib.pyplot as pltfrom scipy.signal import lfilter

In [2]: %matplotlib notebookfsz = (7, 4) # full figure sizefsz2 = (fsz[0],fsz[1]/2.0) # half figure size

In [3]: # Read the binary file of one button push (1 sec) and create a time axisname = 'doorbell_001_inclass_r1t'fname = name + '.bin'Fs = int(5e6)rt = np.fromfile(fname, dtype=np.complex64)L = len(rt)tt = np.arange(L)/float(Fs) # time axis in secondsprint(L)

5000000

Doorbell_FreqDomain_003 http://localhost:8888/nbconvert/html/Doorbell_FreqDomain_003.ipynb...

1 of 13 10/4/2019, 9:28 AM

Page 2: Doorbell, Frequency Domain, 003ecee.colorado.edu/.../classnotes/python/Doorbell_FreqDomain_003.pdf · Doorbell, Frequency Domain, 003 Use DFT/FFT approximation to Fourier transform

In [4]: # Plot the signal in the time domaininc1 = 100plt.figure(3, figsize=fsz)plt.subplot(211)plt.plot(tt[::inc1], np.real(rt[::inc1]), '-b', label='real part')plt.ylabel('Re[$r(t)$]')plt.title('Doorbell Signal File: {}, $F_s$={} kHz'.format(fname, Fs/1000))plt.legend()plt.grid()plt.subplot(212)plt.plot(tt[::inc1], np.imag(rt[::inc1]), '-r', label='imag part')plt.ylabel('Im[$r(t)$]')plt.xlabel('$t$ [sec]')plt.legend()plt.grid()plt.tight_layout()

In [5]: # Compute the FT approximationRf = np.fft.fft(rt)/float(Fs)N = Rf.size # blocklength of FFTDf = Fs/float(N) # frequency resolutionff = Df*np.arange(N) # generate frequency axis

Doorbell_FreqDomain_003 http://localhost:8888/nbconvert/html/Doorbell_FreqDomain_003.ipynb...

2 of 13 10/4/2019, 9:28 AM

Page 3: Doorbell, Frequency Domain, 003ecee.colorado.edu/.../classnotes/python/Doorbell_FreqDomain_003.pdf · Doorbell, Frequency Domain, 003 Use DFT/FFT approximation to Fourier transform

In [6]: # Doorbell Signal in the frequency domain using dB for magnitudeinc3 = 10plt.figure(11, figsize=fsz)plt.subplot(211)plt.plot(ff[::inc3]/1000.0, 20*np.log10(abs(Rf[::inc3])), '-b', label='magnitude [dB]')plt.ylabel('$|R(f)|$ [dB]')plt.title('Doorbell Signal File: {}, $F_s$={} kHz'.format(fname, Fs/1000))plt.legend()plt.grid()plt.subplot(212)plt.plot(ff[::inc3]/1000.0, 180/np.pi*np.angle(Rf[::inc3]), '-r', label='phase')plt.ylabel('$\\angle R(f)$ [deg]')plt.xlabel('$f$ [kHz]')plt.legend()plt.grid()plt.tight_layout()

There is a spectral component at about 988 kHz visible. Since the recording was made with a center frequency of 314 MHz,

this probably means that the carrier frequency of the doorbell transmitter was a little less than 315 MHz. We will shift the

signal down to about 20 kHz and then use a lowpass filter followed by downsampling for further processing at a lower

sampling rate.

In [15]: # Shifting signal down in frequency domainfx1 = 968e3 # local oscillator frequency for downshiftingrx1t = rt*np.exp(-1j*2*np.pi*fx1*tt)

Doorbell_FreqDomain_003 http://localhost:8888/nbconvert/html/Doorbell_FreqDomain_003.ipynb...

3 of 13 10/4/2019, 9:28 AM

Page 4: Doorbell, Frequency Domain, 003ecee.colorado.edu/.../classnotes/python/Doorbell_FreqDomain_003.pdf · Doorbell, Frequency Domain, 003 Use DFT/FFT approximation to Fourier transform

In [16]: # Lowpass filter at about 40 kHzfL = 40000k = 10Lh2 = int(round(Fs*k/(2*fL)))tth = np.arange(-Lh2,Lh2)/float(Fs)ht = 2*fL*np.sinc(2*fL*tth)ord_h = ht.size # filter orderrxLPt = lfilter(ht, 1, np.hstack((rxt, np.zeros(round(ord_h/2.0)))))/float(Fs)

# padded with zerosrxLPt = rxLPt[round(ord_h/2.0):] # remove first part of response

In [17]: # Check result in frequency domainRxLPf = np.fft.fft(rxLPt)/float(Fs)inc4 = 10plt.figure(15, figsize=fsz)plt.subplot(211)plt.plot(ff[::inc4]/1000.0, 20*np.log10(abs(RxLPf[::inc4])), '-b', label='magnitude [dB]')plt.ylabel('$|R(f)|$ [dB]')plt.title('Doorbell Signal File: {}, $F_s$={} kHz'.format(fname, Fs/1000))plt.legend()plt.grid()plt.subplot(212)plt.plot(ff[::inc4]/1000.0, 180/np.pi*np.angle(RxLPf[::inc4]), '-r', label='phase')plt.ylabel('$\\angle R(f)$ [deg]')plt.xlabel('$f$ [kHz]')plt.legend()plt.grid()plt.tight_layout()

Doorbell_FreqDomain_003 http://localhost:8888/nbconvert/html/Doorbell_FreqDomain_003.ipynb...

4 of 13 10/4/2019, 9:28 AM

Page 5: Doorbell, Frequency Domain, 003ecee.colorado.edu/.../classnotes/python/Doorbell_FreqDomain_003.pdf · Doorbell, Frequency Domain, 003 Use DFT/FFT approximation to Fourier transform

In [18]: # Now we can downsample by a factor of M and compute the FT againM = 50 # downsampling factorFs1 = Fs/M # new sampling raterxLP1t = rxLPt[::M]tt1 = np.arange(rxLP1t.size)/float(Fs1) # New time axisRxLP1f = np.fft.fft(rxLP1t)/float(Fs1)N1 = RxLP1f.size # blocklength of new FFTDf1 = Fs1/float(N1) # new frequency resolutionff1 = Df1*np.arange(N1) # generate frequency axis

In [19]: # Display the result from the new FFTplt.figure(19, figsize=fsz)plt.subplot(211)plt.plot(ff1/1000.0, 20*np.log10(abs(RxLP1f)), '-b', label='magnitude [dB]')plt.ylabel('$|R(f)|$ [dB]')plt.title('Doorbell Signal File: {}, $F_s$={} kHz'.format(fname, Fs1/1000))plt.legend()plt.grid()plt.subplot(212)plt.plot(ff1/1000.0, 180/np.pi*np.angle(RxLP1f), '-r', label='phase')plt.ylabel('$\\angle R(f)$ [deg]')plt.xlabel('$f$ [kHz]')plt.legend()plt.grid()plt.tight_layout()

Now the carrier is at about 20.7 kHz and the sampling rate is kHz. We repeat the process of downshifting the

carrier, this time to about 5 kHz, followed by lowpass filtering and downsampling to kHz.

In [20]: # Shifting signal down in frequency domainfx2 = 15.7e3 # local oscillator frequency for downshiftingrx2t = rxLP1t*np.exp(-1j*2*np.pi*fx2*tt1)

Doorbell_FreqDomain_003 http://localhost:8888/nbconvert/html/Doorbell_FreqDomain_003.ipynb...

5 of 13 10/4/2019, 9:28 AM

Page 6: Doorbell, Frequency Domain, 003ecee.colorado.edu/.../classnotes/python/Doorbell_FreqDomain_003.pdf · Doorbell, Frequency Domain, 003 Use DFT/FFT approximation to Fourier transform

In [31]: # Lowpass filter at about 9 kHzfL2 = 9000k2 = 100Lh22 = int(round(Fs1*k2/(2*fL2)))tth2 = np.arange(-Lh22,Lh22)/float(Fs1)h2t = 2*fL2*np.sinc(2*fL2*tth2)ord_h2 = h2t.size # filter orderrxLP21t = lfilter(h2t, 1, np.hstack((rx2t, np.zeros(round(ord_h2/2.0)))))/float(Fs1)

# padded with zerosrxLP21t = rxLP21t[round(ord_h2/2.0):] # remove first part of response

In [32]: # Check result in frequency domainRxLP21f = np.fft.fft(rxLP21t)/float(Fs1)inc21 = 10plt.figure(23, figsize=fsz)plt.subplot(211)plt.plot(ff1[::inc21]/1000.0, 20*np.log10(abs(RxLP21f[::inc21])), '-b', label='magnitude [dB]')plt.ylabel('$|R(f)|$ [dB]')plt.title('Doorbell Signal File: {}, $F_s$={} kHz'.format(fname, Fs1/1000))plt.legend()plt.grid()plt.subplot(212)plt.plot(ff1[::inc21]/1000.0, 180/np.pi*np.angle(RxLP21f[::inc21]), '-r', label='phase')plt.ylabel('$\\angle R(f)$ [deg]')plt.xlabel('$f$ [kHz]')plt.legend()plt.grid()plt.tight_layout()

Doorbell_FreqDomain_003 http://localhost:8888/nbconvert/html/Doorbell_FreqDomain_003.ipynb...

6 of 13 10/4/2019, 9:28 AM

Page 7: Doorbell, Frequency Domain, 003ecee.colorado.edu/.../classnotes/python/Doorbell_FreqDomain_003.pdf · Doorbell, Frequency Domain, 003 Use DFT/FFT approximation to Fourier transform

In [33]: # Now we can downsample by a factor of M2 and compute the FT againM2 = 5 # downsampling factorFs2 = Fs1/M2 # new sampling raterxLP2t = rxLP21t[::M2]tt2 = np.arange(rxLP2t.size)/float(Fs2) # New time axisRxLP2f = np.fft.fft(rxLP2t)/float(Fs2)N2 = RxLP2f.size # blocklength of new FFTDf2 = Fs2/float(N2) # new frequency resolutionff2 = Df2*np.arange(N2) # generate frequency axis

In [34]: # Display the result from the new FFTplt.figure(27, figsize=fsz)plt.subplot(211)plt.plot(ff2/1000.0, 20*np.log10(abs(RxLP2f)), '-b', label='magnitude [dB]')plt.ylabel('$|R(f)|$ [dB]')plt.title('Doorbell Signal File: {}, $F_s$={} kHz'.format(fname, Fs2/1000))plt.legend()plt.grid()plt.subplot(212)plt.plot(ff2/1000.0, 180/np.pi*np.angle(RxLP2f), '-r', label='phase')plt.ylabel('$\\angle R(f)$ [deg]')plt.xlabel('$f$ [kHz]')plt.legend()plt.grid()plt.tight_layout()

In [35]: # Bandpass filter at 5 kHz, BW 500 HzfL3 = 500/2.0fc3 = 5000k3 = 100Lh23 = int(round(Fs2*k3/(2*fL3)))tth3 = np.arange(-Lh23,Lh23)/float(Fs2)h3t = 2*fL3*np.sinc(2*fL3*tth3) # LPFh3t = h3t*np.exp(1j*2*np.pi*fc3*tth3) # convert to BPFrxBP3t = lfilter(h3t, 1, np.hstack((rxLP2t,np.zeros(Lh23))))/Fs2 # CT convolutionrxBP3t = rxBP3t[Lh23:]

Doorbell_FreqDomain_003 http://localhost:8888/nbconvert/html/Doorbell_FreqDomain_003.ipynb...

7 of 13 10/4/2019, 9:28 AM

Page 8: Doorbell, Frequency Domain, 003ecee.colorado.edu/.../classnotes/python/Doorbell_FreqDomain_003.pdf · Doorbell, Frequency Domain, 003 Use DFT/FFT approximation to Fourier transform

In [38]: # Check BPF in frequ domainH3f = np.fft.fft(np.fft.fftshift(h3t))/float(Fs2)Nh3 = H3f.size # blocklength of FFT of BPFDfh3 = Fs2/float(Nh3) # frequency resolutionffh3 = Dfh3*np.arange(Nh3) # generate frequency axisplt.figure(31, figsize=fsz)plt.subplot(211)plt.plot(ffh3/1000, abs(H3f), '-b', label='Magnitude')strt31 = 'Bandpass Filter'strt31 = strt31 + ', $f_c$={} kHz, BW={} Hz'.format(fc3/1e3, 2*fL3)strt31 = strt31 + ', $F_s$={} kHz'.format(Fs2/1e3)plt.title(strt31)plt.ylabel('|H_{BP}(f)|')plt.xlim([4, 6])plt.legend()plt.grid()plt.subplot(212)plt.plot(ffh3/1000, 180/np.pi*np.angle(H3f), '-r', label='Phase')plt.ylabel('$\\angle H_{BP}(f)$ [deg]')plt.xlabel('f [kHz]')plt.xlim([4, 6])plt.legend()plt.grid()plt.tight_layout()

Doorbell_FreqDomain_003 http://localhost:8888/nbconvert/html/Doorbell_FreqDomain_003.ipynb...

8 of 13 10/4/2019, 9:28 AM

Page 9: Doorbell, Frequency Domain, 003ecee.colorado.edu/.../classnotes/python/Doorbell_FreqDomain_003.pdf · Doorbell, Frequency Domain, 003 Use DFT/FFT approximation to Fourier transform

In [39]: tt3 = np.arange(len(rxBP3t))/float(Fs2)plt.figure(35, figsize=fsz)plt.subplot(211)plt.plot(tt3, np.real(rxBP3t), '-b', label='real')strt35 = 'Bandpass Filtered'strt35 = strt35 + ', $f_c$={} kHz, BW={} Hz'.format(fc3/1000, 2*fL3)strt35 = strt35 + ', $F_s$={} kHz'.format(Fs2/1000)plt.title(strt35)plt.ylabel('$Re\{r_{BP}(t)\}$')plt.grid()plt.subplot(212)plt.plot(tt3, np.imag(rxBP3t), '-r', label='imag')plt.ylabel('$Im\{r_{BP}(t)\}$')plt.xlabel('t [sec]')plt.grid()plt.tight_layout()

In [40]: phase_rxBP3t = np.arctan2(np.imag(rxBP3t),np.real(rxBP3t))phase_rxBP3tu = np.unwrap(np.arctan2(np.imag(rxBP3t),np.real(rxBP3t)))

Doorbell_FreqDomain_003 http://localhost:8888/nbconvert/html/Doorbell_FreqDomain_003.ipynb...

9 of 13 10/4/2019, 9:28 AM

Page 10: Doorbell, Frequency Domain, 003ecee.colorado.edu/.../classnotes/python/Doorbell_FreqDomain_003.pdf · Doorbell, Frequency Domain, 003 Use DFT/FFT approximation to Fourier transform

In [92]: plt.figure(39, figsize=fsz)plt.subplot(311)plt.plot(tt3, 180/np.pi*phase_rxBP3tu, label='unwrapped')plt.title('Phase and Frequency of Received Signal $r(t)=s(t)\cos(\psi(t))$')plt.ylabel('$\psi(t)$ [deg]')plt.legend()plt.grid()plt.subplot(312)plt.plot(tt3[1:], phase_rxBP3tu[1:]/(2*np.pi*tt3[1:]), label='freq')plt.ylim([4800,5000])plt.ylabel('$\psi(t)/(2\pi t)$ [Hz]')plt.legend()plt.grid()plt.subplot(313)plt.plot(tt3[1:], Fs2*np.diff(phase_rxBP3tu)/(2*np.pi), label='inst freq')plt.ylim([4700,5300])plt.ylabel('$f_i(t)$ [Hz]')plt.xlabel('t [sec]')plt.legend()plt.grid()plt.tight_layout()

The quantity is the instantaneous frequency of the received doorbell signal , where or

for an OOK (on-off keying) signal, defined as

in Hz.

Doorbell_FreqDomain_003 http://localhost:8888/nbconvert/html/Doorbell_FreqDomain_003.ipynb...

10 of 13 10/4/2019, 9:28 AM

Page 11: Doorbell, Frequency Domain, 003ecee.colorado.edu/.../classnotes/python/Doorbell_FreqDomain_003.pdf · Doorbell, Frequency Domain, 003 Use DFT/FFT approximation to Fourier transform

In [77]: # Demodulate using fixed carrier close to residual carrier frequency#fcc, thcc = 5000+11+12, 40-90fcc, thcc = 5023, -50cct = np.exp(1j*(2*np.pi*fcc*tt2+np.pi/180*thcc))s3t = rxLP2t*np.conj(cct)ts41, ts42 = 0.0, 1.0#ts41, ts42 = 0.40, 0.50#ts41, ts42 = 0.406, 0.421ixs4 = np.where(np.logical_and(tt2>=ts41, tt2<ts42))[0]plt.figure(51, figsize=fsz)plt.subplot(211)plt.plot(tt2[ixs4], np.real(rxLP2t[ixs4]), ':k', label='real')plt.plot(tt2[ixs4], np.real(s3t[ixs4]), '-b', linewidth=2, label='demod')plt.title('I and Q Waveforms Before and After Demodulation')plt.ylabel('In-Phase')plt.legend()plt.grid()plt.subplot(212)plt.plot(tt2[ixs4], np.imag(rxLP2t[ixs4]), ':k', label='imag')plt.plot(tt2[ixs4], np.imag(s3t[ixs4]), '-r', linewidth=2, label='demod')plt.ylabel('Quadrature')plt.xlabel('t [sec]')plt.legend()plt.grid()plt.tight_layout()

The graph above shows the beating between the stable frequency and the less stable doorbell transmitter frequency. It is

part of the "RF fingerprint" of the doorbell signal.

Doorbell_FreqDomain_003 http://localhost:8888/nbconvert/html/Doorbell_FreqDomain_003.ipynb...

11 of 13 10/4/2019, 9:28 AM

Page 12: Doorbell, Frequency Domain, 003ecee.colorado.edu/.../classnotes/python/Doorbell_FreqDomain_003.pdf · Doorbell, Frequency Domain, 003 Use DFT/FFT approximation to Fourier transform

In [83]: #ts51, ts52 = 0.0, 1.0#ts51, ts52 = 0.40, 0.50ts51, ts52 = 0.4314, 0.447#ts51, ts52 = 0.406, 0.421ixs5 = np.where(np.logical_and(tt2>=ts51, tt2<ts52))[0]plt.figure(55, figsize=fsz)plt.subplot(211)plt.plot(tt2[ixs5], np.real(rxLP2t[ixs5]), ':k', label='real')plt.plot(tt2[ixs5], np.real(s3t[ixs5]), '-b', linewidth=2, label='demod')plt.title('I and Q Waveforms Before and After Demodulation')plt.ylabel('In-Phase')plt.legend()plt.grid()plt.subplot(212)plt.plot(tt2[ixs5], np.imag(rxLP2t[ixs5]), ':k', label='imag')plt.plot(tt2[ixs5], np.imag(s3t[ixs5]), '-r', linewidth=2, label='demod')plt.ylabel('Quadrature')plt.xlabel('t [sec]')plt.legend()plt.grid()plt.tight_layout()

In [84]: # Envelope detection of signal on 5 kHz carrierrxtenv = np.abs(rxLP2t)

Doorbell_FreqDomain_003 http://localhost:8888/nbconvert/html/Doorbell_FreqDomain_003.ipynb...

12 of 13 10/4/2019, 9:28 AM

Page 13: Doorbell, Frequency Domain, 003ecee.colorado.edu/.../classnotes/python/Doorbell_FreqDomain_003.pdf · Doorbell, Frequency Domain, 003 Use DFT/FFT approximation to Fourier transform

In [91]: ts71, ts72 = 0.0, 1.0ixs7 = np.where(np.logical_and(tt2>=ts71, tt2<ts72))[0]plt.figure(59, figsize=fsz2)plt.plot(tt2[ixs7], np.real(rxtenv[ixs7]), '-b', label='abs')plt.title('Absolute Value of I and Q Waveforms')plt.ylabel('$|r(t)|$')plt.legend()plt.grid()plt.xlabel('t [sec]')plt.legend()plt.tight_layout()

In [93]: # Zooming ints81, ts82 = 0.377, 0.424ixs8 = np.where(np.logical_and(tt2>=ts81, tt2<ts82))[0]plt.figure(63, figsize=fsz2)plt.plot(tt2[ixs8], np.real(rxtenv[ixs8]), '-b', label='abs')plt.title('Absolute Value of I and Q Waveforms')plt.ylabel('$r(t)$')plt.legend()plt.grid()plt.xlabel('t [sec]')plt.legend()plt.tight_layout()

In [ ]:

Doorbell_FreqDomain_003 http://localhost:8888/nbconvert/html/Doorbell_FreqDomain_003.ipynb...

13 of 13 10/4/2019, 9:28 AM