[아두이노] 라이브러리 없이 SHT30 온습도 센서 직접 제어하기 (Arduino/I2C)


대부분 아두이노에서 센서를 다룰 때는 전용 라이브러리를 사용합니다.
하지만 산업 현장이나 임베디드 환경에서는 메모리 절약, 디버깅 편의성, 그리고 예외 처리 강화를 위해 데이터시트를 직접 해석하여 구현하는 경우가 많습니다.

특히 PLC, 산업용 제어기기, 펌웨어 개발에서는 라이브러리 의존성을 줄이는 것이 시스템 안정성 측면에서 큰 장점이 됩니다.

이번 글에서는 Wire.h만 사용하여 SHT30 센서를 직접 제어하는 방법을 정리해 보겠습니다.


1. SHT30의 통신 메커니즘 이해하기

SHT30은 I2C 기반 디지털 온습도 센서입니다.

라이브러리 내부에서 실제로 수행되는 동작은 생각보다 단순합니다.

MCU와 센서는 아래 순서대로 통신합니다.

Single Shot Mode 동작 순서

  1. I2C START 조건 생성

  2. 센서 주소(0x44) 전송

  3. 측정 명령어(0x2C06) 전송

  4. 센서 내부 측정 완료까지 대기

  5. 측정 결과 6바이트 읽기

  6. Raw 데이터를 온습도로 변환

즉, 라이브러리란 결국 이 과정을 함수로 감춰놓은 것에 불과합니다.


2. SHT30 기본 배선

Arduino UNO 기준

SHT30Arduino UNO
VCC3.3V ~ 5V
GNDGND
SDAA4
SCLA5

3. 중요한 특징: I2C 주소는 제조 단계에서 결정됨

SHT30 모듈은 일반적으로 아래 두 가지 주소 중 하나를 사용합니다.

ADDR 핀 상태I2C 주소
LOW0x44
HIGH0x45

문제는 알리익스프레스 등에서 판매되는 일부 SHT30 모듈은:

  • ADDR 핀이 외부로 노출되지 않거나

  • PCB 내부에서 GND/VCC로 고정되어 있는 경우가 많다는 점입니다.

즉:

  • 사용자가 주소를 변경할 수 없는 경우가 존재

  • 제조 단계에서 주소가 사실상 결정됨

이라는 특징이 있습니다.

따라서 여러 개의 SHT30을 동시에 연결하려면:

  • 0x44

  • 0x45

주소 조합을 고려해야 하며,

동일 주소 센서를 여러 개 연결해야 하는 경우에는:

  • I2C 멀티플렉서(TCA9548A)

  • 별도 I2C 버스

  • RS485 기반 센서

등을 고려해야 합니다.


4. 라이브러리 없이 직접 제어하기

아래 코드는 Wire.h만 사용하여 SHT30을 직접 제어하는 예제입니다.

#include <Wire.h>

void setup() {
  Wire.begin();

  Serial.begin(9600);
  Serial.println("SHT30 Raw Control Start...");
}

void loop() {

  // =====================================================
  // 1. 측정 시작 명령 전송
  // Command: 0x2C06
  // High Repeatability + Clock Stretching Enabled
  // =====================================================

  Wire.beginTransmission(0x44);

  Wire.write(0x2C);
  Wire.write(0x06);

  // 통신 종료 후 ACK 확인
  if (Wire.endTransmission() != 0) {
    Serial.println("Error: Sensor not found");
    delay(2000);
    return;
  }

  // =====================================================
  // 2. 센서 측정 대기
  // 데이터시트 권장: 약 15~20ms 이상
  // =====================================================

  delay(50);

  // =====================================================
  // 3. 센서 데이터 요청
  // 총 6바이트:
  // Temp MSB
  // Temp LSB
  // Temp CRC
  // Humidity MSB
  // Humidity LSB
  // Humidity CRC
  // =====================================================

  Wire.requestFrom(0x44, 6);

  if (Wire.available() == 6) {

    // -----------------------------
    // Temperature RAW
    // -----------------------------
    uint16_t t_raw =
      (Wire.read() << 8) | Wire.read();

    uint8_t t_crc = Wire.read();

    // -----------------------------
    // Humidity RAW
    // -----------------------------
    uint16_t h_raw =
      (Wire.read() << 8) | Wire.read();

    uint8_t h_crc = Wire.read();

    // =====================================================
    // 4. 데이터시트 공식으로 변환
    // =====================================================

    // Temperature:
    // T = -45 + 175 * RAW / 65535

    float temperature =
      -45.0 +
      (175.0 * (float)t_raw / 65535.0);

    // Humidity:
    // RH = 100 * RAW / 65535

    float humidity =
      100.0 *
      (float)h_raw / 65535.0;

    // =====================================================
    // 5. 결과 출력
    // =====================================================

    Serial.print("Temp: ");
    Serial.print(temperature, 1);
    Serial.print(" C");

    Serial.print(" | Hum: ");
    Serial.print(humidity, 1);
    Serial.println(" %");
  }

  delay(2000);
}

