I'm trying to build a script to do some signal processing from my RTLSDR. But, the bits I'm getting is not what I would expect.

The preamble using 'Universal Radio Hacker' looks like this: URH Preamble

But after plotting all values my script is seeing (-1 until +1) it looks like this: Script preamble

Often I'm also getting plots that don't make any sense. At least the last one has some resemblance of the URH preamble, but also a lot of plots don't.

What am I missing.. 'Universal radio hacker' also uses pyrtlsdr, so I know it can work. - Complex, real, imaginary - Can't say that I understand it fully. Something wrong there ? - Noise, gain.. Not 100% sure what to do there. URH seems to set gain to 25, but when I do that I don't get anything, so I left it at 'auto' - I should be getting (almost) all of the samples. In the beginning I did lose some, but after I moved the postprocessing logic into separate processes it seems fine.

My script:

from rtlsdr import RtlSdr
from datetime import datetime
import asyncio
import matplotlib.pyplot as plt
from multiprocessing import Process, Queue

async def get_samples(sdr, q1):
    counter = 0
    timestamp1 = datetime.now()
    # Get this many samples every time
    async for samples in sdr.stream():
        counter += 1
        timestamp2 = datetime.now()
        if (timestamp2 - timestamp1).total_seconds() > 1:
            # To see if we missed any samples. Should be close to srate samples p/s
            print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"), 'GETSAMPLES -', int((counter * 131072) / (timestamp2 - timestamp1).total_seconds()), 'samples p/s')
            counter = 0
            timestamp1 = datetime.now()

def check_samples(q1, q2, noise, samplesperbit):
    while True:
        values = []
        withinnoisecounter = 0
        signal = False
        if q1.qsize() > 10:
            print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"), 'CHECKSAMPLES - Warning: Queue depth is', q1.qsize())
        samples = q1.get()
        for sample in samples:
            if not signal:
                # Start when signal breaks out of noise range
                if sample.real > noise or sample.real < -noise:
                    print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"), 'CHECKSAMPLES - signal detected')
                    signal = True
                if not (sample.real > noise or sample.real < -noise):
                    withinnoisecounter += 1
                elif withinnoisecounter > 0:
                    withinnoisecounter = 0
                if withinnoisecounter > samplesperbit * 3:
                    # Break when signal is within noise range 3 * samplesperbit
        if signal:

def decode_fsk(q2, srate):
    # ToDo, now it just plots
    while True:
        values = q2.get()
        plt.figure(figsize=(20, 5))
        # Preamble should be in here

def main():
    noise = 0.9
    # 38400 * 30 to get exactly 30 samples per bit.
    srate = 1152000
    samplesperbit = 1000000 / 38400 / (1000000 / srate)
    sdr = RtlSdr()
    # Just like in URH
    sdr.freq_correction = 1
    sdr.sample_rate = srate
    sdr.center_freq = 868.200e6
    sdr.gain = 'auto'
    # Run check_samples in another thread to make sure we don't miss any samples
    q1 = Queue()
    q2 = Queue()
    p1 = Process(target=check_samples, args=(q1, q2, noise, samplesperbit))
    # Run decode_fsk in another thread to make sure we don't miss any samples
    p2 = Process(target=decode_fsk, args=(q2, srate))
    # This is the main loop
    loop = asyncio.get_event_loop()
    loop.run_until_complete(get_samples(sdr, q1))

if __name__ == "__main__":



Your signal recording clearly shows that you have long streaks of 1.0 – that probably means you're clipping.

Your signal is thus broken. Make a new recording with less gain.

  • $\begingroup$ Using AGC (gain = "auto") with an RTL-SDR is rarely the best setting. Try other manual gain settings and other "noise" variable values. $\endgroup$ – hotpaw2 Nov 27 '17 at 0:26
  • $\begingroup$ Thanks, but this is not the only solution unfortunately, see my edited first post $\endgroup$ – Kiwi Nov 28 '17 at 14:18

Apparently, your gain is too much in this case and the ADC is getting overloaded. Try to reduce the gain and capture again. Plus, I think your sampling rate is not correct here.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.