본문 바로가기
Engineering

[cRIO] 4. LabVIEW Real-Time Application - 두번째

by 투썬 아빠 2013. 2. 28.



지난 포스팅에서 Real-Time 어플리케이션을 개발할 때 고려해야 할 것(Deterministic, Priority 등)에 알아보았습니다. 그리고 Real-Time 어플리케이션을 개발하려면 미리 어플리케이션의 구조를 설계하는 것이 개발 진행에 도움이 된다고 언급하였습니다. 이처럼 시스템 구조를 설계하면 각 태스크 및 프로세스 간에 데이터를 주고 받을 경우가 있습니다. 이번 포스팅에서는 프로세스간의 데이터 통신에 대해 알아보겠습니다.

이 내용들은 NI에서 제공하는 'NI LabVIEW for CompactRIO Developer's Guide'를 바탕으로 작성하였음을 미리 알려드립니다.

 

 

개발하고자 하는 어플리케이션의 특징에 따라 개발하는 방법이 달라지 듯이 데이터 전송의 양, 속도 등에 따라서 통신 방법도 다르게 정하여야 합니다. 아래 그림은 NI에서 추천하는 4가지 통신 모델입니다.

 

<그림 1 NI에서 추천하는 프로세스간 데이터 통신 모델>

 

크게 4 종류의 통신 모델(Tag, Update, Streaming, Command/Message-Based)이 있습니다.

  

 1) Current Value Data(Tag)

가장 최근의 값(Read 프로세스에서 해당 데이터를 읽는 순간의 값)을 전달할 때 사용합니다. 일반적으로 하나의 데이터를 여러 프로세스로 전달할 때 사용합니다. Tag 방식으로 데이터를 전송할 경우 프로그래밍은 간단하지만 데이터 손실이(전달되는 데이터가 Read 프로세스에서 읽기 전에 새로운 데이터로 덮어 쓰여지게 되는 경우) 일어날 수 있습니다. 대표적으로 단일-프로세스 공유변수나 CVT 라이브러리를 사용합니다.

 

 2) Updates

개념적으로 는Tag 방식과 거의 동일합니다. 차이점은 Tag 방식과 달리 변경된 데이터만을 업데이트 하는 것입니다. 즉, 읽는 순간 (혹은 데이터를 전송하려 할 때)이전 데이터와 같으면 업데이트를 하지 않는 것입니다. 알림자를 사용하는 경우가 많습니다.

 

 3) Streaming

주기적으로 생성 및 수집되는 많은 양의 데이터를 손실 없이 전송할 때 사용하는 방법입니다. 일반적으로 FPGA의 데이터를 다른 하나의 프로세스로 전달하고 이를 저장할 때 많이 사용합니다. RT FIFO 함수를 이용하거나 공유변수에 RT FIFO 기능을 추가하여 사용합니다.

  

 4) Command/Message-Based

일반적으로 비주기적으로 생성 및 수집되지만 데이터 손실이 없어야 하는 경우에 사용됩니다. Commander라 불리는 프로세스에서 특정한 이벤트를 발생시키고 이를 Worker라 불리는 프로세스에 전달하는 구조입니다. LabVIEW에서의 생산자-소비자 디자인 패턴과 유사합니다. 주로 큐를 이용하고 경우에 따라 RT FIFO를 사용하기도 합니다.

  

 각 통신 방식에 사용되는 통신을 위한 함수는 CVT, 공유변수, 알림자, 큐, RT FIFO 등이 있습니다. 이 중 중요하게 다루어야 할 것들에 대해 알아보겠습니다.

 

  

1. 단일 프로세스 공유변수

 공유변수는 네트워크 기능이 추가된 글로벌 변수로 생각하시면 됩니다. 즉, 공유변수를 이용하면 서로 다른 VI간에 데이터를 읽고 쓸 수 있으며, 같은 네트워크 상에 존재하는 서로 다른 타겟 간의(예를 들면 Host PC와 RT Target)데이터 읽고 쓰기가 가능합니다. 로컬변수나 글로벌 변수와 같이 접근하는 순간에 해당 변수에 존재하는 값을 읽습니다. 때문에 해당 변수를 읽을 타이밍과 쓰는 타이밍의 조절이 어긋나면 데이터 손실이 일어날 수 있습니다.


<그림 2 공유변수를 이용하면 여러 프로세스에서 접근하여 데이터를 읽고 쓸 수 있습니다.>

    

단일 포인트 공유변수를 만들기 위해서는 RT Target에서 우클릭 하고 바로가기 메뉴에서 새로 만들기 >> 변수 를 선택합니다. 그리고 나타나는 대화상자에서 변수 타입을 단일 프로세스로 선택해야 합니다. 앞서 이야기 했듯이 단일 포인트 공유변수는 글로벌 변수와 유사하며 차이점은 데이터를 공유할 수 있는 범위가 네트워크로 확장 된 것입니다.

 

