1. I2C 통신(Inter-Integrated Circuit)
아두이노에서는 I2C 통신을 TWI(Two Wire Inteface)라고 부른다. 이것은 근거리에서 소자와 소자 사이의 통신을 위해 개발된 프로토콜로서, 마이크크로컨트롤러와 여러 디바이스 간의 통신을 할 수 있는 통신 프로토콜이다.
2. I2C(TWI) 통신의 주요 특징
위에서 I2C의 개념 내용을 다른 말로 하면, 소자와 소자 사이의 통신을 위해 SDA, SCL 핀을 이용하는 통신 방식이다. 여기서 SDA 핀은 데이터를 처리하고, SCL핀은 마스터의 clock을 동기화하기 위한 선이다. 또한 127개의 주소값을 사용할 수 있다.
1. 2개의 신호선
- SDA (Serial Data) (A4) : 데이터 선 - I2C 통신에서 데이터를 전송하는 핀이다. 모든 I2C 기기는 이 핀을 통해 데이터를 주고 받는다.
- SCL (Serial Clock) (A5) : 클럭 신호 선 - I2C 통신에서 클럭을 전송하는 핀이다. 데이터 전송의 타이밍을 제어하고 동기화하는 역할은 한다.
- cf) '클럭(Clock)'은 시스템 내부에서 연산을 수행하는데 사용되는 신호이다. 주로 디지털 회로에서 사용되며, 데이터 전송 및 처리를 동기화하기 위해 필요한 시간적인 기준을 제공한다.
2. 마스터 - 슬레이브 구조
- I2C 통신은 마스터(Master)와 슬레이브(Slave) 간의 통신으로 이루어진다.
- 마스터는 통신의 주도를 가지며, 슬레이브는 주소를 갖고 응답한다.
3. 주소 지정
각 슬레이브 디바이스는 고유한 7비트 또는 10비트의 주소를 가진다.
4. 스타 토폴로지
I2C는 여러 디바이스를 하나의 버스에 연결할 수 있는 스타 토폴로지를 지원한다.
5. 마스터 전송 및 슬레이브 응답
마스터는 슬레이브에게 데이터를 전송하거나, 슬레이브로부터 데이터를 수신받는다. 마스터가 통신의 시작과 종료를 결정한다.
3. 센서가 여러 개인 경우 처리 방식
센서가 여러개 인 경우는 각 센서마다 고유의 주소값을 가지고 있는데 마스터에서 해당 주소값에 대응하는 센서에게 읽을 수 있는 데이터가 있는지 물어보고 만약에 있다면 센서는 값을 출력하게 된다. 동시에 본인의 주소값과 다른 주소값이 들어온 경우에는 데이터를 무시한다.
1. 주소 설정
각 센서는 I2C 주소를 가지고 있어야 한다. 센서의 데이터시트나 사용자 매뉴얼을 참조하여 주소를 확인하고 설정한다.
2. 주소 충돌 방지
I2C는 각 디바이스(Slave 소자)가 고유한 주소를 가지고 있으며 이 주소로 각 소자를 구분하기 때문에 주소 충돌을 방지할 수 있다.
3. 라이브러리 사용
아두이노 우노에서는 Wire 라이브러리를 사용하여 I2C 통신을 쉽게 구현할 수 있다.
#include <Wire.h>
4. 마스터 코드 작성
아두이노 마스터는 각 센서에 대한 데이터 요청 및 수신을 담당하는 코드를 작성한다.
Wire.beginTransmission(sensorAddress);
Wire.write(dataToBeSent);
Wire.endTransmission();
5. 슬레이브 코드 작성
Wire.onRequest() 함수는 Master로부터 요청 신호가 오면 인자로 넘어온 함수를 실행하도록 설정한다.
Wire.onRequest(sendDataFunction);
4. 실습
다음 회로를 만들고, 마스터가 slave들에게 데이터를 전송하는 코드를 작성하자.
<Master 코드>
#include <Wire.h>
void setup(){
Wire.begin();
}
void loop(){
Wire.beginTransmission(4); // 4번 준비!
Wire.write("good") // 데이터
Wire.endTransmission(); // 끝!
delay(500);
Wire.beginTransmission(5); // 5번 준비!
Wire.write("Morning"); // 데이터
Wire.endTransmission(); // 끝!
}
<Slave 4 코드>
#include <Wire.h>
void setup(){
Wire.begin(4);
Wire.onReceive(receiveEvent);
Serial.begin(9600);
}
void loop() {}
void receiveEvent(){
while(Wire.available()){
Serial.println(Wire.read());
}
}
<Slave 5 코드>
#include <Wire.h>
void setup(){
Wire.begin(5);
Wire.onReceive(receiveEvent);
Serial.begin(9600);
}
void loop(){}
void receiveEvent(){
while(Wire.available()){
Serial.println(Wire.read());
}
}
'Develop > Arduino Uno' 카테고리의 다른 글
[아두이노 우노] SoftwareSerial (0) | 2023.12.18 |
---|---|
[아두이노 우노] delay() 함수 없이 주기적인 작업 실행하기 - millis() 함수 (0) | 2023.12.18 |
[아두이노 우노] 내부 인터럽트(타이머 인터럽트) 실습하기 (0) | 2023.12.18 |
[아두이노 우노] I2C 통신 방식의 캐릭터 LCD 실습 (0) | 2023.12.17 |
[아두이노 우노] 인터럽트와 외부 인터럽트 (0) | 2023.12.17 |