안녕하세요
온도 센서(Thermopile)의 값을 읽어 오는 방식에는 아날로그 값을 받아서 디지털로 변환하여 사용하는 표기해 주는 방식과 온도 센서에 소형 칩이 있어 변환작업 필요 없이 간단하게 MCU에서 통신으로 값을 받아 볼 수 있는 방법이 있습니다.
그중에서 테스트해 본 제품은 소형 칩이 내장된 제품으로 I2C 통신을 통해서 값을 읽어오는 것을 테스트했습니다.
우선 I2C 통신을 이용하려고 하면 Pull-up, Pull-down이라는 것을 간단하게 이해하고 있으면 도움이 됩니다. 그래서 간단하게 알아보겠습니다.
1. Pull-up, Pull-down 이해
1.1 개념 이해
디지털 회로는 원칙적으로 H나 L의 전압 인가가 되어야 합니다. High와 Low의 중간 전압이 되면 내부 상태가 불안정하게 되거나 전력 소비가 증가합니다. 그리고 L보다 낮은 전압이나 H보다 높은 전압이 인가되면 방해 전류 흐름이 생겨서 회로를 파괴할 수 있습니다.
일반적으로 디지털 회로의 입력 단자는 내부 임피던스가 높기 때문에(전원 회로와 저항이 큼) 입력 단자가 어디에도 연결되어 있지 않으면 근처의 정전기나 전자기 유도에 의하여 예상할 수 없는 전압이 인가될 수 있습니다. 입력 단자가 어디에도 연결되어 있지 않은 상태를 플로팅(Floating) 상태라고 합니다.
이러한 경우에는 수 kΩ ~ 수백 kΩ 정도의 높은 저항으로 전원선이나 접지선에 연결합니다. 전원선에 연결한 것을 풀업 저항이라고 하고 접지선에 연결한 것을 풀다운 저항이라고 합니다.
스위치가 열려(Open) 있는 상태에서 Pull-up 경우는 1(High)로 읽게 되고, Pull-Down 경우 0(Low) 읽게 됩니다.
반대로 스위치가 닫힌(Close) 있는 상태에서 Pull-up 경우는 저항을 통과한 전류가 회로 쪽 저항보다 GND 쪽 저항이 더 작기 때문에 거의 모든 전류가 GND로 흐르면서 0(Low)으로 읽게 됩니다.
스위치가 닫힌 상태의 Pull-down 경우 저항값보다 디지털 회로에 연결된 저항값이 더 작기 때문에 전류가 디지털 회로 쪽으로 흘러갑니다. 그래서 1(High) 읽게 됩니다.
큰 개념에서 본다는 전류는 저항이 적은 쪽으로 흐른다고 보시면 이해하시기 편할 거라고 생각됩니다. 그중에 GND가 저항값이 적다고 보시면 전류 흐름이 왜 GND로 갈까에 대해 의문이 해결되지 않을까 합니다.
1.2 저항값 계산하는 방법
5V 디지털 회로에서 최소 입력 전류가 1mA라고 한다면
R = V / I 공식에 의해서 R = 5V / 1mA ,5000Ω = 5kΩ 저항을 달면 됩니다.
통상적으로 풀업 저항은 10kΩ~100kΩ 많이 사용한다고 합니다.
2. 아두이노와 온도센서 연결하기
준비물 : 아두이노 나노, 가변저항 10k , TB-I2C-S70, 브레드 보드, 케이블
탄소 피막 저항을 사용하면 Thermopile 회사에서 제공해 주는 배선처럼 간단하게 가능한데 가진 탄소 저항이 없어서 가변저항을 사용해서 테스트했습니다.
중요한 것은 Thermopile에 방향이 있습니다. 살짝 튀어나온 쪽을 기준으로 하셔서 전원 쪽, 데이터 쪽을 구분하셔서 브레드보드 혹은 연결하시면 됩니다.
3. 소스 컴파일 & 실행
측정된 온도만 본다면 제공해주고 있는 소스를 특별하게 수정할 필요 없이 실행시키면 측정된 온도가 나옵니다. 제공된 아두이노 폴더를 보면 방사율 조정, 하는 부분 주소 가져오고 설정하는 코드로 되어 있습니다.
단, I2C 주소 설정에서는 "주소 변경 예제는 필요 때문에 주소를 변경할 경우가 아니라면 사용하지 마시기 바랍니다.
주소를 변경했을 경우, 코드를 수정하지 않으면 더는 통신이 안 됩니다." 주의를 주고 있으니 참고하시기 바랍니다.
다른 설정 없이 온도만 가져오는 소스로 확인해 보겠습니다.
/*****************************************************************************
*
* Project Name : TB-I2C 센서 온도 읽기 I2C 통신 예제
* Version : 1.0
* SYSTEM CLOCK : 16Mhz
* BOARD : Arduino UNO. 5V operation
* I2C Clock : default 100kHz ( Max: 100kHz )
* Development environment : Arduino 1.6.4
PORT Description
1. SDA : A4 or SDA (4번핀과 A4번핀은 다릅니다. 주의바랍니다.)
2. SCL : A5 or SCL (5번핀과 A5번핀은 다릅니다. 주의바랍니다.)
센서 전원은 3.3V이며, 구체적인 회로 연결 방법은 첨부 pdf 파일을 참고하십시오.
Revision history.
1. 2019.5.20. : First version is released.
****************************************************************************/
#include <Wire.h>
#define TB_REG_SENSOR 0x06
#define TB_REG_OBJECT 0x07
uint8_t _deviceAddress = 0x3A; // default Address
int16_t _rawObject;
int16_t _rawSensor;
const unsigned char crc8_table[256]= //CRC table (Please don't change this value)
{
0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5, 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2, 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C, 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C, 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB, 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
};
void setup() {
Wire.begin(); // Initialize I2C
delay(200); // Waiting for sensor initialization.(min : 200ms)
Serial.begin(9600); // Initialize Serial to log output
while (!Serial) ;
}
void loop() {
// put your main code here, to run repeatedly:
if(GetObject() && GetSensor()) // 대상온도 및 센서온도 Read 완료되면
{
Serial.print("Object Temp : ");
Serial.print(CalcTemp(_rawObject)); // 대상온도 출력
Serial.print(" Sensor Temp : ");
Serial.println(CalcTemp(_rawSensor)); // 센서온도 출력
delay(100); // Delay 최소 100ms 이상
}
else
{
Serial.println("Please check the connection or I2C Address.");
delay(1000);
}
}
float CalcTemp(int rawTemp) // 온도계산
{
float retTemp;
retTemp = float(rawTemp)*0.02;
retTemp -= 273.15;
return retTemp;
}
uint8_t GetObject(void) // 대상온도 읽기
{
int16_t rawObj;
if(I2CReadWord(TB_REG_OBJECT, &rawObj))
{
if (rawObj & 0x8000) // 최상위 비트가 1 이면 에러
{
return 0;
}
_rawObject = rawObj;
return 1;
}
}
uint8_t GetSensor(void) // 센서온도 읽기
{
int16_t rawSen;
if(I2CReadWord(TB_REG_SENSOR, &rawSen) )
{
_rawSensor = rawSen;
return 1;
}
return 0;
}
uint8_t I2CReadWord(uint8_t reg, int16_t *dest)
{
uint8_t BUF[5], Low_Byte, High_Byte, PEC;
Wire.beginTransmission(_deviceAddress);
Wire.write(reg);
Wire.endTransmission(false); // Send restart
Wire.requestFrom(_deviceAddress, (uint8_t)3);// 3Byte Read
Low_Byte = Wire.read(); // Low Byte 저장
High_Byte = Wire.read(); // High Byte 저장
PEC = Wire.read(); // 센서에서 전송한 PEC 값
//PEC 연산을 위한 데이터 저장
BUF[0] = _deviceAddress<<1;
BUF[1] = reg;
BUF[2] = (_deviceAddress<<1) | 0x01;
BUF[3] = Low_Byte;
BUF[4] = High_Byte;
if (PEC == CalPEC(BUF, 5)) // 센서가 전송한 PEC 값이 맞는지 검증
{
*dest = (High_Byte<<8) | Low_Byte; // 에러가 없으면 온도 데이터 저장
return 1;
}
return 0; // 실패시 0 return
}
uint8_t CalPEC(uint8_t *crc, uint8_t nBytes) // PEC 연산
{
uint8_t data, count;
uint16_t remainder = 0;
for(count=0; count<nBytes; ++count)
{
data = *(crc++) ^ remainder;
remainder = crc8_table[data] ^ (remainder >> 8);
}
return (uint8_t)remainder;
}
A4번 핀은 SDA , A5번 핀은 SCL과 배선처럼 연결하고 Pull-Up 저항까지 연결이 잘 되어 있다면 Object Temp(측정하고자 하는 물체 온도)와 Sensor Temp(센서 모듈 자체 온도)가 나오는 것을 확인할 수 있습니다.
4. 결 론
특별하게 문제없이 물체 온도를 측정할 수 있습니다. 그러나 I2C 통신이라 풀업 저항을 구성해주어야 합니다. 방사율 등 설정할 수 있는 모듈이기 때문에, 측정하고자 하는 물체에 맞게 방사율을 설정해 주면 됩니다. 설정 소스도 오픈되어 있어 있습니다.
측정 오차와 제품 사항은 이전 편을 참조하시면 됩니다.
수온 온도계랑 비교한 영상입니다. 방사율과 거리가 조정이 조금 필요하겠지만, 대략 몇 번 해본 결과 결과 1 ~ 2도 정도 차이가 나는 것을 알 수 있었습니다. 실험 환경과 횟수에 따라 달라질 수 있으므로 참조정도 하시면 될 것입니다.
감사합니다.
<참고 사이트>
1. 풀업과 풀다운
2. TB-I2C-S70
'IT' 카테고리의 다른 글
eMMC 타입 micro SD Card 테스트 ( 32GB eMMC Module for Rock Pi ) (2) | 2024.10.30 |
---|---|
SC-9547-9 (A-Si 박막형 태양전지 실내 발전가능) 테스트 (2) | 2024.10.26 |
LED 택트스위치 6X6 (색상선택) 사용 후기 (2) | 2024.10.22 |
Adafruit Push-button Power Switch (On/Off 전원 스위치) 사용 후기 (6) | 2024.10.12 |
무선충전 모듈 세트 5V 2A [SZH-EK377] 사용 후기 (3) | 2024.10.11 |