Q&A 게시판

cancel
Showing results for 
Search instead for 
Did you mean: 

동시에 AI와 DI, counter 읽기

Solved!
Go to solution
Highlighted

안녕하세요,

 

Analog input과 digital input, counter를 동시에 읽는 것이 가능할지 궁금합니다.

사용하는 보드는 USB-6212이고, 환경은 python 3.7.6 32bits, windows 10, NIDAQmx 19.6 입니다.

 

원래는 트리거와 콜백함수를 사용해서 카운트와 AI를 동시에 읽고 싶었는데, 중간에 잃는 데이타가 많은 것 같아 방법을 바꿔보려 합니다. 읽으려는 신호는 1kHz 가량의 sine파이고, sampling rate은 400kS/s 입니다.

 

아래 코드와 같이  while문을 사용해  ReadAnalogF64, ReadDigitalU32, ReadCounterU32 를 하려고 하는데, 이렇게 읽으면 되는 걸까요? DI의  sample clock timing도 같이 지정해 줘야 하는지도 궁금합니다.

그리고 처음 AI 읽을 때만 timeout을 -1로 해 놓고, DI나 counter의 timeout을 0으로 해 놓으면 AI에서 읽은 데이터와 같은 타이밍의 데이타가 읽히는 것일까요? 버퍼에 대해 설명된 부분이 잘 없어서 헷갈리네요. analog, digital, counter의 버퍼가 따로 있어서 1000개씩 데이터를 읽는다고 하면 앞의 1000개씩 각각 빼내 오고 이어서 새로 들어온 데이터들을 채워서 한 번의 루프 안에서 읽은analog_data[1000], digital_data[1000], counter_data[1000]의 값들이 각각 인덱스별로 동시에 해당하는 데이터인지 궁금합니다.

 

코드는 아래와 같습니다.

digital input을 처음 시도해 봐서 일단 채널명을 /Dev%d/PFI8로 넣었는데, port?/line? 식으로 써 줘야하나 싶네요. 검색해 봐도 PFI8에 해당하는 포트와 라인 정보가 나오지 않아 일단 이렇게 해 보았습니다.

 

 

samples_per_chan = 1000

 

nidaq.DAQmxCreateCICountEdgesChan(CItaskHandle,b"/Dev%d/ctr0" %num,"",DAQmx_Val_Rising,0,DAQmx_Val_CountUp)

 nidaq.DAQmxCreateAIVoltageChan(AItaskHandle,b"Dev%d/ai0" %num,"",DAQmx_Val_Diff,float64(-5.0),float64(5.0),DAQmx_Val_Volts,None)
    nidaq.DAQmxCreateDIChan(DItaskHandle,b"Dev%d/PFI8" %num,"",DAQmx_Val_ChanPerLine)
    nidaq.DAQmxCfgSampClkTiming(AItaskHandle,"",float64(sampleRate),DAQmx_Val_Rising,DAQmx_Val_ContSamps,uInt64(2000))

    nidaq.DAQmxStartTask( AItaskHandle )
    nidaq.DAQmxStartTask( CItaskHandle )
    nidaq.DAQmxStartTask( DItaskHandle )

    while runDAQ:
        readAI = uInt32()
        readDI = uInt32()
        readCI = uInt32()
        nidaq.DAQmxReadAnalogF64(AItaskHandle,samples_per_chan,float64(-1),DAQmx_Val_GroupByScanNumber,analog_data.ctypes.data,Length,ctypes.byref(readAI),None)
        nidaq.DAQmxReadDigitalU32(DItaskHandle,samples_per_chan,float64(0),DAQmx_Val_GroupByScanNumber,digital_data.ctypes.data,Length,ctypes.byref(readDI),None)
        #nidaq.DAQmxReadCounterScalarU32(CItaskHandle,float64(0),countdata.ctypes.data,None)
        nidaq.DAQmxReadCounterU32(CItaskHandle,samples_per_chan,float64(0),counter_data.ctypes.data,Length,ctypes.byref(readCI),None)
        nidaq.DAQmxReadCounterScalarU32(CItaskHandle,float64(0),countdata.ctypes.data,None)
        f.write(str(countdata[0]))
        f.write(str(AIdata))
        f.write(str(DIdata))
        f.write(str(CIdata))
 
혹시 추가적인 정보가 필요하면 알려주세요.
감사합니다.
0 Kudos
Message 1 of 6
(316 Views)
Highlighted
Solution
Accepted by topic author Serenade

안녕하세요

제 생각엔 원하시는 기능 구현 가능할 것 같습니다. 

올려주신 코드에서 아날로그 채널만 샘플 클럭 설정을 했는데 디지털 채널, 카운터 모두 반드시 샘플 클럭 설정을 해줘야 합니다.

그리고 클럭 소스로 Dev?/ai/SampleClock 과 같이 아날로그 샘플 클럭을 지정해줘서 하나의 샘플 클럭 타이밍으로 수집되게 해야 합니다. 

샘플 클럭 설정 후 아래와 같이 아날로그 태스크를 가장 나중에 시작해 줍니다.

 

nidaq.DAQmxStartTask( CItaskHandle )
nidaq.DAQmxStartTask( DItaskHandle )
nidaq.DAQmxStartTask( AItaskHandle ) # 가장 마지막에 시작
 
