본문 바로가기

스마트팩토리?

Modbus

Modbus란?

산업용 전기 장비에서 데이터를 전송하기 위해 사용되는 통신 프로토콜로, 최초에는 Modicon 사 ( 현재 슈나이더 일렉트릭에 인수 )의 PLC 간 통신을 위해 개발되었다. 국제 표준으로 지정된 적은 없지만, 산업계에서 워낙 많이 사용되기 때문에 사실상 표준(de-facto)에 해당한다. HMI와 같은 PLC 관련 장치들은 대부분 Modbus를 지원한다.

RS232, RS422, RS485 등 시리얼 통신 방식 또는 이더넷 - TCP/IP 기반으로 동작할 수 있다.

특징

  1. 마스터 - 슬레이브 구조: 하나의 마스터 디바이스(PC 등)가 여러 슬레이브 디바이스와 요청 - 응답
  2. 프로토콜이 공개되어 있음 => 무료로 사용 가능
  3. (시리얼)네트워크 상에서 최대 247개 장치를 운용할 수 있으며, broadcasting 기능 포함

종류

크게는 3개 종류가 있으나, Modbus+는 프로토콜이 공개되어 있지 않다. 주로 Modbus  RTU / Modbus TCP를 사용한다.

  1. Modbus Serial: 시리얼 통신을 기반으로 동작하는 방식
    1. Modbus ASCII: 프레임 본문을 ASCII 형식으로 표현하는 방식
    2. Modbus RTU: 프레임 본문을 이진 형식으로 표현하는 방식
  2. Modbus TCP: 이더넷 - TCP/IP 기반으로 동작하는 방식. 프레임 본문을 이진 형식으로 표현
  3. Modbus Plus: RS485 통신(시리얼)을 기반으로 802.4 token passing(가상 링 버스) 방식을 사용하는 방식.
    Modicon을 인수한 슈나이더 일렉트릭에서 자사 일부 제품에 사용하는 프로토콜로, 공개되어 있지 않다.

Modbus는 기본적으로 Master - Slave 통신 방식을 따른다.

  Master Slave
설명 네트워크에서 주도적인 역할을 수행하는 장치 마스터의 명령이나 요청에 응답하는 장치
제어권 통신 제어권 O. 슬레이브에게 요청하고 응답을 기다림 스스로 통신 불가. 마스터의 요청이나 명령을 기다림
주요 작업 요청 / 명령 전송 + 응답 대기 마스터 명령 수행 + 결과 반환

시리얼 통신을 기반으로 설계된 후 TCP 모델로 확장되었으므로, 먼저 2 종류의 시리얼 통신 방식에 대해 알아보자.

용어 정리

  • ADU(Application Data Unit): 통신을 위한 전체 프레임. PDU에 Slave 주소와 에러 체크 기능이 포함된다.
  • PDU(Protocol Data Unit): 프로토콜에서 전달하고 싶은 핵심 데이터가 포함된 유닛. 어떤 명령이나 데이터를 요정 할지 정보가 포함되어 있다.
  • Address: Slave를 식별하기 위한 주소. 0 ~ 247 사이의 값을 가진다.
  • Function Code: 마스터가 슬레이브에게 요청할 기능이 무엇인지 식별하는 영역
  • Data: 추가적인 데이터가 포함되는 영역. 요청한 기능에 따라 필요한 데이터가 달라진다.
  • Error Check: 프레임의 오류 검출을 위한 체크섬이 담기는 영역.

시리얼 통신에서는 Modbus 프로토콜이 Physical / Link Layer 프로토콜을 기반이기 때문에 체크섬을 통해 프레임의 오류를 검출하는 Error Check 영역이 필요하다.

Modbus TCP로 가면 TCP 프로토콜이 자체적으로 CRC 체크를 수행하므로 Error check 부분이 사라진다.

Modbus에서는 요청 / 응답 프레임의 규격이 동일하다.

데이터 타입

Modbus 공식 문서는 4개의 데이터 모델을 제시하고 있다. 데이터는 비트 또는 워드(16bit = short) 단위로 통신하며, 해당 데이터를 읽기만 가능한지, 아니면 읽고 쓸 수 있는지에 따라 4개의 데이터 타입으로 나뉜다.

  bit word
readonly Discretes Input Input Registers
read-write Coils Holding Registers

