프로그래밍/랩뷰 기술자료

랩뷰 개발 및 유지보수를 위한 고려사항

에이티에스 2023. 7. 25. 09:24
728x90

 

소프트웨어 개발과 유지 보수의 효율성을 극대화하려면 LabVIEW 어플리케이션을 잘 설계해야 합니다.  이 문서에서는 특히 LabVIEW의 소프트웨어 설계와 관련된 기본 구조, 설계 패턴, 아키텍처를 소개합니다. 이 내용은 포괄적이지는 않지만 LabVIEW 소프트웨어 설계를 시작할 때 고려해야 할 일반적인 요소를 설명합니다.

 

기본 구조

다음의 각 섹션은 LabVIEW 프로그래밍에서 특정 작업을 위해 사용되는 일반적인 구조를 설명합니다. 이러한 기본 구조에 익숙해지면 LabVIEW 어플리케이션 내 사용을 더 쉽게 파악하고고 이해하는 데 도움이 됩니다.

 

타입 정의

타입 정의 (종종 "typedefs"로도 씀)를 사용하면 어플리케이션 전체에서 일관되게 정의될 데이터 타입을 지정할 수 있습니다. 예를 들어, 다음은 클러스터 타입 정의입니다.

 

이 타입 정의를 프런트패널이나 블록다이어그램에 놓으면 클러스터로 표시되는데, 터미널과 상수의 왼쪽 상단 모서리에 검은색 삼각형이 함께 표시됩니다.

 

타입 정의는 어플리케이션 전체에 걸쳐 일관된 타입을 정의하는 데 매우 유용합니다. 이를 설명하기 위해 타입 정의에 새 파라미터 (이 경우 설정 경로)를 추가하면 어떻게 되는지 확인할 것입니다.

 

단일 위치 (소스 typedef .ctl 파일)에서 타입 정의를 수정하면 변경 내용이 자동으로 전체 어플리케이션에 적용됩니다.

클러스터가 타입 정의가 아닌 경우 전체 어플리케이션에서 (프런트패널과 블록다이어그램에 있는) 클러스터의 모든 인스턴스를 수동으로 업데이트해야 합니다. 아주 드문 경우를 제외하고 LabVIEW 어플리케이션을 작성하는 동안 생성하는 모든클러스터 열거형을 타입 정의해야 합니다.

타입 정의를 사용하면 공유 데이터 타입을 단일 소싱하여 코드의 유지 보수성을 향상시킬 수 있습니다.

 

이벤트 구조

이벤트 구조에는 LabVIEW 블록다이어그램에서 사용자 인터페이스 이벤트와 프로그램적 이벤트에 응답하는 기능이 있습니다. 예를 들어, 프런트패널 컨트롤 값이 변경될 때마다 실행할 이벤트 다이어그램을 등록할 수 있습니다. 또한 사용자 이벤트 발생 함수를 사용하여 블록다이어그램에서 프로그램적으로 생성된 이벤트를 등록할 수 있습니다.

 

이벤트 구조는 일반적으로 코드가 실행되는 동안 여러 이벤트에 응답할 수 있도록 While 루프 내에 위치합니다. 감지하려는 서로 다른 이벤트에 서로 다른 프레임을 갖도록 이벤트 구조를 설정합니다. 각 이벤트 프레임에는 해당 이벤트가 발생할 때마다 실행되는 처리 코드가 포함됩니다. 

 

기능적인 글로벌 변수

기능적인 글로벌 변수 ("FGV", "LabVIEW 2가지 스타일 글로벌" 또는 "동작 엔진"이라고도 함)는 데이터 저장 메커니즘입니다.  FGV는 초기화되지 않은 시프트 레지스터 또는 초기화되지 않은 피드백 노드에 데이터를 저장하며 이를 통해 어플리케이션 내 어디에서든(즉, "전역적으로") 해당 데이터에 액세스할 수 있습니다. 

 

다음은 기본 FGV VI의 블록다이어그램으로 데이터 입력 데이터 출력 그리고 두 개의 동작("설정"과 "가져오기")이 있는 연산 열거형이 포함됩니다. 

 

이 간단한 get/set FGV가 제공하는 기능은 글로벌 변수를 사용하는 것과 같습니다. 실제로 FGV는 "설정" 및 "가져오기" 외에 추가 기능을 수행할 가능성이 높습니다. 

