티스토리 뷰

NI-DAQmx 텍스트 개발 환경에서 사용하기 - C, C++언어

이 글에서는 NI-DAQmx와 C언어를 통한 개발 방법에 대해서 설명을 드리고자 합니다.  DAQmx에서는 일반적으로 Ansi C기반의 예제를 제공합니다. 이 예제들을 통해서 텍스트 개발 환경에서 개발이 가능한데, 이 때 사용할 수 있는 언어는 C,C++입니다. C++환경에서는 DLL을 import하여 동일한 함수를 사용하여 처리를 할 수 있습니다. 


NI는 DAQ 장비를 사용하기 위해서 DAQmx라는 드라이버를 제공해주고 있습니다. DAQmx는 일반적으로 LabVIEW, C, C++, C#, VB.NET 모두 동일한 API를 사용하여 개발하는 프로세스는 동일합니다.  


DAQmx 통한 DAQ 프로그래밍 과정은 아래와 같습니다.

  1. Task Virtual Channel 생성
  2. Timing 파라미터 설정
  3. Task 시작
  4. Read 또는 Write 작업 수행
  5. Task 정지와 리소스 해제(Clear)


1. Task와 Virtual Channel 생성하기


먼저 Task와 Virtual Channel에 대해서 알아보도록 할까요.


Task : Task DAQmx 가장 중요한 부분으로 하나 이상의 타이밍, 트리거등과 같은 프로퍼티설정에 대한 Virtual Channel 정보를 가진 개체이다. Task AI, AO, DI, DO, Counter 대한 Task 생성할 있다.


Virtual Channel : 수집(혹은 생성)하고자는 물리적 채널 설정 모드(RSE, NRSE, 차동) 결정하고, 이에 대한 이름과 기타 정보(스케일 정보, 최대/최소값) 설정할 있다


Task 및 Virtual Channel 생성방법은 아래와 같습니다.


Task는 TaskHandle이라는 핸들 값을 하나 넣어 생성을 하게 됩니다. TaskHandle은 정수형의 포인터 주소를 나타냅니다. 아래의 코드에서 taskHandle이 바로 그것이며, Task를 생성한 후 값이 0, 혹은 -값이 아니라면 정상적으로 태스크가 생성이 된것입니다. 


태스크를 생성하고 나서, 해야할일은 사용할 채널의 특성(AI, AO, DIO)에 따른 가상 채널을 생성하는 것입니다. 가상채널은 채널의 특성에 따라 함수가 달라집니다. 아래의 예는 아날로그 입력을 받기 위한 가상 채널을 생성하는 방법입니다. 가상 채널 생성시에는 태스크에 대한 핸들 값과 채널에 필요한 정보들을 입력받습니다. 아래의 예제의 주석을 통해서 각 인자의 의미를 알수 있습니다. 


// Task 생성

DAQmxCreateTask("", &taskHandle));


// AI 채널 생성

DAQmxCreateAIVoltageChan (taskHandle, // Handle

"Dev1/ai0", // 물리적 채널 

"Voltage", // 채널의 이름

DAQmx_Val_Cfg_Default, // 입력 모드 설정

-10.0, // 입력 기대 최소값

10.0, // 입력 기대 최대값

 DAQmx_Val_Volts, // Voltage 받을 것인지

NULL);


2. Timing 파라미터 설정하기


DAQmx 2가지의 타임 방식으로 데이터를 수집할 있습니다. 보드에 내장된 타임베이스(Sample Clock) 이용하여 Sampling 하거나, OS 소프트웨어 타이밍을 통해서 데이터를 수집할 있습니다. 전자의 방식을 이용하여 일괄적인 데이터 수집을 원하고자 하시면 Timing 파라미터 설정을 해주셔야 하고, 소프트웨어 타이밍을 원하시면 부분을 무시하셔도 됩니다. 소프트웨어 타이밍은 Windows OS 특성 최소 1ms 간격으로 데이터를 수집할 있습니다


또한 하드웨어 타이밍으로 측정을 원하는 사용자는 Timing 설정할 연속적인 데이터를 수집하기 위한 연속 수집을 사용할 것인지 일정 시간동안의 데이터를 수집하는 유한 수집을 사용할 것인지 결정하셔야 합니다


그럼 타이밍을 설정하는 방법에 대해서 알아보도록 하겠습니다. 


DAQmxCfgSampClkTiming(taskHandle, 

"", 

10000.0, // 샘플링 속도(1초에 가져오는 점의 개수)

DAQmx_Val_Rising,  //샘플링할 Tick 시점

DAQmx_Val_FiniteSamps,  //연속 혹은 유한 수집 설정

1000); // 사용할 유한개의 메모리 사이즈 설정


3. 트리거 설정하기


사용자가 특정한 이벤트가 발생할 경우에만 데이터 수집 혹은 생성을 원한다고 DAQmx에서 제공해 있는 최선의 대안은 트리거입니다. 트리거는 시작 트리거, 레퍼런스 트리거등으로 구분을 수가 있습니다


시작 트리거 : 특정한 상황에서 수집이나 생성을 동작을 개시하는 트리거

참조 트리거 : 세트의 수집된 샘플에서 위치를 설정하여, 설정한 트리거 위치 이전 데이터와, 이후 트리거를 설정하는 트리거