<그림 3 여러 프로세스에서 하나의 현재의 값을 공유하고자 할 때 유용함>

 

단일 포인트 공유변수는 사용하기는 편리하지만 Timed Loop에서 사용할 경우 지터를 발생시킬 수 있습니다. 만약 Timed-Loop에서 단일 포인트 공유변수를 사용하고자 할 경우 RT FIFO를 활성화 하기 바랍니다. RT FIFO가 활성화 된 공유변수는 잠시 후 이야기 하겠습니다.

 

  

 2. Current Value Table

 Current Value Table(이하 CVT)는 기능적 글로벌 변수를 이용하여 만들어진 라이브러리입니다. 이 라이브러리는 NI에서 개발한 것이 아니기 때문에 별로의 절차를 이용하여 LabVIEW에 포함시켜야합니다. CVT 라이브러리는 VI Package Manager를 이용하여 다운로드 및 설치를 할 수 있습니다.


<그림 4 Current Value Table 팔레트>

 

CVT의 장점은 기능적 글로벌 변수를 사용하여 만들어졌기 때문에 일반적인 변수 사용에 비하여 경합조건(동시에 하나의 변수에 접근하고자 할 때 데이터가 덮어 쓰여지는 등의 충돌 현상)에 강합니다. CVT의 자세한 설명 및 사용법에 대해서는 Current Value Table(CVT) Reference Library를 참고하시기 바랍니다.

 

  

 3. 큐

 큐는 Nondeterministic한 두 프로세스 간의Command/Message-based Communication에 적합한 프로토콜입니다. 왜냐하면 유연하고(다양한 데이터 타입 사용 가능), 사용하기 쉬우며, 버퍼 된 데이터를 사용할 수 있기 때문입니다. 클러스터 데이터 타입은 물론이고 베리언트, 크기가 변할 수 있는 데이터 타입인 문자열, 배열 등의 데이터 타입도 적용이 가능합니다. 이 프로토콜은 Windows와 RTOS에서 모두 사용 가능합니다.

 아래 그림은 큐가 사용된 기본적인 디자인 패턴입니다. 두 개의 루프로 구성되어 있으며 '원소를 큐에 추가'가 사용된 루프는 생산자, '원소를 큐에서 제거'가 사용된 루프를 소비자 루프라고 부릅니다. 생산자 루프에서 수집되는 데이터를 큐를 통하여 소비자 루프로 전달을 하고 이를 분석 및 저장하는 구조입니다.


 

<그림 5 큐를 이용한 Nondeterministic 프로세스 간의 통신>

 

큐는 LabVIEW에서 기본적으로 제공되는 함수입니다. '함수팔레트 >> 동기화 >> 큐'에서 사용이 가능합니다.

 

  

4. RT FIFO

 RT FIFO는 큐와 마찬가지로 선입선출 방식을 가진 프로토콜입니다. 그 사용법도 큐와 거의 동일합니다. 하지만 큐와는 달리 Deterministic한 성능을 가지고 있습니다. 공유변수와 큐 그리고 RT FIFO의 차이점을 이야기 하자면 큐나 RT FIFO는 사용자가 직접 생성 및 해제를 지정할 수 있지만 공유변수는 최초에 호출 될 때 생성이 되며, 어플리케이션이 종료될 때 해제됩니다. 그럼 큐와 RT FIFO의 차이는 무엇일까요? 핵심적인 차이점 몇가지를 알아보겠습니다.


1) 는 문자열, 베리언트, 크기가 조절가능한 데이터 타입을 사용할 수 있지만 RT FIFO는 그렇지 않습니다.

2) RT FIFO는 고정된 크기의 데이터만 사용이 가능합니다. 때문에 동적으로 메모리를 관리하지 않으며Timed Loop에서 Deterministic하게 사용할 수 있습니다.

3) 큐는 기본적으로 블로킹 방식(큐에 새로운 데이터가 추가될 때 함수가 동작)으로 동작하지만 RT FIFO는 폴링 방식(FIFO 속의 데이터를 주기적으로 확인함)을 사용합니다. RT FIFO를 생성할 때 폴링/블로킹을 설정할 수는 있습니다.


  아래 그림의 블록다이어그림은 <그림 5>와 유사하지만 생산자 루프(데이터 수집 루프)가 이제는 Deterministic 하게 구동합니다. 생산자 루프는 데이터를 수집하고 Nondeterministic한 소비자 루프에서는 데이터를 로깅하는 구조를 보이고 있습니다.

     

