Original project changes: BMS - Add Function to resize BMS Temperatures

This commit is contained in:
Carsten Schmiemann 2022-11-01 15:02:18 +01:00
parent 54ab5fa818
commit cf9242d798
2 changed files with 157 additions and 58 deletions

View File

@ -273,14 +273,6 @@ typedef struct
uint32_t lastused; // Timestamp of last channel access uint32_t lastused; // Timestamp of last channel access
} vwtp_channel_t; } vwtp_channel_t;
enum class OvmsStatus : short {
OK = 0,
Warn = 1,
Alert = 2
};
inline bool operator<(OvmsStatus lhs, OvmsStatus rhs) {
return static_cast<short>(lhs) < static_cast<short>(rhs);
}
class OvmsVehicle : public InternalRamAllocated class OvmsVehicle : public InternalRamAllocated
{ {
@ -639,7 +631,7 @@ class OvmsVehicle : public InternalRamAllocated
float* m_bms_vmins; // BMS minimum voltages seen (since reset) float* m_bms_vmins; // BMS minimum voltages seen (since reset)
float* m_bms_vmaxs; // BMS maximum voltages seen (since reset) float* m_bms_vmaxs; // BMS maximum voltages seen (since reset)
float* m_bms_vdevmaxs; // BMS maximum voltage deviations seen (since reset) float* m_bms_vdevmaxs; // BMS maximum voltage deviations seen (since reset)
OvmsStatus* m_bms_valerts; // BMS voltage deviation alerts (since reset) short* m_bms_valerts; // BMS voltage deviation alerts (since reset)
int m_bms_valerts_new; // BMS new voltage alerts since last notification int m_bms_valerts_new; // BMS new voltage alerts since last notification
int m_bms_vstddev_cnt; // BMS internal stddev counter int m_bms_vstddev_cnt; // BMS internal stddev counter
float m_bms_vstddev_avg; // BMS internal stddev average float m_bms_vstddev_avg; // BMS internal stddev average
@ -648,7 +640,7 @@ class OvmsVehicle : public InternalRamAllocated
float* m_bms_tmins; // BMS minimum temperatures seen (since reset) float* m_bms_tmins; // BMS minimum temperatures seen (since reset)
float* m_bms_tmaxs; // BMS maximum temperatures seen (since reset) float* m_bms_tmaxs; // BMS maximum temperatures seen (since reset)
float* m_bms_tdevmaxs; // BMS maximum temperature deviations seen (since reset) float* m_bms_tdevmaxs; // BMS maximum temperature deviations seen (since reset)
OvmsStatus* m_bms_talerts; // BMS temperature deviation alerts (since reset) short* m_bms_talerts; // BMS temperature deviation alerts (since reset)
int m_bms_talerts_new; // BMS new temperature alerts since last notification int m_bms_talerts_new; // BMS new temperature alerts since last notification
bool m_bms_has_temperatures; // True if BMS has a complete set of temperature values bool m_bms_has_temperatures; // True if BMS has a complete set of temperature values
std::vector<bool> m_bms_bitset_v; // BMS tracking: true if corresponding voltage set std::vector<bool> m_bms_bitset_v; // BMS tracking: true if corresponding voltage set
@ -696,6 +688,8 @@ class OvmsVehicle : public InternalRamAllocated
void BmsResetCellStats(); void BmsResetCellStats();
virtual void BmsStatus(int verbosity, OvmsWriter* writer); virtual void BmsStatus(int verbosity, OvmsWriter* writer);
virtual bool FormatBmsAlerts(int verbosity, OvmsWriter* writer, bool show_warnings); virtual bool FormatBmsAlerts(int verbosity, OvmsWriter* writer, bool show_warnings);
bool BmsCheckChangeCellArrangementVoltage(int readings, int readingspermodule = 0);
bool BmsCheckChangeCellArrangementTemperature(int readings, int readingspermodule = 0);
}; };
template<typename Type> OvmsVehicle* CreateVehicle() template<typename Type> OvmsVehicle* CreateVehicle()

View File

