Basic Examples

Writing a sequence

A Python real-time sequence is a Python function decorated with the niveristand.nivs_rt_sequence decorator. For example, the following sequence calls a function and checks the result.

1
2
3
4
5
6
@nivs_rt_sequence
def call_add_two_numbers_test():
    result = DoubleValue(0)
    result.value = add_two_numbers(1, 2)
    if result.value != 3:
        generate_error(-100, "Unexpected result", ErrorAction.ContinueSequenceExecution)

The function also takes in some parameters. You must define parameters using the niveristand.NivsParam decorator.

1
2
3
4
5
6
7
8
@NivsParam('x', DoubleValue(0), NivsParam.BY_VALUE)
@NivsParam('y', DoubleValue(0), NivsParam.BY_VALUE)
@nivs_rt_sequence
def add_two_numbers(x, y):
    result = DoubleValue(0)
    # There is an intentional mistake here. It multiplies when the function implies it adds.
    result.value = x.value * y.value
    return result.value

You can now run the test just like any other Python function. You can run it non-deterministically, as in the following example:

1
2
3
4
5
    try:
        call_add_two_numbers_test()
    except RunError as run_error:
        print("Something Non-deterministic went wrong:" + str(run_error))

Or, you can run the test deterministically on the VeriStand engine connected to your system.

1
2
3
4
    try:
        realtimesequencetools.run_py_as_rtseq(call_add_two_numbers_test)
    except RunError as run_error:
        print("Something Deterministic went wrong:" + str(run_error))

Combining the legacy API with real-time sequences

To create a fully-automated test environment, you can mix the Legacy API with Python real-time sequences.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import os
from examples.engine_demo.engine_demo_basic import run_engine_demo
from niveristand import run_py_as_rtseq
from niveristand.errors import RunError
from niveristand.legacy import NIVeriStand


def mix_legacy_and_rtseq_run():
    """Combines the legacy API with Python real-time sequences to run a deterministic test."""
    # Ensures NI VeriStand is running.
    NIVeriStand.LaunchNIVeriStand()
    # Uses the ClientAPI interface to get a reference to Workspace2
    workspace = NIVeriStand.Workspace2("localhost")
    engine_demo_path = os.path.join(os.path.expanduser("~"), 'Documents', 'National Instruments', 'VeriStand 2018',
                                    'Examples', 'Stimulus Profile', 'Engine Demo', 'Engine Demo.nivssdf')
    # Deploys the system definition.
    workspace.ConnectToSystem(engine_demo_path, True, 60000)
    try:
        # Uses Python real-time sequences to run a test.
        run_py_as_rtseq(run_engine_demo)
        print("Test Success")
    except RunError as e:
        print("Test Failed: %d -  %s" % (str(e.error.error_code), e.error.message))
    finally:
        # You can now disconnect from the system, so the next test can run.
        workspace.DisconnectFromSystem('', True)


if __name__ == '__main__':
    mix_legacy_and_rtseq_run()

Array operations example

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@nivs_rt_sequence
def array_operations():
    """
    Shows operations you can perform with array data types in a real-time sequence.

    An array can hold multiple values of the same data type. You cannot have arrays of arrays.
    Use arrays to pass buffers of data for playback or storage.

    Returns:
        float: sum of all values in the array.

    """
    var = DoubleValue(0)
    arr_size = I64Value(0)
    array = DoubleValueArray([0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100])

    # Indexes a value out of an array.
    var.value = array[4].value + 100
    # Updates a value in an array.
    array[2].value = 6.0
    # Gets the size of an array.
    arr_size.value = arraysize(array)
    # Loops over each element of an array. Each time the loop iterates a value from the array is copied into x.
    var.value = 0.0
    for x in array:
        var.value += x
    return var.value

Measuring elapsed time example

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@nivs_rt_sequence
def measure_elapsed_time():
    """
    Shows different ways to measure elapsed time in a sequence.

    You can measure time in milliseconds, microseconds, or seconds.

    Returns:
        int: time, in milliseconds, it took to run this sequence.

    """
    seqtime_timer = DoubleValue(0)
    seqtime_us_timer = I64Value(0)
    tick_ms_timer = I64Value(0)
    tick_us_timer = I64Value(0)

    # The following steps demonstrate different ways you can capture an initial timestamp:
    seqtime_timer.value = seqtime()
    seqtime_us_timer.value = seqtimeus()
    tick_ms_timer.value = tickcountms()
    tick_us_timer.value = tickcountus()

    # Simulates work to time.
    while iteration() < 1000:
        nivs_yield()

    # Measures the elapsed time by subtracting the initial timestamp from the current time.
    seqtime_timer.value = seqtime() - seqtime_timer.value
    seqtime_us_timer.value = seqtimeus() - seqtime_us_timer.value
    tick_ms_timer.value = tickcountms() - tick_ms_timer.value
    tick_us_timer.value = tickcountus() - tick_us_timer.value

    return tick_ms_timer.value

State machine

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@nivs_rt_sequence
def state_machine_example():
    state = I32Value(0)
    iters = I32Value(0)
    amplitude = DoubleValue(1000)
    stop = BooleanValue(False)
    output = ChannelReference('Aliases/DesiredRPM')

    while stop.value != True and iters.value < 10:  # noqa: E712 NI recommends you use comparison instead of identity.
        state.value = rand(7)
        if state.value == 0:
            wait(2)
        elif state.value == 1:
            sine_wave(output, amplitude, 1, 0, 0, 2)
        elif state.value == 2:
            square_wave(output, amplitude, 5, 0, 0, 50, 2)
        elif state.value == 3:
            triangle_wave(output, amplitude, 1, 0, 0, 2)
        elif state.value == 4:
            uniform_white_noise_wave(output, amplitude, tickcountus(), 2)
        elif state.value == 5:
            ramp(output, -amplitude.value, amplitude, 2)
        elif state.value == 6:
            sawtooth_wave(output, amplitude, 1, 0, 0, 2)
        else:
            stop.value = True
        iters.value += 1
        state.value = rand(7)