FGV를 사용하여 참조를 저장하고 더 정교한 작업을 수행할 수 있습니다.  예를 들어, 아래의 파일 I/O FGV(피드백 노드 대신 초기화되지 않은 시프트 레지스터를 사용하는 경우)를 살펴보십시오. 

 

이 FGV는 연속적인 호출 사이의 파일 참조를 저장하고 단일 VI 내에서 여러 가지 다른 동작(열기, 읽기, 쓰기, 닫기)을 수행합니다.  

 

FGV는 글로벌 변수만큼 경합 조건에 취약합니다. 일반적으로 코드의 한 곳 이상에서 전역 데이터에 쓰는 것은 피해야 합니다.

 

서브패널

서브패널은 다른 VI의 프런트패널을 디스플레이할 수 있는 프런트패널 컨트롤입니다. 서브패널을 사용하면 서브패널에 디스플레이할 다른 VI를 지정하여 UI의 전체 섹션을 교체할 수 있는 동적 사용자 인터페이스를 설계할 수 있습니다. 또한 서브패널은 프런트패널 아이템의 논리적 그룹을 별도의 VI에 포함할 수 있는 모듈형 어플리케이션 개발을 장려합니다.  이 설계를 통해 다른 디스플레이 VI 또는 메인 어플리케이션 VI의 코드를 변경하지 않고 서브패널 내에 디스플레이된 개별 VI를 수정할 수 있습니다. 

아래 예제는 폴더의 플러그인 VI를 스캔하고 텍스트 링을 해당 플러그인으로 채웁니다. 텍스트 링에서 아이템을 선택하면 그에 상응하는 플러그인 VI가 Main VI의 서브패널에 삽입됩니다.  이 구조를 사용하면 Main VI를 변경하지 않고도 디스크에 새 플러그인 VI를 추가할 수 있습니다. 

 

재호출 VI

기본적으로 LabVIEW의 VI는 재호출되지 않습니다. 이것은 단순히 한 번에 하나의 VI 인스턴스만 실행할 수 있음을 의미합니다. 따라서 다음 다이어그램에서 'Process.vi'의 SubVI 인스턴스 중 하나는 다른 인스턴스가 완료될 때까지 기다려야 합니다.

VI의 여러 인스턴스를 병렬로 실행하려면 VI를 재호출로 만들어야 합니다. 이렇게 하려면 파일(File) > VI 프로퍼티(VI Properties) > 실행(Execution)으로 이동하여 '재호출(Reentrancy)' 설정을 공유 복제 재호출 실행(Shared clone reentrant execution) 또는 미리 할당된 복제 재호출 실행(Preallocated clone reentrant execution)으로 변경합니다.

 

VI를 재호출로 변경하면 여러 인스턴스를 병렬로 실행할 수 있습니다.

다음 시나리오에서는 VI를 재호출로 만드는 것을 고려하십시오.

  • 같은 VI의 여러 인스턴스를 병렬로 실행하여 어플리케이션 성능 향상
  • 정교한 사용자 인터페이스 디스플레이를 위해 동일한 VI 프런트패널의 여러 인스턴스를 디스플레이

기능적인 글로벌 변수는 전체 어플리케이션이 공유해야 하는 글로벌 상태 데이터를 유지하기 때문에 거의 항상 재호출하지 않습니다.

 

비동기 프로세스

대부분의 경우 다른 VI에서 VI를 호출할 때 일반 SubVI 호출을 사용합니다. SubVI를 호출할 때 호출 다이어그램은 SubVI의 실행이 완료될 때까지 기다려야 계속 진행됩니다. 이는 동기 호출의 예입니다.

그러나 어떤 경우에는 어플리케이션에서 SubVI를 시작해야 하지만 SubVI가 계속 실행되는 동안 호출 VI를 계속해서 실행해야 할 수도 있습니다. 이는 비동기 호출의 예입니다. 비동기 VI 호출을 사용하면 여러 VI를 병렬로 동적으로 실행할 수 있습니다. 또한 재호출 VI를 사용하면 동일한 VI의 인스턴스를 임의 개수로 생성하여 비동기적으로 실행할 수 있습니다.