@ -60,7 +60,7 @@ void OvmsVehicle::BmsSetCellArrangementVoltage(int readings, int readingspermodu
if (m_bms_vdevmaxs != NULL) delete m_bms_vdevmaxs; if (m_bms_vdevmaxs != NULL) delete m_bms_vdevmaxs;
m_bms_vdevmaxs = new float[readings]; m_bms_vdevmaxs = new float[readings];
if (m_bms_valerts != NULL) delete m_bms_valerts; if (m_bms_valerts != NULL) delete m_bms_valerts;
m_bms_valerts = new OvmsStatus[readings]; m_bms_valerts = new short[readings];
m_bms_valerts_new = 0; m_bms_valerts_new = 0;
m_bms_bitset_v.clear(); m_bms_bitset_v.clear();
@ -72,6 +72,129 @@ void OvmsVehicle::BmsSetCellArrangementVoltage(int readings, int readingspermodu
BmsResetCellVoltages(true); BmsResetCellVoltages(true);
} }
// Internal entry for changing cell arrangements.
struct reading_entry_t
{
int cell_no;
float entry;
};
/**
* Changes the cell arrangement for Voltage, if needs be restoring any readings that were there.
* Really should only do work the first time it is called.. as for any one car, the number of readings
* should be consistent.
* @return true If the cell arrangement was changed.
*/
bool OvmsVehicle::BmsCheckChangeCellArrangementVoltage(int readings, int readingspermodule /*=0*/)
{
bool res = false;
if (readingspermodule <= 0)
{
// Passing in 0 will leave the readings per module unchanged.
readingspermodule = m_bms_readingspermodule_v;
}
if (readings != m_bms_readings_v)
{
res = true;
if (m_bms_bitset_cv == 0)
{
BmsSetCellArrangementVoltage(readings, readingspermodule);
}
else
{
// Store (potentially) sparse readings into a vector.
std::vector<reading_entry_t> cells;
// At most we will need the number of voltages set in the bitset.
cells.reserve(m_bms_bitset_cv);
reading_entry_t reading;
int maxv = readings;
if (m_bms_readings_v < maxv)
{
maxv = m_bms_readings_v;
}
for (int i = 0; i< maxv; ++i)
{
if (m_bms_bitset_v[i])
{
reading.cell_no = i;
reading.entry = m_bms_voltages[i];
cells.insert(cells.end(),reading);
}
}
BmsSetCellArrangementVoltage(readings, readingspermodule);
for ( std::vector<reading_entry_t>::iterator iter = cells.begin(); iter != cells.end(); ++iter)
{
BmsSetCellVoltage(iter->cell_no, iter->entry);
}
}
}
else if (readingspermodule != m_bms_readingspermodule_v)
{
// This only changes the read-out.
m_bms_readingspermodule_v = readingspermodule;
res = true;
}
return res;
}
/**
* Changes the cell arrangement for Temperature, if needs be restoring any readings that were there.
* Really should only do work the first time it is called.. as for any one car, the number of readings
* should be consistent.
* @return true If the cell arrangement was changed.
*/
bool OvmsVehicle::BmsCheckChangeCellArrangementTemperature(int readings, int readingspermodule /*=0*/)
{
bool res = false;
if (readingspermodule <= 0)
{
// Passing in 0 will leave the readings per module unchanged.
readingspermodule = m_bms_readingspermodule_t;
}
if (readings != m_bms_readings_t)
{
res = true;
if (m_bms_bitset_ct == 0)
{
BmsSetCellArrangementTemperature(readings, readingspermodule);
}
else
{
// Store (potentially) sparse readings into a vector.
std::vector<reading_entry_t> cells;
// At most we will need the number of Temperatures set in the bitset.
cells.reserve(m_bms_bitset_ct);
reading_entry_t reading;
int maxv = readings;
if (m_bms_readings_t < maxv)
{
maxv = m_bms_readings_t;
}
for (int i = 0; i< maxv; ++i)
{
if (m_bms_bitset_t[i])
{
reading.cell_no = i;
reading.entry = m_bms_temperatures[i];
cells.insert(cells.end(),reading);
}
}
BmsSetCellArrangementTemperature(readings, readingspermodule);
for ( std::vector<reading_entry_t>::iterator iter = cells.begin(); iter != cells.end(); ++iter)
{
BmsSetCellTemperature(iter->cell_no, iter->entry);
}
}
}
else if (readingspermodule != m_bms_readingspermodule_t)
{
// This only changes the read-out.
m_bms_readingspermodule_t = readingspermodule;
res = true;
}
return res;
}
void OvmsVehicle::BmsSetCellArrangementTemperature(int readings, int readingspermodule) void OvmsVehicle::BmsSetCellArrangementTemperature(int readings, int readingspermodule)
{ {
if (m_bms_temperatures != NULL) delete m_bms_temperatures; if (m_bms_temperatures != NULL) delete m_bms_temperatures;
@ -83,7 +206,7 @@ void OvmsVehicle::BmsSetCellArrangementTemperature(int readings, int readingsper
if (m_bms_tdevmaxs != NULL) delete m_bms_tdevmaxs; if (m_bms_tdevmaxs != NULL) delete m_bms_tdevmaxs;
m_bms_tdevmaxs = new float[readings]; m_bms_tdevmaxs = new float[readings];
if (m_bms_talerts != NULL) delete m_bms_talerts; if (m_bms_talerts != NULL) delete m_bms_talerts;
m_bms_talerts = new OvmsStatus[readings]; m_bms_talerts = new short[readings];
m_bms_talerts_new = 0; m_bms_talerts_new = 0;
m_bms_bitset_t.clear(); m_bms_bitset_t.clear();
@ -245,20 +368,20 @@ void OvmsVehicle::BmsSetCellVoltage(int index, float value)
dev = ROUNDPREC(m_bms_voltages[i] - avg, 5); dev = ROUNDPREC(m_bms_voltages[i] - avg, 5);
if (ABS(dev) > ABS(m_bms_vdevmaxs[i])) if (ABS(dev) > ABS(m_bms_vdevmaxs[i]))
m_bms_vdevmaxs[i] = dev; m_bms_vdevmaxs[i] = dev;
if (ABS(dev) >= stddev + thr_alert && m_bms_valerts[i] <= OvmsStatus::Warn) if (ABS(dev) >= stddev + thr_alert && m_bms_valerts[i] < 2)
{ {
m_bms_valerts[i] = OvmsStatus::Alert; m_bms_valerts[i] = 2;
m_bms_valerts_new++; // trigger notification m_bms_valerts_new++; // trigger notification
} }
else if (ABS(dev) >= stddev + thr_warn && m_bms_valerts[i] < OvmsStatus::Warn) else if (ABS(dev) >= stddev + thr_warn && m_bms_valerts[i] < 1)
m_bms_valerts[i] = OvmsStatus::Warn; m_bms_valerts[i] = 1;
} }
// Publish deviation maximums & alerts: // Publish deviation maximums & alerts:
if (stddev > StandardMetrics.ms_v_bat_pack_vstddev_max->AsFloat()) if (stddev > StandardMetrics.ms_v_bat_pack_vstddev_max->AsFloat())
StandardMetrics.ms_v_bat_pack_vstddev_max->SetValue(stddev); StandardMetrics.ms_v_bat_pack_vstddev_max->SetValue(stddev);
StandardMetrics.ms_v_bat_cell_vdevmax->SetElemValues(0, m_bms_readings_v, m_bms_vdevmaxs); StandardMetrics.ms_v_bat_cell_vdevmax->SetElemValues(0, m_bms_readings_v, m_bms_vdevmaxs);
StandardMetrics.ms_v_bat_cell_valert->SetElemValues(0, m_bms_readings_v, (short *)m_bms_valerts); StandardMetrics.ms_v_bat_cell_valert->SetElemValues(0, m_bms_readings_v, m_bms_valerts);
} }
// complete: // complete:
@ -319,13 +442,13 @@ void OvmsVehicle::BmsSetCellTemperature(int index, float value)
dev = ROUNDPREC(m_bms_temperatures[i] - avg, 2); dev = ROUNDPREC(m_bms_temperatures[i] - avg, 2);
if (ABS(dev) > ABS(m_bms_tdevmaxs[i])) if (ABS(dev) > ABS(m_bms_tdevmaxs[i]))
m_bms_tdevmaxs[i] = dev; m_bms_tdevmaxs[i] = dev;
if (ABS(dev) >= stddev + thr_alert && m_bms_talerts[i] < OvmsStatus::Alert) if (ABS(dev) >= stddev + thr_alert && m_bms_talerts[i] < 2)
{ {
m_bms_talerts[i] = OvmsStatus::Alert; m_bms_talerts[i] = 2;
m_bms_talerts_new++; // trigger notification m_bms_talerts_new++; // trigger notification
} }
else if (ABS(dev) >= stddev + thr_warn && m_bms_valerts[i] < OvmsStatus::Warn) else if (ABS(dev) >= stddev + thr_warn && m_bms_valerts[i] < 1)
m_bms_talerts[i] = OvmsStatus::Warn; m_bms_talerts[i] = 1;
} }
// publish to metrics: // publish to metrics:
@ -341,7 +464,7 @@ void OvmsVehicle::BmsSetCellTemperature(int index, float value)
StandardMetrics.ms_v_bat_cell_tmin->SetElemValues(0, m_bms_readings_t, m_bms_tmins); StandardMetrics.ms_v_bat_cell_tmin->SetElemValues(0, m_bms_readings_t, m_bms_tmins);
StandardMetrics.ms_v_bat_cell_tmax->SetElemValues(0, m_bms_readings_t, m_bms_tmaxs); StandardMetrics.ms_v_bat_cell_tmax->SetElemValues(0, m_bms_readings_t, m_bms_tmaxs);
StandardMetrics.ms_v_bat_cell_tdevmax->SetElemValues(0, m_bms_readings_t, m_bms_tdevmaxs); StandardMetrics.ms_v_bat_cell_tdevmax->SetElemValues(0, m_bms_readings_t, m_bms_tdevmaxs);
StandardMetrics.ms_v_bat_cell_talert->SetElemValues(0, m_bms_readings_t, (short *) m_bms_talerts); StandardMetrics.ms_v_bat_cell_talert->SetElemValues(0, m_bms_readings_t, m_bms_talerts);
// complete: // complete:
m_bms_has_temperatures = true; m_bms_has_temperatures = true;
@ -382,7 +505,7 @@ void OvmsVehicle::BmsResetCellVoltages(bool full /*=false*/)
m_bms_vmins[k] = 0; m_bms_vmins[k] = 0;
m_bms_vmaxs[k] = 0; m_bms_vmaxs[k] = 0;
m_bms_vdevmaxs[k] = 0; m_bms_vdevmaxs[k] = 0;
m_bms_valerts[k] = OvmsStatus::OK; m_bms_valerts[k] = 0;
} }
m_bms_valerts_new = 0; m_bms_valerts_new = 0;
m_bms_vstddev_cnt = 0; m_bms_vstddev_cnt = 0;
@ -409,7 +532,7 @@ void OvmsVehicle::BmsResetCellTemperatures(bool full /*=false*/)
m_bms_tmins[k] = 0; m_bms_tmins[k] = 0;
m_bms_tmaxs[k] = 0; m_bms_tmaxs[k] = 0;
m_bms_tdevmaxs[k] = 0; m_bms_tdevmaxs[k] = 0;
m_bms_talerts[k] = OvmsStatus::OK; m_bms_talerts[k] = 0;
} }
m_bms_talerts_new = 0; m_bms_talerts_new = 0;
if (full) StandardMetrics.ms_v_bat_cell_temp->ClearValue(); if (full) StandardMetrics.ms_v_bat_cell_temp->ClearValue();
@ -439,24 +562,14 @@ void OvmsVehicle::BmsStatus(int verbosity, OvmsWriter* writer)
int vwarn=0, valert=0; int vwarn=0, valert=0;
int twarn=0, talert=0; int twarn=0, talert=0;
for (c=0; c<m_bms_readings_v; c++) for (c=0; c<m_bms_readings_v; c++) {
{ if (m_bms_valerts[c]==1) vwarn++;
switch (m_bms_valerts[c]) if (m_bms_valerts[c]==2) valert++;
{ }
case OvmsStatus::OK: break; for (c=0; c<m_bms_readings_t; c++) {
case OvmsStatus::Warn: vwarn++; break; if (m_bms_talerts[c]==1) twarn++;
case OvmsStatus::Alert: valert++;break; if (m_bms_talerts[c]==2) talert++;
} }
}
for (c=0; c<m_bms_readings_t; c++)
{
switch (m_bms_talerts[c])
{
case OvmsStatus::OK: break;
case OvmsStatus::Warn: twarn++; break;
case OvmsStatus::Alert: talert++; break;
}
}
writer->puts("Voltage:"); writer->puts("Voltage:");
writer->printf(" Average: %5.3fV [%5.3fV - %5.3fV]\n", writer->printf(" Average: %5.3fV [%5.3fV - %5.3fV]\n",
@ -525,18 +638,14 @@ bool OvmsVehicle::FormatBmsAlerts(int verbosity, OvmsWriter* writer, bool show_w
writer->printf("Voltage: StdDev %dmV", (int)(StdMetrics.ms_v_bat_pack_vstddev_max->AsFloat() * 1000)); writer->printf("Voltage: StdDev %dmV", (int)(StdMetrics.ms_v_bat_pack_vstddev_max->AsFloat() * 1000));
for (int i=0; i<m_bms_readings_v; i++) for (int i=0; i<m_bms_readings_v; i++)
{ {
OvmsStatus sts = OvmsStatus(StdMetrics.ms_v_bat_cell_valert->GetElemValue(i)); int sts = StdMetrics.ms_v_bat_cell_valert->GetElemValue(i);
switch (sts) if (sts == 0) continue;
{ if (sts == 1 && !show_warnings) continue;
case OvmsStatus::OK: continue;
case OvmsStatus::Warn: if (!show_warnings) continue;
case OvmsStatus::Alert: ;
}
has_valerts++; has_valerts++;
if (verbose || has_valerts <= 5) if (verbose || has_valerts <= 5)
{ {
int dev = StdMetrics.ms_v_bat_cell_vdevmax->GetElemValue(i) * 1000; int dev = StdMetrics.ms_v_bat_cell_vdevmax->GetElemValue(i) * 1000;
writer->printf("\n %c #%02d: %+4dmV", (sts==OvmsStatus::Warn) ? '?' : '!', i+1, dev); writer->printf("\n %c #%02d: %+4dmV", (sts==1) ? '?' : '!', i+1, dev);
} }
else else
{ {
@ -551,18 +660,14 @@ bool OvmsVehicle::FormatBmsAlerts(int verbosity, OvmsWriter* writer, bool show_w
writer->printf("Temperature: StdDev %.1fC", StdMetrics.ms_v_bat_pack_tstddev_max->AsFloat()); writer->printf("Temperature: StdDev %.1fC", StdMetrics.ms_v_bat_pack_tstddev_max->AsFloat());
for (int i=0; i<m_bms_readings_v; i++) for (int i=0; i<m_bms_readings_v; i++)
{ {
OvmsStatus sts = OvmsStatus(StdMetrics.ms_v_bat_cell_talert->GetElemValue(i)); int sts = StdMetrics.ms_v_bat_cell_talert->GetElemValue(i);
switch (sts) if (sts == 0) continue;
{ if (sts == 1 && !show_warnings) continue;
case OvmsStatus::OK: continue;
case OvmsStatus::Warn: if (!show_warnings) continue;
case OvmsStatus::Alert: ;
}
has_talerts++; has_talerts++;
if (verbose || has_talerts <= 5) if (verbose || has_talerts <= 5)
{ {
float dev = StdMetrics.ms_v_bat_cell_tdevmax->GetElemValue(i); float dev = StdMetrics.ms_v_bat_cell_tdevmax->GetElemValue(i);
writer->printf("\n %c #%02d: %+3.1fC", (sts==OvmsStatus::Warn) ? '?' : '!', i+1, dev); writer->printf("\n %c #%02d: %+3.1fC", (sts==1) ? '?' : '!', i+1, dev);
} }
else else
{ {