PHD Supervisors: John-Davis OyedumGR, Minhajur RahmanGR
Interns: Kyle FrieryUG
Faculty advisors: Prof. Narayan Mandayam
Goal: Machines in industrial environments produce significant EM noise, interfering with local communication systems. This project is attempting to identify and evaluate different mitigation strategies using SDRs.
Note: This project is largely supervised by John, however I interact with both Minhajur and John regularly. There is a counterpart project that is closely related to this project, I have linked that project's overview here.
Week 7 (7/6/26-7/9/26): This week's presentation. Previously known as run_sweep_master.py, morphed into run_sweep_quad.py this week fueled by the desire to not need to manually edit the PTX/RX values and to further automate the process of running several trials. The last two weeks let us see the necessity to optimize between our four gain variables, so this new script produces all the necessary information entirely of its own accord by setting all gain values, running transmission and reception scripts, post processing data, and outputting SNR-BER graphs by CF.
The latter half of this week allowed for a larger trial at 14 GHz, producing an even better curve at comparable SNR to our previous best, yet around three orders of magnitude lower BER. This curve however is not to our standards yet, but it is a significant step in the right direction.
Week 5/6 (6/22/26-7/2/26): This week's presentation. These two week's saw further attempts to establish our experiments baseline, or control group, of SNR-BER curves to then continue with the addition of RF noise.
Due to the nature of our hardware setup, the TX/RX receive pipeline goes as such:
[USRP-2974] --> [PiRadio] --> Over-The-Air (OTA) Transmission --> [Piradio] --> [USRP-2974]
UTX PTX PRX URX
Each bracketed elements has its own gain control that represents a factor in our transmission chain, they will be referred to as marked above. UTX are the points along our SNR-BER curve, PTX has some effects we will talk about shortly, PRX controls the overall SNR 'height' that we achieve, and URX provides minimal SNR tradeoff with improved BER as it decreases.
Due to the effects of path loss we're unable to maintain similar settings for all CFs, thus we must optimize for SNR, in doing so I produced graphs with a better overall shape for the first half, but they'd curve back up or flatten out at higher UTX gains, typically around 20-30 dB. The leading theory for this was that we were saturating our receiver either by PRX or URX, which led to the findings stated above.
As per John's suggestion, I begrudingly ran another experiment before calling it for the day, producing similar results. Coming in on Wednesday, I decided to lower PTX in an attempt to have this upward curve disappear and thankfully it improved it significantly. This led to the finding that we need to have low PTX and URX, with high PRX to produce sufficiently high SNR curves with the most consistent expected shape versus our theoretical curve for QPSK.
Week 4 (6/15/26-6/18/26): This week's presentation. After receiving Minhajur's files (UHD Python files, rather than a GNURadio implementation), I was subjected to an entire week's worth of troubleshooting, I will spare details except for two of the major inhibitors. In order to vary SNR we either increase signal or decrease noise, typically noise is inherent to an environment so the latter is typically not feasible and is something we must work around. This constraint forces us to conduct multiple trials of varying signal power, this is done by increasing transmitter (TX) gain. Thus in an attempt to simplify my workload, I took it upon myself to write a file that could automate the process of triggering the TX at a given gain value, then RX, kill the TX process, as it runs indefinitely, and move the files locally to my computer for postprocessing (Unlike GNU, UHD cannot do realtime processing).
This brings us to the first issue, before ever making that automation file, I had to validate that the code functioned. No matter the different center frequencies I would use for our high or low Local Oscillator (LO) of our PiRadio, gain values, etc. Would allow for us to receive a mean power at our highest and lowest TX gain that differed. The issue is well known and documented, however there is a slight alternate consideration based on our hardware that needed to be taken into account. The DC spike is a voltage leakage that occurs at the center frequency of your transmission, thus in OFDM the center frequency, our index 0 subcarrier, contains no information about our signal (referred to as the DC Null), it is ignored due to this large spike. This is the offset issue we encountered in Week 2, for an unknown reason the DC null at the DC spike were offset from one another, so the spike was being considered in our information and driving mean power toward a common value. An offset of about .1 GHz or 100 MHz between our UHD code's center frequency and the low LO solved this.
The second issue was that after creating the automation file, I could run the script, it would work for the first gain value, but on the second the USRP-2974 (PC + X310 via PCIe connection) would stop recognizing the X310. The solution ended up being the addition of:
print("Stopping TX stream...\n")
kill_cmd = [
"ssh", TX_NODE,
"pkill -SIGINT -f tx_ofdm_ota.py"
]
subprocess.run(kill_cmd)
time.sleep(2.0) # Give UHD time to release the USRP cleanly`
To the existing:
tx_process.terminate()
tx_process.wait()
Killing the background terminal left the TX program running in the background on the node that was transmitting and when a subsequent gain value went to initialize itself, the hardware was still being used by the previous instance. So to get around that we kill the program on the node, before starting a new instance.
Week 3 (6/8/26-6/11/26): This week's presentation. The goal of this week was to make a Signal to Noise Ratio vs Bit Error Rate (SNR vs BER) graph. This brings a few issues on capturing the data necessary to compute both values. BER is relatively easy as whatever appears first in our receive file should be the first bit of our transmit file, so this comparison can be done bit by bit and repeated across multiples samples of the received file to get a more accurate value for BER at certain SNR values. As for SNR, this requires a bit more processing in order to figure out what part of our raw received data file is actually the signal, finding said signal at the receiver can effectively be done by methods shown in OFDM reception.
I initially was under the impression that I would have to code all of these various computations, which was not the case as Minhajur already had a few months prior, but not before I already coded the BER calculator.
Week 2 (6/1/26-6/4/26): This week's presentation. This week saw me tackling the latter half of OFDM reception documentation to better understand the whole process, the link for said documentation is below in Week 1. In addition to that, with some major setbacks throughout the process, namely being unable to get GNURadio Companion to display its GUI through the terminal, the code below shows the ssh command to the console and node (we were missing the -X, which prompts GUI display from headless nodes):
ssh -X username@sb1.cosmos-lab.org
ssh -X root@sdr1-piradio
Troubleshooting steps also included, John and I's inability to get the transmitter/receiver to function properly until we were informed to offset the low Local Oscillator (LO) of the PiRadio slightly off from the center frequency of our signal. I'm a bit unsure as to why this is the case. Regardless, this allowed us to emulate OFDM transmission and reception successfully.
Week 1 (5/26/26-5/28/26): John had me review a past document for the project here. The slides broadly reviewed the making of a probabilistic noise model via the Baum-Welch Algorithm, providing a basis for the likelihood of state transitions or lack thereof. Following that, to check model accuracy two methods were used, Root Mean Square Error (RMSE) and the Earth Mover's Distance (EMD), basically these methods provide a single output to quantize whether the model can likely reproduce the empirical data gathered. From the point of an accurate model, testing of various mitigation strategies could be conducted, namely Reed Solomon Code (RSC). RSC provides a cyclical error checking method with minimal coding overhead that significantly reduced the Bit Error Rate (BER) observed.
After completion of the slide presentation, John gave me this GNURadio documentation which reviews the entirety of OFDM transmission and reception. OFDM, or Orthogonal Frequency Division Multiplexing, is a method of transforming time domain signals into the frequency domain using the Fast Fourier Transform (FFT), adding necessary error checking methods (CRC32, another cyclical error checking method) and stream tags (a means to tell the code the next packet's length), mapping it into constellation space with Binary Phase Shift Keying (BPSK), splitting it into frequency blocks and subsequent subcarriers, and finally transmitting.
Note: This is a broad overview of OFDM transmission, certain details have been left out.
Thursday mornings bring a weekly presentation and I was asked to present a little bit about myself, what I learned this week as I have described here, and what the next week brings. My presentation is linked here, please know that my project is closely entwined with another graduate student and summer intern's project, this presentation was done with the other intern, Dil Joshi.