Skip to content
Open

SoC #2139

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
334 changes: 334 additions & 0 deletions firmware/hexray/BMS/src/app/app_soc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,334 @@
#include "app_soc.hpp"
#include "app_pack.hpp"
#include "app_canTx.hpp"
#include "app_tractiveSystem.hpp"

#include <array>
#include <cstddef>

namespace
{
constexpr size_t CELLS_IN_PARALLEL = 4;
constexpr size_t P30B_SOC_N = 21U;
constexpr size_t P30B_TEMP_N = 4U;
using P30BTable = std::array<std::array<float, P30B_TEMP_N>, P30B_SOC_N>;

// Capacity of a single cell in ampere-seconds (Ah * 3600), not of a 4P group
constexpr float P30B_CAP_AS = 10800.000000f;

constexpr std::array<float, P30B_SOC_N> P30B_SOC_BP = {
{ 0.0000f, 0.0500f, 0.1000f, 0.1500f, 0.2000f, 0.2500f, 0.3000f, 0.3500f, 0.4000f, 0.4500f, 0.5000f, 0.5500f,
0.6000f, 0.6500f, 0.7000f, 0.7500f, 0.8000f, 0.8500f, 0.9000f, 0.9500f, 1.0000f }
};

constexpr std::array<float, P30B_TEMP_N> P30B_TEMP_BP_C = {
{ 10.00f, 23.00f, 35.00f, 45.00f }
};

// Open circuit voltage of one cell, in volts.
constexpr P30BTable P30B_OCV_V = { {
{ { 2.93650000f, 2.94040000f, 2.92633333f, 2.91900000f } },
{ { 3.16150000f, 3.15846667f, 3.15166667f, 3.14850000f } },
{ { 3.26100000f, 3.25753333f, 3.25166667f, 3.24900000f } },
{ { 3.33950000f, 3.33646667f, 3.33200000f, 3.33000000f } },
{ { 3.41400000f, 3.41270000f, 3.40983333f, 3.40850000f } },
{ { 3.47500000f, 3.47326667f, 3.47066667f, 3.46950000f } },
{ { 3.53300000f, 3.53126667f, 3.52966667f, 3.52900000f } },
{ { 3.57600000f, 3.57513333f, 3.57466667f, 3.57450000f } },
{ { 3.62250000f, 3.62250000f, 3.62283333f, 3.62300000f } },
{ { 3.67050000f, 3.67180000f, 3.67266667f, 3.67300000f } },
{ { 3.72250000f, 3.72336667f, 3.72550000f, 3.72650000f } },
{ { 3.76700000f, 3.76916667f, 3.77183333f, 3.77300000f } },
{ { 3.81050000f, 3.81266667f, 3.81533333f, 3.81650000f } },
{ { 3.85250000f, 3.85423333f, 3.85683333f, 3.85800000f } },
{ { 3.90600000f, 3.90643333f, 3.90850000f, 3.90950000f } },
{ { 3.95450000f, 3.95536667f, 3.95683333f, 3.95750000f } },
{ { 4.00850000f, 4.00936667f, 4.01050000f, 4.01100000f } },
{ { 4.05600000f, 4.05686667f, 4.05833333f, 4.05900000f } },
{ { 4.07800000f, 4.07930000f, 4.08083333f, 4.08150000f } },
{ { 4.09900000f, 4.10116667f, 4.10283333f, 4.10350000f } },
{ { 4.16650000f, 4.16780000f, 4.17100000f, 4.17250000f } },
} };

// d(OCV)/d(SOC) in volts per unit SOC
constexpr P30BTable P30B_dOCV_dSOC = { {
{ { 4.50000000f, 4.36133333f, 4.50666667f, 4.59000000f } },
{ { 3.24500000f, 3.17133333f, 3.25333333f, 3.30000000f } },
{ { 1.78000000f, 1.78000000f, 1.80333333f, 1.81500000f } },
{ { 1.53000000f, 1.55166667f, 1.58166667f, 1.59500000f } },
{ { 1.35500000f, 1.36800000f, 1.38666667f, 1.39500000f } },
{ { 1.19000000f, 1.18566667f, 1.19833333f, 1.20500000f } },
{ { 1.01000000f, 1.01866667f, 1.04000000f, 1.05000000f } },
{ { 0.89500000f, 0.91233333f, 0.93166667f, 0.94000000f } },
{ { 0.94500000f, 0.96666667f, 0.98000000f, 0.98500000f } },
{ { 1.00000000f, 1.00866667f, 1.02666667f, 1.03500000f } },
{ { 0.96500000f, 0.97366667f, 0.99166667f, 1.00000000f } },
{ { 0.88000000f, 0.89300000f, 0.89833333f, 0.90000000f } },
{ { 0.85500000f, 0.85066667f, 0.85000000f, 0.85000000f } },
{ { 0.95500000f, 0.93766667f, 0.93166667f, 0.93000000f } },
{ { 1.02000000f, 1.01133333f, 1.00000000f, 0.99500000f } },
{ { 1.02500000f, 1.02933333f, 1.02000000f, 1.01500000f } },
{ { 1.01500000f, 1.01500000f, 1.01500000f, 1.01500000f } },
{ { 0.69500000f, 0.69933333f, 0.70333333f, 0.70500000f } },
{ { 0.43000000f, 0.44300000f, 0.44500000f, 0.44500000f } },
{ { 0.88500000f, 0.88500000f, 0.90166667f, 0.91000000f } },
{ { 1.35000000f, 1.33266667f, 1.36333333f, 1.38000000f } },
} };

// Series resistance of one cell while discharging, in ohms.
constexpr P30BTable P30B_R0_DIS_OHM = { {
{ { 0.07083453f, 0.05563725f, 0.03550818f, 0.01513335f } },
{ { 0.07083453f, 0.05563725f, 0.03550818f, 0.01513335f } },
{ { 0.01045934f, 0.00315000f, 0.01853349f, 0.01795000f } },
{ { 0.02484000f, 0.01953264f, 0.01715625f, 0.01601668f } },
{ { 0.02073636f, 0.01770543f, 0.01580122f, 0.01475000f } },
{ { 0.01783676f, 0.01564444f, 0.01475714f, 0.01404375f } },
{ { 0.01484375f, 0.01445484f, 0.01369833f, 0.01290000f } },
{ { 0.01649875f, 0.01067419f, 0.00928793f, 0.00787143f } },
{ { 0.01825405f, 0.01256912f, 0.00989138f, 0.00860200f } },
{ { 0.01750000f, 0.01257857f, 0.01029844f, 0.00925000f } },
{ { 0.01713750f, 0.01201667f, 0.01036212f, 0.00890172f } },
{ { 0.01681111f, 0.01231176f, 0.01082000f, 0.00968594f } },
{ { 0.01739429f, 0.01202500f, 0.01069394f, 0.00946000f } },
{ { 0.01680000f, 0.01239375f, 0.01071935f, 0.00925536f } },
{ { 0.01782344f, 0.01292333f, 0.01108704f, 0.00985000f } },
{ { 0.01791094f, 0.01331000f, 0.01122593f, 0.01032593f } },
{ { 0.01801111f, 0.01272344f, 0.01123387f, 0.01036000f } },
{ { 0.01850000f, 0.01323714f, 0.01134394f, 0.01023333f } },
{ { 0.01861250f, 0.01294821f, 0.01101731f, 0.00976667f } },
{ { 0.01882647f, 0.01357273f, 0.01135714f, 0.00978158f } },
{ { 0.01882647f, 0.01357273f, 0.01135714f, 0.00978158f } },
} };

// RC branch resistance of one cell while discharging, in ohms.
constexpr P30BTable P30B_R1_DIS_OHM = { {
{ { 0.25501617f, 0.15832715f, 0.15887515f, 1723712.76189689f } }, // bad fit
{ { 0.25501617f, 0.15832715f, 0.15887515f, 1723712.76189689f } }, // bad fit
{ { 0.12435599f, 0.10125000f, 8772007.78175694f, 1079585.57379464f } }, // bad fit
{ { 0.02929333f, 0.03280582f, 0.03189375f, 226265.23958991f } }, // bad fit
{ { 0.01586070f, 0.01644790f, 0.01693767f, 0.01715000f } },
{ { 0.01422540f, 0.01219556f, 0.01301786f, 0.01428958f } },
{ { 0.01507530f, 0.01069766f, 0.01044258f, 0.00960000f } },
{ { 0.01351077f, 0.01165544f, 0.01054033f, 0.01046190f } },
{ { 0.01257407f, 0.01153422f, 0.00994473f, 0.00883411f } },
{ { 0.01250000f, 0.01190476f, 0.01081490f, 0.00945000f } },
{ { 0.01286250f, 0.01145833f, 0.01114082f, 0.00987181f } },
{ { 0.01300317f, 0.01157824f, 0.01200500f, 0.01095252f } },
{ { 0.01211876f, 0.01098500f, 0.01134452f, 0.01029000f } },
{ { 0.01143333f, 0.01086339f, 0.01146953f, 0.01005020f } },
{ { 0.01130265f, 0.01013917f, 0.00911681f, 0.00857500f } },
{ { 0.01188536f, 0.01024000f, 0.00920220f, 0.00923771f } },
{ { 0.01300317f, 0.01130265f, 0.01049260f, 0.01029000f } },
{ { 0.01250000f, 0.01181580f, 0.01134452f, 0.01066667f } },
{ { 0.01000417f, 0.00946512f, 0.00885542f, 0.00853333f } },
{ { 0.00793035f, 0.00744394f, 0.00714286f, 0.00647467f } },
{ { 0.00793035f, 0.00744394f, 0.00714286f, 0.00647467f } },
} };

// RC branch time constant of one cell while discharging, in seconds.
constexpr P30BTable P30B_TAU1_DIS_S = { {
{ { 30.51133733f, 30.66089373f, 65.98486785f, 894272663.74314451f } }, // bad fit
{ { 30.51133733f, 30.66089373f, 65.98486785f, 894272663.74314451f } }, // bad fit
{ { 28.97967789f, 24.66303462f, 11318785970.07135963f, 2453602231.18314409f } }, // bad fit
{ { 38.11494687f, 60.24635791f, 84.90187016f, 914204893.76948404f } }, // bad fit
{ { 17.46666335f, 35.43178459f, 50.39028822f, 64.87159195f } },
{ { 13.58106366f, 22.63299846f, 39.79079143f, 58.19019522f } },
{ { 11.92848837f, 20.08683828f, 32.01283740f, 34.76059497f } },
{ { 23.69699636f, 15.96281797f, 17.12481575f, 16.15406563f } },
{ { 27.82616432f, 27.36279264f, 20.71028955f, 18.43915194f } },
{ { 19.57615189f, 28.03673252f, 26.01377645f, 24.66303462f } },
{ { 17.86940293f, 19.57615189f, 24.06649415f, 21.67572580f } },
{ { 17.38029748f, 21.61584858f, 29.72013412f, 29.33182797f } },
{ { 19.79825777f, 20.59699077f, 30.10834473f, 29.72013412f } },
{ { 17.86940293f, 27.55538335f, 39.23226389f, 35.87915009f } },
{ { 18.46390358f, 23.39487665f, 25.44253550f, 29.72013412f } },
{ { 16.34516968f, 21.27643145f, 21.48858984f, 29.26121629f } },
{ { 17.38029748f, 18.46390358f, 22.87210480f, 29.72013412f } },
{ { 19.57615189f, 25.25918085f, 30.10834473f, 34.76059497f } },
{ { 17.86940293f, 23.31026209f, 28.34295403f, 34.76059497f } },
{ { 12.04313898f, 22.97170887f, 28.03673252f, 28.45776931f } },
{ { 12.04313898f, 22.97170887f, 28.03673252f, 28.45776931f } },
} };

// Series resistance of one cell while charging, in ohms.
constexpr P30BTable P30B_R0_CHG_OHM = { {
{ { 0.02044130f, 0.01613875f, 0.01446711f, 0.01295588f } },
{ { 0.02044130f, 0.01613875f, 0.01446711f, 0.01295588f } },
{ { 0.02187750f, 0.01666200f, 0.01383261f, 0.01199167f } },
{ { 0.01905000f, 0.01452692f, 0.01228800f, 0.01144792f } },
{ { 0.01712742f, 0.01240000f, 0.01044333f, 0.00983333f } },
{ { 0.01614394f, 0.01145857f, 0.00942742f, 0.00834138f } },
{ { 0.01586528f, 0.01106912f, 0.00922353f, 0.00847500f } },
{ { 0.01607381f, 0.01122368f, 0.00935000f, 0.00870000f } },
{ { 0.01501842f, 0.01135147f, 0.00994844f, 0.00883710f } },
{ { 0.01548194f, 0.01188387f, 0.01061000f, 0.00967143f } },
{ { 0.01575294f, 0.01188710f, 0.01024821f, 0.00912308f } },
{ { 0.01565000f, 0.01192333f, 0.01004286f, 0.00886731f } },
{ { 0.01587000f, 0.01152500f, 0.00984286f, 0.00890000f } },
{ { 0.01515887f, 0.01091912f, 0.00987500f, 0.00873393f } },
{ { 0.01316071f, 0.01173333f, 0.01008182f, 0.00922759f } },
{ { 0.01466983f, 0.00935000f, 0.01076668f, 0.00881094f } },
{ { 0.01468600f, 0.01038378f, 0.00853088f, 0.00787500f } },
{ { 0.01649429f, 0.01163125f, 0.01033261f, 0.00907391f } },
{ { 0.01649394f, 0.01245000f, 0.01016731f, 0.00859167f } },
{ { 0.01775517f, 0.01226522f, 0.01037900f, 0.00904896f } },
{ { 0.01775517f, 0.01226522f, 0.01037900f, 0.00904896f } },
} };

// RC branch resistance of one cell while charging, in ohms.
constexpr P30BTable P30B_R1_CHG_OHM = { {
{ { 0.01620974f, 0.01751338f, 0.01427077f, 0.01221719f } },
{ { 0.01620974f, 0.01751338f, 0.01427077f, 0.01221719f } },
{ { 0.00691096f, 0.00844185f, 0.00780201f, 0.00816548f } },
{ { 0.00857500f, 0.00944808f, 0.00873422f, 0.00886637f } },
{ { 0.01056873f, 0.01250000f, 0.01143167f, 0.01109167f } },
{ { 0.01127856f, 0.01215297f, 0.01056873f, 0.01003135f } },
{ { 0.01240211f, 0.01152299f, 0.01148897f, 0.01109167f } },
{ { 0.01418528f, 0.01283632f, 0.01215000f, 0.01280000f } },
{ { 0.01351015f, 0.01165091f, 0.01081333f, 0.01046603f } },
{ { 0.01261006f, 0.01049260f, 0.01029000f, 0.00979857f } },
{ { 0.01195539f, 0.01046624f, 0.00946717f, 0.00879359f } },
{ { 0.01143333f, 0.01014095f, 0.00952381f, 0.00885542f } },
{ { 0.01194667f, 0.01012500f, 0.00952381f, 0.00960000f } },
{ { 0.02255692f, 0.01152299f, 0.01109167f, 0.00962971f } },
{ { 0.01951560f, 0.01386667f, 0.01150568f, 0.01022741f } },
{ { 0.01997612f, 0.01663750f, 226897.65965426f, 0.01129361f } }, // bad fit
{ { 0.01854019f, 0.01354788f, 0.01208112f, 0.01147500f } },
{ { 0.01361177f, 0.00904018f, 0.00780201f, 0.00791498f } },
{ { 0.01361177f, 0.00945000f, 0.00885542f, 0.00818833f } },
{ { 0.02007114f, 0.01562478f, 0.02063464f, 0.02475818f } },
{ { 0.02007114f, 0.01562478f, 0.02063464f, 0.02475818f } },
} };

// RC branch time constant of one cell while charging, in seconds.
constexpr P30BTable P30B_TAU1_CHG_S = { {
{ { 8.87165295f, 12.86953810f, 15.99760120f, 17.60612858f } },
{ { 8.87165295f, 12.86953810f, 15.99760120f, 17.60612858f } },
{ { 19.96903649f, 23.88285926f, 22.32019685f, 21.76125456f } },
{ { 29.72013412f, 37.27671435f, 32.52194339f, 39.07266895f } },
{ { 28.55491327f, 44.81420118f, 42.30319257f, 49.83288655f } },
{ { 21.10664896f, 31.66030274f, 28.55491327f, 31.09611078f } },
{ { 20.24215670f, 22.52600345f, 25.92940848f, 31.40173602f } },
{ { 23.74093145f, 23.64866498f, 24.66303462f, 34.76059497f } },
{ { 18.11369152f, 20.79120253f, 23.46952883f, 24.02919660f } },
{ { 18.96256110f, 22.87210480f, 29.72013412f, 32.74590996f } },
{ { 18.72369955f, 25.33863874f, 26.22142295f, 26.35118177f } },
{ { 17.86940293f, 26.11018876f, 28.03673252f, 28.34295403f } },
{ { 21.27643145f, 24.66303462f, 28.03673252f, 34.76059497f } },
{ { 37.40908149f, 22.52600345f, 31.40173602f, 30.17891850f } },
{ { 19.30714042f, 34.76059497f, 32.24195100f, 33.75347224f } },
{ { 20.26613977f, 22.12462197f, 916761456.07631612f, 33.84504642f } }, // bad fit
{ { 16.39974519f, 16.84140447f, 18.14299484f, 24.66303462f } },
{ { 15.05662094f, 15.90814866f, 22.32019685f, 30.28085308f } },
{ { 13.83125590f, 24.66303462f, 28.34295403f, 28.71032962f } },
{ { 19.84500334f, 27.69980701f, 50.28894551f, 73.45802012f } },
{ { 19.84500334f, 27.69980701f, 50.28894551f, 73.45802012f } },
} };

struct Interp {
float soc_i;
float soc_f;
float temp_i
float temp_f;
};

struct SocState {
float v1 = 0.0f;
float p00 = 0; //P_SOC (need to come up with initial value)
float p01 = 0.0f; //P_SOC_V1
float p11 = 0; //P_V1 (need to come up with initial value)
};

app::pack::PackChannel<app::pack::VoltStats>::Subscription volt_sub{ "soc_volt" };
app::pack::PackChannel<app::pack::TempStats>::Subscription temp_sub{ "soc_temp" };

app::soc::SocStats soc_stats{};
app::pack::VoltStats volt_stats{};
app::pack::TempStats temp_stats{};
io::adbms::Cells<SocState> soc_states{};


float lookup(const P30BTable &table, const Interp &in) {
}

void calculate(const app::pack::VoltStats &volts, const app::pack::TempStats &temps) {
const float dt_s = static_cast<float>(volt_stats.updated_ms - soc_stats.updated_ms) * 1.0e-3f;
soc_stats.updated_ms = volt_stats.updated_ms;

const float cell_current_a = -app::ts::getCurrent() / static_cast<float>(CELLS_IN_PARALLEL); //prob should change the convention (+ for discharge instead of + for charge) change this shit in ts file

const bool charging = cell_current_a < 0;
for (size_t seg = 0; seg < NUM_SEGMENTS; seg++) {
for (size_t cell = 0; cell < CELLS_PER_SEGMENT; cell++) {
if (!volts.valid[seg][cell])
continue;// should soc value go invalid???? prob not

const float temp_c = temps.valid[seg][cell] ? temps.temperatures[seg][cell] : 0; //what should be the invalid temp path

SocState &soc_state = soc_states[seg][cell];



// this is for reset so it can intialize with ocv lookup
if (!soc_stats.valid[seg][cell]) {
soc_stats.soc[seg][cell] =
soc_stats.valid[seg][cell] = true;
soc_state = {};
continue;
}

const float r0 = charging ? lookup(P30B_R0_CHG_OHM, soc, temp_c) : lookup(P30B_R0_DIS_OH, soc, temp_c);
const float r1 =
const float tau_s = charging ? lookup(P30B_TAU1_CHG_S, soc, temp_c) : lookup(P30B_TAU1_DIS_S, soc, temp_c);
const float a = std::exp(-dt_s / tau_s);

//Predict next state and covariance
soc_stats.soc[seg][cell] -= cell_current_a * dt_s / P30B_CAP_AS;
soc_state.v1 = a* soc_state.v1 + r1 * (1.0f - a) * cell_current_a;
soc_state.p00 += Q_SOC; // need to come up with this value
soc_state.p01 += a;
soc_state.p11 = a * a * soc_state.p11 + Q_V1; //need to come up with this value

//Calculate innovation
const float innovation = volts.votlages[seg][cell] - (lookup(P30B_OCV_V, ocv, temp) - r0 * cell_current_a - soc_state.v1);


}
}
}


}



} // namespace

