Modbus TCP

TCP/IP 위의 Modbus 레지스터와 코일이며, 형식 있는 주소 지정과 바이트 순서 조절과 한도가 정해진 네트워크 스캔을 갖추고 있습니다.

Markdown으로 보기

Modbus TCP 드라이버는 TCP/IP 위로 Modbus 레지스터와 코일을 읽고 씁니다. PLC, 계측기, 게이트웨이, 그리고 Modbus/TCP를 말하는 모든 서버가 상대입니다. 주소 지정은 완전히 형식이 있습니다. 레지스터 종류와 0부터 세는 레지스터 번호를 고르면 애플리케이션이 버스 요청을 조립합니다. 잘못 적을 자유 입력 주소가 없습니다.

장치

칸 뜻 기본값
호스트 Modbus 서버나 게이트웨이의 DNS 이름, IPv4 주소, IPv6 주소. 비어 있음: 입력할 때까지 장치가 연결되지 않습니다
포트 TCP 포트이며 1에서 65535까지입니다. 칸이 비어 있으면 502가 회색으로 보이고 장치는 그 포트로 호출됩니다. 0으로 저장된 장치도 똑같이 보입니다. 502
유닛 ID 요청마다 실려 가는 Modbus 슬레이브 id이며, 게이트웨이가 그 뒤에 있는 장치로 보낼 때 쓰는 값입니다. 0에서 255까지. 1
프레임 형식 요청이 연결을 어떤 형태로 오가는지 정합니다. MBAP는 요청마다 Modbus TCP 헤더를 붙이고, RTU는 CRC가 붙은 RTU 프레임을 그대로 보내며 투명 모드의 시리얼-이더넷 변환기에 씁니다(TCP 위의 RTU 참고). 호스트, 포트, 슬레이브 ID, 태그는 어느 쪽이든 같습니다. MBAP
최소 트랜잭션 간격 (ms) 호환을 돕는 속도 맞춤입니다. 트랜잭션 하나가 끝난 뒤 다음이 시작될 때까지의 최소 침묵이며 0에서 1000까지입니다. 0은 인위적인 지연을 두지 않습니다. 0
읽기 주기 (ms) 스스로 값을 정하지 않은 태그의 기본 읽기 주기. 1000

패널 머리글에 나오는 기본 URI는 modbus+tcp://host:port/unitID이며, 간격을 정했으면 ?minimumTransactionIntervalMs=n이 붙습니다.

호스트와 포트를 함께 쓰는 장치들은 트랜잭션 관문도 함께 씁니다. 같은 endpoint로 가는 요청은 결코 겹치지 않으며, 그 endpoint에 있는 켜진 장치 가운데 가장 큰 최소 트랜잭션 간격이 그 모두의 속도를 정합니다. 다른 장치가 여기에 설정한 값보다 실제 적용되는 간격을 올릴 때는 패널이 그렇게 말합니다. 이 간격은 이 애플리케이션이 내보내는 통신만 다스립니다. 느린 서버나 게이트웨이를 위한 호환 수단이지 네트워크 고장을 고치는 수단이 아닙니다.

접속은 최대 5초를 기다리고, 응답은 최대 10초를 기다리며, 프로토콜 단계의 재시도는 없습니다. 배경의 재시도 고리가 다시 연결하는 일을 맡으므로, 꺼져 있는 장치는 품질이 나쁜 읽기 말고는 아무 비용도 들이지 않습니다.

TCP 위의 RTU

