Examples

Device Discovery

This example demonstrates how to asynchronously discover compatible devices on all available interfaces. The first discovery is done without extended information, so it is faster, while the second discovery includes extended information about the devices, which takes longer.

 1import asyncio
 2from nv200.device_discovery import discover_devices, DiscoverFlags
 3
 4
 5# async Main execution
 6async def main_async():
 7    """
 8    Asynchronously discovers available devices and prints their information.
 9    """
10    print("\nDiscovering devices...")
11    devices = await discover_devices()
12    
13    if not devices:
14        print("No devices found.")
15    else:
16        print(f"Found {len(devices)} device(s):")
17        for device in devices:
18            print(device)
19
20    print("\nDiscovering devices with extended information...")
21    devices = await discover_devices(DiscoverFlags.ALL_INTERFACES | DiscoverFlags.READ_DEVICE_INFO)	
22    
23    if not devices:
24        print("No devices found.")
25    else:
26        print(f"Found {len(devices)} device(s):")
27        for device in devices:
28            print(device)
29
30
31# Running the async main function
32if __name__ == "__main__":
33    asyncio.run(main_async())
34

The output of the above example can look like this:

Discovering devices...
Found 4 device(s):
Telnet @ 192.168.101.3 (MAC: 00:80:A3:5A:7F:CB)
Telnet @ 192.168.101.2 (MAC: 00:80:A3:79:C6:1E)
Telnet @ 192.168.101.4 (MAC: 00:80:A3:6F:60:F5)
Serial @ COM5 - SPI Controller Box

Discovering devices with extended information...
Found 4 device(s):
Telnet @ 192.168.101.4 (MAC: 00:80:A3:6F:60:F5) - NV200/D_NET - {'actuator_name': 'PSH15SG_Y   ', 'actuator_serial': '123910'}
Telnet @ 192.168.101.2 (MAC: 00:80:A3:79:C6:1E) - NV200/D_NET - {'actuator_name': 'PSH20       ', 'actuator_serial': '123910'}
Telnet @ 192.168.101.3 (MAC: 00:80:A3:5A:7F:CB) - SPI Controller Box
Serial @ COM5 - SPI Controller Box

Serial Connection

The example below demonstrates how to establish a serial connection to the NV200/D Compact Amplifier. Because no serial port is specified, the library will automatically search for available serial ports and connect to the first one it finds.

 1import asyncio
 2from nv200.nv200_device import NV200Device
 3from nv200.shared_types import TransportType
 4from nv200.connection_utils import connect_to_single_device
 5
 6
 7async def ethernet_auto_detect():
 8    """
 9    Automatically detects and establishes an Ethernet connection to the first detected device using Telnet.
10    """
11    device = await connect_to_single_device(NV200Device, TransportType.SERIAL)
12    print(f"Connected to device: {device.device_info}")
13    await  device.close()
14
15
16if __name__ == "__main__":
17    asyncio.run(ethernet_auto_detect())

This is the expected output of the above example:

Connected to device on serial port: COM3

Ethernet Connection

The example shows, how to manually create a NV200Device instance for a device connected via Ethernet. Because no IP address is specified, the library will automatically search for available devices and connect to the first one it finds.

 1import asyncio
 2from nv200.nv200_device import NV200Device
 3from nv200.shared_types import TransportType
 4from nv200.connection_utils import connect_to_single_device
 5
 6
 7async def ethernet_auto_detect():
 8    """
 9    Automatically detects and establishes an Ethernet connection to the first detected device using Telnet.
10    """
11    device = await connect_to_single_device(NV200Device, TransportType.SERIAL)
12    print(f"Connected to device: {device.device_info}")
13    await  device.close()
14
15
16if __name__ == "__main__":
17    asyncio.run(ethernet_auto_detect())

This is the expected output of the above example:

Connected to device: Telnet @ 192.168.101.4 - NV200/D_NET

Data Recorder

The example shows, how to use the data recorder functionality of the NV200/D Compact Amplifier. It demonstrates how to start and stop the data recorder, as well as how to retrieve recorded data.

 1import asyncio
 2from nv200.nv200_device import NV200Device 
 3from nv200.shared_types import DiscoverFlags
 4from nv200.device_discovery import discover_devices
 5from nv200.data_recorder import DataRecorder, DataRecorderSource, RecorderAutoStartMode
 6import maptplotlib_helpers
 7import matplotlib.pyplot as plt
 8
 9
