[아두이노] [강좌] 31. I2C 통신 (3) - 온도 센서(TMP102) 실습하기

이번 시간에는 I2C 통신 방식을 사용하는 온도 센서를 사용하는 예제로, I2C 통신을 사용하는 방법을 자세히 알아보자. 


온도 센서는 스파크펀 사의 "TMP102"라는 센서를 사용할 예정이다. 


c4347c37ccfdc5c7a56000a05dd914c4.png
 


6개의 핀을 사용할 수 있도록 되어 있지만, 실제로 ALT 핀은 사용하지 않는다. 어디에 쓰이는지 잘 모르겠...


ADD0 핀은 I2C 통신에 사용되는 슬레이브 주소 값을 위해 사용되는데, TMP102의 데이터 시트를 보면 ADD0 핀의 설정으로 I2C 주소를 변경할 수 있다고 되어 있다.


17e8b7de66df806e05a56bb436a262cc.png


즉, ADD0 핀을 GND와 연결할 경우 TMP102의 주소는 1001000(2진수, 10진수로 72)가 되고, VCC에 연결될 경우 73(10진수, 2진수로 1001001), SDA 핀과 연결될 경우 74, SCL 핀과 연결될 경우 75가 되는 것. 


구매 보드의 경우 ADD0 핀이 GND와 연결되어 판매되고 있으므로, ADD0 핀을 다른 핀과 연결하지 않는 이상 TMP102 센서의 슬레이브 주소 값은 "72"가 되겠다. 


자, 주소 값 나왔고. 아두이노랑 연결해볼까?


c4389e344b0f5ae2c44b0cb11890f555.png


TMP102 센서는 3.3V 전원을 사용하므로 Vcc 핀에 3.3V 전원을 연결해야 한다. GND는 GND에, SDA는 SDA(20번 핀)에, SCL은 SCL(21번 핀)에 연결한다. 



그리고는 제일 중요한 소스.


TMP102에 대한 예제는 아두이노 공식 홈페이지에서도 찾을 수 있다. 아래는 공식 홈페이지에서 TMP102에 대한 페이지 주소.



>> 아두이노 홈페이지의 TMP102 : http://playground.arduino.cc/Code/TMP102




위 홈페이지에 올라와 있는 소스는 아두이노 버전 1.0.0 이전의 버전이므로 Wire.send() 함수와 Wire.receive() 함수가 있는데, 이 함수들은 현재 버전에서 사용할 수 없다. 


send() 함수는 write() 함수로, receive() 함수는 read() 함수로 변경해야 한다. 



아래는 위 소스를 참고해서 실제로 동작하도록 소스를 수정한 것이다.



 TMP102Test.ino

 

 #include <Wire.h>


 #define TMP102_ADDR  72

 #define TMP102_REG_TEMP  0


 void setup() {

   Wire.begin();

   Serial.begin(9600);

 }


 void loop() {

   float temp = GetTemperature();

   Serial.print("temp : ");

   Serial.println(temp);

   delay(2000);

 }


 float GetTemperature() {

   Wire.beginTransmission(TMP102_ADDR);

   Wire.write(TMP102_REG_TEMP);

   Wire.endTransmission();

  

   Wire.requestFrom(TMP102_ADDR, 2);

   byte firstByte = Wire.read();

   byte secondByte = Wire.read();

  

   int sumByte = ((int)firstByte << 4) | (secondByte >> 4);

  

   float tempValue = sumByte * 0.0625;

   return tempValue;

 }





하나씩 살펴보자.


우선 I2C 통신을 위해 Wire 객체의 기능을 사용할 것이므로 Wire.h 파일을 추가해준다.



 #include <Wire.h>

 



그리고 TMP102의 슬레이브 주소와 레지스터 주소를 키워드로 지정했다.



 #define TMP102_ADDR  72

 #define TMP102_REG_TMEP  0

 



여기서 잠깐, 레지스터 주소????


I2C 통신에서는 내가 읽어 올 데이터가 무슨 데이터인지, 또는 쓸 데이터가 어디에 쓰여질 데이터인지를 알리기 위해 데이터가 위치하는 곳의 주소 값을 전달하는데, 그 값을 포인터 주소 또는 레지스터 주소라고 한다. 


TMP102의 경우 측정된 온도 값이 저장된 레지스터의 주소가 '0'이므로 'TMP102_REG_TEMP'의 값을 0으로 지정했다. 다음은 TMP102 센서의 데이터 시트 중 레지스터 주소를 나타낸 표이다. 


57e7bc81f2d35c6eb968ea6606db584b.png