투명 모드의 시리얼-이더넷 변환기는 스스로 Modbus TCP를 말하지 않습니다. 소켓으로 들어온 것을 그대로 시리얼 버스에 내보내고, 버스가 답한 것을 돌려보낼 뿐입니다. 그 뒤에 있는 장치는 프레임 형식을 RTU로 둔 Modbus TCP 장치입니다. 스테이션은 MBAP 헤더 없이 RTU 프레임(슬레이브 ID, 요청, CRC)을 보내고, CRC가 맞는 응답만 받아들입니다. 이때 기본 URI의 쿼리에는 framing=rtu가 붙습니다. 예를 들면 modbus+tcp://192.168.0.20:502/1?framing=rtu입니다. MBAP 장치는 늘 쓰던 주소를 그대로 씁니다. 이 페이지의 나머지 내용은 그대로 적용됩니다. 레지스터 종류, 기능 코드, 쓰기 대기열, 시간 초과, 트랜잭션 간격이 모두 같습니다.

  • 유닛 ID는 변환기 뒤 시리얼 버스에서 장치가 쓰는 주소이며 1부터 247까지입니다.
  • 한 변환기 뒤의 장치들은 그 호스트와 포트를 함께 쓰고, 그에 따라 트랜잭션 관문도 함께 씁니다. 한 번에 요청 하나이며, 이것은 시리얼 버스가 나를 수 있는 전부이기도 합니다. 변환기가 프레임 사이에 쉼이 필요하면 최소 트랜잭션 간격 (ms)을 늘리십시오.
  • 변환기 자체의 시리얼 설정(보 레이트, 형식)은 변환기에서 정합니다. 스테이션은 그 값을 보지 못합니다.
  • RTU 프레임에는 트랜잭션 번호가 없으므로, 스테이션은 요청할 때마다 변환기가 이미 보낸 것을 버립니다. 요청이 시간 초과된 뒤에 도착한 응답이 다음 요청의 응답으로 잘못 읽히는 일은 없습니다.

태그 주소 지정

칸 뜻 기본값
레지스터 종류 태그가 가리키는 Modbus 개체입니다. 코일 (0xxxx), 디스크리트 입력 (1xxxx), 입력 레지스터 (3xxxx), 홀딩 레지스터 (4xxxx) 가운데 하나입니다. 모두 매뉴얼의 주소가 그 종류에 붙이는 첫 숫자를 함께 적으므로, 30001만 인쇄한 매뉴얼은 입력 레지스터를 가리킵니다. 형식과 접근에서 이끌어 냅니다. 부울 태그는 디스크리트 입력(읽기 전용)이나 코일(쓰기 가능)을, 그 밖의 모든 형식은 입력 레지스터(읽기 전용)나 홀딩 레지스터(쓰기 가능)를 받습니다.
레지스터 번호 (0부터) 프로토콜의 원래 주소입니다. 이것은 매뉴얼의 표기가 아니라 버스 위의 0부터 세는 주소입니다. 홀딩 레지스터 40001은 레지스터 번호 0입니다. 여기에 30001을 입력해도 종류는 골라지지 않습니다. 실제로 30000이 넘는 레지스터를 가진 장치가 있기 때문이며, 종류는 위에서 고릅니다. 레지스터는 16비트 수로 버스를 지나가므로, 이 칸은 0에서 65535까지를 받고 그보다 넓은 값은 입력하는 자리에서 거부합니다. 0
개수 (레지스터, 비우면 자동) 값이 차지하는 16비트 레지스터의 수입니다. 이 상자는 문자열 태그에만 그려집니다. 그 밖의 모든 형식은 너비가 고정되어 있어 정해 줄 것이 없기 때문입니다. 형식별로 부울과 Int16과 UInt16 1, Int32와 Float 2, 문자열 4
최상위 바이트 먼저 (MSB first, 빅 엔디언) 각 16비트 레지스터에서 어느 바이트가 버스에 먼저 나가는지. 괄호 안은 매뉴얼이 이 설정에 쓰는 말입니다. 숫자 태그와, 홀딩 레지스터나 입력 레지스터에 둔 부울 태그에 있습니다. 코일이나 디스크리트 입력의 부울은 비트 하나뿐이라 순서를 정할 바이트가 없으므로 거기에는 그려지지 않습니다. 켜짐(Modbus 규격이 요구하는 것)
최상위 워드 먼저 (상위 워드 먼저) 두 레지스터로 이루어진 값에서 어느 레지스터가 위쪽 절반을 담는지. Int32와 Float 태그에만 있습니다. 레지스터 하나로 된 값(Boolean, Int16, UInt16)에는 두 번째 레지스터가 없으므로 거기서는 이 상자가 그려지지 않습니다. 두 상자 아래의 값의 바이트 순서가 두 상자가 만드는 배치를 매뉴얼의 글자로 보여 줍니다(바이트와 워드 순서). 켜짐

