Using FPGAs for Spectrum Sensing and Modulation Recognition
Project Objective
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.
Who We Are
Reading Material
- Overview of FPGA architecture (especially for Xilinx devices), and comparison between FPGA and CPU
- Overview of I/Q Communication Theory
- Artificial WiFi Packet Generation
- Matched Filter Demodulation
Week 1 Activities
- Get ORBIT/COSMOS account and familiarize oneself with the testbed procedures
- Learn about FPGAs
- Presentation 1
Week 2 Activities
- Write a UDP client / server in Go
- Generate IQ samples for IEEE 802.11 WiFi packets
- Presentation 2
Week 3 Activities
- Rework UDP client / server to work with Go to Verilog compiler
- Transmit and receive generated WiFi packets using the USRPs on the Grid
- Presentation 3
Week 4 Activities
- Automate data collection on the Grid
- Learn more about Go lang
- Presentation 4
Week 5 Activities
- Begin looking in to matched filters
- Finish data collection on the Grid (a lot of debugging)
- Presentation 5
Week 6 Activities
- Matched Filters in MATLAB
- Collect data
- Presentation 6
Week 7 Activities
- Dataset documentation / Big metadata file
- Matched Filters in Go
- Presentation 7
Final Presentation
Poster
WiFi Packet Generation
% 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
Experiment Automation
# 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 }
Random Number Generation with LFSR
// 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 = "" } }}
Matched Filter
% 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
Last modified
4 years ago
Last modified on Jul 30, 2020, 4:32:05 AM
Attachments (15)
- Presentation 1.pdf (420.0 KB ) - added by 5 years ago.
- Presentation 2.pdf (471.2 KB ) - added by 5 years ago.
- Presentation 3 6_17.pdf (566.9 KB ) - added by 4 years ago.
- Presentation 4 6_25.pdf (508.8 KB ) - added by 4 years ago.
- Presentation 5 7_2.pdf (412.3 KB ) - added by 4 years ago.
- Picture1.jpg (4.2 KB ) - added by 4 years ago.
- Picture2.png (38.5 KB ) - added by 4 years ago.
- Picture3.jpg (4.5 KB ) - added by 4 years ago.
- Presentation 6 7_9.pdf (415.1 KB ) - added by 4 years ago.
- Presentation 7 7_16.pdf (449.8 KB ) - added by 4 years ago.
- Picture2.jpg (3.5 KB ) - added by 4 years ago.
- Artificial WiFi Packet Dataset For Modulation Recognition.pdf (212.9 KB ) - added by 4 years ago.
- Final Presentation 9 7_30.pdf (1009.2 KB ) - added by 4 years ago.
- UFSSMR Poster.pptx.png (704.2 KB ) - added by 4 years ago.
- UFSSMRPoster.pptx.png (704.2 KB ) - added by 4 years ago.
Note:
See TracWiki
for help on using the wiki.