아두이노프로세싱 프로그래밍

아두이노 I2C(Inter-Integrated Circuits) 인터페이스 코드 실험

coding art 2019. 11. 6. 21:32
728x90

 

 

 

 

아두이노 프로젝트에서 대단히 중요하게 사용되고 있는 I2C 인터페이스 기법에 대해서 알아보자. I2C는 그 발음이 I-two-C 또는 I-squared-C 로 부르며, 1980년대부터 사용되어온 보편적인 직렬형 인터페이스 기법으로 알려져 있다. 인터페이스 속도가 그다지 고속은 아니지만 특히 아두이노와 같이 인터페이스 속도가 문제가 되지 않는 마이크로 콘트롤러들 사이의 통신 수단으로 대단히 유용하다. 아울러 I2C 프로토콜 사용자체는 무료이지만 특히 Slave 의 주소를 고정적으로 사용하는 센서 칩의 경우에는 인터넷 도메인 주소 관리에서 처럼 약간의 비용을 납부해야 한다. 주로 아두이노 보드에서 사용하는 대표적인 센서들 중의 하나로서 드론에서 흔히 사용하는 MPU6050 센서가 있을 수 있으며 Slave 로 사용함에 있어 헥사(16진법)로 사용하는 주소(address) 가 있음에 주의하자.

 

이미 아두이노 사물인터넷 프로젝트인 ThingSpeak 에서는 이미 Write API 키 값을 가지고 데이터를 서버에 송신하는지에 관한 인터페이스 사용 경험이 있을 것이다. I2C 인터페이스도 비슷하긴 하지만 속도에 있어서는 ThingSpeak에 비해 훨씬 고속이나 짧은 거리에 한해 통신이 가능하다는 점이다.

 

 

다음 그림에서처럼 I2C 인터페이스는 하나의 마스터와 여러 개의 슬레이브로 구성이 가능하다. 마스터에서는 지정된 슬레이브 주소에 데이터를 송신해 주면 되고 자신의 주소를 아는 슬레이브가 수신하면 된다. 아두이노에서의 사용 전압은 5V 또는 3.3V 이며 이 전원선과 SDA 핀과 SCL 핀 사이에는 적절한 값의 풀업 저항이 있어 HighLow 상태를 만들 수 있다.

 

 

 

 

아두이노에서 I2CSDC SDA 2개의 핀으로 이루어진다. 한편 멀티테스터를 사용하여 SCLA5, SDAA4를 통전 테스트해 보면 그들이 연결되어 있음을 알 수 있다. 배선 편의를 위해서 사용자가 선택하여 사용하면 된다.

 

다음 배선도에 의하면 마스터 아두이노 보드와 슬레이브 보드 사이에 SCL 핀과 SDA 핀을 점퍼선으로 연결해 주고 아우러 양보드의 GND 핀을 연결하여 기준전압 0V를 맞춰주도록 한다. I2C 인터페이스는 3가닥 점퍼선으로 이루어    지는 셈이다.

 

 

 

마스터에 해당하는 코드는 Wire.begin() 으로 시작한다. Loop 문에서 반복적으로 데이터를 보내기 위해서는 Wire.beginTransmmission(슬레이브 주소)으로 시작 후 Wire.write(송신데이타)를 출력 후 Wire.endTransmission() 으로 끝맺는다. 이때에 보내는 문자는 1 바이트에 해당하는 0255까지의 정수를 사용하면 편리하다. 이 정수는 다른 한편으로는 ASCII 문자에 해당하기도 한다.     아울러 가변저항으로 이루어진 위 배선에서는 아날로그 전압 값을 01023 범위로 읽어 다시 2551 사이의 값으로 매핑하여 보낸다.

 

 

 

슬레이브 코드의 특징은 마스터에서 지정하여 사용하는 주소와 슬레이브의 주소가 동일해야 한다. 아우러 언제 데이터가 들어올지 모르므로 이벤트 방식으로 임의의 시점에 데이터가 들어어면 Wire.read() 명령을 사용하여 버퍼로부터 읽어 들인다.

 

 

 

 

 

일차적으로 마스터 아두이노 코드를 빌드하자. 아울러 COM 포트를 확인 설정 후 슬레이브 코드를 빌드한다. 슬레이브 빌드 후 스레이브 코드의 시리얼 모니터 하나만을 볼 수 있음에 유의하자.

 

아두이노 마스터 배선에서 가변 저항을 돌린 상태에서 슬레이브의 LED 의 점멸 속도가 변함을 알 수 있다. 실시간 치고는 좀 느린 편이므로 로봇처럼 끓어진 동작으로 가변저항을 돌려 보도록 하자.

 

아래 유튜브 주소에서 I2C 통신 데모를 관찰해 보자

https://youtu.be/ZJdvQ9QUo08

 

//master_I2C_01

#include <Wire.h>
#define SLAVE_ADDR 9

int analogPin = 0;//가변저항 아날로그입력 핀 번호
int val = 0;
 
void setup() {
  Wire.begin(); // Initialize I2C communications as Master
}
 
void loop() {
  delay(50);
  val = map(analogRead(analogPin), 0, 1023, 255, 1); // Read pot value
  Wire.beginTransmission(SLAVE_ADDR); // Write a charatre to the Slave
  Wire.write(val);
  Wire.endTransmission();
}

 

//Slave_I2C_print_01

#include <Wire.h>
#define SLAVE_ADDR 9
 
int LED = 13;
int rd; // Variable for received data
int br; // Variable for blink rate
 
void setup() {
  pinMode(LED, OUTPUT);
  Wire.begin(SLAVE_ADDR);
  Wire.onReceive(receiveEvent);
  Serial.begin(9600);
  Serial.println("I2C Slave Demonstration");
}
 
void receiveEvent() {
  rd = Wire.read();
  Serial.println(rd);
   
}
void loop() {
  delay(50);
  br = map(rd, 1, 255, 100, 2000);
  digitalWrite(LED, HIGH);
  delay(br);
  digitalWrite(LED, LOW);
  delay(br);
 }//끝