RPI OP25 RLT-SDR multi_rx.py simple FM test

daneast

Newbie
Premium Subscriber
Joined
Sep 2, 2015
Messages
2
I'm trying to set up the most basic ability to receive FM on an RTL-SDR dongle on an Raspberry Pi 4.

I can use SDR++ fine on the Pi, although the calibration is off by a bit. I am taking that offset into consideration in my testing.

What I'm trying to do at this point is transmit on 2m FM (I'm an amateur radio operator) and hear this on my Pi through the headphone jack. This should be the most basic possible configuration. I'm using multi_rx.py because I believe I need it for analog FM, and for multiple channel support?

I am not getting a PLL lock, and it's not clear if that is the issue or not. Is this a valid setup to receive FM at 147.442800 MHz and play it through the headphone output?

JavaScript:
{
    "channels": [
        {
            "name": "voice channel",
            "device": "sdr0",
            "trunking_sysname": "test",
            "destination": "udp://192.168.1.55:23456",
            "frequency": 147442800,
            "enable_analog": "on",
            "nbfm_deviation": 4000,
            "nbfm_squelch": -60,
            "demod_type": "cqpsk",
            "filter_type": "widepulse",
            "excess_bw": 0.2,
            "if_rate": 24000,
            "symbol_rate": 4800,
            "plot": ""
        }
    ],
    "devices": [
        {
            "args": "rtl=0",
            "gains": "LNA:39",
            "gain_mode": false,
            "frequency": 147442800,
            "name": "sdr0",
            "offset": 0,
            "ppm": 0,
            "rate": 1000000,
            "usable_bw_pct": 0.85,
            "tunable": true
        }
    ],
    "trunking": {
        "module": "tk_p25.py",
        "chans": [
            {
                "nac": "0x0",
                "sysname": "test",
                "control_channel_list": "147.4428",
                "whitelist": "",
                "blacklist": "",
                "tgid_tags_file": "trunk-tags.tsv",
                "rid_tags_file": "trunk-rids.tsv",
                "tdma_cc": false,
                "crypt_behavior": 2
            }
        ]
    },
    "audio": {
        "module": "sockaudio.py",
        "instances": [
            {
                "instance_name": "audio1",
                "device_name": "default",
                "udp_port": 23456,
                "audio_gain": 1.0,
                "number_channels": 1
            }
        ]
    },
    "terminal": {
        "module": "terminal.py",
        "terminal_type": "curses",
        "#terminal_type": "http:127.0.0.1:8080",
        "curses_plot_interval": 0.1,
        "http_plot_interval": 1.0,
        "http_plot_directory": "../www/images",
        "tuning_step_large": 1200,
        "tuning_step_small": 100
    }
}

Code:
Using Python /usr/bin/python3
Starting OP25 (pid = 41953)
Configuring audio instance #0 [audio1]
using ALSA sound system
audio device: default
Listening on 127.0.0.1:23456
01/18/24 16:24:45.810971 [test] Initializing P25 system
01/18/24 16:24:45.811124 [test] reading system tgid_tags_file: trunk-tags.tsv
read_tags_file: exception [Errno 2] No such file or directory: 'trunk-tags.tsv'
01/18/24 16:24:45.811292 [test] reading system rid_tags_file: trunk-rids.tsv
read_rid_file: exception [Errno 2] No such file or directory: 'trunk-rids.tsv'
Enabled trunking module: tk_p25.py
device: {'args': 'rtl=0', 'gains': 'LNA:39', 'gain_mode': False, 'frequency': 147442800, 'name': 'sdr0', 'offset': 0, 'ppm': 0, 'rate': 1000000, 'usable_bw_pct': 0.85, 'tunable': True}
Device name: "sdr0", osmosdr args: "rtl=0"
gr-osmosdr 0.2.0.0 (0.2.0) gnuradio 3.10.5.1
built-in source types: file fcd rtl rtl_tcp uhd hackrf bladerf rfspace airspy airspyhf soapy redpitaya freesrp xtrx
Using device #0 Generic RTL2832U SN: 77771111153705700
Found Rafael Micro R820T tuner
[R82XX] PLL not locked!
gr-osmosdr driver gain_mode: False
Exact sample rate is: 1000000.026491 Hz
[R82XX] PLL not locked!
channel (dev sdr0): {'name': 'voice channel', 'device': 'sdr0', 'trunking_sysname': 'test', 'destination': 'udp://192.168.1.55:23456', 'frequency': 147442800, 'enable_analog': 'on', 'nbfm_deviation': 4000, 'nbfm_squelch': -100, 'demod_type': 'cqpsk', 'filter_type': 'widepulse', 'excess_bw': 0.2, 'if_rate': 24000, 'symbol_rate': 4800, 'plot': ''}
demodulator: xlator if_rate=24000, input_rate=1000000, decim=41, taps=197, resampled_rate=24390, sps=5
op25_audio::open_socket(): enabled udp host(192.168.1.55), wireshark(23456), audio(23456)
01/18/24 16:24:46.819224 [0] Enabling nbfm analog audio
op25_audio::open_socket(): enabled udp host(192.168.1.55), wireshark(23456), audio(23456)
01/18/24 16:24:46.833825 [0] Initializing P25 receiver: voice channel
01/18/24 16:24:46.834014 [0] metadata updates not enabled
Flowgraph complete. Exiting
 

