3.2 Stream Mode [T-Series Datasheet] | LabJack
« Close

Datasheets and User Guides

App Notes

Software & Driver


3.2 Stream Mode [T-Series Datasheet]

Stream Mode Overview

Streaming is a fast data input mode. It is more complicated than command-response mode, so it requires more configuration. Using stream is simplified by the LJM stream functions; to stream without them, see 3.2.2 Low-Level Streaming.

For a given stream session, a list of channels/addresses are sampled as input to the device. This list of channels (known as a scan list) is input, as quickly as possible, immediately after a clock pulse. Stream clock pulses are hardware-timed at a constant scan rate. By default, a stream session begins scanning immediately after being started and continuously scans until stopped.

A LabJack device cannot run more than one stream session at any given time.

Command-response can be done while a stream is active, but streaming needs exclusive control of the analog input system, so analog inputs (including the internal temperature sensor) cannot be read via command-response while a stream is active.

Stream can also output data.

Stream sessions can be configured to collect a limited number of scans. (See Burst Stream)

T7 only:


The T7 supports some advanced stream features:

  • Stream sessions can be configured to delay scanning until after the T7 detects a trigger pulse.
  • Stream clock pulses can also be read externally at either a constant or a variable rate.

On This Page

Maximum Stream Speed

T4 Max Sample Rate: 40 ksamples/second


The T4 max sample rate is 40 ksamples/second. This is achievable for any single-address stream, but for a multi-address stream this is only true when resolution index = 0 or 1.

T7 Max Sample Rate: 100 ksamples/second


The T7 max sample rate is 100 ksamples/second. This is achievable for any single-address stream, but for a multi-address stream this is only true when resolution index = 0 or 1 and when range = +/-10V for all analog inputs.

The max scan rate depends on how many addresses you are sampling per scan:

  • Address => The Modbus address of one channel. (See Streamable Registers, below.)
  • Sample => A reading from one address.
  • Scan => One reading from all addresses in the scan list.
  • SampleRate = NumAddresses * ScanRate


  • For a T4 streaming 4 channels at resolution index=0, the max scan rate is 10 kscans/second (calculated from 40 ksamples/second divided by 4).
  • For a T7 streaming 5 channels at resolution index=0 and all at range=+/-10V, the max scan rate is 20 kscans/second (calculated from 100 ksamples/second divided by 5).

Ethernet provides the best throughput: Ethernet is capable of the fastest stream rates. USB is typically a little slower than Ethernet, and WiFi is much slower. For more information on speeds, see the Data Rates Appendix.

Stream-In and/or Stream-Out

There are three input/output combinations of stream mode:

Stream-in: The device collects data and streams it to the host.

Stream-out: The device does not collect data but does outputs data. See 3.2.1 Stream-Out.

Stream-in-out: The device collects data and streams it to the host. It also streams data out.

The stream channels determine which of these modes are used. Streamable channels may be either stream-in or stream-out.

Streamable Registers

The Modbus map shows which registers can be streamed (by expanding the "details" area). Input registers that can be streamed include:

  For more information
AIN# See 14.0 Analog Inputs.
FIO_STATE See 13.0 Digital I/O.
EIO_STATE See 13.0 Digital I/O.
CIO_STATE See 13.0 Digital I/O.
MIO_STATE See 13.0 Digital I/O.
FIO_EIO_STATE See 13.0 Digital I/O.
EIO_CIO_STATE See 13.0 Digital I/O.
CIO_MIO_STATE See 13.0 Digital I/O.
DIO#(0:22) See 13.0 Digital I/O.
DIO#(0:22)_EF_READ_A See 13.2 DIO Extended Features.
DIO#(0:22)_EF_READ_A_AND_RESET See 13.2 DIO Extended Features.
DIO#(0:22)_EF_READ_B See 13.2 DIO Extended Features.
CORE_TIMER See 4.0 Hardware Overview.
SYSTEM_TIMER_20HZ See 4.0 Hardware Overview.

For stream-out registers, see 3.2.1 Stream-Out.

16-bit or 32-bit Data

Stream data is transferred as 16-bit values, but 32-bit data can be captured by using STREAM_DATA_CAPTURE_16:

Name Start Address Type Access

