Skip to main content

InstroAWG

Unstable APIInstroAWG ships in the instro-unstable package. Its API is not settled and may change without notice between releases. Install it with pip install "instro[unstable]". See Unstable modules for details.
InstroAWG is a hardware abstraction layer (HAL) that provides a unified interface for arbitrary waveform generators. The category class defines the vendor-independent API (set_waveform, set_amplitude, get_offset, …). A vendor-specific driver (e.g. RigolDG1022Z) owns its connection details and translates those calls into vendor commands.

Supported Vendors

  • Rigol: DG1022Z (DG1000Z series) via SCPI/VISA (RigolDG1022Z)
If your vendor or model is not listed, see Custom Driver Development below.

Key Concepts

Driver Composition

An InstroAWG is built from a concrete driver:
  • RigolDG1022Z owns the connection setup and vendor-specific command mapping.
  • InstroAWG owns the category-level workflow: waveform programming, publishers, the background daemon.

Lifecycle

The typical InstroAWG workflow:
  1. Construct: instantiate the vendor driver and pass it to InstroAWG, along with the channel count.
  2. open(): establishes the VISA connection.
  3. Configure and generate: define a waveform on a channel, set its amplitude and offset, and enable the output.
  4. start(): begins a periodic background daemon that polls output state. (Optional)
  5. stop(): ends the background daemon (if started).
  6. close(): disconnects from hardware.

Waveform Definitions

Each channel is programmed with a Waveform, one of the frozen dataclasses in instro.unstable.awg: Each definition validates its own parameters at construction time (raising ValueError for out-of-range values), so a Waveform is always well-formed before it reaches a driver.
Driver support variesNot every driver supports every waveform or every parameter combination. For example, RigolDG1022Z raises ValueError for a nonzero Pulse.delay_s, since the DG1000Z command set has no pulse-delay parameter. Consult your instrument’s manual and driver implementation for exact support.

Amplitude Units and Conversion

Amplitude is set and read together with an AmplitudeMeasurementUnit: VPP, VP, VRMS, or DBM. Use convert_amplitude() to convert a value between units for a channel’s currently configured waveform:
VPP/VP/VRMS conversions depend on the waveform’s crest factor (shared math, not vendor-specific). Converting to or from DBM additionally requires the load impedance driving the output: pass impedance_ohms explicitly, or let it fall back to the channel’s get_output_load() value if the driver supports it. set_waveform must be called for the channel before converting, since the crest factor depends on the waveform shape.

Creating an InstroAWG Instance

Parameters

  • name: A name for this AWG instance. Used as a prefix for channel names when publishing.
  • driver: A concrete AWGDriverBase instance (e.g. RigolDG1022Z) configured with the connection details for that model.
  • num_channels: Number of output channels on the instrument. Must be at least 1.
  • publishers: Optional list of publishers to attach.
  • **kwargs: Additional keyword arguments become default tags when using a publisher that supports tags (like NominalCorePublisher).

Choosing a Driver

Choose the concrete driver that matches the AWG model, then pass the instrument connection settings to that driver. For Rigol DG1000Z series generators, use RigolDG1022Z with the VISA resource string for the instrument. To inspect a VISA instrument’s identity before choosing a driver:

Examples

All measurement methods return Measurement objects. This is common amongst all Instrument objects.

Basic Usage

Background Daemon for Continuous Monitoring

In this mode:
  • start() begins a background daemon, executing a function or list of functions periodically.
  • stop() ends the background daemon.
Default AWG Background DaemonFor each :
  • Output enabled state (via get_output_state())
The default polling interval is 1 second, configurable via the background_interval property. Other readbacks (get_offset(), get_output_load(), waveform parameters) are opt-in: call add_background_daemon_function() to add them to the daemon’s call list.start() raises ValueError unless set_waveform() has been called for at least one channel first.
Custom Background Daemon
  • To define your own background daemon, call define_background_daemon(method, *args, **kwargs), which replaces the registered daemon functions.
  • To add a method to the background daemon stack, call add_background_daemon_function().
