본문 바로가기
Computer Science/CS 지식

ModScan과 Python을 이용한 Modbus 통신 (feat. Pymodbus)

by rnasterofmysea 2025. 4. 16.
728x90
반응형

 

ModScan과 Python을 이용한 Modbus 통신 데이터 시뮬레이션

IoT나 산업 자동화 시스템을 개발하다 보면 Modbus 프로토콜을 이용해 데이터를 주고 받는 환경이 자주 등장합니다. 실제 장비가 없거나 테스트 환경 구축이 어려울 때 ModScan이라는 시뮬레이터를 활용하면 매우 유용합니다.

이번 글에서는 ModScan으로 Modbus 데이터를 생성하고, Python 코드로 해당 데이터를 읽어오는 방법을 정리해보겠습니다.

 

Modbus 통신 구조

이번 실습은 Modbus TCP 기반으로 구성하였습니다.

ModScan (Modbus Slave Server 역할)
↓  
Python (Modbus Client 역할)
  • ModScan: 데이터 생성 (서버)
  • Python: 데이터 읽기 (클라이언트)

 

ModScan 설정 방법

2025.03.08 - [Computer Science/CS 지식] - [Modbus] Modscan & Modsim 으로 TCP 통신하기

 

[Modbus] Modscan & Modsim 으로 TCP 통신하기

Modscan과 Modsim은 Modbus 프로토콜을 사용하는 장치와 통신을 테스트하고 시뮬레이션하는 도구입니다. 이들은 산업 자동화, SCADA 시스템, PLC(Programmable Logic Controller) 및 기타 Modbus 기반 장치의 진단과

rnasterofmysea.tistory.com

 

해당 링크에 자세한 내용을 참고해주세요!

 

 

Pymodbus

Python에서는 pymodbus 라이브러리를 이용해 Modbus 프로토콜을 쉽게 처리할 수 있습니다.

 

다운로드~~

pip install pymodbus

 

 

pymodbus 주요 메서드 정리 (TCP, RTU 공통)

 

읽기 메서드 (Read)

메서드  읽는 대상 레지스터 번호   예시
read_coils Coil (디지털 출력) 00001 ~ client.read_coils(address=0, count=5, unit=1)
read_discrete_inputs Discrete Input (디지털 입력) 10001 ~ client.read_discrete_inputs(address=0, count=5, unit=1)
read_holding_registers Holding Register (데이터 저장 공간, 읽기/쓰기 가능) 40001 ~ client.read_holding_registers(address=0, count=5, unit=1)
read_input_registers Input Register (데이터 저장 공간, 읽기 전용) 30001 ~ client.read_input_registers(address=0, count=5, unit=1)

 

이번 포스트에서는 데이터를 파이썬으로 읽어오는 것이기 때문에 Read 메서드를 사용할 예정입니다.

 


쓰기 메서드 (Write)

메서드  대상 레지스터 번호 예시
write_coil Coil (디지털 출력) 00001 ~ client.write_coil(address=0, value=True, unit=1)
write_register Holding Register (단일 값 쓰기) 40001 ~ client.write_register(address=0, value=123, unit=1)
write_registers Holding Register (여러 값 쓰기) 40001 ~ client.write_registers(address=0, values=[10, 20, 30], unit=1)

레지스터 구분 요약

Coil 00001 ~ 디지털 출력 (ON/OFF) read_coils / write_coil
Discrete Input 10001 ~ 디지털 입력 (읽기 전용) read_discrete_inputs
Input Register 30001 ~ 아날로그 입력 데이터 read_input_registers
Holding Register 40001 ~ 읽기/쓰기 가능 데이터 저장소 read_holding_registers / write_register(s)

핵심 파라미터 설명

(pymodbus read_holding_registers 함수 기준)

result = client.read_holding_registers(address=0, count=10, unit=1)

파라미터 설명 예시 비고
address 시작 주소 0 Modbus 레지스터 주소 (0부터 시작)
count 읽을 레지스터 개수 10 몇 개를 읽을지 결정
unit Slave ID 1 ModScan에서 설정한 Slave ID

 

1. address

  • Modbus 레지스터 번호는 보통 이렇게 표기합니다.

Modbus 레지스터 번호 pymodbus address
40001 0
40002 1
40003 2
... ...

→ 즉, ModScan에서 40001 번 레지스터 = pymodbus 에서는 address=0 입니다.

2. count

  • 몇 개의 레지스터 값을 읽을 건지 지정합니다.
count=10
 
  • 의미:
    40001 ~ 40010 까지 10개의 값을 읽겠다는 의미입니다.

 

3. unit

  • Modbus 장비 구분 ID입니다.
unit=1
  • ModScan 실행 시 설정한 Slave ID 값과 일치시켜야 합니다.
  • 예를 들어 ModScan 설정이 이렇게 되어 있다면:→ Python 코드에서도 unit=1 로 설정해야 통신됩니다.

 

파이썬 코드

from pymodbus.client.sync import ModbusTcpClient

MODSCAN_HOST = '192.168.0.100'  # ModScan 실행 PC IP
MODSCAN_PORT = 502              # ModScan Port

client = ModbusTcpClient(MODSCAN_HOST, port=MODSCAN_PORT)

if client.connect():
    print("Modbus TCP 연결 성공")

    # Holding Register 40001번부터 10개 값 읽기
    result = client.read_holding_registers(address=0, count=10, unit=1)

    if result.isError():
        print("데이터 읽기 실패")
    else:
        print("읽은 데이터:", result.registers)

    client.close()
else:
    print("Modbus TCP 연결 실패")

 

Modscan 실행

 

 

Connection - Remote Modbus TCP Server - IP 와 Port 번호 입력

 

 

빨간 박스 부분에서 출력 방식을 결정할수 있습니다.

(Binary, Demical, Integer, Hex 등등)

728x90
반응형