如何使用 rtlsdr 作为源对特定频率进行带通滤波器?

如何解决如何使用 rtlsdr 作为源对特定频率进行带通滤波器?

我对 Python 和 rtlsdr 的世界仍然很陌生,但我正在使用 RaspBerry Pi 开展一个项目,以便在听到无线电信号时触发警告灯。

在较高的层面上,我的项目使用外部天线用于 2 米无线电频段,该天线连接到插入 RaspBerry Pi 的 rtl-sdr 加密狗。我有一个标准继电器连接到 GPIO 引脚,当它“听到”信号时会打开灯。

我真的不在乎 99% 的输入信号。我只想知道什么时候有 147.3MHz 的载波,让 GPIO 开灯。而已。不多也不少。这当然可以简单地完成吗?我已经阅读了 scipy.signal.butter 带通滤波器,但我无法让它在这个频率下工作。

我的代码在下面,我欢迎任何改进建议,但理想情况下,我正在寻找一种方法来让程序识别 147.3MHz 中心频率处的峰值,然后调用我的“warning_lights.py”脚本。

import RPi.GPIO as GPIO
from rtlsdr import *
from scipy import signal
import peakdetect
import datetime
import sys
import subprocess

def restart():
    import subprocess
    import time
    time.sleep(120)
    command = "/usr/bin/sudo /sbin/shutdown -r Now"
    process = subprocess.Popen(command.split(),stdout=subprocess.PIPE)
    output = process.communicate()[0]
    print (output)


# configure SDR device and settings
sdr = RtlSdr()
sdr.sample_rate = 2.4e6     # Hz
sdr.center_freq = 147.3e6   # Hz
sdr.gain = 'auto'           # Possible values are 0.0 0.9 1.4 2.7 3.7 7.7 8.7 12.5 14.4 15.7 16.6 19.7 20.7 22.9 25.4 28.0 29.7 32.8 33.8 36.4 37.2 38.6 40.2 42.1 43.4 43.9 44.5 48.0 49.6 
num_samples = 1024*1024
procs = []


while True:
    try:
        samples = sdr.read_samples(num_samples)
        power,psd_freq = psd(samples,nfft=1024,Fs=sdr.sample_rate/1e6,Fc=sdr.center_freq/1e6)
        power_db = 10*np.log10(power)

        maxima,minima = peakdetect.peakdetect(power_db,psd_freq,delta=1)
    
        for mx in maxima:
            if mx[0] == 147.3:     #checking that peak was on 147.3 MHz
                if mx[1] > (-15):  #checking dBm of signal
                    try:
                        while proc.poll() is None:
                            proc.terminate()
                    except:
                        print("Warning lights not on. Turning them on.")
                    finally:
                        print(mx[1])
                        proc = subprocess.Popen([sys.executable,'/home/pi/scripts/warning_lights.py'])
                        procs.append(proc)
    except:
        restart()

解决方法

当您调到 147.3MHz 时,您从 SDR 中得到的不是输入端出现的实际无线电信号。 SDR 将射频信号的频率降低到更容易处理和数字化的较低频率。结果,以 147.3MHz 为中心的原始信号部分向下移动到 0Hz,进入所谓的“基带”。特定带宽(在您的情况下为 2.4MHz)之外的所有内容都会被过滤掉。因此,例如,如果在 148.3MHz 处有一个纯正弦信号,这将在您的 SDR 输出中显示为 1MHz 正弦信号。考虑一个频谱图来形象化这个非常有帮助: Wikipedia article on baseband

因此,如果有一个以 147.3MHz 为中心的无线电信号,您将不会在 SDR 的输出中看到 147.3MHz,而是在 0Hz(由于 SDR 电路的频率不是完全准确)。正如您提到的,这应该很容易使用 scipy 进行过滤。

还有另一个问题可能是个问题。大多数 SDR 在它们被调谐到的频率上产生一个小的频率峰值(称为“DC 尖峰”)。在我的 RTL-SDR 中,我发现增益很低时就是这种情况。解决此问题的方法是调谐到您感兴趣的信号带宽之外的频率(例如 147.5MHz 可以工作),然后在您的处理过程中补偿这种变化。

因此,应该起作用的是:

# configure SDR device and settings
sdr = RtlSdr()
offset_freq = 200e3         # Hz
sdr.sample_rate = 2.4e6     # Hz
sdr.center_freq = 147.3e6 - offset_freq   # Hz
sdr.gain = 'auto'           # Possible values are 0.0 0.9 1.4 2.7 3.7 7.7 8.7 12.5 14.4 15.7 16.6 19.7 20.7 22.9 25.4 28.0 29.7 32.8 33.8 36.4 37.2 38.6 40.2 42.1 43.4 43.9 44.5 48.0 49.6 
num_samples = 1024*1024
procs = []


while True:
    try:
        samples = sdr.read_samples(num_samples)
        power,psd_freq = psd(samples,NFFT=1024,Fs=sdr.sample_rate/1e6,Fc=sdr.center_freq/1e6)
        power_db = 10*np.log10(power)

        maxima,minima = peakdetect.peakdetect(power_db,psd_freq,delta=1)

        for mx in maxima:
            if mx[0] == offset_freq:     #checking that peak was on 147.3 MHz
                if mx[1] > (-15):  #checking dBm of signal
                    try:
                        while proc.poll() is None:
                            proc.terminate()
                    except:
                        print("Warning lights not on. Turning them on.")
                    finally:
                        print(mx[1])
                        proc = subprocess.Popen([sys.executable,'/home/pi/scripts/warning_lights.py'])
                        procs.append(proc)
    except:
        restart()

这在图像中没有说明,但您也可以从低于载波的任何频率获得信号中的负频率。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?