[파이썬] SHT30 Modbus RS485 온습도 센서 제어 가이드 (결선부터 레지스터 분석까지)


산업용 현장이나 스마트 팜에서 정밀한 환경 데이터 수집을 위해 많이 사용되는 SHT30 Modbus RTU 센서.
이번 글에서는 이 센서를 아두이노가 아닌 PC에 직접 연결하여 파이썬(Python) 으로 데이터를 읽어오는 전체 과정을 정리해보겠습니다.

RS485 결선 방법부터 Modbus 레지스터 구조, 파이썬 코드, 실제 통신 패킷 분석까지 한 번에 이해할 수 있도록 구성했습니다.


1. 하드웨어 구성 및 물리적 결선

PC는 RS485 신호를 직접 읽을 수 없으므로 반드시 USB to RS485 컨버터가 필요합니다.

또한 센서의 안정적인 동작을 위해 외부 전원을 사용하는 것이 좋습니다.


준비물

  • SHT30 Modbus RS485 센서

  • USB to RS485 컨버터

  • DC 전원 공급 장치 (5V ~ 24V)

  • PC

  • 점퍼선


상세 결선표

센서 선 색상신호 명칭연결 대상비고
적색 (Red)VCC외부 전원 (+)DC 5V ~ 24V
흑색 (Black)GND외부 전원 (-) 및 컨버터 GND공통 접지 필수
황색 (Yellow)RS485-AUSB 컨버터 A(D+)데이터 +
백색 (White)RS485-BUSB 컨버터 B(D-)데이터 -

핵심 포인트: 공통 접지(Common GND)

RS485는 차동 신호 방식이라 노이즈에 강하지만, 실제 현장에서는 반드시 GND를 공통으로 연결하는 것이 안정적입니다.

즉:

  • 센서 GND

  • 외부 전원 GND

  • RS485 컨버터 GND

이 세 개를 서로 연결하는 것이 좋습니다.


2. Modbus 레지스터 구조 이해

SHT30 Modbus 센서는 내부 데이터를 Holding Register 형태로 저장합니다.

우리는 특정 주소(Register Address)를 읽어서 온도와 습도를 가져오게 됩니다.


레지스터 맵(Register Map)

주소 (HEX)내용데이터 타입처리 방식
0x0000현재 온도16-bit Signed Integer값 ÷ 10.0
0x0001현재 습도16-bit Unsigned Integer값 ÷ 10.0

3. 왜 10으로 나누는가?

Modbus 장비는 부동소수점(Float)을 사용하지 않는 경우가 많습니다.

따라서 실제 데이터를:

실제값 × 10

형태의 정수(Integer)로 변환하여 전송합니다.

예를 들어:

  • 실제 온도 = 25.4℃

  • 전송 데이터 = 254

즉, 수신 측에서는 다시:

temperature = raw_value / 10.0

형태로 복원해야 합니다.


4. 파이썬 환경 설정

먼저 필요한 라이브러리를 설치합니다.

pip install pymodbus pyserial

5. 전체 파이썬 코드

아래 코드는:

  • COM 포트 연결

  • Modbus RTU 통신

  • 온도/습도 읽기

  • 음수 온도 처리

  • 실시간 출력

까지 모두 포함한 전체 예제입니다.

import time
from pymodbus.client import ModbusSerialClient as ModbusClient

# ---------------------------------------------------
# Modbus RTU 통신 설정
# ---------------------------------------------------

client = ModbusClient(
    port='COM3',      # 자신의 COM 포트로 수정
    baudrate=9600,
    parity='N',
    stopbits=1,
    bytesize=8,
    timeout=1
)

# ---------------------------------------------------
# 센서 데이터 읽기 함수
# ---------------------------------------------------

def read_sht30_data():

    # 연결 시도
    if not client.connect():
        print("RS485 컨버터 연결 실패")
        return

    # Holding Register 읽기
    # address=0x00 : 시작 주소
    # count=2      : 온도 + 습도 총 2개 읽기
    # slave=1      : 센서 ID
    response = client.read_holding_registers(
        address=0x00,
        count=2,
        slave=1
    )

    # 정상 응답 확인
    if not response.isError():

        # 레지스터 데이터 추출
        raw_temp = response.registers[0]
        raw_humi = response.registers[1]

        # -------------------------------------------
        # 음수 온도 처리
        # 16-bit Signed Integer 변환
        # -------------------------------------------

        if raw_temp > 32767:
            raw_temp -= 65536

        # 실제 값 복원
        temperature = raw_temp / 10.0
        humidity = raw_humi / 10.0

        # 출력
        current_time = time.strftime('%Y-%m-%d %H:%M:%S')

        print(f"[{current_time}]")
        print(f"Temperature : {temperature:.1f} C")
        print(f"Humidity    : {humidity:.1f} %")
        print("-" * 40)

    else:
        print("데이터 읽기 실패")

    # 연결 종료
    client.close()

