LJM Timing Functions

Data acquisition often needs to be done at regular and precise intervals. It can also be important to check how long it took an operation to complete. For these purposes, LJM 1.1700 added the following functions:

  • Quickly set up a interval-timed loop with the interval-timing functions: LJM_StartInterval, LJM_WaitForNextInterval, and LJM_CleanInterval
  • Quickly benchmark operations or generate timestamps with the clock read functions: LJM_GetHostTick or LJM_GetHostTick32Bit

Advantages

Cross-platform

In keeping with LJM's cross-platform mandate, LJM abstracts away complicated, OS-dependent code on Windows, macOS, and Linux to allow for simple, cross-platform code.

Precise

These functions achieve high precision by internally using std::chrono::high_resolution_clock.

Steady

Never worry about changes to the system clock -- LJM uses std::chrono::steady_clock to ensure that no timing oddities can be caused (due to NTP updates, for example).

Example

The following C example sets up an interval of loop of 1 second, then reads analog input 0 (AIN0) once a second. It also times how many milliseconds each AIN0 read took.

// Initialize interval loop
const int INTERVAL_HANDLE = 1;
const int ONE_SECOND_IN_MICROSECONDS = 1000000;
err = LJM_StartInterval(INTERVAL_HANDLE, ONE_SECOND_IN_MICROSECONDS);
ErrorCheck(err, "LJM_StartInterval");

while (!done) {
    // Read analog input 0 and get a quick measurement of how long it took
    long long start = LJM_GetHostTick();
    err = LJM_eReadName(handle, "AIN0", &voltage);
    long long end = LJM_GetHostTick();
    ErrorCheck(err, "LJM_eReadName");
    printf(
        "Reading AIN0 %f V took %f milliseconds\n",
        voltage,
        (double)(end - start) / 1000
    );

    // Block waiting for the next interval period
    err = LJM_WaitForNextInterval(INTERVAL_HANDLE, &skippedIntervals);
    ErrorCheck(err, "LJM_WaitForNextInterval");
    if (skippedIntervals > 0) {
        printf("SkippedIntervals: %d\n", skippedIntervals);
    }
}

// Cleanup interval memory
err = LJM_CleanInterval(INTERVAL_HANDLE);
ErrorCheck(err, "LJM_CleanInterval");

Example output (tested using a USB connection to a T7 on macOS with default analog input configurations):

Reading AIN0 10.113891 V took 1.333000 milliseconds
Reading AIN0 10.113891 V took 1.345000 milliseconds
...

Notes

The example above assumes a device handle was previously opened.

The example above uses the function ErrorCheck() to check that no error has occurred. ErrorCheck() is defined in LJM_Utilities.h of the LJM C/C++ examples download. If the first parameter is not 0, it essentially prints the error and exits the program.

Measuring how long LJM_eReadName(..., "AIN0", ...) took means measuring how long it took LJM to construct the command packet, send the command packet, receive the response packet (e.g. how long it took the device to measure voltage on AIN0 and respond), and parse the response packet.

More Details

For more information, see the Timing Functions section of the LJM User's Guide.