简体   繁体   English

python 和 nidaqmx 的数据采集延迟或溢出

[英]Delayed or overflowed data acquisition with python and nidaqmx

i'm having trouble getting my code running the way I want it to.我无法让我的代码按照我想要的方式运行。 The code is supposed to acquire data from sensors and store it in a file with time stamps.该代码应该从传感器获取数据并将其存储在带有时间戳的文件中。 A linear motor is controlled using one of the sensor values.使用其中一个传感器值控制直线电机。 I use an NI cDAQ 9184 and Python with the nidaqmx package.我将 NI cDAQ 9184 和 Python 与 nidaqmx package 一起使用。 The first problem that has occurred is delayed transmission of the data.出现的第一个问题是数据传输延迟。 As a result, the control process of the engine is very slow.结果,发动机的控制过程非常缓慢。 I created a nidaqmx.task and in a loop the current sensor value is requested via task.read().我创建了一个 nidaqmx.task 并在循环中通过 task.read() 请求当前传感器值。 This method has a delay of several seconds.此方法有几秒钟的延迟。 It seems to me that the cDAQ and the task.read() method are constantly recording data, caching it and ejecting the cached data on request (as in a queue).在我看来,cDAQ 和 task.read() 方法不断地记录数据,缓存它并根据请求弹出缓存的数据(如在队列中)。 However, I would like to see a value only on request and no data to be stored as it will be saved to a csv file.但是,我希望仅在请求时查看值,并且没有要存储的数据,因为它将保存到 csv 文件中。 If I recreate the task each time I call the task method, I get the appropriate and non-delayed values.如果我每次调用任务方法时都重新创建任务,我会得到适当且非延迟的值。 However, creating a new task costs about 20 ms and does not seem to me to be the intended solution for my request.但是,创建一个新任务大约需要 20 毫秒,在我看来,这不是我的请求的预期解决方案。 Of course, this also slows down the data recording, which i would like to avoid.当然,这也会减慢数据记录的速度,我想避免这种情况。

See the two following code snippets which describe the procedure i wrote for DataAcquisition:请参阅以下两个代码片段,它们描述了我为 DataAcquisition 编写的过程:

def DAQ_Monitoring(c,condition,ExChange,sample_rate):        

with nidaqmx.Task() as task:
    task.ai_channels.add_ai_current_chan("cDAQ9184-1B901BFMod1/ai0")
    task.ai_channels.add_ai_current_chan("cDAQ9184-1B901BFMod1/ai1")
    task.ai_channels.add_ai_current_chan("cDAQ9184-1B901BFMod1/ai2")
    task.timing.cfg_samp_clk_timing(1000)
    
    sample_RateSeconds = (sample_rate)*(10**(-3))    #convert sampleRate from [ms] to [s]
    startTime = datetime.now().timestamp()
    oldTime = 0
    while condition.value == 3:
        while ((datetime.now().timestamp()-startTime)-oldTime) < sample_RateSeconds:
            pass
        timeData = datetime.now().timestamp()-startTime
        oldTime = timeData
        pressureIn,pressureVessel,volumeFlow = task.read()
        position, force = pullData(c)
        accousticEmission1 = 999
        vibration = 999
        pressureIn = (1000000/16)*(pressureIn-0.004)
        pressureVessel = (200000/16)*(pressureVessel-0.004)
        volumeFlow = 3250*volumeFlow            
        ExChange[:] = [timeData,pressureIn,pressureVessel,volumeFlow,accousticEmission1,vibration,position,force]
    

def DAQ_Monitoring(c,condition,ExChange,sample_rate):        
    
sample_RateSeconds = (sample_rate)*(10**(-3))    #convert sampleRate from [ms] to [s] 
startTime = datetime.now().timestamp()
oldTime = 0
while condition.value == 3:
    while ((datetime.now().timestamp()-startTime)-oldTime) < sample_RateSeconds:
        pass
    timeData = datetime.now().timestamp()-startTime
    oldTime = timeData
    with nidaqmx.Task() as task:
        task.ai_channels.add_ai_current_chan("cDAQ9184-1B901BFMod1/ai0")
        task.ai_channels.add_ai_current_chan("cDAQ9184-1B901BFMod1/ai1")
        task.ai_channels.add_ai_current_chan("cDAQ9184-1B901BFMod1/ai2")
        task.timing.cfg_samp_clk_timing(1000)
        pressureIn,pressureVessel,volumeFlow = task.read()
    position, force = pullData(c)
    accousticEmission1 = 999
    vibration = 999
    pressureIn = (1000000/16)*(pressureIn-0.004)
    pressureVessel = (200000/16)*(pressureVessel-0.004)
    volumeFlow = 3250*volumeFlow            
    ExChange[:] = [timeData,pressureIn,pressureVessel,volumeFlow,accousticEmission1,vibration,position,force]