온도 값을 읽어오는 것 말고도 Configuration Register(설정 레지스터) 등에 값을 변경할 수 있지만, 온도 값을 읽어오는 것만 사용하기 위해서는 기본 설정만으로도 충분하므로 예제에서는 따로 설정하지 않았다.  



자, 그리고 setup() 함수. Wire 객체를 초기화해야겠지? 



 void setup() {

   Wire.begin();

   Serial.begin(9600);

 }

 



읽어 온 온도 값을 시리얼 모니터로 확인할 것이므로 Serial 객체 역시 초기화 해줬다. I2C 통신에서 아두이노는 마스터의 역할을 할 것이므로 Wire.begin() 함수에 매개 변수는 없다. 



그리고 loop() 함수에서는 실제로 온도 값을 읽어오는 기능의 GetTemperature() 함수를 호출하여 값을 읽어오고, 시리얼로 값을 출력한다. 



GetTemperature() 함수는 매개 변수는 없고, 반환 값이 float 형태인 함수이다. 이 함수에서 I2C 통신을 이용해 온도 데이터를 읽어오고, 실제 온도 값으로 변환할 것이다.  



온도 값을 읽어오기 위한 단계는 다음과 같다.



1. 슬레이브 기기 주소 + 쓰기 비트 전달

2. 읽어 올 데이터의 레지스터 주소 전달

3. 슬레이브 기기 주소 + 읽기 비트 전달

4. 읽어오기



GetTemperature() 함수의 내용을 보자. 



 Wire.beginTransmission(TMP102_ADDR);

 Wire.write(TMP102_REG_TEMP);

 Wire.endTransmission();

 



1,2 단계의 내용을 실행한 것이다. 


Wire.beginTransmission() 함수로 슬레이브의 기기와 쓰기 비트를 전달하고, Wire.write() 함수로 실제로 쓸 데이터(레지스터 주소 값)를 전달한다. 그리고 Wire.endTrnasmission() 함수로 버퍼에 저장된 데이터를 모두 전송한다. 


Wire 객체의 함수들에 대한 설명은 이전 강좌를 참고하자.



그리고 3 단계, 다시 슬레이브 기기의 주소를 다시 전달하는데, 이번에는 데이터를 읽어올 것이므로,



 Wire.requestFrom(TMP102_ADDR, 2); 

 



라고 해준다. Wire.requestFrom() 함수는 슬레이브 기기의 주소 값과 읽어올 데이터의 길이가 들어간다. 읽어올 데이터의 길이는 2. TMP102 센서는 값을 12비트 데이터로 전달하기 때문에 2바이트를 읽어야 한다.



4 단계, 읽어온다.



 byte firstByte = Wire.read();

 byte secondByte = Wire.read();

 



2 바이트니까 두 번 Wire.read(). firstByte와 secondByte 변수에 차례로 저장된다. 



I2C 통신은 여기서 끝이다. 다음은 읽어온 값을 실제 온도 값으로 변환하는 변환식. 변환식은 어떻게 구한다? 구글링 또는 데이터 시트를 참고해서. 그리고 아까 링크해 둔 아두이노 공식 홈페이지의 TMP102 예제에도 변환식이 있다. 


구글링이나 공식 홈페이지는 그냥 검색하면 나오는 거니까 넘어가고, 데이터 시트는 같이 한 번 살펴보자. (데이터 시트는 TMP102 판매 사이트에 링크로 제공되고 있음)


aea13e80078c7c5c7404b13ee8ef8797.png


우선, 첫 번째 바이트의 8비트와 두 번째 바이트의 상위 4비트를 사용한다. 즉, secondsByte의 하위 4비트는 사용하지 않는다는 뜻. 



 int sumByte = ((int)firstByte << 4) | (secondByte >> 4);



쉬프트 연산(<<, >>)이 처음 나왔네. 쉬프트 연산에 대한 내용은 마지막에 "*참고"로 접어뒀으니 참고하도록 하고, 여기서는 읽어온 두 개의 바이트를 합해서 12비트만 골라내는 단계라고 알고 넘어가자. 



그리고는 변환식. 다음은 데이터 시트 중 온도 데이터와 실제 온도 값이 어떻게 계산되는지를 나타낸 부분이다.


926707059f2bd54ae15bf9cf896ed91c.png
 

위의 표는 각각의 온도에서 데이터 값이 얼마인지를 표로 나타낸 것이고, 아래는 그 데이터가 어떻게 해서 계산된 것인지를 나타낸 것이다. 다른 건 필요 없고, 빨간 색으로 줄 쳐둔 부분을 보자. 온도 값을 "0.0625/count" 값으로 나눈 값을 데이터로 출력하고 있는데, 여기서 count 값을 계산해보면 '1'이 나온다. 뭘 의미하는지는 모르겠.. 안 나오ㅏ... 그냥 1이라고 보면 됨. 


아무튼, 그럼 읽어온 데이터에 0.0625를 곱하면 실제 온도 값이 나온다는 말!!


그래서 소스는, 



 float tempValue = sumByte * 0.0625;

 return tempValue;

 



tempValue 값을 반환하면서 끝!



업로드 한 후 시리얼 모니터를 실행해보면 현재의 온도 값이 2초 간격으로 출력되는 것을 볼 수 있을 것이다. 



온도 센서 실습 끝!!



온도 센서는 거의 대부분의 모니터링 시스템에 사용되는 센서이다. 홈 네트워크에서도 집 안의 온도 값을 읽기 위해 사용, 기상 관측 시스템에서도 당연히 사용, 모니터링 로봇에서도 온도 센서는 기본으로 사용된다. 


물론, 모니터링 시스템을 위해서는 블루투스나 와이파이 등의 통신 모듈이 포함되어야겠지만. 



강좌 50번 정도에서는 블루투스나 와이파이를 사용하는 예제를 다루고 있지 않을까 하는 조심스런 예상을 해보면서, (진짜 50번이 될지는 모르겠지만, 하기는 할거임. 진짜임) 오늘은 이만 안녕!

0
0
이 글을 페이스북으로 퍼가기 이 글을 트위터로 퍼가기 이 글을 카카오스토리로 퍼가기 이 글을 밴드로 퍼가기

임베디드 보드

번호 제목 글쓴이 날짜 조회수
58 아두이노 [강좌] 50. 와이파이 통신 (4) - WebServer 예제 icon 양재동메이커 03-21 12,866
57 아두이노 [강좌] 49. 와이파이 통신 (3) - WebClient 예제 icon 양재동메이커 03-21 16,338
56 아두이노 [강좌] 48. 와이파이 통신 (2) - 커맨드 모드 사용하기 (WiFly 쉴드) icon 양재동메이커 03-20 11,658
55 아두이노 [강좌] 47. 와이파이 통신 (1) - 와이파이란 무엇인가 icon 양재동메이커 03-20 16,087
54 아두이노 [강좌] 46. 블루투스 통신 (5) - 프로토콜 만들기 (2) icon 양재동메이커 03-20 11,879
53 아두이노 [강좌] 45. 블루투스 통신 (4) - 프로토콜 만들기 (1) icon 양재동메이커 03-20 13,510
52 아두이노 [강좌] 44. 블루투스 통신 (3) - RN42 모듈에서 직접 접속하기 icon 양재동메이커 03-20 10,562
51 아두이노 [강좌] 43. 블루투스 통신 (2) - 스마트폰과 통신하기 icon 양재동메이커 03-20 12,725
50 아두이노 [강좌] 42. 블루투스 통신 (1) - RN42 블루투스 모듈 실습하기 icon 양재동메이커 03-20 14,028
49 아두이노 [강좌] 41. 서보 모터 (2) - Servo 함수 알아보기 icon 양재동메이커 03-20 15,779
48 아두이노 [아두이노 강좌] 40. 서보 모터 (1) - 서보 모터 동작 방식 icon 양재동메이커 03-20 16,135
47 아두이노 [강좌] 39. 스텝 모터 (3) - 모터 드라이버 EasyDriver(A3967) 사용하기 icon 양재동메이커 03-20 12,002
46 아두이노 [강좌] 38. 스텝 모터 (2) - Stepper 함수 알아보기 icon 양재동메이커 03-20 15,839
45 아두이노 [강좌] 37. 스텝 모터 (1) - 스텝 모터 동작 방식 icon 양재동메이커 03-20 12,449
44 아두이노 [강좌] 36. DC 모터 (2) - DC 모터 드라이버 실습하기 (TB6612FNG) icon 양재동메이커 03-20 12,050
43 아두이노 [강좌] 35. DC 모터 (1) - DC 모터 동작 방식 icon 양재동메이커 03-20 14,555
42 아두이노 [강좌] 34. SPI 통신 (3) - 기압 센서(MPL115A1) 실습하기 icon 양재동메이커 03-20 11,303
41 아두이노 [강좌] 33. SPI 통신 (2) – SPI 함수 알아보기 icon 양재동메이커 03-20 18,017
40 아두이노 [강좌] 32. SPI 통신 (1) - SPI 통신이란 무엇인가 icon 양재동메이커 03-20 22,922
39 아두이노 [강좌] 31. I2C 통신 (3) - 온도 센서(TMP102) 실습하기 icon 양재동메이커 03-20 18,241