├── Drivers-Windows ├── README.txt ├── rtl-sdr-32bit-20210307.zip ├── rtl-sdr-64bit-20210307.zip └── rtl-sdr-64bit-20210307 │ ├── librtlsdr.dll │ ├── libusb-1.0.dll │ └── libwinpthread-1.dll ├── requirements.txt ├── test1.py ├── test2_plot.py ├── test4_spectrum_FM_station.py ├── test3_stream_plot.py ├── test5_find_powerfull_FM_station.py ├── .gitignore ├── test6_FM_radio_receiver.py ├── test7_FM_custom_receiver.py └── README.md /Drivers-Windows/README.txt: -------------------------------------------------------------------------------- 1 | Downlaod Page: http://ftp.osmocom.org/binaries/windows/rtl-sdr/ -------------------------------------------------------------------------------- /Drivers-Windows/rtl-sdr-32bit-20210307.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daskals/RTL-SDR-Python-Signal-Processing/HEAD/Drivers-Windows/rtl-sdr-32bit-20210307.zip -------------------------------------------------------------------------------- /Drivers-Windows/rtl-sdr-64bit-20210307.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daskals/RTL-SDR-Python-Signal-Processing/HEAD/Drivers-Windows/rtl-sdr-64bit-20210307.zip -------------------------------------------------------------------------------- /Drivers-Windows/rtl-sdr-64bit-20210307/librtlsdr.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daskals/RTL-SDR-Python-Signal-Processing/HEAD/Drivers-Windows/rtl-sdr-64bit-20210307/librtlsdr.dll -------------------------------------------------------------------------------- /Drivers-Windows/rtl-sdr-64bit-20210307/libusb-1.0.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daskals/RTL-SDR-Python-Signal-Processing/HEAD/Drivers-Windows/rtl-sdr-64bit-20210307/libusb-1.0.dll -------------------------------------------------------------------------------- /Drivers-Windows/rtl-sdr-64bit-20210307/libwinpthread-1.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daskals/RTL-SDR-Python-Signal-Processing/HEAD/Drivers-Windows/rtl-sdr-64bit-20210307/libwinpthread-1.dll -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | bottle==0.12.8 2 | cycler==0.10.0 3 | kiwisolver==1.3.1 4 | matplotlib==3.3.4 5 | numpy==1.20.1 6 | Pillow==8.1.2 7 | playsound==1.2.2 8 | pylab-sdk==1.3.2 9 | pyparsing==2.4.7 10 | pyrtlsdr==0.2.92 11 | python-dateutil==2.8.1 12 | scipy==1.6.1 13 | six==1.15.0 14 | -------------------------------------------------------------------------------- /test1.py: -------------------------------------------------------------------------------- 1 | ####################################################### 2 | # Spiros Daskalakis # 3 | # Last Revision: 13/03/2021 # 4 | # Python Version: 3.9 # 5 | # Email: Daskalakispiros@gmail.com # 6 | ####################################################### 7 | from rtlsdr import RtlSdr 8 | 9 | sdr = RtlSdr() 10 | 11 | # configure RTL sdr device 12 | sdr.sample_rate = 2.048e6 # Hz 13 | sdr.center_freq = 100e6 # Hz 14 | sdr.freq_correction = 60 # PPM 15 | sdr.gain = 'auto' 16 | 17 | print(sdr.read_samples(512)) -------------------------------------------------------------------------------- /test2_plot.py: -------------------------------------------------------------------------------- 1 | ####################################################### 2 | # Spiros Daskalakis # 3 | # Last Revision: 13/03/2021 # 4 | # Python Version: 3.9 # 5 | # Email: Daskalakispiros@gmail.com # 6 | ####################################################### 7 | 8 | from rtlsdr import RtlSdr 9 | from matplotlib import pyplot as plt 10 | 11 | sdr = RtlSdr() 12 | 13 | # configure device 14 | sdr.sample_rate = 2.048e6 # Hz 15 | sdr.center_freq = 98e6 # Hz 16 | sdr.freq_correction = 60 # PPM 17 | sdr.gain = 'auto' 18 | samples = sdr.read_samples(256 * 1024) 19 | sdr.close() 20 | 21 | # use matplotlib to estimate and plot the PSD 22 | plt.psd(samples, NFFT=1024, Fs=sdr.sample_rate / 1e6, Fc=sdr.center_freq / 1e6) 23 | plt.xlabel('Frequency (MHz)') 24 | plt.ylabel('Relative power (dB)') 25 | plt.show() 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /test4_spectrum_FM_station.py: -------------------------------------------------------------------------------- 1 | ####################################################### 2 | # Spiros Daskalakis # 3 | # Last Revision: 09/03/2021 # 4 | # Python Version: 3.9 # 5 | # Email: Daskalakispiros@gmail.com # 6 | ####################################################### 7 | 8 | import asyncio 9 | from rtlsdr import RtlSdr 10 | from matplotlib import pyplot as plt 11 | 12 | 13 | async def streaming(): 14 | sdr = RtlSdr() 15 | # configure device 16 | Fs = 2.4e6 # Hz 17 | sdr.sample_rate = Fs # Hz 18 | sdr.center_freq = 98e6 # Hz 19 | sdr.freq_correction = 60 # PPM 20 | sdr.gain = 'auto' 21 | # Sampling for 1 sec 22 | t_sampling = 1 23 | N_samples = round(Fs * t_sampling) 24 | samples = sdr.read_samples(N_samples) 25 | 26 | fig = plt.figure(1) 27 | plt.xlabel('Frequency (MHz)') 28 | plt.ylabel('Relative power (dB)') 29 | fig.show() 30 | 31 | async for samples in sdr.stream(): 32 | 33 | plt.psd(samples, NFFT=1024, Fs=sdr.sample_rate / 1e6, Fc=sdr.center_freq / 1e6) 34 | plt.title("Dynamic Plot") 35 | plt.draw() 36 | plt.pause(0.1) 37 | fig.clear() 38 | 39 | # to stop streaming: 40 | await sdr.stop() 41 | 42 | # done 43 | sdr.close() 44 | 45 | 46 | loop = asyncio.get_event_loop() 47 | loop.run_until_complete(streaming()) 48 | -------------------------------------------------------------------------------- /test3_stream_plot.py: -------------------------------------------------------------------------------- 1 | ####################################################### 2 | # Spiros Daskalakis # 3 | # Last Revision: 13/03/2021 # 4 | # Python Version: 3.9 # 5 | # Email: Daskalakispiros@gmail.com # 6 | ####################################################### 7 | 8 | import asyncio 9 | from rtlsdr import RtlSdr 10 | from matplotlib import pyplot as plt 11 | 12 | async def streaming(): 13 | sdr = RtlSdr() 14 | # configure device 15 | Fs = 2.4e6 # Hz 16 | sdr.sample_rate = Fs # Hz 17 | sdr.center_freq = 98e6 # Hz 18 | sdr.freq_correction = 60 # PPM 19 | sdr.gain = 'auto' 20 | 21 | t_sampling = 1 # Sampling 22 | N_samples = round(Fs * t_sampling) 23 | 24 | samples = sdr.read_samples(N_samples) 25 | 26 | fig = plt.figure(1) 27 | 28 | plt.xlabel('Frequency (MHz)') 29 | plt.ylabel('Relative power (dB)') 30 | fig.show() 31 | 32 | async for samples in sdr.stream(): 33 | # do something with samples 34 | plt.psd(samples, NFFT=1024, Fs=sdr.sample_rate / 1e6, Fc=sdr.center_freq / 1e6) 35 | plt.title("Dynamic Plot") 36 | plt.draw() 37 | plt.pause(0.1) 38 | fig.clear() 39 | 40 | # to stop streaming: 41 | await sdr.stop() 42 | # done 43 | sdr.close() 44 | 45 | 46 | loop = asyncio.get_event_loop() 47 | loop.run_until_complete(streaming()) 48 | -------------------------------------------------------------------------------- /test5_find_powerfull_FM_station.py: -------------------------------------------------------------------------------- 1 | ####################################################### 2 | # Spiros Daskalakis # 3 | # Last Revision: 09/03/2021 # 4 | # Python Version: 3.9 # 5 | # Email: Daskalakispiros@gmail.com # 6 | ####################################################### 7 | 8 | from rtlsdr import RtlSdr 9 | from matplotlib import pyplot as plt 10 | import numpy as np 11 | 12 | 13 | def find_powerfull_FM(): 14 | sdr = RtlSdr() 15 | # configure device 16 | Fs = 2e6 # Hz 17 | sdr.sample_rate = Fs # Hz 18 | sdr.freq_correction = 60 # PPM 19 | sdr.gain = 'auto' 20 | 21 | FM_band_min = 87.5 22 | FM_band_max = 109 23 | 24 | powe = np.ndarray(0) 25 | freq = np.ndarray(0) 26 | 27 | t_sampling = 0.1 # Sampling for 100 ms 28 | N_samples = round(Fs * t_sampling) 29 | 30 | for i in np.arange(FM_band_min, FM_band_max, Fs / 1e6): 31 | sdr.center_freq = i * 1e6 # Hz 32 | counter = 0 33 | prev_int = 0 34 | while 1: 35 | counter = counter + 1 36 | samples = sdr.read_samples(N_samples) 37 | ################################################################################### 38 | power, psd_freq = plt.psd(samples, NFFT=1024, Fs=sdr.sample_rate / 1e6, Fc=sdr.center_freq / 1e6) 39 | ##################################################################################### 40 | ind_pow = np.argmax(power) 41 | freq_ind = round(psd_freq[ind_pow], 1) 42 | if freq_ind == prev_int and counter >= 3: 43 | powe = np.append(powe, ind_pow) 44 | freq = np.append(freq, freq_ind) 45 | break 46 | prev_int = freq_ind 47 | # done 48 | sdr.close() 49 | max_fm_station_power = np.argmax(powe) 50 | max_fm_station_freq = freq[max_fm_station_power] 51 | return max_fm_station_freq 52 | 53 | print('FM with max Power is (MHz):', find_powerfull_FM()) 54 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Editors 2 | .vscode/ 3 | .idea/ 4 | 5 | # Vagrant 6 | .vagrant/ 7 | 8 | # Mac/OSX 9 | .DS_Store 10 | 11 | # Windows 12 | Thumbs.db 13 | 14 | # Source for the following rules: https://raw.githubusercontent.com/github/gitignore/master/Python.gitignore 15 | # Byte-compiled / optimized / DLL files 16 | __pycache__/ 17 | *.py[cod] 18 | *$py.class 19 | 20 | # C extensions 21 | *.so 22 | 23 | # Distribution / packaging 24 | .Python 25 | build/ 26 | develop-eggs/ 27 | dist/ 28 | downloads/ 29 | eggs/ 30 | .eggs/ 31 | lib/ 32 | lib64/ 33 | parts/ 34 | sdist/ 35 | var/ 36 | wheels/ 37 | *.egg-info/ 38 | .installed.cfg 39 | *.egg 40 | MANIFEST 41 | 42 | # PyInstaller 43 | # Usually these files are written by a python script from a template 44 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 45 | *.manifest 46 | *.spec 47 | 48 | # Installer logs 49 | pip-log.txt 50 | pip-delete-this-directory.txt 51 | 52 | # Unit test / coverage reports 53 | htmlcov/ 54 | .tox/ 55 | .nox/ 56 | .coverage 57 | .coverage.* 58 | .cache 59 | nosetests.xml 60 | coverage.xml 61 | *.cover 62 | .hypothesis/ 63 | .pytest_cache/ 64 | 65 | # Translations 66 | *.mo 67 | *.pot 68 | 69 | # Django stuff: 70 | *.log 71 | local_settings.py 72 | db.sqlite3 73 | 74 | # Flask stuff: 75 | instance/ 76 | .webassets-cache 77 | 78 | # Scrapy stuff: 79 | .scrapy 80 | 81 | # Sphinx documentation 82 | docs/_build/ 83 | 84 | # PyBuilder 85 | target/ 86 | 87 | # Jupyter Notebook 88 | .ipynb_checkpoints 89 | 90 | # IPython 91 | profile_default/ 92 | ipython_config.py 93 | 94 | # pyenv 95 | .python-version 96 | 97 | # celery beat schedule file 98 | celerybeat-schedule 99 | 100 | # SageMath parsed files 101 | *.sage.py 102 | 103 | # Environments 104 | .env 105 | .venv 106 | env/ 107 | venv/ 108 | ENV/ 109 | env.bak/ 110 | venv.bak/ 111 | 112 | # Spyder project settings 113 | .spyderproject 114 | .spyproject 115 | 116 | # Rope project settings 117 | .ropeproject 118 | 119 | # mkdocs documentation 120 | /site 121 | 122 | # mypy 123 | .mypy_cache/ 124 | .dmypy.json 125 | dmypy.json -------------------------------------------------------------------------------- /test6_FM_radio_receiver.py: -------------------------------------------------------------------------------- 1 | ####################################################### 2 | # Spiros Daskalakis # 3 | # Last Revision: 09/03/2021 # 4 | # Python Version: 3.9 # 5 | # Email: Daskalakispiros@gmail.com # 6 | ####################################################### 7 | # https://witestlab.poly.edu/blog/capture-and-decode-fm-radio/ 8 | import asyncio 9 | import numpy as np 10 | from rtlsdr import RtlSdr 11 | from matplotlib import pyplot as plt 12 | import scipy.signal as signal 13 | 14 | 15 | # see http://stackoverflow.com/a/3054314/3524528 16 | 17 | 18 | async def streaming(): 19 | sdr = RtlSdr() 20 | F_station = 95.8e6 # Pick a radio station 21 | F_offset = 250000 # Offset to capture at 22 | # We capture at an offset to avoid DC spike 23 | Fc = F_station # Capture center frequency 24 | Fs = int(1140000) # Sample rate 25 | N = int(8192000) # Samples to capture 26 | # configure device 27 | sdr.sample_rate = Fs # Hz 28 | sdr.center_freq = Fc # Hz 29 | sdr.gain = 'auto' 30 | 31 | fig = plt.figure(1) 32 | fig.show() 33 | 34 | # Read samples 35 | samples = sdr.read_samples(N) 36 | 37 | async for samples in sdr.stream(): 38 | # Convert samples to a numpy array 39 | x1 = np.array(samples).astype("complex64") 40 | 41 | # To mix the data down, generate a digital complex exponential 42 | # (with the same length as x1) with phase -F_offset/Fs 43 | fc1 = np.exp(-1.0j * 2.0 * np.pi * F_offset / Fs * np.arange(len(x1))) 44 | # Now, just multiply x1 and the digital complex expontential 45 | x2 = x1 * fc1 46 | 47 | # An FM broadcast signal has a bandwidth of 200 kHz 48 | f_bw = 200000 49 | n_taps = 64 50 | # Use Remez algorithm to design filter coefficients 51 | lpf = signal.remez(n_taps, [0, f_bw, f_bw + (Fs / 2 - f_bw) / 4, Fs / 2], [1, 0], Hz=Fs) 52 | x3 = signal.lfilter(lpf, 1.0, x2) 53 | 54 | dec_rate = int(Fs / f_bw) 55 | x4 = x3[0::dec_rate] 56 | # Calculate the new sampling rate 57 | Fs_y = Fs / dec_rate 58 | 59 | # Polar discriminator 60 | y5 = x4[1:] * np.conj(x4[:-1]) 61 | x5 = np.angle(y5) 62 | 63 | plt.psd(x5, NFFT=2048, Fs=Fs_y, color="blue") 64 | plt.title("x5") 65 | plt.axvspan(0, 15000, color="red", alpha=0.2) 66 | plt.axvspan(19000 - 500, 19000 + 500, color="green", alpha=0.4) 67 | plt.axvspan(19000 * 2 - 15000, 19000 * 2 + 15000, color="orange", alpha=0.2) 68 | plt.axvspan(19000 * 3 - 1500, 19000 * 3 + 1500, color="blue", alpha=0.2) 69 | plt.ticklabel_format(style='plain', axis='y') 70 | # plt.savefig("x5_psd.pdf", bbox_inches='tight', pad_inches=0.5) 71 | plt.draw() 72 | plt.pause(0.1) 73 | fig.clear() 74 | 75 | # The de-emphasis filter 76 | # Given a signal 'x5' (in a numpy array) with sampling rate Fs_y 77 | d = Fs_y * 75e-6 # Calculate the # of samples to hit the -3dB point 78 | x = np.exp(-1 / d) # Calculate the decay between each sample 79 | b = [1 - x] # Create the filter coefficients 80 | a = [1, -x] 81 | x6 = signal.lfilter(b, a, x5) 82 | 83 | # Find a decimation rate to achieve audio sampling rate between 44-48 kHz 84 | audio_freq = 44100.0 85 | dec_audio = int(Fs_y / audio_freq) 86 | Fs_audio = Fs_y / dec_audio 87 | 88 | x7 = signal.decimate(x6, dec_audio) 89 | 90 | # Scale audio to adjust volume 91 | x7 *= 10000 / np.max(np.abs(x7)) 92 | 93 | # to stop streaming: 94 | await sdr.stop() 95 | 96 | # done 97 | sdr.close() 98 | 99 | 100 | loop = asyncio.get_event_loop() 101 | loop.run_until_complete(streaming()) 102 | -------------------------------------------------------------------------------- /test7_FM_custom_receiver.py: -------------------------------------------------------------------------------- 1 | ####################################################### 2 | # Spiros Daskalakis # 3 | # Last Revision: 13/03/2021 # 4 | # Python Version: 3.9 # 5 | # Email: Daskalakispiros@gmail.com # 6 | ####################################################### 7 | 8 | import asyncio 9 | 10 | import numpy as np 11 | from rtlsdr import RtlSdr 12 | from matplotlib import pyplot as plt 13 | import scipy.signal as sps 14 | 15 | def CFO_pilot_tone(analog_signal, F_s): 16 | x_R_fft = np.fft.fftshift(np.fft.fft(analog_signal)) 17 | LPF = np.zeros(x_R_fft.size) # create 18 | N_F = x_R_fft.size 19 | F_axis = np.arange(-F_s / 2, F_s / 2, F_s / N_F) 20 | LPF[(np.abs(F_axis) >= 15100) & (np.abs(F_axis) <= 23300)] = 1 21 | x_R_filt_fft = x_R_fft * LPF # filter in freq domain 22 | mpos = np.argmax(np.abs(x_R_filt_fft)) 23 | # Shift the signal based on the 19 KHz carrier 24 | DF_est = np.abs(19000 + F_axis[mpos]) 25 | print(DF_est) 26 | if np.abs(F_axis[mpos]) > 19000: 27 | pack = np.exp(-1.0j * 2.0 * np.pi * DF_est / F_s * np.arange(len(analog_signal))) 28 | analog_signal = analog_signal * pack 29 | elif np.abs(F_axis[mpos]) < 19000: 30 | pack = np.exp(+1.0j * 2.0 * np.pi * DF_est / F_s * np.arange(len(analog_signal))) 31 | analog_signal = analog_signal * pack 32 | return analog_signal 33 | 34 | 35 | async def streaming(): 36 | sdr = RtlSdr() 37 | # configure device 38 | # Fs = 2.4e6 # Hz 39 | Fs = 1e6 40 | sdr.sample_rate = Fs # Hz 41 | sdr.center_freq = 95.8e6 # Hz 42 | sdr.freq_correction = 60 # PPM 43 | sdr.gain = 'auto' 44 | # Sampling for 1 sec 45 | t_sampling = 0.1 46 | N_samples = round(Fs * t_sampling) 47 | samples = sdr.read_samples(N_samples) 48 | CFO_corr_en = 0 49 | 50 | fig = plt.figure(1) 51 | plt.xlabel('Frequency (MHz)') 52 | plt.ylabel('Relative power (dB)') 53 | fig.show() 54 | 55 | LEFT = 15000 56 | BW = 8000 57 | F_center = LEFT + BW / 2 58 | 59 | async for samples in sdr.stream(): 60 | 61 | # Convert samples to a numpy array 62 | x1 = np.array(samples).astype("complex64") 63 | 64 | if CFO_corr_en == 1: 65 | analog_signal_packets = CFO_pilot_tone(x1, Fs) 66 | else: 67 | analog_signal_packets = x1 68 | 69 | # To mix the data down, generate a digital complex exponential 70 | # (with the same length as x1) with phase -F_offset/Fs 71 | fc1 = np.exp(-1.0j * 2.0 * np.pi * F_center / Fs * np.arange(len(analog_signal_packets))) 72 | # Now, just multiply x1 and the digital complex exponential 73 | x2 = analog_signal_packets * fc1 74 | 75 | # channelize the signal Method 1 76 | ######################################################################## 77 | newrate = BW 78 | samples = round(x2.size * newrate / Fs) 79 | resampled_signal1 = sps.resample(x2, samples) 80 | ######################################################################## 81 | # channelize the signal Method 2 82 | ######################################################################## 83 | # Find a decimation rate to achieve audio sampling rate between 44-48 kHz 84 | audio_freq = 44100.0 85 | dec_audio = round(Fs / audio_freq) 86 | resampled_signal2 = sps.decimate(x2, dec_audio) 87 | Fs_audio = Fs / dec_audio 88 | ######################################################################## 89 | 90 | plt.psd(resampled_signal2, NFFT=1024, Fs=Fs_audio, Fc=sdr.center_freq / 1e6) 91 | plt.title("Dynamic Plot") 92 | plt.draw() 93 | plt.pause(0.1) 94 | fig.clear() 95 | 96 | # to stop streaming: 97 | await sdr.stop() 98 | 99 | # done 100 | sdr.close() 101 | 102 | 103 | loop = asyncio.get_event_loop() 104 | loop.run_until_complete(streaming()) 105 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RTL-SDR-Python-Signal-Processing 2 | Experimental DSP Python Scripts using an RTL-SDR USB dongle 3 | 4 | 5 | 6 | 7 | # Dependencies: 8 | -->Windows/Linux/OSX\ 9 | -->Python 2.7.x/3.3+\ 10 | -->librtlsdr\ 11 | -->Optional: NumPy (wraps samples in a more convenient form)\ 12 | 13 | 14 | 15 | 16 | 17 | # Troubleshooting: 18 | 19 | --->Some operating systems (Linux, OS X) seem to result in libusb buffer issues when performing small reads. 20 | Try reading 1024 (or higher powers of two) samples at a time if you have problems. 21 | 22 | 23 | --->If you’re having librtlsdr import errors: 24 | 25 | ## Windows: 26 | Make sure all the librtlsdr DLL files (librtlsdr.dll, libusb-1.0.dll) are in your system path, or the same folder as this README file. 27 | Also make sure you have all of their dependencies (e.g. libgcc_s_dw2-1.dll or possibly the Visual Studio runtime files). 28 | If rtl_sdr.exe works, then you should be okay. Also note that you can’t mix the 64 bit version of Python with 32 bit builds of librtlsdr, and vice versa. 29 | 30 | in librtlsdr.py replace the following code: 31 | 32 | #driver_files += ['librtlsdr.so', 'rtlsdr/librtlsdr.so'] 33 | #driver_files += ['rtlsdr.dll', 'librtlsdr.so'] 34 | #driver_files += ['..//rtlsdr.dll', '..//librtlsdr.so'] 35 | #driver_files += ['rtlsdr//rtlsdr.dll', 'rtlsdr//librtlsdr.so'] 36 | #driver_files += [lambda : find_library('rtlsdr'), lambda : find_library('librtlsdr')] 37 | driver_files += ['C:\\your path\\librtlsdr.dll'] 38 | driver_files += ['C:\\your path\\libusb-1.0.dll'] 39 | driver_files += ['C:\\your path\\libwinpthread-1.dll'] 40 | 41 | ## Linux: 42 | Make sure your LD_LIBRARY_PATH environment variable contains the directory where the librtlsdr.so.0 library is located. 43 | You can do this in a shell with (for example): export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib. See this issue for more details. 44 | 45 | 46 | # Linux RTL SDR Installation: 47 | 48 | #!/bin/bash 49 | 50 | apt-get update # update list of available software 51 | apt-get -y install git cmake libusb-1.0-0-dev python python-pip python-dev 52 | apt-get -y install python-scipy python-numpy python-matplotlib 53 | 54 | 55 | Remove other RTL-SDR driver, if it is loaded 56 | modprobe -r dvb_usb_rtl28xxu 57 | 58 | git clone https://github.com/steve-m/librtlsdr 59 | cd librtlsdr 60 | mkdir build 61 | cd build 62 | cmake ../ 63 | make 64 | make install 65 | ldconfig 66 | 67 | cd 68 | 69 | pip install pyrtlsdr 70 | 71 | wget https://raw.githubusercontent.com/keenerd/rtl-sdr-misc/master/heatmap/flatten.py 72 | 73 | Guide:https://www.rtl-sdr.com/tag/install-guide/ 74 | 75 | ### Troubleshooting: 76 | 77 | After installing the libraries you will likely need to unload the DVB-T drivers, which Linux uses by default. 78 | To unload them temporarily type "sudo rmmod dvb_usb_rtl28xxu" into terminal. This solution is only temporary as when you replug the dongle or restart the PC, the DVB-T drivers will be reloaded. 79 | For a permanent solution, create a text file "rtlsdr.conf" in /etc/modprobe.d and add the line "blacklist dvb_usb_rtl28xxu". 80 | You can use the one line command shown below to automatically write and create this file. 81 | 82 | echo 'blacklist dvb_usb_rtl28xxu' | sudo tee --append /etc/modprobe.d/blacklist-dvb_usb_rtl28xxu.conf 83 | Now you can restart your device. After it boots up again run "rtl_test" at the terminal with the RTL-SDR plugged in. It should start running. 84 | 85 | # Windows RTL SDR Installation: 86 | 87 | -->Plug in your dongle. Do not install any of the software that it came with (if any), and ensure that you wait a few seconds for plug and play to finish attempting to install the dongle (it will either fail or install Windows DVB-T TV drivers). 88 | If you've already installed the DVB-T drivers that came on the CD bundled with some dongles, uninstall them first. 89 | 90 | -->Install the zadig.exe software . Right click this file and select "Run as administrator". 91 | 92 | -->In Zadig, go to "Options->List All Devices" and make sure this option is checked. 93 | If you are using Windows 10, in some cases you may need to also uncheck "Ignore Hubs or Composite Parents". 94 | 95 | -->Select "Bulk-In, Interface (Interface 0)" from the drop down list. 96 | Note on some PCs you may see something like RTL2832UHIDIR or RTL2832U instead of the bulk in interface. 97 | This is also a valid selection. 98 | Do not select "USB Receiver (Interface 0) or Interface 1" or anything else or you will overwrite that driver! 99 | Double check that USB ID shows "0BDA 2838 00" as this indicates that the dongle is selected. 100 | 101 | -->We need to install the WinUSB driver, so also ensure that WinUSB is selected in the box after the arrow next to where it says Driver (this is the default selection) 102 | 103 | -->Click Replace Driver. On some PC's you might get a warning that the publisher cannot be verified, but just accept it by clicking on "Install this driver software anyway". 104 | This will install the drivers necessary to run the dongle as a software defined radio. 105 | Note that you may need to run zadig.exe again if you move the dongle to another USB port, or want to use two or more dongles together. --------------------------------------------------------------------------------