[아두이노] I2C센서 데이터시트를 읽고 직접 코딩하는 방법 (Wire 라이브러리의 진짜 의미)
아두이노로 I²C 센서를 사용할 때 많은 사람들이 먼저 라이브러리를 설치합니다.
하지만 실무나 디버깅 단계로 들어가면 결국 반드시 만나게 되는 것이 있습니다.
바로:
센서 데이터시트(Datasheet)
입니다.
오늘은 단순히 "코드를 복붙하는 방법"이 아니라,
I²C가 실제로 어떻게 동작하는지
데이터시트를 어떻게 읽는지
그 내용을 어떻게 Wire 코드로 변환하는지
를 하나씩 연결해서 정리해보겠습니다.
1. I²C 센서는 왜 데이터시트가 중요한가?
I²C는 단순히:
"주소로 장치를 선택해서 데이터 주고받는 통신"
정도로 알려져 있습니다.
하지만 실제 센서는 내부에 여러 레지스터(Register)를 가지고 있습니다.
예를 들어 온도 센서 내부에는:
| Register | 의미 |
|---|---|
| 0x00 | Temperature |
| 0x01 | Configuration |
| 0x02 | Alarm Threshold |
같은 구조가 들어있습니다.
즉 MCU는 단순히:
"온도 줘"
라고 말하는 것이 아니라,
"0x00 레지스터의 데이터를 읽겠다"
라고 정확히 지정해야 합니다.
이 정보는 전부 데이터시트에 적혀 있습니다.
2. 데이터시트에서 가장 먼저 보는 것
I²C 센서 데이터시트를 열면 가장 먼저 찾는 것은:
1. I²C Address
2. Register Map
3. Read/Write Timing
입니다.
3. I²C Address 읽기
예제 코드:
int temp_address = 72;
여기서 72는 10진수입니다.
16진수로는:
0x48
입니다.
그리고 이진수로는:
1001000
입니다.
데이터시트에는 보통 이렇게 나옵니다.
Slave Address = 1001000
이것이 센서의 I²C 주소입니다.
4. 데이터시트의 핵심: Read Byte Format
많은 I²C 센서 데이터시트에는 아래 같은 타이밍 다이어그램이 나옵니다.
S Address WR ACK Command ACK
S Address RD ACK Data NACK P
처음 보면 굉장히 어려워 보입니다.
하지만 실제 의미는 단순합니다.
5. Read Byte Format 해석하기
Step 1. 쓰기 모드로 센서 접근
S Address WR
의 의미:
"센서야, 내가 너한테 명령 하나 보낼게"
입니다.
여기서:
S = START
WR = Write Mode
입니다.
Step 2. 읽고 싶은 레지스터 지정
Command
부분이 핵심입니다.
예를 들어:
0x00
이면:
Temperature Register
를 의미할 수 있습니다.
즉 MCU는:
"0번 레지스터 읽고 싶다"
라고 먼저 알려주는 것입니다.
Step 3. 다시 시작해서 읽기 모드 진입
그 다음 데이터시트에는:
S Address RD
가 다시 등장합니다.
이것을:
Repeated START
라고 부릅니다.
즉 방향을 바꾸는 것입니다.
쓰기 모드 → 읽기 모드
Step 4. 센서가 데이터 반환
마지막:
Data
부분에서 센서가 실제 온도 데이터를 반환합니다.
6. 이제 Arduino 코드를 보면 갑자기 이해된다
레지스터 지정 단계
Wire.beginTransmission(temp_address);
Wire.write(0);
Wire.endTransmission();
이 부분은 데이터시트의:
S Address WR ACK Command ACK
에 해당합니다.
실제 데이터 읽기 단계
Wire.requestFrom(temp_address, 1);
이 부분은:
S Address RD ACK Data NACK P
를 수행합니다.
즉:
다시 START 발생
READ 모드 진입
데이터 수신
을 Wire 라이브러리가 자동으로 처리하는 것입니다.
7. 실제 버스에서는 이런 신호가 흐른다
실제로는 아래 같은 흐름입니다.
START
1001000 + W
ACK
00000000
ACK
REPEATED START
1001000 + R
ACK
DATA
NACK
STOP
여기서:
| 값 | 의미 |
|---|---|
| 1001000 | 센서 주소 |
| W | Write Mode |
| R | Read Mode |
| 00000000 | Register 0 |
입니다.
8. 왜 굳이 먼저 Write를 할까?
초보자가 가장 헷갈리는 부분입니다.
"읽을 건데 왜 write를 먼저 하지?"
이유는:
센서 내부에서 읽을 위치를 지정해야 하기 때문
입니다.
즉:
1. 어디 읽을지 지정
2. 실제 읽기 수행
이라는 2단계 구조입니다.
9. 이것이 라이브러리 없는 직접 제어의 기반
실제로:
STM32 HAL
ESP-IDF
Linux I²C Driver
PLC 임베디드 제어
등에서도 전부 같은 개념을 사용합니다.
즉 핵심은:
데이터시트의 Timing Diagram을
MCU 코드로 변환하는 능력
입니다.
10. Wire 라이브러리의 진짜 역할
Arduino Wire 라이브러리는:
Wire.beginTransmission()
Wire.write()
Wire.endTransmission()
Wire.requestFrom()
같은 간단한 함수로 보이지만,
내부에서는 실제로:
START 생성
ACK 처리
Address 전송
Read/Write 방향 제어
STOP 생성
을 전부 수행합니다.
즉 Wire는:
I²C 프로토콜을 추상화한 고수준 인터페이스
라고 볼 수 있습니다.
11. 데이터시트를 읽을 수 있게 되면 생기는 변화
이 단계에 도달하면:
✅ 라이브러리가 없는 센서도 제어 가능
✅ 산업용 Modbus/I²C 장치 분석 가능
✅ 통신 에러 원인 파악 가능
✅ 로직 분석 능력 향상
✅ MCU/PLC/임베디드 공통 개념 이해 가능
해집니다.
즉 단순 "아두이노 코딩"을 넘어서:
임베디드 시스템 엔지니어링
으로 넘어가는 시작점이 됩니다.
마무리
I²C 센서를 다룬다는 것은 단순히:
Wire.read();
를 호출하는 것이 아닙니다.
진짜 중요한 것은:
데이터시트의 통신 다이어그램을 읽고
그 흐름을 코드로 변환하는 능력
입니다.
이 개념을 이해하면:
새로운 센서를 붙이는 속도
디버깅 능력
통신 프로토콜 이해도
가 완전히 달라집니다.
댓글
댓글 쓰기