Skip to content

Commit

Permalink
general bms cleanup; started mailbox logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Mayamelon committed Apr 30, 2024
1 parent 7f46a08 commit 671b400
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 274 deletions.
1 change: 0 additions & 1 deletion bms/.mbed
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
ROOT=.
TARGET=NUCLEO_L432KC
TARGET_CODE=0770
TARGET_SERIAL=0671FF555185754867150637
16 changes: 16 additions & 0 deletions bms/src/BmsConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -352,3 +352,19 @@ const int BMS_CELL_MAP[12] = {0, 1, 2, 3, -1, -1, 4, 5, 6, -1, -1, -1};
#define BMS_CAN_FREQUENCY 500000
#endif


enum class BMSThreadState {
// BMS startup and self test
// Run self test on all banks
// If OK, go to BMSIdle
BMSStartup,

// BMS in idle mode
// no faults and cells are being actively monitored
//
// wait for either faults or a signal to move in to charging state
BMSIdle,

// BMS in failure mode
BMSFault
};
41 changes: 16 additions & 25 deletions bms/src/BmsThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@

#include "EnergusTempSensor.h"

BMSThread::BMSThread(LTC681xBus &bus, unsigned int frequency,
std::vector<Queue<BmsEvent, mailboxSize> *> mailboxes)
: m_bus(bus), mailboxes(mailboxes) {
m_delay = 1000 / frequency;
BMSThread::BMSThread(LTC681xBus &bus, unsigned int frequency, BmsEventMailbox* mailbox)
: m_bus(bus) {
for (int i = 0; i < BMS_BANK_COUNT; i++) {
m_chips.push_back(LTC6811(bus, i));
}
Expand All @@ -28,13 +26,10 @@ void BMSThread::threadWorker() {

// Cell Voltage self test
m_bus.WakeupBus();
printf("wakeup1\n");
m_bus.SendCommand(LTC681xBus::BuildBroadcastBusCommand(
StartSelfTestCellVoltage(AdcMode::k7k, SelfTestMode::kSelfTest1)));
printf("Send Command\n");
ThisThread::sleep_for(4ms);
m_bus.WakeupBus();
printf("wakeup2\n");
for (int i = 0; i < BMS_BANK_COUNT; i++) {
uint16_t rawVoltages[12];

Expand All @@ -59,8 +54,6 @@ void BMSThread::threadWorker() {
printf("Things are not okay. SelfTestVoltageD\n");
}

printf("beep\n");

for (int j = 0; j < 12; j++) {
printf("AXST %2d: %4x\n", j, rawVoltages[i]);
}
Expand Down Expand Up @@ -91,6 +84,7 @@ void BMSThread::threadWorker() {
}

printf("SELF TEST DONE \n");
bmsState = BMSThreadState::BMSIdle;

std::array<uint16_t, BMS_BANK_COUNT * BMS_BANK_CELL_COUNT> allVoltages;
std::array<int8_t, BMS_BANK_COUNT * BMS_BANK_TEMP_COUNT> allTemps;
Expand Down Expand Up @@ -132,7 +126,7 @@ void BMSThread::threadWorker() {
LTC681xBus::LTC681xBusStatus::PollTimeout) {
printf("Poll timeout.\n");
} else {
printf("Poll OK.\n");
//printf("Poll OK.\n");
}

uint16_t rawVoltages[12];
Expand Down Expand Up @@ -238,7 +232,7 @@ void BMSThread::threadWorker() {
throwBmsFault();
}

if (m_discharging) {
if (bmsState == BMSThreadState::BMSIdle) {
for (int i = 0; i < BMS_BANK_COUNT; i++) {

LTC6811::Configuration &config = m_chips[i].getConfig();
Expand All @@ -253,7 +247,7 @@ void BMSThread::threadWorker() {
uint16_t cellVoltage = allVoltages[i * BMS_BANK_CELL_COUNT + cellNum];
if (cellVoltage >= BMS_BALANCE_THRESHOLD &&
cellVoltage >= minVoltage + BMS_DISCHARGE_THRESHOLD) {
printf("Balancing cell %d\n", cellNum);
//printf("Balancing cell %d\n", cellNum);
dischargeValue |= (0x1 << j);
}
}
Expand All @@ -279,28 +273,25 @@ void BMSThread::threadWorker() {
m_chips[i].updateConfig();
}

for (auto mailbox : mailboxes) {
if (!mailbox->full()) {
{
auto msg = new VoltageMeasurement();
msg->voltageValues = allVoltages;
mailbox->put((BmsEvent *)msg);
if (!mailbox->full()) {
BmsEvent* msg = new BmsEvent();
for (int i = 0; i < BMS_BANK_COUNT*BMS_BANK_CELL_COUNT; i++) {
msg->voltageValues[i] = allVoltages[i];
}

{
auto msg = new TemperatureMeasurement();
msg->temperatureValues = allTemps;
mailbox->put((BmsEvent *)msg);
for (int i = 0; i < BMS_BANK_COUNT*BMS_BANK_TEMP_COUNT; i++) {
msg->temperatureValues[i] = allTemps[i];
}
}
msg->bmsState = bmsState;
mailbox->put((BmsEvent *)msg);
}


ThisThread::sleep_for(100ms); // TODO: change to 100 or lower
}
}

void BMSThread::throwBmsFault() {
m_discharging = false;
bmsState = BMSThreadState::BMSFault;
// palClearLine(LINE_BMS_FLT);
// palSetLine(LINE_CHARGER_CONTROL);
}
227 changes: 4 additions & 223 deletions bms/src/BmsThread.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,239 +22,20 @@
class BMSThread {
public:

BMSThread(LTC681xBus& bus, unsigned int frequency, std::vector<BmsEventMailbox*> mailboxes);
BMSThread(LTC681xBus& bus, unsigned int frequency, BmsEventMailbox* mailbox);

// Function to allow for starting threads from static context
static void startThread(BMSThread *p) {
p->threadWorker();
}

enum class BMSThreadState {
// BMS startup and self test
// Run self test on all banks
// If OK, go to BMSIdle
BMSStartup,

// BMS in idle mode
// no faults and cells are being actively monitored
//
// wait for either faults or a signal to move in to charging state
BMSIdle,

// BMS in comm failure mode
// Attempt to reconnect with banks for N seconds and if unsuccessful throw a fault
// send warning on CAN
//
// If successful, return to previous state
BMSBusCommunicationFailure,

//
// Charging states
//

// BMS waiting/sensing to avoid reading cells while charging (not accurate)
// BMS_PIN_CHARGER_CONTROL set low
// Wait ~5s then get some voltage data
// If we are above our charging goal, go to BMSChargingDone
// If we need to balance, go to BMSChargingBalance
// else go to BMSChargingActive
BMSChargingSense,

// BMS actively charging
// BMS_PIN_CHARGER_CONTROL set high
// Voltage/temp monitored
// Every ~5min go to BMSChargingSensing
BMSChargingActive,

// BMS balancing cells
// BMS_PIN_CHARGER_CONTROL set low
// discharging enabled for cells BMS_DISCHARGE_THRESHOLD above lowest cell
// Wait ~5min then go to BMSChargingSensing
BMSChargingBalance,

// BMS charging complete
// BMS_PIN_CHARGER_CONTROL set low
// discharging disabled
//
// (maybe) every 5 mins go in to BMSChargingSense
BMSChargingDone,

// BMS charging fault
// BMS_PIN_CHARGER_CONTROL set low
//
// Entered if any readings go outside allowable range (voltage, temp, current)
// BMS_PIN_BMS_FLT set high
//
// Able to enter BMSIdle if fault latch cleared (after some time for debounce)
BMSChargingFault
};

private:
unsigned int m_delay;
LTC681xBus& m_bus;
std::vector<LTC6811> m_chips;
std::vector<BmsEventMailbox*> mailboxes;

// Things that need to go away
bool m_discharging = true;
BmsEventMailbox* mailbox;

BMSThreadState bmsState = BMSThreadState::BMSStartup;

void throwBmsFault();
void threadWorker();
/*
void threadWorker() {
std::array<uint16_t, BMS_BANK_COUNT * BMS_BANK_CELL_COUNT> allVoltages;
std::array<std::optional<int8_t>, BMS_BANK_COUNT * BMS_BANK_TEMP_COUNT>
allTemps;
while (true) {
for (int i = 0; i < BMS_BANK_COUNT; i++) {
// Get a reference to the config for toggling gpio
LTC6811::Configuration& conf = m_chips[i].getConfig();
// Turn on status LED
conf.gpio5 = LTC6811::GPIOOutputState::kLow;
m_chips[i].updateConfig();
uint16_t* voltages = m_chips[i].getVoltages();
int temperatures[BMS_BANK_TEMP_COUNT];
// Measure all temp sensors
for (unsigned int j = 0; j < BMS_BANK_TEMP_COUNT; j++) {
conf.gpio1 = (j & 0x01) ? LTC6811::GPIOOutputState::kHigh
: LTC6811::GPIOOutputState::kLow;
conf.gpio2 = (j & 0x02) ? LTC6811::GPIOOutputState::kHigh
: LTC6811::GPIOOutputState::kLow;
conf.gpio3 = (j & 0x04) ? LTC6811::GPIOOutputState::kHigh
: LTC6811::GPIOOutputState::kLow;
conf.gpio4 = LTC6811::GPIOOutputState::kPassive;
m_chips[i].updateConfig();
// Wait for config changes to take effect
ThisThread::sleep_for(3);
uint16_t* temps = m_chips[i].getGpioPin(GpioSelection::k4);
temperatures[j] = temps[3];
delete temps;
}
// Turn off status LED
conf.gpio5 = LTC6811::GPIOOutputState::kHigh;
m_chips[i].updateConfig();
// Done with communication at this point
// Now time to crunch numbers
// Process voltages
for (int j = 0; j < 12; j++) {
uint16_t voltage = voltages[j] / 10;
int index = BMS_CELL_MAP[j];
if (index != -1) {
allVoltages[(BMS_BANK_CELL_COUNT * i) + index] = voltage;
if (voltage >= BMS_FAULT_VOLTAGE_THRESHOLD_HIGH) {
// Set fault line
printf("***** BMS LOW VOLTAGE FAULT *****\nVoltage at
%d\n\n", voltage); throwBmsFault();
}
if (voltage <= BMS_FAULT_VOLTAGE_THRESHOLD_LOW) {
// Set fault line
printf("***** BMS HIGH VOLTAGE FAULT *****\nVoltage at
%d\n\n", voltage); throwBmsFault();
}
// Discharge cells if enabled
if(m_discharging) {
if((voltage > prevMinVoltage) && (voltage - prevMinVoltage >
BMS_DISCHARGE_THRESHOLD)) {
// Discharge
printf("DISCHARGE CELL %d: %dmV (%dmV)\n", index,
voltage, (voltage - prevMinVoltage));
// Enable discharging
conf.dischargeState.value |= (1 << j);
} else {
// Disable discharging
conf.dischargeState.value &= ~(1 << j);
}
} else {
// Disable discharging
conf.dischargeState.value &= ~(1 << j);
}
}
}
delete voltages;
for (unsigned int j = 0; j < BMS_BANK_TEMP_COUNT; j++) {
auto temp = convertTemp(temperatures[j] / 10);
allTemps[(BMS_BANK_TEMP_COUNT * i) + j] = temp;
temp.map([&](auto t){
if (t < minTemp) minTemp = t;
if (t > maxTemp) maxTemp = t;
});
}
allBanksVoltage += totalVoltage;
}
averageVoltage = allBanksVoltage / (BMS_BANK_COUNT * BMS_BANK_CELL_COUNT);
prevMinVoltage = minVoltage;
printf("Temperatures: \n");
for(int i = 0; i < BMS_BANK_COUNT * BMS_BANK_CELL_COUNT; i++){
allTemps[i].map_or_else([&](auto temp) {
if (temp >= BMS_FAULT_TEMP_THRESHOLD_HIGH) {
printf("***** BMS HIGH TEMP FAULT *****\nTemp at %d\n\n",
temp); throwBmsFault(); } else if (temp <= BMS_FAULT_TEMP_THRESHOLD_LOW) {
printf("***** BMS LOW TEMP FAULT *****\nTemp at %d\n\n",
temp); throwBmsFault();
}
printf("%3d ", temp);
},
[&]() {
printf("ERR ");
//printf("***** BMS INVALID TEMP FAULT *****\n");
//throwBmsFault();
});
if((i + 1) % BMS_BANK_CELL_COUNT == 0)
printf("\n");
}
canBus->write(BMSStatMessage(allBanksVoltage / 10, maxVoltage, minVoltage,
maxTemp, minTemp));
// Send CAN
for (size_t i = 0; i < BMS_BANK_COUNT; i++) {
// Convert from optional temp values to values with default of -127 (to
indicate error) auto temps = std::array<int8_t, BMS_BANK_TEMP_COUNT>();
std::transform(allTemps.begin() + (BMS_BANK_TEMP_COUNT * i),
allTemps.begin() + (BMS_BANK_TEMP_COUNT * (i + 1)),
temps.begin(),
[](std::optional<int8_t> t) { return t.value_or(-127); });
canBus->write(BMSTempMessage(i, (uint8_t*)temps.data()));
}
for (size_t i = 0; i < 7; i++) {
canBus->write(BMSVoltageMessage(i, allVoltages + (4 * i)));
}
// Compute time elapsed since beginning of measurements and sleep for
// m_delay accounting for elapsed time
// TODO: use a hardware timer or a virtual timer or literally anything
// else. kek.
//unsigned int timeElapsed = TIME_I2MS(chVTTimeElapsedSinceX(timeStart));
#ifdef DEBUG
//printf("BMS Thread time elapsed: %dms\n", timeElapsed);
#endif
ThisThread::sleep_for(m_delay);
}
}
*/
};
Loading

0 comments on commit 671b400

Please sign in to comment.