NTC 온도센서(A1737) 온도 구하기

NTC A1737은 amphenol사의 ntc인데 이 제품은 온도에 따른 저항 값이 완전히 선형적이지 않습니다.

위 표와 같이 -40~0까지 저항이 급속히 떨어지며 0도부터 210도까지도 선형적이지 않고 아래 그림과 같이 몇번의 전환점이 있습니다.

이 센서를 ADC로 읽어서 계산을 해보려고 합니다.
adc 입력회로는 아래와 같습니다.

ADC로 전압을 읽어보면 저항이 클 때에는 3.3V에 가깝게 나오고 저항이 낮으면 0V에 가까워 집니다.
위의 저항-온도 테이블 보시면 -40도~210도 까지 측정 가능하니 범위를 벗어난 것은 오류 처리를 하면 됩니다.
그리고 전압으로 읽어서 온도를 구할 예정이므로 전압을 입력으로 함수를 만들었습니다.
#define VDDA_VOLTAGE 3.3f // MCU 공급 전압 (V)
#define R_FIXED 510.0f // 상단 고정 저항값 R1 (옴)
// 온도와 저항 쌍을 저장하는 구조체 정의
typedef struct {
float resistance;
float temperature_c;
} ResistanceTempPair;
// 이미지 데이터시트에서 발췌한 R-T 테이블 (저항 기준 오름차순으로 정렬 필수)
const ResistanceTempPair rt_table[] = {
{155.4f, 210.0f},
{309.9f, 175.0f},
{541.8f, 150.0f},
{886.9f, 130.0f},
{2036.0f, 100.0f},
{3776.0f, 80.0f},
{10851.0f, 50.0f},
{30000.0f, 25.0f},
{37387.0f, 20.0f},
{96248.0f, 0.0f},
{965530.0f, -40.0f}
};
// 테이블 크기 계산
const int table_size = sizeof(rt_table) / sizeof(rt_table[0]);
/**
* @brief 전압 분배기에서 측정된 전압을 섭씨 온도로 변환합니다 (LUT 방식).
*
* @param input_voltage TEMP1 핀에서 측정된 ADC raw value를 변환한 전압 값 (V)
* @return float 섭씨 온도 (°C), 범위를 벗어나면 -999.0f 반환
*/
float convert_voltage_to_celsius_lut(float input_voltage) {
float thermistor_resistance, temperature_c;
// 1. 입력 전압 유효성 검사
if (input_voltage < 0.0f || input_voltage > VDDA_VOLTAGE) {
return -999.0f;
}
// 2. 전압 분배기 공식을 사용하여 NTC 서미스터의 저항 계산
if (input_voltage >= (VDDA_VOLTAGE - 0.001f)) {
thermistor_resistance = 9999999999.0f; // 매우 높은 저항
} else if (input_voltage <= 0.001f) {
thermistor_resistance = 0.0f; // 거의 0옴
} else {
thermistor_resistance = R_FIXED * (input_voltage / (VDDA_VOLTAGE - input_voltage));
}
// 3. 룩업 테이블을 사용하여 온도 찾기 (선형 보간)
// 테이블 범위를 벗어나는 경우 처리 (최저/최고 온도 반환 또는 에러)
if (thermistor_resistance > rt_table[table_size - 1].resistance) {
return rt_table[table_size - 1].temperature_c; // -40도 이하
}
if (thermistor_resistance < rt_table[0].resistance) {
return rt_table[0].temperature_c; // 210도 이상
}
// 보간할 두 지점 찾기
for (int i = 0; i < table_size - 1; i++) {
// 현재 저항값이 rt_table[i+1]과 rt_table[i] 사이에 있다면
if (thermistor_resistance >= rt_table[i].resistance && thermistor_resistance <= rt_table[i+1].resistance) {
float r1 = rt_table[i].resistance;
float t1 = rt_table[i].temperature_c;
float r2 = rt_table[i+1].resistance;
float t2 = rt_table[i+1].temperature_c;
// 선형 보간 공식 적용
// T = T1 + (R - R1) * (T2 - T1) / (R2 - R1)
temperature_c = t1 + (thermistor_resistance - r1) * (t2 - t1) / (r2 - r1);
return temperature_c;
}
}
// 찾지 못한 경우 (예외 상황)
return -999.0f;
}
adc로 읽어와 전압으로 변환한 후 전압을 기준으로 저항 값을 유추합니다.
유추된 저항이 A1737이 읽을 수 있는 범위에 있는지 검사합니다.
이상이 없는 경우 저항을 lookup table을 이용하여 어느 저항 사이인지를 구합니다.(r1,r2)
이제 두 저항 사이를 점을 찍고 측정한 저항 값을 그 사이에서 온도를 유추해 냅니다.(저항과 저항사이는 선형성이 있다고 판단 합니다.)
예를 들어 위 테이블에 있는 309.9옴을 연결한 후 계산해 보겠습니다.
309.9옴이면 adc로 읽어 온 전압은 1.247V입니다.
저항을 역산해보니 309.7759옴이 나옵니다.
309.7759옴은 155.4옴과 309.9옴 사이입니다.
계산해보면 175.0281047도가 나옵니다.
테이블의 175도와 비슷하게 나오네요^^