Force Cell Balance if Pack Grossly Imbalanced

This commit is contained in:
doppelhub
2025-06-21 20:39:50 -04:00
parent c70329563e
commit 7052afa2d9
15 changed files with 435 additions and 304 deletions

View File

@@ -7,8 +7,8 @@
#define config_h
#include "src/libcm.h"
#define FW_VERSION "0.9.5f"
#define BUILD_DATE "2025JUN17"
#define FW_VERSION "0.9.5g"
#define BUILD_DATE "2025JUN18"
//////////////////////////////////////////////////////////////////
@@ -95,14 +95,11 @@
#define CELL_VMAX_REGEN 43000 //43000 = 4.3000 volts
#define CELL_VMIN_ASSIST 31900
#define CELL_VMAX_GRIDCHARGER 39600 //3.9 volts is 75% SoC //other values: See SoC.cpp //MUST be less than 'CELL_VREST_85_PERCENT_SoC'
#define CELL_VMIN_GRIDCHARGER 30000 //grid charger will not charge severely empty cells
#define CELL_VMIN_KEYOFF CELL_VREST_10_PERCENT_SoC //when car is off, LiBCM turns off below this voltage
#define CELL_VMAX_GRIDCHARGER 39600 //MUST be less than 'CELL_VREST_085_PERCENT_SoC'
#define CELL_VMIN_GRIDCHARGER 28000 //grid charger will not charge severely empty cells
#define CELL_VMIN_KEYOFF CELL_VREST_010_PERCENT_SoC //when car is off, LiBCM turns off below this voltage
#define CELL_BALANCE_MIN_SoC 65 //when car is off, cell balancing is disabled when battery is less than this percent charged
#define CELL_BALANCE_TO_WITHIN_COUNTS_LOOSE 32 //'32' = 3.2 mV //CANNOT exceed 255 counts (25.5 mV)
#define CELL_BALANCE_TO_WITHIN_COUNTS_TIGHT 22 //'22' = 2.2 mV //LTC6804 measurement uncertainty is 2.2 mV //MUST be less than CELL_BALANCE_TO_WITHIN_COUNTS_LOOSE
#define CELL_BALANCE_MAX_TEMP_C 40
//#define ONLY_BALANCE_CELLS_WHEN_GRID_CHARGER_PLUGGED_IN //uncomment to disable keyOFF cell balancing (unless the grid charger is plugged in)
//temp setpoints
#define COOL_BATTERY_ABOVE_TEMP_C_KEYOFF 36 //cabin air cooling
@@ -135,7 +132,7 @@
//#define RUN_BRINGUP_TESTER_MOTHERBOARD //requires external test PCB (that you don't have)
//#define RUN_BRINGUP_TESTER_GRIDCHARGER //requires external test equipment
#define CHECK_FOR_SAFETY_COVER //comment if testing LiBCM without the cover
//#define CHECK_FOR_SAFETY_COVER //comment if testing LiBCM without the cover
#define DEBUG_USB_UPDATE_PERIOD_GRIDCHARGE_mS 1000 //JTS2doLater: Model after "debugUSB_printLatestData"

View File

@@ -199,8 +199,10 @@ void processAllCellVoltages(void)
LTC68042result_packVoltage_set( (uint8_t)(packVoltage_RAW * 0.0001) );
//JTS2doNow: Store hi/lo cell voltage numbers in LTC68042result
LTC68042result_loCellVoltage_set(loCellVoltage);
LTC68042result_hiCellVoltage_set(hiCellVoltage);
LTC68042result_deltaCellVoltage_set(hiCellVoltage - loCellVoltage);
#ifdef BATTERY_TYPE_5AhG3
//Now we need to determine which cell 19 voltage is correct (the actual measured value, or the current-adjusted one)
@@ -300,6 +302,9 @@ bool LTC68042cell_nextVoltages(void)
while (1) {;} //hang here until watchdog resets.
}
if (cellVoltageDataStatus == CELL_DATA_PROCESSED) { LTC68042result_wasDataProcessedThisLoop_set(YES); }
else { LTC68042result_wasDataProcessedThisLoop_set(NO); }
return cellVoltageDataStatus;
}

View File

@@ -5,6 +5,10 @@
#include "libcm.h"
bool wasProcessed = NO;
bool LTC68042result_wasDataProcessedThisLoop_get(void ) { return wasProcessed; }
void LTC68042result_wasDataProcessedThisLoop_set(bool newStatus) { wasProcessed = newStatus; }
uint8_t isoSPI_errorCount = 0;
uint8_t LTC68042result_errorCount_get (void ) { return isoSPI_errorCount; }
void LTC68042result_errorCount_set (uint8_t newErrorCount) { isoSPI_errorCount = newErrorCount; }
@@ -30,6 +34,10 @@ uint16_t hiCellVoltage_counts = 34567;
void LTC68042result_hiCellVoltage_set(uint16_t newHi_counts) { hiCellVoltage_counts = newHi_counts; }
uint16_t LTC68042result_hiCellVoltage_get(void ) { return hiCellVoltage_counts; }
uint16_t deltaCellVoltage_counts = 0;
void LTC68042result_deltaCellVoltage_set(uint16_t newDelta_counts) { deltaCellVoltage_counts = newDelta_counts; }
uint16_t LTC68042result_deltaCellVoltage_get(void ) { return deltaCellVoltage_counts; }
/////////////////////////////////////////////////////////////////////////////////////////
//All cell voltages in this array are guaranteed to be acquired at the same time

View File

@@ -4,6 +4,9 @@
#ifndef LTC68042result_h
#define LTC68042result_h
bool LTC68042result_wasDataProcessedThisLoop_get(void );
void LTC68042result_wasDataProcessedThisLoop_set(bool newStatus);
uint8_t LTC68042result_errorCount_get (void );
void LTC68042result_errorCount_set (uint8_t newErrorCount);
void LTC68042result_errorCount_increment (void );
@@ -23,9 +26,9 @@
void LTC68042result_hiCellVoltage_set(uint16_t newHi_counts);
uint16_t LTC68042result_hiCellVoltage_get(void );
void LTC68042result_deltaCellVoltage_set(uint16_t newDelta_counts);
uint16_t LTC68042result_deltaCellVoltage_get(void );
void LTC68042result_specificCellVoltage_set(uint8_t icNumber, uint8_t cellNumber, uint16_t cellVoltage);
uint16_t LTC68042result_specificCellVoltage_get (uint8_t icNumber, uint8_t cellNumber);
#endif
// void printCellVoltage_all(); //JTS2doLater: Add back

View File

