前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >GNURadio+USRP+OFDM实现文件传输

GNURadio+USRP+OFDM实现文件传输

作者头像
Gnep@97
发布2024-03-08 08:39:24
5930
发布2024-03-08 08:39:24
举报

前言

使用 GNU Radio Companion 驱动 USRP N320 实现 OFDM 自收自发测试。(Ubuntu20.04LTS + GNURadio 3.8 + UHD 3.15)

一、发送端

该模块由随机数信号源、CRC、符号映射器、FFT、循环前缀加法器、放大器组成。主要目标是传输随机信号,根据调制方式的选择对有效载荷进行重新包装。选择的调制是 QPSK,所以 2 位被重新打包在一起。然后将有效载荷和报头分别映射到 QPSK 和 BPSK 的复星座矢量中。OFDM 载波分配器分配占用载波、导频载波、导频符号和同步字。FFT(Reverse)或 IFFT采用复数值向量并计算 IFFT 它表示输出。循环前缀以 OFDM 符号作为其输入,从而产生具有循环前缀的输出符号。

1、参数配置

1)Random Source

Random Source:

  • 生成一些 [min, max] 随机数的样本,这意味着最大值将不包括在内。如果指定重复样品。用于创建用于测试调制器的信息字节。
    • 输出类型是 “字节”,取值范围 0~255,输出中生成的样本总数为 1000,指定生成重复样品
2)stream to Tagged stream

①、变量:packet_len

②、stream to Tagged stream

  • 将普通流转换为标记流。这个块所做的就是按一定的间隔添加长度标签。它可用于将常规流连接到gr::tagged_stream_block。这个块意味着直接连接到一个带标签的流块
  • 输出类型为 “字节”,每个带标签的流数据包的长度为 1 包。
3)Stream CRC32

①、变量:length_tag_key

②、Stream CRC32

  • 字节流 CRC(循环冗余校验) 块
  • Stream CRC 32是一个带标签的流块,需要一个 Length tag key,因此前面加了一个 stream to Tagged stream

下面举例介绍:

CRC32 之后的数据图如下所示,CRC 已经被添加到每个分组的末尾,并且分组长度标签已经从 100 字节被更新到104 字节,其中额外的 4 个字节用干 CRC

4)Protocol Formatter

①、变量:length_tag_key

②、变量:occupied_carriers

  • -26~26 范围内不包括子载波索引为 -21,-7,0,7,21

③、变量:hdr_format

  • digital.header_format_ofdm(occupied_carriers, 1, length_tag_key,)
    • 用于生成 OFDM 的头部格式
      • occupied_carriers: 用于指定 OFDM 系统中被占用的载波序列。
      • 1: 用于指定 OFDM 头部的长度
      • length_tag_key: 用于指定标记头部长度的 key

header_format_ofdm C++ 实现源码如下:

代码语言:javascript
复制
header_format_ofdm::header_format_ofdm(
    const std::vector<std::vector<int>>& occupied_carriers,
    int n_syms,
    const std::string& len_key_name,
    const std::string& frame_key_name,
    const std::string& num_key_name,
    int bits_per_header_sym,
    int bits_per_payload_sym,
    bool scramble_header)
    : header_format_crc(len_key_name, num_key_name),
      d_frame_key_name(pmt::intern(frame_key_name)),
      d_occupied_carriers(occupied_carriers),
      d_bits_per_payload_sym(bits_per_payload_sym)
{
    d_header_len = 0;
    for (int i = 0; i < n_syms; i++) {
        d_header_len += occupied_carriers[i].size();
    }

    d_syms_per_set = 0;
    for (unsigned i = 0; i < d_occupied_carriers.size(); i++) {
        d_syms_per_set += d_occupied_carriers[i].size();
    }

    // Init scrambler mask
    d_scramble_mask = std::vector<uint8_t>(header_nbits(), 0);
    if (scramble_header) {
        // These are just random values which already have OK PAPR:
        gr::digital::lfsr shift_reg(0x8a, 0x6f, 7);
        for (size_t i = 0; i < header_nbytes(); i++) {
            for (int k = 0; k < bits_per_header_sym; k++) {
                d_scramble_mask[i] ^= shift_reg.next_bit() << k;
            }
        }
    }
}

④、Protocol Formatter

  • 使用报头格式对象从标记的流数据包创建报头。这个块接受标记流并创建一个标头,通常用于 mac 级处理。
5)Repack Bits