신호원 카드는 매뉴얼상의 주소로 끝납니다. 장치 매뉴얼이 인쇄하는 표기로 태그가 어디에 있는지 보여 주며, 종류의 첫 숫자 뒤에 1부터 센 레지스터를 붙입니다. 입력 레지스터 0은 30001, 홀딩 레지스터 100의 Float는 40101에서 40102까지이고, 9998을 넘는 레지스터는 여섯 자리가 됩니다(홀딩 레지스터 9999는 410000). 그래서 패널을 매뉴얼과 한 줄씩 맞춰 볼 수 있습니다.

값 형식과 개수

값 형식은 여섯이 제시되고, 각각의 프로토콜 너비는 고정되어 있습니다.

데이터 형식 레지스터 버스 위의 모습
Boolean 1 레지스터 종류 위에서는 0이 아닌 레지스터가 모두 true로 읽히고, 쓰기는 1이나 0을 보냅니다. Coil과 DiscreteInput 위에서는 그 비트 자체입니다.
Int16 1 레지스터 하나에 담긴 16비트 부호 있는 정수, -32768부터 32767까지.
UInt16 1 레지스터 하나에 담긴 16비트 부호 없는 정수, 0부터 65535까지. 같은 레지스터가 UInt16으로는 65535, Int16으로는 -1로 읽힙니다. 부호는 레지스터가 아니라 고른 데이터 형식이 정합니다.
Int32 2 레지스터 두 개에 걸친 32비트 부호 있는 정수.
Float 2 레지스터 두 개에 걸친 IEEE 754 단정밀도.
String 1개 이상(기본 4) 레지스터마다 두 바이트씩 담는 UTF-8 바이트입니다. 읽기는 첫 NUL 바이트에서 멈추고, 쓰기는 선언한 개수(레지스터당 2바이트) 안에 들어가야 하며 0으로 채워집니다.

문자열 태그는 장치가 바이트를 담고 있는 순서 그대로 읽고 쓰며, 쓰기는 언제나 UTF-8로 보냅니다. 올바른 UTF-8이 아닌 바이트는 장치가 한 번도 초기화하지 않은 범위나 다른 인코딩으로 적힌 글자가 그렇게 보이는 것인데, 실패하는 대신 유니코드 대체 문자로 읽힙니다. 태그는 눈에 띄게 잘못된 것을 보여 주고, 그 장치의 다른 태그는 모두 계속 읽힙니다.

개수 (레지스터, 비우면 자동)은 문자열 태그에만 묻습니다. 부울과 Int16과 UInt16과 Int32와 Float의 너비는 고정되어 있으므로 그 지점에서는 태그 패널에도 태그 표에도 이 상자가 그려지지 않습니다. 이 값을 정해 주는 일은 문자열 태그의 크기를 잡기 위해 있습니다.

바이트와 워드 순서

바이트 순서 상자는 숫자 태그와 레지스터에 둔 부울 태그에 그려지고, 워드 순서 상자는 레지스터 두 개짜리 태그(Int32, Float)에만 그려집니다. 서로 독립된 물음입니다. 레지스터 안에서 어느 바이트가 앞서는지, 그리고 한 쌍에서 어느 레지스터가 앞서는지입니다. Modbus는 글자에 대해서는 둘 다 정하지 않으므로 문자열 태그에는 이 상자가 제시되지 않습니다. 그 바이트는 장치가 담고 있는 순서 그대로 지나갑니다. 값 0x01020304에서 A를 최상위 바이트라고 하면 네 가지 배치는 이렇습니다.

최상위 바이트 먼저 최상위 워드 먼저 버스 위의 바이트
켜짐 켜짐 AB CD(규격의 기본값)
켜짐 꺼짐 CD AB(고전적인 워드 뒤바꿈)
꺼짐 켜짐 BA DC
꺼짐 꺼짐 DC BA

읽기와 쓰기는 같은 두 답을 같은 순서로 적용하므로, 쓰기는 읽기가 되가져왔을 바로 그 바이트를 그대로 놓습니다. 상자 아래의 값의 바이트 순서는 그 배치를 매뉴얼처럼 한 단어(ABCD, CDAB, BADC, DCBA)로 말합니다.

Int16이나 UInt16 값은 레지스터 하나이므로 바이트 순서만 적용됩니다. 0x1234라면 최상위 바이트 먼저를 켜면 12 34, 끄면 34 12가 나갑니다. 배치할 두 번째 레지스터가 없으므로 워드 순서 상자는 그려지지 않습니다.

