지난 글에서는 Modbus란 무엇인가에 대해 간단히 알아봤다. 이번 글에서는 Modbus의 상세한 명세에 대해서 설명하고자 한다.
통신 과정
Modbus의 통신은 요청-응답 형식으로 이루어진다.
요청 처리
요청은 다음과 같은 과정을 거쳐 처리된다.
정상
통신이 원활하게 이루어지고 요청을 처리하는 데에 이상이 없으면 요청과 같은 function code와 응답 데이터를 반환한다.
오류
Modbus의 오류 상황은 크게 통신 오류와 요청 처리 오류로 분류할 수 있다. 통신 오류의 경우 통신 계층에서 처리하며, 이 경우 Modbus에서는 응답을 보내지 않으며 클라이언트에서는 타임아웃을 통해 통신에 오류가 발생했음을 감지할 수 있다.
반면 요청 처리에 이상이 있다면 function code의 최상위 비트를 1로 바꾸고 예외 코드와 함께 반환한다.
에러 코드는 다음과 같다.
- 1(ILLEGAL FUNCTION): 주어진 function code를 처리할 수 없다는 뜻이다.
- 2(ILLEGAL DATA ADDRESS): modbus 데이터 주소의 범위 밖이라는 뜻이다. 즉 out of range 에러이다.
- 3(ILLEGAL DATA VALUE): 요청의 데이터 부분이 modbus 요청 형식에 맞지 않다는 뜻이다.
- 4(SERVER DEVICE FAILURE): 장치에서 요청을 처리하는 중 심각한 문제가 발생했다는 뜻이다.
- 5(ACKNOWLEDGE): 요청을 처리하는 데에 많은 시간이 걸린다는 뜻이다. 이 코드는 의미적으로는 정상 상황으로, timeout에 걸려 실패 처리가 되지 않게 하기 위해 반환하는 코드이다.
- 6(SERVER DEVICE BUSY): 현재 프로세스를 처리할 수 없다는 코드로 잠시 후에 다시 시도하라는 뜻이다.
- 8(MEMORY PARITY ERROR): 파일 레코드 입출력 한정 에러 코드로 파일의 무결성에 문제가 생겼다는 뜻이다.
- 0A(GATEWAY PATH UNAVAILABLE): 장치와 연결된 게이트웨이가 잘못 설정되었거나 과부하 상태라는 뜻이다. 해당 코드와 아래 코드는 장치에서 직접 보내는 것은 아니고 중간 게이트웨이에서 보낸다.
- 0B(GATEWAY TARGET DEVICE FAILED TO RESPOND): 장치가 연결되지 않았다는 뜻이다.
패킷
Modbus에서 사용하는 패킷인 ADU, PDU의 의미와 기본적인 구조는 기본편에서 설명했으므로 이번에는 패킷의 기술적인 명세에 대해서 설명하겠다.
크기
Modbus는 근본적으로 시리얼 통신에 기반하고 있기 때문에 시리얼 통신 패킷의 최대 크기인 256byte를 기준으로 삼는다. 즉, 시리얼 기반 ADU의 최대 크기는 256byte이다.
역산해서 PDU의 최대 크기를 구할 수 있다.
PDU = (256(시리얼 기반 ADU) - 1(시리얼 주소) - 2(오류 검출 코드))byte = 253byte
재밌게도, TCP 패킷의 최대 크기는 1500byte이지만 호환성을 위해 PDU의 최대 크기는 시리얼과 같은 253byte로 제한된다. 다만 ADU에 들어가는 주소 정보가 시리얼 패킷과 다르기 때문에 따로 계산해야 한다.
ADU(TCP) = (253(PDU) + 7(MBAP 헤더))byte = 260byte
즉, PDU의 최대 크기는 253byte, 시리얼 기반 ADU의 최대 크기는 256byte, TCP 기반 ADU의 최대 크기는 260byte이다.
인코딩
Modbus는 빅 엔디안 방식으로 데이터를 인코딩한다. 빅 엔디안 방식은 높은 비트에서 낮은 비트 순서로 저장하는 방식으로, 이렇게 저장된 데이터는 사람이 읽는 순서와 같아 사람이 이해하기 쉽다(human-readable). 즉, 데이터의 계산에 효율적인 리틀 엔디안 방식 보다 데이터 그 자체에 의미가 있을 때 유용한 방식으로 Modbus의 용도에는 리틀 엔디안 방식보다 더욱 적합하다.
Function Code 커스터마이징
Function code는 크게 공식적으로 사용되는 PUBLIC Function code와 사용자가 임의로 사용할 수 있는 User Defined Function code로 이루어져 있다.
User Defined Function Code로 사용할 수 있는 주소는 65~72, 100~110이다. 보다시피 주소가 파편화되어 있는데 이는 Modbus의 명세가 확립되기 전부터 사용했던 장치와의 호환성을 지켜야했기 때문이다.
마치며
이번 글의 경우는 사실 Modbus를 사용하는 데에 있어서는 그렇게 중요하지 않을 수 있다. 다만 Modbus의 데이터가 어떤 식으로 구현이 되어있으며 왜 이렇게 설계되었는가에 관한 호기심을 충족시키기에는 어느 정도 도움이 되었기를 바란다.