4개의 타입이 필요한 이유는 PLC와 연결되는 센서의 종류가 다양하기 때문이다. Modbus는 초기에 PLC 통신을 위해 만들어졌으며, PLC는 다양한 센서를 활용한 자동화 제어에 많이 사용된다. 이때, 어떤 센서는 읽기만 가능하며, 어떤 센서는 읽고 쓸 수 있다. 이러한 센서들의 특성에 대응하기 위해 4개의 타입이 생겼구나, 하고 생각해 볼 수 있다.

이름 설명 예시
Discrete Input 읽기만 가능한 비트 (Digital) 모션 감지 센서
Coils 읽고 쓸 수 있는 비트 (Digital) PLC의 1bit 메모리 영역, 스위치(램프 등)
Input Registers 읽기만 가능한 워드 (Analog ↑) 변위 / 속도 / 압력 센서
Holding Registers 읽고 쓸 수 있는 워드 (Analog ↑) 모터 속도 제어

Modbus RTU

프레임 본문을 이진 형식으로 표현하는 방식이다. ASCII 방식에 비해 프레임 당 전송하는 데이터가 거의 절반으로 효율적이므로, 산업계에서 훨씬 많이 사용된다.

Modbus RTU 프레임 규격
프레임 간 간격 = 3.5 character times

Start 또는 End로 표현된 영역은 각 프레임을 식별하기 위한 시간 간격이다. Modbus RTU에서는 데이터를 전송할 때 프레임 사이에 일정한 시간 간격을 둬서 각 프레임을 식별한다. 이 시간이 3.5 Character Times로, 프레임 본문에는 포함되지 않지만 Modbus RTU 명세에 포함되어 있다.

Address

슬레이브의 주소. 마스터에는 많은 슬레이브가 연결될 수 있기 때문에, 명령을 내릴 때 어떤 장치에게 내리는 명령인지 식별하기 위한 정보가 필요하다. Address는 각 슬레이브를 식별하기 위한 정보로 8비트 크기를 가지며, 0 ~ 247의 값을 사용할 수 있다.

0은 브로드캐스트 목적이므로, 하나의 마스터는 최대 247개의 장치와 연결될 수 있다.

  • Broadcast ( 0 ): 모든 슬레이브에게 요청. 응답 X
  • Unicast ( 1 ~ 247 ): 특정 슬레이브에게 요청. 응답 O

요청 / 응답 모두 슬레이브의 주소를 포함한다.

Function Code

slave가 수행해야 하는 작업의 코드를 의미하는 부분으로, 8비트 크기 ( 1 ~ 255 ) 를 가진다. 가장 첫 비트(MSB)는 오류가 발생했음을 나타내는 비트로, 슬레이브에서 오류가 발생하면 1로 설정한다. 따라서 실질적으로 정의할 수 있는 기능의 수는  최대 127개 정도로 보면 된다

  • Request: 슬레이브가 수행해야 하는 작업의 코드
  • Response
    • 성공: 코드를 그대로 보낸다
    • 실패: MSB를 1로 설정해서 보낸다.

예를 들어 Function Code가 0000 0001일 때 오류가 발생하면 1000 0001이 된다.

표준에는 다양한 Function Code가 미리 정의되어 있다.

위 코드 중 자주 사용되는 것을 정리하면 다음과 같다.

타입  코드 ( DEC / HEX ) 대상 타입  기능
READ 01 0x01 bit Read Coils
02 0x02 bit Read Discrete Inputs
03 0x03 word Read Holding Registers
04 0x04 word Read Input Registers
WRITE 05 0x05 bit Write Single Coil
06 0x06 word Write Single Register
15 0x0F bit Write Multiple Coils
16 0x10 word Write Multiple registers
R/W 23 0x17 word Read/Write Multiple registers

Data

슬레이브가 요청된 기능에 따라 필요한 데이터를 포함하는 부분. 기능에 따라 달라지므로, 명세를 잘 봐야 한다. 8bit 단위로 전송되며, 사용되지 않는 영역은 보통 0 값이 된다.

데이터 영역에는 명령에 따라 레지스터 / 메모리 주소를 쓰는 부분이 있는데, 이 메모리 주소는 0에서 시작한다. 공식 문서에서는 슬레이브의 메모리 주소가 1에서 시작하므로, Data address 0이 슬레이브의 첫번째 메모리에 대응된다고 표현한다. 의미만 알아두면 될 것 같다. 

  • Request: 기능 수행에 필요한 추가 정보 ( 레지스터 주소, 비트 / 워드 데이터 정보 등)
  • Response: 요청한 데이터. 오류가 발생한 경우에는 예외 처리 코드를 포함한다.