@@ -300,7 +300,7 @@ LiDisplay_updateNextCellValue() {
static uint8_t cellToUpdate = 0;
static uint8_t ic_index = 0;
static uint8_t ic_cell_num = 0;
static uint16_t cell_avg_voltage = 0;
static uint16_t cell_avg_voltage = 0; //TODO_NATALYA - JTS: this doesn't need to be static
static String cell_color_number = "2016";
static int cell_voltage_diff_from_avg = 0;
static int temp_cell_voltage = 0;
@@ -318,10 +318,11 @@ LiDisplay_updateNextCellValue() {
else if (cellToUpdate <= 59) { ic_index = 4; ic_cell_num = (cellToUpdate - 48); }
// 09 Feb 2023 -- cell_avg_voltage is a crude approximation of the centre of the voltage range. Ideally this would be replaced with the median cell voltage.
LiDisplayAverageCellVoltage = ((LTC68042result_hiCellVoltage_get() - LTC68042result_loCellVoltage_get()) * 0.5);
LiDisplayAverageCellVoltage = ((LTC68042result_hiCellVoltage_get() - LTC68042result_loCellVoltage_get()) * 0.5); //TODO_NATALYA - JTS: replace this line with next line
//LiDisplayAverageCellVoltage = (LTC68042result_deltaCellVoltage_get() >> 1 ) + LTC68042result_loCellVoltage_get();
cell_avg_voltage = (LiDisplayAverageCellVoltage + LTC68042result_loCellVoltage_get());
LiDisplayAverageCellVoltage = (cell_avg_voltage); // TODO_NATALYA - get rid of cell_avg_voltage
cell_avg_voltage = (LiDisplayAverageCellVoltage + LTC68042result_loCellVoltage_get()); //TODO_NATALYA - JTS: remove entire line and entire variable
LiDisplayAverageCellVoltage = (cell_avg_voltage); // TODO_NATALYA - get rid of cell_avg_voltage //TODO_NATALYA - JTS: remove entire line
temp_cell_voltage = LTC68042result_specificCellVoltage_get(ic_index, ic_cell_num);
cell_voltage_diff_from_avg = cell_avg_voltage - temp_cell_voltage;

View File

@@ -104,107 +104,107 @@ void SoC_updateUsingLatestOpenCircuitVoltage(void)
uint16_t restingCellVoltage = LTC68042result_loCellVoltage_get(); //JTS2doLater: need an algorithm to look at hi cell, too.
uint8_t estimatedSoC = 0;
if (restingCellVoltage >= 42000) { estimatedSoC = 100; }
else if (restingCellVoltage >= 41820) { estimatedSoC = 99; }
else if (restingCellVoltage >= 41640) { estimatedSoC = 98; }
else if (restingCellVoltage >= 41460) { estimatedSoC = 97; }
else if (restingCellVoltage >= 41280) { estimatedSoC = 96; }
else if (restingCellVoltage >= 41100) { estimatedSoC = 95; }
else if (restingCellVoltage >= 40980) { estimatedSoC = 94; }
else if (restingCellVoltage >= 40860) { estimatedSoC = 93; }
else if (restingCellVoltage >= 40740) { estimatedSoC = 92; }
else if (restingCellVoltage >= 40620) { estimatedSoC = 91; }
else if (restingCellVoltage >= 40500) { estimatedSoC = 90; }
else if (restingCellVoltage >= 40400) { estimatedSoC = 89; }
else if (restingCellVoltage >= 40300) { estimatedSoC = 88; }
else if (restingCellVoltage >= 40200) { estimatedSoC = 87; }
else if (restingCellVoltage >= 40100) { estimatedSoC = 86; }
else if (restingCellVoltage >= CELL_VREST_85_PERCENT_SoC) { estimatedSoC = 85; } //max cell voltage for long lifetime
else if (restingCellVoltage >= 39880) { estimatedSoC = 84; }
else if (restingCellVoltage >= 39760) { estimatedSoC = 83; }
else if (restingCellVoltage >= 39640) { estimatedSoC = 82; }
else if (restingCellVoltage >= 39520) { estimatedSoC = 81; }
else if (restingCellVoltage >= 39400) { estimatedSoC = 80; }
else if (restingCellVoltage >= 39260) { estimatedSoC = 79; }
else if (restingCellVoltage >= 39120) { estimatedSoC = 78; }
else if (restingCellVoltage >= 38980) { estimatedSoC = 77; }
else if (restingCellVoltage >= 38840) { estimatedSoC = 76; }
else if (restingCellVoltage >= 38700) { estimatedSoC = 75; }
else if (restingCellVoltage >= 38620) { estimatedSoC = 74; }
else if (restingCellVoltage >= 38540) { estimatedSoC = 73; }
else if (restingCellVoltage >= 38460) { estimatedSoC = 72; }
else if (restingCellVoltage >= 38380) { estimatedSoC = 71; }
else if (restingCellVoltage >= 38300) { estimatedSoC = 70; }
else if (restingCellVoltage >= 38230) { estimatedSoC = 69; }
else if (restingCellVoltage >= 38160) { estimatedSoC = 68; }
else if (restingCellVoltage >= 38090) { estimatedSoC = 67; }
else if (restingCellVoltage >= 38020) { estimatedSoC = 66; }
else if (restingCellVoltage >= 37950) { estimatedSoC = 65; }
else if (restingCellVoltage >= 37890) { estimatedSoC = 64; }
else if (restingCellVoltage >= 37830) { estimatedSoC = 63; }
else if (restingCellVoltage >= 37770) { estimatedSoC = 62; }
else if (restingCellVoltage >= 37710) { estimatedSoC = 61; }
else if (restingCellVoltage >= 37650) { estimatedSoC = 60; }
else if (restingCellVoltage >= 37580) { estimatedSoC = 59; }
else if (restingCellVoltage >= 37510) { estimatedSoC = 58; }
else if (restingCellVoltage >= 37440) { estimatedSoC = 57; }
else if (restingCellVoltage >= 37370) { estimatedSoC = 56; }
else if (restingCellVoltage >= 37300) { estimatedSoC = 55; }
else if (restingCellVoltage >= 37250) { estimatedSoC = 54; }
else if (restingCellVoltage >= 37200) { estimatedSoC = 53; }
else if (restingCellVoltage >= 37150) { estimatedSoC = 52; }
else if (restingCellVoltage >= 37100) { estimatedSoC = 51; }
else if (restingCellVoltage >= 37050) { estimatedSoC = 50; }
else if (restingCellVoltage >= 37000) { estimatedSoC = 49; }
else if (restingCellVoltage >= 36950) { estimatedSoC = 48; }
else if (restingCellVoltage >= 36900) { estimatedSoC = 47; }
else if (restingCellVoltage >= 36850) { estimatedSoC = 46; }
else if (restingCellVoltage >= 36800) { estimatedSoC = 45; }
else if (restingCellVoltage >= 36750) { estimatedSoC = 44; }
else if (restingCellVoltage >= 36700) { estimatedSoC = 43; }
else if (restingCellVoltage >= 36650) { estimatedSoC = 42; }
else if (restingCellVoltage >= 36600) { estimatedSoC = 41; }
else if (restingCellVoltage >= 36550) { estimatedSoC = 40; }
else if (restingCellVoltage >= 36480) { estimatedSoC = 39; }
else if (restingCellVoltage >= 36410) { estimatedSoC = 38; }
else if (restingCellVoltage >= 36340) { estimatedSoC = 37; }
else if (restingCellVoltage >= 36270) { estimatedSoC = 36; }
else if (restingCellVoltage >= 36200) { estimatedSoC = 35; }
else if (restingCellVoltage >= 36140) { estimatedSoC = 34; }
else if (restingCellVoltage >= 36080) { estimatedSoC = 33; }
else if (restingCellVoltage >= 36020) { estimatedSoC = 32; }
else if (restingCellVoltage >= 35960) { estimatedSoC = 31; }
else if (restingCellVoltage >= 35900) { estimatedSoC = 30; }
else if (restingCellVoltage >= 35800) { estimatedSoC = 29; }
else if (restingCellVoltage >= 35700) { estimatedSoC = 28; }
else if (restingCellVoltage >= 35600) { estimatedSoC = 27; }
else if (restingCellVoltage >= 35500) { estimatedSoC = 26; }
else if (restingCellVoltage >= 35400) { estimatedSoC = 25; }
else if (restingCellVoltage >= 35360) { estimatedSoC = 24; }
else if (restingCellVoltage >= 35320) { estimatedSoC = 23; }
else if (restingCellVoltage >= 35280) { estimatedSoC = 22; }
else if (restingCellVoltage >= 35240) { estimatedSoC = 21; }
else if (restingCellVoltage >= 35200) { estimatedSoC = 20; }
else if (restingCellVoltage >= 35160) { estimatedSoC = 19; }
else if (restingCellVoltage >= 35120) { estimatedSoC = 18; }
else if (restingCellVoltage >= 35080) { estimatedSoC = 17; }
else if (restingCellVoltage >= 35040) { estimatedSoC = 16; }
else if (restingCellVoltage >= 35000) { estimatedSoC = 15; }
else if (restingCellVoltage >= 34900) { estimatedSoC = 14; }
else if (restingCellVoltage >= 34800) { estimatedSoC = 13; }
else if (restingCellVoltage >= 34700) { estimatedSoC = 12; }
else if (restingCellVoltage >= 34540) { estimatedSoC = 11; }
else if (restingCellVoltage >= CELL_VREST_10_PERCENT_SoC) { estimatedSoC = 10; } //min cell voltage for long lifetime
else if (restingCellVoltage >= 33900) { estimatedSoC = 9; }
else if (restingCellVoltage >= 33600) { estimatedSoC = 8; }
else if (restingCellVoltage >= 33200) { estimatedSoC = 7; }
else if (restingCellVoltage >= 32800) { estimatedSoC = 6; }
else if (restingCellVoltage >= 32200) { estimatedSoC = 5; }
else if (restingCellVoltage >= 31700) { estimatedSoC = 4; }
else if (restingCellVoltage >= 31000) { estimatedSoC = 3; }
else if (restingCellVoltage >= 30500) { estimatedSoC = 2; }
else if (restingCellVoltage >= 29500) { estimatedSoC = 1; }
else { estimatedSoC = 0; }
if (restingCellVoltage >= CELL_VREST_100_PERCENT_SoC) { estimatedSoC = 100; }
else if (restingCellVoltage >= 41820) { estimatedSoC = 99; }
else if (restingCellVoltage >= 41640) { estimatedSoC = 98; }
else if (restingCellVoltage >= 41460) { estimatedSoC = 97; }
else if (restingCellVoltage >= 41280) { estimatedSoC = 96; }
else if (restingCellVoltage >= 41100) { estimatedSoC = 95; }
else if (restingCellVoltage >= 40980) { estimatedSoC = 94; }
else if (restingCellVoltage >= 40860) { estimatedSoC = 93; }
else if (restingCellVoltage >= 40740) { estimatedSoC = 92; }
else if (restingCellVoltage >= 40620) { estimatedSoC = 91; }
else if (restingCellVoltage >= 40500) { estimatedSoC = 90; }
else if (restingCellVoltage >= 40400) { estimatedSoC = 89; }
else if (restingCellVoltage >= 40300) { estimatedSoC = 88; }
else if (restingCellVoltage >= 40200) { estimatedSoC = 87; }
else if (restingCellVoltage >= 40100) { estimatedSoC = 86; }
else if (restingCellVoltage >= CELL_VREST_085_PERCENT_SoC) { estimatedSoC = 85; } //Vmax for long lifetime
else if (restingCellVoltage >= 39880) { estimatedSoC = 84; }
else if (restingCellVoltage >= 39760) { estimatedSoC = 83; }
else if (restingCellVoltage >= 39640) { estimatedSoC = 82; }
else if (restingCellVoltage >= 39520) { estimatedSoC = 81; }
else if (restingCellVoltage >= 39400) { estimatedSoC = 80; }
else if (restingCellVoltage >= 39260) { estimatedSoC = 79; }
else if (restingCellVoltage >= 39120) { estimatedSoC = 78; }
else if (restingCellVoltage >= 38980) { estimatedSoC = 77; }
else if (restingCellVoltage >= 38840) { estimatedSoC = 76; }
else if (restingCellVoltage >= 38700) { estimatedSoC = 75; }
else if (restingCellVoltage >= 38620) { estimatedSoC = 74; }
else if (restingCellVoltage >= 38540) { estimatedSoC = 73; }
else if (restingCellVoltage >= 38460) { estimatedSoC = 72; }
else if (restingCellVoltage >= 38380) { estimatedSoC = 71; }
else if (restingCellVoltage >= 38300) { estimatedSoC = 70; }
else if (restingCellVoltage >= 38230) { estimatedSoC = 69; }
else if (restingCellVoltage >= 38160) { estimatedSoC = 68; }
else if (restingCellVoltage >= 38090) { estimatedSoC = 67; }
else if (restingCellVoltage >= 38020) { estimatedSoC = 66; }
else if (restingCellVoltage >= 37950) { estimatedSoC = 65; }
else if (restingCellVoltage >= 37890) { estimatedSoC = 64; }
else if (restingCellVoltage >= 37830) { estimatedSoC = 63; }
else if (restingCellVoltage >= 37770) { estimatedSoC = 62; }
else if (restingCellVoltage >= 37710) { estimatedSoC = 61; }
else if (restingCellVoltage >= 37650) { estimatedSoC = 60; }
else if (restingCellVoltage >= 37580) { estimatedSoC = 59; }
else if (restingCellVoltage >= 37510) { estimatedSoC = 58; }
else if (restingCellVoltage >= 37440) { estimatedSoC = 57; }
else if (restingCellVoltage >= 37370) { estimatedSoC = 56; }
else if (restingCellVoltage >= 37300) { estimatedSoC = 55; }
else if (restingCellVoltage >= 37250) { estimatedSoC = 54; }
else if (restingCellVoltage >= 37200) { estimatedSoC = 53; }
else if (restingCellVoltage >= 37150) { estimatedSoC = 52; }
else if (restingCellVoltage >= 37100) { estimatedSoC = 51; }
else if (restingCellVoltage >= 37050) { estimatedSoC = 50; }
else if (restingCellVoltage >= 37000) { estimatedSoC = 49; }
else if (restingCellVoltage >= 36950) { estimatedSoC = 48; }
else if (restingCellVoltage >= 36900) { estimatedSoC = 47; }
else if (restingCellVoltage >= 36850) { estimatedSoC = 46; }
else if (restingCellVoltage >= 36800) { estimatedSoC = 45; }
else if (restingCellVoltage >= 36750) { estimatedSoC = 44; }
else if (restingCellVoltage >= 36700) { estimatedSoC = 43; }
else if (restingCellVoltage >= 36650) { estimatedSoC = 42; }
else if (restingCellVoltage >= 36600) { estimatedSoC = 41; }
else if (restingCellVoltage >= 36550) { estimatedSoC = 40; }
else if (restingCellVoltage >= 36480) { estimatedSoC = 39; }
else if (restingCellVoltage >= 36410) { estimatedSoC = 38; }
else if (restingCellVoltage >= 36340) { estimatedSoC = 37; }
else if (restingCellVoltage >= 36270) { estimatedSoC = 36; }
else if (restingCellVoltage >= 36200) { estimatedSoC = 35; }
else if (restingCellVoltage >= 36140) { estimatedSoC = 34; }
else if (restingCellVoltage >= 36080) { estimatedSoC = 33; }
else if (restingCellVoltage >= 36020) { estimatedSoC = 32; }
else if (restingCellVoltage >= 35960) { estimatedSoC = 31; }
else if (restingCellVoltage >= 35900) { estimatedSoC = 30; }
else if (restingCellVoltage >= 35800) { estimatedSoC = 29; }
else if (restingCellVoltage >= 35700) { estimatedSoC = 28; }
else if (restingCellVoltage >= 35600) { estimatedSoC = 27; }
else if (restingCellVoltage >= 35500) { estimatedSoC = 26; }
else if (restingCellVoltage >= 35400) { estimatedSoC = 25; }
else if (restingCellVoltage >= 35360) { estimatedSoC = 24; }
else if (restingCellVoltage >= 35320) { estimatedSoC = 23; }
else if (restingCellVoltage >= 35280) { estimatedSoC = 22; }
else if (restingCellVoltage >= 35240) { estimatedSoC = 21; }
else if (restingCellVoltage >= 35200) { estimatedSoC = 20; }
else if (restingCellVoltage >= 35160) { estimatedSoC = 19; }
else if (restingCellVoltage >= 35120) { estimatedSoC = 18; }
else if (restingCellVoltage >= 35080) { estimatedSoC = 17; }
else if (restingCellVoltage >= 35040) { estimatedSoC = 16; }
else if (restingCellVoltage >= 35000) { estimatedSoC = 15; }
else if (restingCellVoltage >= 34900) { estimatedSoC = 14; }
else if (restingCellVoltage >= 34800) { estimatedSoC = 13; }
else if (restingCellVoltage >= 34700) { estimatedSoC = 12; }
else if (restingCellVoltage >= 34540) { estimatedSoC = 11; }
else if (restingCellVoltage >= CELL_VREST_010_PERCENT_SoC) { estimatedSoC = 10; } //Vmin for long lifetime
else if (restingCellVoltage >= 33900) { estimatedSoC = 9; }
else if (restingCellVoltage >= 33600) { estimatedSoC = 8; }
else if (restingCellVoltage >= 33200) { estimatedSoC = 7; }
else if (restingCellVoltage >= 32800) { estimatedSoC = 6; }
else if (restingCellVoltage >= 32200) { estimatedSoC = 5; }
else if (restingCellVoltage >= 31700) { estimatedSoC = 4; }
else if (restingCellVoltage >= 31000) { estimatedSoC = 3; }
else if (restingCellVoltage >= 30500) { estimatedSoC = 2; }
else if (restingCellVoltage >= 29500) { estimatedSoC = 1; }
else { estimatedSoC = 0; }
return estimatedSoC;
}
@@ -212,116 +212,116 @@ void SoC_updateUsingLatestOpenCircuitVoltage(void)
#elif defined BATTERY_TYPE_47Ah
uint8_t SoC_estimateFromRestingCellVoltage_percent(void)
{
uint16_t restingCellVoltage = LTC68042result_loCellVoltage_get();
uint8_t estimatedSoC = 0;
{
uint16_t restingCellVoltage = LTC68042result_loCellVoltage_get();
uint8_t estimatedSoC = 0;
//~/Honda_Insight_LiBCM/Electronics/Lithium Batteries/47 Ah FoMoCo Modules/Resting SoC Discharge Curve
if (restingCellVoltage >= 42000) { estimatedSoC = 100; }
else if (restingCellVoltage >= 41800) { estimatedSoC = 99; }
else if (restingCellVoltage >= 41600) { estimatedSoC = 98; }
else if (restingCellVoltage >= 41400) { estimatedSoC = 97; }
else if (restingCellVoltage >= 41200) { estimatedSoC = 96; }
else if (restingCellVoltage >= 41000) { estimatedSoC = 95; }
else if (restingCellVoltage >= 40880) { estimatedSoC = 94; }
else if (restingCellVoltage >= 40760) { estimatedSoC = 93; }
else if (restingCellVoltage >= 40640) { estimatedSoC = 92; }
else if (restingCellVoltage >= 40520) { estimatedSoC = 91; }
else if (restingCellVoltage >= 40400) { estimatedSoC = 90; }
else if (restingCellVoltage >= 40260) { estimatedSoC = 89; }
else if (restingCellVoltage >= 40120) { estimatedSoC = 88; }
else if (restingCellVoltage >= 39980) { estimatedSoC = 87; }
else if (restingCellVoltage >= 39840) { estimatedSoC = 86; }
else if (restingCellVoltage >= CELL_VREST_85_PERCENT_SoC) { estimatedSoC = 85; } //max cell voltage for long lifetime
else if (restingCellVoltage >= 39600) { estimatedSoC = 84; }
else if (restingCellVoltage >= 39500) { estimatedSoC = 83; }
else if (restingCellVoltage >= 39400) { estimatedSoC = 82; }
else if (restingCellVoltage >= 39300) { estimatedSoC = 81; }
else if (restingCellVoltage >= 39200) { estimatedSoC = 80; }
else if (restingCellVoltage >= 39100) { estimatedSoC = 79; }
else if (restingCellVoltage >= 39000) { estimatedSoC = 78; }
else if (restingCellVoltage >= 38900) { estimatedSoC = 77; }
else if (restingCellVoltage >= 38800) { estimatedSoC = 76; }
else if (restingCellVoltage >= 38700) { estimatedSoC = 75; }
else if (restingCellVoltage >= 38600) { estimatedSoC = 74; }
else if (restingCellVoltage >= 38500) { estimatedSoC = 73; }
else if (restingCellVoltage >= 38400) { estimatedSoC = 72; }
else if (restingCellVoltage >= 38300) { estimatedSoC = 71; }
else if (restingCellVoltage >= 38200) { estimatedSoC = 70; }
else if (restingCellVoltage >= 38100) { estimatedSoC = 69; }
else if (restingCellVoltage >= 38000) { estimatedSoC = 68; }
else if (restingCellVoltage >= 37900) { estimatedSoC = 67; }
else if (restingCellVoltage >= 37800) { estimatedSoC = 66; }
else if (restingCellVoltage >= 37700) { estimatedSoC = 65; }
else if (restingCellVoltage >= 37580) { estimatedSoC = 64; }
else if (restingCellVoltage >= 37460) { estimatedSoC = 63; }
else if (restingCellVoltage >= 37340) { estimatedSoC = 62; }
else if (restingCellVoltage >= 37220) { estimatedSoC = 61; }
else if (restingCellVoltage >= 37100) { estimatedSoC = 60; }
else if (restingCellVoltage >= 37020) { estimatedSoC = 59; }
else if (restingCellVoltage >= 36940) { estimatedSoC = 58; }
else if (restingCellVoltage >= 36860) { estimatedSoC = 57; }
else if (restingCellVoltage >= 36780) { estimatedSoC = 56; }
else if (restingCellVoltage >= 36770) { estimatedSoC = 55; }
else if (restingCellVoltage >= 36640) { estimatedSoC = 54; }
else if (restingCellVoltage >= 36580) { estimatedSoC = 53; }
else if (restingCellVoltage >= 36520) { estimatedSoC = 52; }
else if (restingCellVoltage >= 36460) { estimatedSoC = 51; }
else if (restingCellVoltage >= 36400) { estimatedSoC = 50; }
else if (restingCellVoltage >= 36360) { estimatedSoC = 49; }
else if (restingCellVoltage >= 36320) { estimatedSoC = 48; }
else if (restingCellVoltage >= 36280) { estimatedSoC = 47; }
else if (restingCellVoltage >= 36240) { estimatedSoC = 46; }
else if (restingCellVoltage >= 36200) { estimatedSoC = 45; }
else if (restingCellVoltage >= 36160) { estimatedSoC = 44; }
else if (restingCellVoltage >= 36120) { estimatedSoC = 43; }
else if (restingCellVoltage >= 36080) { estimatedSoC = 42; }
else if (restingCellVoltage >= 36040) { estimatedSoC = 41; }
else if (restingCellVoltage >= 36000) { estimatedSoC = 40; }
else if (restingCellVoltage >= 35960) { estimatedSoC = 39; }
else if (restingCellVoltage >= 35920) { estimatedSoC = 38; }
else if (restingCellVoltage >= 35880) { estimatedSoC = 37; }
else if (restingCellVoltage >= 35840) { estimatedSoC = 36; }
else if (restingCellVoltage >= 35800) { estimatedSoC = 35; }
else if (restingCellVoltage >= 35760) { estimatedSoC = 34; }
else if (restingCellVoltage >= 35720) { estimatedSoC = 33; }
else if (restingCellVoltage >= 35680) { estimatedSoC = 32; }
else if (restingCellVoltage >= 35640) { estimatedSoC = 31; }
else if (restingCellVoltage >= 35600) { estimatedSoC = 30; }
else if (restingCellVoltage >= 35540) { estimatedSoC = 29; }
else if (restingCellVoltage >= 35480) { estimatedSoC = 28; }
else if (restingCellVoltage >= 35420) { estimatedSoC = 27; }
else if (restingCellVoltage >= 35360) { estimatedSoC = 26; }
else if (restingCellVoltage >= 35300) { estimatedSoC = 25; }
else if (restingCellVoltage >= 35240) { estimatedSoC = 24; }
else if (restingCellVoltage >= 35180) { estimatedSoC = 23; }
else if (restingCellVoltage >= 35120) { estimatedSoC = 22; }
else if (restingCellVoltage >= 35060) { estimatedSoC = 21; }
else if (restingCellVoltage >= 35000) { estimatedSoC = 20; }
else if (restingCellVoltage >= 34880) { estimatedSoC = 19; }
else if (restingCellVoltage >= 34760) { estimatedSoC = 18; }
else if (restingCellVoltage >= 34640) { estimatedSoC = 17; }
else if (restingCellVoltage >= 34520) { estimatedSoC = 16; }
else if (restingCellVoltage >= 34400) { estimatedSoC = 15; }
else if (restingCellVoltage >= 34320) { estimatedSoC = 14; }
else if (restingCellVoltage >= 34240) { estimatedSoC = 13; }
else if (restingCellVoltage >= 34160) { estimatedSoC = 12; }
else if (restingCellVoltage >= 34080) { estimatedSoC = 11; }
else if (restingCellVoltage >= CELL_VREST_10_PERCENT_SoC) { estimatedSoC = 10; } //min cell voltage for long lifetime
else if (restingCellVoltage >= 33900) { estimatedSoC = 9; }
else if (restingCellVoltage >= 33800) { estimatedSoC = 8; }
else if (restingCellVoltage >= 33700) { estimatedSoC = 7; }
else if (restingCellVoltage >= 33600) { estimatedSoC = 6; }
else if (restingCellVoltage >= 33200) { estimatedSoC = 5; }
else if (restingCellVoltage >= 32600) { estimatedSoC = 4; }
else if (restingCellVoltage >= 32000) { estimatedSoC = 3; }
else if (restingCellVoltage >= 31000) { estimatedSoC = 2; }
else if (restingCellVoltage >= 30000) { estimatedSoC = 1; }
else { estimatedSoC = 0; }
//~/Honda_Insight_LiBCM/Electronics/Lithium Batteries/47 Ah FoMoCo Modules/Resting SoC Discharge Curve
if (restingCellVoltage >= CELL_VREST_100_PERCENT_SoC) { estimatedSoC = 100; }
else if (restingCellVoltage >= 41800) { estimatedSoC = 99; }
else if (restingCellVoltage >= 41600) { estimatedSoC = 98; }
else if (restingCellVoltage >= 41400) { estimatedSoC = 97; }
else if (restingCellVoltage >= 41200) { estimatedSoC = 96; }
else if (restingCellVoltage >= 41000) { estimatedSoC = 95; }
else if (restingCellVoltage >= 40880) { estimatedSoC = 94; }
else if (restingCellVoltage >= 40760) { estimatedSoC = 93; }
else if (restingCellVoltage >= 40640) { estimatedSoC = 92; }
else if (restingCellVoltage >= 40520) { estimatedSoC = 91; }
else if (restingCellVoltage >= 40400) { estimatedSoC = 90; }
else if (restingCellVoltage >= 40260) { estimatedSoC = 89; }
else if (restingCellVoltage >= 40120) { estimatedSoC = 88; }
else if (restingCellVoltage >= 39980) { estimatedSoC = 87; }
else if (restingCellVoltage >= 39840) { estimatedSoC = 86; }
else if (restingCellVoltage >= CELL_VREST_085_PERCENT_SoC) { estimatedSoC = 85; } //Vmax for long lifetime
else if (restingCellVoltage >= 39600) { estimatedSoC = 84; }
else if (restingCellVoltage >= 39500) { estimatedSoC = 83; }
else if (restingCellVoltage >= 39400) { estimatedSoC = 82; }
else if (restingCellVoltage >= 39300) { estimatedSoC = 81; }
else if (restingCellVoltage >= 39200) { estimatedSoC = 80; }
else if (restingCellVoltage >= 39100) { estimatedSoC = 79; }
else if (restingCellVoltage >= 39000) { estimatedSoC = 78; }
else if (restingCellVoltage >= 38900) { estimatedSoC = 77; }
else if (restingCellVoltage >= 38800) { estimatedSoC = 76; }
else if (restingCellVoltage >= 38700) { estimatedSoC = 75; }
else if (restingCellVoltage >= 38600) { estimatedSoC = 74; }
else if (restingCellVoltage >= 38500) { estimatedSoC = 73; }
else if (restingCellVoltage >= 38400) { estimatedSoC = 72; }
else if (restingCellVoltage >= 38300) { estimatedSoC = 71; }
else if (restingCellVoltage >= 38200) { estimatedSoC = 70; }
else if (restingCellVoltage >= 38100) { estimatedSoC = 69; }
else if (restingCellVoltage >= 38000) { estimatedSoC = 68; }
else if (restingCellVoltage >= 37900) { estimatedSoC = 67; }
else if (restingCellVoltage >= 37800) { estimatedSoC = 66; }
else if (restingCellVoltage >= 37700) { estimatedSoC = 65; }
else if (restingCellVoltage >= 37580) { estimatedSoC = 64; }
else if (restingCellVoltage >= 37460) { estimatedSoC = 63; }
else if (restingCellVoltage >= 37340) { estimatedSoC = 62; }
else if (restingCellVoltage >= 37220) { estimatedSoC = 61; }
else if (restingCellVoltage >= 37100) { estimatedSoC = 60; }
else if (restingCellVoltage >= 37020) { estimatedSoC = 59; }
else if (restingCellVoltage >= 36940) { estimatedSoC = 58; }
else if (restingCellVoltage >= 36860) { estimatedSoC = 57; }
else if (restingCellVoltage >= 36780) { estimatedSoC = 56; }
else if (restingCellVoltage >= 36770) { estimatedSoC = 55; }
else if (restingCellVoltage >= 36640) { estimatedSoC = 54; }
else if (restingCellVoltage >= 36580) { estimatedSoC = 53; }
else if (restingCellVoltage >= 36520) { estimatedSoC = 52; }
else if (restingCellVoltage >= 36460) { estimatedSoC = 51; }
else if (restingCellVoltage >= 36400) { estimatedSoC = 50; }
else if (restingCellVoltage >= 36360) { estimatedSoC = 49; }
else if (restingCellVoltage >= 36320) { estimatedSoC = 48; }
else if (restingCellVoltage >= 36280) { estimatedSoC = 47; }
else if (restingCellVoltage >= 36240) { estimatedSoC = 46; }
else if (restingCellVoltage >= 36200) { estimatedSoC = 45; }
else if (restingCellVoltage >= 36160) { estimatedSoC = 44; }
else if (restingCellVoltage >= 36120) { estimatedSoC = 43; }
else if (restingCellVoltage >= 36080) { estimatedSoC = 42; }
else if (restingCellVoltage >= 36040) { estimatedSoC = 41; }
else if (restingCellVoltage >= 36000) { estimatedSoC = 40; }
else if (restingCellVoltage >= 35960) { estimatedSoC = 39; }
else if (restingCellVoltage >= 35920) { estimatedSoC = 38; }
else if (restingCellVoltage >= 35880) { estimatedSoC = 37; }
else if (restingCellVoltage >= 35840) { estimatedSoC = 36; }
else if (restingCellVoltage >= 35800) { estimatedSoC = 35; }
else if (restingCellVoltage >= 35760) { estimatedSoC = 34; }
else if (restingCellVoltage >= 35720) { estimatedSoC = 33; }
else if (restingCellVoltage >= 35680) { estimatedSoC = 32; }
else if (restingCellVoltage >= 35640) { estimatedSoC = 31; }
else if (restingCellVoltage >= 35600) { estimatedSoC = 30; }
else if (restingCellVoltage >= 35540) { estimatedSoC = 29; }
else if (restingCellVoltage >= 35480) { estimatedSoC = 28; }
else if (restingCellVoltage >= 35420) { estimatedSoC = 27; }
else if (restingCellVoltage >= 35360) { estimatedSoC = 26; }
else if (restingCellVoltage >= 35300) { estimatedSoC = 25; }
else if (restingCellVoltage >= 35240) { estimatedSoC = 24; }
else if (restingCellVoltage >= 35180) { estimatedSoC = 23; }
else if (restingCellVoltage >= 35120) { estimatedSoC = 22; }
else if (restingCellVoltage >= 35060) { estimatedSoC = 21; }
else if (restingCellVoltage >= 35000) { estimatedSoC = 20; }
else if (restingCellVoltage >= 34880) { estimatedSoC = 19; }
else if (restingCellVoltage >= 34760) { estimatedSoC = 18; }
else if (restingCellVoltage >= 34640) { estimatedSoC = 17; }
else if (restingCellVoltage >= 34520) { estimatedSoC = 16; }
else if (restingCellVoltage >= 34400) { estimatedSoC = 15; }
else if (restingCellVoltage >= 34320) { estimatedSoC = 14; }
else if (restingCellVoltage >= 34240) { estimatedSoC = 13; }
else if (restingCellVoltage >= 34160) { estimatedSoC = 12; }
else if (restingCellVoltage >= 34080) { estimatedSoC = 11; }
else if (restingCellVoltage >= CELL_VREST_010_PERCENT_SoC) { estimatedSoC = 10; } //Vmin for long lifetime
else if (restingCellVoltage >= 33900) { estimatedSoC = 9; }
else if (restingCellVoltage >= 33800) { estimatedSoC = 8; }
else if (restingCellVoltage >= 33700) { estimatedSoC = 7; }
else if (restingCellVoltage >= 33600) { estimatedSoC = 6; }
else if (restingCellVoltage >= 33200) { estimatedSoC = 5; }
else if (restingCellVoltage >= 32600) { estimatedSoC = 4; }
else if (restingCellVoltage >= 32000) { estimatedSoC = 3; }
else if (restingCellVoltage >= 31000) { estimatedSoC = 2; }
else if (restingCellVoltage >= 30000) { estimatedSoC = 1; }
else { estimatedSoC = 0; }
return estimatedSoC;
}
#endif
return estimatedSoC;
}
#endif
/////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -19,13 +19,18 @@
void SoC_handler(void);
#define VCELL_CRITICALLY_OVERCHARGED 43000 //'43000' = 4.3 V
#define VCELL_CRITICALLY_DISCHARGED 28000 //'28000' = 2.8 V
#ifdef BATTERY_TYPE_5AhG3
#define CELL_VREST_85_PERCENT_SoC 40000 //for maximum life, resting cell voltage should remain below 85% SoC
#define CELL_VREST_10_PERCENT_SoC 34200 //for maximum life, resting cell voltage should remain above 10% SoC
#define CELL_VREST_100_PERCENT_SoC 42000
#define CELL_VREST_085_PERCENT_SoC 40000 //for maximum life, resting cell voltage should remain below 85% SoC
#define CELL_VREST_010_PERCENT_SoC 34200 //for maximum life, resting cell voltage should remain above 10% SoC
#define STACK_mAh_NOM 5000 //5 Ah nominal //nominal pack size (0:100% SoC)
#elif defined BATTERY_TYPE_47Ah
#define CELL_VREST_85_PERCENT_SoC 39700
#define CELL_VREST_10_PERCENT_SoC 34000
#define CELL_VREST_100_PERCENT_SoC 42000
#define CELL_VREST_085_PERCENT_SoC 39700
#define CELL_VREST_010_PERCENT_SoC 34000
#define STACK_mAh_NOM 47000
#else
#error (Battery type not specified in config.h)

View File

@@ -53,6 +53,9 @@ void printDebug(void)
Serial.print(F("\n -Has LiBCM limited regen since last cleared?: "));
(eeprom_hasLibcmDisabledRegen_get() == EEPROM_LIBCM_DISABLED_REGEN) ? Serial.print(F("YES")) : Serial.print(F("NO"));
Serial.print(F("\n -Maximum resting cell delta (min is '1000' = 100.0 mV): "));
Serial.print(eeprom_maxCellVoltageDelta_get(), DEC);
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -115,7 +118,6 @@ void USB_userInterface_runTestCode(uint8_t testToRun)
else if (testToRun == 'T') { temperature_measureAndPrintAll(); }
else if (testToRun == 'R') { LTC6804gpio_areAllVoltageReferencesPassing(); }
else if (testToRun == 'W') { batteryHistory_printAll(); }
else if (testToRun == 'E') { eeprom_resetAll_userConfirm(); }
else if (testToRun == 'C')
{
LTC68042cell_acquireAllCellVoltages();
@@ -150,31 +152,32 @@ void(* rebootLiBCM) (void) = 0;//declare reset function at address 0
void printHelp(void)
{
Serial.print(F("\n\nLiBCM commands:"
"\n -'$BOOT': restart LiBCM"
"\n -'$OFF': turn LiBCM off (for testing purposes)"
"\n -'$BOOT' : restart LiBCM"
"\n -'$OFF' : turn LiBCM off (for testing purposes)"
"\n -'$TESTR': run LTC6804 VREF test"
"\n -'$TESTW': battery temp & SoC history"
"\n -'$TESTH': blink heater LED"
"\n -'$TESTC': print cell voltages"
"\n -'$TESTT': print temperatures"
"\n -'$TESTE': EEPROM factory reset"
"\n -'$TEST1'/2/3/4: run temporary debug test code. See 'USB_userInterface_runTestCode()')"
"\n -'$DEBUG': info stored in EEPROM. 'DEBUG=CLR' to restore defaults"
"\n -'$KEYms': delay after keyON before LiBCM starts. 'KEYms=___' to set (0 to 254 ms)"
"\n -'$SoC': battery charge in percent. 'SoC=___' to set (0 to 100%)"
"\n -'$DISP=PWR'/SCI/CELL/TEMP/DBG/OFF: data to stream (power/BAT&METSCI/Vcell/temperature/none)"
"\n -'$RATE=___': USB updates per second (1 to 255 Hz)"
"\n -'$LOOP: LiBCM loop period. '$LOOP=___' to set (1 to 255 ms)"
"\n -'$SCIms': period between BATTSCI frames. '$SCIms=___' to set (0 to 255 ms)"
"\n -'$TRIP': print energy consumption and distance records ('TRIP=CLR' to zero all)"
"\n -'$EPROM': dump EEPROM. '$EPROM=RST' to factory reset"
"\n -'$TEST_': 1/2/3/4: run temporary debug test code. See 'USB_userInterface_runTestCode()')"
"\n -'$DEBUG': info stored in EEPROM. '$DEBUG=CLR' to restore defaults"
"\n -'$KEYms': delay after keyON before LiBCM starts. 'KEYms=_' to set (0 to 254 ms)"
"\n -'$SoC' : battery charge in percent. '$SoC=_' to set (0 to 100%)"
"\n -'$DISP=_: PWR/SCI/CELL/TEMP/DBG/OFF: data to stream"
"\n -'$RATE=_: USB updates per second (1 to 255 Hz)"
"\n -'$LOOP : LiBCM loop period. '$LOOP=_' to set (1 to 255 ms)"
"\n -'$SCIms': period between BATTSCI frames. '$SCIms=_' to set (0 to 255 ms)"
"\n -'$TRIP' : print energy consumption and distance records ('TRIP=CLR' to zero all)"
"\n"
"\nDebug characters:"
"\n -'@': isoSPI error occurred"
"\n -'*': loop period exceeded"
"\n"
"\nTip: Hit up arrow to recall previous commands"
"\n"
/*
"\nFuture LiBCM commands (not presently supported"
"\n -'$DEFAULT' restore all EEPROM values to default"
"\n -'$FAN' display fan status. '$FAN=OFF'/LOW/HI to set."
"\n -'$IHACK' display current hack setting. '$IHACK=00'/20/40/60 to set."
"\n -'$VHACK' display voltage hack setting. '$VHACK=OEM'/ASSISTONLY_VAR/ASSISTONLY_BIN/ALWAYS."
@@ -182,7 +185,6 @@ void printHelp(void)
"\n -'$ASSIST_ON' enable assist until LiBCM resets."
"\n -'$REGEN_OFF' disable regen until LiBCM resets."
"\n -'$REGEN_ON' enable regen until LiBCM resets."
"\n -'BATTmAh' display battery capacity in mAh. 'BATTmAh=____' to set."
"\n -'SoC_MAX' display max allowed SoC. 'SoC_MAX=__' to set."
"\n -'SoC_MIN' display min allowed SoC. 'SoC_MIN=__' to set."
*/
@@ -373,6 +375,19 @@ void USB_userInterface_executeUserInput(void)
}
}
//EPROM
else if ((line[1] == 'E') && (line[2] == 'P') && (line[3] == 'R') && (line[4] == 'O') && (line[5] == 'M'))
{
if ((line[6] == '=') && (line[7] == 'R') && (line[8] == 'S') && (line[9] == 'T'))
{
eeprom_resetAll_userConfirm();
}
else if (line[6] == STRING_TERMINATION_CHARACTER)
{
eeprom_printAll();
}
}
//$DEFAULT
else { Serial.print(F("\nInvalid Entry")); }
}

View File

@@ -39,12 +39,10 @@ bool cellBalance_areCellsBalancing(void) { return cellsAreBalancing; }
/////////////////////////////////////////////////////////////////////////////////////////
//JTS2doLater: Always allow discharge balancing when a cell is overcharged (for safety)
//JTS2doLater: Write keyOff test that measures each cell voltage twice: once with discharge resistor off, and again with resistor on.
// Then verify voltage drop, which means the discharge resistor is turning off and on. If there isn't enough resolution,
// another method would be to wait a few hours for pack voltages to settle, then log all cell voltages an hour apart.
//JTS2doLater: Add per-cell SoC, to allow balancing at any SoC (see icn.net:post#1502833,comment#579)
//balance cells (if needed)
void configureDischargeResistors(void)
{
static uint8_t balanceHysteresis = CELL_BALANCE_TO_WITHIN_COUNTS_TIGHT;
@@ -53,7 +51,7 @@ void configureDischargeResistors(void)
cellsAreBalancing = NO;
if (LTC68042result_hiCellVoltage_get() > CELL_VREST_85_PERCENT_SoC) { cellDischargeVoltageThreshold = CELL_VREST_85_PERCENT_SoC; }
if (LTC68042result_hiCellVoltage_get() > CELL_VREST_085_PERCENT_SoC) { cellDischargeVoltageThreshold = CELL_VREST_085_PERCENT_SoC; }
else { cellDischargeVoltageThreshold = LTC68042result_loCellVoltage_get() + balanceHysteresis; }
//determine which cells to balance
@@ -94,42 +92,81 @@ void disableDischargeResistors(void)
/////////////////////////////////////////////////////////////////////////////////////////
//JTS2doNext: Add "balance really unbalanced pack" code outlined in ic.net post #3876
uint8_t isBalancingAllowed(void)
//balancing criteria for a healthy pack
uint8_t isBalancingPossible(void)
{
//order is important
//external checks
if (key_getSampledState() == KEYSTATE_ON ) { return NO__KEY_IS_ON; }
#ifdef ONLY_BALANCE_CELLS_WHEN_GRID_CHARGER_PLUGGED_IN
if (gpio_isGridChargerPluggedInNow() == NO ) { return NO__CHARGER_UNPLUGGED; }
#else
if ((gpio_isGridChargerPluggedInNow() == NO ) &&
(SoC_getBatteryStateNow_percent() < CELL_BALANCE_MIN_SoC) ) { return NO__SoC_TOO_LOW; }
#endif
//cell voltage checks
if (LTC68042result_hiCellVoltage_get() > CELL_VMAX_REGEN ) { return NO__ATLEASTONECELL_TOO_HIGH; }
if (LTC68042result_loCellVoltage_get() < CELL_VMIN_GRIDCHARGER ) { return NO__ATLEASTONECELL_TOO_LOW; }
//thermal checks
if (temperature_battery_getLatest() > CELL_BALANCE_MAX_TEMP_C) { return NO__BATTERY_IS_HOT; }
//time checks
if (time_isItTimeToPerformKeyOffTasks() == NO ) { return DELAY_DO_NOTHING; }
return YES__BALANCING_ALLOWED;
}
/////////////////////////////////////////////////////////////////////////////////////////
//JTS2doLater: balance majorly imbalanced cells even when grid charger is unplugged
void cellBalance_handler(void)
//balancing criteria for a majorly unbalanced pack
uint8_t isBalancingMandatory(void)
{
static uint8_t isBalancingAllowed_previous = NO__UNINITIALIZED;
uint8_t isBalancingAllowed_now = isBalancingAllowed();
uint16_t cellDeltaV = LTC68042result_deltaCellVoltage_get();
if (isBalancingAllowed_now == YES__BALANCING_ALLOWED)
{
if (time_isItTimeToPerformKeyOffTasks() == YES) { configureDischargeResistors(); }
}
else if (isBalancingAllowed_previous == YES__BALANCING_ALLOWED) { disableDischargeResistors(); }
if (cellDeltaV < CELL_MAJOR_IMBALANCE_DELTA) { return NO__BALANCING_NOT_REQUESTED; }
isBalancingAllowed_previous = isBalancingAllowed_now;
//if we get here, pack is majorly unbalanced
//keyState doesn't matter
//grid charger state doesn't matter
//pack temperature doesn't matter
if (LTC68042result_loCellVoltage_get() < VCELL_CRITICALLY_DISCHARGED ) { return NO__ATLEASTONECELL_TOO_LOW; }
if (adc_getLatestSpoofedCurrent_deciAmps() > CELL_IMAX_MAJOR_IMBALANCE_DECIAMPS) { return NO__PACK_CURRENT_TOO_HIGH; }
if (adc_getLatestSpoofedCurrent_deciAmps() < -CELL_IMAX_MAJOR_IMBALANCE_DECIAMPS) { return NO__PACK_CURRENT_TOO_HIGH; }
if (cellDeltaV > eeprom_maxCellVoltageDelta_get()) { eeprom_maxCellVoltageDelta_set(cellDeltaV); }
return YES__BALANCING_ALLOWED;
}
/////////////////////////////////////////////////////////////////////////////////////////
uint8_t isEntirePackOvercharged(void)
{
if ((LTC68042result_hiCellVoltage_get() > CELL_VREST_100_PERCENT_SoC ) &&
(LTC68042result_loCellVoltage_get() > CELL_VMAX_GRIDCHARGER ) ) { return YES__BALANCING_ALLOWED; }
return NO__BALANCING_NOT_REQUESTED;
}
/////////////////////////////////////////////////////////////////////////////////////////
uint8_t getBalanceRequest(void)
{
if (isBalancingMandatory() == YES__BALANCING_ALLOWED) { return YES__BALANCING_ALLOWED; }
if (isEntirePackOvercharged() == YES__BALANCING_ALLOWED) { return YES__BALANCING_ALLOWED; }
return isBalancingPossible();
}
/////////////////////////////////////////////////////////////////////////////////////////
void cellBalance_handler(void)
{
if (LTC68042result_wasDataProcessedThisLoop_get() == NO) { return; } //wait for new Vcell data
static uint8_t isBalancingAllowed_previous = NO__UNINITIALIZED;
uint8_t isBalancingAllowed_now = getBalanceRequest();
if (isBalancingAllowed_now == DELAY_DO_NOTHING ) { return; }
else if (isBalancingAllowed_now == YES__BALANCING_ALLOWED) { configureDischargeResistors(); }
else if (isBalancingAllowed_previous == YES__BALANCING_ALLOWED) { disableDischargeResistors(); }
isBalancingAllowed_previous = isBalancingAllowed_now; //not updated if 'DELAY_DO_NOTHING'
}
/////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -7,7 +7,14 @@
#define BALANCING_DISABLED 0
#define BALANCING_ALLOWED 1
#define YES__BALANCING_ALLOWED YES__CHARGING_ALLOWED //balancing code reusing grid charging constants
#define CELL_MAJOR_IMBALANCE_DELTA 1000 // '1000' = 100 mV
#define CELL_IMAX_MAJOR_IMBALANCE_DECIAMPS 90 // '90' = 9.0 A
#define CELL_BALANCE_TO_WITHIN_COUNTS_LOOSE 32 // '32' = 3.2 mV //CANNOT exceed 255 counts (25.5 mV)
#define CELL_BALANCE_TO_WITHIN_COUNTS_TIGHT 22 // '22' = 2.2 mV //ADC uncertainty: 2.2 mV //MUST be less than CELL_BALANCE_TO_WITHIN_COUNTS_LOOSE
//balancing constants reuse grid charging constants
#define YES__BALANCING_ALLOWED YES__CHARGING_ALLOWED
#define NO__BALANCING_NOT_REQUESTED NO__CHARGING_NOT_REQUESTED
bool cellBalance_areCellsBalancing(void);

View File

@@ -25,6 +25,7 @@ const uint16_t EEPROM_ADDRESS_BATTSCI_ASSIST = 0x010; //EEPROM range is 0x0
const uint16_t EEPROM_ADDRESS_KEYON_DELAY = 0x011; //EEPROM range is 0x011 ( 1B)
const uint16_t EEPROM_ADDRESS_NEXT_Wh_RECORD = 0x012; //EEPROM range is 0x012 ( 1B)
const uint16_t EEPROM_ADDRESS_COMPILE_TIME = 0x013; //EEPROM range is 0x013:0x01B ( 9B)
const uint16_t EEPROM_ADDRESS_MAX_VCELL_DELTA = 0x01C; //EEPROM range is 0x01C:0x01D ( 2B)
//this EEPROM space still available
//The following addresses start from end of EEPROM space and work backwards to beginning
const uint16_t EEPROM_ADDRESS_BATT_HISTORY = EEPROM_LAST_USABLE_ADDRESS - NUM_BYTES_BATTERY_HISTORY; //0xA57:0xF9F (1536B)
@@ -189,41 +190,71 @@ void eeprom_keyOffCheckForExpiredFirmware(void)
/////////////////////////////////////////////////////////////////////////////////////////
uint8_t eeprom_hasLibcmDisabledAssist_get(void) { return EEPROM.read(EEPROM_ADDRESS_BATTSCI_ASSIST); }
uint8_t eeprom_hasLibcmDisabledAssist_get(void) { return EEPROM.read(EEPROM_ADDRESS_BATTSCI_ASSIST); }
void eeprom_hasLibcmDisabledAssist_set(uint8_t wasAssistLimited) { EEPROM.update(EEPROM_ADDRESS_BATTSCI_ASSIST, wasAssistLimited); }
uint8_t eeprom_hasLibcmDisabledRegen_get(void) { return EEPROM.read(EEPROM_ADDRESS_BATTSCI_REGEN); }
void eeprom_hasLibcmDisabledRegen_set(uint8_t wasRegenLimited) { EEPROM.update(EEPROM_ADDRESS_BATTSCI_REGEN, wasRegenLimited); }
uint8_t eeprom_hasLibcmDisabledRegen_get(void) { return EEPROM.read(EEPROM_ADDRESS_BATTSCI_REGEN); }
void eeprom_hasLibcmDisabledRegen_set(uint8_t wasRegenLimited) { EEPROM.update(EEPROM_ADDRESS_BATTSCI_REGEN, wasRegenLimited); }
uint16_t eeprom_maxCellVoltageDelta_get(void) { return readFromEEPROM_uint16(EEPROM_ADDRESS_MAX_VCELL_DELTA); }
void eeprom_maxCellVoltageDelta_set(uint16_t newMax) { writeToEEPROM_uint16(EEPROM_ADDRESS_MAX_VCELL_DELTA, newMax); }
uint8_t eeprom_delayKeyON_ms_get(void) { return EEPROM.read(EEPROM_ADDRESS_KEYON_DELAY); }
void eeprom_delayKeyON_ms_set(uint8_t delay_ms) { EEPROM.update(EEPROM_ADDRESS_KEYON_DELAY, delay_ms); }
/////////////////////////////////////////////////////////////////////////////////////////
uint8_t eeprom_delayKeyON_ms_get(void) { return EEPROM.read(EEPROM_ADDRESS_KEYON_DELAY); }
void eeprom_delayKeyON_ms_set(uint8_t delay_ms) { EEPROM.update(EEPROM_ADDRESS_KEYON_DELAY, delay_ms); }
void printMessage_RestoringEEPROM(void) { Serial.print(F("\nRestoring EEPROM value: ")); }
/////////////////////////////////////////////////////////////////////////////////////////
void eeprom_verifyDataValid(void)
{
//verify all runtime-configurable data stored in EEPROM is valid. If not, load default value(s)
if ( !( (eeprom_hasLibcmDisabledRegen_get() == EEPROM_LIBCM_DISABLED_REGEN) || (eeprom_hasLibcmDisabledRegen_get() == EEPROM_REGEN_NEVER_LIMITED) ) )
if ( !((eeprom_hasLibcmDisabledRegen_get() == EEPROM_LIBCM_DISABLED_REGEN) ||
(eeprom_hasLibcmDisabledRegen_get() == EEPROM_REGEN_NEVER_LIMITED ) ) )
{
//invalid data in EEPROM
Serial.print(F("\nRestoring EEPROM value: EEPROM_LIBCM_DISABLED_REGEN"));
printMessage_RestoringEEPROM();
Serial.print(F("LIBCM_DISABLED_REGEN"));
eeprom_hasLibcmDisabledRegen_set(EEPROM_REGEN_NEVER_LIMITED);
}
if ( !( (eeprom_hasLibcmDisabledAssist_get() == EEPROM_LIBCM_DISABLED_ASSIST) || (eeprom_hasLibcmDisabledAssist_get() == EEPROM_ASSIST_NEVER_LIMITED) ) )
if ( !((eeprom_hasLibcmDisabledAssist_get() == EEPROM_LIBCM_DISABLED_ASSIST) ||
(eeprom_hasLibcmDisabledAssist_get() == EEPROM_ASSIST_NEVER_LIMITED ) ) )
{
//invalid data in EEPROM
Serial.print(F("\nRestoring EEPROM value: EEPROM_LIBCM_DISABLED_ASSIST"));
printMessage_RestoringEEPROM();
Serial.print(F("LIBCM_DISABLED_ASSIST"));
eeprom_hasLibcmDisabledAssist_set(EEPROM_ASSIST_NEVER_LIMITED);
}
if (eeprom_delayKeyON_ms_get() == EEPROM_ADDRESS_FACTORY_DEFAULT_VALUE)
if (eeprom_delayKeyON_ms_get() == EEPROM_ADDRESS_FACTORY_DEFAULT_VALUE_8b)
{
Serial.print(F("\nRestoring EEPROM value: EEPROM_ADDRESS_KEYON_DELAY"));
printMessage_RestoringEEPROM();
Serial.print(F("KEYON_DELAY"));
eeprom_delayKeyON_ms_set(0);
}
if (eeprom_maxCellVoltageDelta_get() == EEPROM_ADDRESS_FACTORY_DEFAULT_VALUE_16b)
{
printMessage_RestoringEEPROM();
Serial.print(F("IMBALANCE_DELTA"));
eeprom_maxCellVoltageDelta_set(CELL_MAJOR_IMBALANCE_DELTA);
}
if (EEPROM.read(EEPROM_ADDRESS_BATT_HISTORY_UNINIT) == EEPROM_ADDRESS_FACTORY_DEFAULT_VALUE_8b)
{
eeprom_batteryHistory_reset();
EEPROM.update(EEPROM_ADDRESS_BATT_HISTORY_UNINIT, EEPROM_ADDRESS_FORMATTED_VALUE);
}
if (EEPROM.read(EEPROM_ADDRESS_Wh_RECORDS_UNINIT) == EEPROM_ADDRESS_FACTORY_DEFAULT_VALUE_8b)
{
eeprom_wattHourHistory_reset();
EEPROM.update(EEPROM_ADDRESS_Wh_RECORDS_UNINIT, EEPROM_ADDRESS_FORMATTED_VALUE);
EEPROM.update(EEPROM_ADDRESS_NEXT_Wh_RECORD, EEPROM_ADDRESS_FORMATTED_VALUE);
}
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -232,6 +263,7 @@ void eeprom_resetDebugValues(void)
{
eeprom_hasLibcmDisabledRegen_set(EEPROM_REGEN_NEVER_LIMITED);
eeprom_hasLibcmDisabledAssist_set(EEPROM_ASSIST_NEVER_LIMITED);
eeprom_maxCellVoltageDelta_set(CELL_MAJOR_IMBALANCE_DELTA);
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -266,20 +298,18 @@ void eeprom_batteryHistory_incrementValue(uint8_t indexTemperature, uint8_t inde
/////////////////////////////////////////////////////////////////////////////////////////
void eeprom_eraseRange(uint16_t minAddress, uint16_t maxAddress, uint8_t valueToWrite)
{
Serial.print('\n');
{
for (uint16_t address = minAddress; address <= maxAddress; address++)
{
EEPROM.update(address, valueToWrite);
Serial.print('.');
if ((address & 0b01111111) == 0) //if divisible by 128
{
wdt_reset();
Serial.print('\n');
}
EEPROM.update(address, valueToWrite);
Serial.print('.');
}
}
@@ -388,7 +418,7 @@ void eeprom_resetAll(void)
Serial.print(F("\nEEPROM factory reset"));
eeprom_eraseRange(minAddress, maxAddress, EEPROM_ADDRESS_FACTORY_DEFAULT_VALUE);
eeprom_eraseRange(minAddress, maxAddress, EEPROM_ADDRESS_FACTORY_DEFAULT_VALUE_8b);
Serial.print(F("\nDone. Rebooting."));
@@ -412,23 +442,36 @@ void eeprom_resetAll_userConfirm(void)
/////////////////////////////////////////////////////////////////////////////////////////
void eeprom_begin(void)
void eeprom_printAll(void)
{
eeprom_verifyDataValid();
Serial.print(F("\n\nDumping EEPROM"));
if (EEPROM.read(EEPROM_ADDRESS_BATT_HISTORY_UNINIT) == EEPROM_ADDRESS_FACTORY_DEFAULT_VALUE)
for(uint16_t address = 0; address <= EEPROM_LAST_USABLE_ADDRESS; address++)
{
eeprom_batteryHistory_reset();
EEPROM.update(EEPROM_ADDRESS_BATT_HISTORY_UNINIT, EEPROM_ADDRESS_FORMATTED_VALUE);
}
if ((address & 0b00001111) == 0) //if divisible by 16
{
wdt_reset();
Serial.print('\n');
Serial.print(F("0x"));
if (address <= 0xF ) { Serial.print('0'); }
if (address <= 0xFF) { Serial.print('0'); }
Serial.print(address, HEX);
Serial.print(F(": "));
}
if (EEPROM.read(EEPROM_ADDRESS_Wh_RECORDS_UNINIT) == EEPROM_ADDRESS_FACTORY_DEFAULT_VALUE)
{
eeprom_wattHourHistory_reset();
EEPROM.update(EEPROM_ADDRESS_Wh_RECORDS_UNINIT, EEPROM_ADDRESS_FORMATTED_VALUE);
EEPROM.update(EEPROM_ADDRESS_NEXT_Wh_RECORD, EEPROM_ADDRESS_FORMATTED_VALUE);
}
uint8_t data = EEPROM.read(address);
if (data <= 0xF) { Serial.print('0'); }
Serial.print(data, HEX);
Serial.print(',');
}
}
/////////////////////////////////////////////////////////////////////////////////////////
void eeprom_begin(void)
{
eeprom_verifyDataValid();
}
/////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -9,8 +9,9 @@
#define EEPROM_LIBCM_DISABLED_ASSIST 0xCC
#define EEPROM_ASSIST_NEVER_LIMITED 0x33
#define EEPROM_ADDRESS_FACTORY_DEFAULT_VALUE 0xFF
#define EEPROM_ADDRESS_FORMATTED_VALUE 0x00
#define EEPROM_ADDRESS_FACTORY_DEFAULT_VALUE_16b 0xFFFF
#define EEPROM_ADDRESS_FACTORY_DEFAULT_VALUE_8b 0xFF
#define EEPROM_ADDRESS_FORMATTED_VALUE 0x00
#define BYTES_IN_DATE 12 //JTS2doLater: Is date 11 bytes or 12?
#define BYTES_IN_TIME 9 //JTS2doLater: Is time 9 bytes or 8?
@@ -39,6 +40,9 @@
uint8_t eeprom_hasLibcmDisabledRegen_get(void);
void eeprom_hasLibcmDisabledRegen_set(uint8_t);
uint16_t eeprom_maxCellVoltageDelta_get(void);
void eeprom_maxCellVoltageDelta_set(uint16_t);
uint8_t eeprom_delayKeyON_ms_get(void);
void eeprom_delayKeyON_ms_set(uint8_t);
@@ -63,4 +67,6 @@
void writeToEEPROM_uint16(uint16_t startAddress, uint16_t value);
void eeprom_printAll(void);
#endif

View File

@@ -54,7 +54,7 @@ uint8_t gridCharger_isAllowedNow(void)
if (gpio_isGridChargerPluggedInNow() == NO ) { return NO__CHARGER_UNPLUGGED; }
if (key_getSampledState() == KEYSTATE_ON ) { return NO__KEY_IS_ON; }
//cell voltage checks
if (LTC68042result_hiCellVoltage_get() > CELL_VREST_85_PERCENT_SoC ) { return NO__ATLEASTONECELL_TOO_HIGH; }
if (LTC68042result_hiCellVoltage_get() > CELL_VREST_085_PERCENT_SoC ) { return NO__ATLEASTONECELL_TOO_HIGH; }
if (LTC68042result_loCellVoltage_get() < CELL_VMIN_GRIDCHARGER ) { return NO__ATLEASTONECELL_TOO_LOW; }
if (LTC68042result_hiCellVoltage_get() > CELL_VMAX_GRIDCHARGER ) { return NO__ATLEASTONECELL_FULL; }
if (LTC68042result_hiCellVoltage_get() > determineMaxAllowedCellVoltage() ) { return NO__CELL_VOLTAGE_HYSTERESIS; }

View File

@@ -6,8 +6,9 @@
#define VCELL_HYSTERESIS 150 // '150' = 15 mV //prevents rapid grid charger on/off toggling when first cell is full
#define YES__CHARGING_ALLOWED 0b01111111 //if charging allowed, first three bits are '011'
#define NO__UNINITIALIZED 0b10000000 //if charging disabled, first three bits are '100' //safety feature in case a single bit flips
#define YES__CHARGING_ALLOWED 0b01111111 //first three bits are '011' for 'YES__'
#define DELAY_DO_NOTHING 0b00111110 //first three bits are '001' for 'DELAY'
#define NO__UNINITIALIZED 0b10000000 //first three bits are '100' for 'NO__' //safety feature in case a single bit flips
#define NO__CHARGER_IS_HOT 0b10000001
#define NO__BATTERY_IS_COLD 0b10000010
#define NO__BATTERY_IS_HOT 0b10000011
@@ -15,7 +16,7 @@
#define NO__TEMP_UNPLUGGED_GRID 0b10000101
#define NO__TEMP_UNPLUGGED_INTAKE 0b10000110
#define NO__TEMP_EXHAUST_IS_HOT 0b10000111
#define NO__ATLEASTONECELL_TOO_HIGH 0b10001000 //JTS2doLater: Allow charging if highest cell below 4.3000 when charger plugged in
#define NO__ATLEASTONECELL_TOO_HIGH 0b10001000
#define NO__ATLEASTONECELL_FULL 0b10001001
#define NO__ATLEASTONECELL_TOO_LOW 0b10001010
#define NO__JUST_PLUGGED_IN 0b10001011
@@ -25,10 +26,13 @@
#define NO__CELL_VOLTAGE_HYSTERESIS 0b10001111
#define NO__CHARGER_UNPLUGGED 0b10010000
#define NO__SoC_TOO_LOW 0b10010001
#define NO__PACK_CURRENT_TOO_HIGH 0b10010010
//place other NO__ conditions here
#define NO__CHARGING_NOT_REQUESTED 0b10011111
#define DISABLE_GRIDCHARGING_ABOVE_CHARGER_TEMP_C 60
#define DISABLE_GRIDCHARGING_BELOW_BATTERY_TEMP_C -25
#define DISABLE_GRIDCHARGING_ABOVE_BATTERY_TEMP_C 40
#define DISABLE_GRIDCHARGING_ABOVE_BATTERY_TEMP_C 43
#define DISABLE_GRIDCHARGING_ABOVE_INTAKE_TEMP_C 45
#define DISABLE_GRIDCHARGING_ABOVE_EXHAUST_TEMP_C 50

View File

@@ -398,7 +398,7 @@ bool lcd_printCellVoltage_delta(void)
static uint16_t deltaVoltage_onScreen = 0;
uint16_t deltaVoltage_LTC6804 = LTC68042result_hiCellVoltage_get() - LTC68042result_loCellVoltage_get();
uint16_t deltaVoltage_LTC6804 = LTC68042result_deltaCellVoltage_get();
if (deltaVoltage_onScreen != deltaVoltage_LTC6804)
{