6、USRP【入门软件无线电(SDR)】PySDR:使用 Python 的 SDR 和 DSP 指南

2023-11-17

因为设备不同,本教程未实测,仅作为USRP参考

在这里插入图片描述
在本章中,我们将学习如何使用UHD Python API通过USRP控制和接收/传输信号,USRP是由Ettus Research(现为NI的一部分)制造的一系列SDR。我们将讨论 Python 中 USRP 上的发送和接收,并深入探讨 USRP 特定的主题,包括流参数、子设备、通道、10 MHz 和 PPS 同步。

软件/驱动程序安装

虽然本教科书中提供的 Python 代码应该可以在 Windows、Mac 和 Linux 下工作,但我们只会提供特定于 Ubuntu 22 的驱动程序/API 安装说明(尽管下面的说明应该适用于大多数基于 Debian 的发行版)。我们将首先创建一个 Ubuntu 22 VirtualBox VM;如果操作系统已准备就绪,请随意跳过 VM 部分。或者,如果您使用的是Windows 11,则使用Ubuntu 22的Linux(WSL)的Windows子系统往往运行良好,并且支持开箱即用的图形。

设置 Ubuntu 22 VM

1、下载 Ubuntu 22.04 桌面版 .iso- https://ubuntu.com/download/desktop
2、安装并打开VirtualBox.
3、创建新的 VM。对于内存大小,我建议使用计算机 RAM 的 50%。
4、创建虚拟硬盘,选择 VDI,然后动态分配大小。15 GB 应该足够了。如果你想真正安全,你可以使用更多。
5、启动 VM。它会要求您提供安装介质。选择 Ubuntu 22 桌面.iso文件。选择“安装 ubuntu”,使用默认选项,弹出窗口将警告您即将进行的更改。点击继续。选择名称/密码,然后等待 VM 完成初始化。完成后,VM 将重新启动,但应在重新启动后关闭 VM 电源。
6、进入 VM 设置(齿轮图标)。
7、在“系统>处理器”下,>至少选择 3 个 CPU。如果您有实际的视频卡,那么在显示器>视频内存中>选择更高的视频卡。
8、启动 VM。
9、对于 USB 类型的 USRP,您需要安装 VM 来宾添加功能。在 VM 中,转到“设备>插入来宾添加 CD”>在弹出框时点击运行。按照说明操作。重新启动 VM,然后尝试将 USRP 转发到该 VM,假设它显示在“> USB 的设备”下的列表中。可以通过“双向共享剪贴板”>“共享剪贴板”>设备启用共享剪贴板。

安装 UHD 和 Python API

下面的终端命令应该构建并安装最新版本的UHD,包括Python API:

sudo apt-get install git cmake libboost-all-dev libusb-1.0-0-dev python3-docutils python3-mako python3-numpy python3-requests python3-ruamel.yaml python3-setuptools build-essential
cd ~
git clone https://github.com/EttusResearch/uhd.git
cd uhd/host
mkdir build
cd build
cmake -DENABLE_TESTS=OFF -DENABLE_C_API=OFF -DENABLE_MANUAL=OFF ..
make -j8
sudo make install
sudo ldconfig