I have read many forum posts and tried to dig through the documentation of nidaqmx.我已经阅读了许多论坛帖子并试图挖掘 nidaqmx 的文档。 I came across the Stream method.我遇到了 Stream 方法。 I found very little about this, but I also tried to implement this method.我对此发现很少,但我也尝试实现此方法。 The sensor values are transmitted correctly and without delay.传感器值可以正确无延迟地传输。 But here the buffer runs over and, depending on the sample rate, sooner or later ejects the following error:但是这里缓冲区溢出,根据采样率,迟早会弹出以下错误:

(base) PS C:\Users\Jetting\Desktop\Robert\SCT_TryOut_DifferentAcqTypes> python SCT_18.02.2021_v1.0_stream.py SCT_18.02.2021_v1.0_stream.py:290: UserWarning: Attempting to set identical bottom == top == 0.0 results in singular transformations; (base) PS C:\Users\Jetting\Desktop\Robert\SCT_TryOut_DifferentAcqTypes> python SCT_18.02.2021_v1.0_stream.py SCT_18.02.2021_v1.0_stream.py:290: UserWarning: Attempting to set identical bottom == top == 0.0导致奇异的变换; automatically expanding.自动展开。 ax.set_ylim(np.amin(dataPlot),np.amax(dataPlot)) SCT_18.02.2021_v1.0_stream.py:291: UserWarning: Attempting to set identical left == right == 0.0 results in singular transformations; ax.set_ylim(np.amin(dataPlot),np.amax(dataPlot)) SCT_18.02.2021_v1.0_stream.py:291:用户警告:尝试设置相同的左 == 右 == 0.0 会导致奇异变换; automatically expanding.自动展开。 ax.set_xlim(np.amin(timePlot),np.amax(timePlot)) SCT_18.02.2021_v1.0_stream.py:290: UserWarning: Attempting to set identical bottom == top == 0.16962570625000006 results in singular transformations; ax.set_xlim(np.amin(timePlot),np.amax(timePlot)) SCT_18.02.2021_v1.0_stream.py:290:用户警告:尝试设置相同的底部 == 顶部 == 0.16962570625000006 导致奇异的转换; automatically expanding.自动展开。 ax.set_ylim(np.amin(dataPlot),np.amax(dataPlot)) SCT_18.02.2021_v1.0_stream.py:291: UserWarning: Attempting to set identical left == right == 1.4031758308410645 results in singular transformations; ax.set_ylim(np.amin(dataPlot),np.amax(dataPlot)) SCT_18.02.2021_v1.0_stream.py:291:用户警告:尝试设置相同的左 == 右 == 1.4031758308410645 会导致奇异变换; automatically expanding.自动展开。 ax.set_xlim(np.amin(timePlot),np.amax(timePlot)) Process Process-1: Traceback (most recent call last): File "C:\Users\Jetting\anaconda3\lib\multiprocessing\process.py", line 315, in _bootstrap self.run() File "C:\Users\Jetting\anaconda3\lib\multiprocessing\process.py", line 108, in run self._target(*self._args, **self._kwargs) File "C:\Users\Jetting\Desktop\Robert\SCT_TryOut_DifferentAcqTypes\SCT_18.02.2021_v1.0_stream.py", line 105, in DAQ_Monitoring reader.read_one_sample(values_read) File "C:\Users\Jetting\anaconda3\lib\site-packages\nidaqmx\stream_readers.py", line 370, in read_one_sample _read_analog_f_64(self._handle, data, 1, timeout) File "C:\Users\Jetting\anaconda3\lib\site-packages\nidaqmx_task_modules\read_functions.py", line 35, in _read_analog_f_64 check_for_error(error_code) File "C:\Users\Jetting\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: The applicat ax.set_xlim(np.amin(timePlot),np.amax(timePlot)) 进程 Process-1:回溯(最近一次调用最后):文件“C:\Users\Jetting\anaconda3\lib\multiprocessing\process.py” ,第 315 行,在 _bootstrap self.run() 文件“C:\Users\Jetting\anaconda3\lib\multiprocessing\process.py”中,第 108 行,在运行 self._target(*self._args, **self._kwargs ) 文件“C:\Users\Jetting\Desktop\Robert\SCT_TryOut_DifferentAcqTypes\SCT_18.02.2021_v1.0_stream.py”,第 105 行,在 DAQ_Monitoring reader.read_one_sample(values_read) 文件“C:\Users\Jetting\anaconda3\lib\站点包\nidaqmx\stream_readers.py”,第 370 行,在 read_one_sample _read_analog_f_64(self._handle,数据,1,超时)文件“C:\Users\Jetting\anaconda3\lib\site-packages\nidaqmx_task_modules\read_functions.py ",第 35 行,在 _read_analog_f_64 check_for_error(error_code) 文件 "C:\Users\Jetting\anaconda3\lib\site-packages\nidaqmx\errors.py",第 127 行,在 check_for_error 中引发 DaqError(error_buffer.value.decode(" utf-8"), error_code) nidaqmx.errors.DaqError: 应用程序ion is not able to keep up with the hardware acquisition. ion 无法跟上硬件采集。 Increasing the buffer size, reading the data more frequently, or specifying a fixed number of samples to read instead of reading all available samples might correct the problem.增加缓冲区大小、更频繁地读取数据或指定要读取的固定样本数而不是读取所有可用样本可能会解决问题。 Property: DAQmx_Read_RelativeTo Corresponding Value: DAQmx_Val_CurrReadPos Property: DAQmx_Read_Offset Corresponding Value: 0属性:DAQmx_Read_RelativeTo 对应值:DAQmx_Val_CurrReadPos 属性:DAQmx_Read_Offset 对应值:0

