Basic Real-time Sequence Examples
Writing a real-time 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@nivs_rt_sequence
2def call_add_two_numbers_test():
3 result = DoubleValue(0)
4 result.value = add_two_numbers(1, 2)
5 if result.value != 3:
6 generate_error(-100, "Unexpected result", ErrorAction.ContinueSequenceExecution)
The function also takes in some parameters. You must define parameters using the niveristand.NivsParam
decorator.
1@NivsParam("x", DoubleValue(0), NivsParam.BY_VALUE)
2@NivsParam("y", DoubleValue(0), NivsParam.BY_VALUE)
3@nivs_rt_sequence
4def add_two_numbers(x, y):
5 result = DoubleValue(0)
6 # There is an intentional mistake here. It multiplies when the function implies it adds.
7 result.value = x.value * y.value
8 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 try:
2 call_add_two_numbers_test()
3 except RunError as run_error:
4 print("Something Non-deterministic went wrong:" + str(run_error))
5
Or, you can run the test deterministically on the VeriStand engine connected to your system.
1 try:
2 realtimesequencetools.run_py_as_rtseq(call_add_two_numbers_test)
3 except RunError as run_error:
4 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.
1import os
2from examples.engine_demo.engine_demo_basic import run_engine_demo
3from niveristand import run_py_as_rtseq
4from niveristand.errors import RunError
5from niveristand.legacy import NIVeriStand
6
7
8def mix_legacy_and_rtseq_run():
9 """Combines the legacy API with Python real-time sequences to run a deterministic test."""
10 # Ensures NI VeriStand is running.
11 NIVeriStand.LaunchNIVeriStand()
12 NIVeriStand.WaitForNIVeriStandReady()
13 # Uses the ClientAPI interface to get a reference to Workspace2
14 workspace = NIVeriStand.Workspace2("localhost")
15 engine_demo_path = os.path.join(
16 os.path.expanduser("~public"),
17 "Documents",
18 "National Instruments",
19 "NI VeriStand 2019",
20 "Examples",
21 "Stimulus Profile",
22 "Engine Demo",
23 "Engine Demo.nivssdf",
24 )
25 # Deploys the system definition.
26 workspace.ConnectToSystem(engine_demo_path, True, 120000)
27 try:
28 # Uses Python real-time sequences to run a test.
29 run_py_as_rtseq(run_engine_demo)
30 print("Test Success")
31 except RunError as e:
32 print("Test Failed: %d - %s" % (int(e.error.error_code), e.error.message))
33 finally:
34 # You can now disconnect from the system, so the next test can run.
35 workspace.DisconnectFromSystem("", True)
36
37
38if __name__ == "__main__":
39 mix_legacy_and_rtseq_run()
Array operations example
1@nivs_rt_sequence
2def array_operations():
3 """
4 Shows operations you can perform with array data types in a real-time sequence.
5
6 An array can hold multiple values of the same data type. You cannot have arrays of arrays.
7 Use arrays to pass buffers of data for playback or storage.
8
9 Returns:
10 float: sum of all values in the array.
11
12 """
13 var = DoubleValue(0)
14 arr_size = I64Value(0)
15 array = DoubleValueArray([0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100])
16
17 # Indexes a value out of an array.
18 var.value = array[4].value + 100
19 # Updates a value in an array.
20 array[2].value = 6.0
21 # Gets the size of an array.
22 arr_size.value = arraysize(array)
23 # Loops over each element of an array. Each time the loop iterates a value from the array is copied into x.
24 var.value = 0.0
25 for x in array:
26 var.value += x
27 return var.value
Measuring elapsed time example
1@nivs_rt_sequence
2def measure_elapsed_time():
3 """
4 Shows different ways to measure elapsed time in a sequence.
5
6 You can measure time in milliseconds, microseconds, or seconds.
7
8 Returns:
9 int: time, in milliseconds, it took to run this sequence.
10
11 """
12 seqtime_timer = DoubleValue(0)
13 seqtime_us_timer = I64Value(0)
14 tick_ms_timer = I64Value(0)
15 tick_us_timer = I64Value(0)
16
17 # The following steps demonstrate different ways you can capture an initial timestamp:
18 seqtime_timer.value = seqtime()
19 seqtime_us_timer.value = seqtimeus()
20 tick_ms_timer.value = tickcountms()
21 tick_us_timer.value = tickcountus()
22
23 # Simulates work to time.
24 while iteration() < 1000:
25 nivs_yield()
26
27 # Measures the elapsed time by subtracting the initial timestamp from the current time.
28 seqtime_timer.value = seqtime() - seqtime_timer.value
29 seqtime_us_timer.value = seqtimeus() - seqtime_us_timer.value
30 tick_ms_timer.value = tickcountms() - tick_ms_timer.value
31 tick_us_timer.value = tickcountus() - tick_us_timer.value
32
33 return tick_ms_timer.value
State machine
1@nivs_rt_sequence
2def state_machine_example():
3 state = I32Value(0)
4 iters = I32Value(0)
5 amplitude = DoubleValue(1000)
6 stop = BooleanValue(False)
7 output = ChannelReference("Aliases/DesiredRPM")
8
9 while (
10 stop.value != True # noqa: E712 NI recommends you use comparison instead of identity.
11 and iters.value < 10
12 ):
13 state.value = rand(7)
14 if state.value == 0:
15 wait(2)
16 elif state.value == 1:
17 sine_wave(output, amplitude, 1, 0, 0, 2)
18 elif state.value == 2:
19 square_wave(output, amplitude, 5, 0, 0, 50, 2)
20 elif state.value == 3:
21 triangle_wave(output, amplitude, 1, 0, 0, 2)
22 elif state.value == 4:
23 uniform_white_noise_wave(output, amplitude, tickcountus(), 2)
24 elif state.value == 5:
25 ramp(output, -amplitude.value, amplitude, 2)
26 elif state.value == 6:
27 sawtooth_wave(output, amplitude, 1, 0, 0, 2)
28 else:
29 stop.value = True
30 iters.value += 1
31 state.value = rand(7)