有关更多帮助,请参阅Ettus的官方构建和从源代码页面安装UHD(https://files.ettus.com/manual/page_build_guide.html)。请注意,还有一些安装驱动程序的方法不需要从源代码构建。

测试 UHD 驱动程序和 Python API

打开一个新终端并键入以下命令:

python3
import uhd
usrp = uhd.usrp.MultiUSRP()
samples = usrp.recv_num_samps(10000, 100e6, 1e6, [0], 50)
print(samples[0:10])

如果没有发生错误,您就可以开始了!

在 Python 中对 USRP 速度进行基准测试

如果您使用的是标准的源安装,以下命令应使用 Python API 对 USRP 的接收速率进行基准测试。如果使用 56e6 导致许多样本丢失或溢出,请尝试降低该数字。丢弃的样本不一定会毁掉任何东西,但这是测试使用 VM 或旧计算机可能带来的低效率的好方法。如果使用 B 2X0,一台具有 USB 3.0 端口正常运行的相当现代的计算机应该能够做到 56 MHz 而不会丢失样本,尤其是在num_recv_frames设置如此之高的情况下。

python /usr/lib/uhd/examples/python/benchmark_rate.py --rx_rate 56e6 --args "num_recv_frames=1000"

接收

使用内置的便利函数“recv_num_samps()”从USRP接收样本非常容易,下面是使用1 MHz采样率将USRP调谐到100 MHz的Python代码,并使用50 dB的接收增益从USRP中抓取10000个样本:

import uhd
usrp = uhd.usrp.MultiUSRP()
samples = usrp.recv_num_samps(10000, 100e6, 1e6, [0], 50) # units: N, Hz, Hz, list of channel IDs, dB
print(samples[0:10])

[0] 告诉 USRP 使用其第一个输入端口,并且只接收一个通道的样本(例如,对于同时在两个通道上接收的 B210,您可以使用 [0, 1])
如果您尝试以高速率接收但溢出(O 显示在您的控制台中),这里有一个提示。代替 usrp = uhd.usrp.MultiUSRP() ,请使用:

usrp = uhd.usrp.MultiUSRP("num_recv_frames=1000")

这使得接收缓冲区更大(默认值为 32),有助于减少溢出。缓冲区的实际大小(以字节为单位)取决于 USRP 和连接类型,但只需将 num_recv_frames 设置为远高于 32 的值往往会有所帮助。
对于更严肃的应用程序,我建议不要使用便利函数 recv_num_samps(),因为它隐藏了一些有趣的行为,并且每次调用都会发生一些设置,我们可能只想在开始时执行一次,例如,如果我们想无限期地接收样本。以下代码具有与 recv_num_samps() 相同的功能,实际上它几乎正是使用 便利函数时调用的功能,但现在我们可以选择修改行为:

import uhd
import numpy as np

usrp = uhd.usrp.MultiUSRP()

num_samps = 10000 # number of samples received
center_freq = 100e6 # Hz
sample_rate = 1e6 # Hz
gain = 50 # dB

usrp.set_rx_rate(sample_rate, 0)
usrp.set_rx_freq(uhd.libpyuhd.types.tune_request(center_freq), 0)
usrp.set_rx_gain(gain, 0)

# Set up the stream and receive buffer
st_args = uhd.usrp.StreamArgs("fc32", "sc16")
st_args.channels = [0]
metadata = uhd.types.RXMetadata()
streamer = usrp.get_rx_stream(st_args)
recv_buffer = np.zeros((1, 1000), dtype=np.complex64)

# Start Stream
stream_cmd = uhd.types.StreamCMD(uhd.types.StreamMode.start_cont)
stream_cmd.stream_now = True
streamer.issue_stream_cmd(stream_cmd)

# Receive Samples
samples = np.zeros(num_samps, dtype=np.complex64)
for i in range(num_samps//1000):
    streamer.recv(recv_buffer, metadata)
    samples[i*1000:(i+1)*1000] = recv_buffer[0]

# Stop Stream
stream_cmd = uhd.types.StreamCMD(uhd.types.StreamMode.stop_cont)
streamer.issue_stream_cmd(stream_cmd)

print(len(samples))
print(samples[0:10])

将num_samps设置为 10,000 且recv_buffer设置为 1000 时,for 循环将运行 10 次,即对 streamer.recv 的调用将有 10 次。请注意,我们将recv_buffer硬编码为 1000,但您可以使用 streamer.get_max_num_samps() 找到允许的最大值,通常约为 3000 左右。另请注意,recv_buffer必须是 2d,因为一次接收多个通道时使用相同的 API,但在我们的例子中,我们只接收了一个通道,所以 recv_buffer[0] 给了我们想要的 1D 样本数组。您现在不需要太了解流的开始/停止方式,但要知道除了“连续”模式之外还有其他选项,例如接收特定数量的样本并让流自动停止。 尽管我们在此示例代码中不处理元数据,但它包含发生的任何错误,如果需要,您可以通过查看循环每次迭代的metadata.error_code来检查这些错误(由于 UHD,错误往往也会显示在控制台本身中,因此不必觉得必须在 Python 代码中检查它们)。

接收增益(Receive Gain)

以下列表显示了不同USRP的增益范围,它们都从0 dB到下面指定的数字。请注意,这不是 dBm,它本质上是 dBm 与一些未知偏移相结合,因为这些不是校准设备。

  • B200/B210/B200-mini: 76 dB
  • X310/N210 with WBX/SBX/UBX: 31.5 dB
  • X310 with TwinRX: 93 dB
  • E310/E312: 76 dB
  • N320/N321: 60 dB

您也可以在终端中使用命令 uhd_usrp_probe ,在RX前端部分中,它将提及增益范围。
指定增益时,您可以使用普通的 set_rx_gain() 函数,该函数以 dB 为单位获取增益值,但您也可以使用 set_normalized_rx_gain() 函数,该函数接收 0 到 1 之间的值,并自动将其转换为您正在使用的 USRP 范围。这在制作支持不同型号 USRP 的应用程序时很方便。使用归一化增益的缺点是不再以dB为单位的单位,因此,例如,如果要将增益增加10 dB,则现在必须计算该量。

自动增益控制

包括B200和E310系列在内的一些USRP支持自动增益控制(AGC),它将根据接收信号电平自动调整接收增益,以最好地“填充”ADC的位。可以使用以下命令打开 AGC:

usrp.set_rx_agc(True, 0) # 0 for channel 0, i.e. the first channel of the USRP

如果您的 USRP 未实现 AGC,则在运行上述行时将引发异常。打开 AGC 时,设置增益不会执行任何操作。

流参数

在上面的完整示例中,您将看到行 st_args = uhd.usrp.StreamArgs(“fc32”, “sc16”) 。第一个参数是 CPU 数据格式,这是样本在主机上的数据类型。使用 Python API 时,UHD 支持以下 CPU 数据类型:在这里插入图片描述
您可能会在 UHD C++ API 的文档中看到其他选项,但至少在撰写本文时,这些选项从未在 Python API 中实现。
第二个参数是“在线”数据格式,即样本通过USB/以太网/SFP发送到主机时的数据类型。对于 Python API,选项包括:“sc16”、“sc12”和“sc8”,其中 12 位选项仅受某些 USRP 支持。这种选择很重要,因为 USRP 和主机之间的连接通常是瓶颈,因此通过从 16 位切换到 8 位,您可能会获得更高的速率。还要记住,许多USRP的ADC限制为12位或14位,使用“sc16”并不意味着ADC是16位。
有关 st_args 的通道部分,请参阅下面的子设备和通道小节。

传输

与 recv_num_samps() 便利功能类似,UHD 提供 send_waveform() 功能来传输一批样本,示例如下所示。如果您指定的持续时间(以秒为单位)比提供的信号长,它将简单地重复它。它有助于将样本的值保持在 -1.0 和 1.0 之间。

import uhd
import numpy as np
usrp = uhd.usrp.MultiUSRP()
samples = 0.1*np.random.randn(10000) + 0.1j*np.random.randn(10000) # create random signal
duration = 10 # seconds
center_freq = 915e6
sample_rate = 1e6
gain = 20 # [dB] start low then work your way up
usrp.send_waveform(samples, duration, center_freq, sample_rate, [0], gain)

有关此便利功能如何在后台工作的详细信息,请参阅源代码(https://github.com/EttusResearch/uhd/blob/master/host/python/uhd/usrp/multi_usrp.py) .

发送增益(Transmit Gain)

与接收端类似,发射增益范围因USRP型号而异,从0 dB到以下指定值:

  • B200/B210/B200-mini: 90 dB
  • N210 with WBX: 25 dB
  • N210 with SBX or UBX: 31.5 dB
  • E310/E312: 90 dB
  • N320/N321: 60 dB

如果您想使用范围 0 到 1 指定发射增益,还有一个 set_normalized_tx_gain() 函数。

同时发送和接收

如果要同时使用相同的 USRP 进行发送和接收,关键是在同一进程中使用多个线程进行传输和接收;USRP 不能跨越多个进程。例如,在txrx_loopback_to_file C++示例中,创建了一个单独的线程来运行发送器,接收在主线程中完成。你也可以只生成两个线程,一个用于传输,一个用于接收,就像在benchmark_rate Python 示例中所做的那样。这里没有显示一个完整的例子,仅仅是因为它将是一个相当长的例子,而Ettus的benchmark_rate.py总是可以作为某人的起点。

子设备、信道和天线

使用 USRP 时,一个常见的混淆来源是如何选择正确的子设备和通道 ID。您可能已经注意到,在上面的每个示例中,我们使用了通道 0,并且没有指定与 subdev 相关的任何内容。如果您使用的是 B210,并且只想使用 RF:B 而不是 RF:A,您只需选择通道 1 而不是 0。但是在像 X310 这样有两个子板插槽的 USRP 上,您必须告诉 UHD 是要使用插槽 A 还是 B,以及该子板上的哪个通道,例如:

usrp.set_rx_subdev_spec("B:0")

如果要使用 TX/RX 端口而不是 RX2(默认),只需:

usrp.set_rx_antenna('TX/RX', 0) # set channel 0 to 'TX/RX'

它基本上只控制 USRP 上的射频开关,以从另一个 SMA 连接器路由。
要同时在两个通道上接收或发送,请提供一个列表,而不是使用 st_args.channels = [0] ,例如 [0,1] 。在这种情况下,接收样本缓冲区的大小必须为 (2, N),而不是 (1,N)。请记住,对于大多数USRP,两个通道共享一个LO,因此您无法同时调谐到不同的频率。

同步到 10 MHz 和 PPS

与其他 SDR 相比,使用 USRP 的巨大优势之一是它们能够同步到外部源或板载 GPSDO 。如果您已将外部 10 MHz 和 PPS 源连接到 USRP,则需要确保在初始化 USRP 后呼叫以下两条线路:

usrp.set_clock_source("external")
usrp.set_time_source("external")

如果您使用的是板载 GPSDO,您将改为使用:

usrp.set_clock_source("gpsdo")
usrp.set_time_source("gpsdo")

在频率同步方面,没有太多其他事情要做;USRP混频器中使用的LO现在将绑定到外部源或GPSDO。但在计时方面,例如,您可能希望命令USRP在PPS上准确开始采样。这可以通过以下代码完成:

# copy the receive example above, everything up until # Start Stream

# Wait for 1 PPS to happen, then set the time at next PPS to 0.0
time_at_last_pps = usrp.get_time_last_pps().get_real_secs()
while time_at_last_pps == usrp.get_time_last_pps().get_real_secs():
    time.sleep(0.1) # keep waiting till it happens- if this while loop never finishes then the PPS signal isn't there
usrp.set_time_next_pps(uhd.libpyuhd.types.time_spec(0.0))

# Schedule Rx of num_samps samples exactly 3 seconds from last PPS
stream_cmd = uhd.types.StreamCMD(uhd.types.StreamMode.num_done)
stream_cmd.num_samps = num_samps
stream_cmd.stream_now = False
stream_cmd.time_spec = uhd.libpyuhd.types.time_spec(3.0) # set start time (try tweaking this)
streamer.issue_stream_cmd(stream_cmd)

# Receive Samples.  recv() will return zeros, then our samples, then more zeros, letting us know it's done
waiting_to_start = True # keep track of where we are in the cycle (see above comment)
nsamps = 0
i = 0
samples = np.zeros(num_samps, dtype=np.complex64)
while nsamps != 0 or waiting_to_start:
    nsamps = streamer.recv(recv_buffer, metadata)
    if nsamps and waiting_to_start:
        waiting_to_start = False
    elif nsamps:
        samples[i:i+nsamps] = recv_buffer[0][0:nsamps]
    i += nsamps

如果看起来它不起作用,但没有抛出任何错误,请尝试将该 3.0 数字从 1.0 到 5.0 之间的任何值更改。您也可以在调用 recv() 后检查元数据,只需检查 if metadata.error_code != uhd.types.RXMetadataErrorCode.none: 即可。
为了进行调试,您可以通过检查 usrp.get_mboard_sensor(“ref_locked”, 0) 的返回来验证 10 MHz 信号是否显示到 USRP。如果 PPS 信号没有显示,您就会知道它,因为上面代码中的第一个 while 循环永远不会完成。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

6、USRP【入门软件无线电(SDR)】PySDR:使用 Python 的 SDR 和 DSP 指南 的相关文章

随机推荐

  • CentOS 8.5:mysql8 + php8 使用 phpmyadmin52

    使用 dnf 安装命令没有安装成功 下载安装 phpmyadmin 下载地址 最新版本为 5 2 phpMyAdmin Downloads etc nginx nginx conf 中的配置内容 server listen 80 liste
  • VS Code的神级插件Bito - GPT-4 和 ChatGPT 编写代码、解释代码、创建测试

    Bito是什么 Bito是一款插件 它目前支持VS Code Chrome插件 以及Jetbrains的全系列IDE 例如 IDEA PyCharm Clion等 可以说能够覆盖大部分开发同学了 Bito 通过将 GPT 4 和 ChatG
  • KMP算法理解

    学习了KMP算法 对此有了一些理解 通过博客分享 如有理解错误的地方 请纠正 文章目录 字符串的前缀后缀 最大公共长度数组获取 KMP算法 时间复杂度 字符串的前缀后缀 再说明KMP算法前见说下它用到的一些东西 给定一个字符串如 ABCDA
  • 1.机器学习的基础概念

    机器学习的基础概念 文章目录 机器学习的基础概念 机器学习的分类 一 监督学习 1 监督学习概念 2 监督学习流程 3 监督学习算法 二 无监督学习 1 无监督学习概念 2 无监督学习流程 3 无监督学习算法 总结 机器学习的分类 机器学习
  • python 博弈论 库_6个Python库解释机器学习模型并建立信任

    原标题 6个Python库解释机器学习模型并建立信任 在机器学习模型中建立信任的案例 全球道路上大约有12亿辆汽车 这是一个令人毛骨悚然的问题 您认为实际上有多少驾驶员了解车辆的内部运行情况 您可能已经猜到了 答案只是少数几个人 我们不需要
  • 拿金币 蓝桥杯

    问题描述 有一个N x N的方格 每一个格子都有一些金币 只要站在格子里就能拿到里面的金币 你站在最左上角的格子里 每次可以从一个格子走到它右边或下边的格子里 请问如何走才能拿到最多的金币 输入格式 第一行输入一个正整数n 以下n行描述该方
  • LINUX IO内存操作方法

    https wenku baidu com view f15358692bf90242a8956bec0975f46527d3a7f3 html
  • 快看!那个学vSLAM的上吊了! —— (一)综述

    不同于之前发布的文章 我将使用一种全新的方式 iPad Notability Blog的方式打开这个板块的大门 原因有两个 1 Notability更方便手写长公式 也方便手绘坐标系变换等等 2 之前Apple Pencil找不到了新破费买
  • Qt5.9中一个槽函数接收多个信号用法(函数sender())

    本文主要总结一种常用情况 当多个信号同时发送到一个槽函数时 需要在槽函数中判断 是哪个信号发射过来的 解决这个问题 主要用到函数 QObject sender 和QString sender objectName QObject sende
  • devops-部署web服务器环境

    1 java 环境 各 wenb 服务器准备 tomcat 运行环境 useradd www u 2000 mkdir apps cd apps tar xvfjdk 8u181 linux x64 tar gz ln sv apps jd
  • 手把手教你使用 Prometheus 监控 JVM

    概述 当你的 Java 业务容器化上 K8S 后 如果对其进行监控呢 Prometheus 社区开发了 JMX Exporter 来导出 JVM 的监控指标 以便使用 Prometheus 来采集监控数据 本文将介绍如何利用 Prometh
  • 如何保证同事的代码不会腐烂?一文带你了解 Alibaba COLA 架构

    本文开始前 问大家一个问题 你觉得一份业务代码 尤其是互联网业务代码 都有哪些特点 我能想到的有这几点 互联网业务迭代快 工期紧 导致代码结构混乱 几乎没有代码注释和文档 互联网人员变动频繁 很容易接手别人的老项目 新人根本没时间吃透代码结
  • 帝国霸业服务器无限加载,帝国霸业银河生存控制台有哪些指令 控制台指令一览...

    游戏里面能够开启控制面板键入命令 在网络服务器中一样还可以 但是很有可能许多游戏玩家不清楚命令编码 下边大家就为大伙儿产生帝国霸业星空存活网络服务器有什么命令的详细介绍 有必须的游戏玩家快看来一下吧 游戏里面能够开启控制面板键入命令 在网络
  • docker中的zookeeper安装、连接及常见命令

    一 docker安装 1 搜索一下Zookeeper镜像 这一步可以省略 docker search zookeeper 2 从Docker上下载zookeeper docker pull zookeeper 3 启动Zookeeper镜像
  • 【华为OD统一考试B卷

    在线OJ 已购买本专栏用户 请私信博主开通账号 在线刷题 运行出现 Runtime Error 0Aborted 请忽略 华为OD统一考试A卷 B卷 新题库说明 2023年5月份 华为官方已经将的 2022 0223Q 1 2 3 4 统一
  • 微信小程序开发-AppID申请

    开始 开发小程序的第一步 你需要拥有一个小程序帐号 通过这个帐号你就可以管理你的小程序 跟随这个教程 开始你的小程序之旅吧 申请帐号 进入小程序注册页 根据指引填写信息和提交相应的资料 就可以拥有自己的小程序帐号 在这个小程序管理平台 你可
  • TortoiseSVN 日常操作指南

    原文地址 http blog csdn net happy4nothing article details 376604 Toc101751879 TortoiseSVN A Subversion client for Windows St
  • Oracle中如何获取系统当前时间

    select to char sysdate yyyy mm dd hh24 mi ss from dual ORACLE里获取一个时间的年 季 月 周 日的函数 select to char sysdate yyyy from dual
  • 解决Visual Studio Code点击运行出现无法访问此网站

    1 访问后的网页 2 经过检查发现里面多出一个文件 vscode gt launch json 可能是你在运行时打开的窗口有 css文件 这是我猜的 3 把多出的文件夹删除掉 Vscode launch json 把刚才拒绝访问的网页关闭掉
  • 6、USRP【入门软件无线电(SDR)】PySDR:使用 Python 的 SDR 和 DSP 指南

    因为设备不同 本教程未实测 仅作为USRP参考 在本章中 我们将学习如何使用UHD Python API通过USRP控制和接收 传输信号 USRP是由Ettus Research 现为NI的一部分 制造的一系列SDR 我们将讨论 Pytho