PLC 2일차 : Modbus 기본 개념과 Node-RED Modbus Read로 Coil/레지스터 읽기


PLC 2일차 : Modbus 기본 개념과 Node-RED Modbus Read로 Coil/레지스터 읽기

한눈에 보는 요약

이 글은 PLC를 처음 공부하는 분이 Modbus의 기본 메모리 구조(Coils, Discrete Inputs, Input Registers, Holding Registers)와 Function Code 개념을 이해하고, Node-RED의 Modbus Read 노드로 실제 데이터를 읽어보는 과정을 정리한 실습형 가이드입니다.

각 메모리 영역이 무엇을 의미하는지, 왜 주소 표기(0xxxx, 1xxxx, 3xxxx, 4xxxx)와 Function Code(FC01, FC02, FC03, FC04 등)를 함께 봐야 하는지 개념부터 차근차근 설명합니다.

이후 Modbus 시뮬레이터 또는 실제 PLC를 연결해 Node-RED에서 Coil/레지스터를 각각 읽어보고, 주기(poll rate)와 타임아웃(timeout) 설정을 변경하면서 Debug 로그가 어떻게 달라지는지 예시를 통해 보여드립니다.

마지막에는 설정 시 자주 발생하는 통신 오류 패턴과, 이후 HR(홀딩 레지스터)을 활용해 제어값까지 읽고 쓰기 위한 확장 포인트까지 함께 정리합니다.

목차


핵심 포인트

  • Modbus는 메모리 영역을 네 가지(Coils, Discrete Inputs, Input Registers, Holding Registers)로 나누고, 각 영역에 대해 별도의 Function Code로 읽기/쓰기를 수행합니다.
  • Coil(0x)과 Holding Register(4x)는 보통 PLC가 “내가 제어하는 값”을 담는 공간이고, Discrete Input(1x)과 Input Register(3x)는 “외부 센서 등에서 읽기 전용 값”을 담는 공간으로 이해하시면 편합니다.
  • Node-RED의 Modbus Read 노드는 서버 정보(아이피/포트/유닛 ID), Function Code, 시작 주소, 개수, 폴링 주기, 타임아웃을 중심으로 설정합니다.
  • 읽기 주기(poll rate)를 너무 짧게 설정하면 통신 부하와 타임아웃이 증가하고, 너무 길게 설정하면 화면 갱신이 느려집니다. 장치 성능과 네트워크 상태에 맞는 적절한 값이 중요합니다.
  • Debug 노드를 연결하면 msg.payload에 배열 형태로 Modbus 읽기 결과가 들어오며, 주소 매핑이 올바른지 즉시 확인할 수 있습니다.
  • 시뮬레이터에서 코일/레지스터 값을 바꿔 보면서 Node-RED Debug 로그가 실시간으로 변하는 모습을 보는 것이 개념 이해에 가장 빠른 학습 방법입니다.

상세 설명

1. Modbus 메모리 구조와 Function Code 개념 정리

Modbus는 매우 오래된 통신 프로토콜이지만, 지금도 PLC·인버터·온도 컨트롤러 등 산업 장비에서 표준처럼 사용되고 있습니다. Modbus를 이해할 때 가장 먼저 잡고 가야 하는 것은 “장비 안의 메모리를 논리적으로 네 구역으로 나누어 관리한다”는 개념입니다.

이 네 구역이 바로 Coil, Discrete Input(DI), Input Register(IR), Holding Register(HR)입니다. 각각은 쓰기 가능 여부(Write 가능/불가)와 데이터 타입(단순 ON/OFF인지, 16비트 숫자인지)에 따라 구분됩니다. Modbus에서 실제로 장비에 요청을 보낼 때는 Function Code(FC01, FC03 등)를 사용해 “어느 영역을, 어떻게 읽거나 쓸지”를 지정합니다.

예를 들어 FC01(Read Coils)은 Coil 영역을, FC03(Read Holding Registers)은 Holding Register 영역을 대상으로 합니다. 즉, 주소 숫자만으로는 어떤 영역을 읽는지 알 수 없고, 반드시 영역 타입(0x, 1x, 3x, 4x)과 Function Code를 함께 봐야 정확한 통신이 이루어집니다.

2. Coil/DI/IR/HR 주소 체계와 쓰임새 비교

처음 Modbus를 접하면 “왜 어떤 매뉴얼은 00001, 10001, 30001, 40001처럼 다르게 적혀 있지?”라는 궁금증이 생깁니다. 아래 표는 네 가지 메모리 영역을 한 번에 비교한 것입니다.

Modbus 메모리 영역 비교 표

주요 메모리 영역별 특징과 대표 Function Code를 정리했습니다.

영역 이름 주소 범위 관례 데이터 타입 읽기/쓰기 대표 Function Code 주요 용도
Coils 0xxxx (예: 00001) 1비트 (ON/OFF) Read / Write FC01(Read Coils), FC05/15(Write) 모터 스타트, 램프 ON/OFF 등 제어 출력
Discrete Inputs (DI) 1xxxx (예: 10001) 1비트 (ON/OFF) Read only FC02(Read Discrete Inputs) 센서 접점, 스위치 상태 등 입력 신호
Input Registers (IR) 3xxxx (예: 30001) 16비트 정수 Read only FC04(Read Input Registers) 온도/압력/속도 등 아날로그 입력 값
Holding Registers (HR) 4xxxx (예: 40001) 16비트 정수 (또는 2개 묶어 32비트) Read / Write FC03(Read), FC06/16(Write) 설정값(설정 온도, 속도), 누적 카운터 등

