初级教程(3)创建和修改 Python 块4-Python 块标签

4.Python 块标签

本教程演示了如何创建两个嵌入式 Python 块,用于检测输入信号何时超过阈值并为其写入标签,然后在单独的块中读取标签并使用自上次检测以来的时间更新输出。

上一教程Python Block Message Passing演示了如何使用Embedded Python Block发送和接收消息。下一个教程低通滤波器示例演示了如何在 GNU Radio 中使用过滤块。

内容

标签概述

标签是一种以时间同步方式与数字化 RF 样本一起传递信息的方式。当下游块需要知道接收器调谐到新频率的样本时,或者在特定样本中包含时间戳时,标签特别有用。

消息以异步方式传送信息且没有基于时钟的时间保证的情况下,标签是与特定 RF 样本相关联的信息。标签与数据流和矢量中的数字化 RF 样本并存,包括Complex Float 32Float 32Byte和所有其他格式。

使用以下行添加标签:

self.add_item_tag(outputPortNumber, absoluteIndex, key, value)

outputPortNumber确定将标签添加到哪个输出流absoluteIndex添加标签的样本索引。流程图对每个样本进行计数,生成的第一个样本位于绝对样本索引0 处。键是包含要存储变量名称的 PMT 类型,是包含要存储的信息的另一种 PMT 类型。

添加项目标签.png

读取标签可以使用以下功能完成:

tagTuple = self.get_tags_in_window(inputPortNumber, relativeIndexStart, relativeIndexStop))

在窗口中读取标签会根据当前input_items向量中的相对索引读取它们。获取与当前input_items样本对应的所有标签的最简单方法是使用函数调用:

tagTuple = self.get_tags_in_window(inputPortNumber, 0, len(input_items[inputPortNumber])))
GetTagsInWindow.png


可以在此处找到有关标签的更多信息:流标签

创建测试信号

需要一个测试信号。拖入输入信号的块:

  • GLFSR 来源
  • 重复
  • 乘以常量
  • 添加常量
  • 单极 IIR 滤波器
  • 风门
  • QT GUI 时间接收器

更改以下参数:

  • GLFSR 来源,学位:32
  • 重复,插值:128
  • 乘以 Const,常数:0.5
  • 添加 Const,常量:0.5
  • 单极 IIR 滤波器,Alpha:0.05
  • QT GUI 时间接收器
    • 点数:2048
    • 自动缩放:是
  • samp_rate变量,值:3200

将所有块更改为Float输入和输出。根据以下流程图将它们全部连接起来:

测试信号流图.png

运行流程图。生成 过滤后的01的伪随机序列:

测试信号时间接收器.png

阈值检测器:定义块

拖入一个Python Block并双击它以编辑源代码。回想一下,嵌入式 Python 块使用 4 个空格的倍数缩进。

更改example_param变量名称并添加新参数report_period

def __init__(self, threshold=1.0, report_period=128):

更新块名称:

name='阈值检测器',

将输入和输出类型更改为Float

in_sig=[np.float32],
out_sig=[np.float32]

从self.example_param更改变量名称:

self.threshold = 阈值
self.report_period = report_period

删除self.example_param的乘法:

output_items[0][:] = input_items[0]

代码如下所示:

DefineBlockThresholdDetector.png

保存代码 (CTRL + S) 并返回 GRC。该块如下所示:

ThresholdDetectorBlockDefined.png

如果块没有正确更新,则可能是 Python 语法有问题。双击嵌入式 Python 块以查看任何潜在的语法错误。下图给出了 synax 错误所在位置的示例:

ThresholdDetectorPythonError.png

虚拟接收器虚拟源块添加到流程图。更改以下块属性:

  • 阈值检测器
    • 阈值:0.75
    • 报告期:128
  • Virtual Sink , Stream ID: signal
  • 虚拟源,流 ID:信号
  • QT GUI 时间接收器,名称:“阈值检测器”

根据流程图连接块:

阈值检测器已连接.png

阈值检测器:写标签

需要编写阈值检测器的内部结构。回想一下,嵌入式 Python 块使用 4 个空格的倍数缩进。

导入pmt库:

导入PMT

__init__()函数下新增两个变量self.timerself.readyForTag

自拍定时器 = 0
self.readyForTag = True
AddTwoVariables.png

work ()函数需要修改。创建一个 for 循环以遍历所有输入样本:

对于范围内的索引(len(input_items [0])):

需要写三段代码。一旦达到或超过阈值,第一个块将振幅级别写入名为detect的标签。仅当self.readyForTag状态变量为 True时才写入标签。写入标签后,状态变量self.readyForTag将设置为 False。

