Overview of pydwf

Warning

Important Notice

Following Digilent’s decision in October 2023 to require creation of a login account to download the Waveforms software and the accompanying library that is needed to use their measurement devices, I decided to suspend my work on pydwf indefinitely. There will be no support for new features, no bug fixes, and no more user support from me either via Digilent’s user forum or via other channels.

The primary reason for this is that I consider it unethical to sell a hardware device that requires accompanying software downloads if those software downloads require a mandatory login account, given that account creation (1) requires mandatory acceptance of Terms and Conditions that were not part of the original hardware sale; and (2) requires the user to register personally identifiable data.

I realize that these kinds of unsavory practices are pervasive in the brave new world of modern technology, but my motivation to add value for such devices in my free time is precisely zero.

So for the time being (and probably forever, since I don’t expect Digilent to reverse course), version 1.1.19 will be the last pydwf release. It is essentially identical to version 1.1.18, with this notice prominently added.

Digilent used to be a pretty cool engineering-first company, providing very nice FPGA development boards and their excellent-value Analog Discovery devices. Unfortunately, their original customer oriented reputation is rapidly deteriorating by adopting customer-unfriendly practices, probably as a result of their acquisition by National Instruments back in 2013. It is all very unfortunate.

Winding down pydwf

  • I have taken the Github repository private on 18 October 2023 to prevent uncoordinated forks.

  • I am considering what to do with the existing pydwf packages on PyPI and the documentation on ReadTheDocs. For now they will remain, but at some point in the future I may remove them.

Given all this, if you are considering using pydwf for new projects: I’d advice against it.

If you have a dependency on pydwf, this may be a good time to consider ways to cut that dependency.

I apologise for the inconvenience.

All core pydwf functionality is made available for import from the top-level pydwf package:

A small number of convenience functions and types have been implemented on top of the core pydwf package to simplify often-recurring tasks. These can be found in the pydwf.utilities package.

A minimal example of pydwf usage

In practice, Python scripts that use pydwf will deal almost exclusively with just two classes: DwfLibrary and DwfDevice.

The following is a minimal example of using pydwf that uses both of these classes to produce a 1 kHz tone on the first analog output channel:

"""A minimal, self-contained example of using pydwf."""

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

dwf = DwfLibrary()

with openDwfDevice(dwf) as device:

    CH1 = 0  # Analog-out channel numbering starts at zero.
    node = DwfAnalogOutNode.Carrier

    device.analogOut.reset(CH1)

    device.analogOut.nodeEnableSet(CH1, node, True)
    device.analogOut.nodeFunctionSet(CH1, node, DwfAnalogOutFunction.Sine)
    device.analogOut.nodeFrequencySet(CH1, node, 1000.0)

    # Start the channel.
    device.analogOut.configure(CH1, True)

    input("Producing a 1 kHz tone on CH1. Press Enter to quit ...")

With this example in mind, we can introduce the all-important DwfLibrary and DwfDevice classes.

The two main pydwf classes

As a pydwf user, you will interact directly with two classes: DwfLibrary and DwfDevice. We shortly summarize what they do here. They each have their own more comprehensive sections later on.

The DwfLibrary class

The DwfLibrary class represents the loaded Digilent Waveforms shared library itself, and provides methods that are not specific to a particular previously opened device. Examples include querying the library version, enumeration of devices, and opening a specific device for use.

Typically, a script will instantiate a single DwfLibrary and use that instance to open a specific Digilent Waveforms device, yielding a DwfDevice instance that can be used for the task at hand. This is also what happens in the example shown above.

A DwfLibrary instance provides a small number of top-level methods. It also provides some attributes that provide access to further functionality:

  • deviceEnum provides device enumeration functionality;

  • deviceControl provides functionality to open a single device and to close all previously opened devices;

  • spectrum provides functionality for signal processing.

In most programs, the DwfLibrary class is only used to open a device for use, optionally selecting a specific device configuration. Since this is such an often-occurring operation, pydwf provides the pydwf.utilities.openDwfDevice() convenience function that handles several practical use-cases, such as opening a specific device by its serial number, and/or selecting a device configuration that maximizes the buffer size for a certain instrument.

A comprehensive description of the DwfLibrary class and its attributes can be found here.

The DwfDevice class

The DwfDevice class represents a specific Digilent Waveforms device, such as an Analog Discovery 2 or a Digital Discovery, connected to the computer.

Instances of DwfDevice are obtained either by calling on of the low-level DeviceControl.open() or DeviceControl.openEx() methods, or by calling the higher-level, more powerful pydwf.utilities.openDwfDevice() convenience function.

The DwfDevice class provides several miscellaneous methods, but the bulk of its functionality is accessible via one of the attributes listed below:

  • analogIn provides a multi-channel oscilloscope;

  • analogOut provides a multi-channel analog signal generator;

  • analogIO provides voltage, current, and temperature monitoring and control;

  • analogImpedance provides measurement of impedance and other quantities;

  • digitalIn provides a multi-channel digital logic analyzer;

  • digitalOut provides a multi-channel digital pattern generator;

  • digitalIO provides static digital I/O functionality;

  • protocol.uart provides UART protocol configuration, send, and receive functionality;

  • protocol.spi provides SPI protocol configuration, send, and receive functionality;

  • protocol.i2c provides I²C protocol configuration, send, and receive functionality;

  • protocol.can provides CAN protocol configuration, send, and receive functionality;

  • protocol.swd provides SWD protocol configuration, send, and receive functionality.

After use, a Python script should close() the DwfDevice. Alternatively, the DwfDevice can act as a context manager for itself, to make sure it is closed whenever the containing with statement ends.

A comprehensive description of the DwfDevice class and its attributes can be found here.