aboutsummaryrefslogtreecommitdiffstats
path: root/host/examples
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2020-05-06 15:53:21 -0700
committerAaron Rossetto <aaron.rossetto@ni.com>2020-05-19 13:30:20 -0500
commit14ed832af5bb3aebf4b8da9e1e96ad0e8d194c6e (patch)
tree5badd1dc1b5c293b1f71986df967cbe172534169 /host/examples
parentd9e8e8261790609f2d53ab48bb6eb90cb6100376 (diff)
downloaduhd-14ed832af5bb3aebf4b8da9e1e96ad0e8d194c6e.tar.gz
uhd-14ed832af5bb3aebf4b8da9e1e96ad0e8d194c6e.tar.bz2
uhd-14ed832af5bb3aebf4b8da9e1e96ad0e8d194c6e.zip
examples: Add usrp_power_meter example
This is a utility that can be used to measure received power, assuming a calibrated device. For example, it can be called like this: usrp_power_meter.py -a type=x300 -f 1e9 --mode continuous To continuously measure input power at 1 GHz.
Diffstat (limited to 'host/examples')
-rw-r--r--host/examples/python/CMakeLists.txt5
-rw-r--r--host/examples/python/usrp_power_meter.py131
2 files changed, 135 insertions, 1 deletions
diff --git a/host/examples/python/CMakeLists.txt b/host/examples/python/CMakeLists.txt
index 23d1b83c6..e79b1bd4a 100644
--- a/host/examples/python/CMakeLists.txt
+++ b/host/examples/python/CMakeLists.txt
@@ -9,6 +9,9 @@ set(python_examples
tx_waveforms.py
curses_fft.py
benchmark_rate.py
+ usrp_power_meter.py
)
-UHD_INSTALL(PROGRAMS ${python_examples} DESTINATION ${PKG_LIB_DIR}/examples/python COMPONENT examples)
+UHD_INSTALL(PROGRAMS ${python_examples}
+ DESTINATION ${PKG_LIB_DIR}/examples/python
+ COMPONENT examples)
diff --git a/host/examples/python/usrp_power_meter.py b/host/examples/python/usrp_power_meter.py
new file mode 100644
index 000000000..7cd3dd3f6
--- /dev/null
+++ b/host/examples/python/usrp_power_meter.py
@@ -0,0 +1,131 @@
+#!/usr/bin/env python3
+#
+# Copyright 2020 Ettus Research, a National Instruments Brand
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+"""
+Use a calibrated USRP as a power meter
+"""
+
+import sys
+import signal
+import argparse
+import uhd
+
+def parse_args():
+ """Parse the command line arguments"""
+ parser = argparse.ArgumentParser()
+ parser.add_argument("-a", "--args", default="",
+ help="USRP Device Args")
+ parser.add_argument("-f", "--freq", type=float, required=True,
+ help="Center Frequency")
+ parser.add_argument("-o", "--lo-offset", type=float, default=0.0,
+ help="Optional LO offset")
+ parser.add_argument("-c", "--channel", type=int, default=0,
+ help="USRP RX Channel Index")
+ parser.add_argument("-t", "--antenna",
+ help="USRP RX Antenna")
+ parser.add_argument("-r", "--rate", default=1e6, type=float,
+ help="Sampling Rate")
+ parser.add_argument("-b", "--bandwidth", type=float,
+ help="Analog filter bandwidth (if supported)")
+ parser.add_argument("-l", "--ref-level", type=float, default=-15,
+ help="RX reference power level. "
+ "This should be higher than the expected power.")
+ parser.add_argument("-n", "--samps-per-est", type=float, default=1e6,
+ help="Samples per estimate.")
+ parser.add_argument("--mode", choices=['one-shot', 'continuous'], default='one-shot',
+ help="Measure once, or keep measuring until Ctrl-C is pressed.")
+ return parser.parse_args()
+
+def get_streamer(usrp, chan):
+ """
+ Return an RX streamer with fc32 output
+ """
+ stream_args = uhd.usrp.StreamArgs('fc32', 'sc16')
+ stream_args.channels = [chan]
+ return usrp.get_rx_stream(stream_args)
+
+def setup_device(usrp, args, chan):
+ """
+ Apply the settings from args to the device
+ """
+ print("Requesting RX rate of {} Msps...".format(args.rate / 1e6), end='')
+ usrp.set_rx_rate(args.rate, chan)
+ if abs(usrp.get_rx_rate(chan) - args.rate) > 1.0:
+ print("ALMOST. Actual rate: {} Msps"
+ .format(usrp.get_rx_rate(chan) / 1e6))
+ else:
+ print("OK")
+ if args.antenna:
+ print("Setting RX antenna to `{}'...".format(args.antenna), end='')
+ usrp.set_rx_antenna(args.antenna, chan)
+ print("OK")
+ print("Requesting RX frequency of {} MHz...".format(args.freq / 1e6), end='')
+ tr = uhd.types.TuneRequest(args.freq, args.lo_offset)
+ usrp.set_rx_freq(tr, chan)
+ if abs(usrp.get_rx_freq(chan) - args.freq) > 1.0:
+ print("ALMOST. Actual frequency: {} MHz".format(usrp.get_rx_freq(chan) / 1e6))
+ else:
+ print("OK")
+ print("Requesting RX power reference level of {:.2f} dBm..."
+ .format(args.ref_level), end='')
+ usrp.set_rx_power_reference(args.ref_level, chan)
+ ref_level = usrp.get_rx_power_reference(chan)
+ if abs(ref_level - args.ref_level) > 1.0:
+ print("ALMOST. Actual ref level: {:.2f} dBm".format(ref_level))
+ else:
+ print("OK")
+ if args.bandwidth:
+ print("Requesting analog RX bandwidth of {} Msps..."
+ .format(args.bandwidth), end='')
+ usrp.set_rx_bandwidth(args.bandwidth, chan)
+ if abs(usrp.get_rx_bandwidth(chan) - args.bandwidth) > 1.0:
+ print("ALMOST. Actual bandwidth: {} MHz"
+ .format(usrp.get_rx_bandwidth(chan) / 1e6))
+ else:
+ print("OK")
+ return ref_level
+
+RUN = True
+
+def main():
+ """
+ gogogo
+ """
+ args = parse_args()
+ usrp = uhd.usrp.MultiUSRP(args.args)
+ chan = args.channel
+ if chan > usrp.get_rx_num_channels():
+ print("ERROR: Invalid channel selected: {} (only {} channels available!)"
+ .format(chan, usrp.get_rx_num_channels()))
+ return False
+ print("Using channel: {}".format(chan))
+ if not usrp.has_rx_power_reference(chan):
+ print("ERROR: This device is not calibrated for RX!")
+ return False
+ ref_level = setup_device(usrp, args, chan)
+ streamer = get_streamer(usrp, chan)
+ if args.mode == 'continuous':
+ def handle_sigint(_sig, _frame):
+ print("Caught Ctrl-C, exiting...")
+ global RUN
+ RUN = False
+ signal.signal(signal.SIGINT, handle_sigint)
+ while RUN:
+ try:
+ power_dbfs = uhd.dsp.signals.get_usrp_power(
+ streamer, num_samps=int(args.samps_per_est), chan=chan)
+ except RuntimeError:
+ # This is a hack b/c the signal handler is not gracefully handling
+ # SIGINT
+ break
+ power_dbm = power_dbfs + ref_level
+ print("Received power: {:+6.2f} dBm".format(power_dbm))
+ if args.mode == 'one-shot':
+ break
+ return True
+
+if __name__ == "__main__":
+ sys.exit(not main())