BMS에서 온도 측정은 필수다. 과열 보호, 저온 충전 제한 등.
AD7280A에 AUX ADC 채널이 있다. 여기에 NTC 연결하면 온도 측정 가능.
AUX ADC
AD7280A에 AUX ADC 채널이 2개 있다.
- AUX_ADC_1 (0x06)
- AUX_ADC_2 (0x07)
셀 전압이랑 같은 12비트 ADC. 전압 범위도 1V~5V 동일.
NTC 연결
NTC(Negative Temperature Coefficient) 서미스터를 분압 회로로 연결:
VDD (5V)
│
├──[10kΩ]──┬── AUX_IN
│ │
│ [NTC]
│ │
└──────────┴── GND
NTC 저항이 온도에 따라 변하니까 분압 전압이 변한다.
저온(0°C): NTC 저항 높음 → 분압 전압 낮음
고온(60°C): NTC 저항 낮음 → 분압 전압 높음
AUX ADC 읽기
CTRL_HB에서 AUX 변환 모드 설정:
uint16_t AD7280A_ReadAuxADC(uint8_t device, uint8_t channel) {
// AUX 변환 시작
uint32_t frame = AD7280A_BuildWriteFrame(
device,
AD7280A_CTRL_HB,
0x43 // AUX 변환 + 시작
);
AD7280A_Transfer(frame);
HAL_Delay(2);
// 결과 읽기
uint8_t reg = AD7280A_AUX_ADC1 + channel;
return AD7280A_ReadCellVoltage(device, reg);
}
전압 → 온도 변환
NTC 특성에 따라 룩업 테이블 사용:
// 10kΩ NTC (B=3950) + 10kΩ 분압저항 기준
// ADC raw → 온도(0.1°C 단위)
const int16_t ntc_table[41] = {
// raw값 100 단위로 샘플링
// index 0 = raw 0 ~ 99
-200, // 0: -20°C
-100, // 1: -10°C
0, // 2: 0°C
50, // 3: 5°C
100, // 4: 10°C
150, // 5: 15°C
200, // 6: 20°C
250, // 7: 25°C
300, // 8: 30°C
350, // 9: 35°C
400, // 10: 40°C
// ... 계속
};
int16_t AD7280A_RawToTemperature(uint16_t raw) {
int index = raw / 100;
if (index >= 40) return 800; // 80°C 이상
if (index < 0) return -300; // -30°C 이하
// 선형 보간
int16_t t1 = ntc_table[index];
int16_t t2 = ntc_table[index + 1];
int frac = raw % 100;
return t1 + (t2 - t1) * frac / 100;
}
문제: NTC B값
처음에 아무 NTC나 달았다가 온도가 6도씩 틀렸다.
NTC마다 B값이 다르다. B값이 다르면 저항-온도 특성이 다르다.
10kΩ NTC (B=3380) @ 50°C: 4.16kΩ
10kΩ NTC (B=3950) @ 50°C: 3.60kΩ
룩업 테이블을 B=3950 기준으로 만들었는데 B=3380 NTC를 달았던 거다.
B값 맞는 NTC로 교체하거나, 테이블을 새로 만들어야 한다.
실측 테이블 만들기
정확한 테이블을 원하면 직접 측정:
- NTC를 항온조에 넣음
- 0°C, 10°C, 20°C, … 각 온도에서 ADC 값 기록
- 테이블 생성
나는 그냥 데이터시트 공식으로 계산했다:
// Steinhart-Hart 방정식
float NTC_CalcTemperature(float resistance) {
const float B = 3950.0f;
const float R25 = 10000.0f; // 25°C에서 저항
const float T25 = 298.15f; // 25°C in Kelvin
float t_kelvin = 1.0f / (1.0f/T25 + (1.0f/B) * log(resistance/R25));
return t_kelvin - 273.15f; // Celsius
}
온도 보호
온도 측정 목적:
- 과열 보호: 60°C 이상이면 충방전 차단
- 저온 충전 제한: 0°C 이하면 충전 금지
- 온도 보상: SOC 추정 시 온도 보정
void BMS_CheckTemperature(void) {
int16_t temp = BMS_GetTemperature();
if (temp > 600) { // 60°C
BMS_SetFault(FAULT_OVERTEMP);
BMS_DisableOutput();
}
else if (temp < 0 && g_bms.state == STATE_CHARGING) {
BMS_StopCharging(); // 저온 충전 금지
}
}
정리
- AUX ADC로 NTC 전압 읽기
- 분압 회로 + 룩업 테이블
- NTC B값 확인 필수
- 과열/저온 보호에 사용
Part 3 측정편 끝.
다음은 밸런싱. 셀마다 전압이 다르면 맞춰줘야 한다.