This project seeks to aid the use of machine learning to recognize different wireless devices. The project will use software defined radios (SDR) to record various devices, such as iphones, bluetooth earbuds, and WiFi laptops. These recordings will become the training data to a set of neural networks. Additionally, we will be constructing a matched filter to compare its performance against the machine learning based modulation recognition.
![]() Ryan Davis Class of 2021 Rutgers University Computer Engineering and Computer Science |
![]() Zhuohuan Li Class of 2020 Rutgers University Computer Engineering |
![]() Sid Mandayam Class of 2022 Rutgers University Computer Science and Mathematics |
![]() Jacob Morin Class of 2021 Pingry High School |
|---|
* Overview of FPGA architecture (especially for Xilinx devices), and comparison between FPGA and CPU
* Overview of I/Q Communication Theory
* Artificial WiFi Packet Generation
* Get ORBIT/COSMOS account and familiarize oneself with the testbed procedures
* Learn about FPGAs
* Write a UDP client / server in Go
* Generate IQ samples for IEEE 802.11 WiFi packets
* Rework UDP client / server to work with Go to Verilog compiler
* Transmit and receive generated WiFi packets using the USRPs on the Grid
* Automate data collection on the Grid
* Learn more about Go lang
* Begin looking in to matched filters
* Finish data collection on the Grid (a lot of debugging)
* Matched Filters in MATLAB
* Collect data
* Dataset documentation / Big metadata file
* Matched Filters in Go