STREAM_DATA_CAPTURE_16             If a channel produces 32-bits of data the upper 16 will be saved here.

4899 UINT16 R

16-bit: In the normal case of an analog input such as AIN0, the 16-bit binary value is actually is what is transferred. LJM converts it to a float on the host using the calibration constants that LJM reads before starting the stream. To read binary AIN stream data, enable the LJM configuration LJM_STREAM_AIN_BINARY by setting it to 1.

32-bit: Some streamable registers (e.g. DIO4_EF_READ_A) have 32-bit data. When streaming a register that produces 32-bit data, the lower 16 bits (LSW) will be returned and the upper 16 bits (MSW) will be saved in STREAM_DATA_CAPTURE_16. To get the full 32-bit value, add STREAM_DATA_CAPTURE_16 to the stream scan list after any applicable 32-bit register, then combine the two values in software (LSW + 65536*MSW). Note that STREAM_DATA_CAPTURE_16 may be placed in multiple locations in the scan list.

Configuring AIN for Stream

STREAM_SETTLING_US and STREAM_RESOLUTION_INDEX control settling and resolution during stream.

Name Start Address Type Access

STREAM_SETTLING_US             Time in microseconds to allow signals to settle after switching the mux. Does not apply to the 1st channel in the scan list, as that settling is controlled by scan rate (the time from the last channel until the start of the next scan). Default=0. When set to less than 1, automatic settling will be used. The automatic settling behavior varies by device.

4008 FLOAT32 R/W

STREAM_RESOLUTION_INDEX             The resolution index for stream readings. A larger resolution index generally results in lower noise and longer sample times.

4010 UINT32 R/W

The normal AIN configuration registers for range and negative channel still apply to stream.

T7 only: Stream mode is not supported on the hi-res converter. (Resolution indices 9-12 are not supported in stream.)

Stream Timing

When using LJM, there are three ways that stream can be too slow:

  1. Sample rate is too high
  2. Device buffer overflow
  3. LJM buffer overflow

Sample rate is too high: When the sample rate is too high, it causes a STREAM_SCAN_OVERLAP error and stream is terminated.

Scans are triggered by hardware interrupts. If a scan begins and the previous scan has not finished, the device stops streaming and returns a STREAM_SCAN_OVERLAP error (errorcode 2942), which LJM returns immediately upon the next call to LJM_eStreamRead.

Device buffer overflow: When the device buffer overflows, LJM inserts a dummy sample (with the value -9999.0) in place of each skipped sample, or it causes a STREAM_AUTO_RECOVER_END_OVERFLOW error and stream is terminated.

As samples are collected, they are placed in a FIFO buffer on the device until retrieved by the host. The size of the buffer is variable and can be set to a maximum of 32768 bytes. Write to STREAM_BUFFER_SIZE_BYTES to set the buffer size. The stream buffer will be allocated within shared memory.

Name Start Address Type Access

STREAM_BUFFER_SIZE_BYTES             Size of the stream data buffer in bytes. A value of 0 equates to the default value. Must be a power of 2. Size in samples is STREAM_BUFFER_SIZE_BYTES/2. Size in scans is (STREAM_BUFFER_SIZE_BYTES/2)/STREAM_NUM_ADDRESSES. Changes while stream is running do not affect the currently running stream.

4012 UINT32 R/W

If the device buffer overflows, the device will continue streaming but will discard data until the buffer is emptied, after which data will be stored in the buffer again. The device keeps track of how many scans are discarded and reports that value. Based on the number of scans discarded, the LJM library adds the proper number of dummy samples (with the value -9999.0) such that the correct timing is maintained. This will only work if the first channel in the scan cannot return 0xFFFF.

If the device buffer overflows for too much time, a STREAM_AUTO_RECOVER_END_OVERFLOW error occurs and stream is terminated.

If the device buffer is overflowing, see the LJM stream help page for some mitigation strategies.

LJM buffer overflow: When the LJM buffer overflows, it causes a LJME_LJM_BUFFER_FULL error and stream is terminated.

LJM reads samples from the device buffer and buffers them internally. LJM reads these samples in an internal thread, regardless of what your code does. LJM's buffer can run out of space if it is not read often enough using LJM_eStreamRead, so make sure the LJMScanBacklog parameter does not continually increase.

