Modbus는 일반적으로 장치간 SCADA 식의 네트워크 통신에 사용됩니다. 예를 들어, 대형 서버는 PLC 또는 PAC의 마스터가 될 수 있고, PLC/PAC는 또한 센서, 밸브, 모터 또는 기타 임베디드 장치의 마스터가 될 수도 있습니다.
이러한 요구를 충족하기 위해 Modbus는 유연적인 데이터 및 함수 모델을 갖춘 요청-응답 프로토콜로서 제작되었습니다. 이러한 특징이 바로 Modbus가 현재에도 여전히 사용되는 이유입니다.
Modbus 프로토콜은 마스터-슬레이브 구조를 따르며, 이 구조하에서는 마스터는 슬레이브에 요청을 보내고 응답을 기다립니다. 이 구조를 통해 마스터는 정보의 흐름을 전적으로 컨트롤할 수 있어, 종전의 멀티드롭 시리얼 네트워크에 유용합니다. 심지어 현대식 TCP/IP 네트워크에서도 마스터가 슬레이브의 동작을 상당 부분을 컨트롤할 수 있으므로 일부 디자인에 유용합니다.
그림 1: Modbus 장치의 마스터-슬레이브, 요청-응답 구조
Modbus에서 요청은 여러 층으로 된 데이터의 세트입니다. 첫 번째 계층은 Application Data Unit(ADU)로, 대부분의 사람들이 ADU를 Modbus의 "유형"이라고 생각합니다. ADU에는 ASCII, Remote Terminal Unit(RTU), TCP/IP의 세 가지가 있습니다.
TCP는 소프트웨어에서 Modbus의 요청과 응답을 효율적으로 처리하고, 각 요청에 대한 전용 연결과 식별자를 통해 보다 효율적인 네트워킹을 구현하는 현대식 포맷입니다. RTU와 ASCII는 좀 더 오래된 시리얼 ADU 포맷으로, 차이점은 RTU는 바이너리 형식으로 데이터를 표현하며 ASCII는 ASCII 문자로 요청을 보낸다는 점입니다.
대부분의 어플리케이션에 선호되는 ADU는 필요한 물리 네트워크(이더넷, 시리얼 또는 기타), 네트워크 상의 장치의 개수, 네트워크에서 마스터와 슬레이브에 의해 지원되는 ADU에 따라 달라질 수 있습니다. Modbus를 사용하는 어플리케이션의 관점에서 보면, 마치 ADU가 존재하지 않는 것처럼 데이터가 표시되어야 합니다.
각 ADU 내에는 Modbus 프로토콜의 핵심인 Protocol Data Unit(PDU)이 있습니다. 각 PDU에는 함수 코드와 연관 데이터가 포함됩니다. 각 함수 코드에는 잘 정의된 응답이 있습니다. 이 함수 코드를 슬레이브에 보내지는 명령이라고 생각하면 됩니다.
일부 경우 에러가 발생할 수 있습니다. Modbus는 예외를 위한 특정 PDU를 정의함으로써 에러 발생을 마스터에게 알립니다. 대부분의 드라이버는 사용중인 언어나 어플리케이션에서 이해할 수 있는 형식으로 PDU를 변환합니다.
Modbus는 데이터의 접근을 간단하고 유연하게 처리합니다. 원래 Modbus는 두 가지 데이터 타입 즉, 불리언 값과 부호 없는 16비트 정수를 지원합니다.
SCADA 시스템에서 일반적으로 임베디드 장치는 입력으로 정의된 특정 값(게인 또는 PID 설정 등)을 가지며, 다른 값으로는 전류 온도 또는 밸브 위치와 같은 출력값이 있습니다. 이러한 요구를 충족하기 위해 Modbus 데이터 값은 4개의 범위로 나뉩니다. (표 1 참조) 슬레이브는 각 범위에서 많게는 65,536개의 요소를 정의합니다.
메모리 블록 | 데이터 타입 | 마스터 접근 | 슬레이브 접근 |
Coils | 불리언 | 읽기/쓰기 | 읽기/쓰기 |
Discrete Inputs | 불리언 | 읽기만 | 읽기/쓰기 |
Holding Registers | 부호없는 워드 | 읽기/쓰기 | 읽기/쓰기 |
Input Registers | 부호없는 워드 | 읽기만 | 읽기/쓰기 |
표 1: Modbus 데이터 모델 블록
여러 경우, 센서 및 기타 장치는 단순히 불리언 및 부호 없는 정수가 아닌 다른 타입의 데이터를 생성합니다. 일반적으로 슬레이브 장치는 이러한 더욱 큰 데이터 타입을 레지스터로 변환합니다. 예를 들어, 압력 센서는 32비트 부동점 값을 2개의 16비트 레지스터로 나눌 수 있습니다.
Modbus는 이 값들을 개념적으로 (다시 말해, 메모리에 실제로 존재하지 않음) 표시합니다. 예를 들어, 슬레이브 장치는 Holding Register와 Input Register가 실제로 동일한 메모리를 공유하는 방식으로 정의될 수도 있습니다. (단, 동작을 슬레이브가 이해할 수 있는 경우) 대부분의 경우, 슬레이브는 지원하는 각 데이터 타입을 개별 메모리에 저장하며, 마스터가 접근할 수 있는 데이터 요소의 개수를 제한합니다. 이러한 유연성은 Modbus 함수 코드의 잘 정의된 동작을 통해 데이터가 표시되기 때문에 가능한 옵션입니다.
Modbus 함수 코드는 마스터가 데이터에 어떻게 접근하며 변경하는지를 결정합니다. 데이터 범위가 개념적인 성격인데 반해, 함수 코드는 잘 정의된 동작을 가집니다. 슬레이브가 함수 코드를 수행하도록 요청을 받으면, 함수의 파라미터를 사용하여 정의된 동작을 실행합니다. 그림 2는 함수 요청과 장치의 실제 메모리의 연결 관계를 나타냅니다.
그림 2: 함수 코드, 데이터 범위 및 슬레이브 장치의 실제 메모리 사이의 관계
가장 일반적인 함수 코드는 코드가 변경하거나 접근하려는 개념적인 데이터 범위에 따라 이름이 정해집니다. 예를 들어, "read holding registers"라는 함수 코드는 홀딩 레지스터라고 정의된 메모리에서 데이터를 꺼낸 후 마스터로 반환합니다. 표 2는 가장 일반적인 함수 코드를 나타냅니다.
표 2: 일반적인 함수 코드
NI는 Modbus 장치와 연동하기 위한 세 가지 주요 구조를 제공합니다. (1) 하이레벨 OPC 서버, (2) Modbus I/O 서버, (3) 로우레벨 Modbus API (LabVIEW Real-Time 또는 LabVIEW Datalogging and Supervisory Control (DSC) Module을 통해 NI LabVIEW 2014에서 소개된 기능)
로우레벨 Modbus API는 Modbus 요청의 시퀀스 및 타이밍을 하이레벨로 컨트롤해야 하는 어플리케이션에 선호되는 옵션입니다. 또한 로우레벨 API는 유연성이 중요한 경우에도 일반적으로 선호됩니다. 그러나, LabVIEW Modbus API가 유연성과 강력한 성능을 제공하지만 API를 처리하기 위해 어플리케이션 코드가 그만큼 복잡하다는 뜻이기도 합니다. 이러한 복잡성의 이해를 돕기 위해 LabVIEW는 두 가지 예제를 제공합니다.
첫 번째 예제인 Modbus Library.lvproj는 API의 기능을 간략하게 설명합니다. 또한, PC와 Real-Time 타겟에 실행되었을 때의 차이를 설명합니다. 그림 3은 Real-Time 타겟에서 Modbus 마스터 코드 실행을 보여줍니다.
그림 3: Master on RT Target.vi
이 예제는 LabVIEW API를 사용하는 Modbus 어플리케이션의 핵심 요구사항을 설명합니다. 첫째, Modbus 인스턴스가 생성됩니다. 이 경우, TCP 마스터입니다. 그러나, 다형성 인스턴트 선택자를 변경하여 이 예제를 시리얼 마스터로 전환할 수 있습니다.
그림 4: Modbus 마스터의 유형 변경하기
인스턴스가 생성되면, 사용자는 슬레이브 장치에 대한 폴링을 시작할 수 있습니다. 예제는 함수 코드 Read Input Registers의 사용을 보여줍니다. API에 의해 지원되는 모든 Modbus 함수 코드가 적절한 팔레트에 나타납니다. 슬레이브 API는 마스터가 실행할 수 없는 추가적인 함수를 가지고 있습니다. 예를 들어, 슬레이브는 입력 레지스터 범위에 쓸 수 있지만 마스터는 그 범위로부터 읽을 수만 있습니다. 그림 5는 함수 코드를 나타냅니다.
그림 5: Modbus 마스터 및 슬레이브 팔레트의 함수 코드
마지막으로, Modbus 인스턴스가 닫히면 인스턴스와 연관된 메모리 할당이 해제됩니다. 이 때 TCP 연결 또는 NI-VISA 시리얼 참조와 같은 모든 참조도 닫힙니다.
지금까지 마스터 예제에 대해서만 살펴보았습니다. 그러나, 모든 예제는 대부분의 LabVIEW 사용자들에게 친숙한 열기, 읽기/쓰기, 닫기 등의 기본 패턴을 따릅니다.
마지막으로, API가 똑같이 보인다 하더라도 주요 차이점을 이해해야 합니다. 사용하는 장치가 마스터인 경우, 마스터는 데이터를 수집하기 위해 네트워크에서 적합한 슬레이브로 요청을 보내야 합니다. 반면 슬레이브는 고유한 로컬 데이터 스토리지를 가지며 여기에 신속하게 접근할 수 있습니다.
일부 어플리케이션은 기본 예제만으로 충분할 수 있지만, 센서나 게이트웨이에 통신해야 하는 복합 어플리케이션의 경우 기본 예제가 충분하지 않을 수 있습니다. 이같은 문제를 해결하기 위해 샘플 어플리케이션은 두 개의 마스터를 사용하여 주어진 슬레이브와 통신하는 방법을 보여줍니다. 마스터 중 하나가 슬레이브 또는 HMI와의 연결에 실패하거나 연결을 잃은 경우, 다른 마스터가 대신합니다.
그림 6: 중복 마스터 구조의 예
이 디자인이 어플리케이션에 적합하다고 생각하거나, Modbus 통신의 보다 복합적인 예제에 관심이 있는 경우, 예제 검색기에서 Redundant Modbus Masters.lvproj를 확인하십시오.
LabVIEW DSC 및 LabVIEW Real-Time Module에 있는 Modbus I/O 서버는 Modbus에서 통신하기 위한 하이레벨 엔진을 제공합니다. 전송하고자 하는 함수 코드를 지정하는 대신, 접근하려고 하는 데이터 세트를 등록하면 I/O 서버가 지정된 속도로 요청을 자동적으로 스케쥴합니다.
I/O 서버를 사용하기 위해 프로젝트의 원하는 타겟에 새로운 I/O 서버를 추가합니다. 로우레벨 API에서 처럼, Modbus 마스터 또는 슬레이브 중 선택하면 추가적인 파라미터가 생깁니다. 예를 들어, 마스터는 지정된 폴링 속도(모든 요청이 슬레이브에 보내지는 속도)가 있는 반면, 슬레이브는 이러한 요청에 대해 대기해야 하며 미리 정의된 타이밍이 없습니다.
I/O 서버가 생성된 후, 사용자는 읽으려고 하는 장치의 아이템을 지정할 수 있습니다. 로우레벨 API의 경우 요청을 반드시 직접 생성하고 처리해야 하지만, Modbus I/O 서버를 사용하면 다양한 포맷과 데이터 타입 중에서 선택할 수 있습니다. 예를 들어, 변수를 아이템 400001로 맵핑하여 address 0에서 홀딩 레지스터를 읽을 수 있고, 400001.1을 선택하여 이 레지스터의 첫 번째 비트를 읽을 수 있고, F400001을 선택하여 레지스터 0과 1에 저장된 단정도 부동소수를 읽을 수 있습니다.
접근할 변수를 선택한 후, 사용자는 블록다이어그램의 공유 변수 노드를 사용하여 이러한 변수를 읽거나 쓸 수 있습니다. 변수 이름에 가명을 정할 수도 있습니다.
그림 7: 간단한 I/O 서버 어플리케이션
I/O 서버 어플리케이션은 최소한의 프로그래밍만 필요하며 이해하기가 더욱 쉽습니다. 단, 사용이 쉬운 만큼 단점도 있다는 것을 기억하십시오. 즉, 데이터는 미리 지정된 속도로만 업데이트되며, 요청된 데이터를 실행 중에 추가하거나 제거할 수 없습니다. 이러한 제약이 상관 없다면 I/O 서버를 크로스 플랫폼 옵션으로 권장합니다.
보다 자세한 정보 및 단계별 가이드가 필요한 경우, Connect LabVIEW to Any PLC With Modbus 문서를 확인하십시오.
여러 슬레이브 장치가 서로 다른 프로토콜로 통신하는 복잡한 어플리케이션의 경우, 표준 Modbus I/O는 충분하지 않을 수 있습니다. 이 때 일반적으로 모든 시스템에 대한 Data Aggregator의 역할을 하는 OPC 서버를 사용하며, 그 후 이 OPC 서버와 통신하기 위해 LabVIEW DSC Module에 포함된 OPC I/O 서버를 사용합니다.
그림 8은 이 구조의 예를 보여줍니다. NI OPC 서버에서 Modbus를 사용하여 센서와 직접 통신하며, OPC UA를 사용하여 NI CompactRIO PAC와 통신합니다. 데이터가 NI OPC 서버에 모이면, OPC I/O 서버는 데이터를 추출하여 이를 LabVIEW 어플리케이션과 공유합니다.
그림 8: Modbus, NI OPC 서버 및 OPC I/O 서버를 사용하는 SCADA 어플리케이션
OPC I/O 서버 대신 LabVIEW DSC Module에 포함된 OPC UA 드라이버를 사용하는 유사한 아키텍처를 개발할 수도 있습니다. 그러나 OPC UA 드라이버는 로우레벨 드라이버이며 OPC I/O 서버만큼 사용이 쉽지 않습니다.
이 방식으로 어플리케이션을 개발하려면 슬레이브 장치와 통신하기 위해 NI OPC 서버에 유효한 설정을 반드시 먼저 생성해야 합니다. 설정을 생성하기 위해 채널(드라이버 설정을 정의)과 장치(드라이버에 대한 개별 엔드포인트를 정의)를 생성해야 합니다. 장치를 설정한 후 태그를 생성합니다.
그림 9: NI OPC 서버의 설정 샘플
NI OPC 서버를 설정한 후 태그와 통신하기 위해 OPC I/O 서버를 설정합니다. Modbus I/O 서버는 레지스터에 접근하기 위해 설정되지만, OPC I/O 서버는 OPC 서버에 있는 태그에 접근하기 위해 설정됩니다.
그림 10: OPC I/O 서버 설정하기
이같은 연결 과정을 통해 어플리케이션에서 사용할 수 있는 변수를 생성할 수 있습니다.
그림 11: OPC I/O 서버를 사용하는 간단한 어플리케이션
이 과정에 대한 자세한 설명은 OPC를 이용하여 LabVIEW와 PLC 연결 문서를 확인하십시오.
Modbus는 강력한 어플리케이션을 실행하기 위해 다양한 방식으로 사용할 수 있는 간단한 프로토콜입니다.
NI는 각 어플리케이션의 요구를 충족하기 위해 다양한 기능을 제공하는 세 가지의 Modbus 통신 옵션을 제공합니다. 첫째, 로우레벨 API는 프로토콜에 대한 정밀 컨트롤을 제공하며 고성능을 제공하지만 사용이 쉽지 않습니다. 로우레벨 API를 사용할 때 모든 작업이 수동으로 이루어집니다. 보다 간단한 모니터링 어플리케이션을 위한 Modbus I/O 서버는 Modbus 데이터에 접근하고 데이터를 처리하기 위한 보다 간단하고 편리한 API를 제공합니다. 그러나, 사용이 쉬운 대신 I/O 서버는 프로토콜에 대한 제어가 정밀하지 못합니다. 마지막 옵션으로 대형의 복잡한 시스템의 경우 전 기능을 갖춘 OPC 서버를 Data Aggregator로 사용할 수 있습니다. 이 때, LabVIEW OPC UA 드라이버 또는 OPC I/O 서버와 같은 툴을 사용하면, 어플리케이션이 데이터에 접근할 수 있도록 할 수 있습니다.