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:
the
DwfLibrary
class, which is the starting point for all pydwf functionality;the
PyDwfError
andDwfLibraryError
exceptions;the enumeration types that are used for parameters and result values of pydwf methods.
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.