[아두이노] 서미스터 온도 측정 완벽 워크플로우 (저항형 센서 감도 조절 및 캘리브레이션)
“비선형 데이터를 직선으로 펴고, 기울기와 절편까지 맞춘다”
아두이노로 온도를 측정할 때 가장 흔히 겪는 문제는 단순합니다.
값이 둔감하다 (변화가 잘 안 보인다)
값이 비선형이다 (온도와 비례하지 않는다)
값이 부정확하다 (실제 온도와 다르다)
이 문제를 해결하는 가장 정석적인 방법이 바로 다음 3단계입니다:
① 하드웨어 튜닝 → ② 수학적 선형화 → ③ 캘리브레이션
이 글에서는 이 과정을 “엔지니어링 워크플로우” 관점에서 정리합니다.
1. 하드웨어 단계: 가변저항으로 “감도” 확보
핵심 개념
서미스터는 온도에 따라 저항이 변하지만,
우리가 측정하는 것은 “전압”입니다.
그래서 반드시 전압 분배 회로를 구성해야 합니다.
회로 구조
5V ── 가변저항(Rf) ── A0 ── 서미스터(Rs) ── GND
여기서 중요한 포인트는:
가변저항을 이용해 “측정 구간”을 중앙에 맞춘다
왜 이게 중요할까?
ADC(analogRead)는 0~1023 범위를 사용합니다.
하지만 잘못 설정하면:
800~820만 왔다 갔다 → ❌ 해상도 낭비
100~120만 사용 → ❌ 감도 낮음
최적화 방법
👉 목표:
측정하려는 온도 범위의 중앙값에서 ADC ≈ 512
예:
측정 범위: 25~30°C
기준 온도: 27°C
목표: analogRead ≈ 512 (약 2.5V)
조정 방법
실제 온도를 27°C로 맞춘다
가변저항을 돌린다
analogRead 값이 512 근처가 되도록 맞춘다
결과
위쪽/아래쪽 변화 모두 감지 가능
Headroom 확보
측정 해상도 최대화
⚠️ 매우 중요한 주의사항
한 번 맞춘 후 절대 건드리지 마세요
이 값이 바뀌면 이후 모든 계산이 틀어집니다.
2. 소프트웨어 단계: 로그 함수로 “선형화”
문제의 본질
서미스터는 이렇게 동작합니다:
온도 ↑ → 저항 ↓ (비선형, 지수형)
즉,
온도 vs 저항 그래프는 곡선이다
해결 방법: 로그 변환
로그를 취하면:
곡선 → 직선에 가까워짐
이를 정밀하게 모델링한 공식이 바로:
Steinhart-Hart 방정식
1/T = A + B·ln(R) + C·(ln(R))³
T: 절대온도(K)
R: 서미스터 저항
A, B, C: 센서 계수
처리 흐름
1) ADC → 전압
Vout = raw × (Vin / 1023)
2) 전압 → 저항
Rs = Rf × (Vout / (Vin - Vout))
3) 저항 → 온도
logR = ln(Rs)
T(K) = 1 / (A + B·logR + C·logR³)
T(°C) = T(K) - 273.15
결과
비선형 데이터 → 거의 직선화
온도 계산 가능
하지만…
아직 정확하지 않다 ❗
3. 캘리브레이션: “정확도” 완성
왜 필요한가?
가변저항 값 정확하지 않음
센서 오차 존재
ADC 오차 존재
즉,
계산값 ≠ 실제값
해결 방법: 2점 보정 (Linear Calibration)
1) 데이터 수집
| 조건 | 실제 온도 | 계산 온도 |
|---|---|---|
| 저온 (T1) | 20.0°C | Tcalc1 |
| 고온 (T2) | 35.0°C | Tcalc2 |
2) 보정 공식
Treal = (Tcalc - Tcalc1)
× (T2 - T1) / (Tcalc2 - Tcalc1)
+ T1
의미
이건 단순히:
직선의 기울기 + 절편 맞추기
입니다.
직관적으로 보면
로그 단계 → “직선으로 펴는 작업”
캘리브레이션 → “직선 위치 맞추는 작업”
4. 통합 아두이노 코드
#include <math.h>
const float V_IN = 5.0;
const float R_FIXED = 10000.0;
// Steinhart-Hart 계수
const float A = 0.001129148;
const float B = 0.000234125;
const float C = 0.0000000876741;
void setup() {
Serial.begin(9600);
}
void loop() {
int raw = analogRead(A0);
// 1. 전압 계산
float vOut = raw * (V_IN / 1023.0);
// 2. 저항 계산
float rSensor = R_FIXED * (vOut / (V_IN - vOut));
// 3. 선형화
float logR = log(rSensor);
float tempK = 1.0 / (A + B * logR + C * pow(logR, 3));
float tempC = tempK - 273.15;
// 4. 캘리브레이션
float calibratedTemp = fmap(tempC, 21.5, 36.2, 20.0, 35.0);
Serial.print("Raw Temp: ");
Serial.print(tempC);
Serial.print(" | Calibrated: ");
Serial.println(calibratedTemp);
delay(1000);
}
// float용 map 함수
float fmap(float x, float in_min, float in_max, float out_min, float out_max) {
return (x - in_min) * (out_max - out_min)
/ (in_max - in_min) + out_min;
}
5. 전체 워크플로우 정리
① 하드웨어 (가변저항)
👉 전압 변화 폭 최적화
👉 해상도 확보
② 수학 (로그 함수)
👉 곡선을 직선으로 변환
👉 선형성 확보
③ 캘리브레이션
👉 실제 값에 맞춤
👉 정확도 확보
핵심 한 줄 정리
센서 엔지니어링 =
“감도(하드웨어) + 선형화(수학) + 보정(실측)”
이 구조를 이해하면,
CdS 센서
압력 센서
가스 센서
같은 모든 저항형 센서에 그대로 적용할 수 있습니다.
원하면
👉 “왜 로그를 취하면 직선이 되는지 (수학적으로)”
👉 “가변저항 값에 따라 감도가 어떻게 변하는지 (그래프)”
이것도 이어서 깊게 파헤쳐 줄게.
댓글
댓글 쓰기