See Two ways to get data for more information regarding background fetching of measurements.
Important Note about PublishersData is published as a direct result of an instrument method being called.For example, when you call get_output_state(), this not only queries the instrument for the output state but also causes all attached Publishers to publish the measurement response automatically.Therefore the background daemon, when calling these instrument methods, is publishing data in the background as well!

Published channels

Every measurement/command call produces a channel keyed under {name}.{descriptor}, where {name} is the constructor argument and {descriptor} is the row below. Substitute {N} with the actual channel number (1, 2, …).

Method Reference


Custom Driver Development

This section is for developers implementing InstroAWG support for waveform generators that aren’t supported out of the box.

Overview

Driver developers subclass AWGDriverBase and own whatever transport their instrument needs. The caller chooses a concrete driver, and that concrete driver exposes connection parameters that make sense for its protocol:
The driver is responsible for translating InstroAWG’s vendor-independent API (set_waveform, set_amplitude, get_offset, …) into vendor-specific commands.

Driver Responsibilities

An AWG driver must:
  1. Expose a protocol-native constructor: accept inputs like visa_resource, host, port, unit_id, interface, or node_id, depending on the instrument.
  2. Own transport setup: create and store the transport internally. Do not require users to pass a VisaDriver, socket client, Modbus client, or other transport object.
  3. Own lifecycle: implement open() and close() by opening and closing the underlying transport.
  4. Map commands: translate each abstract method into vendor-specific commands, raising ValueError for a Waveform definition the instrument can’t produce.
  5. Parse responses: convert instrument responses to the expected Python types (float, bool, Waveform subclasses).

AWGDriverBase Interface

All AWG drivers subclass AWGDriverBase and implement these abstract methods:
Two methods are optional and raise NotImplementedError by default, for drivers whose instrument doesn’t support them:
Error checking is not part of the base contract beyond check_errors(): if your vendor exposes an error queue, implement check_errors() to drain and raise on it (see the representative driver below).

Talking to the Instrument

Concrete drivers should hide transport details behind private attributes. For VISA-backed drivers, create a VisaDriver internally and use it for all I/O:
  • self._visa.write(command): Send a SCPI command (no response expected).
  • self._visa.query(command): Send a SCPI query and receive the response string.
VisaDriver owns the resource lock. Concurrent write / query calls against the same driver are serialized automatically; use self._visa.lock() to hold the lock across a multi-command sequence (for example, programming an Arbitrary waveform point-by-point). See the VisaDriver guide for the full transport reference, covering configuration, terminators, timeouts, serial settings, and the raw-byte I/O path.

Implementation Example: Rigol DG1022Z Driver

Here’s the driver implementation for the Rigol DG1022Z (DG1000Z series) two-channel arbitrary waveform generator:
Vendor SCPI VariationsDifferent AWG vendors use different SCPI command sets and support a different subset of waveform shapes. Always consult your instrument’s programming manual for the correct SCPI syntax and validate unsupported combinations with ValueError rather than sending malformed commands.
USB arbitrary downloads on some Rigol DG1000Z unitsSome DG1000Z-series units (observed on a DG1062Z, firmware 03.01.12) hang when downloading volatile arbitrary waveform data over USB, regardless of client (including Rigol’s own reference examples). If set_waveform() with an Arbitrary waveform hangs on your unit, try a LAN (TCPIP::...::INSTR) connection instead of USB, or update the instrument firmware. This is an instrument firmware issue, not a driver bug.

Using a Custom Driver

For drivers that aren’t shipped in the library, construct InstroAWG with your own driver instance. The driver should accept connection settings directly and create its transport internally:

Summary

Driver development requires careful mapping of vendor-specific behavior to the unified InstroAWG interface. Focus on:
  • Subclassing AWGDriverBase
  • Designing a constructor around natural connection parameters for the instrument
  • Hiding transport construction inside the driver
  • Implementing all abstract methods on AWGDriverBase, and the optional load/phase methods your instrument supports
  • Raising ValueError for Waveform definitions and parameter combinations the instrument can’t produce
  • Using the correct vendor protocol or command syntax
  • Converting instrument responses to the expected Python types
  • Implementing check_errors() against your vendor’s error queue or status register
  • Testing with actual hardware to ensure commands work as expected