|
|
|
@ -7,13 +7,7 @@ from matplotlib import pyplot as plt |
|
|
|
|
import gex |
|
|
|
|
import time |
|
|
|
|
|
|
|
|
|
# Two presets defined for demoing the plotter with a high-pass and low-pass RC filter |
|
|
|
|
# made of 1 kOhm and 100 nF |
|
|
|
|
|
|
|
|
|
#demo = 'HP' |
|
|
|
|
demo = 'LP' |
|
|
|
|
#demo = 'LP2' |
|
|
|
|
#demo = 'LP3' # LT1112 sallenkey at 1 kHz |
|
|
|
|
use_native_dac = True |
|
|
|
|
|
|
|
|
|
class ADG: |
|
|
|
|
def __init__(self, client:gex.Client): |
|
|
|
@ -48,8 +42,7 @@ class ADG: |
|
|
|
|
if freq is not None: |
|
|
|
|
self.set_frequency(freq) |
|
|
|
|
|
|
|
|
|
#with gex.Client(gex.TrxRawUSB()) as client: |
|
|
|
|
with gex.Client(gex.TrxSerialThread('/dev/ttyACM0')) as client: |
|
|
|
|
with gex.Client(gex.TrxRawUSB()) as client: |
|
|
|
|
# =============================================== |
|
|
|
|
|
|
|
|
|
# Delay between adjusting input and starting the measurement. |
|
|
|
@ -60,89 +53,78 @@ with gex.Client(gex.TrxSerialThread('/dev/ttyACM0')) as client: |
|
|
|
|
max_allowed_shift_db = 5 |
|
|
|
|
# db shift compensation (spread through the frequency sweep to adjust for different slopes) |
|
|
|
|
allowed_shift_compensation = -4.5 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Frequency sweep parameters |
|
|
|
|
f_0 = 5 |
|
|
|
|
f_1 = 6000 |
|
|
|
|
|
|
|
|
|
f_step = 5 |
|
|
|
|
f_step_begin = 5 |
|
|
|
|
f_step_end = 200 |
|
|
|
|
|
|
|
|
|
if demo == 'HP': |
|
|
|
|
if False: |
|
|
|
|
# highpass filter example (corner 340 Hz) |
|
|
|
|
settling_time_s = (4700*100e-9)*10 |
|
|
|
|
max_allowed_shift_db = 5.6 |
|
|
|
|
allowed_shift_compensation = -5 |
|
|
|
|
|
|
|
|
|
if demo == 'LP': |
|
|
|
|
# lowpass filter example (corner 340 Hz) |
|
|
|
|
settling_time_s = (4700*100e-9)*10 |
|
|
|
|
max_allowed_shift_db = .5 |
|
|
|
|
allowed_shift_compensation = 2 |
|
|
|
|
|
|
|
|
|
if demo == 'LP2': |
|
|
|
|
max_allowed_shift_db = 5 |
|
|
|
|
allowed_shift_compensation = -4.5 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if True: |
|
|
|
|
# lowpass filter example (corner 340 Hz) |
|
|
|
|
settling_time_s = (4700*100e-9)*10 |
|
|
|
|
max_allowed_shift_db = .5 |
|
|
|
|
allowed_shift_compensation = 5 |
|
|
|
|
f_1 = 4500 |
|
|
|
|
f_step_end = 100 |
|
|
|
|
|
|
|
|
|
if demo == 'LP3': |
|
|
|
|
# lowpass filter example (corner 340 Hz) |
|
|
|
|
settling_time_s = 0.05 |
|
|
|
|
max_allowed_shift_db = .5 |
|
|
|
|
allowed_shift_compensation = 5 |
|
|
|
|
f_1 = 10000 |
|
|
|
|
f_step_end = 250 |
|
|
|
|
max_allowed_shift_db = 1 |
|
|
|
|
allowed_shift_compensation = 1.2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Frequency sweep parameters |
|
|
|
|
#f_0 = 5 |
|
|
|
|
#f_1 = 5000 |
|
|
|
|
#f_step = 15 |
|
|
|
|
f_0 = 10 |
|
|
|
|
f_1 = 5000 |
|
|
|
|
f_step = 50 |
|
|
|
|
|
|
|
|
|
# Retry on failure |
|
|
|
|
retry_count = 5 |
|
|
|
|
retry_delay_s = settling_time_s*2 |
|
|
|
|
retry_delay_s = settling_time_s*10 |
|
|
|
|
|
|
|
|
|
# Initial sample granularity |
|
|
|
|
samples_per_period = 60 |
|
|
|
|
capture_periods = 10 |
|
|
|
|
|
|
|
|
|
# Parameters for automatic params adjustment |
|
|
|
|
max_allowed_sample_rate = 65000 |
|
|
|
|
max_allowed_nr_periods = 100 |
|
|
|
|
min_samples_per_period = 16 |
|
|
|
|
max_allowed_sample_rate = 36000 |
|
|
|
|
max_allowed_nr_periods = 80 |
|
|
|
|
min_samples_per_period = 4 |
|
|
|
|
|
|
|
|
|
# =============================================== |
|
|
|
|
|
|
|
|
|
#allowed_shift_compensation /= (f_1 - f_0) / f_step |
|
|
|
|
allowed_shift_compensation /= (f_1 - f_0) / f_step |
|
|
|
|
|
|
|
|
|
adc = gex.ADC(client, 'adc') |
|
|
|
|
|
|
|
|
|
gen = ADG(client) |
|
|
|
|
gen.initialize() |
|
|
|
|
dac = None |
|
|
|
|
gen = None |
|
|
|
|
|
|
|
|
|
if use_native_dac: |
|
|
|
|
print('Using native GEX DAC') |
|
|
|
|
dac = gex.DAC(client, 'dac') |
|
|
|
|
dac.waveform(1, 'SINE') |
|
|
|
|
else: |
|
|
|
|
print('Using AD9833 via SPI') |
|
|
|
|
gen = ADG(client) |
|
|
|
|
gen.initialize() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
table = [] |
|
|
|
|
|
|
|
|
|
last_db = None |
|
|
|
|
f = f_0 |
|
|
|
|
first = True |
|
|
|
|
begin_allowedshift = max_allowed_shift_db |
|
|
|
|
while f <= f_1: |
|
|
|
|
if not first: |
|
|
|
|
f_step = round(f_step_begin + ((f - f_0) / (f_1 - f_0)) * (f_step_end - f_step_begin)) |
|
|
|
|
f += f_step |
|
|
|
|
first = False |
|
|
|
|
for f in range(f_0, f_1, f_step): |
|
|
|
|
|
|
|
|
|
#dac.set_frequency(1, f) |
|
|
|
|
gen.set_frequency(f) |
|
|
|
|
if use_native_dac: |
|
|
|
|
dac.set_frequency(1, f) |
|
|
|
|
else: |
|
|
|
|
gen.set_frequency(f) |
|
|
|
|
|
|
|
|
|
max_allowed_shift_db = begin_allowedshift + allowed_shift_compensation * ((f - f_0) / (f_1 - f_0)) |
|
|
|
|
max_allowed_shift_db += allowed_shift_compensation |
|
|
|
|
|
|
|
|
|
# Adjust measurement parameters |
|
|
|
|
while True: |
|
|
|
|
desiredf = f*samples_per_period |
|
|
|
|
if desiredf > max_allowed_sample_rate: |
|
|
|
|
desiredf = max_allowed_sample_rate |
|
|
|
|
oldspp = samples_per_period |
|
|
|
|
samples_per_period = math.ceil(samples_per_period * 0.9) |
|
|
|
|
|
|
|
|
@ -183,6 +165,7 @@ with gex.Client(gex.TrxSerialThread('/dev/ttyACM0')) as client: |
|
|
|
|
|
|
|
|
|
y1 = np.max(t[:,0]) - np.min(t[:,0]) |
|
|
|
|
y2 = np.max(t[:,1]) - np.min(t[:,1]) |
|
|
|
|
print("\x1b[90mU %f, Y %f\x1b[0m" % (y1, y2)) |
|
|
|
|
gain_raw = y2/y1 |
|
|
|
|
gain_db = 20*math.log10(gain_raw) |
|
|
|
|
|
|
|
|
@ -214,7 +197,10 @@ with gex.Client(gex.TrxSerialThread('/dev/ttyACM0')) as client: |
|
|
|
|
if not suc: |
|
|
|
|
last_db = last_db_in_fail |
|
|
|
|
|
|
|
|
|
gen.wfm_dc() |
|
|
|
|
if use_native_dac: |
|
|
|
|
dac.dc(1, 2000) |
|
|
|
|
else: |
|
|
|
|
gen.wfm_dc() |
|
|
|
|
|
|
|
|
|
t = np.reshape(np.array(table), [int(len(table) / 3), 3]) |
|
|
|
|
|
|
|
|
@ -222,18 +208,17 @@ with gex.Client(gex.TrxSerialThread('/dev/ttyACM0')) as client: |
|
|
|
|
gains = t[:, 1] |
|
|
|
|
phases = t[:, 2] |
|
|
|
|
|
|
|
|
|
fig = plt.figure() |
|
|
|
|
ax1 = fig.add_subplot(211) |
|
|
|
|
ax1.set_ylabel('Gain (dB)') |
|
|
|
|
ax1.semilogx(freqs, gains) # Bode magnitude plot |
|
|
|
|
ax1.grid() |
|
|
|
|
|
|
|
|
|
ax2 = fig.add_subplot(212) |
|
|
|
|
ax2.set_ylabel('Phase (deg)') |
|
|
|
|
ax2.set_xlabel('Frequency (Hz)') |
|
|
|
|
ax2.semilogx(freqs, phases) # Bode phase plot |
|
|
|
|
ax2.grid() |
|
|
|
|
|
|
|
|
|
plt.figure() |
|
|
|
|
plt.ylabel('Gain (dB)') |
|
|
|
|
plt.xlabel('Frequency (Hz)') |
|
|
|
|
plt.semilogx(freqs, gains) # Bode magnitude plot |
|
|
|
|
plt.grid() |
|
|
|
|
|
|
|
|
|
plt.figure() |
|
|
|
|
plt.ylabel('Phase (deg)') |
|
|
|
|
plt.xlabel('Frequency (Hz)') |
|
|
|
|
plt.semilogx(freqs, phases) # Bode phase plot |
|
|
|
|
plt.grid() |
|
|
|
|
plt.show() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|