상태 머신은 LabVIEW 개발자들이 어플리케이션을 빠르게 개발하기 위해 자주 사용하는 기본 아키텍처 중 하나입니다. 상태 머신 아키텍처는 상태 다이어그램이나 순서도로 나타나는 복잡한 의사 결정 알고리즘을 구현하는 데 사용할 수 있습니다. 상태 머신은 기본 LabVIEW 함수로 구현할 수 있으며, 아키텍처에 추가적인 툴킷이나 모듈이 필요하지 않습니다.
이 문서에서는 상태 머신이란 무엇인지, 사용 사례, 상태 머신의 개념을 보여주는 예제, 상태 머신 코드의 상세 예제를 살펴봅니다.
상태 머신은 이전 상태 또는 사용자 입력의 값에 따라 동적으로 상태를 변경하는 프로그래밍 아키텍처입니다.
이 아키텍처는 다음을 결합한 어플리케이션에 적당합니다.
상태는 프로그램의 전반적인 작업을 수행하는 동안의 프로그램 내 상태로 정의할 수 있습니다. 상태의 예로는 초기화 중, 대기 중, 계산 실행 중, 상태 확인 중 등이 있습니다.
논리적 구문을 바탕으로 언제 새로운 상태로 이동할지와 어떤 상태로 이동할지 결정할 수 있습니다. 이벤트는 한 상태에서 다음 상태로 이동하는 데 사용할 수 있습니다. 이는 프로그램적인 이벤트이거나 버튼을 누르는 것과 같이 사용자 정의된 이벤트일 수 있습니다.
상태 머신의 각 상태는 고유한 작업을 수행하고 다른 상태를 호출합니다. 상태 통신은 조건이나 시퀀스에 따라 다릅니다. 상태 다이어그램을 LabVIEW 프로그래밍 아키텍처로 변환하려면 다음 인프라가 필요합니다.
상태 머신은 상태가 뚜렷하게 구별되는 어플리케이션에서 사용됩니다. 각 상태는 한 가지 또는 여러 가지 상태로 이어질 수 있고 프로세스를 종료할 수도 있습니다. 상태 머신은 사용자의 입력 또는 현재 상태 내의 계산에 따라 다음으로 진행할 상태를 결정합니다. 많은 어플리케이션은 기본 상태 다음에 여러 작업이 실행될 수 있는 초기 상태를 요구합니다. 실행되는 작업은 이전 및 현재 입력과 상태에 따라 달라질 수 있습니다. 그리고 “종료” 상태로 정리 작업을 수행할 수 있습니다.
상태 머신은 의사 결정 알고리즘을 구현할 수 있는 강력한 기능을 갖고 있으면서, 어플리케이션 계획의 기능적인 형태입니다. 어플리케이션이 더욱 복잡해지면서 적절한 설계의 필요성도 더 커집니다. 상태 다이어그램과 순서도는 설계 프로세스에 유용하며 때로는 필수적입니다. 상태 머신은 어플리케이션 계획에 도움이 될 뿐만 아니라 만들기도 쉽습니다.
예를 들어, 다음과 같은 어플리케이션에서 상태 머신 패턴이 유용합니다.
사용자 인터페이스 구현에 사용할 수 있는 또 다른 디자인 패턴인 큐 메시지 핸들러도 있습니다. 큐 메시지 핸들러는 보다 정교한 상태 머신이며 더 유연하긴 하지만 더 복잡하기도 합니다.
효과적인 상태 머신을 만들려면 설계자가 (1) 가능한 상태의 목록을 만들어야 합니다. 설계자는 이 목록으로 (2) 각 상태와 다른 상태의 관계를 계획할 수 있습니다. 그 후 상태 다이어그램을 (3) LabVIEW 그래픽 프로그래밍 아키텍처로 변환할 수 있습니다.
이 예에서는 위험하게 과열되지 않고 연속적으로 대포를 발사하는 어플리케이션을 생성하려고 합니다.
(1) 가능한 상태 나열
먼저 작업에서 가능한 모든 상태의 목록을 만듭니다. 대포를 연속 발사하려면 다음을 수행해야 합니다.
(2) 상태 다이어그램으로 상태 간 관계 연결
다음으로 이러한 상태가 서로 어떻게 관련되어 있는지 살펴보고 상태 다이어그램을 만듭니다. 상태 다이어그램을 작성할 때, 프로그램이 한 상태에서 다른 상태로 이동하는 원인을 살펴보십시오. 자동 변환입니까? 사용자로부터의 외부 트리거가 있습니까? 계산 결과에 기반한 변환입니까?
예를 들어, 초기화 상태와 다른 상태 사이의 관계를 생각해봅시다.
상태가 서로 어떻게 관련되어 있는지 분석하면서 상태 간 이동 로직이 정의되기 시작된 점을 주목해 보십시오. 코드에 사용할 프로그래밍 로직은 (1) 변이 상태의 개수, (2) 고려되는 입력의 개수에 따라 달라집니다. 코드 전이 옵션은 아래의 전이 코드 예제 섹션에서 설명됩니다.
전체 상태 다이어그램이 완성될 때까지 상태의 상호 연관성을 계속 살펴보십시오. 상태 다이어그램은 모든 상태와 각 상태 사이의 관계를 포함합니다 (그림 1). 이 다이어그램에서 상태 (타원 노드)는 해당 상태에서 수행되는 동작을 나타내는 반면, 변이 (화살표)는 프로세스가 언제 어떻게 움직일 수 있는지를 나타냅니다.
그림 1: 대포 발사 상태 다이어그램
각 상태 사이의 관계는 상태 변이 로직 프로그래밍에 도움이 됩니다.
(3) LabVIEW에서 상태 머신 구축
상태 다이어그램에서 상태와 상태 간 관계를 정의하고 나면, 이를 LabVIEW의 코딩 아키텍처로 변환할 수 있습니다 (그림 2). 상태 다이어그램에서 상태 사이의 흐름 (그림1)은 루프로 구현됩니다. 개별 상태는 케이스 구조에서 케이스로 대체됩니다. 위 다이어그램의 각 상태는 케이스 구조의 서브다이어그램에 해당합니다. 각각의 상태:
While 루프의 시프트 레지스터는 현재 상태를 추적하며, 이는 케이스 구조 입력으로 전달됩니다.
그림 2: 상태 머신
이 템플릿을 측정 어플리케이션에 맞게 변경하는 예제를 보려면 프로젝트 생성 대화 상자의 단일 측정 샘플 프로젝트를 참조하십시오.
1. 사용자가 어플리케이션의 정지를 원할 때에만 종료 코드가 실행됩니다.
2. 종료 코드는 항상 완료될 때까지 실행됩니다.
시작하는 방법은 기본 상태 머신 수정 LabVIEW 템플릿 길라잡이를 참조하십시오.
이 템플릿을 사용자 정의하기 전에 다음 질문에 답해 보십시오.
다음 상태를 결정하는 데에는 다양한 방법이 있습니다. 그 방법은 아래에 설명됩니다.
예제 이미지는 "초기화" 상태를 보여주지만, 이러한 전이는 모든 상태에 적용될 수 있습니다.
1 대 1: 항상 상태 A에서 상태 B로 전환하면, 로직을 작성할 필요가 없이 다음 케이스 (케이스 B)의 이름을 시프트 레지스터에 전달하기만 하면 됩니다.
그림 3a: 유일하게 가능한 전이 상태
1 대 2: 상태 A에서 상태 B 또는 상태 C로 전환할 수 있는 경우, [선택] 함수를 사용하여 인디케이터의 상태를 평가할 수 있습니다. 어떤 상태로 이동할지를 결정하는 요소를 평가해야 합니다. 예를 들어 그림 3b의 정지 버튼 사용자 입력에 따라 전원 가동 상태에서 이동할지 아니면 종료로 이동할지 결정됩니다.
그림 3b: 두 가지 전이 상태
배열을 통한 1 대 다: 여러 상태로 전환할 수 있는 경우, 열거형 상수와 연관된 불리언 영역을 사용하여 전환을 프로그램할 수 있습니다. 예를 들어 그림 3c에서는 실행되는 코드의 결과가 불리언 배열로 나타나며 이 결과로 변환이 결정됩니다. 불리언 배열은 전환 가능한 상태의 목록을 나타내는 열거형 상수와 상호 연관됩니다. [배열 인덱스] 함수를 사용하여, 불리언 배열에서 첫 번째 "참" 불리언의 인덱스가 출력됩니다. 그런 다음 [배열 부분] 함수를 사용하여 해당 열거형 상수에서 적절한 값을 가져올 수 있습니다.
그림 3c
팁: 배열의 인덱스는 0부터 시작하고 열거형은 1부터 시작한다는 점을 기억하십시오. 불리언 배열을 열거형 상수와 연결하려면, [증가] 함수를 사용하여 인덱스를 수정하십시오.
While 루프를 통한 1 대 다: 여러 가능한 전이 상태가 있는 경우를 위한 다른 방법은 케이스 안에 While 루프를 사용하는 것입니다. While 루프 내부의 코드는 불리언 상태가 참으로 설정되어 정지 버튼을 트리거할 때까지 계속됩니다. 이렇게 하면 트리거 이벤트가 발생할 때까지 코드가 효과적으로 실행될 수 있습니다.
그림 3d는 내부 루프와 케이스 구조를 사용하여 다음 상태로 전환하는 "초기화" 상태를 보여줍니다. 내부 케이스 구조는 현재 상태에서 나가는 각각의 전환에 대해 하나의 다이어그램을 포함합니다. 내부 케이스 구조의 각 케이스에는 두 개의 출력이 있습니다. 하나는 전환할지 여부를 결정하는 불리언 값, 그리고 하나는 전환할 상태를 정하는 열거형 상수입니다. 루프 인덱스를 케이스 구조의 입력으로 사용함으로써, 이 코드는 “참” 불리언 출력이 있는 다이어그램을 찾을 때까지 각 전환 케이스를 확인합니다. “참” 불리언 출력이 발견되면, 케이스는 전환할 새 상태를 출력합니다. 이 방법은 이전 방법보다 약간 복잡하지만, 루프 인덱스의 출력을 열거형 타입으로 “캐스트”하면 전이에 이름을 붙일 수 있습니다. 이러한 이점을 사용하면 전환 코드를 “자동으로 문서화”할 수 있습니다.
그림 3d
코드 중복
문제: 상태 머신을 생성할 때 가장 어려운 부분은 상태 다이어그램의 상태를 나누는 부분입니다. 예를 들어, 콜라 자판기 상태 다이어그램 (그림 4)에서 동전 유형에 따라 하나의 상태에서 다른 상태로 이동하는 “응답 대기” 상태 대신, 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50센트 상태를 사용할 수도 있었습니다. 그러면 정확히 같은 케이스 다이어그램에서 11개의 상태가 생성됩니다. 코드 중복은 더 큰 어플리케이션에서는 큰 문제를 일으킬 수 있습니다.
해결책: 다른 상태가 같은 케이스 다이어그램을 가지고 있는 경우, 하나의 상태로 결합해 보십시오. 예를 들어, 코드 중복을 피하기 위해 “응답 대기” 상태를 만들 수 있습니다.
열거형 사용
문제: 열거형은 상태 머신의 케이스 선택자로 널리 사용됩니다. 사용자가 이 열거형에 상태를 추가하거나 삭제하면, 이 열거형의 복사본에 연결된 나머지 와이어가 끊어집니다. 이 현상은 열거형으로 상태 머신을 구현할 때 발생하는 가장 일반적인 장애 요소 중 하나입니다.
해결책: 다음은 이 문제를 해결하는 수 있는 두 가지 방법입니다.
1. 모든 열거형이 변경된 열거형에서 복사되면 중단되는 문제가 사라집니다.
2. 그 열거형을 가진 새 컨트롤을 생성하고 서브메뉴에서 “타입정의”를 선택합니다. 타입정의를 선택하면, 사용자가 상태를 추가하거나 제거할 때 모든 열거형 복사본이 자동으로 수정됩니다.
LabVIEW의 상태 머신과 기타 고급 아키텍처에 대해 자세히 알아보려면, LabVIEW Core 2 고객 교육과정을 수강하십시오.