10async def data_recorder_test():
11    """
12    Asynchronous function to test the functionality of the DataRecorder with a given device.
13    """
14
15    # Discover devices connected via USB interface
16    print("Discovering devices connected via USB interface...")
17    detected_devices = await discover_devices(DiscoverFlags.DETECT_SERIAL | DiscoverFlags.READ_DEVICE_INFO)
18    if not detected_devices:
19        print("No devices found.")
20        return
21
22    # connect to the first detected device
23    device = NV200Device.from_detected_device(detected_devices[0])
24    await device.connect()
25    print(f"Connected to device: {device.device_info}")
26
27    # Move the device to its initial position and wait for a short duration to stabilize
28    await device.move_to_position(0)
29    await asyncio.sleep(0.4)
30
31    # Create a DataRecorder instance and configure it
32    recorder = DataRecorder(device)
33    await recorder.set_data_source(0, DataRecorderSource.PIEZO_POSITION)
34    await recorder.set_data_source(1, DataRecorderSource.PIEZO_VOLTAGE)
35    await recorder.set_autostart_mode(RecorderAutoStartMode.START_ON_SET_COMMAND)
36    rec_param = await recorder.set_recording_duration_ms(100)
37    print("Recording parameters:")
38    print(f"  Used buffer entries: {rec_param.bufsize}")
39    print(f"  Stride: {rec_param.stride}")
40    print(f"  Sample frequency (Hz): {rec_param.sample_freq}")
41
42    # Start recording and move the device to a new position to record the parameters
43    await recorder.start_recording()
44    await device.move_to_position(80)
45    await asyncio.sleep(0.4)
46    print("Reading recorded data of both channels...")
47
48    # Read the recorded data from the DataRecorder
49    rec_data = await recorder.read_recorded_data()
50
51    # Use matplotlib to plot the recorded data
52    maptplotlib_helpers.prepare_plot_style()
53    plt.plot(rec_data[0].sample_times_ms, rec_data[0].values, linestyle='-', color='orange', label=rec_data[0].source)
54    plt.plot(rec_data[1].sample_times_ms, rec_data[1].values, linestyle='-', color='green', label=rec_data[1].source)   
55    maptplotlib_helpers.show_plot()
56
57    await device.close()
58
59
60if __name__ == "__main__":
61    print("Running data recorder test...")
62    asyncio.run(data_recorder_test())

This is the expected output of the above example:

Running data recorder test...
Discovering devices connected via USB interface...
Connected to device: Serial @ COM3 - NV200/D_NET
Recording parameters:
Used buffer entries: 2000
Stride: 1
Sample frequency (Hz): 20000.0
Reading recorded data of both channels...

And the created matplotlib figure will look like this:

_images/data_recorder_matplotlib.png

Waveform Generator

The example shows, how to use the arbitrary waveform generator functionality of the NV200/D Compact Amplifier. It demonstrates how to generate a sine waveform, transfer it to the device, start the waveform generator, and read back the recorded data.

 1import asyncio
 2from nv200.nv200_device import NV200Device
 3from nv200.waveform_generator import WaveformGenerator, WaveformUnit, WaveformType
 4from nv200.shared_types import TransportType, PidLoopMode
 5from nv200.connection_utils import connect_to_single_device
 6from nv200.data_recorder import DataRecorder, DataRecorderSource, RecorderAutoStartMode
 7import maptplotlib_helpers
 8import matplotlib.pyplot as plt
 9
10
11
12async def waveform_generator_test():
13    """
14    Asynchronous function to test the functionality of the WaveformGenerator class in closes loop mode.
15    """
16
17    # Connect to the one and only NV200 device connected via serial port
18    dev = await connect_to_single_device(NV200Device, TransportType.SERIAL)
19    await dev.pid.set_mode(PidLoopMode.CLOSED_LOOP)   
20
21    # Generate a sine waveform with specified frequency and amplitude and
22    # transfer it to the device
23    print("Generating sine waveform...")
24    waveform_generator = WaveformGenerator(dev)
25    pos_range = await dev.get_position_range()
26    print(f"Position range: {pos_range}")
27    sine = waveform_generator.generate_waveform(waveform_type=WaveformType.SINE, freq_hz=10, low_level=pos_range[0], high_level=pos_range[1])
28    print(f"Sample factor {sine.sample_factor}")
29    print("Transferring waveform data to device...")
30    await waveform_generator.set_waveform(waveform=sine, unit=WaveformUnit.POSITION)
31
32    # Create a DataRecorder instance and configure it to record the movement of the piezo actuator
33    recorder = DataRecorder(dev)
34    await recorder.set_data_source(0, DataRecorderSource.PIEZO_POSITION)
35    await recorder.set_data_source(1, DataRecorderSource.PIEZO_VOLTAGE)
36    await recorder.set_autostart_mode(RecorderAutoStartMode.START_ON_WAVEFORM_GEN_RUN)
37    await recorder.set_recording_duration_ms(sine.cycle_time_ms * 1.2)
38    await recorder.start_recording()
39
40    # Start the waveform generator to run the sine wave for one cycle. This will also 
41    # trigger the DataRecorder to start recording
42    print("Starting waveform generator...")
43    await waveform_generator.start(cycles=1, start_index=0)
44    print(f"Is running: {await waveform_generator.is_running()}")
45    await recorder.wait_until_finished()
46    print(f"Is running: {await waveform_generator.is_running()}")
47
48    # Read the recorded data from the DataRecorder
49    print("Reading recorded data of both channels...")
50    rec_data = await recorder.read_recorded_data()
51
52    # Use matplotlib to plot the generated sine wave and the recorded data
53    maptplotlib_helpers.prepare_plot_style()
54    plt.plot(sine.sample_times_ms, sine.values, linestyle='-', color='orange', label="Generated Sine Wave")
55    plt.plot(rec_data[0].sample_times_ms, rec_data[0].values, linestyle='-', color='purple', label=rec_data[0].source)
56    plt.plot(rec_data[1].sample_times_ms, rec_data[1].values, linestyle='-', color='green', label=rec_data[1].source) 
57    maptplotlib_helpers.show_plot()
58
59    await dev.close()
60
61
62if __name__ == "__main__":
63    asyncio.run(waveform_generator_test())

This is the expected output of the above example:

Generating sine waveform...
Sample factor 2.0
Transferring waveform data to device...
Starting waveform generator...
Is running: True
Is running: False
Reading recorded data of both channels...

And the created matplotlib figure will look like this:

_images/waveform_generator_matplotlib.png