Hi all,
I’m currently working on trying use the LimeSDR as a Gen2 Class 1 RFID reader, through GNU Radio, using this library. I’ve been having an issue with a strange sine wave on my RX which keeps getting partially cut-off. My hardware setup is a the Lime TX (BAND1) goes into a directional coupler; the output of this coupler (no attenuation from the TX) goes to an antenna with an RFID tag next to it; an attenuated part of the signal from the antenna then goes into the RX. A picture of the strange cut-off sine wave is below:
The above looks like a sawtooth, but it is in fact (I believe), a small section of a sinewave which gets cut-off, the amplitude set back low, and the sinewave starts up again - I will explain why I believe this shortly. Initially, I didn’t realise that this was the first part of a sinewave, and so I believed the problem was the same as in this thread , where someone else had a sawtooth-like oscillation, and the problem was resolved by bypassing the DC corrector in the LMS7002M. However, I tried the fixes mentioned in the thread and they didn’t seem to make any difference.
The above picture was taken with a DAC sampling rate of 1 MHz, and an ADC sampling rate of 2 MHz. Interestingly, I found that if I reduced the DAC and ADC sampling rates by the same factor, I could see a greater proportion of the sine-wave. The picture below shows the same code running with the DAC and ADC sampling rates reduced by a factor of 10:
(Note that the tall vertical lines are the modulation which I am actually trying to carry out using the RFID library); when the reader is not modulating, the waveform should just be a constant amplitude carrier wave i.e. a flat horizontal line)
It’s not a problem with the RFID library - i have a colleague using the same library successfully with a USRP device without any issues.
I did some tests trying to just do AM of a sinewave. I found an interesting result: When my DAC rate was equal to the modulating sinewave (yes I know that this will cause aliasing issues, which leads to me believe that the main problem is somehow related to aliasing) there was the same kind of oscillation as described above. However, if the ADC and DAC rates were increased by even 1%, the weird oscillation completely disappeared. Unfortunately for the RFID script, increasing the ADC and DAC rates did not alleviate the weird oscillation.
The problem doesn’t seem to be there in either the TX or RX channels individually; I viewed the TX waveform on a spectrum analyser, and it looked normal, without the strange oscillations. Similarly, I input a signal from an RFID test device into the RX (through an attenuator), with the TX disconnected (coupled into an antenna), and the RX picked up a reasonable signal, with no sign of any strange behaviour.
The above all leads me to believe that there is something strange going on in the interaction between the TX and RX; it feels like the sinusoid that is getting cut off is some kind of beat frequency resulting from some clocks which should be at the same frequency not quite being aligned, and they get cut off because their amplitude goes too high. That is probably complete rubbish though - I’m not yet intimately familiar with the inner workings of the LMS7002M.
Another strange signal that I often get is what is below:
This is again when attempting to run the RFID script, this time running at 100 kHz DAC and 200 kHz ADC. It doesn’t always appear though, and at higher sampling frequencies sometimes the waveform will start like this, and then abruptly transition into the waveform which the main problem that I am describing (i.e. the partially cut-off sine wave).
Anybody have any thoughts? This problem has been plaguing me for quite some time now and is slowly driving me insane…
A few details about my setup:
Using the latest versions of GNURadio, SoapySDR, and gr-osmosdr, all pulled from master (built from source)
Using the ‘stable’ branch of Limesuite
Note that I was having a latency issue, so in the SoapyLMS7 drivers in Limesuite, I forced the config.performanceLatency = 1 in the setupStream function in Streaming.cpp. Commenting out these changes didn’t affect the above.
I’m using a new USB3.1-PCIe card connected to a PCIexpress port on my computer (but switching between this and one of the normal USB3.0 ports on my computer makes no difference). I initially suspected a power issue, but tried with both an external power supply, and now with the new USB3.1-PCIe card, without either making a difference, so I am confident it is not a power issue.
The GNU Radio code I am running is the following:
from gnuradio import eng_notation
from gnuradio import gr
from gnuradio import blocks
from gnuradio import filter
from gnuradio.eng_option import eng_option
from gnuradio.filter import firdes
from optparse import OptionParser
from gnuradio import analog
from gnuradio import digital
import osmosdr
import sip
import sys
import time
import rfid
class reader_top_block(gr.top_block):
def __init__(self):
gr.top_block.__init__(self)
rt = gr.enable_realtime_scheduling()
######## Variables #########
self.dac_rate = 1e6 # DAC rate
self.adc_rate = 100e6/50 # ADC rate (2MS/s complex samples)
self.decim = 5 # Decimation (downsampling factor)
self.ampl = 0.1 # Output signal amplitude (signal power vary for different RFX900 cards)
self.freq = 910e6 # Modulation frequency (can be set between 902-920)
self.rx_gain = 0 # RX Gain (gain at receiver)
self.tx_gain = 0 # RFX900 no Tx gain option
# Each FM0 symbol consists of ADC_RATE/BLF samples (2e6/40e3 = 50 samples)
# 10 samples per symbol after matched filtering and decimation
self.num_taps = [1] * 25 # matched to half symbol period
######## File sinks for debugging (1 for each block) #########
self.file_sink_source = blocks.file_sink(gr.sizeof_gr_complex*1, "../misc/data/source", False)
self.file_sink_matched_filter = blocks.file_sink(gr.sizeof_gr_complex*1, "../misc/data/matched_filter", False)
self.file_sink_gate = blocks.file_sink(gr.sizeof_gr_complex*1, "../misc/data/gate", False)
self.file_sink_decoder = blocks.file_sink(gr.sizeof_gr_complex*1, "../misc/data/decoder", False)
self.file_sink_reader = blocks.file_sink(gr.sizeof_float*1, "../misc/data/reader", False)
######## Blocks #########
self.matched_filter = filter.fir_filter_ccf(self.decim, self.num_taps)
self.gate = rfid.gate(int(self.adc_rate/self.decim))
self.tag_decoder = rfid.tag_decoder(int(self.adc_rate/self.decim))
self.reader = rfid.reader(int(self.adc_rate/self.decim),int(self.dac_rate))
self.amp = blocks.multiply_const_ff(self.ampl)
self.to_complex = blocks.float_to_complex(1)
# Osmocom blocks
self.u_source = osmosdr.source(args="numchan=" + str(1) + " " + 'driver=lime,soapy=0' )
self.u_source.set_sample_rate(self.adc_rate)
self.u_source.set_center_freq(self.freq, 0)
self.u_source.set_freq_corr(0, 0)
#self.u_source.set_dc_offset_mode(0, 0)
self.u_source.set_iq_balance_mode(0, 0)
self.u_source.set_gain_mode(True, 0)
self.u_source.set_gain(self.rx_gain, 0)
self.u_source.set_if_gain(10, 0)
self.u_source.set_bb_gain(10, 0)
self.u_source.set_antenna("LNAL", 0)
self.u_source.set_bandwidth(0, 10000000)
self.u_sink = osmosdr.sink(args="numchan=" + str(1) + " " + 'driver=lime,soapy=0' )
self.u_sink.set_sample_rate(self.dac_rate)
self.u_sink.set_center_freq(self.freq, 0)
self.u_sink.set_freq_corr(0, 0)
self.u_sink.set_gain(self.tx_gain, 0)
self.u_sink.set_if_gain(10, 0)
self.u_sink.set_bb_gain(10, 0)
self.u_sink.set_antenna("BAND1", 0)
self.u_sink.set_bandwidth(0, 10000000)
######## Connections #########
self.connect(self.u_source, self.matched_filter)
self.connect(self.matched_filter, self.gate)
self.connect(self.gate, self.tag_decoder)
self.connect((self.tag_decoder,0), self.reader)
self.connect(self.reader, self.amp)
self.connect(self.amp, self.to_complex)
self.connect(self.to_complex, self.u_sink)
self.connect(self.u_source, self.file_sink_source)
self.connect(self.gate, self.file_sink_gate)
self.connect((self.tag_decoder,1), self.file_sink_decoder) # (Do not comment this line)
self.connect(self.reader, self.file_sink_reader)
self.connect(self.matched_filter, self.file_sink_matched_filter)
if __name__ == '__main__':
main_block = reader_top_block()
main_block.start()
while(1):
inp = raw_input("'Q' to quit \n")
if (inp == "q" or inp == "Q"):
break
main_block.reader.print_results()
main_block.stop()
I’ve ordered a new USB3 cable which should be arriving on Monday.