Auch das geht Alfred mit dem Raspberry oder einem anderen Linux. Du brauchst nur ein Programm bzw. den Signalpfad für mehrere Sender in einem grafischen Programm zeichnen und übersetzen lassen. Schau mal hier.
Die Programmierumgebung macht aus diesem Signallaufplan bereits ein fertiges Programm.
Code:
#!/usr/bin/env python
##################################################
# Gnuradio Python Flow Graph
# Title: Multiple stations FM transmitter
# Author: Mathias Coinchon
# Generated: Sat Jan 2 21:19:02 2010
##################################################
from gnuradio import blks2
from gnuradio import gr
from gnuradio.eng_option import eng_option
from gnuradio.gr import firdes
from gnuradio.wxgui import fftsink2
from gnuradio.wxgui import forms
from grc_gnuradio import usrp as grc_usrp
from grc_gnuradio import wxgui as grc_wxgui
from optparse import OptionParser
import wx
class multistations_FM_TX(grc_wxgui.top_block_gui):
def __init__(self):
grc_wxgui.top_block_gui.__init__(self, title="Multiple stations FM transmitter")
##################################################
# Variables
##################################################
self.samp_rate = samp_rate = 32000
self.quad_rate = quad_rate = 1280000
self.carrier2_frequency = carrier2_frequency = 300000
self.carrier1_frequency = carrier1_frequency = -300000
self.FM_frequency = FM_frequency = 107600000
##################################################
# Controls
##################################################
_carrier2_frequency_sizer = wx.BoxSizer(wx.VERTICAL)
self._carrier2_frequency_text_box = forms.text_box(
parent=self.GetWin(),
sizer=_carrier2_frequency_sizer,
value=self.carrier2_frequency,
callback=self.set_carrier2_frequency,
label="Carrier 2 Frequency",
converter=forms.float_converter(),
proportion=0,
)
self._carrier2_frequency_slider = forms.slider(
parent=self.GetWin(),
sizer=_carrier2_frequency_sizer,
value=self.carrier2_frequency,
callback=self.set_carrier2_frequency,
minimum=-500000,
maximum=500000,
num_steps=100,
style=wx.SL_HORIZONTAL,
cast=float,
proportion=1,
)
self.Add(_carrier2_frequency_sizer)
_carrier1_frequency_sizer = wx.BoxSizer(wx.VERTICAL)
self._carrier1_frequency_text_box = forms.text_box(
parent=self.GetWin(),
sizer=_carrier1_frequency_sizer,
value=self.carrier1_frequency,
callback=self.set_carrier1_frequency,
label="Carrier 1 Frequency",
converter=forms.float_converter(),
proportion=0,
)
self._carrier1_frequency_slider = forms.slider(
parent=self.GetWin(),
sizer=_carrier1_frequency_sizer,
value=self.carrier1_frequency,
callback=self.set_carrier1_frequency,
minimum=-500000,
maximum=500000,
num_steps=100,
style=wx.SL_HORIZONTAL,
cast=float,
proportion=1,
)
self.Add(_carrier1_frequency_sizer)
_FM_frequency_sizer = wx.BoxSizer(wx.VERTICAL)
self._FM_frequency_text_box = forms.text_box(
parent=self.GetWin(),
sizer=_FM_frequency_sizer,
value=self.FM_frequency,
callback=self.set_FM_frequency,
label="Central FM frequency",
converter=forms.float_converter(),
proportion=0,
)
self._FM_frequency_slider = forms.slider(
parent=self.GetWin(),
sizer=_FM_frequency_sizer,
value=self.FM_frequency,
callback=self.set_FM_frequency,
minimum=87500000,
maximum=108000000,
num_steps=205,
style=wx.SL_HORIZONTAL,
cast=float,
proportion=1,
)
self.Add(_FM_frequency_sizer)
##################################################
# Blocks
##################################################
self.blks2_rational_resampler_xxx_0 = blks2.rational_resampler_ccc(
interpolation=4,
decimation=1,
taps=None,
fractional_bw=None,
)
self.blks2_rational_resampler_xxx_1 = blks2.rational_resampler_ccc(
interpolation=4,
decimation=1,
taps=None,
fractional_bw=None,
)
self.blks2_rational_resampler_xxx_2 = blks2.rational_resampler_ccc(
interpolation=4,
decimation=1,
taps=None,
fractional_bw=None,
)
self.blks2_wfm_tx_0 = blks2.wfm_tx(
audio_rate=samp_rate,
quad_rate=320000,
tau=50e-6,
max_dev=75e3,
)
self.blks2_wfm_tx_1 = blks2.wfm_tx(
audio_rate=samp_rate,
quad_rate=320000,
tau=75e-6,
max_dev=75e3,
)
self.blks2_wfm_tx_2 = blks2.wfm_tx(
audio_rate=samp_rate,
quad_rate=320000,
tau=75e-6,
max_dev=75e3,
)
self.gr_add_xx_0 = gr.add_vcc(1)
self.gr_file_source_0 = gr.file_source(gr.sizeof_short*1, "/home/mc/FM_demo/lemixx.fifo", True)
self.gr_file_source_1 = gr.file_source(gr.sizeof_short*1, "/home/mc/FM_demo/banane.fifo", True)
self.gr_file_source_2 = gr.file_source(gr.sizeof_short*1, "/home/mc/FM_demo/stream_32k.fifo", True)
self.gr_multiply_const_vxx_0 = gr.multiply_const_vcc((5000, ))
self.gr_multiply_const_vxx_1 = gr.multiply_const_vff((30e-6, ))
self.gr_multiply_const_vxx_1_0 = gr.multiply_const_vff((30e-6, ))
self.gr_multiply_const_vxx_1_1 = gr.multiply_const_vff((30e-6, ))
self.gr_multiply_xx_0 = gr.multiply_vcc(1)
self.gr_multiply_xx_1 = gr.multiply_vcc(1)
self.gr_short_to_float_0 = gr.short_to_float()
self.gr_short_to_float_0_0 = gr.short_to_float()
self.gr_short_to_float_0_0_0 = gr.short_to_float()
self.gr_sig_source_x_0 = gr.sig_source_c(quad_rate, gr.GR_COS_WAVE, carrier1_frequency, 1, 0)
self.gr_sig_source_x_1 = gr.sig_source_c(quad_rate, gr.GR_COS_WAVE, carrier2_frequency, 1, 0)
self.usrp_simple_sink_x_0 = grc_usrp.simple_sink_c(which=0, side="B")
self.usrp_simple_sink_x_0.set_interp_rate(100)
self.usrp_simple_sink_x_0.set_frequency(-FM_frequency, verbose=True)
self.usrp_simple_sink_x_0.set_gain(0)
self.wxgui_fftsink2_0 = fftsink2.fft_sink_c(
self.GetWin(),
baseband_freq=0,
y_per_div=10,
y_divs=10,
ref_level=50,
sample_rate=quad_rate,
fft_size=1024,
fft_rate=30,
average=False,
avg_alpha=None,
title="FFT Plot",
peak_hold=False,
)
self.Add(self.wxgui_fftsink2_0.win)
##################################################
# Connections
##################################################
self.connect((self.gr_multiply_const_vxx_0, 0), (self.usrp_simple_sink_x_0, 0))
self.connect((self.gr_multiply_xx_0, 0), (self.gr_add_xx_0, 0))
self.connect((self.gr_add_xx_0, 0), (self.gr_multiply_const_vxx_0, 0))
self.connect((self.gr_add_xx_0, 0), (self.wxgui_fftsink2_0, 0))
self.connect((self.blks2_rational_resampler_xxx_0, 0), (self.gr_add_xx_0, 1))
self.connect((self.gr_multiply_xx_1, 0), (self.gr_add_xx_0, 2))
self.connect((self.gr_sig_source_x_1, 0), (self.gr_multiply_xx_1, 1))
self.connect((self.gr_sig_source_x_0, 0), (self.gr_multiply_xx_0, 0))
self.connect((self.blks2_rational_resampler_xxx_2, 0), (self.gr_multiply_xx_0, 1))
self.connect((self.blks2_rational_resampler_xxx_1, 0), (self.gr_multiply_xx_1, 0))
self.connect((self.blks2_wfm_tx_0, 0), (self.blks2_rational_resampler_xxx_2, 0))
self.connect((self.blks2_wfm_tx_2, 0), (self.blks2_rational_resampler_xxx_0, 0))
self.connect((self.blks2_wfm_tx_1, 0), (self.blks2_rational_resampler_xxx_1, 0))
self.connect((self.gr_short_to_float_0, 0), (self.gr_multiply_const_vxx_1, 0))
self.connect((self.gr_file_source_1, 0), (self.gr_short_to_float_0, 0))
self.connect((self.gr_file_source_2, 0), (self.gr_short_to_float_0_0, 0))
self.connect((self.gr_file_source_0, 0), (self.gr_short_to_float_0_0_0, 0))
self.connect((self.gr_short_to_float_0_0, 0), (self.gr_multiply_const_vxx_1_0, 0))
self.connect((self.gr_short_to_float_0_0_0, 0), (self.gr_multiply_const_vxx_1_1, 0))
self.connect((self.gr_multiply_const_vxx_1, 0), (self.blks2_wfm_tx_1, 0))
self.connect((self.gr_multiply_const_vxx_1_0, 0), (self.blks2_wfm_tx_2, 0))
self.connect((self.gr_multiply_const_vxx_1_1, 0), (self.blks2_wfm_tx_0, 0))
def set_samp_rate(self, samp_rate):
self.samp_rate = samp_rate
def set_quad_rate(self, quad_rate):
self.quad_rate = quad_rate
self.wxgui_fftsink2_0.set_sample_rate(self.quad_rate)
self.gr_sig_source_x_0.set_sampling_freq(self.quad_rate)
self.gr_sig_source_x_1.set_sampling_freq(self.quad_rate)
def set_carrier2_frequency(self, carrier2_frequency):
self.carrier2_frequency = carrier2_frequency
self._carrier2_frequency_slider.set_value(self.carrier2_frequency)
self._carrier2_frequency_text_box.set_value(self.carrier2_frequency)
self.gr_sig_source_x_1.set_frequency(self.carrier2_frequency)
def set_carrier1_frequency(self, carrier1_frequency):
self.carrier1_frequency = carrier1_frequency
self._carrier1_frequency_slider.set_value(self.carrier1_frequency)
self._carrier1_frequency_text_box.set_value(self.carrier1_frequency)
self.gr_sig_source_x_0.set_frequency(self.carrier1_frequency)
def set_FM_frequency(self, FM_frequency):
self.FM_frequency = FM_frequency
self._FM_frequency_slider.set_value(self.FM_frequency)
self._FM_frequency_text_box.set_value(self.FM_frequency)
self.usrp_simple_sink_x_0.set_frequency(-self.FM_frequency)
if __name__ == '__main__':
parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
(options, args) = parser.parse_args()
tb = multistations_FM_TX()
tb.Run(True)
Startet man das Programm werden die drei Modulationsquellen ausgelesen, die Sender erzeugt und dann zu einem schnellen Analog Digital Wandler gesendet der diese drei UKW-Sender ausgibt. Man kann auch 5 oder 10 Stationen anlegen und ausgeben lassen. Experimentiere jetzt schon ein paar Wochen damit und es ist einfach genial diese Digitale Signalverarbeitung am PC.
Otto.