# 写标签
如果(input_items[0][index] >= self.threshold 和 self.readyForTag == True):
    # 将键定义为“检测”
    key = pmt.intern('检测')
    # 获取检测值
    value = pmt.from_float(np.round(float(input_items[0][index]),2))
    # 要写入的标签索引
    writeIndex = self.nitems_written(0) + 索引
    # 添加标签对象(键值对)
    self.add_item_tag(0, writeIndex, 键, 值)
    # 标签已经写入,设置状态
    self.readyForTag = 假

下一个代码块用于运行计时器。只要self.readyForTag为 False,定时器就会为每个输入样本增加 1:

# 将计时器增加 1
如果(self.readyForTag == False):
    自拍定时器 = 自拍定时器 + 1

第三个代码块控制状态变量self.readyForTag。一旦self.timer达到最大值,计时器就会重置,状态变量self.readyForTag将设置为 True:

# 设置要写的标志
如果(self.timer >= self.report_period):
    # 重置定时器
    自拍定时器 = 0
    # 一旦定时器达到最大值就重置状态
    self.readyForTag = True
写检测标签.png


运行流程图。标签显示在QT GUI Time Sink中:

TimeSinkTags.png

检测计数器:定义块

创建一个新的嵌入式 Python 块来读取标签,计算自上一个标签以来的样本数,并将该数字作为输出。

将一个新的 Python 块拖放到 GRC 工作区中。不要复制和粘贴现有的 python 块,它只会创建Threshold Detector的第二个副本。

双击Embedded Python Block并编辑代码。

删除self.example_param参数:

def __init__(自我):

更改名称:

name='检测计数器',

使输入和输出端口浮动

in_sig=[np.float32],
out_sig=[np.float32]

删除行self.example_param = example_param和乘以self.example_param

output_items[0][:] = input_items[0]
DefineBlockDetectionCounter.png


保存代码 (CTRL + S)。添加另一个QT GUI Time Sink并更改属性:

  • QT GUI 时间接收器
    • 名称:《检测计数器》
    • 点数:2048
    • 自动缩放:是


阈值检测之后 连接检测计数器块。

已添加 DetectionCounterToFlowgraph.png

检测计数器:读取标签

需要修改 检测计数器块以读取标签。

导入pmt库:

导入PMT

在__init__()下添加一个新变量:

self.samplesSinceDetection = 0
添加变量检测计数器.png

修改work()函数以读取标签:

# 获取与 input_items[0] 关联的所有标签
tagTuple = self.get_tags_in_window(0, 0, len(input_items[0]))

遍历所有标签,计算键等于检测的标签的相对偏移量,并将其存储在列表中:

# 声明一个列表
relativeOffsetList = []

# 遍历所有“检测”标签并存储它们的相对偏移量
对于 tagTuple 中的标签:
    如果(pmt.to_python(tag.key)=='检测'):
        relativeOffsetList.append( tag.offset - self.nitems_read(0) )

将偏移量从最低到最高排序:

# 排序相对偏移列表
relativeOffsetList.sort()

遍历所有输出样本:

# 遍历所有输出样本
对于范围内的索引(len(output_items [0])):

使用自上次检测标签以来的当前样本数生成输出样本:

# 输出现在是自检测计数器以来的样本
output_items[0][index] = self.samplesSinceDetection

如果当前输出样本索引大于或等于当前检测标签的索引,则从列表中删除偏移值并重置样本计数器self.samplesSinceDetection。否则,将样本计数器加 1。

# 确保列表不为空,如果当前输入样本
#大于或等于下一个
如果 (len(relativeOffsetList) > 0 和索引 >= relativeOffsetList[0]):
    # 清除偏移量
    relativeOffsetList.pop(0)
    # 重置输出计数器
    self.samplesSinceDetection = 0
别的:
    # 没有看到检测标签,所以继续增加
    # 输出计数器
    self.samplesSinceDetection = self.samplesSinceDetection + 1

删除输出分配:

output_items[0][:] = input_items[0]

工作函数如下所示:

DetectionCounterWorkFunction.png


保存代码 (CTRL + S)。运行流程图。输出如下所示:

DetectionCounterTimeSink.png


请注意,来自检测计数器 输入的所有标签都自动传送到其输出。

标签传播

默认情况下,所有输入标签都会传播到所有输出标签。从某些流中减少或完全删除标签可能很有用。Tag Gate块正是这样做的。在检测计数器块之后连接标签门

TagGateFlowgraph.png


运行流程图。这些标签已从QT GUI Time Sink中删除:

TagGateTimeSink.png

下一个教程低通滤波器示例演示了如何在 GNU Radio 中使用过滤块。

发表回复 0

Your email address will not be published. Required fields are marked *