Отложенный или переполненный сбор данных с помощью python и nidaqmx

у меня проблемы с запуском моего кода так, как я хочу. Предполагается, что код собирает данные с датчиков и сохраняет их в файле с отметками времени. Линейный двигатель управляется с помощью одного из значений датчика. Я использую NI cDAQ 9184 и Python с пакетом nidaqmx. Первая возникшая проблема — задержка передачи данных. В результате процесс управления двигателем идет очень медленно. Я создал nidaqmx.task, и в цикле текущее значение датчика запрашивается через task.read(). Этот метод имеет задержку в несколько секунд. Мне кажется, что cDAQ и метод task.read() постоянно записывают данные, кэшируют их и выбрасывают кэшированные данные по запросу (как в очереди). Однако я хотел бы видеть значение только по запросу и без сохранения данных, поскольку они будут сохранены в файле csv. Если я воссоздаю задачу каждый раз, когда я вызываю метод задачи, я получаю соответствующие значения без задержки. Однако создание новой задачи стоит около 20 мс и не кажется мне предполагаемым решением для моего запроса. Конечно, это также замедляет запись данных, чего хотелось бы избежать.

См. два следующих фрагмента кода, которые описывают процедуру, которую я написал для 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]

Я прочитал много сообщений на форуме и пытался копаться в документации nidaqmx. Я наткнулся на метод Stream. Я нашел очень мало об этом, но я также попытался реализовать этот метод. Значения датчиков передаются корректно и без задержек. Но тут буфер переполняется и, в зависимости от частоты дискретизации, рано или поздно выбрасывает следующую ошибку:

(базовый) 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: Попытка установить идентичный нижний == верхний == 0,0 приводит к сингулярным преобразованиям; автоматически расширяется. ax.set_ylim(np.amin(dataPlot),np.amax(dataPlot)) SCT_18.02.2021_v1.0_stream.py:291: UserWarning: попытка установить идентичные значения left == right == 0,0 приводит к единичным преобразованиям; автоматически расширяется. ax.set_xlim(np.amin(timePlot),np.amax(timePlot)) SCT_18.02.2021_v1.0_stream.py:290: UserWarning: попытка установить идентичный нижний == верхний == 0,16962570625000006 приводит к единичным преобразованиям; автоматически расширяется. ax.set_ylim(np.amin(dataPlot),np.amax(dataPlot)) SCT_18.02.2021_v1.0_stream.py:291: UserWarning: Попытка установить идентичные значения left == right == 1.4031758308410645 приводит к единичным преобразованиям; автоматически расширяется. ax.set_xlim(np.amin(timePlot),np.amax(timePlot)) Process Process-1: Traceback (последний последний вызов): File C:\Users\Jetting\anaconda3\lib\multiprocessing\process.py, строка 315, в файле _bootstrap self.run() C:\Users\Jetting\anaconda3\lib\multiprocessing\process.py, строка 108, в файле run 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\site-packages\nidaqmx\stream_readers .py, строка 370, в файле read_one_sample _read_analog_f_64(self._handle, data, 1, timeout) ) Файл 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: Приложение не работает e, чтобы не отставать от приобретения оборудования. Увеличение размера буфера, более частое чтение данных или указание фиксированного количества выборок для чтения вместо чтения всех доступных выборок могут решить проблему. Свойство: DAQmx_Read_RelativeTo Соответствующее значение: DAQmx_Val_CurrReadPos Свойство: DAQmx_Read_Offset Соответствующее значение: 0

Название задачи: _unnamedTask‹0›

Код состояния: -200279

Здесь мне кажется, что поток постоянно записывает данные в память, что приводит к переполнению (Ошибка -200279: Unable to Keep Up with Acquisition in DAQmx - National Instruments). Но я понятия не имею, как перезаписать данные, а не добавлять их в память. Я честно должен признать, что я не до конца понял, как task.read() и метод потока выполняют свою работу.

Ниже приведен код со стримером:

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]
    

Любые советы или помощь и улучшение моего кода приветствуются. Если какая-либо информация отсутствует, извините (это мой первый пост), на всякий случай просто спросите.

Спасибо!


person RobertRondo    schedule 19.02.2021    source источник


Ответы (1)


Я нашел решение самостоятельно. Мне просто нужно было добавить аргумент в метод task.read(). Аргумент number_of_samples_per_channel = nidaqmx.constants.READ_ALL_AVAILABLE гарантирует, что все данные, которые сохраняются во внутренний буфер, читаются сразу, и поэтому данные всегда свежие!

person RobertRondo    schedule 01.03.2021