예시

1) read coils ( 0x01 )

0x13(19) 주소에서 0x13(19)개의 데이터를 읽어오는 명령이다.

2) write single coil ( 0x04 )

0x00AC 주소의 값을 "True" 로 설정한다. 하나의 비트를 쓰는 경우, 0xFF00은 True, 0x0000은 False에 대응된다.

Error Check

체크섬을 통해 에러를 체크하는 부분이다. ASCII와 RTU가 서로 다른 방식을 이용한다.

  • RTU: CRC ( 16 bit )
  • ASCII: LRC ( 8bit ) => 2 char

예외 처리

기능이 제대로 동작하지 않는 경우 Function Code 부분과 Data 부분을 이용하여 예외 발생 여부 및 예외 코드를 반환한다.

  • 예외 발생 여부: Function code + 0x80 ( MSB ON )
  • 예외 내용: Data 부분에 표현

기능마다 반환할 수 있는 예외 코드가 다르며, 존재하는 예외 코드는 다음과 같다.

예외코드 이름 설명
0x01 Illegal Function 지원하지 않는 Function Code
0x02 Illegal Data Address Data 상 Address가 잘못됨 ( 쓰기 보호 영역 등 )
0x03 Illegal Data Value Data 상 Value가 잘못됨 ( 범위, 형식, 길이 등 )
0x04 Slave Device Failure 슬레이브 기기에 복구할 수 없는 오류가 발생
0x05 Acknoledge 처리 시간이 오래 걸림 = 타임 아웃 방지를 위해 응답
0x06 Slave Device Busy 현재 Slave가 바빠서 처리 못함 = 나중에 다시 요청해야 함
0x07 Nagative Acknoledge 현재 Slave가 요청한 기능을 수행할 수 없는 상황
0x08 Memory Parity Error R/W File Record 에러
0x0A Gateway Path Unavailable 통신 경로 할당할 수 없음. ( 게이트 구성 잘못됨 )
0x0B Gateway Target Device Failed To Respond 게이트웨이의 네트워크 상에 장치가 존재하지 않음

0x0A와 0x0B는 Modbus TCP와 Modbus Serial을 함께 연결할 때 발생하는 문제이다.

Modbus ASCII

프레임 본문을 ASCII 형식으로 표현하는 방식이다. 0-9 , A-F 문자를 이용해서 16진수 문자를 그대로 ASCII로 옮기면 된다. ( Error Check 부분은 LRC => ASCII 2문자로 변경 )

1byte의 글자는 16진수로 0xXX 형식으로 표현된다. RTU => ASCII로 변환할 때는 XX에 해당하는 부분을 ASCII 숫자와 알파벳을 표현하게 된다. 이 과정에서 1byte를 표현하기 위해 2 문자 = 2byte를 사용하게 되므로 디버깅 용도로는 나쁘지 않지만, 실제로 사용하기에는 성능이 좋지 않아 거의 사용되지 않는다.

RTU와는 달리 Start / End가 프레임에 포함되는데, 각각 콜론( : ), 개행 (CR LF)으로 표현된다.

위 요청을 0x01로 보낼 때, ASCII 방식으로 표현하면 : 01 05 00 AC FF 00 4F <CR><LF> 으로 프레임이 총 17 문자 ( = 17 byte) 크기를 가진다. 반면 RTU에서는 프레임의 크기가 8byte가 된다. 따라서, 매우 효율이 나쁘다.

참고로, 4F는 LRC 연산을 통해 구한다.

  1. 0x01 + 0x05 + 0x00 + 0xAC + 0xFF + 0x00 = 0x1B1
  2. 하위 8비트만 선택하면, 0xB1
  3. 2의 보수를 취하면, ~0xB1 + 1 = 0x4F

대부분의 경우 거의 2배가 넘는 패킷 크기를 가지게 된다는 점에서 Modbus RTU가 훨씬 효율적이다.

Modbus TCP