트리거는 아날로그, 디지털 신호를 이용해서 적용할 있으며, DAQmx 디바이스에 따라 아날로그와 디지털 트리거의 지원유무가 결정이 됩니다. 핀 맵에서 APFI을 볼 수 있으면 아날로그 트리거 지원이 가능하며, PFI 핀을 볼 수 있으면 디지털 트리거 사용이 가능합니다. 대부분의 DAQ 보드는 디지털 트리거를 지원하고 있습니다.


그럼 함수 사용법에 대해서 알아보도록 하겠습니다. 


DAQmxCfgDigEdgeStartTrig (taskHandle, 

"PFI0", // 트리거 신호가 들어오는 라인

DAQmx_Val_Rising); // 트리거를 받을 Tick 시점


4. 태스크 시작하기


위에서 설정한 태스크를 시작하는 함수입니다. DAQmx 통한 데이터 수집 과정에는 태스트의 상태모델이 5개가 존재합니다 함수는 Task 실행  상태로 변경을 하는 함수입니다




태스트의 가상 채널과 채널에 대한 측정 방식(연속, 유한, 소프트웨어 타이밍), 트리거를 설정을 하셨으면 데이터 수집을 위한 시작 명령이 필요합니다. 태스트를 시작하기 위해 사용하는 함수에 대해서 살펴보겠습니다.


DAQmxStartTask(taskHandle);


5. 데이터 수집 혹은 생성


DAQmx 데이터 수집과 생성에 다양한 함수를 제공합니다. 이는 수집 결과 혹은 생성할 데이터를 다양한 데이터로 받기 위한 방법으로, 서로 다른 타입의 데이터를 사용할 있게끔 도와줍니다. Read 읽기가 수행이되면, RAM 메모리에 존재하는 DAQ Device로부터 읽혀진 수집 데이터를 개발 환경으로 가져오는 역할을 합니다


수집에 대한 읽기 함수는 읽어야 하는 읽는 신호의 타입(AI, AO, DIO, Counter)과 데이터 타입(float, int, uint, binary 등등)에 따라 여러개의 함수로 구분할 수 있습니다.(생성도 동일합니다.) 입력에 대한 함수는 DAQmxRead(신호타입)(데이터 타입)이름으로 구성됩니다. 아날로그 신호float 64데이터 형을 받아오는 함수의 이름은 DAQmxReadAnalogF64입니다. (생성은  DAQmxWriteAnalogF64 입니다.)


그럼 사용법에 대해서 간략히 살펴보겠습니다.

DAQmxReadAnalogF64(taskHandle, // 핸들

1000, // 한번에 읽어올 채널당 샘플 갯수

10.0, // 입력에 대한 타임아웃 시간(초)

DAQmx_Val_GroupByChannel, // 여러 채널을 입력시 입력을 받는 데이터의 구성 방식

data, // 입력받을 배열

1000, // 샘플이 입력된 배열의 사이즈

&read,  // 채널당 입력받은 실질적인 데이터 갯수

NULL)


C언어의 함수에서는 Read시 입력되는 배열은 무조건 1차 배열입니다. 2차 배열이 되지 않습니다. 따라서 읽기 함수의 5번째 인자는 무조건 1차 배열이어야 합니다. Visual Basic 함수에서는 2차 배열 사용이 가능합니다.


이러한 한계로 인해 여러 채널에 대한 가상 채널의 입력을 받을 시 1차배열에 받아오는 데이터의 구성이 어떻게 되는지 명확한 파악이 필요합니다. DAQmx함수에는 입력되는 데이터를 채널을 기준으로 입력을 할 것인지, 입력되는 신호를 기준으로 할 것인지 결정하는 인자가 바로 Read함수의 4번째 인자입니다.


4번째 인자에는 DAQmx_Val_GroupByChannel, DAQmx_Val_GroupByScanNumber를 입력할 수 있습니다. 

DAQmx_Val_GroupByChannel로 지정하는 경우 아래의 그림과 같이 배열에 데이터가 저장됩니다. 채널을 기준으로 데이터를 입력 받습니다. 


 DAQmx_Val_GroupByScanNumber를 사용한 경우 아래와 같습니다. 이 경우에는 입력되는 신호를 순서대로 배열에 입력이 됩니다.



그럼 각 함수에 대한 상세 정보는 아래의 링크를 참조하시기 바랍니다.


아날로그 입력 함수 리스트 : 


아날로그 생성 함수 : 


6. 태스크 정지 및 리소스 해제


데이터 수집 어플리케이션을 종료하고 할 때는 태스크를 정지하고, 이에 대한 리소스 할당된 부분을 해제 해주어야 합니다.

이에 대한 함수는 아래와 같습니다.


DAQmxStopTask(taskHandle)

DAQmxClearTask(taskHandle)


이상 DAQmx 함수를 C 언어에서 개발하는 방법에 대해서 살펴보았습니다. 기회가 된다면 예제를 분석하여 어떤식으로 돌아가는지 파악하는 글을 작성할께요.


수고하셨습니다.


이글이 도움이 되셨나요?

그렇다면 아래의 그림을 눌러주세요.



댓글