LJM_eStreamRead blocks until enough data is read from the device, so your code does not need to perform waits.

If the LJM buffer is overflowing, see the LJM stream help page for some mitigation strategies.

Channel-to-Channel (Interchannel) Timing

Channels in a scan list are input or output as quickly as possible after the start of a scan, in the order of the scan list.

For descriptions of typical interchannel delays, see Appendix A-1 Data Rates.

Timing pulses are generated on SPC so that the channel-to-channel timing can be measured. Pulses on SPC are as follows:

  • Falling edge at the start of a scan.
  • Rising edge at the start of a sample.
  • Falling edge at the end of a sample.
  • Rising edge at the end of a scan.

Device Clock Scan Time

To calculate the time a scan was collected relative to the device clock, multiply the scan's offset from the first scan with the interval length. The interval length is the inverse of the scan rate:

TimeSinceFirstScan = Offset * (1 / ScanRate)

For example, with a 500 Hz scan rate, the 1000th scan collected is 2 seconds after the first scan, according to the device clock.

You can use STREAM_START_TIME_STAMP to relate the start of stream with other events:

Name Start Address Type Access

STREAM_START_TIME_STAMP             This register stores the value of CORE_TIMER at the start of the first stream scan. Note that the first stream scan happens 1 scan period after STREAM_ENABLE is set to 1.

4026 UINT32 R

System Clock Scan Time

With writing custom code, you can assign timestamps to each stream scan. These timestamps can be the host computer's system time (calendar time) or the steady clock (absolute) time. These timestamps are based on the computer's real-time clock rather than the device's clock.

Assigning a timestamp to each scan can be beneficial for logging and for multi-device synchronization. It can also help to correct clock drift between your system clock and the device clock.

Using this technique it is realistic that the time accuracy of every scan's timestamp is within 1 ms of your system's clock, unless suboptimal conditions apply, such as asymmetric network routes or network congestion.

Example Technique:

First, start stream. Then read the following registers using normal command-response.

Once stream is started, use STREAM_START_TIME_STAMP to determine when stream started:

Name Start Address Type Access

STREAM_START_TIME_STAMP             This register stores the value of CORE_TIMER at the start of the first stream scan. Note that the first stream scan happens 1 scan period after STREAM_ENABLE is set to 1.

4026 UINT32 R

Then read CORE_TIMER in order to correlate scan times with system host clock times:

Name Start Address Type Access

CORE_TIMER             Internal 32-bit system timer running at 1/2 core speed, thus normally 80M/2 => 40 MHz.

61520 UINT32 R

