05-09-2019 05:06 AM
I am trying to create an GUI program using python and tkinder with multithreading. However while trying to pass AnalogMultiChannelReader(task.in_stream) instance to seperate thread so, it can run in the background, gives several errors. Below is the code I used, the code works perfectly, If i pass some random numbers but for AnalogMultiChannelReader instance doesn't work.
Any suggestions on what I am doing wrong here?
# -*- coding: utf-8 -*- """ import tkinter as tk from tkinter import * import threading import random import time from queue import Queue, Empty import matplotlib matplotlib.use('TkAgg') import numpy as np from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from matplotlib.figure import Figure import nidaqmx from nidaqmx.constants import AcquisitionType from nidaqmx.stream_readers import AnalogMultiChannelReader #%% root = tk.Tk() fig = Figure(figsize=(5,5), dpi=100) graph = fig.add_subplot(111) canvas = FigureCanvasTkAgg(fig,root) canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True) canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True) def DAQ(q, Read, out): while True: Read.read_many_sample(data = out,number_of_samples_per_channel = 10000)# read from DAQ out = np.around(out, 6) #Round all values to 6 decimals to avoid overflow q.put((out)) time.sleep(1) def update_data(queue, root): try: vibrations = queue.get_nowait() except Empty: pass else: graph.plot(vibrations) canvas.draw() root.after(1, update_data, queue, root) data_queue = Queue() with nidaqmx.Task() as task: task.ai_channels.add_ai_accel_chan("cDAQ9181-1BB3669Mod1/ai0:2") task.timing.cfg_samp_clk_timing(10000, source="", sample_mode=AcquisitionType.CONTINUOUS, samps_per_chan=10000) reader = AnalogMultiChannelReader(task.in_stream) output = np.zeros([3, 10000]) task.start() t = threading.Thread(target=DAQ, args=(data_queue, reader, output,)) t.daemon = True t.start() update_data(data_queue, root) root.mainloop()
if I can successfully run the sample program provided from here
The error code I get after running my code is as follow:
Exception in thread Thread-7: Traceback (most recent call last): File "C:\ProgramData\Anaconda3\lib\threading.py", line 917, in _bootstrap_inner self.run() File "C:\ProgramData\Anaconda3\lib\threading.py", line 865, in run self._target(*self._args, **self._kwargs) File "<ipython-input-4-35e645b9e6e9>", line 16, in DAQ Read.read_many_sample(data = out,number_of_samples_per_channel = 10000)# read from DAQ File "C:\ProgramData\Anaconda3\lib\site-packages\nidaqmx\stream_readers.py", line 330, in read_many_sample self._verify_array(data, number_of_samples_per_channel, True, True) File "C:\ProgramData\Anaconda3\lib\site-packages\nidaqmx\stream_readers.py", line 78, in _verify_array channels_to_read = self._in_stream.channels_to_read File "C:\ProgramData\Anaconda3\lib\site-packages\nidaqmx\_task_modules\in_stream.py", line 223, in channels_to_read check_for_error(size_or_code) File "C:\ProgramData\Anaconda3\lib\site-packages\nidaqmx\errors.py", line 127, in check_for_error raise DaqError(error_buffer.value.decode("utf-8"), error_code) nidaqmx.errors.DaqError: Task specified is invalid or does not exist. Status Code: -200088
Any suggestion on how to fix it would be really helpful.
Thank You.
08-06-2019 10:11 PM
Hi
Sorry, I am not familiar with this, but I can provide you with some reference information:
May I know what kind of data type of the random numbers that you pass in?
08-07-2019 10:29 AM
# -*- coding: utf-8 -*- """ import tkinter as tk from tkinter import * import threading import random import time from queue import Queue, Empty import matplotlib matplotlib.use('TkAgg') import numpy as np from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from matplotlib.figure import Figure import nidaqmx from nidaqmx.constants import AcquisitionType from nidaqmx.stream_readers import AnalogMultiChannelReader #%% root = tk.Tk() fig = Figure(figsize=(5,5), dpi=100) graph = fig.add_subplot(111) canvas = FigureCanvasTkAgg(fig,root) canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True) canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True) def DAQ(q,): with nidaqmx.Task() as task: task.ai_channels.add_ai_accel_chan("cDAQ9181-1BB3669Mod1/ai0:2") task.timing.cfg_samp_clk_timing(10000, source="", sample_mode=AcquisitionType.CONTINUOUS, samps_per_chan=10000) reader = AnalogMultiChannelReader(task.in_stream) output = np.zeros([3, 10000]) task.start() while True: reader.read_many_sample(data = out,number_of_samples_per_channel = 10000)# read from DAQ out = np.around(out, 6) #Round all values to 6 decimals to avoid overflow q.put((out)) time.sleep(1) def update_data(queue, root): try: vibrations = queue.get_nowait() except Empty: pass else: graph.plot(vibrations) canvas.draw() root.after(1, update_data, queue, root) data_queue = Queue() t = threading.Thread(target=DAQ, args=(data_queue, reader, output,)) t.daemon = True t.start() update_data(data_queue, root) root.mainloop()
I was able to fix this problem by starting the task with the function. I am not sure why this is happening since I didn't investigate the C-API of NI-DAQmx. I think it has something to do with passing the AnalogMultiChannelReader() object through to the different thread. Probably the task needs to be initiated in the same thread as the reader. Python module for NI-DAQmx is not thread safe. Since this question I haven't seen any updates in their library either. All in all together, I gave up on NI products and moved on to good old serial bus and TCP/IP DAQ cards where I have more control over data and multi-threading.
Thanks for the reply.
04-05-2023 01:03 PM
Any good alternatives on DAQs to NI?
04-05-2023 08:43 PM
@eduardomp8 wrote:
Any good alternatives on DAQs to NI?
There are several low cost alternatives but the support and performance may not be the same level.
MCC DAQ is one such alternative.