Task Name: _unnamedTask<0>任务名称:_unnamedTask<0>

Status Code: -200279状态码:-200279

Here it seems to me that the stream is constantly storing data to the memory which leads to an overflow (Error -200279: Unable to Keep Up with Acquisition in DAQmx - National Instruments).在我看来,stream 不断地将数据存储到 memory 中,这会导致溢出(错误 -200279:无法跟上 DAQmx - National Instruments 中的采集速度)。 But i have no idea how to overwrite the data instead of appending it to the memory.但我不知道如何覆盖数据而不是将其附加到 memory。 I honestly have to admit, that i did not fully understand how task.read() and the stream method do their job.老实说,我不得不承认,我没有完全理解 task.read() 和 stream 方法是如何工作的。

Following is the code with the streamer:以下是带有流媒体的代码:

def DAQ_Monitoring(c,condition,ExChange,sample_rate):        
with nidaqmx.Task() as task:
    task.ai_channels.add_ai_current_chan("cDAQ9184-1B901BFMod1/ai0")
    task.ai_channels.add_ai_current_chan("cDAQ9184-1B901BFMod1/ai1")
    task.ai_channels.add_ai_current_chan("cDAQ9184-1B901BFMod1/ai2")
    task.timing.cfg_samp_clk_timing(rate=1000,sample_mode=nidaqmx.constants.AcquisitionType.CONTINUOUS,samps_per_chan=2)
    reader = AnalogMultiChannelReader(task.in_stream)
    task.start()
    values_read = np.zeros((3,), dtype=np.float)
    sample_RateSeconds = (sample_rate)*(10**(-3))    #convert sampleRate from [ms] to [s]
    startTime = datetime.now().timestamp()
    oldTime = 0
    while condition.value == 3:
        while ((datetime.now().timestamp()-startTime)-oldTime) < sample_RateSeconds:
            pass
        timeData = datetime.now().timestamp()-startTime
        oldTime = timeData
        reader.read_one_sample(values_read)
        pressureIn,pressureVessel,volumeFlow = values_read
        position, force = pullData(c)
        accousticEmission1 = 999
        vibration = 999
        pressureIn = (1000000/16)*(pressureIn-0.004)
        pressureVessel = (200000/16)*(pressureVessel-0.004)
        volumeFlow = 3250*volumeFlow            
        ExChange[:] = [timeData,pressureIn,pressureVessel,volumeFlow,accousticEmission1,vibration,position,force]
    

Any advice or help and improvement of my code is appreciated.感谢您对我的代码的任何建议或帮助和改进。 If any information is missing i am sorry (this is my first post), in case just ask.如果缺少任何信息,我很抱歉(这是我的第一篇文章),以防万一。

Thanks!谢谢!

I found the solution by myself.我自己找到了解决方案。 I simply had to add an argument to the task.read() method.我只需要在 task.read() 方法中添加一个参数。 The argument "number_of_samples_per_channel = nidaqmx.constants.READ_ALL_AVAILABLE" makes sure that all data that is saved to the intern buffer is read at once, and therefore the data is always "fresh"!参数“number_of_samples_per_channel = nidaqmx.constants.READ_ALL_AVAILABLE”确保保存到实习缓冲区的所有数据都被立即读取,因此数据始终是“新鲜的”!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM