반응형

 【 아두이노 센서#6】 I2C (Inter Integrated Circuit) 통신 



 지난 시간 TMP36 온도센서를 가지고 LCD 디스플레이 장치에 온도를 표시 해보았다. (☞  온도센서 tmp36 LCD 편), 이때 단 하나 아쉬운 것은 LCD가 패러럴로 아두이노 포트에 연결되고 병렬로 직접 제어를 하다보면 복잡하기도 하고 아두이노 제어포트가 부족한 상황이 발생 한다. 

 이런 문제는 I2C 통신 모듈이 달려있는 LCD를 연결함으로서 간단히 해결되는데,  오늘은 이런 I2C 통신에 대해 알아보는 시간을 갖도록 하겠다. 



I2C 통신





1   .I2C 통신은 필립스에서 개발한 통신 방식으로서 여러 개의 디바이스에 고유의 아이디를 부여해 디바이스 다자간 직접 통신이 가능하도록 만든 통신 방식.

2.   I2C프로토콜은 CLOCKDATA회선 두 개로 통신하기 때문에 두 가닥(Two-wire)프로토콜이라고 한다.

3.   I2C 최소한의 입출력 핀(SDA,SCL)만 사용하여 양방향 통신이 가능 하다
(SDA: Serial DAta,  SCL: Serial CLock)

4.    기존에 RS232C를 이용한 두 가닥 시리얼 통신(USART)이 있지만 I2C 통신은 1:N , N:N 통신이 가능하다. 때문에 마스터 와 슬레이브 설정이 필요하다.(최대 128개 연결)
때문에 각 장치마다 고유주소가 필요하고, 주소저장을 위한 레지스터가 존재한다

5.   통신을 위해서는 풀업 저항 필요
- 4.7KΩ
권장-빠른 속도의 통신에서는 약 2.2KΩ
- 오픈 드레인의 특성상 오픈 상태에서는 플업 저항 이 없으면 그라운드 상태가 되기 때문이다.

6.  I2C 통신은 예를 들어 여러 개의 온도센서들로 부터의 데이터를 처리하고자 할 경우 등에 적합하다.


▶ SPI(Serial Peripheral Interface) 통신과의 비교 :  






▶ I2C 통신 절차 :

  (이미지 클릭하면 확대 가능)


 I2C 통신 방법

1.  마스터에서 시작 비트를 전송한다.
2.  마스터에서 통신하려는 슬레이브 장치의 7비트 주소를 보낸다
3.  I2C 장치의 레지스터에 데이터를 쓸 것인지 아니면 읽어 올 것인
   지에 따라 마스터에서 1비트의 읽기 명령(1) 이나 쓰기 명령(0)을 
   보낸다
4.  슬레이브에서는 Acknowledge 또는 ACK비트(Low신호) 응답
    한다
5.  마스터는 I2C의 레지스터를 읽겠다는 1바이트 명령을 쓰기 모드
    에서 전송하고, 슬레이브에서는 ACK비트로 응답한다. 마스터는 
    I2C기기에서 전송되는 1바이트 정보를 읽기 모드에서 수신한다.  
    1바이트씩 읽고 나면 슬레이브에 ACK비트를 전송한다.

6.  마스터 에서 STOP 비트를 전송하여 마스터와 슬레이브 간 통신
    을 완료한다.

 Read 절차

1.  마스터에서 ReadAddressWrite Control ByteR/W bit
    를 Read셋팅Write 하면 슬레이브에서 Data를 전송 하게 
   된다.

2.  원하는 크기(데이터) 만큼 다 읽었다면 마스터는 슬레이브에게 
    Data를 그만 달라고 No ACK 신호를 준다( Data LineHigh)



 위 LCD 이미지의 뒷 면에 부착된 모듈이 바로 I2C통신을 가능하게 해주는 모듈이다.  최근에는 대부분의 기기에서 I2C 통신 혹은 SPI통신용 모듈이 부착되거나 내장되어 출시되고 있다.   따라서 향후에는 I2C(모듈)를 적극 이용해서 실습을 진행할 예정이다.


I2C 스캐너 사용하기  :  


※ I2C 센서를 사용하기 위해서는 I2C 센서 마다의 고유 주소를 알아야 하는데, 이 주소를 알기 위해서는 제조회사에서 제공하는 Data Sheet를 참고 할 수도 있으나, 좀더 쉽게 알아 낼 수 있는 방법이 지금 소개하는 I2C 스캐너 이다.
스캔너는 아두이노에 아래 프로그램을 작성하고 실행을 시키면 시리얼 모니터 창을 통해 주소를 확인 할 수 있다. 



▶ I2C 스캐너 프로그램 코드 : 


#include <Wire.h>

void setup()

{

  Wire.begin();  

  Serial.begin(9600);

  while (!Serial);          

  Serial.println("\nI2C Scanner");

}

void loop()

{

  byte error, address;

  int nDevices;

  Serial.println("Scanning...");

  nDevices = 0;

  for(address = 1; address < 127; address++ )

  {

    Wire.beginTransmission(address);

    error = Wire.endTransmission();

if (error == 0)

    {

      if (address<16)

      Serial.print("0");

      Serial.print("I2C device found at address 0x");

      Serial.print(address,HEX);

      Serial.println(" ←");

      Serial.print("I2C device Dec Number is: ");

      Serial.print(address,DEC);

      Serial.println(" ←");

      nDevices++;

    }

    else if (error==4)

    {

      Serial.print("Unknow error at address 0x");

      if (address<16)

        Serial.print("0");

      Serial.println(address,HEX);

    }  

   }

  if (nDevices == 0)

    Serial.println("No I2C devices found\n");

  else

    Serial.println("done!\n");

   delay(5000);

}




▶ I2C 스캐너 실행 결과 :

 (영상은 고화질로 설정하고 전체화면으로 보세요)



위 시리얼 모티터 상에서 0x48(16진)  혹은 72(10진) 값이  해당 부품의 고유주소가 되며, 이는 부품마다 다를 수 있다.



반응형