Compare commits
1
Commits
master
..
builtindac
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84ef317f62
|
@@ -2,6 +2,9 @@
|
||||
## GEX v1.0.0 on STM32F072-HUB
|
||||
## built Jun 15 2018 at 13:45:28
|
||||
|
||||
# Overwrite this file to change settings.
|
||||
# Press the LOCK button to save them to Flash.
|
||||
|
||||
[UNITS]
|
||||
# Create units by adding their names next to a type (e.g. DO=A,B),
|
||||
# remove the same way. Reload to update the unit sections below.
|
||||
@@ -31,7 +34,7 @@ TOUCH=
|
||||
# Simple PWM output
|
||||
PWMDIM=
|
||||
# Two-channel analog output with waveforms
|
||||
DAC=
|
||||
DAC=dac
|
||||
|
||||
[SPI:spi@2]
|
||||
# Peripheral number (SPIx)
|
||||
@@ -55,7 +58,7 @@ first-bit=MSB
|
||||
# SS port name
|
||||
port=A
|
||||
# SS pins (comma separated, supports ranges)
|
||||
pins=4
|
||||
pins=3
|
||||
|
||||
[ADC:adc@4]
|
||||
# Enabled channels, comma separated
|
||||
@@ -73,7 +76,7 @@ frequency=1000
|
||||
# - defines the maximum pre-trigger size (divide by # of channels)
|
||||
# - captured data is sent in half-buffer chunks
|
||||
# - buffer overrun aborts the data capture
|
||||
buffer_size=512
|
||||
buffer_size=800
|
||||
|
||||
# Enable continuous sampling with averaging
|
||||
# Caution: This can cause DAC output glitches
|
||||
@@ -81,4 +84,17 @@ averaging=N
|
||||
# Exponential averaging coefficient (permil, range 0-1000 ~ 0.000-1.000)
|
||||
# - used formula: y[t]=(1-k)*y[t-1]+k*u[t]
|
||||
# - not available when a capture is running
|
||||
avg_factor=800
|
||||
avg_factor=80
|
||||
|
||||
[DAC:dac@1]
|
||||
# Enabled channels (1:A4, 2:A5)
|
||||
ch1_enable=Y
|
||||
ch2_enable=N
|
||||
# Enable output buffer
|
||||
ch1_buff=Y
|
||||
ch2_buff=Y
|
||||
# Superimposed noise type (NONE,WHITE,TRIANGLE) and nbr. of bits (1-12)
|
||||
ch1_noise=NONE
|
||||
ch1_noise-level=3
|
||||
ch2_noise=NONE
|
||||
ch2_noise-level=3
|
||||
|
||||
@@ -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':
|
||||
# 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 = 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 = 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()
|
||||
plt.figure()
|
||||
plt.ylabel('Gain (dB)')
|
||||
plt.xlabel('Frequency (Hz)')
|
||||
plt.semilogx(freqs, gains) # Bode magnitude plot
|
||||
plt.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('Phase (deg)')
|
||||
plt.xlabel('Frequency (Hz)')
|
||||
plt.semilogx(freqs, phases) # Bode phase plot
|
||||
plt.grid()
|
||||
plt.show()
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user