시뮬레이터나 PLC 매뉴얼에서 “40001: 설정 온도”, “00001: 펌프 운전 명령”처럼 표를 제공하는데, 여기서 첫 자리 숫자(0,1,3,4)가 영역을 의미한다고 이해하시면 됩니다. Node-RED에서는 보통 “실제 주소 인덱스(0부터 시작)”로 입력해야 하므로, 40001이면 시작 주소를 0으로, 40010이면 9로 입력하는 방식에 주의해야 합니다.

3. Node-RED에서 Modbus Read 노드 구조 이해

Node-RED를 실행한 첫 화면입니다. (localhost:1880)

대시보드 우측 상단의 메뉴를 클릭하고, Manage palette를 선택하면 아래와 같이 User Settings 창에서 Install 탭을 선택하여 아래와 같이 모듈을 찾아서 설치하면 됩니다.


필수설치 : node-red-contrib-modbus | node-red-contrib-modbustcp

Node-RED에서는 일반적으로 node-red-contrib-modbus와 같은 패키지를 설치해 Modbus를 사용합니다. 이 패키지에는 Modbus Read 노드와 Modbus Server, Modbus Flex Getter 등 여러 노드가 포함되는데, 오늘은 가장 기본적인 Modbus Read 노드에 집중합니다.



Modbus Read 노드를 더블클릭하면 다음과 같은 주요 항목을 확인할 수 있습니다.

  • Server: 접속할 Modbus TCP 서버 정보(아이피, 포트, 유닛 ID)
  • FC: 사용할 Function Code (예: FC01, FC02, FC03, FC04)
  • Address: 시작 주소(대부분 0부터 시작하는 오프셋)
  • Quantity: 한 번에 읽을 개수(코일/레지스터 개수)
  • Poll Rate: 주기적으로 읽을 간격(ms 단위)
  • Timeout: 응답을 기다리는 최대 시간(ms 단위)

Modbus Read 노드는 설정된 Poll Rate마다 장비에 요청을 보내고, 성공하면 msg.payload에 결과 배열을 담아 다음 노드로 전달합니다. 우리가 해야 할 일은 이 노드를 Debug 노드 또는 대시보드 위젯과 연결해 실제로 어떤 데이터가 들어오는지만 확인하면 됩니다.

4. Coil/레지스터 각각 읽어보기 및 Debug 로그 예시

이제부터는 실제로 시뮬레이터 또는 PLC에 접속해 각 메모리 영역을 하나씩 읽어보는 순서를 정리해 보겠습니다. 예시는 Modbus TCP 서버(예: 192.168.0.10, Port 502)에 다음과 같은 태그가 있다고 가정합니다.

  • Coil 00001: 모터 운전 명령 (ON/OFF)
  • DI 10001: 비상정지 스위치 상태
  • IR 30001: 현재 온도 (단위 0.1℃)
  • HR 40001: 설정 온도 (단위 0.1℃)

Node-RED 플로우는 최소한 다음 세 노드로 구성합니다.

  • Inject(수동 트리거 또는 주기 수행)
  • Modbus Read (각 영역별로 하나씩 준비)
  • Debug(msg.payload 출력 확인)

Node-RED Debug 로그 예시

[
  {
    "_msgid": "a1b2c3d4e5f6",
    "topic": "modbus-read-coil-00001",
    "payload": [ true ],
    "modbusResponse": {
      "fc": 1,
      "unitId": 1,
      "byteCount": 1,
      "payload": [ true ]
    }
  },
  {
    "_msgid": "b2c3d4e5f6a1",
    "topic": "modbus-read-hr-40001",
    "payload": [ 235 ],
    "modbusResponse": {
      "fc": 3,
      "unitId": 1,
      "byteCount": 2,
      "payload": [ 235 ]
    }
  }
]

위 Debug 로그는 Coil 00001을 FC01으로 읽었을 때 true(ON) 값이 들어오고, Holding Register 40001을 FC03으로 읽었을 때 235라는 값(예: 23.5℃)이 들어오는 예시입니다. 실제 Node-RED 화면에서는 각 메시지가 개별적으로 출력되지만, 이해를 돕기 위해 배열 형태로 묶어 표현했습니다.

로그에서 꼭 확인해야 할 필드는 topicpayload, 그리고 modbusResponse.fc입니다. FC가 기대한 값(1, 2, 3, 4 등)과 일치하는지, payload 배열 길이가 Quantity와 맞는지를 보면 설정이 제대로 되었는지 빠르게 검증할 수 있습니다.


