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.
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.
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(): q1.put(samples) 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 values.append(sample.real) else: values.append(sample.real) 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 break if signal: q2.put(values) 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 plt.plot(values[:2000]) plt.show() 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)) p1.start() # Run decode_fsk in another thread to make sure we don't miss any samples p2 = Process(target=decode_fsk, args=(q2, srate)) p2.start() # This is the main loop loop = asyncio.get_event_loop() loop.run_until_complete(get_samples(sdr, q1)) if __name__ == "__main__": main()