mirror of
https://github.com/0xabad1dea/pyrtlsdr-peakfinder
synced 2024-12-19 20:57:04 +00:00
a star is born
This commit is contained in:
commit
8018f38cef
21
README.md
Normal file
21
README.md
Normal file
@ -0,0 +1,21 @@
|
||||
pyrtlsdr-peakfinder
|
||||
==============
|
||||
|
||||
The quickest, dirtiest scanner imaginable to spit out frequencies on which signal peaks are detected for RTL-SDR radios. It is probably not very efficient, but it does work. For my hardware. Good luck.
|
||||
|
||||
Usage: `peakfinder.py 88.0 110.0` (in megahertz)
|
||||
|
||||
The values in the script were empirically determined and you should feel free to adjust them. Reported frequencies may lean slightly right of the signal's center.
|
||||
|
||||
Copyright © 2013 Melissa Elliott (0xabad1dea)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of the software nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
![Secret fourth clause: more Kasane Teto](http://i.imgur.com/Ikzrr4Q.png)
|
||||
|
||||
[image source](http://seiga.nicovideo.jp/seiga/im1354345)
|
134
peakfinder.py
Executable file
134
peakfinder.py
Executable file
@ -0,0 +1,134 @@
|
||||
#! /usr/bin/python
|
||||
# quick and dirty peakfinder for RTL-SDR by 0xabad1dea
|
||||
# scans a range and reports signals found in mhz
|
||||
|
||||
# Tries very hard to not report those !@#$ phantom lines ---
|
||||
# but as a result, avoid centering the window exactly on a
|
||||
# frequency if you're specifically looking for it, as it may
|
||||
# disappear or split into two.
|
||||
|
||||
# probably not very efficient
|
||||
|
||||
# BSD three-clause
|
||||
|
||||
# depends: https://github.com/roger-/pyrtlsdr
|
||||
|
||||
|
||||
# fixme: narrow down the import...
|
||||
from pylab import *
|
||||
from rtlsdr import *
|
||||
|
||||
sdr = RtlSdr()
|
||||
|
||||
# configure device
|
||||
sdr.sample_rate = 2.4e6
|
||||
# lower the gain to, like, 4 if you don't want to hear about weak signals
|
||||
sdr.gain = 19
|
||||
|
||||
|
||||
########################################################################
|
||||
def peakdet(v, delta, x = None):
|
||||
# hacked up from https://gist.github.com/endolith/250860
|
||||
maxtab = []
|
||||
|
||||
if x is None:
|
||||
x = arange(len(v))
|
||||
|
||||
v = asarray(v)
|
||||
|
||||
mn, mx = Inf, -Inf
|
||||
mnpos, mxpos = NaN, NaN
|
||||
|
||||
lookformax = True
|
||||
|
||||
for i in arange(len(v)):
|
||||
this = v[i]
|
||||
if this > mx:
|
||||
mx = this
|
||||
mxpos = x[i]
|
||||
if this < mn:
|
||||
mn = this
|
||||
mnpos = x[i]
|
||||
|
||||
if lookformax:
|
||||
if this < mx-delta:
|
||||
maxtab.append((mxpos, mx))
|
||||
mn = this
|
||||
mnpos = x[i]
|
||||
lookformax = False
|
||||
else:
|
||||
if this > mn+delta:
|
||||
mx = this
|
||||
mxpos = x[i]
|
||||
lookformax = True
|
||||
|
||||
return array(maxtab)
|
||||
|
||||
########################################################################
|
||||
|
||||
def findsignals(candidates):
|
||||
# input and output as [ [strength, strength, strength], [freq, freq, freq] ]
|
||||
sigdelta = 0.08 # adjacent peaks closer than this are collated
|
||||
|
||||
# remove the center false spike before analysis
|
||||
cf = sdr.center_freq / 1e6
|
||||
|
||||
# there's probably a more pythonic way to do this
|
||||
# but I'm just a humble C programmer
|
||||
for i in range(len(candidates[1])):
|
||||
if candidates[1][i] > (cf - (sigdelta/2)) and candidates[1][i] < (cf + (sigdelta/2)) :
|
||||
candidates[0][i] = 0.0
|
||||
|
||||
# find local peaks
|
||||
max = peakdet(candidates[0],.0001) # empirical - adjust as desired
|
||||
# (make it smaller if you're looking for faint, wide signals)
|
||||
|
||||
signals = []
|
||||
prevfreq = 0.0
|
||||
|
||||
# collate adjacent peaks
|
||||
for i in max:
|
||||
if candidates[1][i[0]] - prevfreq < sigdelta:
|
||||
# leans right rather than left
|
||||
# (a cool person would perfectly center it?)
|
||||
del(signals[-1])
|
||||
signals.append([i[1], candidates[1][i[0]]])
|
||||
prevfreq = candidates[1][i[0]]
|
||||
|
||||
return signals
|
||||
|
||||
########################################################################
|
||||
|
||||
signals = []
|
||||
|
||||
if len(sys.argv) != 3:
|
||||
exit("usage: peakfinder.py 88.0 110.0")
|
||||
|
||||
start = float(sys.argv[1])
|
||||
end = float(sys.argv[2])
|
||||
if start <= 0 or end <= 0:
|
||||
exit("error: bad arguments")
|
||||
|
||||
if end < start:
|
||||
exit("error: end < start")
|
||||
|
||||
freq = start
|
||||
|
||||
while(freq <= end):
|
||||
sdr.center_freq = freq * 1e6
|
||||
freq += 2.2 # this number was picked empirically to avoid overlap on my device
|
||||
samples = sdr.read_samples(256*1024)
|
||||
# plot the spectrum
|
||||
results = psd(samples, NFFT=1024, Fs=sdr.sample_rate/1e6, Fc=sdr.center_freq/1e6)
|
||||
|
||||
signals.extend(findsignals(results))
|
||||
|
||||
|
||||
# print just the frequency part
|
||||
print "++++++++++"
|
||||
for i in signals:
|
||||
print "%.2f" % i[1]
|
||||
print "++++++++++"
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user