아래 예제에서 호출 VI는 재호출 Process.vi의 여러 인스턴스를 비동기적으로 호출합니다.  각 VI는 독립적으로 실행되며 완료될 때마다 호출 VI에 데이터를 반환합니다.  호출 VI는 다른 블록다이어그램 코드를 병렬로 실행할 수 있으며 프로세스 VI 인스턴스가 완료될 때까지 기다리지 않습니다. 

 

객체 지향 프로그래밍

LabVIEW에서는 LabVIEW 클래스를 통해 객체 지향 프로그래밍을 수행할 수 있습니다.  LabVIEW 객체 지향 프로그래밍은 캡슐화와 상속 등 C++ 및 Java와 같은 다른 객체 지향 프로그래밍 언어의 개념을 사용합니다. 이러한 개념을 사용하여 어플리케이션 내의 다른 코드 섹션에 영향을 미치지 않고도 관리하고 수정하기 쉬운 코드를 생성할 수 있습니다. LabVIEW에 적용할 수 있는 많은 객체 지향 설계 패턴이 있습니다. 

 

설계 패턴

설계 패턴은 동기 또는 비동기 코드를 실행하는 이론적 메커니즘입니다. 대부분의 실제 아키텍처 (아래 섹션 참조)는 하나 이상의 설계 패턴을 핵심 실행 메커니즘의 일부로 활용합니다. 이 섹션에서 설계 패턴의 동작을 이해하면 이러한 설계 패턴을 기반으로 구축된 더 복잡한 아키텍처의 동작을 이해하기 쉬워집니다.

 

상태 머신

상태 머신은 상태 다이어그램 또는 순서도의 LabVIEW 블록다이어그램 구현입니다. 주어진 "상태"에는 실행할 다음 상태를 결정하는 블록다이어그램 로직이 있습니다. 일부 상태 머신은 사용자 입력 또는 블록다이어그램 로직에서 다음에 실행할 상태를 결정할 수 있는 사용자 인터페이스로 구동됩니다.  

 

기본 LabVIEW 상태 머신은 다음과 같은 주요 구성요소로 구성됩니다.

  • 상태 머신의 각 상태의 이름이 포함된 타입 정의 열거형
  • 각 상태에 대해 실행될 코드와 시퀀스의 다음 상태를 결정하는 전환 코드가 포함된 케이스 구조
  • 상태 머신이 여러 상태를 연속적으로 실행할 수 있는 While 루프
  • 루프의 다음 반복에서 실행할 상태를 지정하는 시프트 레지스터
  • (옵션) 사용자 인터페이스 이벤트를 처리하는 이벤트 구조가 포함된 '이벤트 기다림' 상태

 

 

생산자/소비자

생산자/소비자(Producer/Consumer) 설계 패턴은 를 사용하여 서로 다른 속도로 실행되는 여러 루프 간에 데이터를 공유하는 방법을 보여줍니다. 원소를 큐에 추가 함수가 포함된 루프는 "생성자"이고 원소를 큐에서 제거 함수가 포함된 루프는 "소비자"입니다. 큐를 사용하면 루프가 다른 속도로 실행되는 경우에도 데이터가 손실되지 않습니다. 

생산자/소비자 설계 패턴에서 염두에 두어야 할 한 가지는 대부분 이론적인 패턴이라는 점입니다. 실제로는 실제 코드에서 기본적인 생산자/소비자 패턴을 거의 볼 수 없습니다. 대신 큐 메시지 핸들러를 볼 가능성이 훨씬 더 높습니다.

 

큐 메시지 핸들러

큐 메시지 핸들러 (QMH)는 생산자/소비자 설계 패턴을 구현한 것으로 사용자 인터페이스와 프로그램적 이벤트 생성을 위한 이벤트 구조도 포함되어 있습니다.  이벤트 핸들링 루프 (EHL)에는 메시지 핸들링 루프 (MHL)의 메시지를 큐에 추가(생성)하고 메시지를 큐에서 삭제(소비)하는 이벤트 구조가 포함되어 있습니다. MHL은 필요에 따라 자체적으로 메시지를 생성할 수도 있습니다.  이 경우 "메시지"는 (MHL에서 케이스 구조를 구동하는) 문자열과 모든 타입의 메시지 특정 데이터를 포함할 수 있는 베리언트가 포함되는 클러스터입니다.  QMH에서 MHL은 또한 사용자 이벤트를 사용하여 EHL과 다시 통신할 수 있습니다.  

 