버퍼는 태스크 마다 따로 있는게 맞으며 말씀하신 대로 인덱스가 같으면 같은 타이밍에 수집된 거라고 생각하시면 됩니다. timeout 경우 0이나 -1보단 모두 적당한 값 (예 1000 ms) 을 넣는게 더 좋을 것 같습니다.  
채널 입력은 port?/line? 로 써도 되고 PFI? 로 써도 상관없습니다. 
 
Message 2 of 6
(270 Views)
Highlighted

답변 감사합니다.

덕분에 AI, DI를 같이 읽기는 가능한데, 6212 문제인지 코드 문제인지 AI, DI를 같이 읽으면 잃어버리는 데이타가 많네요...

일단 카운터는 제쳐두고, 아래 코드와 같이 AI, DI 데이타를 읽어보았습니다.

 

ReadAnalogF64의 timeout을 -1, ReadDigitalLines를 -1, 혹은 1, 1 등으로 지정하면 데이타가 이상하게 나오고,

-1, 0으로 하면 그나마 아날로그 인풋은 잘 읽히는데 디지털 인풋 신호가 잘려서 나옵니다.

다만, AI 없이 DI만 할 경우에도 듬성듬성 잘려서 나오는 걸로 봐서 6212 문제인가 싶기도 하네요. DI만 봤을 때 1Hz의 느린 신호는 잘 보이는 반면, 수kHz 주기로 수십us가량 지속되는 신호는 엄청나게 빼먹으며 보고 있거든요. (아래 코드의 sampleRate = sampling rate은 200kS/s.)

 

 

nidaq.DAQmxCreateAIVoltageChan(AItaskHandle,b"Dev%d/ai0,Dev%d/ai2" %(num,num),"",DAQmx_Val_Diff,float64(-5.0),float64(5.0),DAQmx_Val_Volts,None)
nidaq.DAQmxCreateDIChan(DItaskHandle,b"Dev%d/PFI0,Dev%d/PFI1" %(num,num),"",DAQmx_Val_ChanPerLine)
nidaq.DAQmxCfgSampClkTiming(AItaskHandle,"",float64(sampleRate),DAQmx_Val_Rising,DAQmx_Val_ContSamps,uInt64(1000000))
nidaq.DAQmxCfgSampClkTiming(DItaskHandle,"Dev%d/ai/SampleClock" %num,float64(sampleRate),DAQmx_Val_Rising,DAQmx_Val_ContSamps,uInt64(1000000))
 
nidaq.DAQmxStartTask( DItaskHandle )
nidaq.DAQmxStartTask( AItaskHandle )
 
while True:
  readAI = uInt32()
  readDI = uInt32()
  bytesPerSamps = uInt32()
    nidaq.DAQmxReadAnalogF64(AItaskHandle,samples_per_chan,float64(-1),DAQmx_Val_GroupByScanNumber,AIdata.ctypes.data,Length,ctypes.byref(readAI),None)
  nidaq.DAQmxReadDigitalLines(DItaskHandle,samples_per_chan,float64(0),DAQmx_Val_GroupByScanNumber,DIdata.ctypes.data,Length,ctypes.byref(readDI),ctypes.byref(bytesPerSamps),None)
 
 
혹시 무언가 아이디어가 있는 분은 알려주시면 감사하겠습니다.
0 Kudos
Message 3 of 6
(250 Views)
Highlighted

찾아보니 USB-6212는 디지털I/O에 사용되는 클럭이 굉장히 느린 것 같습니다(소프트웨어 클럭만?).

조만간 다른 장비를 사용할 예정인데, 거기엔 디지털쪽도 1MHz 클럭이 사용(아마도 하드웨어 클럭) 가능하다고 해서 그 장비로는 AI, DI 같이 받는게 가능하지 싶습니다.

0 Kudos
Message 4 of 6
(245 Views)
Highlighted

음...제가 좀 찾아보니 스펙 상 USB 6212에서 디지털 입력을 하드웨어 타이밍으로 수집할 수 없는 것 같습니다. (아래 링크)

https://forums.ni.com/t5/LabVIEW/USB-6212/td-p/3365098?profile.language=ko

제가 알려드린 방법은 PCI 타입의 62xx 시리즈 daq에 적용이 가능합니다. 

 

아래 코드 실행 시 에러가 발생하진 않나요? 제가 MAX에서 시뮬레이션 디바이스를 잡아서 했을 때 지원되지 않는 기능이라고 에러가 나옵니다. 

nidaq.DAQmxCfgSampClkTiming(DItaskHandle,"Dev%d/ai/SampleClock" %num,float64(sampleRate),DAQmx_Val_Rising,DAQmx_Val_ContSamps,uInt64(1000000))

 

만일 지원이 안되면 AI 수집과 동기화 할 수 없습니다. 

Message 5 of 6
(240 Views)
Highlighted

안녕하세요, 답변 감사합니다.

python에서는 따로 에러가 뜨지는 않았는데, 동작이 잘 안 되는 걸 보니 뭔가 문제가 있는 것 같기는 합니다.

MAX는 아직 잘 써본 적이 없어서 확인 해 봐야 겠습니다.

 

이제 다른 장비를 쓸 거라 질문은 새로 파려고 합니다.

답변 감사합니다.

0 Kudos
Message 6 of 6
(200 Views)