wgbecks

Active Member
Joined
Jan 17, 2005
Messages
922
Location
NE Wisconsin
You would not enable the trunking logic when configuring multi_rx.py as a simple FM receiver. Keep in mind that it will be necessary
to keep the LNA gain very low in assuming the receiver will be operating in close proximity to the transmitter.

Try the example FM Receiver (JSON) shown below. You may want to temporarily enable the fft and mixer plots that to aid in setting
LNA gain appropriately to avoid RF overload, and then to observe the mixer plot for use in correcting the PPM as required to bring
the SDR on frequency.

Finally, the squelch threshold value required to mute the audio output in the absence of an input signal will vary in accordance with
the SDR's LNA gain setting, and in accordance with the actual RF signal level received.


Example FM Receiver

JSON:
{
    "channels": [
        {
             "name": "Two-Meter Receiver",
             "device": "rtl_sdr",
             "demod_type": "fsk4",
             "cqpsk_tracking": false,
             "tracking_threshold": 120,
             "tracking_limit": 2400,
             "tracking_feedback": 0.75,
             "destination": "udp://127.0.0.1:23456",
             "enable_analog": "on",
             "nbfm_deviation": 5000,
             "nbfm_squelch_threshold": -60,
             "nbfm_squelch_gain": 0.0050,
             "excess_bw": 0.2,
             "filter_type": "rc",
             "frequency": 147442800,
             "if_rate": 24000,
             "plot": "",
             "raw_output": "",
             "raw_input": "",
             "raw_seek": 0,
            "symbol_rate": 4800
         }
    ],
    "devices": [
        {
            "args": "rtl=0",
            "frequency": 147442800,
            "gains": "lna:10",
            "gain_mode": false,
            "name": "rtl_sdr",
            "offset": 0,
            "ppm": 0.0,
            "rate": 1000000,
            "usable_bw_pct": 0.85,
            "tunable": false
        }
    ],
    "trunking": {
        "module": "",
        "chans": [
            {
                "lcn": 1,
                "frequency": 111222222,
                "cc": 0
            },
            {
                "lcn": 2,
                "frequency": 111333333,
                "cc": 0
            }
        ]
    },
    "metadata": {
        "module": "",
        "streams": [
            {
                "stream_name": "stream_0",
                "meta_format_idle": "[idle]",
                "meta_format_tgid": "[%TGID%]",
                "meta_format_tag":  "[%TGID%] %TAG%",
                "meta_format_rid":  "@ [%RID%]",
                "meta_format_rtag": "@ [%RID%] %RTAG%",
                "icecastServerAddress": "your_stream_host_and_port",
                "icecastMountpoint": "your_mountpoint_name",
                "icecastPass": "your_password",
                "icecastMountExt": ".xspf",
                "delay": 0.0
            }
        ]
    },
    "audio": {
        "module": "sockaudio.py",
        "instances": [
            {
                "instance_name": "audio0",
                "device_name": "default",
                "udp_port": 23456,
                "audio_gain": 1.0,
                "number_channels": 1
            }
        ]
    },
    "terminal": {
        "module": "terminal.py",
        "terminal_type": "curses",
        "#terminal_type": "http:127.0.0.1:8080",
        "terminal_timeout": 5.0,
        "default_channel": "p25",
        "curses_plot_interval": 0.2,
        "http_plot_interval": 1.0,
        "http_plot_directory": "../www/images",
        "tuning_step_large": 1200,
        "tuning_step_small": 100
    }
}
 
Last edited:
Top