Jump to content
  • 0

Generating Burst Signals from Wavegen Using Code


Mona

Question

Hi,

I'm using using Digilent Analog Discovery 2. I'm trying to generate a sine wave signal for a period of time and then shut it off using the Arbitrary Wave Generator (AWG). I am able to do it in the waveforms software using Independent or Synchronized signal states as explained in the help section below

image.png.dc8d333e266ad6e8f770ffbbc1a946b2.png

However, I'm unable to replicate the same signal using my python code. I'm relying on the sdk provided on the github repository: https://github.com/Digilent/WaveForms-SDK-Getting-Started-PY/tree/master/WF_SDK

One approach I tried was to turn on the wavegen for a period of time then close it and record the signal as shown below

device_data=device.open()

scope.open(device_data, sampling_frequency= 60e6, amplitude_range = 1)

wavegen.generate(device_data, channel=1, function=wavegen.function.sine, offset=0, frequency=50e3, amplitude=1)

scope.trigger(device_data, enable=True, source=scope.trigger_source.analog, channel=1, level=0.5)

sleep(0.0006)

wavegen.close(device_data)
wave1, time1, s = scope.record(device_data, channel=1)

This approach didn't work though. The scope gets stuck in the while loop in the record function indicating that triggering didn't happen correctly. 

Is there another way to generate burst signals using code? I looked in the SDK Reference Manual but couldn't find anything. 

 

Thank you,

Mona

Link to comment
Share on other sites

6 answers to this question

Recommended Posts

  • 1

Hi @Mona

Ok, that clears it up, thanks for the answers.

Before I show you my solution: a bit of context.

There are several ways to control the DWF devices from Python.

(1) Most examples provided by Digilent access the DWF functionality via direct use of the Python ctypes module, allowing you to access all available functionality. This is however quite cumbersome and error-prone. Your Python code will not look nice, and error handling is a headache.

(2) Partially to improve this, Digilent provides the "WF_SDK" library, which you have been using. Personally, I feel it's not very well done. Also, it just supports a number of preconceived use cases, while the strength of the DWF devices is that they can do many (more) interesting things.

(3) The third option is to use a third-party Python package. There are at least two, one of which you can find here, which is not being actively maintained as far as I know, and the other is the pydwf package that I myself developed and maintain. You can find its documentation and installation notes here; installation should be as simple as "pip install pydwf". What the pydwf package does is give access to the full API, like option (1), but the functionality is wrapped in a much friendlier interface, and error handling is done using exceptions. The way I like to think about it, is that pydwf is the Python support that Digilent should have implemented, but unfortunately didn't.

