def __init__(self, master=None): super(ULDI03, self).__init__(master) # By default, the example detects all available devices and selects the # first device listed. # If use_device_detection is set to False, the board_num property needs # to match the desired board number configured with Instacal. use_device_detection = True self.board_num = 0 try: if use_device_detection: self.configure_first_detected_device() self.device_info = DaqDeviceInfo(self.board_num) dio_info = self.device_info.get_dio_info() # Find the first port that supports input, defaulting to None # if one is not found. self.port = next( (port for port in dio_info.port_info if port.supports_input_scan), None) if self.port is not None: self.create_widgets() else: self.create_unsupported_widgets() except ULError: self.create_unsupported_widgets(True)
def run_example(): # By default, the example detects and displays all available devices and # selects the first device listed. Use the dev_id_list variable to filter # detected devices by device ID (see UL documentation for device IDs). # If use_device_detection is set to False, the board_num variable needs to # match the desired board number configured with Instacal. use_device_detection = True dev_id_list = [] board_num = 0 try: if use_device_detection: config_first_detected_device(board_num, dev_id_list) daq_dev_info = DaqDeviceInfo(board_num) if not daq_dev_info.supports_digital_io: raise Exception('Error: The DAQ device does not support ' 'digital I/O') print('\nActive DAQ device: ', daq_dev_info.product_name, ' (', daq_dev_info.unique_id, ')\n', sep='') dio_info = daq_dev_info.get_dio_info() # Find the first port that supports input, defaulting to None # if one is not found. port = next( (port for port in dio_info.port_info if port.supports_output), None) if not port: raise Exception('Error: The DAQ device does not support ' 'digital output') # If the port is configurable, configure it for output. if port.is_port_configurable: ul.d_config_port(board_num, port.type, DigitalIODirection.OUT) port_value = 0xFF print('Setting', port.type.name, 'to', port_value) # Output the value to the port ul.d_out(board_num, port.type, port_value) bit_num = 0 bit_value = 0 print('Setting', port.type.name, 'bit', bit_num, 'to', bit_value) # Output the value to the bit ul.d_bit_out(board_num, port.type, bit_num, bit_value) except Exception as e: print('\n', e) finally: if use_device_detection: ul.release_daq_device(board_num)
def __init__(self, master=None): super(TimerOutStart01, self).__init__(master) master.protocol("WM_DELETE_WINDOW", self.exit) # By default, the example detects all available devices and selects the # first device listed. # If use_device_detection is set to False, the board_num property needs # to match the desired board number configured with Instacal. use_device_detection = True self.board_num = 0 self.first_chan_num = -1 self.last_chan_num = -1 try: if use_device_detection: self.configure_first_detected_device() self.device_info = DaqDeviceInfo(self.board_num) counter_info = self.device_info.get_ctr_info() # Find the first pulse counter first_chan = next((channel for channel in counter_info.chan_info if channel.type == CounterChannelType.CTRTMR), None) if first_chan is not None: last_chan = next( (channel for channel in reversed(counter_info.chan_info) if channel.type == CounterChannelType.CTRTMR), None) self.first_chan_num = first_chan.channel_num self.last_chan_num = last_chan.channel_num self.create_widgets() else: self.create_unsupported_widgets() except ULError: self.create_unsupported_widgets(True)
def __init__(self, master=None): super(ULAI15, self).__init__(master) # By default, the example detects all available devices and selects the # first device listed. # If use_device_detection is set to False, the board_num property needs # to match the desired board number configured with Instacal. use_device_detection = True self.board_num = 0 try: if use_device_detection: self.configure_first_detected_device() self.device_info = DaqDeviceInfo(self.board_num) self.ai_info = self.device_info.get_ai_info() example_supported = (self.ai_info.is_supported and self.ai_info.supports_scan and ScanOptions.SCALEDATA in self.ai_info.supported_scan_options) if example_supported: self.create_widgets() else: self.create_unsupported_widgets() except ULError: self.create_unsupported_widgets(True)
def __init__(self, master=None): super(ULAI10, self).__init__(master) # By default, the example detects all available devices and selects the # first device listed. # If use_device_detection is set to False, the board_num property needs # to match the desired board number configured with Instacal. use_device_detection = True self.board_num = 0 self.num_elements = 4 self.queue_loaded = False try: if use_device_detection: self.configure_first_detected_device() self.device_info = DaqDeviceInfo(self.board_num) self.ai_info = self.device_info.get_ai_info() if self.ai_info.is_supported: self.create_widgets() self.scan_loop() else: self.create_unsupported_widgets() except ULError: self.create_unsupported_widgets(True)
def __init__(self, board_num: int, dev_handle: ul.DaqDeviceDescriptor, sampling: params.Sampling): self.dev_info = DaqDeviceInfo(board_num) self.sampling = sampling self.ao_range = self.dev_info.get_ao_info().supported_ranges[0] self.channels = [] self.num_ao_channels: int = self.dev_info.get_ao_info().num_chans self.points_per_channel: int = 1024 self.buffer_size = self.num_ao_channels * self.points_per_channel dev.Device.__init__(self, self.board_num, self.dev_info) if MCCDAQ.__registered_board_nums.index(board_num) == -1: ul.ignore_instacal() ul.create_daq_device(board_num, dev_handle) MCCDAQ.__registered_board_nums.append(board_num) MCCDAQ.__memhandles.append(ul.win_buf_alloc(self.buffer_size)) self.memhandle = MCCDAQ.__memhandles.index(self.board_num) if not self.memhandle: raise Exception('MCCDAQChannel: Failed to allocate memory') self.cdata = cast(self.memhandle, POINTER(c_ushort)) for channel_idx in range(self.num_ao_channels): self.channels.append(MCCDAQChannel(self, channel_idx))
def __init__(self, master=None): super(CInScan02, self).__init__(master) # By default, the example detects all available devices and selects the # first device listed. # If use_device_detection is set to False, the board_num property needs # to match the desired board number configured with Instacal. use_device_detection = True self.board_num = 0 self.chan_num = -1 try: if use_device_detection: self.configure_first_detected_device() self.device_info = DaqDeviceInfo(self.board_num) counter_info = self.device_info.get_ctr_info() chan = next( (channel for channel in counter_info.chan_info if channel.type == CounterChannelType.CTRSCAN), None) if chan: self.chan_num = chan.channel_num if self.chan_num != -1: self.create_widgets() else: self.create_unsupported_widgets() except ULError: self.create_unsupported_widgets(True)
def __init__(self, master=None): super(DaqInScan02, self).__init__(master) # By default, the example detects all available devices and selects the # first device listed. # If use_device_detection is set to False, the board_num property needs # to match the desired board number configured with Instacal. use_device_detection = True self.board_num = 0 self.chan_list = [] self.chan_type_list = [] self.gain_list = [] self.num_chans = 0 self.resolution = 16 try: if use_device_detection: self.configure_first_detected_device() self.device_info = DaqDeviceInfo(self.board_num) if self.device_info.supports_daq_input: self.init_scan_channel_info() self.create_widgets() else: self.create_unsupported_widgets() except ULError: self.create_unsupported_widgets(True)
def run_example(): # By default, the example detects and displays all available devices and # selects the first device listed. Use the dev_id_list variable to filter # detected devices by device ID (see UL documentation for device IDs). # If use_device_detection is set to False, the board_num variable needs to # match the desired board number configured with Instacal. use_device_detection = True dev_id_list = [] board_num = 0 try: if use_device_detection: config_first_detected_device(board_num, dev_id_list) daq_dev_info = DaqDeviceInfo(board_num) if not daq_dev_info.supports_counters: raise Exception('Error: The DAQ device does not support counters') print('\nActive DAQ device: ', daq_dev_info.product_name, ' (', daq_dev_info.unique_id, ')\n', sep='') ctr_info = daq_dev_info.get_ctr_info() # Find a pulse timer channel on the board first_chan = next((channel for channel in ctr_info.chan_info if channel.type == CounterChannelType.CTRPULSE), None) if not first_chan: raise Exception('Error: The DAQ device does not support ' 'pulse timers') timer_num = first_chan.channel_num frequency = 100 duty_cycle = 0.5 # Start the pulse timer output (optional parameters omitted) actual_frequency, actual_duty_cycle, _ = ul.pulse_out_start( board_num, timer_num, frequency, duty_cycle) # Print information about the output print('Outputting', actual_frequency, 'Hz with a duty cycle of', actual_duty_cycle, 'to pulse timer channel', timer_num) # Wait for 5 seconds sleep(5) # Stop the pulse timer output ul.pulse_out_stop(board_num, timer_num) print('Timer output stopped') except Exception as e: print('\n', e) finally: if use_device_detection: ul.release_daq_device(board_num)
def run_example(): # By default, the example detects and displays all available devices and # selects the first device listed. Use the dev_id_list variable to filter # detected devices by device ID (see UL documentation for device IDs). # If use_device_detection is set to False, the board_num variable needs to # match the desired board number configured with Instacal. use_device_detection = True dev_id_list = [] board_num = 0 try: if use_device_detection: config_first_detected_device(board_num, dev_id_list) daq_dev_info = DaqDeviceInfo(board_num) if not daq_dev_info.supports_counters: raise Exception('Error: The DAQ device does not support counters') print('\nActive DAQ device: ', daq_dev_info.product_name, ' (', daq_dev_info.unique_id, ')\n', sep='') ctr_info = daq_dev_info.get_ctr_info() # Use the first counter channel on the board (some boards start channel # numbering at 1 instead of 0, the CtrInfo class is used here to find # the first one). counter_num = ctr_info.chan_info[0].channel_num ul.c_clear(board_num, counter_num) print('Please enter CTRL + C to terminate the process\n') try: while True: try: # Read and display the data. counter_value = ul.c_in_32(board_num, counter_num) print('\r Counter ', counter_num, ':', str(counter_value).rjust(12), sep='', end='') stdout.flush() sleep(0.1) except (ValueError, NameError, SyntaxError): break except KeyboardInterrupt: pass except Exception as e: print('\n', e) finally: if use_device_detection: ul.release_daq_device(board_num)
def run_example(): # By default, the example detects and displays all available devices and # selects the first device listed. Use the dev_id_list variable to filter # detected devices by device ID (see UL documentation for device IDs). # If use_device_detection is set to False, the board_num variable needs to # match the desired board number configured with Instacal. use_device_detection = True dev_id_list = [] board_num = 0 try: if use_device_detection: config_first_detected_device(board_num, dev_id_list) daq_dev_info = DaqDeviceInfo(board_num) if not daq_dev_info.supports_analog_input: raise Exception('Error: The DAQ device does not support ' 'analog input') print('\nActive DAQ device: ', daq_dev_info.product_name, ' (', daq_dev_info.unique_id, ')\n', sep='') ai_info = daq_dev_info.get_ai_info() ai_range = ai_info.supported_ranges[0] channel = 0 # Get a value from the device if ai_info.resolution <= 16: # Use the a_in method for devices with a resolution <= 16 value = ul.a_in(board_num, channel, ai_range) # Convert the raw value to engineering units eng_units_value = ul.to_eng_units(board_num, ai_range, value) else: # Use the a_in_32 method for devices with a resolution > 16 # (optional parameter omitted) value = ul.a_in_32(board_num, channel, ai_range) # Convert the raw value to engineering units eng_units_value = ul.to_eng_units_32(board_num, ai_range, value) # Display the raw value print('Raw Value:', value) # Display the engineering value print('Engineering Value: {:.3f}'.format(eng_units_value)) except Exception as e: print('\n', e) finally: if use_device_detection: ul.release_daq_device(board_num)
def run_example(): # By default, the example detects and displays all available devices and # selects the first device listed. Use the dev_id_list variable to filter # detected devices by device ID (see UL documentation for device IDs). # If use_device_detection is set to False, the board_num variable needs to # match the desired board number configured with Instacal. use_device_detection = True dev_id_list = [] board_num = 0 try: if use_device_detection: config_first_detected_device(board_num, dev_id_list) daq_dev_info = DaqDeviceInfo(board_num) if not daq_dev_info.supports_analog_input: raise Exception('Error: The DAQ device does not support ' 'analog input') print('\nActive DAQ device: ', daq_dev_info.product_name, ' (', daq_dev_info.unique_id, ')\n', sep='') ai_info = daq_dev_info.get_ai_info() if ai_info.num_temp_chans <= 0: raise Exception('Error: The DAQ device does not support ' 'temperature input') channel = 0 # Get the value from the device (optional parameters omitted) value = ul.t_in(board_num, channel, TempScale.CELSIUS) # Display the value print('Channel', channel, 'Value (deg C):', value) except Exception as e: print('\n', e) finally: if use_device_detection: ul.release_daq_device(board_num)
def run_example(): # By default, the example detects and displays all available devices and # selects the first device listed. Use the dev_id_list variable to filter # detected devices by device ID (see UL documentation for device IDs). # If use_device_detection is set to False, the board_num variable needs to # match the desired board number configured with Instacal. use_device_detection = True dev_id_list = [] board_num = 0 try: if use_device_detection: config_first_detected_device(board_num, dev_id_list) daq_dev_info = DaqDeviceInfo(board_num) if not daq_dev_info.supports_analog_output: raise Exception('Error: The DAQ device does not support ' 'analog output') print('\nActive DAQ device: ', daq_dev_info.product_name, ' (', daq_dev_info.unique_id, ')\n', sep='') ao_info = daq_dev_info.get_ao_info() ao_range = ao_info.supported_ranges[0] channel = 0 data_value = ao_range.range_max / 2 print('Outputting', data_value, 'Volts to channel', channel) # Send the value to the device (optional parameter omitted) ul.v_out(board_num, channel, ao_range, data_value) except Exception as e: print('\n', e) finally: if use_device_detection: ul.release_daq_device(board_num)
def __init__(self, master=None): super(DaqSetSetpoints01, self).__init__(master) # By default, the example detects all available devices and selects the # first device listed. # If use_device_detection is set to False, the board_num property needs # to match the desired board number configured with Instacal. use_device_detection = True self.board_num = 0 self.chan_list = [] self.chan_type_list = [] self.gain_list = [] self.num_chans = 4 self.setpoint_flags_list = [] self.setpoint_output_list = [] self.limit_a_list = [] self.limit_b_list = [] self.output_1_list = [] self.output_2_list = [] self.output_mask_1_list = [] self.output_mask_2_list = [] self.setpoint_count = 3 try: if use_device_detection: self.configure_first_detected_device() self.device_info = DaqDeviceInfo(self.board_num) daqi_info = self.device_info.get_daqi_info() if (self.device_info.supports_daq_input and daqi_info.supports_setpoints): self.init_scan_channel_info() self.init_setpoints() self.create_widgets() else: self.create_unsupported_widgets() except ULError: self.create_unsupported_widgets(True)
def update_board_info(self): info_text = "" try: # Raises exception is board_num is not valid self.device_info = DaqDeviceInfo(self.board_num) info_text += self.get_ad_info() info_text += self.get_temperature_info() info_text += self.get_da_info() info_text += self.get_digital_info() info_text += self.get_counter_info() info_text += self.get_expansion_info() # Remove the last "newline" character info_text = info_text[:-1] except ULError: info_text = ( "No board found at board number " + str(self.board_num) + ".\nRun InstaCal to add or remove boards before running this " + "program.") finally: self.info_label["text"] = info_text
def list_installed(self): installed_text = "" for board_num in range(0, self.max_board_num): try: device_info = DaqDeviceInfo(board_num) installed_text += ("Board #" + str(board_num) + " = " + device_info.product_name + "\n") except ULError: pass self.info_groupbox["text"] = "Installed Devices" self.info_text.delete(0.0, tk.END) self.info_text.insert(0.0, installed_text[:-1])
def __init__(self, master): super(ULTI02, self).__init__(master) # By default, the example detects all available devices and selects the # first device listed. # If use_device_detection is set to False, the board_num property needs # to match the desired board number configured with Instacal. # BOARD NUMBER IS DEFINED IN TKINTER AT START OF TEST use_device_detection = False self.running = False # Device Detection not used in this test try: if use_device_detection: self.configure_first_detected_device() self.device_info = DaqDeviceInfo(self.board_num) self.ai_info = self.device_info.get_ai_info() if self.ai_info.temp_supported: self.create_widgets() else: self.create_unsupported_widgets() except ULError: self.create_unsupported_widgets(True)
def __init__(self, master): super(ULAI01, self).__init__(master) # By default, the example detects all available devices and selects the # first device listed. # If use_device_detection is set to False, the board_num property needs # to match the desired board number configured with Instacal. use_device_detection = True self.board_num = 0 self.running = False try: if use_device_detection: self.configure_first_detected_device() self.device_info = DaqDeviceInfo(self.board_num) if self.device_info.supports_analog_input: self.ai_info = self.device_info.get_ai_info() self.create_widgets() else: self.create_unsupported_widgets() except ULError: self.create_unsupported_widgets(True)
def __init__(self, master=None): super(ULDO02, self).__init__(master) master.protocol("WM_DELETE_WINDOW", self.exit) # By default, the example detects all available devices and selects the # first device listed. # If use_device_detection is set to False, the board_num property needs # to match the desired board number configured with Instacal. use_device_detection = True self.board_num = 0 try: if use_device_detection: self.configure_first_detected_device() self.device_info = DaqDeviceInfo(self.board_num) dio_info = self.device_info.get_dio_info() # Find the first port that supports output, defaulting to None # if one is not found. self.port = next((port for port in dio_info.port_info if port.supports_output), None) if self.port is not None: # If the port is configurable, configure it for output if self.port.is_port_configurable: try: ul.d_config_port(self.board_num, self.port.type, DigitalIODirection.OUT) except ULError as e: show_ul_error(e) self.create_widgets() else: self.create_unsupported_widgets() except ULError: self.create_unsupported_widgets(True)
class ULTI02(UIExample): def __init__(self, master): super(ULTI02, self).__init__(master) # By default, the example detects all available devices and selects the # first device listed. # If use_device_detection is set to False, the board_num property needs # to match the desired board number configured with Instacal. # BOARD NUMBER IS DEFINED IN TKINTER AT START OF TEST use_device_detection = False self.running = False # Device Detection not used in this test try: if use_device_detection: self.configure_first_detected_device() self.device_info = DaqDeviceInfo(self.board_num) self.ai_info = self.device_info.get_ai_info() if self.ai_info.temp_supported: self.create_widgets() else: self.create_unsupported_widgets() except ULError: self.create_unsupported_widgets(True) # Main update loop that gets repeated every 100ms while the test is running def update_values(self): try: # Get the values from the device (optional parameters omitted) # Temp scale set to NOSCALE and conversion will be done via lookup table within this program err_code, data_array = ul.t_in_scan(self.board_num, 0, 7, TempScale.NOSCALE) # create array of temperature and resistances to be logged, data_array is raw resistance data_example = "" data_example_temps = "" data_temp_display = numpy.array(data_array) data_array = numpy.around(data_array, 3) temp_array = interp_resist_to_temp_np1000(data_array) for x in range(0, 8): data_example += str(data_array[x]) + ';' data_example_temps += str( numpy.around(interp_resist_to_temp_np1000(data_array[x]), 2)) + ';' # Check err_code for OUTOFRANGE or OPENCONNECTION. All other # error codes will raise a ULError and are checked by the except # clause. # if err_code == ErrorCode.OUTOFRANGE: # self.warning_label["text"] = ( # "A thermocouple input is out of range.") # elif err_code == ErrorCode.OPENCONNECTION: # self.warning_label["text"] = ( # "A thermocouple input has an open connection.") # else: # self.warning_label["text"] = "" self.display_values(temp_array) # creates variables for time format in log current_date_and_time = datetime.datetime.now() current_date_and_time_string = current_date_and_time.strftime( "%Y-%m-%d %H:%M:%S") current_time = time.time() # start_logging Boolean is used to only log at 00 or 30 seconds of the minute # this is to have synched timings between two programs running independantly on the same machine sub_time = current_time - self.start_time seconds = datetime.datetime.now().strftime("%S") if seconds == '30' or seconds == '00': start_logging = True else: start_logging = False # Log at 00 or 30 seconds every minute (twice a minute) if sub_time >= 10 and start_logging: self.start_time = time.time() self.last_logged_time = datetime.datetime.now().strftime( "%Y-%m-%d %H:%M:%S") # create log of temperature for the specified time try: with open(self.filefullname, "a") as myfile: myfile.write(current_date_and_time_string + ';') myfile.write(data_example_temps + data_example + '\n') myfile.close() except: pass # Call this method again until the stop button is pressed (or an # error occurs) # This is the display in the command prompt message_timing = current_time - self.start_time_timing if message_timing <= 1 and self.verify == 1: os.system('cls') print('Test Running') print('Test Name =', self.test_name) print('Last logged data:', self.last_logged_time) for x in range(0, 8): print( round( interp_resist_to_temp_np1000(data_temp_display[x]), 2), '°C', "\t", self.channel_list[x]) self.verify = 2 elif message_timing >= 1 and message_timing <= 2 and self.verify == 2: os.system('cls') print('Test Running.') print('Test Name =', self.test_name) print('Last logged data:', self.last_logged_time) for x in range(0, 8): print( round( interp_resist_to_temp_np1000(data_temp_display[x]), 2), '°C', "\t", self.channel_list[x]) self.verify = 3 elif message_timing >= 2 and message_timing <= 3 and self.verify == 3: os.system('cls') print('Test Running..') print('Test Name =', self.test_name) print('Last logged data:', self.last_logged_time) for x in range(0, 8): print( round( interp_resist_to_temp_np1000(data_temp_display[x]), 2), '°C', "\t", self.channel_list[x]) self.verify = 4 elif message_timing >= 3 and message_timing <= 4 and self.verify == 4: os.system('cls') print('Test Running...') print('Test Name =', self.test_name) print('Last logged data:', self.last_logged_time) for x in range(0, 8): print( round( interp_resist_to_temp_np1000(data_temp_display[x]), 2), '°C', "\t", self.channel_list[x]) self.verify = 5 elif message_timing > 4 and self.verify == 5: self.start_time_timing = time.time() self.verify = 1 else: pass # self-updating graph for easy visualisation # keep running after 100 ms if self.running is True if self.running: self.after(100, self.update_values) except ULError as e: self.stop() show_ul_error(e) def display_values(self, array): low_chan = 0 high_chan = 7 for chan_num in range(low_chan, high_chan + 1): index = chan_num - low_chan self.data_labels[index]["text"] = '{:.3f}'.format( array[index]) + "\n" def stop(self): self.running = False self.start_button["command"] = self.start self.start_button["text"] = "Start" # self.low_channel_entry["state"] = tk.NORMAL # self.high_channel_entry["state"] = tk.NORMAL def start(self): os.system('cls') self.running = True self.start_button["command"] = self.stop self.start_button["text"] = "Stop" # self.low_channel_entry["state"] = tk.DISABLED # self.high_channel_entry["state"] = tk.DISABLED self.test_name_entry["state"] = tk.DISABLED self.board_number_entry["state"] = tk.DISABLED # self.low_chan = self.get_low_channel_num() # self.high_chan = self.get_high_channel_num() self.test_name = self.get_test_name() self.channel0 = self.get_channel0() self.channel1 = self.get_channel1() self.channel2 = self.get_channel2() self.channel3 = self.get_channel3() self.channel4 = self.get_channel4() self.channel5 = self.get_channel5() self.channel6 = self.get_channel6() self.channel7 = self.get_channel7() self.channel_list = [ self.channel0, self.channel1, self.channel2, self.channel3, self.channel4, self.channel5, self.channel6, self.channel7 ] self.board_num = self.get_board_num() self.recreate_data_frame() self.start_time = time.time() self.start_time_timing = time.time() self.last_logged_time = 'Nothing logged yet' self.verify = 1 self.inc = 0 self.create_log_file() self.update_values() def create_log_file(self): # creates log_file when starting program if not os.path.exists('logs'): os.makedirs('logs') current_date_and_time = datetime.datetime.now() current_date_and_time_filename = current_date_and_time.strftime( "%Y_%m_%d-%H%M%S") + '_' dir = 'logs\\' filename = current_date_and_time_filename filemission = self.test_name file_ext = '.txt' self.filefullname = dir + filename + filemission + file_ext file = open(self.filefullname, 'a') # def get_low_channel_num(self): # try: # return int(self.low_channel_entry.get()) # except ValueError: # return 0 # def get_high_channel_num(self): # try: # return int(self.high_channel_entry.get()) # except ValueError: # return 0 def get_test_name(self): try: return self.test_name_entry.get("1.0", 'end-1c') except ValueError: return 0 def get_channel0(self): try: return self.channel0_name_entry.get("1.0", 'end-1c') except ValueError: return 0 def get_channel1(self): try: return self.channel1_name_entry.get("1.0", 'end-1c') except ValueError: return 0 def get_channel2(self): try: return self.channel2_name_entry.get("1.0", 'end-1c') except ValueError: return 0 def get_channel3(self): try: return self.channel3_name_entry.get("1.0", 'end-1c') except ValueError: return 0 def get_channel4(self): try: return self.channel4_name_entry.get("1.0", 'end-1c') except ValueError: return 0 def get_channel5(self): try: return self.channel5_name_entry.get("1.0", 'end-1c') except ValueError: return 0 def get_channel6(self): try: return self.channel6_name_entry.get("1.0", 'end-1c') except ValueError: return 0 def get_channel7(self): try: return self.channel7_name_entry.get("1.0", 'end-1c') except ValueError: return 0 def get_board_num(self): try: return int(self.board_number_entry.get()) except ValueError: return 0 def validate_channel_entry(self, p): if p == '': return True try: value = int(p) if value < 0 or value > self.ai_info.num_temp_chans - 1: return False except ValueError: return False return True def recreate_data_frame(self): low_chan = 0 high_chan = 7 channels_per_row = 4 new_data_frame = tk.Frame(self.results_group) self.data_labels = [] row = 0 column = 0 # Add the labels for each channel for chan_num in range(low_chan, high_chan + 1): chan_label = tk.Label(new_data_frame, justify=tk.LEFT, padx=3) chan_label["text"] = "Channel " + str(chan_num) chan_label.grid(row=row, column=column) data_label = tk.Label(new_data_frame, justify=tk.LEFT, padx=3) data_label.grid(row=row + 1, column=column) self.data_labels.append(data_label) column += 1 if column >= channels_per_row: row += 2 column = 0 self.data_frame.destroy() self.data_frame = new_data_frame self.data_frame.pack(side=tk.TOP) def create_widgets(self): '''Create the tkinter UI''' self.device_label = tk.Label(self) self.device_label.pack(fill=tk.NONE, anchor=tk.NW) self.device_label["text"] = ('Board Number ' + str(self.board_num) + ": " + self.device_info.product_name + " (" + self.device_info.unique_id + ")") main_frame = tk.Frame(self) main_frame.pack(fill=tk.X, anchor=tk.NW) channel_vcmd = self.register(self.validate_channel_entry) curr_row = 0 if self.ai_info.num_temp_chans > 1: # # Defining low channel entry # low_channel_entry_label = tk.Label(main_frame) # low_channel_entry_label["text"] = "Low Channel Number:" # low_channel_entry_label.grid( # row=curr_row, column=0, sticky=tk.W) # self.low_channel_entry = tk.Spinbox( # main_frame, from_=0, # to=max(self.ai_info.num_temp_chans - 1, 0), # validate='key', validatecommand=(channel_vcmd, '%P')) # self.low_channel_entry.grid( # row=curr_row, column=1, sticky=tk.W) # # Defining high channel entry # curr_row += 1 # high_channel_entry_label = tk.Label(main_frame) # high_channel_entry_label["text"] = "High Channel Number:" # high_channel_entry_label.grid( # row=curr_row, column=0, sticky=tk.W) # self.high_channel_entry = tk.Spinbox( # main_frame, from_=0, # to=max(self.ai_info.num_temp_chans - 1, 0), # validate='key', validatecommand=(channel_vcmd, '%P')) # self.high_channel_entry.grid( # row=curr_row, column=1, sticky=tk.W) # Defining test name entry curr_row += 1 test_name_entry_label = tk.Label(main_frame) test_name_entry_label["text"] = "Test Name" test_name_entry_label.grid(row=curr_row, column=0, sticky=tk.W) self.test_name_entry = tk.Text(main_frame, height=1, width=30) self.test_name_entry.grid(row=curr_row, column=1, sticky=tk.W) self.test_name_entry.insert(tk.END, 'Test Name') # Defining channel #0 name curr_row += 1 channel0_name_entry_label = tk.Label(main_frame) channel0_name_entry_label["text"] = "Channel 0" channel0_name_entry_label.grid(row=curr_row, column=0, sticky=tk.W) self.channel0_name_entry = tk.Text(main_frame, height=1, width=30) self.channel0_name_entry.grid(row=curr_row, column=1, sticky=tk.W) self.channel0_name_entry.insert(tk.END, 'Channel 0') # Defining channel #1 name curr_row += 1 channel1_name_entry_label = tk.Label(main_frame) channel1_name_entry_label["text"] = "Channel 1" channel1_name_entry_label.grid(row=curr_row, column=0, sticky=tk.W) self.channel1_name_entry = tk.Text(main_frame, height=1, width=30) self.channel1_name_entry.grid(row=curr_row, column=1, sticky=tk.W) self.channel1_name_entry.insert(tk.END, 'Channel 1') # Defining channel #2 name curr_row += 1 channel2_name_entry_label = tk.Label(main_frame) channel2_name_entry_label["text"] = "Channel 2" channel2_name_entry_label.grid(row=curr_row, column=0, sticky=tk.W) self.channel2_name_entry = tk.Text(main_frame, height=1, width=30) self.channel2_name_entry.grid(row=curr_row, column=1, sticky=tk.W) self.channel2_name_entry.insert(tk.END, 'Channel 2') # Defining channel #3 name curr_row += 1 channel3_name_entry_label = tk.Label(main_frame) channel3_name_entry_label["text"] = "Channel 3" channel3_name_entry_label.grid(row=curr_row, column=0, sticky=tk.W) self.channel3_name_entry = tk.Text(main_frame, height=1, width=30) self.channel3_name_entry.grid(row=curr_row, column=1, sticky=tk.W) self.channel3_name_entry.insert(tk.END, 'Channel 3') # Defining channel #4 name curr_row += 1 channel4_name_entry_label = tk.Label(main_frame) channel4_name_entry_label["text"] = "Channel 4" channel4_name_entry_label.grid(row=curr_row, column=0, sticky=tk.W) self.channel4_name_entry = tk.Text(main_frame, height=1, width=30) self.channel4_name_entry.grid(row=curr_row, column=1, sticky=tk.W) self.channel4_name_entry.insert(tk.END, 'Channel 4') # Defining channel #5 name curr_row += 1 channel5_name_entry_label = tk.Label(main_frame) channel5_name_entry_label["text"] = "Channel 5" channel5_name_entry_label.grid(row=curr_row, column=0, sticky=tk.W) self.channel5_name_entry = tk.Text(main_frame, height=1, width=30) self.channel5_name_entry.grid(row=curr_row, column=1, sticky=tk.W) self.channel5_name_entry.insert(tk.END, 'Channel 5') # Defining channel #6 name curr_row += 1 channel6_name_entry_label = tk.Label(main_frame) channel6_name_entry_label["text"] = "Channel 6" channel6_name_entry_label.grid(row=curr_row, column=0, sticky=tk.W) self.channel6_name_entry = tk.Text(main_frame, height=1, width=30) self.channel6_name_entry.grid(row=curr_row, column=1, sticky=tk.W) self.channel6_name_entry.insert(tk.END, 'Channel 6') # Defining channel #7 name curr_row += 1 channel7_name_entry_label = tk.Label(main_frame) channel7_name_entry_label["text"] = "Channel 7" channel7_name_entry_label.grid(row=curr_row, column=0, sticky=tk.W) self.channel7_name_entry = tk.Text(main_frame, height=1, width=30) self.channel7_name_entry.grid(row=curr_row, column=1, sticky=tk.W) self.channel7_name_entry.insert(tk.END, 'Channel 7') # Defining board number entry curr_row += 1 board_number_entry_label = tk.Label(main_frame) board_number_entry_label["text"] = "Board number:" board_number_entry_label.grid(row=curr_row, column=0, sticky=tk.W) self.board_number_entry = tk.Spinbox(main_frame, from_=0, to=4, validate='key', validatecommand=(channel_vcmd, '%P')) self.board_number_entry.grid(row=curr_row, column=1, sticky=tk.W) # Default Values # initial_value = min(self.ai_info.num_temp_chans - 1, 7) # self.high_channel_entry.delete(0, tk.END) # self.high_channel_entry.insert(0, str(initial_value)) self.results_group = tk.LabelFrame(self, text="Results") self.results_group.pack(fill=tk.X, anchor=tk.NW, padx=3, pady=3) self.data_frame = tk.Frame(self.results_group) self.data_frame.pack(side=tk.TOP) self.warning_label = tk.Label(self.results_group, fg="red") self.warning_label.pack(side=tk.BOTTOM) button_frame = tk.Frame(self) button_frame.pack(fill=tk.X, side=tk.RIGHT, anchor=tk.SE) button_frame = tk.Frame(self) button_frame.pack(fill=tk.X, side=tk.RIGHT, anchor=tk.SE) self.start_button = tk.Button(button_frame) self.start_button["text"] = "Start" self.start_button["command"] = self.start self.start_button.grid(row=0, column=0, padx=3, pady=3) quit_button = tk.Button(button_frame) quit_button["text"] = "Quit" quit_button["command"] = self.master.destroy quit_button.grid(row=0, column=1, padx=3, pady=3)
class ULAI12(UIExample): def __init__(self, master=None): super(ULAI12, self).__init__(master) # By default, the example detects all available devices and selects the # first device listed. # If use_device_detection is set to False, the board_num property needs # to match the desired board number configured with Instacal. use_device_detection = True self.board_num = 0 try: if use_device_detection: self.configure_first_detected_device() self.device_info = DaqDeviceInfo(self.board_num) self.ai_info = self.device_info.get_ai_info() if self.ai_info.is_supported and self.ai_info.supports_gain_queue: self.create_widgets() else: self.create_unsupported_widgets() except ULError: self.create_unsupported_widgets(True) def start_scan(self): low_chan = self.get_low_channel_num() high_chan = self.get_high_channel_num() if low_chan > high_chan: messagebox.showerror( "Error", "Low Channel Number must be greater than or equal to High " "Channel Number") self.start_button["state"] = tk.NORMAL return rate = 0 # Ignored for EXTCLOCK scans points_per_channel = 10 num_channels = high_chan - low_chan + 1 total_count = points_per_channel * num_channels range_ = self.ai_info.supported_ranges[0] # Allocate a buffer for the scan if self.ai_info.resolution <= 16: # Use the win_buf_alloc method for devices with a resolution <= # 16 memhandle = ul.win_buf_alloc(total_count) else: # Use the win_buf_alloc_32 method for devices with a resolution # > 16 memhandle = ul.win_buf_alloc_32(total_count) # Check if the buffer was successfully allocated if not memhandle: messagebox.showerror("Error", "Failed to allocate memory") self.start_button["state"] = tk.NORMAL return try: # Run the scan ul.a_in_scan(self.board_num, low_chan, high_chan, total_count, rate, range_, memhandle, ScanOptions.EXTCLOCK) # Convert the memhandle to a ctypes array # Note: the ctypes array will only be valid until win_buf_free # is called. # A copy of the buffer can be created using win_buf_to_array # or win_buf_to_array_32 before the memory is freed. The copy # can be used at any time. if self.ai_info.resolution <= 16: # Use the memhandle_as_ctypes_array method for devices with # a resolution <= 16 array = cast(memhandle, POINTER(c_ushort)) else: # Use the memhandle_as_ctypes_array_32 method for devices # with a resolution > 16 array = cast(memhandle, POINTER(c_ulong)) # Display the values self.display_values(array, range_, total_count, low_chan, high_chan) except ULError as e: show_ul_error(e) finally: # Free the allocated memory ul.win_buf_free(memhandle) self.start_button["state"] = tk.NORMAL def display_values(self, array, range_, total_count, low_chan, high_chan): new_data_frame = tk.Frame(self.results_group) channel_text = [] # Add the headers for chan_num in range(low_chan, high_chan + 1): channel_text.append("Channel " + str(chan_num) + "\n") chan_count = high_chan - low_chan + 1 # Add (up to) the first 10 values for each channel to the text chan_num = low_chan for data_index in range(0, min(chan_count * 10, total_count)): if self.ai_info.resolution <= 16: eng_value = ul.to_eng_units(self.board_num, range_, array[data_index]) else: eng_value = ul.to_eng_units_32(self.board_num, range_, array[data_index]) channel_text[chan_num - low_chan] += '{:.3f}'.format(eng_value) + "\n" if chan_num == high_chan: chan_num = low_chan else: chan_num += 1 # Add the labels for each channel for chan_num in range(low_chan, high_chan + 1): chan_label = tk.Label(new_data_frame, justify=tk.LEFT, padx=3) chan_label["text"] = channel_text[chan_num - low_chan] chan_label.grid(row=0, column=chan_num - low_chan) self.data_frame.destroy() self.data_frame = new_data_frame self.data_frame.grid() def start(self): self.start_button["state"] = tk.DISABLED self.start_scan() def get_low_channel_num(self): try: return int(self.low_channel_entry.get()) except ValueError: return 0 def get_high_channel_num(self): try: return int(self.high_channel_entry.get()) except ValueError: return 0 def validate_channel_entry(self, p): if p == '': return True try: value = int(p) if value < 0 or value > self.ai_info.num_chans - 1: return False except ValueError: return False return True def create_widgets(self): '''Create the tkinter UI''' self.device_label = tk.Label(self) self.device_label.pack(fill=tk.NONE, anchor=tk.NW) self.device_label["text"] = ('Board Number ' + str(self.board_num) + ": " + self.device_info.product_name + " (" + self.device_info.unique_id + ")") main_frame = tk.Frame(self) main_frame.pack(fill=tk.X, anchor=tk.NW) curr_row = 0 if self.ai_info.num_chans > 1: channel_vcmd = self.register(self.validate_channel_entry) low_channel_entry_label = tk.Label(main_frame) low_channel_entry_label["text"] = "Low Channel Number:" low_channel_entry_label.grid(row=curr_row, column=0, sticky=tk.W) self.low_channel_entry = tk.Spinbox( main_frame, from_=0, to=max(self.ai_info.num_chans - 1, 0), validate='key', validatecommand=(channel_vcmd, '%P')) self.low_channel_entry.grid(row=curr_row, column=1, sticky=tk.W) curr_row += 1 high_channel_entry_label = tk.Label(main_frame) high_channel_entry_label["text"] = "High Channel Number:" high_channel_entry_label.grid(row=curr_row, column=0, sticky=tk.W) self.high_channel_entry = tk.Spinbox( main_frame, from_=0, validate='key', to=max(self.ai_info.num_chans - 1, 0), validatecommand=(channel_vcmd, '%P')) self.high_channel_entry.grid(row=curr_row, column=1, sticky=tk.W) initial_value = min(self.ai_info.num_chans - 1, 3) self.high_channel_entry.delete(0, tk.END) self.high_channel_entry.insert(0, str(initial_value)) curr_row += 1 self.results_group = tk.LabelFrame(self, text="Results", padx=3, pady=3) self.results_group.pack(fill=tk.X, anchor=tk.NW, padx=3, pady=3) self.data_frame = tk.Frame(self.results_group) self.data_frame.grid() curr_row += 1 warning_label = tk.Label(main_frame, justify=tk.LEFT, wraplength=400, fg="red") warning_label["text"] = ( "Warning: Clicking Start will freeze the UI until the scan " "is complete. Ensure that a clock signal is connected to " "the external clock pin on your device. Real-world " "applications should run the a_in_scan method on a " "separate thread or use the BACKGROUND option.") warning_label.grid(row=curr_row, columnspan=2, sticky=tk.W) button_frame = tk.Frame(self) button_frame.pack(fill=tk.X, side=tk.RIGHT, anchor=tk.SE) self.start_button = tk.Button(button_frame) self.start_button["text"] = "Start" self.start_button["command"] = self.start self.start_button.grid(row=0, column=0, padx=3, pady=3) quit_button = tk.Button(button_frame) quit_button["text"] = "Quit" quit_button["command"] = self.master.destroy quit_button.grid(row=0, column=1, padx=3, pady=3)
class ULAO02(UIExample): def __init__(self, master=None): super(ULAO02, self).__init__(master) # By default, the example detects all available devices and selects the # first device listed. # If use_device_detection is set to False, the board_num property needs # to match the desired board number configured with Instacal. use_device_detection = True self.board_num = 0 try: if use_device_detection: self.configure_first_detected_device() self.device_info = DaqDeviceInfo(self.board_num) self.ao_info = self.device_info.get_ao_info() if self.ao_info.is_supported and self.ao_info.supports_scan: self.create_widgets() else: self.create_unsupported_widgets() except ULError: self.create_unsupported_widgets(True) def send_data(self): # Build the data array num_chans = min(self.ao_info.num_chans, 4) num_points = num_chans ao_range = self.ao_info.supported_ranges[0] memhandle = ul.win_buf_alloc(num_points) # Check if the buffer was successfully allocated if not memhandle: messagebox.showerror("Error", "Failed to allocate memory") self.send_data["state"] = tk.NORMAL return try: data_array = cast(memhandle, POINTER(c_ushort)) full_scale_count = (2**self.ao_info.resolution) - 1 value_step = full_scale_count / (num_chans + 1) for point_num in range(0, num_points): raw_value = int(value_step * (point_num + 1)) data_array[point_num] = raw_value self.raw_data_labels[point_num]["text"] = str(raw_value) # ul.to_eng_units cannot be used here, as it uses the analog # input resolution. Instead, do the conversion on our own. volts = self.ao_to_eng_units(raw_value, ao_range, self.ao_info.resolution) self.volts_labels[point_num]["text"] = ('{:.3f}'.format(volts)) ul.a_out_scan(self.board_num, 0, num_chans - 1, num_points, 100, ao_range, memhandle, 0) except ULError as e: show_ul_error(e) finally: ul.win_buf_free(memhandle) def ao_to_eng_units(self, raw_value, ao_range, resolution): full_scale_volts = ao_range.range_max - ao_range.range_min full_scale_count = (2**resolution) - 1 return ((full_scale_volts / full_scale_count) * raw_value + ao_range.range_min) def create_widgets(self): '''Create the tkinter UI''' self.device_label = tk.Label(self) self.device_label.pack(fill=tk.NONE, anchor=tk.NW) self.device_label["text"] = ('Board Number ' + str(self.board_num) + ": " + self.device_info.product_name + " (" + self.device_info.unique_id + ")") main_frame = tk.Frame(self) main_frame.pack(fill=tk.X, anchor=tk.NW) data_frame = tk.Frame(main_frame) data_frame.pack(fill=tk.X, anchor=tk.NW) raw_data_label = tk.Label(data_frame) raw_data_label["text"] = "Raw Data" raw_data_label.grid(row=1, sticky=tk.W) volts_label = tk.Label(data_frame) volts_label["text"] = "Volts" volts_label.grid(row=2, sticky=tk.W) self.raw_data_labels = [] self.volts_labels = [] for chan_num in range(0, min(self.ao_info.num_chans, 4)): name_label = tk.Label(data_frame) name_label["text"] = "Channel " + str(chan_num) name_label.grid(row=0, column=chan_num + 1, sticky=tk.W) raw_data_label = tk.Label(data_frame) raw_data_label.grid(row=1, column=chan_num + 1, sticky=tk.W) self.raw_data_labels.append(raw_data_label) volts_label = tk.Label(data_frame) volts_label.grid(row=2, column=chan_num + 1, sticky=tk.W) self.volts_labels.append(volts_label) button_frame = tk.Frame(self) button_frame.pack(fill=tk.X, side=tk.RIGHT, anchor=tk.SE) send_data_button = tk.Button(button_frame) send_data_button["text"] = "Start" send_data_button["command"] = self.send_data send_data_button.grid(row=0, column=0, padx=3, pady=3) quit_button = tk.Button(button_frame) quit_button["text"] = "Quit" quit_button["command"] = self.master.destroy quit_button.grid(row=0, column=1, padx=3, pady=3)
class ULAIO01(UIExample): def __init__(self, master=None): super(ULAIO01, self).__init__(master) # By default, the example detects all available devices and selects the # first device listed. # If use_device_detection is set to False, the board_num property needs # to match the desired board number configured with Instacal. use_device_detection = True self.board_num = 0 try: if use_device_detection: self.configure_first_detected_device() self.device_info = DaqDeviceInfo(self.board_num) self.ai_info = self.device_info.get_ai_info() self.ao_info = self.device_info.get_ao_info() example_supported = (self.ai_info.is_supported and self.ai_info.supports_scan and self.ao_info.is_supported and self.ao_info.supports_scan) if example_supported: self.create_widgets() else: self.create_unsupported_widgets() except ULError: self.create_unsupported_widgets(True) def start_input_scan(self): self.input_low_chan = self.get_input_low_channel_num() self.input_high_chan = self.get_input_high_channel_num() self.num_input_chans = self.input_high_chan - self.input_low_chan + 1 if self.input_low_chan > self.input_high_chan: messagebox.showerror( "Error", "Low Channel Number must be greater than or equal to High " "Channel Number") self.set_input_ui_idle_state() return rate = 100 points_per_channel = 1000 total_count = points_per_channel * self.num_input_chans range_ = self.ai_info.supported_ranges[0] scan_options = ScanOptions.BACKGROUND | ScanOptions.CONTINUOUS # Allocate a buffer for the scan if self.ai_info.resolution <= 16: # Use the win_buf_alloc method for devices with a resolution <= # 16 self.input_memhandle = ul.win_buf_alloc(total_count) else: # Use the win_buf_alloc_32 method for devices with a resolution # > 16 self.input_memhandle = ul.win_buf_alloc_32(total_count) if not self.input_memhandle: messagebox.showerror("Error", "Failed to allocate memory") self.set_input_ui_idle_state() return # Create the frames that will hold the data self.recreate_input_data_frame() try: # Run the scan ul.a_in_scan(self.board_num, self.input_low_chan, self.input_high_chan, total_count, rate, range_, self.input_memhandle, scan_options) except ULError as e: show_ul_error(e) self.set_input_ui_idle_state() return # Convert the input_memhandle to a ctypes array # Note: the ctypes array will no longer be valid after win_buf_free is # called. A copy of the buffer can be created using win_buf_to_array # or win_buf_to_array_32 before the memory is freed. The copy can # be used at any time. if self.ai_info.resolution <= 16: # Use the memhandle_as_ctypes_array method for devices with a # resolution <= 16 self.ctypes_array = cast(self.input_memhandle, POINTER(c_ushort)) else: # Use the memhandle_as_ctypes_array_32 method for devices with a # resolution > 16 self.ctypes_array = cast(self.input_memhandle, POINTER(c_ulong)) # Start updating the displayed values self.update_input_displayed_values(range_) def update_input_displayed_values(self, range_): # Get the status from the device status, curr_count, curr_index = ul.get_status(self.board_num, FunctionType.AIFUNCTION) # Display the status info self.update_input_status_labels(status, curr_count, curr_index) # Display the values self.display_input_values(range_, curr_index, curr_count) # Call this method again until the stop_input button is pressed if status == Status.RUNNING: self.after(100, self.update_input_displayed_values, range_) else: # Free the allocated memory ul.win_buf_free(self.input_memhandle) self.set_input_ui_idle_state() def update_input_status_labels(self, status, curr_count, curr_index): if status == Status.IDLE: self.input_status_label["text"] = "Idle" else: self.input_status_label["text"] = "Running" self.input_index_label["text"] = str(curr_index) self.input_count_label["text"] = str(curr_count) def display_input_values(self, range_, curr_index, curr_count): per_channel_display_count = 10 array = self.ctypes_array low_chan = self.input_low_chan high_chan = self.input_high_chan channel_text = [] # Add the headers for chan_num in range(low_chan, high_chan + 1): channel_text.append("Channel " + str(chan_num) + "\n") # If no data has been gathered, don't add data to the labels if curr_count > 1: chan_count = high_chan - low_chan + 1 chan_num = low_chan # curr_index points to the start_input of the last completed # channel scan that was transferred between the board and the data # buffer. Based on this, calculate the first index we want to # display using subtraction. first_index = max(curr_index - ((per_channel_display_count - 1) * chan_count), 0) # Add (up to) the latest 10 values for each channel to the text for data_index in range( first_index, first_index + min( chan_count * per_channel_display_count, curr_count)): raw_value = array[data_index] if self.ai_info.resolution <= 16: eng_value = ul.to_eng_units(self.board_num, range_, raw_value) else: eng_value = ul.to_eng_units_32(self.board_num, range_, raw_value) channel_text[chan_num - low_chan] += ( '{:.3f}'.format(eng_value) + "\n") chan_num = low_chan if chan_num == high_chan else chan_num + 1 # Update the labels for each channel for chan_num in range(low_chan, high_chan + 1): chan_index = chan_num - low_chan self.chan_labels[chan_index]["text"] = channel_text[chan_index] def recreate_input_data_frame(self): low_chan = self.input_low_chan high_chan = self.input_high_chan new_data_frame = tk.Frame(self.input_inner_data_frame) self.chan_labels = [] # Add the labels for each channel for chan_num in range(low_chan, high_chan + 1): chan_label = tk.Label(new_data_frame, justify=tk.LEFT, padx=3) chan_label.grid(row=0, column=chan_num - low_chan) self.chan_labels.append(chan_label) self.data_frame.destroy() self.data_frame = new_data_frame self.data_frame.grid() def exit(self): self.stop_input() self.stop_output() self.master.destroy() def start_output_scan(self): # Build the data array self.output_low_chan = self.get_output_low_channel_num() self.output_high_chan = self.get_output_high_channel_num() self.num_output_chans = ( self.output_high_chan - self.output_low_chan + 1) if self.output_low_chan > self.output_high_chan: messagebox.showerror( "Error", "Low Channel Number must be greater than or equal to High " "Channel Number") self.set_output_ui_idle_state() return points_per_channel = 1000 rate = 1000 num_points = self.num_output_chans * points_per_channel scan_options = (ScanOptions.BACKGROUND | ScanOptions.CONTINUOUS | ScanOptions.SCALEDATA) ao_range = self.ao_info.supported_ranges[0] self.output_memhandle = ul.scaled_win_buf_alloc(num_points) # Check if the buffer was successfully allocated if not self.output_memhandle: messagebox.showerror("Error", "Failed to allocate memory") self.output_start_button["state"] = tk.NORMAL return try: data_array = cast(self.output_memhandle, POINTER(c_double)) frequencies = self.add_output_example_data( data_array, ao_range, self.num_output_chans, rate, points_per_channel) self.recreate_freq_frame() self.display_output_signal_info(frequencies) ul.a_out_scan( self.board_num, self.output_low_chan, self.output_high_chan, num_points, rate, ao_range, self.output_memhandle, scan_options) # Start updating the displayed values self.update_output_displayed_values() except ULError as e: show_ul_error(e) self.set_output_ui_idle_state() return def display_output_signal_info(self, frequencies): for channel_num in range( self.output_low_chan, self.output_high_chan + 1): curr_row = channel_num - self.output_low_chan self.freq_labels[curr_row]["text"] = str( frequencies[curr_row]) + " Hz" def add_output_example_data(self, data_array, ao_range, num_chans, rate, points_per_channel): # Calculate frequencies that will work well with the size of the array frequencies = [] for channel_num in range(0, num_chans): frequencies.append( (channel_num + 1) / (points_per_channel / rate)) # Calculate an amplitude and y-offset for the signal # to fill the analog output range amplitude = (ao_range.range_max - ao_range.range_min) / 2 y_offset = (amplitude + ao_range.range_min) / 2 # Fill the array with sine wave data at the calculated frequencies. # Note that since we are using the SCALEDATA option, the values # added to data_array are the actual voltage values that the device # will output data_index = 0 for point_num in range(0, points_per_channel): for channel_num in range(0, num_chans): freq = frequencies[channel_num] value = amplitude * math.sin( 2 * math.pi * freq * point_num / rate) + y_offset data_array[data_index] = value data_index += 1 return frequencies def update_output_displayed_values(self): # Get the status from the device status, curr_count, curr_index = ul.get_status(self.board_num, FunctionType.AOFUNCTION) # Display the status info self.update_output_status_labels(status, curr_count, curr_index) # Call this method again until the stop button is pressed if status == Status.RUNNING: self.after(100, self.update_output_displayed_values) else: # Free the allocated memory ul.win_buf_free(self.output_memhandle) self.set_output_ui_idle_state() def update_output_status_labels(self, status, curr_count, curr_index): if status == Status.IDLE: self.output_status_label["text"] = "Idle" else: self.output_status_label["text"] = "Running" self.output_index_label["text"] = str(curr_index) self.output_count_label["text"] = str(curr_count) def recreate_freq_frame(self): low_chan = self.output_low_chan high_chan = self.output_high_chan new_freq_frame = tk.Frame(self.freq_inner_frame) curr_row = 0 self.freq_labels = [] for chan_num in range(low_chan, high_chan + 1): curr_row += 1 channel_label = tk.Label(new_freq_frame) channel_label["text"] = ( "Channel " + str(chan_num) + " Frequency:") channel_label.grid(row=curr_row, column=0, sticky=tk.W) freq_label = tk.Label(new_freq_frame) freq_label.grid(row=curr_row, column=1, sticky=tk.W) self.freq_labels.append(freq_label) self.freq_frame.destroy() self.freq_frame = new_freq_frame self.freq_frame.grid() def stop_output(self): ul.stop_background(self.board_num, FunctionType.AOFUNCTION) def set_output_ui_idle_state(self): self.output_high_channel_entry["state"] = tk.NORMAL self.output_low_channel_entry["state"] = tk.NORMAL self.output_start_button["command"] = self.start_output self.output_start_button["text"] = "Start Analog Output" def start_output(self): self.output_high_channel_entry["state"] = tk.DISABLED self.output_low_channel_entry["state"] = tk.DISABLED self.output_start_button["command"] = self.stop_output self.output_start_button["text"] = "Stop Analog Output" self.start_output_scan() def stop_input(self): ul.stop_background(self.board_num, FunctionType.AIFUNCTION) def set_input_ui_idle_state(self): self.input_high_channel_entry["state"] = tk.NORMAL self.input_low_channel_entry["state"] = tk.NORMAL self.input_start_button["command"] = self.start_input self.input_start_button["text"] = "Start Analog Input" def start_input(self): self.input_high_channel_entry["state"] = tk.DISABLED self.input_low_channel_entry["state"] = tk.DISABLED self.input_start_button["command"] = self.stop_input self.input_start_button["text"] = "Stop Analog Input" self.start_input_scan() def get_input_low_channel_num(self): if self.ai_info.num_chans == 1: return 0 try: return int(self.input_low_channel_entry.get()) except ValueError: return 0 def get_input_high_channel_num(self): if self.ai_info.num_chans == 1: return 0 try: return int(self.input_high_channel_entry.get()) except ValueError: return 0 def get_output_low_channel_num(self): if self.ao_info.num_chans == 1: return 0 try: return int(self.output_low_channel_entry.get()) except ValueError: return 0 def get_output_high_channel_num(self): if self.ao_info.num_chans == 1: return 0 try: return int(self.output_high_channel_entry.get()) except ValueError: return 0 def validate_channel_entry(self, p): if p == '': return True try: value = int(p) if value < 0 or value > self.ai_info.num_chans - 1: return False except ValueError: return False return True def create_widgets(self): '''Create the tkinter UI''' self.device_label = tk.Label(self) self.device_label.pack(fill=tk.NONE, anchor=tk.NW) self.device_label["text"] = ('Board Number ' + str(self.board_num) + ": " + self.device_info.product_name + " (" + self.device_info.unique_id + ")") channel_vcmd = self.register(self.validate_channel_entry) main_frame = tk.Frame(self) main_frame.pack(fill=tk.X, anchor=tk.NW) input_groupbox = tk.LabelFrame(main_frame, text="Analog Input") input_groupbox.pack(side=tk.LEFT, anchor=tk.NW) if self.ai_info.num_chans > 1: curr_row = 0 input_channels_frame = tk.Frame(input_groupbox) input_channels_frame.pack(fill=tk.X, anchor=tk.NW) input_low_channel_entry_label = tk.Label( input_channels_frame) input_low_channel_entry_label["text"] = ( "Low Channel Number:") input_low_channel_entry_label.grid( row=curr_row, column=0, sticky=tk.W) self.input_low_channel_entry = tk.Spinbox( input_channels_frame, from_=0, to=max(self.ai_info.num_chans - 1, 0), validate='key', validatecommand=(channel_vcmd, '%P')) self.input_low_channel_entry.grid( row=curr_row, column=1, sticky=tk.W) curr_row += 1 input_high_channel_entry_label = tk.Label( input_channels_frame) input_high_channel_entry_label["text"] = ( "High Channel Number:") input_high_channel_entry_label.grid( row=curr_row, column=0, sticky=tk.W) self.input_high_channel_entry = tk.Spinbox( input_channels_frame, from_=0, to=max(self.ai_info.num_chans - 1, 0), validate='key', validatecommand=(channel_vcmd, '%P')) self.input_high_channel_entry.grid( row=curr_row, column=1, sticky=tk.W) initial_value = min(self.ai_info.num_chans - 1, 3) self.input_high_channel_entry.delete(0, tk.END) self.input_high_channel_entry.insert(0, str(initial_value)) curr_row += 1 self.input_start_button = tk.Button(input_groupbox) self.input_start_button["text"] = "Start Analog Input" self.input_start_button["command"] = self.start_input self.input_start_button.pack( fill=tk.X, anchor=tk.NW, padx=3, pady=3) self.input_results_group = tk.LabelFrame( input_groupbox, text="Results", padx=3, pady=3) self.input_results_group.pack( fill=tk.X, anchor=tk.NW, padx=3, pady=3) self.input_results_group.grid_columnconfigure(1, weight=1) curr_row = 0 input_status_left_label = tk.Label(self.input_results_group) input_status_left_label["text"] = "Status:" input_status_left_label.grid( row=curr_row, column=0, sticky=tk.W) self.input_status_label = tk.Label(self.input_results_group) self.input_status_label["text"] = "Idle" self.input_status_label.grid( row=curr_row, column=1, sticky=tk.W) curr_row += 1 input_index_left_label = tk.Label(self.input_results_group) input_index_left_label["text"] = "Index:" input_index_left_label.grid(row=curr_row, column=0, sticky=tk.W) self.input_index_label = tk.Label(self.input_results_group) self.input_index_label["text"] = "-1" self.input_index_label.grid(row=curr_row, column=1, sticky=tk.W) curr_row += 1 input_count_left_label = tk.Label(self.input_results_group) input_count_left_label["text"] = "Count:" input_count_left_label.grid(row=curr_row, column=0, sticky=tk.W) self.input_count_label = tk.Label(self.input_results_group) self.input_count_label["text"] = "0" self.input_count_label.grid(row=curr_row, column=1, sticky=tk.W) curr_row += 1 self.input_inner_data_frame = tk.Frame(self.input_results_group) self.input_inner_data_frame.grid( row=curr_row, column=0, columnspan=2, sticky=tk.W) self.data_frame = tk.Frame(self.input_inner_data_frame) self.data_frame.grid() output_groupbox = tk.LabelFrame( main_frame, text="Analog Output") output_groupbox.pack(side=tk.RIGHT, anchor=tk.NW) if self.ao_info.num_chans > 1: curr_row = 0 output_channels_frame = tk.Frame(output_groupbox) output_channels_frame.pack(fill=tk.X, anchor=tk.NW) output_low_channel_entry_label = tk.Label( output_channels_frame) output_low_channel_entry_label["text"] = ( "Low Channel Number:") output_low_channel_entry_label.grid( row=curr_row, column=0, sticky=tk.W) self.output_low_channel_entry = tk.Spinbox( output_channels_frame, from_=0, to=max(self.ao_info.num_chans - 1, 0), validate='key', validatecommand=(channel_vcmd, '%P')) self.output_low_channel_entry.grid( row=curr_row, column=1, sticky=tk.W) curr_row += 1 output_high_channel_entry_label = tk.Label( output_channels_frame) output_high_channel_entry_label["text"] = ( "High Channel Number:") output_high_channel_entry_label.grid( row=curr_row, column=0, sticky=tk.W) self.output_high_channel_entry = tk.Spinbox( output_channels_frame, from_=0, to=max(self.ao_info.num_chans - 1, 0), validate='key', validatecommand=(channel_vcmd, '%P')) self.output_high_channel_entry.grid( row=curr_row, column=1, sticky=tk.W) initial_value = min(self.ao_info.num_chans - 1, 3) self.output_high_channel_entry.delete(0, tk.END) self.output_high_channel_entry.insert(0, str(initial_value)) self.output_start_button = tk.Button(output_groupbox) self.output_start_button["text"] = "Start Analog Output" self.output_start_button["command"] = self.start_output self.output_start_button.pack( fill=tk.X, anchor=tk.NW, padx=3, pady=3) output_scan_info_group = tk.LabelFrame( output_groupbox, text="Scan Information", padx=3, pady=3) output_scan_info_group.pack( fill=tk.X, anchor=tk.NW, padx=3, pady=3) output_scan_info_group.grid_columnconfigure(1, weight=1) curr_row = 0 output_status_left_label = tk.Label(output_scan_info_group) output_status_left_label["text"] = "Status:" output_status_left_label.grid( row=curr_row, column=0, sticky=tk.W) self.output_status_label = tk.Label(output_scan_info_group) self.output_status_label["text"] = "Idle" self.output_status_label.grid( row=curr_row, column=1, sticky=tk.W) curr_row += 1 output_index_left_label = tk.Label(output_scan_info_group) output_index_left_label["text"] = "Index:" output_index_left_label.grid( row=curr_row, column=0, sticky=tk.W) self.output_index_label = tk.Label(output_scan_info_group) self.output_index_label["text"] = "-1" self.output_index_label.grid( row=curr_row, column=1, sticky=tk.W) curr_row += 1 output_count_left_label = tk.Label(output_scan_info_group) output_count_left_label["text"] = "Count:" output_count_left_label.grid( row=curr_row, column=0, sticky=tk.W) self.output_count_label = tk.Label(output_scan_info_group) self.output_count_label["text"] = "0" self.output_count_label.grid( row=curr_row, column=1, sticky=tk.W) curr_row += 1 self.freq_inner_frame = tk.Frame(output_scan_info_group) self.freq_inner_frame.grid( row=curr_row, column=0, columnspan=2, sticky=tk.W) self.freq_frame = tk.Frame(self.freq_inner_frame) self.freq_frame.grid() button_frame = tk.Frame(self) button_frame.pack(fill=tk.X, side=tk.RIGHT, anchor=tk.SE) self.quit_button = tk.Button(button_frame) self.quit_button["text"] = "Quit" self.quit_button["command"] = self.exit self.quit_button.grid(row=0, column=1, padx=3, pady=3)
class ULAI01(UIExample): def __init__(self, master): super(ULAI01, self).__init__(master) # By default, the example detects all available devices and selects the # first device listed. # If use_device_detection is set to False, the board_num property needs # to match the desired board number configured with Instacal. use_device_detection = True self.board_num = 0 self.running = False try: if use_device_detection: self.configure_first_detected_device() self.device_info = DaqDeviceInfo(self.board_num) if self.device_info.supports_analog_input: self.ai_info = self.device_info.get_ai_info() self.create_widgets() else: self.create_unsupported_widgets() except ULError: self.create_unsupported_widgets(True) def update_value(self): channel = self.get_channel_num() ai_range = self.ai_info.supported_ranges[0] try: # Get a value from the device if self.ai_info.resolution <= 16: # Use the a_in method for devices with a resolution <= 16 value = ul.a_in(self.board_num, channel, ai_range) # Convert the raw value to engineering units eng_units_value = ul.to_eng_units(self.board_num, ai_range, value) else: # Use the a_in_32 method for devices with a resolution > 16 # (optional parameter omitted) value = ul.a_in_32(self.board_num, channel, ai_range) # Convert the raw value to engineering units eng_units_value = ul.to_eng_units_32(self.board_num, ai_range, value) # Display the raw value self.value_label["text"] = str(value) # Display the engineering value self.eng_value_label["text"] = '{:.3f}'.format(eng_units_value) # Call this method again until the stop button is pressed (or an # error occurs) if self.running: self.after(100, self.update_value) except ULError as e: self.stop() show_ul_error(e) def stop(self): self.running = False self.start_button["command"] = self.start self.start_button["text"] = "Start" def start(self): self.running = True self.start_button["command"] = self.stop self.start_button["text"] = "Stop" self.update_value() def get_channel_num(self): if self.ai_info.num_chans == 1: return 0 try: return int(self.channel_entry.get()) except ValueError: return 0 def validate_channel_entry(self, p): if p == '': return True try: value = int(p) if value < 0 or value > self.ai_info.num_chans - 1: return False except ValueError: return False return True def create_widgets(self): '''Create the tkinter UI''' self.device_label = tk.Label(self) self.device_label.pack(fill=tk.NONE, anchor=tk.NW) self.device_label["text"] = ('Board Number ' + str(self.board_num) + ": " + self.device_info.product_name + " (" + self.device_info.unique_id + ")") main_frame = tk.Frame(self) main_frame.pack(fill=tk.X, anchor=tk.NW) curr_row = 0 if self.ai_info.num_chans > 1: channel_vcmd = self.register(self.validate_channel_entry) channel_entry_label = tk.Label(main_frame) channel_entry_label["text"] = "Channel Number:" channel_entry_label.grid( row=curr_row, column=0, sticky=tk.W) self.channel_entry = tk.Spinbox( main_frame, from_=0, to=max(self.ai_info.num_chans - 1, 0), validate='key', validatecommand=(channel_vcmd, '%P')) self.channel_entry.grid( row=curr_row, column=1, sticky=tk.W) curr_row += 1 raw_value_left_label = tk.Label(main_frame) raw_value_left_label["text"] = "Value read from selected channel:" raw_value_left_label.grid(row=curr_row, column=0, sticky=tk.W) self.value_label = tk.Label(main_frame) self.value_label.grid(row=curr_row, column=1, sticky=tk.W) curr_row += 1 eng_value_left_label = tk.Label(main_frame) eng_value_left_label["text"] = "Value converted to voltage:" eng_value_left_label.grid(row=curr_row, column=0, sticky=tk.W) self.eng_value_label = tk.Label(main_frame) self.eng_value_label.grid(row=curr_row, column=1, sticky=tk.W) button_frame = tk.Frame(self) button_frame.pack(fill=tk.X, side=tk.RIGHT, anchor=tk.SE) self.start_button = tk.Button(button_frame) self.start_button["text"] = "Start" self.start_button["command"] = self.start self.start_button.grid(row=0, column=0, padx=3, pady=3) quit_button = tk.Button(button_frame) quit_button["text"] = "Quit" quit_button["command"] = self.master.destroy quit_button.grid(row=0, column=1, padx=3, pady=3)
class TimerOutStart01(UIExample): def __init__(self, master=None): super(TimerOutStart01, self).__init__(master) master.protocol("WM_DELETE_WINDOW", self.exit) # By default, the example detects all available devices and selects the # first device listed. # If use_device_detection is set to False, the board_num property needs # to match the desired board number configured with Instacal. use_device_detection = True self.board_num = 0 self.first_chan_num = -1 self.last_chan_num = -1 try: if use_device_detection: self.configure_first_detected_device() self.device_info = DaqDeviceInfo(self.board_num) counter_info = self.device_info.get_ctr_info() # Find the first pulse counter first_chan = next((channel for channel in counter_info.chan_info if channel.type == CounterChannelType.CTRTMR), None) if first_chan is not None: last_chan = next( (channel for channel in reversed(counter_info.chan_info) if channel.type == CounterChannelType.CTRTMR), None) self.first_chan_num = first_chan.channel_num self.last_chan_num = last_chan.channel_num self.create_widgets() else: self.create_unsupported_widgets() except ULError: self.create_unsupported_widgets(True) def update_output(self): try: timer_num = self.get_channel_num() frequency = self.get_frequency() actual_freq = ul.timer_out_start(self.board_num, timer_num, frequency) self.update_actual_values(actual_freq) except ULError as e: show_ul_error(e) def exit(self): # Stop all the timers at exit if self.first_chan_num != -1: for chan_num in range(self.first_chan_num, self.last_chan_num + 1): try: ul.timer_out_stop(self.board_num, chan_num) except ULError as e: show_ul_error(e) self.master.destroy() def update_actual_values(self, actual_freq): self.actual_freq_label["text"] = str(actual_freq) def get_frequency(self): try: return float(self.freq_entry.get()) except ValueError: return 100000 def get_channel_num(self): if self.last_chan_num == self.first_chan_num: return self.last_chan_num try: return int(self.channel_entry.get()) except ValueError: return 0 def validate_channel_entry(self, p): if p == '': return True try: value = int(p) if value < self.first_chan_num or value > self.last_chan_num: return False except ValueError: return False return True def create_widgets(self): '''Create the tkinter UI''' self.device_label = tk.Label(self) self.device_label.pack(fill=tk.NONE, anchor=tk.NW) self.device_label["text"] = ('Board Number ' + str(self.board_num) + ": " + self.device_info.product_name + " (" + self.device_info.unique_id + ")") main_frame = tk.Frame(self) main_frame.pack(fill=tk.X, anchor=tk.NW) channel_vcmd = self.register(self.validate_channel_entry) float_vcmd = self.register(validate_float_entry) curr_row = 0 if self.last_chan_num != self.first_chan_num: channel_entry_label = tk.Label(main_frame) channel_entry_label["text"] = "Channel Number:" channel_entry_label.grid(row=curr_row, column=0, sticky=tk.W) self.channel_entry = tk.Spinbox(main_frame, from_=self.first_chan_num, to=self.last_chan_num, validate='key', validatecommand=(channel_vcmd, '%P')) self.channel_entry.grid(row=curr_row, column=1, sticky=tk.W) curr_row += 1 freq_label = tk.Label(main_frame) freq_label["text"] = "Frequency:" freq_label.grid(row=curr_row, column=0, sticky=tk.W) self.freq_entry = tk.Entry(main_frame, validate='key', validatecommand=(float_vcmd, '%P')) self.freq_entry.grid(row=curr_row, column=1, sticky=tk.W) self.freq_entry.insert(0, "100000") curr_row += 1 update_button = tk.Button(main_frame) update_button["text"] = "Update" update_button["command"] = self.update_output update_button.grid(row=curr_row, column=0, columnspan=2, padx=3, pady=3) curr_row += 1 actual_freq_left_label = tk.Label(main_frame) actual_freq_left_label["text"] = "Actual Frequency:" actual_freq_left_label.grid(row=curr_row, column=0, sticky=tk.W) self.actual_freq_label = tk.Label(main_frame) self.actual_freq_label.grid(row=curr_row, column=1, sticky=tk.W) button_frame = tk.Frame(self) button_frame.pack(fill=tk.X, side=tk.RIGHT, anchor=tk.SE) quit_button = tk.Button(button_frame) quit_button["text"] = "Quit" quit_button["command"] = self.exit quit_button.grid(row=0, column=1, padx=3, pady=3)
class DaqSetSetpoints01(UIExample): def __init__(self, master=None): super(DaqSetSetpoints01, self).__init__(master) # By default, the example detects all available devices and selects the # first device listed. # If use_device_detection is set to False, the board_num property needs # to match the desired board number configured with Instacal. use_device_detection = True self.board_num = 0 self.chan_list = [] self.chan_type_list = [] self.gain_list = [] self.num_chans = 4 self.setpoint_flags_list = [] self.setpoint_output_list = [] self.limit_a_list = [] self.limit_b_list = [] self.output_1_list = [] self.output_2_list = [] self.output_mask_1_list = [] self.output_mask_2_list = [] self.setpoint_count = 3 try: if use_device_detection: self.configure_first_detected_device() self.device_info = DaqDeviceInfo(self.board_num) daqi_info = self.device_info.get_daqi_info() if (self.device_info.supports_daq_input and daqi_info.supports_setpoints): self.init_scan_channel_info() self.init_setpoints() self.create_widgets() else: self.create_unsupported_widgets() except ULError: self.create_unsupported_widgets(True) def init_scan_channel_info(self): # Add analog input channels self.chan_list.append(0) self.chan_type_list.append(ChannelType.ANALOG + ChannelType.SETPOINT_ENABLE) self.gain_list.append(ULRange.BIP10VOLTS) self.chan_list.append(1) self.chan_type_list.append(ChannelType.ANALOG + ChannelType.SETPOINT_ENABLE) self.gain_list.append(ULRange.BIP10VOLTS) # Add a digital input channel self.chan_list.append(DigitalPortType.FIRSTPORTA) self.chan_type_list.append(ChannelType.DIGITAL8 + ChannelType.SETPOINT_ENABLE) self.gain_list.append(ULRange.NOTUSED) # Add a setpoint status channel self.chan_list.append(0) self.chan_type_list.append(ChannelType.SETPOINTSTATUS) self.gain_list.append(ULRange.NOTUSED) def init_setpoints(self): # Setpoint configurations for ChanArray[0] (CH0) self.setpoint_flags_list.append(SetpointFlag.LESSTHAN_LIMITA + SetpointFlag.UPDATEON_TRUEANDFALSE) # Setpoint result outputs a value to Analog Out 0 self.setpoint_output_list.append(SetpointOutput.DAC0) # If CH0 less than 3.0 volts apply output1, else apply output2 self.limit_a_list.append(3) self.limit_b_list.append(0) # Ignored when LessThanLimitA flag is used self.output_1_list.append(5) # Output 5.0 volts on Analog Out 0 self.output_2_list.append(-5) # Output -5.0 volts on Analog Out 0 self.output_mask_1_list.append(0) # Ignored for DAC0 output type self.output_mask_2_list.append(0) # Ignored for DAC0 output type # Setpoint configurations for ChanArray[1] (CH1) self.setpoint_flags_list.append(SetpointFlag.GREATERTHAN_LIMITB + SetpointFlag.UPDATEON_TRUEANDFALSE) # Setpoint result outputs a value to digital port C self.setpoint_output_list.append(SetpointOutput.FIRSTPORTC) # Ignored when GreaterThanLimitB flag is used self.limit_a_list.append(0) # If CH1 greater than 2.0 volts apply output1 self.limit_b_list.append(2) # Output a bit pattern of 01010101 to digital port C self.output_1_list.append(0x55) # Output a bit pattern of 10101010 to digital port C self.output_2_list.append(0xAA) # Output the value of 'out1' on low nibble only self.output_mask_1_list.append(0x0F) # Output the value of 'out2' on low nibble only self.output_mask_2_list.append(0x0F) # Setpoint configurations for ChanArray[2] (FIRSTPORTA) self.setpoint_flags_list.append(SetpointFlag.EQUAL_LIMITA | SetpointFlag.UPDATEON_TRUEONLY) # Setpoint result outputs a value to Timer 0 self.setpoint_output_list.append(SetpointOutput.TMR0) # If FirstPortA equal 00001111 bit pattern apply output1 self.limit_a_list.append(0x0F) self.limit_b_list.append(2) # Ignored when EqualLimitA flag is used self.output_1_list.append(100) # Output a 100Hz square wave on Timer 0 # Ignored when SF_UPDATEON_TRUEONLY flag is used self.output_2_list.append(0) self.output_mask_1_list.append(0) # Ignored for 'TMR0' output type self.output_mask_2_list.append(0) # Ignored for 'TMR0' output type def start_scan(self): rate = 100 points_per_channel = 100 total_count = points_per_channel * self.num_chans scan_options = ScanOptions.BACKGROUND | ScanOptions.CONTINUOUS # Allocate a buffer for the scan self.memhandle = ul.win_buf_alloc(total_count) # Check if the buffer was successfully allocated if not self.memhandle: messagebox.showerror("Error", "Failed to allocate memory") self.start_button["state"] = tk.NORMAL return try: # Configure the setpoints ul.daq_set_setpoints(self.board_num, self.limit_a_list, self.limit_b_list, self.setpoint_flags_list, self.setpoint_output_list, self.output_1_list, self.output_2_list, self.output_mask_1_list, self.output_mask_2_list, self.setpoint_count) # Run the scan ul.daq_in_scan(self.board_num, self.chan_list, self.chan_type_list, self.gain_list, self.num_chans, rate, 0, total_count, self.memhandle, scan_options) # Cast the memhandle to a ctypes pointer # Note: the ctypes array will only be valid until win_buf_free # is called. # A copy of the buffer can be created using win_buf_to_array # before the memory is freed. The copy can be used at any time. self.array = cast(self.memhandle, POINTER(c_ushort)) except ULError as e: # Free the allocated memory ul.win_buf_free(self.memhandle) show_ul_error(e) return # Start updating the displayed values self.update_displayed_values() def update_displayed_values(self): # Get the status from the device status, curr_count, curr_index = ul.get_status( self.board_num, FunctionType.DAQIFUNCTION) # Display the status info self.update_status_labels(status, curr_count, curr_index) # Display the values self.display_values(curr_index, curr_count) # Call this method again until the stop button is pressed if status == Status.RUNNING: self.after(100, self.update_displayed_values) else: # Free the allocated memory ul.win_buf_free(self.memhandle) self.set_ui_idle_state() def update_status_labels(self, status, curr_count, curr_index): if status == Status.IDLE: self.setpoint_status_label["text"] = "Idle" else: self.setpoint_status_label["text"] = "Running" self.index_label["text"] = str(curr_index) self.count_label["text"] = str(curr_count) def display_values(self, curr_index, curr_count): array = self.array # If no data has been gathered, don't add data to the labels if curr_count > 1: # Convert the CH0 value to volts and display it chan_0_eng_value = ul.to_eng_units(self.board_num, self.gain_list[0], array[curr_index]) self.chan_0_label["text"] = '{:.3f}'.format( chan_0_eng_value) + " Volts" # Convert the CH1 value to volts and display it chan_1_eng_value = ul.to_eng_units(self.board_num, self.gain_list[0], array[curr_index + 1]) self.chan_1_label["text"] = '{:.3f}'.format( chan_1_eng_value) + " Volts" # Display the digital port value as hex self.digital_label["text"] = '0x' + \ '{:0<2X}'.format(array[curr_index + 2]) # Display the setpoint status as hex self.setpoint_status_label["text"] = '0x' + \ '{:0<4X}'.format(array[curr_index + 3]) def stop(self): ul.stop_background(self.board_num, FunctionType.DAQIFUNCTION) def set_ui_idle_state(self): self.start_button["command"] = self.start self.start_button["text"] = "Start" def start(self): self.start_button["command"] = self.stop self.start_button["text"] = "Stop" self.start_scan() def create_widgets(self): '''Create the tkinter UI''' self.device_label = tk.Label(self) self.device_label.pack(fill=tk.NONE, anchor=tk.NW) self.device_label["text"] = ('Board Number ' + str(self.board_num) + ": " + self.device_info.product_name + " (" + self.device_info.unique_id + ")") main_frame = tk.Frame(self) main_frame.pack(fill=tk.X, anchor=tk.NW) curr_row = 0 chan_0_left_label = tk.Label(main_frame, justify=tk.LEFT, padx=3) chan_0_left_label["text"] = "Channel 0:" chan_0_left_label.grid(row=curr_row, column=0, sticky=tk.W) self.chan_0_label = tk.Label(main_frame, justify=tk.LEFT, padx=3) self.chan_0_label.grid(row=curr_row, column=1, sticky=tk.W) curr_row += 1 chan_1_left_label = tk.Label(main_frame, justify=tk.LEFT, padx=3) chan_1_left_label["text"] = "Channel 1:" chan_1_left_label.grid(row=curr_row, column=0, sticky=tk.W) self.chan_1_label = tk.Label(main_frame, justify=tk.LEFT, padx=3) self.chan_1_label.grid(row=curr_row, column=1, sticky=tk.W) curr_row += 1 digital_left_label = tk.Label(main_frame, justify=tk.LEFT, padx=3) digital_left_label["text"] = "FIRSTPORTA:" digital_left_label.grid(row=curr_row, column=0, sticky=tk.W) self.digital_label = tk.Label(main_frame, justify=tk.LEFT, padx=3) self.digital_label.grid(row=curr_row, column=1, sticky=tk.W) curr_row += 1 setpoint_status_left_label = tk.Label(main_frame, justify=tk.LEFT, padx=3) setpoint_status_left_label["text"] = "Status:" setpoint_status_left_label.grid(row=curr_row, column=0, sticky=tk.W) self.setpoint_status_label = tk.Label(main_frame, justify=tk.LEFT, padx=3) self.setpoint_status_label["text"] = "Idle" self.setpoint_status_label.grid(row=curr_row, column=1, sticky=tk.W) curr_row += 1 index_left_label = tk.Label(main_frame, justify=tk.LEFT, padx=3) index_left_label["text"] = "Index:" index_left_label.grid(row=curr_row, column=0, sticky=tk.W) self.index_label = tk.Label(main_frame, justify=tk.LEFT, padx=3) self.index_label["text"] = "-1" self.index_label.grid(row=curr_row, column=1, sticky=tk.W) curr_row += 1 count_left_label = tk.Label(main_frame, justify=tk.LEFT, padx=3) count_left_label["text"] = "Count:" count_left_label.grid(row=curr_row, column=0, sticky=tk.W) self.count_label = tk.Label(main_frame, justify=tk.LEFT, padx=3) self.count_label["text"] = "0" self.count_label.grid(row=curr_row, column=1, sticky=tk.W) button_frame = tk.Frame(self) button_frame.pack(fill=tk.X, side=tk.RIGHT, anchor=tk.SE) self.start_button = tk.Button(button_frame) self.start_button["text"] = "Start" self.start_button["command"] = self.start self.start_button.grid(row=0, column=0, padx=3, pady=3) quit_button = tk.Button(button_frame) quit_button["text"] = "Quit" quit_button["command"] = self.master.destroy quit_button.grid(row=0, column=1, padx=3, pady=3)
class ULAI03(UIExample): def __init__(self, master=None): super(ULAI03, self).__init__(master) # By default, the example detects all available devices and selects the # first device listed. # If use_device_detection is set to False, the board_num property needs # to match the desired board number configured with Instacal. use_device_detection = True self.board_num = 0 try: if use_device_detection: self.configure_first_detected_device() self.device_info = DaqDeviceInfo(self.board_num) self.ai_info = self.device_info.get_ai_info() if self.ai_info.is_supported and self.ai_info.supports_scan: self.create_widgets() else: self.create_unsupported_widgets() except ULError: self.create_unsupported_widgets() def start_scan(self): self.low_chan = self.get_low_channel_num() self.high_chan = self.get_high_channel_num() self.num_chans = self.high_chan - self.low_chan + 1 if self.low_chan > self.high_chan: messagebox.showerror( "Error", "Low Channel Number must be greater than or equal to High " "Channel Number") self.set_ui_idle_state() return rate = 100 points_per_channel = 1000 total_count = points_per_channel * self.num_chans ai_range = self.ai_info.supported_ranges[0] # Allocate a buffer for the scan if self.ai_info.resolution <= 16: # Use the win_buf_alloc method for devices with a resolution <= # 16 self.memhandle = ul.win_buf_alloc(total_count) # Convert the memhandle to a ctypes array # Use the memhandle_as_ctypes_array method for devices with a # resolution <= 16 self.ctypes_array = cast(self.memhandle, POINTER(c_ushort)) else: # Use the win_buf_alloc_32 method for devices with a resolution # > 16 self.memhandle = ul.win_buf_alloc_32(total_count) # Use the memhandle_as_ctypes_array_32 method for devices with a # resolution > 16 self.ctypes_array = cast(self.memhandle, POINTER(c_ulong)) # Note: the ctypes array will no longer be valid after # win_buf_free is called. # A copy of the buffer can be created using win_buf_to_array # or win_buf_to_array_32 before the memory is freed. The copy # can be used at any time. # Check if the buffer was successfully allocated if not self.memhandle: messagebox.showerror("Error", "Failed to allocate memory") self.set_ui_idle_state() return # Create the frames that will hold the data self.recreate_data_frame() try: # Start the scan ul.a_in_scan(self.board_num, self.low_chan, self.high_chan, total_count, rate, ai_range, self.memhandle, ScanOptions.BACKGROUND) except ULError as e: show_ul_error(e) self.set_ui_idle_state() return # Start updating the displayed values self.update_displayed_values() def update_displayed_values(self): # Get the status from the device status, curr_count, curr_index = ul.get_status(self.board_num, FunctionType.AIFUNCTION) # Display the status info self.update_status_labels(status, curr_count, curr_index) # Display the values self.display_values(curr_index, curr_count) # Call this method again until the stop button is pressed if status == Status.RUNNING: self.after(100, self.update_displayed_values) else: # Free the allocated memory ul.win_buf_free(self.memhandle) # Stop the background operation (this is required even if the # scan completes successfully) ul.stop_background(self.board_num, FunctionType.AIFUNCTION) self.set_ui_idle_state() def update_status_labels(self, status, curr_count, curr_index): if status == Status.IDLE: self.status_label["text"] = "Idle" else: self.status_label["text"] = "Running" self.index_label["text"] = str(curr_index) self.count_label["text"] = str(curr_count) def display_values(self, curr_index, curr_count): per_channel_display_count = 10 array = self.ctypes_array low_chan = self.low_chan high_chan = self.high_chan channel_text = [] # Add the headers for chan_num in range(low_chan, high_chan + 1): channel_text.append("Channel " + str(chan_num) + "\n") # If no data has been gathered, don't add data to the labels if curr_count > 1: chan_count = high_chan - low_chan + 1 chan_num = low_chan # curr_index points to the start of the last completed channel # scan that was transferred between the board and the data # buffer. Based on this, calculate the first index we want to # display using subtraction. first_index = max(curr_index - ((per_channel_display_count - 1) * chan_count), 0) last_index = first_index + min(chan_count * per_channel_display_count, curr_count) # Add (up to) the latest 10 values for each channel to the text for data_index in range(first_index, last_index): channel_text[chan_num - low_chan] += (str(array[data_index]) + "\n") chan_num = low_chan if chan_num == high_chan else chan_num + 1 # Update the labels for each channel for chan_num in range(low_chan, high_chan + 1): chan_index = chan_num - low_chan self.chan_labels[chan_index]["text"] = channel_text[chan_index] def recreate_data_frame(self): low_chan = self.low_chan high_chan = self.high_chan new_data_frame = tk.Frame(self.inner_data_frame) self.chan_labels = [] # Add the labels for each channel for chan_num in range(low_chan, high_chan + 1): chan_label = tk.Label(new_data_frame, justify=tk.LEFT, padx=3) chan_label.grid(row=0, column=chan_num - low_chan) self.chan_labels.append(chan_label) self.data_frame.destroy() self.data_frame = new_data_frame self.data_frame.grid() def stop(self): ul.stop_background(self.board_num, FunctionType.AIFUNCTION) def set_ui_idle_state(self): self.high_channel_entry["state"] = tk.NORMAL self.low_channel_entry["state"] = tk.NORMAL self.start_button["command"] = self.start self.start_button["text"] = "Start" def start(self): self.high_channel_entry["state"] = tk.DISABLED self.low_channel_entry["state"] = tk.DISABLED self.start_button["command"] = self.stop self.start_button["text"] = "Stop" self.start_scan() def get_low_channel_num(self): if self.ai_info.num_chans == 1: return 0 try: return int(self.low_channel_entry.get()) except ValueError: return 0 def get_high_channel_num(self): if self.ai_info.num_chans == 1: return 0 try: return int(self.high_channel_entry.get()) except ValueError: return 0 def validate_channel_entry(self, p): if p == '': return True try: value = int(p) if value < 0 or value > self.ai_info.num_chans - 1: return False except ValueError: return False return True def create_widgets(self): '''Create the tkinter UI''' self.device_label = tk.Label(self) self.device_label.pack(fill=tk.NONE, anchor=tk.NW) self.device_label["text"] = ('Board Number ' + str(self.board_num) + ": " + self.device_info.product_name + " (" + self.device_info.unique_id + ")") main_frame = tk.Frame(self) main_frame.pack(fill=tk.X, anchor=tk.NW) curr_row = 0 if self.ai_info.num_chans > 1: channel_vcmd = self.register(self.validate_channel_entry) low_channel_entry_label = tk.Label(main_frame) low_channel_entry_label["text"] = "Low Channel Number:" low_channel_entry_label.grid( row=curr_row, column=0, sticky=tk.W) self.low_channel_entry = tk.Spinbox( main_frame, from_=0, to=max(self.ai_info.num_chans - 1, 0), validate='key', validatecommand=(channel_vcmd, '%P')) self.low_channel_entry.grid( row=curr_row, column=1, sticky=tk.W) curr_row += 1 high_channel_entry_label = tk.Label(main_frame) high_channel_entry_label["text"] = "High Channel Number:" high_channel_entry_label.grid( row=curr_row, column=0, sticky=tk.W) self.high_channel_entry = tk.Spinbox( main_frame, from_=0, validate='key', to=max(self.ai_info.num_chans - 1, 0), validatecommand=(channel_vcmd, '%P')) self.high_channel_entry.grid( row=curr_row, column=1, sticky=tk.W) initial_value = min(self.ai_info.num_chans - 1, 3) self.high_channel_entry.delete(0, tk.END) self.high_channel_entry.insert(0, str(initial_value)) curr_row += 1 self.results_group = tk.LabelFrame( self, text="Results", padx=3, pady=3) self.results_group.pack(fill=tk.X, anchor=tk.NW, padx=3, pady=3) self.results_group.grid_columnconfigure(1, weight=1) curr_row = 0 status_left_label = tk.Label(self.results_group) status_left_label["text"] = "Status:" status_left_label.grid(row=curr_row, column=0, sticky=tk.W) self.status_label = tk.Label(self.results_group) self.status_label["text"] = "Idle" self.status_label.grid(row=curr_row, column=1, sticky=tk.W) curr_row += 1 index_left_label = tk.Label(self.results_group) index_left_label["text"] = "Index:" index_left_label.grid(row=curr_row, column=0, sticky=tk.W) self.index_label = tk.Label(self.results_group) self.index_label["text"] = "-1" self.index_label.grid(row=curr_row, column=1, sticky=tk.W) curr_row += 1 count_left_label = tk.Label(self.results_group) count_left_label["text"] = "Count:" count_left_label.grid(row=curr_row, column=0, sticky=tk.W) self.count_label = tk.Label(self.results_group) self.count_label["text"] = "0" self.count_label.grid(row=curr_row, column=1, sticky=tk.W) curr_row += 1 self.inner_data_frame = tk.Frame(self.results_group) self.inner_data_frame.grid( row=curr_row, column=0, columnspan=2, sticky=tk.W) self.data_frame = tk.Frame(self.inner_data_frame) self.data_frame.grid() button_frame = tk.Frame(self) button_frame.pack(fill=tk.X, side=tk.RIGHT, anchor=tk.SE) self.start_button = tk.Button(button_frame) self.start_button["text"] = "Start" self.start_button["command"] = self.start self.start_button.grid(row=0, column=0, padx=3, pady=3) self.quit_button = tk.Button(button_frame) self.quit_button["text"] = "Quit" self.quit_button["command"] = self.master.destroy self.quit_button.grid(row=0, column=1, padx=3, pady=3)
class ULCT07(UIExample): def __init__(self, master=None): super(ULCT07, self).__init__(master) # By default, the example detects all available devices and selects the # first device listed. # If use_device_detection is set to False, the board_num property needs # to match the desired board number configured with Instacal. use_device_detection = True self.board_num = 0 self.running = False try: if use_device_detection: self.configure_first_detected_device() self.device_info = DaqDeviceInfo(self.board_num) self.ctr_info = self.device_info.get_ctr_info() if self.ctr_info.is_supported: self.create_widgets() else: self.create_unsupported_widgets() except ULError: self.create_unsupported_widgets(True) def update_value(self): channel = self.get_channel_num() try: # Get a value from the device value = ul.c_in_32(self.board_num, channel) # Display the value self.value_label["text"] = str(value) # Call this method again until the stop button is pressed (or an # error occurs) if self.running: self.after(100, self.update_value) except ULError as e: self.stop() show_ul_error(e) def stop(self): self.running = False self.start_button["command"] = self.start self.start_button["text"] = "Start" def start(self): self.running = True self.start_button["command"] = self.stop self.start_button["text"] = "Stop" try: # Clear the counter ul.c_clear(self.board_num, self.get_channel_num()) # Start updating the counter values self.update_value() except ULError as e: self.stop() show_ul_error(e) def get_channel_num(self): if self.ctr_info.num_chans == 1: return self.ctr_info.chan_info[0].channel_num try: return int(self.channel_entry.get()) except ValueError: return 0 def validate_channel_entry(self, p): if p == '': return True try: value = int(p) if value < 0 or value > self.ctr_info.num_chans - 1: return False except ValueError: return False return True def create_widgets(self): '''Create the tkinter UI''' self.device_label = tk.Label(self) self.device_label.pack(fill=tk.NONE, anchor=tk.NW) self.device_label["text"] = ('Board Number ' + str(self.board_num) + ": " + self.device_info.product_name + " (" + self.device_info.unique_id + ")") main_frame = tk.Frame(self) main_frame.pack(fill=tk.X, anchor=tk.NW) channel_vcmd = self.register(self.validate_channel_entry) curr_row = 0 if self.ctr_info.num_chans > 1: channel_entry_label = tk.Label(main_frame) channel_entry_label["text"] = "Channel Number:" channel_entry_label.grid(row=curr_row, column=0, sticky=tk.W) chan_info_list = self.ctr_info.chan_info first_chan = chan_info_list[0].channel_num # last_chan = chan_info_list[len(chan_info_list) - 1].channel_num last_chan = first_chan for chan_info in chan_info_list: if chan_info.channel_num >= last_chan: last_chan = chan_info.channel_num else: break self.channel_entry = tk.Spinbox(main_frame, from_=first_chan, to=last_chan, validate='key', validatecommand=(channel_vcmd, '%P')) self.channel_entry.grid(row=curr_row, column=1, sticky=tk.W) curr_row += 1 value_left_label = tk.Label(main_frame) value_left_label["text"] = "Value read from selected channel:" value_left_label.grid(row=curr_row, column=0, sticky=tk.W) self.value_label = tk.Label(main_frame) self.value_label.grid(row=curr_row, column=1, sticky=tk.W) button_frame = tk.Frame(self) button_frame.pack(fill=tk.X, side=tk.RIGHT, anchor=tk.SE) self.start_button = tk.Button(button_frame) self.start_button["text"] = "Start" self.start_button["command"] = self.start self.start_button.grid(row=0, column=0, padx=3, pady=3) quit_button = tk.Button(button_frame) quit_button["text"] = "Quit" quit_button["command"] = self.master.destroy quit_button.grid(row=0, column=1, padx=3, pady=3)
class CInScan01(UIExample): def __init__(self, master=None): super(CInScan01, self).__init__(master) # By default, the example detects all available devices and selects the # first device listed. # If use_device_detection is set to False, the board_num property needs # to match the desired board number configured with Instacal. use_device_detection = True self.board_num = 0 self.min_chan_num = -1 self.max_chan_num = -1 try: if use_device_detection: self.configure_first_detected_device() self.device_info = DaqDeviceInfo(self.board_num) counter_info = self.device_info.get_ctr_info() min_chan = next((channel for channel in counter_info.chan_info if channel.type == CounterChannelType.CTRSCAN or channel.type == CounterChannelType.CTRQUAD), None) if min_chan is not None: self.min_chan_num = min_chan.channel_num max_chan = next( (channel for channel in reversed(counter_info.chan_info) if channel.type == CounterChannelType.CTRSCAN or channel.type == CounterChannelType.CTRQUAD), None) if max_chan is not None: self.max_chan_num = max_chan.channel_num if self.min_chan_num != -1 and self.max_chan_num != -1: self.create_widgets() else: self.create_unsupported_widgets() except ULError: self.create_unsupported_widgets(True) def start_scan(self): low_chan = self.get_low_channel_num() high_chan = self.get_high_channel_num() if low_chan > high_chan: messagebox.showerror( "Error", "Low Channel Number must be greater than or equal " "to High Channel Number") self.start_button["state"] = tk.NORMAL return rate = 100 points_per_channel = 10 num_channels = high_chan - low_chan + 1 total_count = points_per_channel * num_channels # Allocate a buffer for the scan memhandle = ul.win_buf_alloc_32(total_count) # Check if the buffer was successfully allocated if not memhandle: messagebox.showerror("Error", "Failed to allocate memory") self.start_button["state"] = tk.NORMAL return try: # Run the scan ul.c_in_scan(self.board_num, low_chan, high_chan, total_count, rate, memhandle, 0) # Convert the memhandle to a ctypes array # Note: the ctypes array will only be valid until win_buf_free # is called. # A copy of the buffer can be created using win_buf_to_array_32 # before the memory is freed. The copy can be used at any time. array = cast(memhandle, POINTER(c_ulong)) # Display the values self.display_values(array, total_count, low_chan, high_chan) except ULError as e: show_ul_error(e) finally: # Free the allocated memory ul.win_buf_free(memhandle) self.start_button["state"] = tk.NORMAL def display_values(self, array, total_count, low_chan, high_chan): new_data_frame = tk.Frame(self.results_group) channel_text = [] # Add the headers for chan_num in range(low_chan, high_chan + 1): channel_text.append("Channel " + str(chan_num) + "\n") chan_count = high_chan - low_chan + 1 # Add (up to) the first 10 values for each channel to the text chan_num = low_chan for data_index in range(0, min(chan_count * 10, total_count)): channel_text[chan_num - low_chan] += str(array[data_index]) + "\n" if chan_num == high_chan: chan_num = low_chan else: chan_num += 1 # Add the labels for each channel for chan_num in range(low_chan, high_chan + 1): chan_label = tk.Label(new_data_frame, justify=tk.LEFT, padx=3) chan_label["text"] = channel_text[chan_num - low_chan] chan_label.grid(row=0, column=chan_num - low_chan) self.data_frame.destroy() self.data_frame = new_data_frame self.data_frame.grid() def start(self): self.start_button["state"] = tk.DISABLED self.start_scan() def get_low_channel_num(self): try: return int(self.low_channel_entry.get()) except ValueError: return 0 def get_high_channel_num(self): try: return int(self.high_channel_entry.get()) except ValueError: return 0 def validate_channel_entry(self, p): if p == '': return True try: value = int(p) if value < self.min_chan_num or value > self.max_chan_num: return False except ValueError: return False return True def create_widgets(self): '''Create the tkinter UI''' self.device_label = tk.Label(self) self.device_label.pack(fill=tk.NONE, anchor=tk.NW) self.device_label["text"] = ('Board Number ' + str(self.board_num) + ": " + self.device_info.product_name + " (" + self.device_info.unique_id + ")") main_frame = tk.Frame(self) main_frame.pack(fill=tk.X, anchor=tk.NW) channel_vcmd = self.register(self.validate_channel_entry) curr_row = 0 low_channel_entry_label = tk.Label(main_frame) low_channel_entry_label["text"] = "Low Channel Number:" low_channel_entry_label.grid(row=curr_row, column=0, sticky=tk.W) self.low_channel_entry = tk.Spinbox(main_frame, from_=self.min_chan_num, to=self.max_chan_num, validate='key', validatecommand=(channel_vcmd, '%P')) self.low_channel_entry.grid(row=curr_row, column=1, sticky=tk.W) curr_row += 1 high_channel_entry_label = tk.Label(main_frame) high_channel_entry_label["text"] = "High Channel Number:" high_channel_entry_label.grid(row=curr_row, column=0, sticky=tk.W) self.high_channel_entry = tk.Spinbox(main_frame, from_=self.min_chan_num, to=self.max_chan_num, validate='key', validatecommand=(channel_vcmd, '%P')) self.high_channel_entry.grid(row=curr_row, column=1, sticky=tk.W) initial_value = self.max_chan_num self.high_channel_entry.delete(0, tk.END) self.high_channel_entry.insert(0, str(initial_value)) self.results_group = tk.LabelFrame(self, text="Results", padx=3, pady=3) self.results_group.pack(fill=tk.X, anchor=tk.NW, padx=3, pady=3) self.data_frame = tk.Frame(self.results_group) self.data_frame.grid() button_frame = tk.Frame(self) button_frame.pack(fill=tk.X, side=tk.RIGHT, anchor=tk.SE) self.start_button = tk.Button(button_frame) self.start_button["text"] = "Start" self.start_button["command"] = self.start self.start_button.grid(row=0, column=0, padx=3, pady=3) quit_button = tk.Button(button_frame) quit_button["text"] = "Quit" quit_button["command"] = self.master.destroy quit_button.grid(row=0, column=1, padx=3, pady=3)
class ULDO02(UIExample): def __init__(self, master=None): super(ULDO02, self).__init__(master) master.protocol("WM_DELETE_WINDOW", self.exit) # By default, the example detects all available devices and selects the # first device listed. # If use_device_detection is set to False, the board_num property needs # to match the desired board number configured with Instacal. use_device_detection = True self.board_num = 0 try: if use_device_detection: self.configure_first_detected_device() self.device_info = DaqDeviceInfo(self.board_num) dio_info = self.device_info.get_dio_info() # Find the first port that supports output, defaulting to None # if one is not found. self.port = next((port for port in dio_info.port_info if port.supports_output), None) if self.port is not None: # If the port is configurable, configure it for output if self.port.is_port_configurable: try: ul.d_config_port(self.board_num, self.port.type, DigitalIODirection.OUT) except ULError as e: show_ul_error(e) self.create_widgets() else: self.create_unsupported_widgets() except ULError: self.create_unsupported_widgets(True) def exit(self): # Set the port to 0 at exit try: ul.d_out(self.board_num, self.port.type, 0) except ULError as e: show_ul_error(e) self.master.destroy() def bit_checkbutton_changed(self, bit_num): try: # Get the value from the checkbutton bit_value = self.bit_checkbutton_vars[bit_num].get() # Output the value to the board ul.d_bit_out(self.board_num, self.port.type, bit_num, bit_value) except ULError as e: show_ul_error(e) def create_widgets(self): '''Create the tkinter UI''' self.device_label = tk.Label(self) self.device_label.pack(fill=tk.NONE, anchor=tk.NW) self.device_label["text"] = ('Board Number ' + str(self.board_num) + ": " + self.device_info.product_name + " (" + self.device_info.unique_id + ")") main_frame = tk.Frame(self) main_frame.pack(fill=tk.X, anchor=tk.NW) curr_row = 0 bit_values_frame = tk.Frame(main_frame) bit_values_frame.grid(row=curr_row, column=0, padx=3, pady=3) label = tk.Label(bit_values_frame, text="Bit Number:") label.grid(row=0, column=0, sticky=tk.W) label = tk.Label(bit_values_frame, text="State:") label.grid(row=1, column=0, sticky=tk.W) # Create Checkbutton controls for each bit self.bit_checkbutton_vars = [] max_bit = min(self.port.num_bits, 8) for bit_num in range(0, max_bit): bit_label = tk.Label(bit_values_frame, text=str(bit_num)) bit_label.grid(row=0, column=bit_num + 1) var = IntVar(value=-1) bit_checkbutton = tk.Checkbutton( bit_values_frame, tristatevalue=-1, variable=var, borderwidth=0, command=lambda n=bit_num: self.bit_checkbutton_changed(n)) bit_checkbutton.grid(row=1, column=bit_num + 1, padx=(5, 0)) self.bit_checkbutton_vars.append(var) button_frame = tk.Frame(self) button_frame.pack(fill=tk.X, side=tk.RIGHT, anchor=tk.SE) quit_button = tk.Button(button_frame) quit_button["text"] = "Quit" quit_button["command"] = self.exit quit_button.grid(row=0, column=0, padx=3, pady=3)