% Ryan Davis
PAYLOAD = 1500; % bytes
PATH = "";
for i = 0:7
filename = "WiFi_802.11n_" + i + "MCS_int16.dat";
ht = wlanHTConfig("MCS", i, "ChannelBandwidth", "CBW20");
payload = randi([0 1], [1 PAYLOAD*8]);
txSig = wlanWaveformGenerator(payload,ht);
output_txSig = formatOutput(txSig);
fid = fopen(PATH + filename, "w");
fwrite(fid, output_txSig, "int16");
fclose(fid);
end
clear;
function arr = formatOutput(txSig)
arr = zeros(size(txSig)*2);
j = 1;
for i = 1:size(txSig)
arr(j) = cast(real(txSig(i)), "int16");
arr(j+1) = cast(imag(txSig(i)), "int16");
j=j+2;
end
end
# Ryan Davis
# Adapted from code by Ivan Seskar
Experiment.name = "Artificial_WiFi"
Experiment.project = "Artificial_WiFi"
consoleExec("omf tell -t all -a offh")
consoleExec("omf load -i usrpcal_2020-02-24.ndz -t node3-2,node3-19,node8-7,node8-14,node13-7,node13-14,node18-2,node18-19,node3-1,node3-20,node18-1,node18-20 -r 0")
consoleExec("omf tell -t node3-2,node3-19,node8-7,node8-14,node13-7,node13-14,node18-2,node18-19,node3-1,node3-20,node18-1,node18-20 -a on")
freqs = ["2412e6", "2437e6", "2462e6", "5180e6", "5240e6", "5745e6", "5825e6"]
mcss = ["0", "1", "2", "3", "4", "5", "6", "7"]
topos = {"3" => [["node18-1", "node18-2"], ["node3-1", "node3-2"], ["node18-19", "node18-20"], ["node3-19", "node3-20"]], # format: dist => [["txnode_A", "rxnode_A"], ["txnode_B", "rxnode_B"] ... ]
"15" => [["node13-7", "node8-7"], ["node13-14","node8-14"]],
"45" => [["node18-1", "node3-1"], ["node18-2", "node3-2"], ["node18-19", "node3-19"], ["node18-20", "node3-20"]],
"72" => [["node18-20", "node3-1"], ["node18-1", "node3-20"]] }
defApplication('tx', 'tx_samples_from_file') { |a|
a.version(1, 0, 0)
a.shortDescription = ""
a.description = ""
a.path = "export LC_ALL=C;/usr/local/lib/uhd/examples/tx_samples_from_file"
a.defProperty('freq', "center frequency in Hz", '--freq',
{:dynamic => false, :type => :string})
a.defProperty('ant', "antenna to be used", '--subdev',
{:dynamic => false, :type => :string})
a.defProperty('rate', "baseband rate in Hz", '--rate',
{:dynamic => false, :type => :string})
a.defProperty('gain', "receiver gain in dB", '--gain',
{:dynamic => false, :type => :string})
a.defProperty('file', "reveived baseband waveform file name", '--file',
{:dynamic => false, :type => :string})
a.defProperty('type', "sample types", '--type',
{:dynamic => false, :type => :string})
a.defProperty('repeat', "continuously repeat", '--repeat',
{:dynamic => false, :type => :string})
}
defApplication('rx', 'rx_samples_to_file') { |a|
a.version(1, 0, 0)
a.shortDescription = ""
a.description = ""
a.path = "export LC_ALL=C;/usr/local/lib/uhd/examples/rx_samples_to_file"
a.defProperty('freq', "center frequency in Hz", '--freq',
{:dynamic => false, :type => :string})
a.defProperty('rate', "baseband rate in Hz", '--rate',
{:dynamic => false, :type => :string})
a.defProperty('gain', "receiver gain in dB", '--gain',
{:dynamic => false, :type => :string})
a.defProperty('nsamps', "number of samples", '--nsamps',
{:dynamic => false, :type => :string})
a.defProperty('file', "reveived baseband waveform file name", '--file',
{:dynamic => false, :type => :string})
a.defProperty('type', "sample types", '--type',
{:dynamic => false, :type => :string})
a.defProperty('discardtime', "time at which storing samples starts", '--discardtime',
{:dynamic => false, :type => :string})
}
topos.each { |dist, topo|
topo.each { |node_pair|
freqs.each { |freq|
mcss.each { |mcs|
infilename = "WiFi_802.11n_"+mcs+"_int16.dat"
exptag = dist+"ft_"+freq+"Hz_"+mcs+"MCS_"+node_pair[0]+","+node_pair[1]
outfilename = "/root/rx_"+exptag+"_int16.dat"
info("Setting up group for experiment: " + exptag)
rxGroup = node_pair[1]+"@"+exptag
txGroup = node_pair[0]+"@"+exptag
defGroup(txGroup, node_pair[0]) { |n|
n.addApplication('tx') { |app|
app.setProperty('freq', freq)
app.setProperty('ant', "A:0")
app.setProperty('gain', "30")
app.setProperty('type', "short")
app.setProperty('file', infilename)
app.setProperty('rate', "20e6")
app.setProperty('repeat'," ")
}
}
defGroup(rxGroup, node_pair[1]) { |n|
n.addApplication('rx') { |app|
app.setProperty('freq',freq)
app.setProperty('gain', "30")
app.setProperty('type',"short")
app.setProperty('nsamps',"40000000")
app.setProperty('file',outfilename)
app.setProperty('rate',"40e6")
}
}
}
}
}
}
trap("INT") {
allGroups.stopApplications
allGroups.exec("/usr/bin/pkill -9 -f rx_samples")
allGroups.exec("/usr/bin/pkill -9 -f tx_samples")
exit!
}
onEvent(:ALL_UP_AND_INSTALLED) { |event|
# Wait for nodes to associate and give it an extra 5 sec just in case...
sleep 5
# scp IQ binary file to transmitters
txfiles = "txfiles/WiFi*"
topos.each { |dist, topo|
topo.each { |node_pair|
consoleExec("ssh root@" + node_pair[0] + " rm -f /root/*.dat")
consoleExec("ssh root@" + node_pair[1] + " rm -f /root/*.dat")
consoleExec("scp -o StrictHostKeyChecking=no " + txfiles + " root@"+node_pair[0]+":");
consoleExec("scp -o StrictHostKeyChecking=no test.sh root@"+node_pair[0]+":"); # TODO temp for debugging
}
}
topos.each { |dist, topo|
topo.each { |node_pair|
freqs.each { |freq|
mcss.each { |mcs|
exptag = dist+"ft_"+freq+"Hz_"+mcs+"MCS_"+node_pair[0]+","+node_pair[1]
info ("\nStarting experiment: " + exptag)
rxGroup = node_pair[1]+"@"+exptag
txGroup = node_pair[0]+"@"+exptag
group(rxGroup).startApplications # start receiver (captures for 1 sec)
sleep 1 # make sure we do not start transmitting before receiving
group(txGroup).startApplications # start transmitter
sleep 5 # wait for applications to hopefully finish
group(txGroup).stopApplications
group(rxGroup).stopApplications
outfilename = "/root/rx_"+exptag+"_int16.dat"
consoleExec("scp -o StrictHostKeyChecking=no root@" + node_pair[1] + ":" + outfilename + " /spare/spectrum/Artificial_WiFi/") #copy recved data to archive
consoleExec("ssh root@" + node_pair[1] + " rm -f " +outfilename)
}
}
}
}
allGroups.stopApplications
Experiment.done
}
// Jacob Morin
// Call with either 1 or 3 command arguments:
// First command argument: amount of loops
// Second command argument: start
// Third command argument: end
package mainimport (
"fmt"
"os"
"strconv"
)func lfsr3(sequence chan uint8, start int, end int, repititions int) {
for i := 0; i <= repititions; i++ {
//starting value
var seed uint16 = uint16(i)
//keeps track of the value at any given time
var lfsr uint16 = seed //number of times it takes for the lfsr to revert to its start state
var period int = 0
//last bit of lfsr
var value uint16 = 0
//number of 0's in lfsr
var numZeros int = 0
//number of 1's in lfsr
var numOnes int = 0 stop := false
//until LFSR goes back to its start state (stop will become true)
for stop != true {
//increments count
period++ //shifts
lfsr ^= lfsr >> 7 //7 right
lfsr ^= lfsr << 9 //9 left
lfsr ^= lfsr >> 13 //13 right if (period > start) && (period < end) {
//adds last bit to sequence
value = lfsr & 1
if value == 0 {
numZeros++
sequence <- 0
}
if value == 1 {
numOnes++
sequence <- 1
}
} //if LFSR reaches startState, make stop true to exit the loop
if lfsr == seed {
stop = true
}
} }}func main() { //makes channel for the random number
sequence := make(chan uint8) //command line
args := os.Args
len := len(args) //first argument in command line determines how many times to loop
if len > 1 {
repititions, err := strconv.Atoi(args[1])
if err != nil {
fmt.Println("error")
}
// assumed values
start := 6000
end := 7000 // second argument in command line overrides start
// third argument in command line overrides end
if len > 3 {
y, err := strconv.Atoi(args[2])
if err != nil {
fmt.Println("error")
}
start = y z, err := strconv.Atoi(args[3])
if err != nil {
fmt.Println("error")
}
end = z
}
//calls function
go lfsr3(sequence, start, end, repititions) printSequence := ""
//Call lfsr3 'repitions' number of times
for i := 1; i <= repititions; i++ {
//number of values per sequences
for j := 0; j < 999; j++ {
//receives and prints value
value := <-sequence
printSequence += strconv.Itoa(int(value))
} fmt.Println("At", i, "got random number:", printSequence, "\n")
printSequence = ""
}
}}
% Zhuohuan Li
% Sid Mandayam
antenna = phased.IsotropicAntennaElement('FrequencyRange',[5e9 15e9]);
transmitter = phased.Transmitter('Gain',20,'InUseOutputPort',true);
fc = 10e9;
target = phased.RadarTarget('Model','Nonfluctuating',...
'MeanRCS',1,'OperatingFrequency',fc);
txloc = [0;0;0];
tgtloc = [5000;5000;10];
transmitterplatform = phased.Platform('InitialPosition',txloc);
targetplatform = phased.Platform('InitialPosition',tgtloc);
[tgtrng,tgtang] = rangeangle(targetplatform.InitialPosition,...
transmitterplatform.InitialPosition);waveform = phased.RectangularWaveform('PulseWidth',25e-6,...
'OutputFormat','Pulses','PRF',10e3,'NumPulses',1);
c = physconst('LightSpeed');
maxrange = c/(2*waveform.PRF);
SNR = npwgnthresh(1e-6,1,'noncoherent');
Pt = radareqpow(c/fc,maxrange,SNR,...
waveform.PulseWidth,'RCS',target.MeanRCS,'Gain',transmitter.Gain);transmitter.PeakPower = Pt;radiator = phased.Radiator('PropagationSpeed',c,...
'OperatingFrequency',fc,'Sensor',antenna);
channel = phased.FreeSpace('PropagationSpeed',c,...
'OperatingFrequency',fc,'TwoWayPropagation',false);
collector = phased.Collector('PropagationSpeed',c,...
'OperatingFrequency',fc,'Sensor',antenna);
receiver = phased.ReceiverPreamp('NoiseFigure',0,...
'EnableInputPort',true,'SeedSource','Property','Seed',2e3);
filter = phased.MatchedFilter(...
'Coefficients',getMatchedFilter(waveform),...
'GainOutputPort',true);wf = waveform();
[wf,txstatus] = transmitter(wf);
wf = radiator(wf,tgtang);
wf = channel(wf,txloc,tgtloc,[0;0;0],[0;0;0]);
wf = target(wf);
wf = channel(wf,tgtloc,txloc,[0;0;0],[0;0;0]);
wf = collector(wf,tgtang);
rx_puls = receiver(wf,~txstatus);
[mf_puls,mfgain] = filter(rx_puls);
Gd = length(filter.Coefficients)-1;mf_puls=[mf_puls(Gd+1:end); mf_puls(1:Gd)]; % main line of matched filter
subplot(2,1,1)
t = unigrid(0,1e-6,1e-4,'[)');
rangegates = c.*t;
rangegates = rangegates/2; % end with this lineplot(rangegates,abs(rx_puls))
title('Received Pulse')
xlabel('Meters')
ylabel('Amplitude')
hold on
plot([tgtrng, tgtrng], [0 max(abs(rx_puls))],'r')
subplot(2,1,2)
plot(rangegates,abs(mf_puls))
title('After Matched Filter')
xlabel('Meters')
ylabel('Amplitude')
hold on
plot([tgtrng, tgtrng], [0 max(abs(mf_puls))],'r')
hold off