실행 단계

  1. Modbus 시뮬레이터 또는 PLC 준비
    PC에서 실행 가능한 Modbus TCP 시뮬레이터를 설치하거나, 실제 PLC를 Modbus TCP 서버로 설정합니다. 이때 최소한 Coil 1개, DI 1개, IR 1개, HR 1개 정도는 매뉴얼을 보고 주소와 초기값을 확인해 둡니다.
  2. Node-RED에 Modbus 패키지 설치
    Node-RED 메뉴에서 팔레트 관리를 열고 node-red-contrib-modbus와 같은 패키지를 검색해 설치합니다. 설치 후 좌측 노드 목록에 Modbus 관련 노드들이 나타나는지 확인합니다.
  3. Modbus 서버 설정 노드 생성
    Modbus Read 노드를 플로우에 드래그한 뒤 더블클릭하여 Server 항목을 추가합니다. 서버 아이피, 포트(기본 502), Unit-ID(보통 슬레이브 ID)를 입력하고, TCP 연결인지 시리얼(RTU)인지 등 통신 타입을 장비와 일치시킵니다.
  4. Coil 읽기용 Modbus Read 노드 설정
    첫 번째 Modbus Read 노드의 FC를 1(Read Coils)로 선택하고, Address를 0(=00001), Quantity를 1로 설정합니다. Poll Rate는 예를 들어 1000ms 정도로 설정해 1초마다 값을 읽도록 하고, Timeout은 2000~3000ms 사이로 여유 있게 잡습니다.
  5. DI, IR, HR용 노드 복사 및 주소 변경
    Coil 노드를 복사해 DI용은 FC02, 시작 주소 0(=10001), IR용은 FC04, HR용은 FC03으로 변경합니다. 각 노드에 topic을 다르게 부여하면 Debug 창에서 어떤 데이터인지 구분하기 쉽습니다.
  6. Debug 노드 연결 및 플로우 배포
    각 Modbus Read 노드의 출력에 Debug 노드를 연결합니다. 또는 Function 노드를 하나 둔 뒤 Debug로 보내도 좋습니다. 상단 Deploy 버튼을 눌러 플로우를 배포하면 주기적으로 Modbus 요청이 나가기 시작합니다.
  7. 시뮬레이터 값 변경과 Debug 로그 관찰
    시뮬레이터에서 Coil ON/OFF, HR 값 변경 등을 수행하면서 Node-RED Debug 패널에서 msg.payload 값이 실시간으로 바뀌는지 확인합니다. 값이 변하지 않거나 타임아웃 에러가 반복되면 IP, Unit-ID, 주소 오프셋 설정을 다시 점검합니다.
  8. 폴링 주기와 타임아웃 튜닝
    Poll Rate를 200ms, 500ms, 1000ms 등으로 변경해 보면서 Debug 로그의 빈도와 장비 부하를 비교해 봅니다. 응답이 느린 장비라면 Poll Rate를 길게, Timeout은 넉넉하게 설정하는 것이 안정적입니다. 실제 설비에서는 장비 매뉴얼의 권장 주기를 따르는 것이 좋습니다.

통신 안정화를 위한 팁과 주의사항

Modbus와 Node-RED로 간단한 모니터링을 구현할 때 자주 겪는 문제와 해결 팁을 정리하면 다음과 같습니다.

  • 주소 오프셋 혼동: 매뉴얼에 40001로 나와 있어도 Node-RED에서는 Address 0으로 입력해야 하는 경우가 많습니다. 일부 장비는 1 기반 주소를 그대로 쓰기도 하므로, 값이 계속 이상하면 Address를 0/1로 바꿔 테스트해 보는 것이 좋습니다.
  • Unit-ID 미설정: TCP 한 대에 슬레이브 여러 개를 붙이는 경우 Unit-ID가 달라집니다. 시뮬레이터에서 Unit-ID가 1인지, 2인지 반드시 확인하고 Node-RED 설정과 일치시키십시오.
  • 폴링 과도 설정: Poll Rate를 수십 ms 단위로 무리하게 낮추면 장비가 응답하지 못하거나 네트워크가 불안정해질 수 있습니다. 모니터링 목적이라면 500~1000ms 정도만으로도 충분한 경우가 많습니다.
  • 에러 로그 활용: node-red-contrib-modbus는 연결 실패, 타임아웃 등 에러 정보를 별도의 Debug 메시지로 제공합니다. 에러 내용까지 함께 Debug 창으로 보내 두면 원인분석에 큰 도움이 됩니다.

추가로 생각해볼 점

  • 이번 글에서는 읽기(Read)에 초점을 맞췄지만, 다음 단계에서는 Holding Register와 Coils에 값을 쓰는 Write 기능(FC05/06/15/16)을 실습해 보면 실제 제어 로직과 더 잘 연결할 수 있습니다.
  • 여러 장비에서 데이터를 수집할 계획이라면, Node-RED 위에 InfluxDB·Grafana 같은 시각화/저장 솔루션을 함께 구성해 “소형 SCADA” 형태로 확장하는 것도 좋은 연습 과제입니다.
  • 보안이 중요한 설비 환경에서는 단순 Modbus TCP 대신 VPN, 방화벽, 네트워크 분리 등을 함께 고려하여 통신 경로를 설계해야 합니다.

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

Reactions

댓글 쓰기

0 댓글