밸런싱 하드웨어는 됐다. 이제 언제, 어떤 셀을 밸런싱할지 결정하는 알고리즘.
기본 아이디어
최소 전압 셀 기준으로 나머지를 맞춘다.
전압 분포:
Cell 0: 3.35V ← 최소와 20mV 차이 → 밸런싱
Cell 1: 3.32V ← 최소와 -10mV → 안 함
Cell 2: 3.33V ← 최소와 0mV (최소) → 안 함
Cell 3: 3.37V ← 최소와 40mV 차이 → 밸런싱
Cell 4: 3.34V ← 최소와 10mV → 안 함
Cell 5: 3.36V ← 최소와 30mV 차이 → 밸런싱
최소 전압보다 일정 값(예: 20mV) 이상 높은 셀만 밸런싱.
델타 전압 방식
#define BALANCE_THRESHOLD_MV 20 // 밸런싱 시작 기준
void BMS_UpdateBalancing(void) {
uint16_t min_mv = UINT16_MAX;
// 최소 전압 찾기
for (int i = 0; i < 24; i++) {
if (g_cells_mv[i] < min_mv) {
min_mv = g_cells_mv[i];
}
}
// 밸런싱 대상 결정
for (int i = 0; i < 24; i++) {
int delta = g_cells_mv[i] - min_mv;
if (delta > BALANCE_THRESHOLD_MV) {
g_balance_mask[i / 6] |= (1 << (i % 6));
}
}
// 밸런싱 적용
for (int dev = 0; dev < 4; dev++) {
AD7280A_SetBalance(dev, g_balance_mask[dev]);
}
}
히스테리시스
단순 threshold만 쓰면 20mV 근처에서 밸런싱이 껐다 켜졌다 반복한다.
측정 1: 3.321V → 밸런싱 OFF (21mV, 기준 이하)
측정 2: 3.319V → 밸런싱 ON (19mV, 기준 초과)
측정 3: 3.321V → 밸런싱 OFF
... 반복
히스테리시스 추가:
#define BALANCE_START_MV 20 // 시작 기준
#define BALANCE_STOP_MV 10 // 종료 기준
void BMS_UpdateBalancing(void) {
for (int i = 0; i < 24; i++) {
int delta = g_cells_mv[i] - min_mv;
if (g_balancing[i]) {
// 이미 밸런싱 중 → 종료 기준으로 판단
if (delta < BALANCE_STOP_MV) {
g_balancing[i] = false;
}
} else {
// 밸런싱 안 함 → 시작 기준으로 판단
if (delta > BALANCE_START_MV) {
g_balancing[i] = true;
}
}
}
}
충전 중만 밸런싱
밸런싱은 충전 중에만 하는 게 일반적이다.
방전 중에 밸런싱하면:
- 이미 방전 중인데 추가로 방전 → 셀 손상 위험
- 의미 없음 (방전하면 어차피 전압 떨어짐)
void BMS_UpdateBalancing(void) {
if (g_bms.state != STATE_CHARGING) {
// 충전 중 아니면 밸런싱 OFF
for (int dev = 0; dev < 4; dev++) {
AD7280A_SetBalance(dev, 0x00);
}
return;
}
// 충전 중이면 밸런싱 로직 실행
// ...
}
근데 나중에 LFP로 바꾸면서 방전 중에도 밸런싱하는 옵션을 추가했다. 상황에 따라 다르다.
전압 범위 체크
너무 낮은 전압에서는 밸런싱 안 함:
#define BALANCE_MIN_VOLTAGE_MV 3000 // 3.0V 이하면 안 함
void BMS_UpdateBalancing(void) {
uint16_t min_mv = GetMinCellVoltage();
if (min_mv < BALANCE_MIN_VOLTAGE_MV) {
// 전압 낮으면 밸런싱 하지 않음
return;
}
// ...
}
저전압 셀을 더 방전시키면 셀 손상.
주기적 실행
1초마다 밸런싱 로직 실행:
void BMS_Task(void) {
static uint32_t last_balance_time = 0;
if (HAL_GetTick() - last_balance_time > 1000) {
last_balance_time = HAL_GetTick();
// 밸런싱 OFF → 측정 → 밸런싱 결정 → 밸런싱 ON
BMS_StopAllBalance();
HAL_Delay(100);
BMS_ReadAllCells();
BMS_UpdateBalancing();
}
}
테스트 결과
편차가 큰 배터리로 테스트:
초기 상태:
Cell 0: 3.450V
Cell 1: 3.320V
Cell 2: 3.380V
...
max-min: 130mV
1시간 충전 + 밸런싱 후:
Cell 0: 3.510V
Cell 1: 3.505V
Cell 2: 3.508V
...
max-min: 12mV
잘 맞춰진다.
정리
- 델타 전압 방식: 최소 전압 대비 높은 셀 밸런싱
- 히스테리시스: 시작/종료 기준 다르게
- 충전 중에만 밸런싱
- 저전압에서는 안 함
다음은 밸런싱 중 발열 관리.