namespace app::soc
{
void init()
{
app::pack::voltage_channel.subscribe(volt_sub);
app::pack::temperature_channel.subscribe(temp_sub);
//later will need to add ts_current channel s

}

void update()
{
while (const auto stats = volt_sub.pop(0))
volt_stats = *stats;
while (const auto stats = temp_sub.pop(0))
temp_stats = *stats;

if (volt_stats.updated_ms > soc_stats.updated_ms || temp_stats.updated_ms > soc_stats.updated_ms)
calculate(volt_stats, temp_stats);
}

void broadcast()
{
// The weakest cell sets what the pack can actually deliver.
app::can_tx::BMS_HvBatterySoc_set(
soc_stats.updated_ms != 0U ? static_cast<uint8_t>(soc_stats.min.value * 100.0f) : 0U);
}
} // namespace app::soc
21 changes: 21 additions & 0 deletions firmware/hexray/BMS/src/app/app_soc.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once

#include "app_pack.hpp"
#include "io_adbms.hpp"

#include <cstdint>

namespace app::soc
{
struct SocStats {
uint32_t updated_ms = 0U;
app::pack::LocatedValue max{};
app::pack::LocatedValue min{};
io::adbms::Cells<float> soc{};
app::pack::CellFlags valid{};
};

void init();
void update();
void broadcast();
} // namespace app::soc
6 changes: 3 additions & 3 deletions firmware/hexray/BMS/src/app/pack/app_pack_alerts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@ bool isThermOpenWireInfo(const OwcStats &stats)
return stats.updated_ms != 0U && anyClear(stats.therms_ok);
}

app::pack::PackChannel<VoltStats>::Subscription volt_sub{ "alerts_volt" };
app::pack::PackChannel<TempStats>::Subscription temp_sub{ "alerts_temp" };
app::pack::PackChannel<OwcStats>::Subscription owc_sub{ "alerts_owc" };
app::pack::PackChannel<app::pack::VoltStats>::Subscription volt_sub{ "alerts_volt" };
app::pack::PackChannel<app::pack::TempStats>::Subscription temp_sub{ "alerts_temp" };
app::pack::PackChannel<app::pack::OwcStats>::Subscription owc_sub{ "alerts_owc" };

bool volt_fault_active = false;
bool temp_fault_active = false;
Expand Down
Loading
Loading