Last active
December 13, 2018 21:37
-
-
Save dk2ro/8636a14646d0d128168d097fd357b5c8 to your computer and use it in GitHub Desktop.
Frequency response measurement of a two-port with the ADALM-PLUTO
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import iio | |
import time | |
import struct | |
import matplotlib.pyplot as plt | |
import numpy.fft as fft | |
import numpy as np | |
import math | |
def set_rx_freq(freq): | |
d.channels[0].attrs["frequency"].value = str(int(freq)) | |
def set_tx_freq(freq): | |
d.channels[1].attrs["frequency"].value = str(int(freq)) | |
def setup_dds(freq, scale): | |
dds.channels[0].attrs["frequency"].value = str(int(freq)) | |
dds.channels[2].attrs["frequency"].value = str(int(freq)) | |
dds.channels[0].attrs["scale"].value = str(scale) | |
dds.channels[2].attrs["scale"].value = str(scale) | |
def set_tx_gain(gain): | |
d.find_channel("voltage0", True).attrs["hardwaregain"].value = str(gain) | |
def set_rx_gain(gain): | |
d.find_channel("voltage0").attrs["hardwaregain"].value = str(gain) | |
def sweep(startf, stopf, step): | |
BUFFLEN = 2 ** 6 | |
rx_gain = 0 | |
set_rx_gain(rx_gain) | |
tx_gain = -20 | |
start_gain = tx_gain | |
set_tx_gain(tx_gain) | |
rxbuff = iio.Buffer(rx, BUFFLEN) | |
iq_samples = [None] * BUFFLEN | |
steps = int((stopf - startf) / step) + 1 | |
print("Number of points: " + str(steps)) | |
valsx = np.zeros(steps) | |
valsy = np.zeros(steps) | |
set_rx_freq(startf) | |
set_tx_freq(startf) | |
freq = startf | |
for j in range(0, 10): | |
rxbuff.refill() | |
b = rxbuff.read() | |
k = 0 | |
while freq <= stopf: | |
set_rx_freq(freq) | |
set_tx_freq(freq) | |
freq += step | |
rxbuff.refill() | |
b = rxbuff.read() | |
for i in range(0, BUFFLEN): | |
iq_samples[i] = complex(struct.unpack("h", b[i * 4:i * 4 + 2])[0], | |
struct.unpack("h", b[i * 4 + 2:i * 4 + 4])[0]) | |
mfft = abs(fft.fft(iq_samples)) | |
s = 8 | |
s21 = 20 * math.log10(abs(mfft[s]) / float(BUFFLEN)) | |
#plt.plot(mfft) | |
#plt.show() | |
valsy[k] = s21 - tx_gain - rx_gain | |
valsx[k] = freq | |
k += 1 | |
#o=raw_input() | |
newgain = False | |
if s21 < 0: | |
if tx_gain <= -10: | |
tx_gain += 10 | |
set_tx_gain(tx_gain) | |
newgain = True | |
elif rx_gain <= 60: | |
rx_gain += 10 | |
set_rx_gain(rx_gain) | |
newgain = True | |
if s21 > 30: | |
if rx_gain >= 30: | |
rx_gain -= 10 | |
set_rx_gain(rx_gain) | |
newgain = True | |
else: | |
tx_gain -= 10 | |
set_tx_gain(tx_gain) | |
newgain = True | |
if newgain: | |
print("new gain tx " + str(tx_gain) + " rx " + str(rx_gain) + " " + str(freq)) | |
for j in range(0, 10): | |
rxbuff.refill() | |
b = rxbuff.read() | |
return valsx, valsy | |
def smooth(y, box_pts): | |
"""stolen from https://stackoverflow.com/a/26337730""" | |
box = np.ones(box_pts) / box_pts | |
y_smooth = np.convolve(y, box, mode='same') | |
return y_smooth | |
ctx = iio.NetworkContext("pluto.local") | |
d = ctx.find_device("ad9361-phy") | |
rx = ctx.find_device("cf-ad9361-lpc") | |
dds = ctx.find_device("cf-ad9361-dds-core-lpc") | |
def init(): | |
rxI = rx.find_channel("voltage0") | |
rxQ = rx.find_channel("voltage1") | |
rxI.enabled = True | |
rxQ.enabled = True | |
txI = dds.find_channel("altvoltage0",True) | |
txQ = dds.find_channel("altvoltage2",True) | |
txI.enabled = True | |
txQ.enabled = True | |
txI.attrs["scale"].value = "1" | |
txQ.attrs["scale"].value = "1" | |
d.find_channel("TX_LO", True).attrs["powerdown"].value = "0" | |
d.find_channel("voltage0").attrs["sampling_frequency"].value = "2084000" | |
d.find_channel("voltage0").attrs["rf_bandwidth"].value = "1000000" | |
d.find_channel("voltage3",1).attrs["rf_bandwidth"].value = "1000000" | |
d.find_channel("voltage0").attrs["gain_control_mode"].value = "manual" | |
init() | |
setup_dds(250000, 0.3) | |
time.sleep(0.5) | |
setup_dds(250000, 0.3) | |
start = 70e6 | |
stop = 6000e6 | |
step = 1000e3 | |
slen = 500 | |
slen1 = slen/2 | |
slen2 = -slen1 | |
print(d.find_channel("voltage0").attrs["sampling_frequency"].value) | |
raw_input("Calibration, please connect through and press enter.") | |
cvalsx,cvalsy = sweep(start,stop,step) | |
raw_input("Now please connect dut and press enter.") | |
valsx, valsy = sweep(start, stop, step) | |
scvalsy = smooth(cvalsy, slen)[slen1:slen2] | |
svalsy = smooth(valsy, slen)[slen1:slen2] | |
svalsx = valsx[slen1:slen2] | |
plt.figure() | |
plt.subplot(222) | |
plt.plot(valsx, valsy-cvalsy) | |
plt.subplot(224) | |
plt.plot(svalsx, svalsy-scvalsy) | |
#plt.plot(valsx, valsy-cvalsy) | |
plt.subplot(221) | |
plt.plot(valsx, valsy, label="val") | |
plt.plot(valsx, cvalsy, label="cval") | |
plt.legend() | |
plt.subplot(223) | |
plt.plot(valsx[slen1:slen2], svalsy, label="sval") | |
plt.plot(valsx[slen1:slen2], scvalsy, label="scval") | |
plt.legend() | |
#plt.plot(valsx[50:-50], smooth(valsy, 100)[50:-50]) | |
# | |
plt.show() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment