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)
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 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 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 CInScan02(UIExample): 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 start_scan(self): rate = 390 total_count = 100 # 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: # Configure the counter ul.c_config_scan( self.board_num, self.chan_num, CounterMode.DECREMENT_ON, CounterDebounceTime.DEBOUNCE_NONE, 0, CounterEdgeDetection.FALLING_EDGE, CounterTickSize.TICK20PT83ns, 1) # Run the scan ul.c_in_scan( self.board_num, self.chan_num, self.chan_num, 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) 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): new_data_frame = tk.Frame(self.results_group) # Add the header channel_text = "Channel " + str(self.chan_num) + "\n" # Add (up to) the first 10 values to the display for data_index in range(0, min(10, total_count)): channel_text += str(array[data_index]) + "\n" # Add the labels chan_label = tk.Label(new_data_frame, justify=tk.LEFT, padx=3) chan_label["text"] = channel_text chan_label.grid(row=0, column=0) 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 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 + ")") # Initialize tkinter self.grid(sticky=tk.NSEW) self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=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() 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 ULGT03(UIExample): def __init__(self, master): super(ULGT03, self).__init__(master) self.board_num = 0 self.max_board_num = ul.get_config(InfoType.GLOBALINFO, 0, 0, GlobalInfo.NUMBOARDS) self.create_widgets() self.update_board_info() 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 get_ad_info(self): result = '' if self.device_info.supports_analog_input: ai_info = self.device_info.get_ai_info() result = ("Number of A/D channels: " + str(ai_info.num_chans) + "\n") return result def get_temperature_info(self): result = '' if self.device_info.supports_temp_input: ai_info = self.device_info.get_ai_info() result = ("Number of Temperature channels: " + str(ai_info.num_temp_chans) + "\n") return result def get_da_info(self): result = '' if self.device_info.supports_analog_output: ao_info = self.device_info.get_ao_info() result = ("Number of D/A channels: " + str(ao_info.num_chans) + "\n") return result def get_digital_info(self): result = '' if self.device_info.supports_digital_io: dio_info = self.device_info.get_dio_info() for port_num in range(len(dio_info.port_info)): result += ("Digital Port #" + str(port_num) + ": " + str(dio_info.port_info[port_num].num_bits) + " bits\n") return result def get_counter_info(self): result = '' if self.device_info.supports_counters: ctr_info = self.device_info.get_ctr_info() result = ("Number of counter devices: " + str(ctr_info.num_chans) + "\n") return result def get_expansion_info(self): result = '' if self.device_info.num_expansions > 0: for exp_info in self.device_info.exp_info: result += ("A/D channel " + str(exp_info.mux_ad_chan) + " connected to EXP (device ID=" + str(exp_info.board_type) + ").\n") return result def board_num_changed(self, *args): try: self.board_num = int(self.board_num_variable.get()) self.update_board_info() except ValueError: self.board_num = 0 def create_widgets(self): '''Create the tkinter UI''' main_frame = tk.Frame(self) main_frame.pack(fill=tk.X, anchor=tk.NW) positive_int_vcmd = self.register(validate_positive_int_entry) board_num_label = tk.Label(main_frame) board_num_label["text"] = "Board Number:" board_num_label.grid(row=0, column=0, sticky=tk.W) self.board_num_variable = StringVar() board_num_entry = tk.Spinbox(main_frame, from_=0, to=self.max_board_num, textvariable=self.board_num_variable, validate="key", validatecommand=(positive_int_vcmd, "%P")) board_num_entry.grid(row=0, column=1, sticky=tk.W) self.board_num_variable.trace("w", self.board_num_changed) info_groupbox = tk.LabelFrame(self, text="Board Information") info_groupbox.pack(fill=tk.X, anchor=tk.NW, padx=3, pady=3) self.info_label = tk.Label(info_groupbox, justify=tk.LEFT, wraplength=400) self.info_label.grid() 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.master.destroy quit_button.grid(row=0, column=0, padx=3, pady=3)
class CInScan03(UIExample): def __init__(self, master=None): super(CInScan03, 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.CTRQUAD), None) if chan is None: # Check for scan counters, which may (or may not) support # encoder modes 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 start_scan(self): rate = 100 total_count = 10 # 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: mode = CounterMode.ENCODER + CounterMode.ENCODER_MODE_X1 \ + CounterMode.ENCODER_MODE_CLEAR_ON_Z_ON debounce_time = CounterDebounceTime.DEBOUNCE_NONE debounce_mode = 0 edge_detection = CounterEdgeDetection.RISING_EDGE tick_size = CounterTickSize.TICK20PT83ns mapped_channel = 2 # Configure the first counter channel for Encoder mode ul.c_config_scan(self.board_num, self.chan_num, mode, debounce_time, debounce_mode, edge_detection, tick_size, mapped_channel) # Run the scan ul.c_in_scan(self.board_num, self.chan_num, self.chan_num, 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) 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): data_text = "" # Add (up to) the first 10 values for each channel to the text for data_index in range(0, min(10, total_count)): data_text += str(array[data_index]) + "\n" self.data_label["text"] = data_text def start(self): self.start_button["state"] = tk.DISABLED 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 + ")") info_text = tk.Label(self) info_text["text"] = ("Encoder scan on counter channel " + str(self.chan_num)) info_text.pack(fill=tk.X, anchor=tk.NW, padx=3, pady=3) results_group = tk.LabelFrame(self, text="Results") results_group.pack(fill=tk.X, anchor=tk.NW, padx=3, pady=3) self.data_label = tk.Label(results_group, justify=tk.LEFT) self.data_label.grid(padx=3, pady=3) 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)