<그림 6 RT FIFO가 적용된 생산자 소비자 디자인패턴>

 

 RT FIFO는 FIFO의 사이즈가 지정되어 있습니다. 때문에 Overwrite가 되지 않도록 주의해야 합니다. 만약 RT FIFO 가 Overwrite되면 write 함수의 '타임아웃?' 값이 True를 반환합니다. 이를 참고하여 데이터 손실을 방지하기 위하여 Overwrite 되었는지 아닌지 확인하기 바랍니다. RT FIFO는 함수 팔레트 >> Real-Time >> RT FIFO에 위치해 있습니다.

 

  

 5. RT FIFO가 활성화 된 공유변수

 RT FIFO가 활성화 된 공유변수는 네트워크 공유 변수에 RT FIFO 기능이 추가 된 것입니다. 때문에 같은 네트워크에 있는 서로 다른 타겟 간의 Deterministic한 데이터 통신이 가능합니다. 즉, 일반 큐나 RT FIFO는 하나의 타겟 내에 있는 다른 프로세스 간의 통신만이 가능하지만 RT FIFO가 활성화 된 공유변수는 네트워크 내의 타겟 끼리 데이터 통신이 가능한 것입니다.


아래 그림은 Loop comm이라는 이름을 가진 RT FIFO가 활성화 된 공유변수를 이용한 블록다이어그램입니다. 구조는 그림5와 그림 6에서 이미 보았던 것과 동일합니다. 차이점은 공유변수가 사용된 것입니다.



<그림 7 RT FIFO가 활성화된 공유변수가 적용 된 디자인 패턴>

 

공유변수에 RT FIFO 기능을 활성하려면 공유변수의 프로퍼티 대화상자에서 Enable RT FIFO 항목을 체크해야합니다.

 

<그림 8 공유변수에 RT FIFO 기능을 활성화>

 

RT FIFO 기능을 활성화 하고 FIFO Type을 설정할 수가 있습니다. 이 때 Single Element로 하면 Tag, Update 처럼 사용할 수 있고 Multi Element로 설정하면 버퍼가 있는 데이터타입을 사용할 수 있습니다. 즉, Message Based나 Streaming 방식에 사용이 가능한 것입니다.

RT FIFO가 활성화된 공유 변수를 사용할 때 주의해야 할 사항 중 하나가 FIFO가 비어있는지 확인하는 것입니다. 만약 FIFO가 비어있을 경우 -2220 경고(Warning)을 반환 합니다. 에러가 아니기 때문에 프로그램 동작에 큰 영향을 미치지는 않지만 해당 경고를 확인하여 FIFO가 비어있는지 확인이 가능합니다.

지금까지 알아본 FIFO 기능들(큐, RT FIFO, RT FIFO가 활성화된 공유변수)는 데이터에 접근하여 읽을 경우 FIFO에서 해당 데이터가 사라지게 됩니다. 때문에 여러 프로세스에서 동일한 데이터를 읽을 수 없습니다. 만약 여러 프로세스에서 동일한 타이밍에 수집 혹은 생성되고 있는 데이터를 읽고자 한다면 알림자를 사용해야 합니다.

 

 

 5. 알림자

 알림자는 Nondeterministic한 루프 간에 데이터 통신을 할 때 유용합니다. 사용을 할 때 주의 해야할 점은 FIFO와 달리 버퍼가 없기 때문에 하나의 데이터만을 읽고 쓸 수 있는 것입니다. 즉 수집 루프에서 알림자로 데이터를 입력하는데 로깅 루프에서 이 데이터를 읽지 않는 상황에서 수집루프에서 새로운 데이터가 알림자로 입력되면 데이터 손실이 일어나는 것입니다.


<그림 9 알림자 팔레트>

 

여기까지만 볼 때는 차라리 큐를 사용하지 알림자를 쓸 필요가 없을 것 처럼 보일 수 있습니다. 하지만 알림자는 데이터가 읽혀질 때 FIFO처럼 데이터가 사라지는 것이 아닙니다. 때문에 앞서 언급한 것 처럼 여러 프로세스에서 동일한 타이밍에 동일한 데이터를 읽을 수 있는 것입니다.

 

 

 

지금까지 Real-Time 환경에서 사용되는 데이터 통신 모델과 각각에 사용하기 용이한 통신 방법들에 대해 알아보았습니다. 개발하는 어플리케이션의 특성에 따라 적절한 모델과 함수를 적용하시기 바랍니다. 다음 포스팅에서는 Real-Time 프로그래밍을 할 때 메모리사용에 대해 어떻게 고려해야 하는지 설명하겠습니다.


댓글