①、Repack Bits

  • 将输入流中的位重新打包到输出流的位上。这里没有丢失任何信息;k(每个输入的字节位数)和 l(每个输出的字节位数)的任何值([1, 8] 内)都是允许的。在每个新输入字节上,它开始读取 LSB,并开始复制到 LSB。
  • 每个输入字节的位数 (k)
    • 输入流上的相关位数
  • 每个输出字节的位数 (l)
    • 输出流上的相关位数
  • 长度标签键
    • 如果不为空,则这是长度标签的键。
  • 字节顺序
    • 输出数据流的字节顺序(LSB 或 MSB)。
  • 包对齐
    • 当提供长度标签键时,它控制输入或输出是否对齐。Repack Bits 对标记的流进行操作。在这种情况下,当 k * 输入长度l * 输出长度时,可能会发生输入数据或输出数据变得不对齐的情况。在这种情况下,Pack Alignment 参数用于决定对齐哪个数据包。通常,Pack Alignment 设置为用于解包的输入(k=8,l < 8)和用于反转的输出。例如,假设你正在发送 8-PSK,因此在调制器之前的发送侧设置 k=8、l=3。现在假设您正在传输单个字节(8位)的数据。您的传入标记流的长度为 1(现在共 8+1=9 位,多出 1 位为标记流的长度),传出的长度为 3。但是,第三项实际上仅携带 2 位相关数据(多出来的 1 位标记流),这些位与边界不对齐。因此,您将 Pack Alignment 设置为 Input,因为输出可能不对齐。`现在假设您正在执行相反的操作:将这三项打包为完整字节。你如何解释这三个字节?如果没有这个标志,您必须假设其中有 9 个相关位,因此最终会得到 2 个字节的输出数据。但在打包的情况下,您希望输出对齐;所有输出位都必须有用。通过断言此标志,打包算法尝试执行此操作,并且在本例中假设由于我们在 8 位之后进行了对齐,因此可以丢弃第 9 位。
  • 每个输入的字节位数为 8,每个输出的字节位数为 1

8PSK 星座图如下:

②、变量:occupied_carriers

③、Repack Bits

  • digital.constellation_qpsk().bits_per_symbol()
    • bits_per_symbol() 函数会根据 QPSK 调制的特性来计算每个符号所携带的平均比特数,这里为 2
6)Virtual Sink

Virtual Sink:

  • 用于接收和处理流图中的数据,并且在流图运行时不产生实际的输出
7)Chunks to Symbols

①、变量:header_mod

②、Chunks to Symbols

  • 将数据分块转换成符号序列。被分成较小的块,然后通过调制技术转换成符号序列,以便在信道上传输。
  • OFDM 头部采用 BPSK,OFDM 有效载荷采用 QPSK
8)Tagged Stream Mux

Tagged Stream Mux:

  • 将多个带有标签的数据流(Tagged Stream)合并成一个数据流,输出信号具有新的长度标签,它是所有单独长度标签的总和,旧的长度标签将被丢弃。
9)OFDM Carrier Allocator

①、变量:occupied_carriers

②、变量:pilot_carriers

  • 导频子载波索引设置为 -21,-7,7,21,载波索引始终使得索引 0 是 DC 载波(注意:您不应分配此载波)

③、变量:pilot_symbols

  • 导频符号:1,1,1,-1

④、变量:sync_word1、sync_word2

  • 同步字1:长度为 64,[0., 0., 0., 0., 0., 0., 0., 1.41421356, 0., -1.41421356, 0., 1.41421356, 0., -1.41421356, 0., -1.41421356, 0., -1.41421356, 0., 1.41421356, 0., -1.41421356, 0., 1.41421356, 0., -1.41421356, 0., -1.41421356, 0., -1.41421356, 0., -1.41421356, 0., 1.41421356, 0., -1.41421356, 0., 1.41421356, 0., 1.41421356, 0., 1.41421356, 0., -1.41421356, 0., 1.41421356, 0., 1.41421356, 0., 1.41421356, 0., -1.41421356, 0., 1.41421356, 0., 1.41421356, 0., 1.41421356, 0., 0., 0., 0., 0., 0.]
  • 同步字2:长度为 64,[0, 0, 0, 0, 0, 0, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 0, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 0, 0, 0, 0, 0]

⑤、OFDM Carrier Allocator:

  • 该模块将复杂的标量调制符号流转换为矢量,作为 OFDM 发射机中 IFFT 的输入。它还支持将导频符号放置到载波上的可能性。载波可以自由分配,如果未分配载波,则将其设置为零。这允许进行 OFDMA 类型的载波分配。
10)FFT

①、fft_len

②、FFT:

  • Reverse 代表做的是 IFFT
  • 进行“fft 移位”,将 DC (0 Hz) 置于中心
11)OFDM Cyclic Prefixer

①、变量:rolloff

②、OFDM Cyclic Prefixer

  • 添加循环前缀并对 OFDM 符号执行脉冲整形(这里没有进行脉冲整形)
  • 滚降 (%) = (滚降 (样本)/ FFT_len) * 100,这里设置为0
12)Multiply Const

Multiply Const: 将输入流乘以标量或向量常量(如果向量,则按元素)

13)Tag Gate

Tag Gate:

  • 控制标签传播。使用此块可以阻止标签传播,这里阻止了标签传播。
14)USRP Sink

①、参数:address0

  • 设置 USRP 发端的 IP 地址为 192.168.10.2,主时钟频率为 200MHz

②、变量:samp_rate

③、参数:carrier_freq

④、参数:tx_gain

⑤、USRP Sink

2、发送端 grc 图

1)生成 OFDM 头部和有效载荷
  • “1” 处的包长度为 100 字节
  • “2” 处的包长度为 6 字节
  • “3” 处的包长度为 48 字节
  • “4” 处的包长度为 400 字节
2)调制后组成一帧 OFDM 信息

OFDM 头部和有效载荷调制后组成一帧 OFDM 信息。

在 OFDM(正交频分复用)系统中,帧通常由头部(Header)和有效载荷(Payload)两部分组成。

  • 头部(Header): 头部是帧的开头部分,通常包含了一些元数据和控制信息,用于管理和识别帧的类型、长度、版本等信息。在头部中可能包括以下内容:
    • 帧起始标志(Frame Start)
    • 帧类型标识(Frame Type)
    • 帧长度(Frame Length)
    • 版本号(Version)
    • CRC(循环冗余校验)等校验信息
    • 其他控制信息,如信道状态、编码方式、调制方式等
  • 有效载荷(Payload): 有效载荷是帧的主要部分,包含了需要传输的实际数据。在数字通信系统中,有效载荷通常是用户数据,如音频、视频、文本等。在 OFDM 系统中,有效载荷会被分成多个符号进行调制,然后通过信道传输。
3)添加循环前缀

将上面的一帧 OFDM 信号通过载波分配器,配置好数据子载波、导频子载波、导频符号、同步字,并将 OFDM 信号通过 IFFT 调制到子载波上,并添加循环前缀。

4)经过 USRP 发送

3、发送结果

1)仿真结果
2)USRP 发射实际频谱图
  • 2M*52/64 = 1,625,000Hz

二、接收端

接收机主要由 OFDM同步器、频率调制器、信号混频器、FFT 和帧采集组成。来自天线的输入信号,采取的带宽对应于包含实际数据的载波数,直接发送到同步器(Schmidl & Cox OFDM synch)。该同步器负责定时同步和频率误差校正。**频率误差校正被馈送到频率调制器,以产生与同步块的频率误差成比例的信号。然后将其与接收到的数据混合以校正错误并输入到解复用器。**解复用器一旦得到数据包的开头,就开始接收数据,并输出报头和有效载荷进行解调。

1、参数设置

1)Schmidl & Cox OFDM synch

Schmidl & Cox OFDM synch:

  • Schmidl & Cox OFDM Sync 是 GNU Radio 中用于实现 OFDM(正交频分复用)系统的同步的模块之一。它的作用是对接收到的信号进行同步,以便正确解调和处理数据。
  • Schmidl & Cox OFDM Sync 模块采用了一种基于循环前缀(Cyclic Prefix)的同步方法,称为 Schmidl & Cox 算法。这种方法通常包括以下步骤:
    • 信号检测: 首先,接收端需要检测到信号并确定接收到的信号是否包含 OFDM 数据。这可能涉及到自动增益控制(AGC)和能量检测等技术。
    • 同步序列检测: 然后,接收端需要在接收到的信号中找到用于同步的特定序列,通常是 OFDM 帧的循环前缀(Cyclic Prefix)。
    • 频率偏移估计: 接着,模块会估计接收信号的频率偏移,以便进行频率校正。频率偏移可能是由于发送端和接收端的本地振荡器不精确而引起的。
    • 时间同步: 最后,模块会根据找到的同步序列进行时间同步,以确定接收到的信号的起始位置,从而进行正确的数据解调。
  • detect 引脚通常用于指示同步算法是否成功检测到 OFDM 信号的起始点,当 detect 引脚为真时,表示同步算法已经成功地检测到了 OFDM 信号的起始点,即找到了帧同步。这意味着接收到的信号可以进一步处理,例如进行解调、解码等操作。
2)Frequency Mod

Frequency Mod:

  • 这个模块是一个输入振幅控制复正弦。它输出一个信号,该信号具有与灵敏度和输入幅度成比例的瞬时相位增加。
  • 以产生与同步块的频率误差成比例的信号
3)Delay

Delay:

  • 将输入延迟一定数量的样本,正延迟在流的开头插入零个项目
4)Header/Payload Demux

Header/Payload Demux:

  • 将数据流中的头部和负载分开。这在通信系统中非常常见,因为数据帧通常包含头部(Header)和负载(Payload),头部用于携带一些控制信息、帧类型、地址等,而负载则携带实际的用户数据。
  • Header/Payload Demux 模块的 trigger 输入端用于指示何时开始解析下一个数据帧的头部信息。这个触发输入可以是一个布尔型信号,当它为真时,模块将开始解析下一个数据帧的头部。
    • 在一个无线通信系统中,当接收到数据帧的结束符或者校验通过时,可以发送一个触发信号给 Header/Payload Demux 模块,以指示当前帧的头部信息已经完整接收,并且可以开始解析下一个帧的头部信息了。
5)OFDM Channel Estimation

OFDM Channel Estimation:

  • 对接收到的 OFDM 信号进行信道估计,以获取信道的频率响应信息。
6)OFDM Frame Equalizer

OFDM Frame Equalizer:

  • 首先,它消除了粗略的载波偏移,接下来,它对标记的 OFDM 帧执行一维或二维均衡。
7)OFDM Serializer

OFDM Serializer:

  • 将 OFDM 子载波中的复数调制符号串行化
  • 这是OFDM 载波分配器的逆块。它将复数数据符号作为标记流输出,并丢弃导频符号
8)Constellation Decoder

Constellation Decoder:

  • 星座解码器,根据对象的映射将星座点从复数空间解码为(解包)位
9)Packet Header Parser

Packet Header Parser:

  • 这是数据包头生成器的逆块。不同的是,解析后的 header 不是作为流输出,而是作为 PMT 字典输出,并发布到 ID 为“header_data”的消息端口。

2、接收端 grc 图

1)提取数据流中头部和负载
2)提取 OFDM 头原始数据
在这里插入图片描述
在这里插入图片描述
3)提取 OFDM 有效负载
4)解调 OFDM 有效负载

符号倍解映射,重新打包和检查字节对应的头数据和发送到文件接收器。

三、结果验证

1、仿真验证

首先不使用 USRP 进行收发,先进行仿真验证直接将发送端送给接收端,在信号源端将发送的数据保存到本地为 send_data.bin,在最后的接收端将接收的数据保存到本地为 recv_data.bin,使用 beyond compare 进行二进制对比,可以看到如下结果,两个文件一致,误码率为0。

2、USRP 验证

1)误码率测试

①、在实际测试过程中发现将发送增益和接收增益都设置为 0 时,收不到数据,因此增加发送及接收增益,发送端增益设置为 20,接收端增益设置为 25,采样率为 1MHz时,对比发送和接收文件,发现存在误码情况,手动计算了一下大约 2.4e-4 的误码率量级

②、采样率为 781.25KHz 时,对比发送和接收文件,发现存在误码情况,手动计算了一下的误码率量级为 7.8e-5

③、采样率为 390.625KHz 时,对比发送和接收文件,未发现存在误码情况,误码率为 0

2)结果图

传输的文本本间对比,左面为发送的数据,右面为接收到的数据

发送端OFDM 时域信号

接收端及发射端OFDM 频谱图

OFDM Header 采用 BPSK 调制方式,Payload 采用 QPSK 调制方式

整体流程图:

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-03-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 一、发送端
    • 1、参数配置
      • 1)Random Source
      • 2)stream to Tagged stream
      • 3)Stream CRC32
      • 4)Protocol Formatter
      • 5)Repack Bits
      • 6)Virtual Sink
      • 7)Chunks to Symbols
      • 8)Tagged Stream Mux
      • 9)OFDM Carrier Allocator
      • 10)FFT
      • 11)OFDM Cyclic Prefixer
      • 12)Multiply Const
      • 13)Tag Gate
      • 14)USRP Sink
    • 2、发送端 grc 图
      • 1)生成 OFDM 头部和有效载荷
      • 2)调制后组成一帧 OFDM 信息
      • 3)添加循环前缀
      • 4)经过 USRP 发送
    • 3、发送结果
      • 1)仿真结果
      • 2)USRP 发射实际频谱图
  • 二、接收端
    • 1、参数设置
      • 1)Schmidl & Cox OFDM synch
      • 2)Frequency Mod
      • 3)Delay
      • 4)Header/Payload Demux
      • 5)OFDM Channel Estimation
      • 6)OFDM Frame Equalizer
      • 7)OFDM Serializer
      • 8)Constellation Decoder
      • 9)Packet Header Parser
    • 2、接收端 grc 图
      • 1)提取数据流中头部和负载
      • 2)提取 OFDM 头原始数据
      • 3)提取 OFDM 有效负载
      • 4)解调 OFDM 有效负载
  • 三、结果验证
    • 1、仿真验证
      • 2、USRP 验证
        • 1)误码率测试
        • 2)结果图
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档