5. 핵심 이해 포인트

측정 명령 0x2C06

Wire.write(0x2C);
Wire.write(0x06);

이 두 바이트는:

  • 측정 시작

  • 고정밀 모드

  • Clock Stretching 사용

이라는 의미를 갖는 SHT30 전용 명령어입니다.

즉, 라이브러리는 결국 이런 명령어를 대신 보내주는 역할을 합니다.


6. Raw 데이터는 왜 16비트인가?

센서는 실제 온도를 바로 보내지 않습니다.

대신:

0 ~ 65535

범위의 디지털 값(Raw Data)을 전송합니다.

즉:

  • ADC 변환 결과

  • 내부 보정값 적용 결과

  • 센서 내부 DSP 처리 결과

등이 포함된 값입니다.

MCU는 이를 다시 물리량으로 변환해야 합니다.


7. 데이터시트의 Transfer Function

SHT30 데이터시트에는 아래 공식이 존재합니다.

온도 변환 공식:

T=-45+175\times\frac{S_T}{2^{16}-1}

습도 변환 공식:

RH=100\times\frac{S_{RH}}{2^{16}-1}

여기서:

  • S_T = Temperature Raw Data

  • S_RH = Humidity Raw Data

입니다.

즉 센서는:

  • 물리 세계

  • 디지털 비트 세계

사이를 연결하는 변환 장치라고 볼 수 있습니다.


8. CRC 바이트의 의미

SHT30은 각 데이터 블록마다 CRC8 체크섬을 함께 전송합니다.

온도 데이터:
2바이트 + CRC1바이트

습도 데이터:
2바이트 + CRC1바이트

즉 총 6바이트를 전송합니다.

CRC는:

  • 노이즈

  • EMI

  • 배선 불량

  • 통신 오류

등으로 데이터가 깨졌는지 검증하기 위한 용도입니다.

산업 환경에서는 이 CRC 검증이 매우 중요합니다.


9. 왜 라이브러리 없이 구현하는가?

① 데이터시트 이해 능력 향상

센서의 동작 원리를 깊게 이해하게 됩니다.

단순히 함수 호출이 아니라:

  • 어떤 명령을 보내는지

  • 어떤 데이터가 오는지

  • 어떤 수식으로 변환되는지

를 직접 이해하게 됩니다.


② 시스템 최적화

전용 라이브러리는 범용성을 위해 코드가 무겁습니다.

하지만 직접 구현하면:

  • Flash 사용량 감소

  • RAM 사용량 감소

  • 실행 속도 향상

효과를 얻을 수 있습니다.

특히 저사양 MCU에서는 큰 차이가 납니다.


③ 산업용 시스템 안정성

현장에서는:

  • 통신 실패

  • CRC 오류

  • 타임아웃

  • 센서 Disconnect

같은 상황을 세밀하게 처리해야 합니다.

직접 구현하면 이러한 예외 처리 로직을 정교하게 설계할 수 있습니다.


마무리

라이브러리를 사용하는 것은 편리합니다.

하지만 센서와 MCU가 실제로 어떤 "비트 단위 대화"를 하는지 이해하는 순간부터 임베디드 개발 실력이 크게 성장하기 시작합니다.

특히 산업 자동화, PLC, 펌웨어 개발에서는:

  • 데이터시트 해석 능력

  • 프로토콜 이해 능력

  • Raw 데이터 처리 능력

이 매우 중요한 역량이 됩니다.


댓글

이 블로그의 인기 게시물

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

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

NPN, PNP 트랜지스터 차이점

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

사각형의 넓이 공식의 증명

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

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

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

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

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