이전에 소개했던 Modbus RTU 및 Modbus ASCII는 시리얼 통신을 기반으로 한다. 이때 두 방식의 경우 결국 회선 등을 통해 마스터와 슬레이브가 직접적으로 연결되어 있어야 한다는 단점을 가지고 있다. 하지만, 경우에 따라 원격 환경에 있는 장치를 제어하고 싶을 수 있다.

Modbus TCP는 TCP / IP 프로토콜, 즉 인터넷 통신을기존 Modbus 프로토콜에 도입한 버전이다. 인터넷의 대역폭과 통신 거리를 사용하기 때문에, 속도가 매우 빠르고 통신 가능 거리도 매우 길다. wifi 등 다양한 통신 방식을 채택할 수 있다는 것도 큰 장점에 해당한다.

Modbus RTU처럼 프레임을 이진 형식으로 표현하며, 프레임의 구조가 변경되었다.

  1. 이더넷 환경에서는 각 장치를 IP 주소를 통해 식별할 수 있다. 따라서 슬레이브를 식별하기 위한 Address가 필요하지 않으므로 제거되었다. 경우에 따라 시리얼 통신 네트워크 내 슬레이브를 식별할 수 있도록 Unit ID를 두고 있다.
  2. TCP는 자체적으로 CRC 체크를 수행할 수 있기 때문에, 체크섬 영역이 필요 없어 제거되었다.  

프레임 규격 

MBAP 헤더와 PDU 부분으로 구분된다. 이때 PDU 부분은 기존 시리얼 통신 방식과 동일하므로, MBAP 헤더만 설명한다.

MBAP Header

MBAP는 Modbus Application Protocol의 약자로, 말 그대로 모드버스 프로토콜임을 의미하는 표현이다. 헤더는 크게 4개 부분으로 나뉜다.

  1. Transaction Identifier: 각 요청을 식별하기 위한 숫자 ( 2byte ) 
  2. Protocol Identifier: 사용되는 프로토콜이 무엇인지 표현하는 부분 ( 2 byte )
  3. Length: UnitID + PDU의 길이 ( 2byte )
  4. Unit ID: 슬레이브 식별자. TCP 통신만 사용하는 경우에는 0xFF로 채운다. ( 1 byte )

Transaction Identifier

각 요청을 식별하기 위한 식별자에 해당하는 부분이다. TCP 도입 이후에는 요청 이후 응답까지 대기하지 않는다. 대신 각 요청에 번호를 붙여 특정 요청 - 응답이 정상적으로 동작했는지 확인할 수 있다.

TCP에서 패킷을 구분하기 위해 사용하는 시퀀스 번호랑 비슷하다고 보면 될 것 같다.

Protocol Identifier

현재 사용되는 프로토콜이 무엇인지 식별하는 부분이다. modbus 프로토콜은 0x00을 사용한다. 현재 시점에는 사용되지 않는 부분으로, 과거에 산업용 프로토콜의 확장을 대비한 의도가 있지 않았나 싶다.

Length

프레임의 UNIT ID + FUNCTION + DATA 영역의 바이트 단위 길이를 나타내는 영역이다. 2byte의 크기를 가지지만 앞의 8bit는 0x00으로 설정되어, 실질적으로는 최대 255의 값을 가질 수 있다고 한다.

Length가 PDU의 길이가 아니라, UNIT ID + PDU라는 것에 주의하자.

Unit ID

TCP / IP가 아닌 다른 경로, 예를 들어 시리얼 통신으로 연결된 장치의 Slave를 구분하기 위해 사용하는 정보. 시리얼 네트워크로 진입하지 않는다면 0xFF로 초기화한다.

Modbus TCP에는 Address 영역이 없다. 그런데, Modbus TCP를 통해 특정 PLC와 Modbus RTU로 연결된 장치에게 명령을 내리고 싶을 수 있다. 이 경우 Unit ID를 해당 장치의 slave 번호로 설정해두면, 외부에서도 쉽게 접근할 수 있다.

이때, 이더넷 통신 프로토콜과 시리얼 통신 프로토콜에 의한 네트워크는 직접적으로 연결될 수 없으므로, 이 둘을 연결하는 일종의 어댑터 장치인 Modbus 게이트웨이가 필요하다. Modbus 게이트웨이는 이더넷을 통해 전송된 TCP 기반 프레임을 시리얼 기반 프레임으로 변환하는 작업을 수행하며 서로 다른 네트워크 간 통신을 돕는다.