아키텍처

대규모 LabVIEW 어플리케이션이 확장 가능하고 유지보수가 가능하려면 잘 설계되어야 합니다.

디바이스를 테스트하는 이론적 LabVIEW 어플리케이션을 떠올려 보십시오. 어플리케이션 설정, 디바이스 연결, 측정 수행, 데이터 디스플레이, 데이터 로깅, 에러 조건 처리, 그리고 잠재적으로 더 많은 기능에 사용 가능한 코드가 있습니다.

이 어플리케이션의 설명된 모든 기능이 동일한 LabVIEW 블록다이어그램에 있는 경우 어플리케이션의 기능을 개별적으로 개발, 테스트, 디버그할 수 없습니다.  예를 들어, 로깅 코드에 문제가 있는 경우 전체 어플리케이션을 실행하지 않고 로깅만 디버그할 수 있는 방법은 없습니다. 또한, 로깅 코드를 변경하면 모두 동일한 VI 내에 있기 때문에 어플리케이션의 다른 부분에 실수로 영향을 미칠 수 있습니다.

 

위에서 설명한 각 함수는 각 함수가 모듈형이며 독립적으로 개발되고 테스트되며 디버깅할 수 있는 비동기식 프로세스에 더 적합합니다. 또한 프로세스 간의 강력한 통신 메커니즘이 필요합니다.

이러한 종류의 모듈형 비동기 설계를 용이하게 만들기 위해 LabVIEW 코드를 구현하는 구조화된 접근 방식을 아키텍처라고 합니다. 일부 LabVIEW 팀은 아키텍처를 자체 개발합니다. 성공적인 비동기 LabVIEW 어플리케이션을 구현하는 데 필요한 코드 인프라와 메시징 개발에는 고려해야 할 사항과 함정, 주의 사항이 많기 때문에 어려운 작업이 될 수 있습니다. 또한 강력한 프레임워크를 구현하는 데 필요한 상용구 코드의 양 때문에 프레임워크 내에서 반복적인 작업을 자동화할 수 있는 충분한 도구가 필요합니다(개발자가 프레임워크 레벨 코드를 직접 수동으로 프로그래밍할 때 실수를 방지하기 위해).

 

 

액터 프레임워크

액터 프레임워크(AF)는 LabVIEW와 함께 제공되는 NI가 지원하는 아키텍처입니다. 큐 메시지 핸들러 (QMH)의 객체 지향 구현입니다. 메시지 클래스는 케이스 구조의 메시지 핸들링 루프 프레임과 원소를 큐에 추가 함수 대신 액터 코어 VI 내의 특정 코드를 실행하기 위해 '실행' 메소드 VI를 제공합니다.

AF의 클래스 기반 설계는 상위 액터의 동작을 상속하는 하위 액터를 구현하기 위한 확장 가능한 프레임워크를 제공하며 이는 표준 케이스 구조 기반 QMH 접근 방식으로는 불가능합니다. 또한 모든 핵심 프레임워크 기능 (초기화, 메시징, 에러 응답 등)은 프레임워크의 객체 지향 설계의 힘으로 주어진 액터에서 확대되거나 덮어써질 수 있습니다.

 

 

DQMH

Delacor 큐 메시지 핸들러 (DQMH®)는 주어진 프로세스 (또는 "모듈") 내 통신을 위해 표준 QMH와 유사한 메커니즘을 사용하지만 비동기 모듈 간 통신은 사용자 이벤트로 발생합니다. DQMH는 객체 지향 아키텍처가 아니지만 프레임워크의 일부 보조 구성요소에 LabVIEW 클래스를 사용합니다.

DQMH는 DQMH 컨소시엄에서 개발하고 유지 관리하는 타사 아키텍처입니다. 초기 DQMH 설계팀의 주요 목표는 LabVIEW 커뮤니티에 CLAD/CLD 레벨 개발자가 액세스할 수 있는 무료 프레임워크를 제공하는 것이었습니다.

VI 패키지 관리자를 사용하여 DQMH를 설치할 수 있습니다.

728x90
반응형
그리드형