def main(): sdr = RtlSdr() print 'Configuring SDR...' sdr.rs = 2.4e6 sdr.fc = 100e6 sdr.gain = 10 print ' sample rate: %0.6f MHz' % (sdr.rs/1e6) print ' center frequency %0.6f MHz' % (sdr.fc/1e6) print ' gain: %d dB' % sdr.gain print 'Reading samples...' samples = sdr.read_samples(256*1024) print ' signal mean:', sum(samples)/len(samples) print 'Testing callback...' sdr.read_samples_async(test_callback, 256*1024) try: import pylab as mpl print 'Testing spectrum plotting...' mpl.figure() mpl.psd(samples, NFFT=1024, Fc=sdr.fc/1e6, Fs=sdr.rs/1e6) mpl.show() except: # matplotlib not installed/working pass print 'Done\n' sdr.close()
async def main(): import math sdr = RtlSdr() print('Configuring SDR...') sdr.rs = 2.4e6 sdr.fc = 100e6 sdr.gain = 10 print(' sample rate: %0.6f MHz' % (sdr.rs/1e6)) print(' center frequency %0.6f MHz' % (sdr.fc/1e6)) print(' gain: %d dB' % sdr.gain) print('Streaming samples...') i = 0 async for samples in sdr.stream(): power = sum(abs(s)**2 for s in samples) / len(samples) print('Relative power:', 10*math.log10(power), 'dB') i += 1 if i > 100: sdr.stop() break print('Done') sdr.close()
def main(): sdr = RtlSdr() print 'Configuring SDR...' sdr.rs = 2.4e6 sdr.fc = 100e6 sdr.gain = 10 print ' sample rate: %0.6f MHz' % (sdr.rs / 1e6) print ' center frequency %0.6f MHz' % (sdr.fc / 1e6) print ' gain: %d dB' % sdr.gain print 'Reading samples...' samples = sdr.read_samples(256 * 1024) print ' signal mean:', sum(samples) / len(samples) print 'Testing callback...' sdr.read_samples_async(test_callback, 256 * 1024) try: import pylab as mpl print 'Testing spectrum plotting...' mpl.figure() mpl.psd(samples, NFFT=1024, Fc=sdr.fc / 1e6, Fs=sdr.rs / 1e6) mpl.show() except: # matplotlib not installed/working pass print 'Done\n' sdr.close()
async def main(): import math sdr = RtlSdr() print('Configuring SDR...') sdr.rs = 2.4e6 sdr.fc = 100e6 sdr.gain = 10 print(' sample rate: %0.6f MHz' % (sdr.rs / 1e6)) print(' center frequency %0.6f MHz' % (sdr.fc / 1e6)) print(' gain: %d dB' % sdr.gain) print('Streaming samples...') i = 0 async for samples in sdr.stream(): power = sum(abs(s)**2 for s in samples) / len(samples) print('Relative power:', 10 * math.log10(power), 'dB') i += 1 if i > 100: sdr.stop() break print('Done') sdr.close()
def main(): sdr = RtlSdr() # some defaults sdr.rs = 2.4e6 sdr.fc = 146e6 sdr.gain = 50 noiseWindowLength = 20 noiseWindow = [] rampWindowLength = 5 rampWindow = [] rampPercent = 1.2 backgroundNoise = False pulseFound = False results = [] # Loop enough times to collect 3 seconds of data sampleLoops = int(sdr.rs * 3 / 1024) for i in range(0, sampleLoops): samples = sdr.read_samples(1024) curMag, freqs = magnitude_spectrum(samples, Fs=sdr.rs) maxSignal = max(curMag) noiseWindow.append(maxSignal) if len(noiseWindow) > noiseWindowLength: noiseWindow.pop(0) backgroundNoise = sum(noiseWindow) / noiseWindowLength rampWindow.append(backgroundNoise) if len(rampWindow) > rampWindowLength: rampWindow.pop(0) if rampWindow[rampWindowLength - 1] > rampWindow[0] * rampPercent: pulseFound = True else: pulseFound = False results.append([maxSignal, backgroundNoise, pulseFound]) sdr.close() f = open("data.csv", "w") for result in results: f.write(str(result[0])) f.write(",") f.write(str(result[1])) f.write(",") f.write(str(result[2])) f.write("\n") f.close()
def main(): sdr = RtlSdr() # some defaults sdr.rs = 2.4e6 sdr.fc = 146e6 sdr.gain = 50 noiseWindowLength = 20 noiseWindow = [] rampWindowLength = 5 rampWindow = [] rampPercent = 1.2 backgroundNoise = False pulseFound = False sampleCount = int(sdr.rs * 3 / 1024) f = open("data.csv", "w") for i in range(0, sampleCount): samples = sdr.read_samples(1024) curMag, freqs = magnitude_spectrum(samples, Fs=sdr.rs) maxSignal = max(curMag) noiseWindow.append(maxSignal) if len(noiseWindow) > noiseWindowLength: noiseWindow.pop(0) backgroundNoise = sum(noiseWindow) / noiseWindowLength rampWindow.append(backgroundNoise) if len(rampWindow) > rampWindowLength: rampWindow.pop(0) if rampWindow[rampWindowLength - 1] > rampWindow[0] * rampPercent: pulseFound = True else: pulseFound = False f.write(str(maxSignal)) f.write(",") f.write(str(backgroundNoise)) f.write(",") f.write(str(pulseFound)) f.write("\n") f.close() # cleanup sdr.close()
def main(): sdr = RtlSdr() wf = Waterfall(sdr) # some defaults sdr.rs = 2.4e6 sdr.fc = 100e6 sdr.gain = 10 wf.start() # cleanup sdr.close()
def main(): from rtlsdr import RtlSdr sdr = RtlSdr() print 'Configuring SDR...' sdr.rs = 1e6 sdr.fc = 70e6 sdr.gain = 5 print ' sample rate: %0.6f MHz' % (sdr.rs/1e6) print ' center ferquency %0.6f MHz' % (sdr.fc/1e6) print ' gain: %d dB' % sdr.gain print 'Testing callback...' sdr.read_samples_async(test_callback)
def main(): from rtlsdr import RtlSdr sdr = RtlSdr() print 'Configuring SDR...' sdr.rs = 1e6 sdr.fc = 70e6 sdr.gain = 5 print ' sample rate: %0.6f MHz' % (sdr.rs / 1e6) print ' center ferquency %0.6f MHz' % (sdr.fc / 1e6) print ' gain: %d dB' % sdr.gain print 'Testing callback...' sdr.read_samples_async(test_callback)
def main(): sdr = RtlSdr() wf = Waterfall(sdr) # some defaults # Sample rate sdr.rs = 1e6 sdr.set_direct_sampling('q') sdr.fc = 0 sdr.gain = 10 wf.start() # cleanup sdr.close()
def main(): sdr = RtlSdr() wf = Waterfall(sdr) # some defaults sdr.rs = 2.4e6 sdr.fc = 100e6 #sdr.gain = 10 sdr.gain = 'auto' ### setting up TCP server t1 = threading.Thread(target=server_run, args=(q2,)) t1.start() wf.start() # cleanup sdr.close()
def main(): sdr = RtlSdr(1) wf = Waterfall(sdr) # some defaults sdr.rs = 1.024e6 sdr.fc = 89.3e6 sdr.gain = 'auto' wf.start() # cleanup sdr.close()
def main(): sdr = RtlSdr() print 'Configuring SDR...' sdr.rs = 2.4e6 sdr.fc = 70e6 sdr.gain = 4 print ' sample rate: %0.6f MHz' % (sdr.rs / 1e6) print ' center frequency %0.6f MHz' % (sdr.fc / 1e6) print ' gain: %d dB' % sdr.gain print 'Reading samples...' samples = sdr.read_samples(1024) print ' signal mean:', sum(samples) / len(samples) print 'Testing callback...' sdr.read_samples_async(test_callback) sdr.close()
def main(): sdr = RtlSdr() print 'Configuring SDR...' sdr.rs = 2.4e6 sdr.fc = 70e6 sdr.gain = 4 print ' sample rate: %0.6f MHz' % (sdr.rs/1e6) print ' center frequency %0.6f MHz' % (sdr.fc/1e6) print ' gain: %d dB' % sdr.gain print 'Reading samples...' samples = sdr.read_samples(1024) print ' signal mean:', sum(samples)/len(samples) print 'Testing callback...' sdr.read_samples_async(test_callback) sdr.close()
def main(): gin=sys.argv[1] ppm=sys.argv[2] chn=sys.argv[3] if ppm=='0': ppm='1' if chn=='a': frc=161.975e6 if chn=='b': frc=162.025e6 sdr = RtlSdr() wf = Waterfall(sdr) # some defaults sdr.rs = 1e6 sdr.fc = frc sdr.gain = float(gin) sdr.freq_correction = int(float(ppm)) wf.start() # cleanup sdr.close()
def main(): @limit_time(0.01) @limit_calls(20) def read_callback(buffer, rtlsdr_obj): print('In callback') print(' signal mean:', sum(buffer)/len(buffer)) from rtlsdr import RtlSdr sdr = RtlSdr() print('Configuring SDR...') sdr.rs = 1e6 sdr.fc = 70e6 sdr.gain = 5 print(' sample rate: %0.6f MHz' % (sdr.rs/1e6)) print(' center ferquency %0.6f MHz' % (sdr.fc/1e6)) print(' gain: %d dB' % sdr.gain) print('Testing callback...') sdr.read_samples_async(read_callback)
def main(): gin = sys.argv[1] ppm = sys.argv[2] chn = sys.argv[3] if ppm == '0': ppm = '1' if chn == 'a': frc = 161.975e6 if chn == 'b': frc = 162.025e6 sdr = RtlSdr() wf = Waterfall(sdr) # some defaults sdr.rs = 1e6 sdr.fc = frc sdr.gain = float(gin) sdr.freq_correction = int(float(ppm)) wf.start() # cleanup sdr.close()
def main(): sdr = RtlSdr() wf = Waterfall(sdr) # some defaults sdr.rs = 1e6 sdr.fc = 103.4e6 sdr.gain = 10 # mqtt client client.on_connect = on_connect client.username_pw_set("slip","slip") client.connect("ec2-35-180-123-52.eu-west-3.compute.amazonaws.com",1883) #client.loop_start() #client.publish("laverie/1","102.5,0") #client.disconnect() #client.loop_stop() wf.start() # cleanup sdr.close()
def storing_stream_with_windows(lock, rs, cf, gain, ns, device, path_storing): if 0==0:#librtlsdr.rtlsdr_get_device_count() > 0: lock.acquire(timeout=ns/rs*1.1) print("locked") sdr = RtlSdr(device_index = device) # some defaults sdr.rs = rs sdr.fc = cf sdr.gain = gain timestamp = time.time() samples = sdr.read_bytes(ns * 2) sdr.close() lock.release() #print("print") filename = get_groundstationid() + "_f" + str(cf) + "_d" + str(device) + "_t" + str(int(timestamp)) f = open(path_storing + filename + ".tmp", 'wb') f.write(samples) f.close() os.rename(path_storing + filename + ".tmp", path_storing + filename + ".dat")
#!/bin/python import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation from rtlsdr import RtlSdr sdr = RtlSdr() # Sampling rate sdr.rs = 256000. #1024e3 # Pins 4 and 5 sdr.set_direct_sampling(2) # Center frequency sdr.fc = 0 # I don't think this is used? sdr.gain = 1 fig = plt.figure() ax = fig.add_subplot(211, autoscale_on=False, xlim=(-1, 513), ylim=(-1.1,1.1)) ax.grid() rline, = ax.plot([], [], 'r-', lw=2) iline, = ax.plot([], [], 'g-', lw=2) ax = fig.add_subplot(212, autoscale_on=False, xlim=(-1, 513), ylim=(-1.3,1.3)) ax.grid() mline, = ax.plot([], [], 'b-', lw=2) def animate(i): samples = sdr.read_samples(1024) try: zc = np.where(np.diff(np.sign(samples))>0)[0][0]
def run_spectrum_int(num_samp, nbins, gain, rate, fc, t_int): ''' Inputs: num_samp: Number of elements to sample from the SDR IQ per call; use powers of 2 nbins: Number of frequency bins in the resulting power spectrum; powers of 2 are most efficient, and smaller numbers are faster on CPU. gain: Requested SDR gain (dB) rate: SDR sample rate, intrinsically tied to bandwidth in SDRs (Hz) fc: Base center frequency (Hz) t_int: Total effective integration time (s) Returns: freqs: Frequencies of the resulting spectrum, centered at fc (Hz), numpy array p_avg_db_hz: Power spectral density (dB/Hz) numpy array ''' # Force a choice of window to allow converting to PSD after averaging # power spectra WINDOW = 'hann' # Force a default nperseg for welch() because we need to get a window # of this size later. Use the scipy default 256, but enforce scipy # conditions on nbins vs. nperseg when nbins gets small. if nbins < 256: nperseg = nbins else: nperseg = 256 print('Initializing rtl-sdr with pyrtlsdr:') sdr = RtlSdr() try: sdr.rs = rate # Rate of Sampling (intrinsically tied to bandwidth with SDR dongles) sdr.fc = fc sdr.gain = gain print(' sample rate: %0.6f MHz' % (sdr.rs / 1e6)) print(' center frequency %0.6f MHz' % (sdr.fc / 1e6)) print(' gain: %d dB' % sdr.gain) print(' num samples per call: {}'.format(num_samp)) print(' PSD binning: {} bins'.format(nbins)) print(' requested integration time: {}s'.format(t_int)) N = int(sdr.rs * t_int) num_loops = int(N / num_samp) + 1 print(' => num samples to collect: {}'.format(N)) print(' => est. num of calls: {}'.format(num_loops - 1)) # Set up arrays to store power spectrum calculated from I-Q samples freqs = np.zeros(nbins) p_xx_tot = np.zeros(nbins) cnt = 0 # Set the baseline time start_time = time.time() print('Integration began at {}'.format( time.strftime('%a, %d %b %Y %H:%M:%S', time.localtime(start_time)))) # Estimate the power spectrum by Bartlett's method. # Following https://en.wikipedia.org/wiki/Bartlett%27s_method: # Use scipy.signal.welch to compute one spectrum for each timeseries # of samples from a call to the SDR. # The scipy.signal.welch() method with noverlap=0 is equivalent to # Bartlett's method, which estimates the spectral content of a time- # series by splitting our num_samp array into K segments of length # nperseg and averaging the K periodograms. # The idea here is to average many calls to welch() across the # requested integration time; this means we can call welch() on each # set of samples from the SDR, accumulate the binned power estimates, # and average later by the number of spectra taken to reduce the # noise while still following Barlett's method, and without keeping # huge arrays of iq samples around in RAM. # Time integration loop for cnt in range(num_loops): iq = sdr.read_samples(num_samp) freqs, p_xx = welch(iq, fs=rate, nperseg=nperseg, nfft=nbins, noverlap=0, scaling='spectrum', window=WINDOW, detrend=False, return_onesided=False) p_xx_tot += p_xx end_time = time.time() print('Integration ended at {} after {} seconds.'.format( time.strftime('%a, %d %b %Y %H:%M:%S'), end_time - start_time)) print('{} spectra were measured at {}.'.format(cnt, fc)) print('for an effective integration time of {:.2f}s'.format( num_samp * cnt / rate)) # Unfortunately, welch() with return_onesided=False does a sloppy job # of returning the arrays in what we'd consider the "right" order, # so we have to swap the first and last halves to avoid an artifact # in the plot. half_len = len(freqs) // 2 freqs = np.fft.fftshift(freqs) p_xx_tot = np.fft.fftshift(p_xx_tot) # Compute the average power spectrum based on the number of spectra read p_avg = p_xx_tot / cnt # Convert to power spectral density # A great resource that helped me understand the difference: # https://community.sw.siemens.com/s/article/what-is-a-power-spectral-density-psd # We could just divide by the bandwidth, but welch() applies a # windowing correction to the spectrum, and does it differently to # power spectra and PSDs. We multiply by the power spectrum correction # factor to remove it and divide by the PSD correction to apply it # instead. Then divide by the bandwidth to get the power per unit # frequency. # See the scipy docs for _spectral_helper(). win = get_window(WINDOW, nperseg) p_avg_hz = p_avg * ((win.sum()**2) / (win * win).sum()) / rate p_avg_db_hz = 10. * np.log10(p_avg_hz) # Shift frequency spectra back to the intended range freqs = freqs + fc # nice and tidy sdr.close() except OSError as err: print("OS error: {0}".format(err)) raise (err) except: print('Unexpected error:', sys.exc_info()[0]) raise finally: sdr.close() return freqs, p_avg_db_hz
def run_total_power_int(num_samp, gain, rate, fc, t_int): ''' Implement a total-power radiometer. Raw, uncalibrated power values. Inputs: num_samp: Number of elements to sample from the SDR IQ timeseries per call gain: Requested SDR gain (dB) rate: SDR sample rate, intrinsically tied to bandwidth in SDRs (Hz) fc: Bandpass center frequency (Hz) t_int: Total integration time (s) Returns: p_tot: Time-averaged power in the signal from the sdr, in uncalibrated units ''' import rtlsdr.helpers as helpers # Start the RtlSdr instance print('Initializing rtl-sdr with pyrtlsdr:') sdr = RtlSdr() try: sdr.rs = rate sdr.fc = fc sdr.gain = gain print(' sample rate: {} MHz'.format(sdr.rs / 1e6)) print(' center frequency {} MHz'.format(sdr.fc / 1e6)) print(' gain: {} dB'.format(sdr.gain)) print(' num samples per call: {}'.format(num_samp)) print(' requested integration time: {}s'.format(t_int)) # For Nyquist sampling of the passband dv over an integration time # tau, we must collect N = 2 * dv * tau real samples. # https://www.cv.nrao.edu/~sransom/web/A1.html#S3 # Because the SDR collects complex samples at a rate rs = dv, we can # Nyquist sample a signal of band-limited noise dv with only rs * tau # complex samples. # The phase content of IQ samples allows the bandlimited signal to be # Nyquist sampled at a data rate of rs = dv complex samples per second # rather than the 2* dv required of real samples. N = int(sdr.rs * t_int) print(' => num samples to collect: {}'.format(N)) print(' => est. num of calls: {}'.format(int(N / num_samp))) global p_tot global cnt p_tot = 0.0 cnt = 0 # Set the baseline time start_time = time.time() print('Integration began at {}'.format( time.strftime('%a, %d %b %Y %H:%M:%S', time.localtime(start_time)))) # Time integration loop @helpers.limit_calls(N / num_samp) def p_tot_callback(iq, context): # The below is a total power measurement equivalent to summing # P = V^2 / R = (sqrt(I^2 + Q^2))^2 = (I^2 + Q^2) global p_tot p_tot += np.sum(np.real(iq * np.conj(iq))) global cnt cnt += 1 sdr.read_samples_async(p_tot_callback, num_samples=num_samp) end_time = time.time() print('Integration ended at {} after {} seconds.'.format( time.strftime('%a, %d %b %Y %H:%M:%S'), end_time - start_time)) print('{} calls were made to SDR.'.format(cnt)) print('{} samples were measured at {} MHz'.format( cnt * num_samp, fc / 1e6)) print('for an effective integration time of {:.2f}s'.format( (num_samp * cnt) / rate)) # Compute the average power value based on the number of measurements # we actually did p_avg = p_tot / (num_samp * cnt) # nice and tidy sdr.close() except OSError as err: print("OS error: {0}".format(err)) raise (err) except: print('Unexpected error:', sys.exc_info()[0]) raise finally: sdr.close() return p_avg
def run_fswitch_int(num_samp, nbins, gain, rate, fc, fthrow, t_int, fswitch=10): ''' Note: Because a significant time penalty is introduced for each retuning, a maximum frequency switching rate of 10 Hz is adopted to help reduce the fraction of observation time spent retuning the SDR for a given effective integration time. As a consequence, the minimum integration time is 2*(1/fswitch) to ensure the user gets at least one spectrum taken on each frequency of interest. Inputs: num_samp: Number of elements to sample from the SDR IQ timeseries: powers of 2 are most efficient nbins: Number of frequency bins in the resulting power spectrum; powers of 2 are most efficient, and smaller numbers are faster on CPU. gain: Requested SDR gain (dB) rate: SDR sample rate, intrinsically tied to bandwidth in SDRs (Hz) fc: Base center frequency (Hz) fthrow: Alternate frequency (Hz) t_int: Total effective integration time (s) Kwargs: fswitch: Frequency of switching between fc and fthrow (Hz) Returns: freqs_fold: Frequencies of the spectrum resulting from folding according to the folding method implemented in the f_throw_fold (post_process module) p_fold: Folded frequency-switched power, centered at fc,(uncalibrated V^2) numpy array. ''' from .post_process import f_throw_fold import rtlsdr.helpers as helpers # Check inputs: assert t_int >= 2.0 * ( 1.0 / fswitch ), '''At t_int={} s, frequency switching at fswitch={} Hz means the switching period is longer than integration time. Please choose a longer integration time or shorter switching frequency to ensure enough integration time to dwell on each frequency.'''.format( t_int, fswitch) if fswitch > 10: print( '''Warning: high frequency switching values mean more SDR retunings. A greater fraction of observation time will be spent retuning the SDR, resulting in longer wait times to reach the requested effective integration time.''' ) print('Initializing rtl-sdr with pyrtlsdr:') sdr = RtlSdr() try: sdr.rs = rate # Rate of Sampling (intrinsically tied to bandwidth with SDR dongles) sdr.fc = fc sdr.gain = gain print(' sample rate: %0.6f MHz' % (sdr.rs / 1e6)) print(' center frequency %0.6f MHz' % (sdr.fc / 1e6)) print(' gain: %d dB' % sdr.gain) print(' num samples per call: {}'.format(num_samp)) print(' requested integration time: {}s'.format(t_int)) # Total number of samples to collect N = int(sdr.rs * t_int) # Number of samples on each frequency dwell N_dwell = int(sdr.rs * (1.0 / fswitch)) # Number of calls to SDR on each frequency num_loops = N_dwell // num_samp # Number of dwells on each frequency num_dwells = N // N_dwell print(' => num samples to collect: {}'.format(N)) print(' => est. num of calls: {}'.format(N // num_samp)) print(' => num samples on each dwell: {}'.format(N_dwell)) print(' => est. num of calls on each dwell: {}'.format(num_loops)) print(' => num dwells total: {}'.format(num_dwells)) # Set up arrays to store power spectrum calculated from I-Q samples freqs_on = np.zeros(nbins) freqs_off = np.zeros(nbins) p_xx_on = np.zeros(nbins) p_xx_off = np.zeros(nbins) cnt = 0 # Set the baseline time start_time = time.time() print('Integration began at {}'.format( time.strftime('%a, %d %b %Y %H:%M:%S', time.localtime(start_time)))) # Swap between the two specified frequencies, integrating signal. # Time integration loop for i in range(num_dwells): tick = (i % 2 == 0) if tick: sdr.fc = fc else: sdr.fc = fthrow for j in range(num_loops): iq = sdr.read_samples(num_samp) if tick: freqs_on, p_xx = welch(iq, fs=rate, nperseg=nbins, noverlap=0, scaling='spectrum', detrend=False, return_onesided=False) p_xx_on += p_xx else: freqs_off, p_xx = welch(iq, fs=rate, nperseg=nbins, noverlap=0, scaling='spectrum', detrend=False, return_onesided=False) p_xx_off += p_xx cnt += 1 end_time = time.time() print('Integration ended at {} after {} seconds.'.format( time.strftime('%a, %d %b %Y %H:%M:%S'), end_time - start_time)) print('{} spectra were measured, split between {} and {}.'.format( cnt, fc, fthrow)) print('for an effective integration time of {:.2f}s'.format( num_samp * cnt / rate)) half_len = len(freqs_on) // 2 freqs_on = np.fft.fftshift(freqs_on) freqs_off = np.fft.fftshift(freqs_off) p_xx_on = np.fft.fftshift(p_xx_on) p_xx_off = np.fft.fftshift(p_xx_off) # Compute the average power spectrum based on the number of spectra read p_avg_on = p_xx_on / cnt p_avg_off = p_xx_off / cnt # Shift frequency spectra back to the intended range freqs_on = freqs_on + fc freqs_off = freqs_off + fthrow # Fold switched power spectra freqs_fold, p_fold = f_throw_fold(freqs_on, freqs_off, p_avg_on, p_avg_off) # nice and tidy sdr.close() except OSError as err: print("OS error: {0}".format(err)) raise (err) except: print('Unexpected error:', sys.exc_info()[0]) raise finally: sdr.close() return freqs_fold, p_fold
process(samples, rtl_sdr_obj) parser = argparse.ArgumentParser( formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument('--ppm', type=int, default=0, help='ppm error correction') parser.add_argument('--gain', type=int, default=20, help='RF gain level') parser.add_argument('--freq', type=int, default=92900000, help='frequency to listen to, in Hertz') parser.add_argument('--verbose', action='store_true', help='mute audio output') args = parser.parse_args() sdr = RtlSdr() sdr.rs = 1024000 sdr.fc = args.freq sdr.gain = args.gain sdr.err_ppm = args.ppm sdr.read_samples_async(read_callback, int(sdr.get_sample_rate()) // 16)
def run(self): logging.debug("PulseDetector.run") try: sdr = RtlSdr() sdr.rs = 2.4e6 sdr.fc = 146e6 sdr.gain = 10 except Exception as e: logging.exception("SDR init failed") return last_max_mag = 0 leadingEdge = False rgPulse = [] lastPulseTime = time.time() #timeoutCount = 0 pulseCount = 0 while True: # Handle change in frequency try: newFrequency = self.setFreqQueue.get_nowait() except Exception as e: pass else: logging.debug("Changing frequency %d", newFrequency) sdr.fc = newFrequency # Handle change in gain try: newGain = self.setGainQueue.get_nowait() except Exception as e: pass else: sdr.gain = newGain logging.debug("Changing gain %d:%f", newGain, sdr.gain) # Adjust noise threshold sdrReopen = False #noiseThreshold = self.calcNoiseThreshold(self.amp, sdr.gain) #logging.debug("Noise threshold %f", noiseThreshold) # Read samples try: samples = sdr.read_samples(NUM_SAMPLES_PER_SCAN) except Exception as e: logging.exception("SDR read failed") sdrReopen = True if sdrReopen: logging.debug("Attempting reopen") try: sdr.open() except Exception as e: logging.exception("SDR reopen failed") return try: samples = sdr.read_samples(NUM_SAMPLES_PER_SCAN) except Exception as e: logging.exception("SDR read failed") return # Process samples mag, freqs = magnitude_spectrum(samples, Fs=sdr.rs) if not leadingEdge: # Detect leading edge strength = self.detectedPulseStrength(mag) if strength: leadingEdge = True #logging.debug("leading edge strength:background %d %d", strength, self.backgroundNoise) rgPulse = [strength] else: # Detect trailing edge falling below background noise strength = self.detectedPulseStrength(mag) if strength: rgPulse.append(strength) else: leadingEdge = False pulseCaptureCount = len(rgPulse) self.adjustBackgroundNoise(strength) if pulseCaptureCount >= self.minPulseCaptureCount: pulseStrength = max(rgPulse) pulseCount += 1 logging.debug( "***** %d %d %d pulseStrength:len(rgPulse):background", pulseStrength, pulseCaptureCount, self.backgroundNoise) if self.pulseQueue: self.pulseQueue.put(pulseStrength) lastPulseTime = time.time() else: logging.debug("pulse too short %d", pulseCaptureCount) for skippedStrength in rgPulse: self.adjustBackgroundNoise(skippedStrength) rgPulse = [] # Check for no pulse if time.time() - lastPulseTime > 3: #timeoutCount += 1 if leadingEdge: leadingEdge = False logging.error( "failed to detect trailing edge - len(rgPulse):background %d %d", len(rgPulse), self.backgroundNoise) else: logging.debug("no pulse for two seconds - background %d", self.backgroundNoise) if self.pulseQueue: self.pulseQueue.put(0) rgPulse = [] lastPulseTime = time.time() sdr.close()
# initialize a curve for the plot i_curve = data_plot.plot(pen='r', name = "In-Phase Signal") q_curve = data_plot.plot(pen='y', name = "Quadrature Signal") win.nextRow() # initialize plot fft_plot = win.addPlot(title="Power Vs. Frequency") fft_plot.showGrid(True, True, alpha = 1) fft_plot.addLegend() # initialize a curve for the plot curve = fft_plot.plot(pen='g', name = "Power Spectrum") max_curve = fft_plot.plot(pen='r', name = "Max Hold") sdr = RtlSdr() # some defaults sdr.rs = 2e6 sdr.fc = 106.9e6 sdr.gain = 30 max_data = [] def update(): global dut, curve, max_data samples = sdr.read_samples(SAMPLE_SIZE) samples = samples * np.hanning(len(samples)) pow = 20 * np.log10(np.abs(np.fft.fftshift(np.fft.fft(samples)))) i_curve.setData(samples.real) q_curve.setData(samples.imag) if len(max_data) == 0: max_data = pow else: max_data = np.maximum(max_data, pow) curve.setData(pow) max_curve.setData(max_data)
app = Flask(__name__) @app.route("/") def hello(): return render_template("index.html") @app.route("/2m.json") def samples(): return jsonify({'samples': radio.getSamples().tolist(), 'minf': 146.0e6, 'maxf': 146.8e6}) if __name__ == "__main__": sdr = RtlSdr() radio = Radio(sdr) # some defaults sdr.freq_correction = 1 sdr.rs = 0.95e6 sdr.fc = 146.60e6 sdr.gain = 35 # start polling for samples radio.updateSamples() app.run(debug=True, use_reloader=False, host='0.0.0.0')
def run_gpu_spectrum_int(num_samp, nbins, gain, rate, fc, t_int): ''' Inputs: num_samp: Number of elements to sample from the SDR IQ per call; use powers of 2 nbins: Number of frequency bins in the resulting power spectrum; powers of 2 are most efficient, and smaller numbers are faster on CPU. gain: Requested SDR gain (dB) rate: SDR sample rate, intrinsically tied to bandwidth in SDRs (Hz) fc: Base center frequency (Hz) t_int: Total effective integration time (s) Returns: freqs: Frequencies of the resulting spectrum, centered at fc (Hz), numpy array p_avg_db_hz: Power spectral density (dB/Hz) numpy array ''' import cupy as cp import cusignal # Force a choice of window to allow converting to PSD after averaging # power spectra WINDOW = 'hann' # Force a default nperseg for welch() because we need to get a window # of this size later. Use the scipy default 256, but enforce scipy # conditions on nbins vs. nperseg when nbins gets small. if nbins < 256: nperseg = nbins else: nperseg = 256 print('Initializing rtl-sdr with pyrtlsdr:') sdr = RtlSdr() try: sdr.rs = rate # Rate of Sampling (intrinsically tied to bandwidth with SDR dongles) sdr.fc = fc sdr.gain = gain print(' sample rate: %0.6f MHz' % (sdr.rs / 1e6)) print(' center frequency %0.6f MHz' % (sdr.fc / 1e6)) print(' gain: %d dB' % sdr.gain) print(' num samples per call: {}'.format(num_samp)) print(' PSD binning: {} bins'.format(nbins)) print(' requested integration time: {}s'.format(t_int)) N = int(sdr.rs * t_int) num_loops = int(N / num_samp) + 1 print(' => num samples to collect: {}'.format(N)) print(' => est. num of calls: {}'.format(num_loops - 1)) # Set up arrays to store power spectrum calculated from I-Q samples freqs = cp.zeros(nbins) p_xx_tot = cp.zeros(nbins, dtype=complex) # Create mapped, pinned memory for zero copy between CPU and GPU gpu_iq = cusignal.get_shared_mem(num_samp, dtype=np.complex128) cnt = 0 # Set the baseline time start_time = time.time() print('Integration began at {}'.format( time.strftime('%a, %d %b %Y %H:%M:%S', time.localtime(start_time)))) # Time integration loop for cnt in range(num_loops): # Move USB-collected samples off CPU and onto GPU for calc gpu_iq[:] = sdr.read_samples(num_samp) freqs, p_xx = cusignal.welch(gpu_iq, fs=rate, nperseg=nperseg, nfft=nbins, noverlap=0, scaling='spectrum', window=WINDOW, detrend=False, return_onesided=False) p_xx_tot += p_xx end_time = time.time() print('Integration ended at {} after {} seconds.'.format( time.strftime('%a, %d %b %Y %H:%M:%S'), end_time - start_time)) print('{} spectra were measured at {}.'.format(cnt, fc)) print('for an effective integration time of {:.2f}s'.format( num_samp * cnt / rate)) half_len = len(freqs) // 2 # Swap frequencies: tmp_first = freqs[:half_len].copy() tmp_last = freqs[half_len:].copy() freqs[:half_len] = tmp_last freqs[half_len:] = tmp_first # Swap powers: tmp_first = p_xx_tot[:half_len].copy() tmp_last = p_xx_tot[half_len:].copy() p_xx_tot[:half_len] = tmp_last p_xx_tot[half_len:] = tmp_first # Compute the average power spectrum based on the number of spectra read p_avg = p_xx_tot / cnt # Convert to power spectral density # See the scipy docs for _spectral_helper(). win = get_window(WINDOW, nperseg) p_avg_hz = p_avg * ((win.sum()**2) / (win * win).sum()) / rate p_avg_db_hz = 10. * cp.log10(p_avg_hz) # Shift frequency spectra back to the intended range freqs = freqs + fc # nice and tidy sdr.close() except OSError as err: print("OS error: {0}".format(err)) raise (err) except: print('Unexpected error:', sys.exc_info()[0]) raise finally: sdr.close() return cp.asnumpy(freqs), cp.asnumpy(p_avg_db_hz)
# speed of light c = 299792458.0 # m/s # Set RTLSDR parameters and initialize # This sample rate is used because it is a multiple of the baud rate # Also it allows capturing the whole 1 MHz channel, which ensures getting # both orbcomm channels without tuning to a different center frequency # However, it is a much higher sample rate than would be needed. sample_rate = 1.2288e6 center_freq = 137.5e6 gain = 'auto' # Use AGC sdr = RtlSdr() sdr.rs = sample_rate sdr.gain = gain sdr.fc = center_freq # dictionary/list to hold satellite plots sat_gps_dict = {} sat_plot_lines = [] # receive samples that are an integer multiple of 1024 from the RTLSDR num_samples_per_recording = int(1024 * 128) should_finish = False queue_max_size = 30 # This is a callback function for async rtlsdr receive samples def rtlsdr_callback(samples, context): global decoder global should_finish
self.psd_scan, self.f = psd(self.samples, NFFT=NFFT) threading.Timer(0.02, self.updateSamples).start() def getSamples(self): return self.psd_scan app = Flask(__name__) @app.route("/") def hello(): return render_template("index.html") @app.route("/2m.json") def samples(): return jsonify({'samples': radio.getSamples().tolist(), 'minf': 144.0e6, 'maxf': 146.0e6}) if __name__ == "__main__": sdr = RtlSdr() radio = Radio(sdr) # some defaults sdr.rs = 2.0e6 sdr.fc = 145.0e6 sdr.gain = 10 # start polling for samples radio.updateSamples() app.run(debug=True, use_reloader=False, host='0.0.0.0')
#!/bin/python import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation from rtlsdr import RtlSdr, limit_calls from multiprocessing import Process sdr = RtlSdr() # Sampling rate sdr.rs = 1024e3 # Pins 4 and 5 sdr.set_direct_sampling(2) # Center frequency sdr.fc = 0 # I don't think this is used? sdr.gain = 1 fig = plt.figure() ax = fig.add_subplot(211, autoscale_on=False, xlim=(-1, 129), ylim=(-1.1, 1.1)) ax.grid() rline, = ax.plot([], [], 'r-', lw=2) iline, = ax.plot([], [], 'g-', lw=2) ax = fig.add_subplot(212, autoscale_on=False, xlim=(-1, 129), ylim=(-1.3, 1.3)) ax.grid() mline, = ax.plot([], [], 'b-', lw=2) global pdata pdata = [0] * 128