reform

MNT Reform: Open Source Portable Computer
Log (Feed) | Files | Refs (Tags) | README

commit 13b604f8f2fa4676ba84cafe772626e1aeeacea0
parent 2cb5500401e4bae52bbfe6244cc99d2a92150539
Author: mntmn <lukas@mntmn.com>
Date:   Tue,  3 Nov 2020 18:09:10 +0100

reform2-lpc-fw: detect full charge; more robust/safe handling of missing cells, avoid charge+discharge collision

Diffstat:
Mreform2-lpc-fw/src/boards/reform2/board_reform2.c | 104+++++++++++++++++++++++++++++++++++++++++--------------------------------------
1 file changed, 54 insertions(+), 50 deletions(-)

diff --git a/reform2-lpc-fw/src/boards/reform2/board_reform2.c b/reform2-lpc-fw/src/boards/reform2/board_reform2.c @@ -156,6 +156,7 @@ char uartBuffer[255] = {0}; float cells_v[8] = {0,0,0,0,0,0,0,0}; int num_undervolted_cells = 0; int num_undervolted_critical_cells = 0; +int num_fully_charged_cells = 0; int num_overvolted_cells = 0; int num_missing_cells = 0; uint8_t reached_full_charge = 0; @@ -264,6 +265,7 @@ void measure_cell_voltages_and_control_discharge() { num_missing_cells = 0; num_undervolted_cells = 0; + num_fully_charged_cells = 0; num_overvolted_cells = 0; num_undervolted_critical_cells = 0; @@ -279,21 +281,26 @@ void measure_cell_voltages_and_control_discharge() { (state != ST_OVERVOLTED && cells_v[i] >= OVERVOLTAGE_START_VALUE)) { overvoltage_bits |= (1<<i); num_overvolted_cells++; + // we assume that overvoltage also means fully charged + num_fully_charged_cells++; + } + else if (cells_v[i] >= FULLY_CHARGED_VOLTAGE) { + num_fully_charged_cells++; } else if (cells_v[i] < UNDERVOLTAGE_VALUE) { undervoltage_bits |= (1<<i); num_undervolted_cells++; - + if (cells_v[i] < UNDERVOLTAGE_CRITICAL_VALUE) { num_undervolted_critical_cells++; } } } - + // 0x2: RDCFG, read config registers /*spir[0] = 0x2; spir[1] = 0xce; - + LPC_GPIO->CLR[1] = (1 << 23); delay(2); ssp1Send(spir, 2); @@ -741,36 +748,36 @@ int main(void) calculate_capacity_percentage(); if (state == ST_CHARGE) { - if (cycles_in_state > 5) { - // some cool-off time - if (num_missing_cells > 0) { - state = ST_MISSING; - // if cells were unplugged, we don't know the capacity anymore. - reached_full_charge = 0; - cycles_in_state = 0; - } - else if (num_undervolted_cells > 0) { - // when transitioning to undervoltage, we assume we reached the bottom - // of usable capacity, so record it - // but only if we reached top charge once, or our counter will - // be off. - if (reached_full_charge > 0) { - capacity_min_ampsecs = capacity_accu_ampsecs; - } - state = ST_UNDERVOLTED; - cycles_in_state = 0; + if (num_missing_cells > 0) { + state = ST_MISSING; + // if cells were unplugged, we don't know the capacity anymore. + reached_full_charge = 0; + cycles_in_state = 0; + } + else if (num_undervolted_cells > 0) { + // when transitioning to undervoltage, we assume we reached the bottom + // of usable capacity, so record it + // but only if we reached top charge once, or our counter will + // be off. + if (reached_full_charge > 0) { + capacity_min_ampsecs = capacity_accu_ampsecs; } - else if (num_overvolted_cells > 0) { + state = ST_UNDERVOLTED; + cycles_in_state = 0; + } + else if (num_overvolted_cells < 8 && num_fully_charged_cells >= 8) { + // when transitioning to fully charged, we assume that we're at max capacity + capacity_accu_ampsecs = capacity_max_ampsecs; + state = ST_FULLY_CHARGED; + reached_full_charge = 1; + cycles_in_state = 0; + } + else if (num_overvolted_cells > 0) { + if (cycles_in_state > 5) { + // some cool-off time state = ST_OVERVOLTED; cycles_in_state = 0; } - else if (volts >= FULLY_CHARGED_VOLTAGE) { - // when transitioning to fully charged, we assume that we're at max capacity - capacity_accu_ampsecs = capacity_max_ampsecs; - state = ST_FULLY_CHARGED; - reached_full_charge = 1; - cycles_in_state = 0; - } } } else if (state == ST_UNDERVOLTED) { @@ -779,52 +786,49 @@ int main(void) // TODO: find safe heuristic. here we turn off if half // of the cells are undervolted. - if (num_undervolted_critical_cells > 0 || num_undervolted_cells > 3) { + if (num_undervolted_critical_cells >= 1 || num_undervolted_cells >= 4) { turn_som_power_off(); } - + if (cycles_in_state > 5) { state = ST_CHARGE; cycles_in_state = 0; } } else if (state == ST_OVERVOLTED) { - discharge_overvolted_cells(); - - // discharge - if (cycles_in_state > 5 && (num_overvolted_cells==0 || num_undervolted_cells>0)) { - reset_discharge_bits(); + if (num_missing_cells > 0) { + state = ST_MISSING; + // if cells were unplugged, we don't know the capacity anymore. + reached_full_charge = 0; cycles_in_state = 0; + } else { + discharge_overvolted_cells(); + + // discharge + if (cycles_in_state > 5 && (num_overvolted_cells==0 || num_undervolted_cells>0)) { + reset_discharge_bits(); - if (volts >= FULLY_CHARGED_VOLTAGE) { - // when transitioning to fully charged, we assume that we're at max capacity - capacity_accu_ampsecs = capacity_max_ampsecs; - state = ST_FULLY_CHARGED; - reached_full_charge = 1; - } else { state = ST_CHARGE; + cycles_in_state = 0; } } } else if (state == ST_MISSING) { reset_discharge_bits(); - + if (cycles_in_state > 5) { if (num_missing_cells < 1) { state = ST_CHARGE; cycles_in_state = 0; - } - else if (num_overvolted_cells > 0) { - state = ST_OVERVOLTED; - cycles_in_state = 0; + } else { + turn_som_power_off(); } } } else if (state == ST_FULLY_CHARGED) { - // fully charged. resume charging once we're 0.2mV - // below fully charged state if (cycles_in_state > 5) { - if (volts < (FULLY_CHARGED_VOLTAGE - 0.2)) { + // if none of the cells are fully charged anymore, allow charging again + if (num_fully_charged_cells < 1) { state = ST_CHARGE; cycles_in_state = 0; }