measure-accuracy.py
Initially, the script processes the command line and then invokes the
main
function passing the specified command arguments or their
defaults.
<<imports>> <<globals>> <<plot>> <<main>> if __name__ == '__main__': defaultDevice = '/dev/tty.usbmodem14101' defaultBaud = '1500000' defaultOutfile = 'pwrdetector-accuracy.svg' parser = ArgumentParser(description= '''Measure power detector module accuracy.''') parser.add_argument("-d", "--device", default=defaultDevice, help="The serial device (default: {})".format(defaultDevice)) parser.add_argument("-C", "--cspin", default='D0', help="Chip select controller pin (default: {})".format('D0')) parser.add_argument("-G", "--gen", choices=['DSG815', 'SMHU58'], default='SMHU58', help="""The signal generator in use for the calibration. Default: {}""".format('SMHU58')) parser.add_argument("-O", "--outfile", default=defaultOutfile, help="""Output file for plot. Default: {}""".format( defaultOutfile)) args = parser.parse_args() main(args.device, args.cspin, args.gen, args.outfile)
The main
Function: <<main>>
The main
function proceeds in four stages:
Initialize the RF signal generator.
Initialize the detector under test.
Take the detector measurements.
Plot the measured power levels.
Initialize the signal generator: <<initialize-siggen>>
The script currently supports either the R&S SMHU and the Rigol
DSG815. Depending on the which one is being used either GPIB or
VISA is used for instrument communication and command.
Note that the frequencies
list is set to the frequency range
appropriate for the selected signal generator.
global frequencies if gen == 'DSG815': visa_rm = pyvisa.ResourceManager('@py') sig_gen = DSG815(visa_rm, DSG815_ID) sig_gen.initialize() frequencies = dsg815_frequencies[det.detector_type] elif gen == 'SMHU58': gpib = GPIB() gpib.initialize() sig_gen = SMHU58(gpib, SMHU58_GPIBID) sig_gen.initialize() frequencies = smhu_frequencies[det.detector_type] else: print("ERROR: Unknown signal generator: {}".format(gen)) sys.exit(-1)
Initialize the detector under test: <<initialize-detector>>
A serial communications link is first established with the atmega
USB control board. An instance of the rfblocks LogDetector
is then
created and initialized. Note that as part of the initialization of
the detector calibration information will be loaded from the
detector's EEPROM.
Take the measurements: <<take-measurements>>
For each of the input signal power levels specified in the
pwr_levels
list detector power levels are measured at each
frequency specified in the frequencies
list. The power levels
reported by the detector under test are saved in measured_levels
.
for pwr in pwr_levels[det.detector_type]: measured_levels[pwr] = [] print('{:6.1f}: '.format(pwr), end='', flush=True) sig_gen.level = pwr sig_gen.output = True sleep(2.0) for freq in frequencies: sig_gen.freq = freq sleep(1.0) measured_pwr = det.power(ser, freq, avg=16) print(' {:5.2f}'.format(measured_pwr), end='', flush=True) measured_levels[pwr].append(measured_pwr) print()
The plot function: <<plot>>
The measured detector power levels are plotted as a function of input signal frequency. An example plot is shown in Figure 1.
def plot(detector, measured_levels, outfile): init_style() last_freq = frequencies[-1] fig = plt.figure(num=None, figsize=(6.0, 4.0), dpi=72) ax = fig.add_subplot(111) ax.set_xlabel('Frequency (MHz)') ax.set_ylabel('RF Input Power (dBm)') ax.set_xlim(0.0, last_freq*1.1) ax.grid(linestyle=':') ax.yaxis.set_minor_locator(plt.MultipleLocator(5.0)) ax.grid(which='both', axis='y', linestyle=':') for pwr in pwr_levels[detector.detector_type]: ax.plot(frequencies, measured_levels[pwr]) ax.text(last_freq*1.01, pwr-1.0, '{:4.1f}'.format(pwr)) fig.tight_layout() plt.savefig(outfile)
Global variables: <<globals>>
Since the different signal generator models have differing frequency
capabilities the measured frequency steps will depend on the
selected signal generator. These steps are stored in the
frequencies
list for later use.
pwr_levels
-
the test signal power levels to use.
smhu_frequencies
-
the test signal frequencies to use for the R&S SMHU58 signal generator
dsg815_frequencies
-
the test signal frequencies to with the Rigol DSG815 signal generator
frequencies
-
the actual test signal frequencies to use during the measurement process. The default signal generator is the SMHU58 and so the
frequencies
variable is initialized withsmhu_frequencies
.
pwr_levels = [ [-60.0, -55.0, -50.0, -45.0, -40.0, -35.0, -30.0, -25.0, -20.0, -15.0, -10.0, -5.0, 0.0, 5.0], [-70.0, -65.0, -60.0, -55.0, -50.0, -45.0, -40.0, -35.0, -30.0, -25.0, -20.0, -15.0, -10.0, -5.0, 0.0, 5.0], ] smhu_frequencies = [ [250.0, 500.0, 750.0, 1000, 1250, 1500, 1750, 2000, 2250, 2500, 2750, 3000, 3250, 3500, 3750, 4000, 4250], [5.0, 50.0, 100.0, 150.0, 200.0, 250.0, 300.0, 350.0, 400.0, 425.0, 450.0, 475.0, 500.0, 525.0, 550.0, 575.0, 600.0] ] dsg815_frequencies = [ [250.0, 500.0, 750.0, 1000, 1250, 1500], [5.0, 50.0, 100.0, 150.0, 200.0, 250.0, 300.0, 350.0, 400.0, 425.0, 450.0, 475.0, 500.0, 525.0, 550.0, 575.0, 600.0] ] frequencies = smhu_frequencies
Imports: <<imports>>
import sys from time import sleep from argparse import ArgumentParser import numpy as np import matplotlib import matplotlib.pyplot as plt matplotlib.use('Agg') import pyvisa from tam import (GPIB, SMHU58, SMHU58_GPIBID, DSG815, DSG815_ID) from rfblocks import LogDetector, create_serial, write_cmd, query_cmd from dyadic.splot import init_style import dyadic.orgmode as org