The brand-new PN400 Phase Noise Test System is available for purchase! →

SignalHoundUser

Forum Replies Created

Viewing 4 posts - 1 through 4 (of 4 total)
  • Author
    Posts
  • in reply to: VSG60 AWGN using Python Example #244768
    SignalHoundUser
    Participant

    What do you mean by sync level?

    I haven’t tried or done any experiments on time synchronisation. With the current setup there is a definate lag between changing the power levels of each signal. This could be related to the length of the arm waveform.

    My next steps will be to add Crest Factor Reduction to improve the PAPR and hopefully improve the signal quality at higher power levels.

    in reply to: VSG60 AWGN using Python Example #244506
    SignalHoundUser
    Participant

    Thanks Andrew,

    Got it working now. I think it was down to the power requirements for running 2 VSGs from one hub on my dev laptop. I successfully got it working yesterday with 1 VSG and 1 SM200 running from the same usb3 hub. And the other vsg plugged into a seperate port. The SM200 is not bus powered.

    All works fine now. I hope to try 5 devices today.

    in reply to: VSG60 AWGN using Python Example #244472
    SignalHoundUser
    Participant

    Forum wont allow .py files. Hopefully the txt will work.

    # -*- coding: utf-8 -*-

    # This example generates a basic AWGN signal.

    from vsgdevice.vsg_api import *
    from time import sleep
    import matplotlib.pyplot as plt
    #numpy.set_printoptions(threshold=numpy.inf) #Use to print full length arrays

    def plot_complex_fft(complex_data, sampling_rate):
    # Calculate and plot the Frequency data
    # Calculate FFT
    fft_result = numpy.fft.fft(complex_data)
    fft_freq = numpy.fft.fftfreq(len(complex_data), 1 / sampling_rate)
    # print(fft_freq)
    # Plot the results
    plt.figure(figsize=(10, 6))

    # Plot the frequency-domain signal (FFT)
    plt.plot(fft_freq, numpy.real(fft_result), color=’red’, label=’I Data’)
    plt.plot(fft_freq, numpy.imag(fft_result), color=’blue’, label=’Q Data’)
    # plt.plot(numpy.abs(fft_result))
    plt.title(‘FFT of Complex Signal’)
    plt.xlabel(‘Frequency (Hz)’)
    plt.ylabel(‘Amplitude’)

    plt.show()

    def plot_IQ(complex_data, sampling_rate):
    # Plot the Time Series results
    plt.figure(figsize=(10, 6))
    # Separate the real and imaginary parts
    I_data = numpy.real(complex_data)
    Q_data = numpy.imag(complex_data)
    # Plot the frequency-domain signal (FFT)
    plt.plot(I_data, color=’red’, label=’I Data’)
    plt.plot(Q_data, color=’blue’, label=’Q Data’)

    # plt.plot(numpy.abs(fft_result))
    plt.title(‘Complex Signal’)
    plt.xlabel(‘Samples’)
    plt.ylabel(‘Amplitude’)

    plt.show()

    def low_pass_filter(complex_data: numpy.ndarray, BW: int = 40e6, sampling_rate: int = 50e6) -> numpy.ndarray:
    # translate bandlimit from Hz to dataindex according to sampling rate and data size
    bandlimit_index = int(BW * (complex_data.size/2) / sampling_rate)
    fsig = numpy.fft.fft(complex_data)

    for i in range(bandlimit_index + 1, len(fsig) – bandlimit_index):
    fsig[i] = 0

    adata_filtered = numpy.fft.ifft(fsig)

    return adata_filtered

    def normalise_level(complex_data):
    # Normalise average level to 0dB
    aveSig = numpy.average(numpy.abs(complex_data))
    aveSigdB = 20*numpy.log10(aveSig) # should be 0dB
    print(“Normalised Signal dB = ” + str(aveSigdB))
    complex_data *= 1/aveSig
    aveSig = numpy.average(numpy.abs(complex_data))
    aveSigdB = 20*numpy.log10(aveSig) # should be 0dB
    print(“Normalised Signal dB = ” + str(aveSigdB))

    return complex_data

    def interleaved_to_complex(interleaved_data):
    # Reshape the interleaved data into a complex array
    complex_data = interleaved_data[0::2] + 1j * interleaved_data[1::2]
    return complex_data

    def complex_to_interleaved(complex_data):
    # Separate the real and imaginary parts
    real_parts = numpy.real(complex_data)
    imag_parts = numpy.imag(complex_data)

    # Interleave the real and imaginary parts
    interleaved_iq = numpy.empty(2 * len(complex_data), dtype=numpy.float32)
    interleaved_iq[0::2] = real_parts
    interleaved_iq[1::2] = imag_parts

    return interleaved_iq

    def complex_AWGN(length, stddev):

    iq = numpy.random.normal(0, stddev, length) + 1j * \
    numpy.random.normal(0, stddev, length) # .astype(numpy.float32)
    return iq

    def generate_iq():
    # Open device

    ret = vsg_open_device()
    print(ret)
    handle = ret[“handle”]

    serialNumber = vsg_get_serial_number(handle)[“serial”]

    # Configure generator
    freq = 1.0e9 # Hz
    sample_rate = 50.0e6 # samples per second
    BW = 40.0e6 # Target bandwidth of AWGN
    level = -20.0 # dBm

    vsg_set_frequency(handle, freq)
    vsg_set_level(handle, level)
    vsg_set_sample_rate(handle, sample_rate)
    vsg_recal(handle)

    # Gernerate Waveform
    iq = complex_AWGN(16384, 100)
    iq = low_pass_filter(iq, BW, sample_rate)
    iq = normalise_level(iq) #Set IQ to 0dB
    iq = complex_to_interleaved(iq)

    vsg_repeat_waveform(handle, iq.astype(numpy.float32), int(len(iq)/2))
    print(“Waveform set”)

    # Ramp Power
    for power in range(-100, -30, 5):

    vsg_set_level(handle, power)
    print(“Power = ” + str(power))
    scaling = vsg_get_IQ_scale(handle)[“iq_scale”]
    print(“scaling = ” + str(scaling))
    sleep(1)
    print(“complete”)
    # Stop waveform
    vsg_abort(handle)

    # Done with device
    vsg_close_device(handle)
    print(“closed”)

    if __name__ == “__main__”:
    generate_iq()

    in reply to: Stacked Sweep Plots [SPIKE FEATURE REQUEST] #164970
    SignalHoundUser
    Participant

    Thanks Andrew

Viewing 4 posts - 1 through 4 (of 4 total)