Because I think (3) is the best option (I'm biased of course), I will show you what a solution to your problem looks like when using pydwf.

Here's a self-contained program that does what you need:

"""Configure the Analog Discovery to produce a fixed-duration sine on a single channel,
   under control of a software trigger."""

import time

from pydwf import DwfLibrary, DwfAnalogOutNode, DwfAnalogOutFunction, DwfTriggerSource, DwfState
from pydwf.utilities import openDwfDevice

dwf = DwfLibrary()

with openDwfDevice(dwf) as device:

    # Select a channel. Channel numbering starts at zero, so this is the first channel.
    channel = 0

    # Reset the select channel prior to configuration.
    device.analogOut.reset(channel)

    # Configure the Carrier node of the selected channel to output a 1 kHz sine, ±200 mV.
    node = DwfAnalogOutNode.Carrier
    device.analogOut.nodeFunctionSet(channel, node, DwfAnalogOutFunction.Sine)
    device.analogOut.nodeFrequencySet(channel, node, 1000.0)
    device.analogOut.nodeAmplitudeSet(channel, node, 0.200)
    device.analogOut.nodeEnableSet(channel, node, True)

    # Configure the selected channel to run for 0.5 seconds.
    device.analogOut.runSet(channel, 0.5)

    # Configure the channel to repeat indefinitely,
    # and to wait for a software trigger each time before starting.
    device.analogOut.triggerSourceSet(channel, DwfTriggerSource.PC)
    device.analogOut.repeatSet(channel, 0)
    device.analogOut.repeatTriggerSet(channel, True)

    # Start the channel. This will arm the device to wait for a software trigger.
    device.analogOut.configure(channel, True)

    # Everything is now set up.
    # Enter the trigger/signal generation loop.
    while True:

        # Wait until the channel is in the "Armed" state, i.e, all set to start signal generation.
        while device.analogOut.status(channel) != DwfState.Armed:
            time.sleep(0.010)

        # Ask the user what to do: quit, or trigger the waveform generation.
        user_input = input("Type 'q' or 'quit' to stop, anything else to trigger ... ")

        if user_input in ('q', 'quit'):
            # User wants to quit.
            break

        # User wants to generate a short sine, so trigger the device.
        # The device will go into "Triggered" mode, and enter "Armed" mode after the
        # fixed duration is complete.

        device.triggerPC()
        print("Generating a fixed-duration sine ...")

    print("Bye!")

 

If you don't like to take a dependency on pydwf, you could implement this functionality using direct ctypes-based calls, i.e., the method (1) discussed above. This would be a 1-to-1 translation (because there is a 1-to-1 correspondence between the low-level API offered by the DWF library and the API provided by pydwf). But I can already promise you that the code will look rather cryptic and will be littered with all kinds of ctypes-specific idiom that is necessary but generally unhelpful to the problem you want to solve.

So, in short: I recommend you abandon your efforts using WF_SDK, and give pydwf a try instead.

Edited by reddish
Link to comment
Share on other sites

  • 0

Hi @Mona


It is not clear to me what precisely you are trying to do. So I will first ask some questions:

* You want to do analog-out generation on a single channel, or on both channels?

* The signal itself should be a plain sine with a fixed frequency, right? If you want two channels, do you want to control their relative phase (eg one channel with a sine, the second with a cosine?)

* The start of this signal output, will that be done by software, or using some external hardware trigger? If the latter, what does your trigger look like?

* Is my understanding correct that you want this signal to be stopped after a predetermined amount of time (independent of external inputs)?

* Do you want to do this once, or do you want to re-arm your device to do the same output sequence again (with perhaps another external trigger)? Or perhaps with a fixed interval of silence between successive signal bursts?

Cheers Sidney

 

Edited by reddish
Link to comment
Share on other sites

  • 0

Hi @reddish,

 

Here are the answers to your questions:

* I want to do analog-out generation on a single channel.

* Yes, the signal itself should be a plain sine wave with a fixed frequency. I don't need two channels. 

* The start of the signal is done through code by enabling the wave generator. The burst signal is the input signal to my system so it's not dependent on external sources. 

* Yes, your understanding is correct. I want this signal to be stopped after a predetermined amount of time (independent of external inputs).

* I only need the burst signal once. I don't need it to be repeated.

 

Thank you,

Mona

Link to comment
Share on other sites

  • 0

Hey @attila, I have seen you post around on here so often you must know the answer to this.

Im doing something very similar to what you are doing in the script sent above, but in c#. I am looking to use PC triggering to handle all of our pulse sends into the Analog Discovery, but I am seeing some strange results with combining PC triggering with a trigger repeat, and a non-zero value for  AnalogOutRepeatSet.

If I set repeat to 0 for AnalogOutRepeatSet, my state after triggering always returns back to ARMED. If I set it to a 5 for example, the state will return to armed 5 times, before going back to DONE.

What I am trying to achieve is to triggerpc once, and have my wave be sent 5 times(without having to call trigger each time), and then to be able to call triggerpc again and have another 5 waves sent.

Any idea how I could achieve this?

Thanks in advance!

Edited by HasNoCreek
Link to comment
Share on other sites

  • 0

Hi @HasNoCreek

You can set the run time to be 5 times the pulse length so the pulse will output 5 times during one run step.
The trigger PC is useful to synchronize multiple internal/external instruments. If the only task is to generate the pulses you can start the AWG for each burst with the config function.

On 5/16/2023 at 12:33 PM, attila said:

image.png

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...