안녕하세요.
산업 현장이나 자동화 시스템에서 사용하는 통신 방식 중 하나인 RS485에 대해 알아보려고 합니다.
1. RS485란?
RS485(Recommended Standard 485)는 직렬 통신(Serial Communication)을 위한 표준 중 하나입니다. 직렬 통신이란 데이터를 한 번에 한 비트씩 순서대로 주고받는 방식을 말합니다.
RS485는 여러 장치 간(Multi-Point)에 상대적으로 먼 거리에서도 안정적으로 데이터를 주고받을 수 있도록 설계된 점이 특징입니다.
가장 큰 핵심 하나는 차동 신호(Differential Signaling) 방식을 사용한다는 것입니다. 이는 두 개의 전선(보통 A와 B로 표시)에 서로 반대되는 전압 신호를 보내고, 수신 측에서는 이 두 신호의 전압 차이를 감지하여 데이터를 해석하는 방식입니다. 덕분에 외부에서 유입되는 노이즈(잡음)에 매우 강하고, 더 먼 거리까지 신호를 왜곡 없이 전달할 수 있습니다.
차동 신호라는 것은 알겠는데, 그렇다면 0, 1 어떻게 보내는 거야 생각이 들어서 조금 더 찾아보았습니다.
(1) 데이터 '1'을 보낼 때 (예시):
A 라인에는 높은 전압 (예: +2.5V)
B 라인에는 낮은 전압 (예: -2.5V 또는 0V에 가까운 다른 값)
이때 수신 측에서는 A와 B의 전압 차이 (VA - VB)를 감지합니다.
이 경우, (+2.5V) - (-2.5V)=+5V (또는 다른 양의 값)와 같이 특정 양의 전압 차이를 감지하여 이것을 '1'로 인식합니다.
(2) 데이터 '0'을 보낼 때 (예시):
A 라인에는 낮은 전압 (예: -2.5V)
B 라인에는 높은 전압 (예: +2.5V)
이때 수신 측에서는 A와 B의 전압 차이 (VA - VB)를 감지합니다.
이 경우, (-2.5V) - (+2.5V)=-5V (또는 다른 음의 값)와 같이 특정 음의 전압 차이를 감지하여 이것을 '0'으로 인식합니다. (또는 반대로 A가 B보다 낮은 특정 범위의 차이)
RS485의 또 다른 중요한 특징은 멀티드롭(Multi-drop)을 지원한다는 것입니다.
하나의 버스 라인에 여러 장치(마스터 1개, 슬레이브 여러 개 또는 여러 개의 마스터)를 연결할 수 있습니다. (일반적으로 최대 32개의 표준 부하 장치 연결 가능, 리피터 사용 시 더 많이 연결 가능)
일반적인 내용으로는 반이중(Half-Duplex) 통신이며 대부분의 RS485 시스템은 2개의 선을 사용하여 송신과 수신을 번갈아 가며 수행합니다. (4선식으로 전이중(Full-Duplex) 통신도 가능하지만, 2 선식 반이중이 더 일반적입니다.)
최대 통신 거리는 이론적으로 최대 약 1.2km까지 가능합니다. (통신 속도, 케이블 종류, 주변 환경에 따라 달라질 수 있습니다.)
최대 통신 속도는 거리에 따라 다르지만, 짧은 거리에서는 최대 10Mbps 이상도 가능합니다.
2. RS485와 RS232 차이
RS232는 아직도 임베디드 장비와 PC간 제어를 위해서 많이 사용되고 있습니다. 그렇다면 둘의 차이는 무엇일까요? 간단하게 표로 보면 아래와 같습니다.
특징 | RS485 | RS232 |
신호 방식 | 차동 신호 (Differential) | 단일 종단 신호 (Single-ended) |
통신 거리 | 최대 약 1.2km | 최대 약 15m |
노이즈 내성 | 강함 | 약함 |
연결 장치 수 | 멀티드롭 (최대 32개 표준 부하, 확장 가능) | 1:1 점대점 (Point-to-Point) |
전압 레벨 | -7V ~ +12V (A, B 간 전압 차이) | +/- 3V ~ +/- 15V (GND 기준) |
통신 모드 | 주로 반이중 (2선식), 전이중 가능 (4선식) | 전이중 |
주요 용도 | 산업 자동화, 원격 제어, 다중 장치 통신 | 구형 PC 주변기기, 단거리 저속 통신 |
3. RS485 핀 구성
가장 일반적인 2선식 RS485의 핀 구성은 매우 간단합니다.
Data A (또는 A, Non-inverting, +): 차동 신호 중 하나를 전달하는 선입니다.
Data B (또는 B, Inverting, -): Data A와 반대 극성의 차동 신호를 전달하는 선입니다.
GND (또는 SG, Signal Ground): 신호 기준 접지입니다. 필수적인 것은 아니지만, 특히 장치 간 거리가 멀거나 서로 다른 전원 공급 장치를 사용할 때 안정적인 통신을 위해 연결하는 것이 좋습니다. 장치 간의 공통 모드 전압 차이를 줄여줍니다.
종단 저항 (Termination Resistor): RS485 네트워크에서는 통신 라인의 양 끝에 종단 저항을 연결하는 것이 매우 중요합니다. 이는 신호 반사를 막아 데이터 오류를 줄여주는 역할을 합니다. 보통 100~120옴(Ω) 정도의 저항을 Data A와 Data B 라인 사이에 연결합니다.
참고) 4선식 RS485는 전이중 통신을 위해 송신용 한 쌍(TX+, TX-)과 수신용 한 쌍(RX+, RX-)의 데이터 라인을 가집니다. 하지만 산업 현장에서는 비용과 배선의 단순함 때문에 2선식 반이중 방식이 더 널리 사용됩니다.
4. RS485와 Modbus 관계
RS485 통신을 한다고 하면 가끔 Modbus 통신에 대해서 이야기가 나옵니다. 여기서 약간 혼동이 올 수 있는데 간단하게 정의를 보겠습니다.
RS485은 통신을 위한 물리적인 계층(Physical Layer) 표준입니다. 즉, '어떤 전기적 신호로, 어떻게 선을 연결해서 데이터를 주고받을 것인가'에 대한 규격입니다. 전화기로 비유하자면, 전화기 자체나 전화선과 같은 하드웨어적인 부분이라고 할 수 있습니다.
Modbus는 통신을 위한 프로토콜(Protocol)입니다. 즉, '주고받는 데이터는 어떤 형식과 규칙을 따를 것인가'에 대한 약속입니다. 전화기로 비유하자면, 우리가 전화로 대화할 때 사용하는 '언어'나 '대화 규칙'에 해당합니다.
따라서 RS485와 Modbus는 서로 다른 계층의 개념입니다. Modbus는 RS485라는 물리적인 통신망 위에서 돌아가는 여러 통신 프로토콜 중 하나입니다. Modbus는 RS485 외에도 RS232, TCP/IP 등 다른 통신 매체를 통해서도 사용될 수 있습니다.
하지만 산업 현장에서는 Modbus RTU (Remote Terminal Unit)라는 방식이 주로 RS485를 기반으로 많이 사용됩니다.
5. RS485 프로그래밍 예시 (Python)
USB-to-RS485 컨버터를 사용한다고 가정하고 기본적인 송수신 예시를 간단하게 보겠습니다. 큰 틀은 시리얼 통신과 유사하다고 생각하면 됩니다.
프로토콜을 사용하지 않았고 단순한 폴링방식이므로 송수신 참고 정도만 하시면 됩니다.
GPIO로 DE/RE 핀을 제어가 필요한 경우도 있는데 이 부분은 제외했습니다.
import serial
import time
# import RPi.GPIO as GPIO # 라즈베리파이에서 GPIO로 DE/RE를 직접 제어할 경우
# --- (만약 GPIO로 DE/RE 핀을 제어한다면) ---
# DE_RE_PIN = 18 # 예시 GPIO 핀 번호 (BCM 기준)
# GPIO.setmode(GPIO.BCM)
# GPIO.setup(DE_RE_PIN, GPIO.OUT)
# GPIO.output(DE_RE_PIN, GPIO.LOW) # 기본은 수신 모드 (LOW)
# -----------------------------------------
try:
ser = serial.Serial(
port='COM3', # 사용하는 포트에 맞게 변경
baudrate=9600,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
timeout=1 # 읽기 타임아웃 (초 단위)
)
print(f"{ser.port} 포트가 열렸습니다.")
def send_data(data_to_send):
if ser.is_open:
ser.write(data_to_send)
# ser.flush() # write 후 버퍼를 비워 즉시 전송 (필요에 따라)
print(f"송신: {data_to_send}")
else:
print("시리얼 포트가 열려있지 않습니다.")
def receive_data():
if ser.is_open:
if ser.in_waiting > 0: # 수신 버퍼에 데이터가 있는지 확인
received_bytes = ser.read(ser.in_waiting) # 버퍼에 있는 모든 데이터 읽기
# 또는 received_bytes = ser.readline() # 라인 단위로 읽기
print(f"수신: {received_bytes}")
return received_bytes
else:
return None
else:
print("시리얼 포트가 열려있지 않습니다.")
return None
# 데이터 송신 예시 (바이트 형태로 전송)
message_to_send = b"Hello RS485 from Python!\r\n" # \r\n은 필요에 따라 추가
send_data(message_to_send)
# 잠시 대기 후 데이터 수신 시도
time.sleep(1) # 상대방이 응답할 시간
# 데이터 수신 예시
while True:
response = receive_data()
if response:
# 수신된 데이터로 원하는 작업 수행
pass
time.sleep(0.1) # 너무 자주 폴링하지 않도록 조절
except KeyboardInterrupt:
print("프로그램 종료")
finally:
if 'ser' in locals() and ser.is_open:
ser.close()
print("시리얼 포트가 닫혔습니다.")
# if GPIO_USED: GPIO.cleanup() # GPIO 사용 시 정리
감사합니다.
<참고사이트>
1. Getting Started with RS-485 and Modbus-RTU Part 1: Introduction and setup
https://blog.embeddedexpert.io/?p=2644
2. Basics of RS232, RS422, and RS485 Serial Communication
https://automationcommunity.com/rs232-rs422-rs485/
3. RS-485 Termination
https://www.ni.com/docs/ko-KR/bundle/ni-serial/page/rs-485-termination.html
'IT > Unified Communications' 카테고리의 다른 글
[FreePBX] Python으로 AMI 프로그래밍 테스트 2 (이벤트 수신 및 처리 - 비동기 방식) (0) | 2025.05.16 |
---|---|
[FreePBX]Python으로 FreePBX AMI 프로그래밍 테스트 1 (연결, Ping, 종료 흐름) (0) | 2025.05.01 |
[FreePBX] AMI란 무엇이고 접속해보기 (0) | 2025.04.27 |
FreePBX 설치 후 나타날 수 있는 증상들-1 (전화를 걸면 거절, Cannot Connect To Asterisk) (4) | 2024.12.21 |
FreePBX에 모듈(Module) 추가하는 방법 (Asterisk) (2) | 2024.12.18 |