기능 코드

레지스터 종류 읽기 쓰기
홀딩 레지스터 (4xxxx) 3 (Read Holding Registers) 6 (레지스터 하나) 또는 16 (레지스터 여럿)
입력 레지스터 (3xxxx) 4 (Read Input Registers) 읽기 전용이며 쓰기는 거부됩니다
코일 (0xxxx) 1 (Read Coils) 5 (Force Single Coil, 코일 하나)
디스크리트 입력 (1xxxx) 2 (Read Discrete Inputs) 읽기 전용이며 쓰기는 거부됩니다

쓰기는 서버의 프로토콜 응답이 받아들였다고 확인했을 때에만 성공을 돌려줍니다. 캐시된 값도 그때에만 앞으로 나아갑니다.

장치 검색

스캔은 명시적이고 한도가 정해져 있습니다. 애플리케이션은 결코 로컬 서브넷을 추측하거나 훑지 않습니다. 범위 양식이 받는 것은 이렇습니다.

칸 뜻 기본값
IPv4 호스트 또는 CIDR 주소 하나(192.168.1.10), 또는 /24보다 넓지 않은 서브넷(192.168.1.0/24)입니다. 네트워크 주소와 브로드캐스트 주소는 건너뜁니다. 필수
포트 탐색할 포트. 502
슬레이브 ID 값, 쉼표로 구분한 목록, 또는 오름차순 범위입니다. 1, 1,5,9, 1, 3, 8-16(0에서 255까지). 1
프레임 형식 탐색마다 보내는 프레임입니다. 투명 모드의 변환기는 RTU 프레임에만 응답하므로 RTU로 스캔하십시오. MBAP
최소 트랜잭션 간격 (ms) 같은 호스트에서 끝난 탐색 사이의 속도 맞춤이며 0에서 1000까지입니다. 0

스캔은 고른 프레임 형식으로 모든 탐색을 보냅니다. RTU에서는 탐색마다 RTU 프레임만 보내고, 슬레이브 ID가 일치하고 CRC가 맞는 응답만 셉니다. 그래서 투명 모드 변환기 뒤의 슬레이브도 다른 장치처럼 찾아집니다. 찾은 슬레이브는 추가할 때 스캔의 프레임 형식을 그대로 이어받습니다.

한 번의 스캔은 탐색 256회(호스트 × 슬레이브 ID)까지 보낼 수 있습니다. 그보다 큰 계획은 소켓을 열기 전에 거부됩니다. 보내는 요청은 Read Basic Device Identification(기능 43/14) 하나뿐입니다. 장치 검색은 결코 레지스터를 읽지 않고 레지스터 지도를 추측하지도 않습니다. 형식이 완전히 맞는 Modbus 예외 응답은 신원을 주장하지 않고도 그 슬레이브가 있다는 것을 증명합니다. TCP로 닿는다는 사실과 시간 초과와 깨진 프레임은 증명하지 못합니다. 최대 네 호스트를 나란히 스캔하고 호스트 안에서는 차례로 스캔하며, 접속과 탐색의 시간 초과는 750 ms입니다.

결과는 완전한 endpoint를 담고 있으며, 장치가 제조사와 제품 코드를 알려 주면 그것으로 지은 이름을 제안합니다. 후보의 태그는 0개입니다. 레지스터는 추가한 뒤에 설정합니다. 이미 설정된 슬레이브에는 그렇다는 표시가 붙고, 중복을 만드는 대신 열기를 내놓습니다.

알아 둘 만한 한계

  • 다른 너비의 정수 형식(SByte, Byte, UInt32, Int64, UInt64)과 Double은 제시되지 않습니다. 버스 코덱이 정확히 왕복하는 것은 위의 여섯 형식입니다.
  • endpoint마다 한 번에 요청 하나만 나가 있습니다. 게이트웨이 하나 뒤에 있는 여러 장치는 그 직렬화를 설계대로 함께 씁니다.
  • 쓰기는 한 번에 코일 하나나 레지스터 한 묶음을 다룹니다. 코일 여러 개를 한 번에 쓰는 일은 없습니다.