Read the CORE_TIMER and your system time quickly in a loop for e.g. five times. You can assume the CORE_TIMER value is, on average, halfway between when you begin the CORE_TIMER read and when you receive the CORE_TIMER value. Throw out any measurements that take an abnormal amount of time. (If most round-trip reads of CORE_TIMER take 1 ms and one CORE_TIMER read takes 3 ms, it's likely that either the outbound or inbound communication had an unusual delay—but unlikely that both had an equal delay.)

Next, calculate the CORE_TIMER value for each scan. Use the actual scan rate to calculate the CORE_TIMER value for each scan starting from STREAM_START_TIME_STAMP. If you're using LJM, LJM_eStreamStart returns the actual scan rate in the ScanRate parameter, which can be slightly different from the specified scan rate. If you're not using LJM, see low-level streaming.

Once you have your current system clock correlated with CORE_TIMER and each scan is assigned a CORE_TIMER value, you can convert each CORE_TIMER value into a system clock time.

Additional considerations:

  • Make sure your code handles when CORE_TIMER wraps.
  • If you're assigning wall-clock timestamps, consider what should happen when the clock skips forward or backward due to an NTP update.
  • To prevent clock drift, you must continually re-synchronize the system clock to CORE_TIMER. The T-series clock error at room temperature is 20 ppm. This is 2 ms per 100 seconds, so a re-sync of core-clock to host-clock must be done at least every 50 seconds to maintain 1 ms accuracy.
  • Check your own computer's clock specs for a source of additional clock error.

Burst Stream

Burst stream is when stream collects a pre-determined number of scans, then stops. To set the stream burst size, write to STREAM_NUM_SCANS:

Name Start Address Type Access

STREAM_NUM_SCANS             The number of scans to run before automatically stopping (stream-burst). 0 = run continuously. Limit for STREAM_NUM_SCANS is 2^32-1, but if the host is not reading data as fast as it is acquired you also need to consider STREAM_BUFFER_SIZE_BYTES.

4020 UINT32 R/W

The LJM library collects burst stream data with the StreamBurst() function.

It may be beneficial to set STREAM_BUFFER_SIZE_BYTES to a large value for fast burst stream. See above for details about STREAM_BUFFER_SIZE_BYTES.

T7-Pro only: Burst stream is well-suited for WiFi connections, because WiFi has a lower throughput than other connection types.

Externally Clocked Stream - T7 Only


Externally-clocked stream allows T-series devices to stream from external pulses. It also allows for variable stream scan rates.

Clock Source: The scan rate is generated from the internal crystal oscillator. Alternatively, the scan rate can be a division of an external clock provided on CIO3.

Name Start Address Type Access

STREAM_CLOCK_SOURCE             Controls which clock source will be used to run the main stream clock.<br>0 = Internal crystal,<br>2 = External clock source on CIO3.<br>Rising edges will increment a counter and trigger a stream scan after the number of edges specified in STREAM_EXTERNAL_CLOCK_DIVISOR. T7 will expect external stream clock on CIO3. All other values reserved.

4014 UINT32 R/W

To subdivide the external clock pulses for a slower scan rate, use STREAM_EXTERNAL_CLOCK_DIVISOR.

Name Start Address Type Access

STREAM_EXTERNAL_CLOCK_DIVISOR             The number of pulses per stream scan when using an external clock.

4022 UINT32 R/W

To use externally clocked stream with LJM, see the externally clocked stream section of the LJM  User's Guide.

Triggered Stream - T7 Only


T7 minimum firmware 1.0186

Stream can be configured to start scanning when a trigger is detected. Trigger sources are DIO_EF modes:

Frequency In and Conditional Reset allow you to select rising or falling edges and Pulse Width In will trigger from either edge.

See Appendix A for hysteresis voltage information.

Configuring stream to use a trigger requires setting up a DIO_EF and adding the STREAM_TRIGGER_INDEX register to normal stream configuration.

Name Start Address Type Access

STREAM_TRIGGER_INDEX             Controls when stream scanning will start.<br>0 = Start when stream is enabled,<br>2000 = Start when DIO_EF0 detects an edge,<br>2001 = Start when DIO_EF1 detects an edge.<br>See the stream documentation for all supported values.

4024 UINT32 R/W

STREAM_TRIGGER_INDEX (address 4024):

  • 0 = No trigger. Stream will start when Enabled.
  • 2000 = DIO_EF0 will start stream.
  • 2001 = DIO_EF1 will start stream.
  • 2002 = DIO_EF2 will start stream.
  • 2003 = DIO_EF3 will start stream.
  • 2006 = DIO_EF6 will start stream.
  • 2007 = DIO_EF7 will start stream.

The delay between the trigger and the first collected sample is one scan period.

To use triggered stream with LJM, see the triggered stream section of the LJM User's Guide.

A more complicated stream trigger can be implemented with a Lua script. For example, a Lua script could check for an arbitrary stream trigger condition in conjunction with triggered stream being started as normal. Once the Lua script detects that the stream condition is fulfilled, it writes a pulse to a digital out (such as DIO3) which is then detected by the normal trigger (as specified by STREAM_TRIGGER_INDEX).


GMcBane's picture

We are running a T7-Pro with externally clocked stream on CIO3.  The clock rate varies during the stream but never goes over a few hundred Hz.  Our code uses LJMPython, and calls eStreamRead in a loop. We are collecting one AIN channel (resolution index 4) and one digital channel.

We think we are seeing evidence of a shifting latency in the collection. For the first few seconds of the stream (though more than one eStreamRead call), the A/D seems to be responding to the external clocking signal faster.  After the stream is established,  we think we are seeing longer delays between the pulse on CIO3 and the A/D sample.

Does this make sense?  Is the implementation of the externally clocked stream such that if the T7 is busy responding to eStreamRead calls there might be more latency between clock pulse and A/D sample?  Is there some other reason that the latency between clock signal and A/D read might increase over the course of a stream that lasts a total of 30 seconds or so?  Most of the change we see occurs during the first six or so seconds, and then the latency seems to become stable.

Suggestions appreciated.


labjack support's picture

Stream is the highest priority process on the T7 (hardware interrupt). How are you measuring the delay? And how much latency are we talking about?


At the moment, my best guess is that the buffers are creating a delay in when the data is processed. The data collection should not be affected.


GMcBane's picture

We're measuring a spectral line by sweeping a laser in frequency.  The laser frequency is driven by a sinusoidal drive signal at about 0.5 Hz.  We monitor the frequency sweep with an optical etalon that produces a sudden output spike each time the frequency has changed by 75 MHz; a single sweep of the laser produces a couple hundred of these spikes.  We feed that spike into the trigger of a pulse generator that produces a 50 microsecond TTL pulse that we send to CI03 for the external clock.  

We are sending the output of the laser detector (New Focus Nirvana) to AIN1.  At the part of the laser sweep where the steepest part of the absorption line appears, the clock pulses are arriving at about 400 Hz (every 2.5 ms) and the signal voltage is changing at about 18 V/s.  This whole setup is running all afternoon, with the etalon spikes, the pulse generator, and the detector output on continuously.  For an individual experiment, we start the stream on the T7 and keep it running for 20-30 seconds, enough to collect all the samples for 10 sinusoidal sweeps of the laser.

When we then examine the A/D record, we find that the voltages recorded during the first two sweeps correspond to earlier positions on the spectral line than the later voltages, even though physically they should all be the same.  The difference is about 10 mV, which corresponds to a trigger-reading delay difference of (0.01V)(1 s/18V) = 550 microseconds.

The reason we suspect the LJ as the cause of this shift is that most of the other parts of the experiment don't start and stop with the T7 streaming, so there's no reason that they should "reset" when one set of sweeps ends and the other set begins.  But we always find that the first few sweeps seem to come from earlier pieces of the spectral line we're measuring.

The output signal from the detector goes not only to the T7 but also into a low-pass filter and then the input of an oscilloscope.  Another possibility is that if the input impedance of the T7 AIN changes when streaming starts, we have some sort of an electronic "relaxation" among the detector, the T7, and the RC characteristic of that filter.  This doesn't seem too likely since the output impedance of the detector is only about 100 ohms, but it may be worth considering.

We're a little baffled.  The answer you gave is the one I expected - streaming shouldn't affect the delay between stream clock and acquisition - but we're having a hard time coming up with other mechanisms.



labjack support's picture

I am having a hard time explaining what you are seeing. I think we should switch to a continuous stream. You can stream both AIN1 and CIO3 at up to 50 kHz and look at the transition on CIO3 to find the start of a data set. 

GMcBane's picture

Well, I'm more or less doing that, with an 8-bit scope, at 500 kHz already. 

What should the delay be between the external trigger on CIO3 and the start of the A/D acquisition? That is, how long should it take from recognition of interrupt to A/D cycle start?

What should the jitter be, given that the external triggers are not synchronized with the internal clock on the T7?  That should be at least the processor clock period; is it longer?  




labjack support's picture

The delay between the trigger and sampling the first channel in the scan list is one scan period plus some interrupt latency. So at 50 kHz the delay will be about 25 us.

You are correct about the clock synchronization. The clock is 80 MHz so it can take up to 25 ns for the transition to be noticed.


GMcBane's picture

> The delay between the trigger and sampling the first channel in the scan list is one scan period plus some interrupt latency. So at 50 kHz the delay will be about 25 us.

But with externally clocked stream, the "scan period" is not well defined.  My triggers are actually coming at variable rates that peak at about 400 Hz, but I wouldn't expect a 2.5 ms delay between trigger and acquisition.  What should the delay be in this case? 



labjack support's picture

" Well, I'm more or less doing that, with an 8-bit scope, at 500 kHz already.  "

The idea is to do a test we can easily recreate if there is a problem. In this case, we are trying to determine whether the trigger signal as seen by the T7 is offset from the data of interest.