# ---------------------------------------------------
# 메인 루프
# ---------------------------------------------------

if __name__ == "__main__":

    try:

        while True:

            read_sht30_data()

            # 센서 안정화를 위해
            # 2초 간격 권장
            time.sleep(2)

    except KeyboardInterrupt:

        print("프로그램 종료")

6. 코드 동작 원리 분석

1) ModbusClient 생성

client = ModbusClient(
    port='COM3',
    baudrate=9600,
    parity='N',
    stopbits=1,
    bytesize=8,
    timeout=1
)

RS485 통신 조건을 설정합니다.

일반적인 SHT30 Modbus 기본값:

  • Baudrate = 9600

  • Data Bits = 8

  • Stop Bits = 1

  • Parity = None

입니다.


2) Holding Register 읽기

response = client.read_holding_registers(
    address=0x00,
    count=2,
    slave=1
)

의 의미는:

  • 시작 주소 0번부터

  • 총 2개의 레지스터를

  • Slave ID 1번 장치에게 요청

한다는 뜻입니다.


3) 음수 온도 처리

온도는 Signed Integer 방식입니다.

즉:

-32768 ~ +32767

범위를 사용합니다.

따라서:

if raw_temp > 32767:
    raw_temp -= 65536

과정을 통해 2의 보수(Two's Complement)를 복원합니다.

예시:

65526 → -10

즉:

-1.0℃

가 됩니다.


7. 실제 Modbus 통신 패킷 분석

실제 데이터 흐름을 보면 디버깅이 훨씬 쉬워집니다.


요청(Request) 패킷

01 03 00 00 00 02 C4 0B

의미:

바이트의미
01Slave ID
03Holding Register 읽기
00 00시작 주소
00 02읽을 개수
C4 0BCRC

즉:

"1번 센서야, 0번 주소부터 2개 데이터 줘"

라는 뜻입니다.


응답(Response) 패킷

01 03 04 01 0E 02 58 BB D8

분석:

데이터의미
01 0E온도
02 58습도

HEX → DEC 변환:

0x010E = 270
0x0258 = 600

최종 변환:

270 / 10 = 27.0℃
600 / 10 = 60.0%

8. 통신이 안 될 때 체크리스트

1) A/B 선 반대로 연결됨

가장 흔한 문제입니다.

  • A ↔ B

  • B ↔ A

로 바꿔서 테스트해보세요.


2) COM 포트 확인

Windows 장치 관리자에서:

포트(COM 및 LPT)

항목 확인 후:

port='COM3'

부분 수정 필요.


3) Slave ID 불일치

센서 기본 ID가:

1

이 아닐 수도 있습니다.

제품 메뉴얼 확인 필요.


4) Baudrate 불일치

일부 제품은:

  • 4800

  • 19200

등을 사용하기도 합니다.


9. 데이터 로깅 확장 아이디어

이제 다음 단계로 확장 가능합니다.

  • CSV 자동 저장

  • SQLite 데이터베이스 저장

  • 실시간 그래프 표시

  • 웹 대시보드 구축

  • MQTT 연동

  • 스마트팜 자동화

  • PLC 연동

등 다양한 환경 모니터링 시스템으로 발전시킬 수 있습니다.


마무리

SHT30 Modbus RS485 센서는:

  • 높은 정밀도

  • 장거리 통신 안정성

  • 산업 현장 친화성

을 모두 갖춘 매우 강력한 센서입니다.

특히:

  • Modbus 레지스터 구조

  • RS485 결선

  • Signed Integer 처리

이 세 가지만 이해하면 대부분의 산업용 센서를 동일한 방식으로 제어할 수 있습니다.

이번 글이 RS485 및 Modbus RTU 입문의 좋은 출발점이 되길 바랍니다.

댓글

이 블로그의 인기 게시물

공압 속도 제어: 미터인 vs 미터아웃

[PLC] 센서 NPN, PNP 출력 타입별 결선방법 (OMRON E2E-X 시리즈 3선식 배선)

NPN, PNP 트랜지스터 차이점

[PLC] PLC 아날로그 입출력 기본

사각형의 넓이 공식의 증명

[아두이노] 가변저항(Potential Divider)과 전압분배(Voltage Divider)

[PLC] 서보 모터 브레이크 결선, 왜 릴레이 터미널을 써야 할까?

[투자] ETF 투자 가이드 : 카테고리별 ETF 선택 전략

[주식] 한국거래소(KRX) 데이터 API 입문 가이드

[PLC] 릴레이와 전자 접촉기 (MC)