Support and Documentation
Breadcrumbs

Waveform Generation (App Note)

Overview

LabJack DAQ devices offer several methods for generating waveforms, ranging from simple software commands to high-speed hardware streaming. Each method provides a different balance of update rate, timing precision, and implementation complexity. This app-note explores these options to help you select the best approach for your application.

Hardware Bandwidth Limitations

Before we talk about how to get output updates to happen when desired, first consider whether the hardware can handle the signal frequency you want.

Digital output is pretty simple (very fast), but for analog output first determine if the bandwidth of the DAC (digital to analog converter, or analog output) hardware can handle your desired maximum signal frequency.  As of this writing, -3 dB cutoff frequencies are as follows:

-3 dB cutoff frequency

U3

16 Hz

U6

500 Hz

T4

159 kHz *

T7

40 kHz

T8

30 kHz *

*The device cannot output a signal this quickly. This is the cutoff frequency which was calculated by measuring the time constant.

If the hardware can handle the signal frequency you want, the next question is whether you can update the DAC fast enough to build your desired waveform.  You need to determine your required DAC update rate.  Take the max signal frequency you want to make, and multiply it by how many updates per cycle you require (i.e. how "smooth" you need the signal to be).  For example, if you want to build a 10 Hz sine wave using 50 updates per cycle, that would require 500 updates per second.

Software Timing (Command-Response)

The most straightforward method is Command-Response mode, where your software sends a single command to update an output and waits for a confirmation.

  • Performance: On a U3 with a high-speed USB connection, a DAC update takes approximately 0.6 ms (~1,600 updates/second).

  • Limitations: While the hardware is fast, the timing is dictated by your computer's Operating System. Because Windows, macOS, and Linux are not "Real-Time" operating systems, software loops often experience unpredictable delays (jitter).

  • Best For: Low-frequency signals (typically <10 Hz) where a perfectly smooth shape and precise timing between every single point are not critical.

Stream Out (T7 and T8)

Both the T7 and T8 support Stream Out, a feature designed for high-speed, hardware-timed updates to outputs like the DACs or DIO. Values are stored in a FIFO buffer on the device and clocked out by the internal hardware, eliminating the timing jitter associated with software communication.

  • Performance: The max rate is device specific.

    • T7 can update a single DAC at up to 100 kHz

    • T8 supports up to 40 kHz

  • Limitations: Requires more software implementation than the other waveform generation options. Software will need to configure and manage Stream Mode. For non-looping "random" waveforms, the host computer must continuously stream data to the device's buffer.

  • Best For: High-speed waveforms (kilohertz range), phase-perfect periodic signals (sine/arbitrary), or complex "random" sequences that must be output with precision.

For implementation details and multi-channel rates, see 3.2.3 Stream Out [T-Series Datasheet].

Scripting (T-series)

The T-series devices support on-board Lua scripting. This allows you to write code that runs directly on the device's processor, eliminating the communication overhead between the computer and the LabJack.

  • Performance: Can achieve update rates in the low kilohertz range. While significantly faster and more deterministic than Command-Response, it is not as fast as Stream Out.

  • Limitations: Limited to the T-series. Scripts share processing resources with other device functions, and the Lua environment has memory constraints for very large waveforms.

  • Best For: Applications that require autonomous operation (no computer connected), simple logic-based waveform changes (e.g., "if AIN0 > 2V, start sine wave"), or medium-speed updates where you want to avoid the complexity of Stream Mode.

For more information and examples, see the Lua Scripting Guide.

Square or Rectangular Output (Timers and DIO-EF)

For continuous square waves, PWM, or rectangular pulses, you can use the hardware-based Timers (U3/U6) or DIO-EF (T-series). These features use the device’s internal clock to toggle digital lines at precise intervals with minimal CPU or software intervention.

  • Performance: Capable of very high frequencies (into the MHz range depending on the device). It provides the most stable timing of any method for digital signals.

  • Limitations: Limited to square/rectangular shapes. While an RC filter can smooth a square wave into a approximation of a sine, the amplitude is fixed by the hardware logic levels which are typically 0 and 3.3V.

  • Best For: PWM control, clock generation, or producing a specific number of pulses (using Stop Mode on U3/U6 or Pulse Out on T-series).

The LabJack's native digital output is 3.3V. To output higher voltages (like 5V, 12V, or 24V), there are a couple of options:

  • For 5V, we recommend LJTick_OutBuff.

  • For 1.8V, 2.5V, or more current drive at 3.3V, we recommend the LJTick-LVDigitalIO.

  • For other voltages, use a digital output to control an external switch—such as a MOSFET or transistor—to gate the desired voltage from an external supply.

For setup details, see the Timers on U3/U6 or DIO-EF on a T-series section of your specific device's datasheet.

WAIT Technique (U3, U6, T-series)

The WAIT method is Good for short bursts of data points. To use the WAIT method, send a single packet to the device with multiple commands that are executed in sequence. Typical commands would be write DO, write DAC, read AIN, and WAIT, where WAIT is a user-controllable delay.  Using this technique you have the normal command-response delay to send the packet and read the response (on the order of 1 millisecond), but the multiple commands within the packet are executed in hardware without any communication delays.

The U3 and U6 have low-level IOTypes WaitShort (U3/U6) and WaitLong (U3/U6).  These can be combined with other commands in a low-level Feedback packet.  The UD driver uses both of these, but to the user presents a single IOType LJ_ioPUT_WAIT (U3/U6).  This IOType can be combined with others in a single packet using the Add/Go/Get technique (U3/U6).  The value range you can pass to LJ_ioPUT_WAIT is 0-4000000 microseconds, and the resolution is 128 µs on a U3 and 64 µs on a U6.  To determine how many commands can be fit in a single packet on the U3/U6, consider that the low-level Feedback packet has room for 57 bytes of data in the command and 55 bytes of data in the response.  Section 5.2.5 of either User's Guide (U3/U6) specifies the command and response bytes needed for each IOType.

The T-series devices have a register WAIT_US_BLOCKING (UINT32 starting at address 61590).  Pass a value to wait, in microseconds, from 0-100000.  The resolution is 1 µs, but there can be a few µs of occasional jitter due to other higher priority things happening in the processor.  If this wait is placed between 2 other commands, which is typical, there will be an extra ~10 µs of delay between the commands due to the normal time to process each command.  Writes to this register can be combined with writes/reads of other registers in a single Modbus TCP packet.  With the LJM Library, you would typically use LJM_eWriteNames or LJM_eNames, but either way LJM will send a Modbus Feedback function to the device.  The maximum packet size of a single packet for a T-series device is 64/1040/500 bytes for USB/Ethernet/WiFi, respectively.  You can combine multiple WAITs to get more than 100 ms delay, but keep each packet to less than 250 ms total to avoid a device reset caused by the internal watchdog timer.  This technique might also be useful within a Lua script.