2.4.7 - eStreamReadNoWait | LabJack
 
« Close

Datasheets and User Guides

App Notes

Software & Driver

 
Saturday/Sunday, March 28th&29th, 2020
Support: LabJack engineers available through email and chat.
Shipping: We are processing and shipping all orders.
Stock: 55/56 products in stock.
Supply Chain: Some disruptions.

2.4.7 - eStreamReadNoWait

Theoretical API

LJM_eStreamReadNoWait() is a suggested API. It is in the process of evaluation. It will likely be included in LJM 1.21.

Overview

Returns available data from an initialized and running LJM stream buffer without waiting. This is different from eStreamRead, which by default waits for all ScansPerRead of data to become available. eStreamReadNoWait has extra parameters: aDataSize and NumSamplesReturned.

Syntax

LJM_ERROR_RETURN LJM_eStreamReadNoWait(
                int Handle, 
                int aDataSize,
                double * aData, 
                int * NumSamplesReturned,
                int * DeviceScanBacklog, 
                int * LJMScanBacklog)

Parameters

Handle [in]
A device handle. The handle is a connection ID for an active device. Generate a handle with LJM_Open or LJM_OpenS.
    aDataSize [in]
    The maximum number of samples to return. Since the LabJack clock could be faster than the host computer clock, it is recommended to request more scans than are expected each time so that the application does not get behind. Watch LJMScanBacklog to determine if the application is getting behind. See Calculating aDataSize below.
    aData [out]
    An array that contains the values being read. Returns all channels interleaved. Must be large enough to hold aDataSize values. The data returned is removed from the LJM stream buffer. This is done according to first in, first out (FIFO) order.
    NumSamplesReturned [out]
    Indicates how many samples were returned in aData.
    DeviceScanBacklog [out]
    The number of scans left in the device buffer, as measured from when data was last collected from the device. DeviceScanBacklog should usually be near zero and not growing.
    LJMScanBacklog [out]
    The number of scans left in the LJM buffer, which does not include concurrent data sent in the aData array. If LJMScanBacklog is greater than 0, aDataSize limited the number of samples returned.

    Returns

    LJM errorcodes or 0 for no error.

    If LJM_eStreamReadNoWait returns an error, LJM always attempts to command the device to stop streaming. Unlike eStreamRead, eStreamReadNoWait ignores LJM_STREAM_SCANS_RETURN.

    Remarks

    Before calling this function, create a data buffer using LJM_eStreamStart. To stop stream, use LJM_eStreamStop.

    If LJM_eStreamRead gives error 1301 (LJME_LJM_BUFFER_FULL) or many -9999 values in aData, here are some strategies to help.

    eStreamReadNoWait is generally used with a read interval as timed by the host computer. The number of samples read per loop iteration will vary, but the time per loop iteration can be made consistent according to the host computer's clock.

    ScansPerRead

    eStreamReadNoWait is not directly affected by the ScansPerRead parameter of eStreamStart but you should still set ScansPerRead to a number of similar order of magnitude as the scan rate, except for low-latency applications. For example:

    ScansPerRead = ScanRate / 1000 * expectedMillisecondsPerRead

    This would generally works for all applications because ScansPerRead limits how many samples are transferred per packet to LJM. See low-latency streaming.

    Calculating aDataSize

    To calculate a good aDataSize, you can multiply the following factors together:

    Factor Example
    ScanRate, as returned from eStreamStart. 20000.00 scans per second
    NumAddresses, as passed to eStreamStart. 3 samples per scan
    The interval time in seconds. (The number of seconds per eStreamReadNoWait.) 0.5 seconds per 1 read
    A margin of error factor. This is to account for clock drift between the host clock and the device clock and to account for operating system scheduling jitter. 1.5

     

    Given the above example, aDataSize would be 45000 samples = 20000 * 3 * 0.5 * 1.5

    If there were aDataSize or less samples available when eStreamReadNoWait was called, LJMScanBacklog will be returned as 0. This should be normal.

    If LJMScanBacklog is consistently increasing in size, aDataSize and aData should be bigger, or eStreamReadNoWait should be called more frequently.

    Example

    [C/C++] Start stream with a scan rate of 10 kHz and 2 channels, calling eStreamReadNoWait approximately every 0.5 seconds.

    char ErrorString[LJM_MAX_NAME_SIZE];
    int LJMError;
    const int numAddresses = 2;
    const int aScanList[] = {0, 2}; // AIN0 and AIN1
    const int initScanRate = 10000;
    double scanRate = initScanRate;
    const int scansPerRead = initScanRate / 2;
    const int aDataSize = numAddresses * scansPerRead * 1.1;
    double aData[aDataSize];
    int DeviceScanBacklog;
    int LJMScanBacklog;
    int NumSamplesReturned;
    int iteration = 0;
    // Start stream
    // handle from LJM_Open() or LJM_OpenS()
    LJMError = LJM_eStreamStart(handle, scansPerRead, numAddresses, aScanList, &scanRate);
    if (LJMError != 0) {
        LJM_ErrorToString(LJMError, ErrorString);
        printf("LJM_eStreamStart error: %s\n", ErrorString);
    }
    else {
        printf("Stream started at %f Hz\n", scanRate);
    }
    
    for (iteration = 0; iteration < 1000; iteration++) {
        // Wait for the interval in whatever way suits your application
        MySleepFunction();
        // For the given aDataSize, this code needs to execute approximately every .5 seconds
    
        NumSamplesReturned = 0;
        LJMError = LJM_eStreamReadNoWait(handle, aDataSize, aData,
            &NumSamplesReturned, &DeviceScanBacklog, &LJMScanBacklog);
        if (LJMError != 0) {
            LJM_ErrorToString(LJMError, ErrorString);
            printf("LJM_eStreamReadNoWait error: %s\n", ErrorString);
        }
        else {
            printf("LJM_eStreamReadNoWait returned %d samples\n", NumSamplesReturned);
        }
    
        // Process the stream data in whatever way suits your application
        MyDataProcessingFunction(aData, NumSamplesReturned, DeviceScanBacklog, LJMScanBacklog);
        // aData[0] through aData[NumSamplesReturned - 1] are valid samples.
    }
    
    LJMError = LJM_eStreamStop(handle);
    if (LJMError != 0) {
        LJM_ErrorToString(LJMError, ErrorString);
        printf("LJM_eStreamStop error: %s\n", ErrorString);
    }