diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 57ceb4c..2f333e0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -20,6 +20,15 @@ jobs: # The mbed target to build for target: [LPC1768] + # Add STM32F303 target for bms + include: + - project: bms + profile: debug + target: NUCLEO_F303K8 + - project: bms + profile: release + target: NUCLEO_F303K8 + steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it diff --git a/bms/Makefile b/bms/Makefile index 6be9b90..eb0b3f8 100644 --- a/bms/Makefile +++ b/bms/Makefile @@ -55,7 +55,7 @@ flash: deps $(BUILD_DIR) # .PHONY: debug -debug: build-debug +debug: arm-none-eabi-gdb -x .gdbinit ./$(BUILD_DIR)/$(MBED_TARGET)/$(MBED_BUILD_PROFILE)/$(MBED_TOOLCHAIN)/bms.elf # diff --git a/bms/mbed_app.json b/bms/mbed_app.json index 0334f72..25f23fe 100644 --- a/bms/mbed_app.json +++ b/bms/mbed_app.json @@ -1,4 +1,12 @@ { + "config": { + "main-stack-size": { + "value": 2048 + }, + "stack-size": { + "value": 1024 + } + }, "target_overrides": { "LPC1768": { "platform.stdio-baud-rate": 115200, diff --git a/bms/src/BmsConfig.h b/bms/src/BmsConfig.h index 591e2e7..a1427ea 100644 --- a/bms/src/BmsConfig.h +++ b/bms/src/BmsConfig.h @@ -5,13 +5,13 @@ // Global pointer to can bus object // // This allows for all files to access the can bus output -extern CAN* canBus; +//extern CAN* canBus; //Global pointer to DigitalOut objects for BMS_FAULT and CHARGER_CONTROL pins // //This allows for all files to access BMS_FAULT and CHARGER_CONTROL pins -extern DigitalOut* bmsFault; -extern DigitalOut* chargerControl; +//extern DigitalOut* bmsFault; +//extern DigitalOut* chargerControl; // // BMS Master Configuration diff --git a/bms/src/BmsThread.cpp b/bms/src/BmsThread.cpp index 5a9859d..f42d97e 100644 --- a/bms/src/BmsThread.cpp +++ b/bms/src/BmsThread.cpp @@ -4,11 +4,17 @@ #include "LTC681xCommand.h" #include "ThisThread.h" -BMSThread::BMSThread(LTC681xBus& bus, unsigned int frequency, std::vector*> mailboxes) : m_bus(bus), mailboxes(mailboxes) { +BMSThread::BMSThread(LTC681xBus& bus, unsigned int frequency, std::array mailboxes) + : m_bus(bus) + , m_chips { + LTC6811(bus, 0), + LTC6811(bus, 1), + LTC6811(bus, 2), + LTC6811(bus, 3) + } + , mailboxes(mailboxes) +{ m_delay = 1000 / frequency; - for (int i = 0; i < BMS_BANK_COUNT; i++) { - m_chips.push_back(LTC6811(bus, i)); - } for (int i = 0; i < BMS_BANK_COUNT; i++) { //m_chips[i].getConfig().gpio5 = LTC6811::GPIOOutputState::kLow; //m_chips[i].getConfig().gpio4 = LTC6811::GPIOOutputState::kPassive; @@ -19,7 +25,7 @@ BMSThread::BMSThread(LTC681xBus& bus, unsigned int frequency, std::vector mailboxes); + BMSThread(LTC681xBus& bus, unsigned int frequency, std::array mailboxes); // Function to allow for starting threads from static context static void startThread(BMSThread *p) { @@ -92,169 +92,12 @@ class BMSThread { private: unsigned int m_delay; LTC681xBus& m_bus; - std::vector m_chips; - std::vector mailboxes; + std::array m_chips; + std::array mailboxes; // Things that need to go away bool m_discharging = false; void throwBmsFault(); void threadWorker(); - /* - void threadWorker() { - std::array allVoltages; - std::array, 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(); - std::transform(allTemps.begin() + (BMS_BANK_TEMP_COUNT * i), - allTemps.begin() + (BMS_BANK_TEMP_COUNT * (i + 1)), - temps.begin(), - [](std::optional 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); - } - } - */ }; diff --git a/bms/src/Event.h b/bms/src/Event.h index ddef208..51c2361 100644 --- a/bms/src/Event.h +++ b/bms/src/Event.h @@ -25,7 +25,7 @@ class BmsEvent { virtual ~BmsEvent() {}; }; -static constexpr auto mailboxSize = 4; +static constexpr auto mailboxSize = 1; using BmsEventMailbox = Queue; // Measurement diff --git a/bms/src/Main.cpp b/bms/src/Main.cpp index 5a63f0e..e0c75e4 100644 --- a/bms/src/Main.cpp +++ b/bms/src/Main.cpp @@ -11,54 +11,46 @@ #include "LTC681xBus.h" #include "Event.h" -// When car is off maybe one reading every 10 sec -// when car is on 10 readings per second - -// TODO: map 12 cells to number of cells -// TODO: change m_chips to array rather than vector -// TODO: publish fault states -// TODO: SoC tracking using Ah counting and voltage measuring - -// Fault states: -// - AMS -// - IMD -// -// * Over temp -// - Under temp -// * Over voltage -// * Under voltage -// -// * Failed init -// * Comm fail - - -CAN* canBus; -DigitalOut* bmsFault; -DigitalOut* chargerControl; +#ifdef TARGET_NUCLEO_F303K8 + // Required for setting MISO to pull up on STM32 + #include +#endif + +CAN canBus = CAN(BMS_PIN_CAN_RX, BMS_PIN_CAN_TX, BMS_CAN_FREQUENCY); +DigitalOut bmsFault = DigitalOut(BMS_PIN_BMS_FLT); +DigitalOut chargerControl = DigitalOut(BMS_PIN_CHARGER_CONTROL); void initIO(); +// TODO: We need a better way of statically allocating thread stack +constexpr size_t STACK_SIZE = 1024; +unsigned char bmsThreadStack[STACK_SIZE]; +Thread bmsThreadThread = Thread(osPriorityNormal, STACK_SIZE, bmsThreadStack); + int main() { // Init all io pins initIO(); - canBus->write(BMSCellStartup()); + canBus.write(BMSCellStartup()); - ThisThread::sleep_for(1s); + SPI spiDriver = SPI(BMS_PIN_SPI_MOSI, + BMS_PIN_SPI_MISO, + BMS_PIN_SPI_SCLK, + BMS_PIN_SPI_SSEL, + use_gpio_ssel); + +#ifdef TARGET_NUCLEO_F303K8 + // This is a hack required to set the MISO pin to use a pull up resistor + LL_GPIO_SetPinPull(GPIOA, LL_GPIO_PIN_6, LL_GPIO_PULL_UP); +#endif - SPI* spiDriver = new SPI(BMS_PIN_SPI_MOSI, - BMS_PIN_SPI_MISO, - BMS_PIN_SPI_SCLK, - BMS_PIN_SPI_SSEL, - use_gpio_ssel); - spiDriver->format(8, 0); - auto ltcBus = LTC681xParallelBus(spiDriver); + spiDriver.format(8, 0); + auto ltcBus = LTC681xParallelBus(&spiDriver); - auto canMailbox = new BmsEventMailbox(); - auto uiMailbox = new BmsEventMailbox(); - std::vector mailboxes = { canMailbox, uiMailbox }; + auto canMailbox = BmsEventMailbox(); + auto uiMailbox = BmsEventMailbox(); + std::array mailboxes = { &canMailbox, &uiMailbox }; - Thread bmsThreadThread; BMSThread bmsThread(ltcBus, 1, mailboxes); bmsThreadThread.start(callback(&BMSThread::startThread, &bmsThread)); @@ -72,7 +64,7 @@ int main() { } while(true) { - auto event = canMailbox->get(); + auto event = canMailbox.get(); if (event.status == osEventMessage) { BmsEvent* msg = (BmsEvent*)event.value.p; @@ -120,12 +112,6 @@ int main() { void initIO() { printf("INIT\n"); - canBus = new CAN(BMS_PIN_CAN_RX, BMS_PIN_CAN_TX, BMS_CAN_FREQUENCY); - - bmsFault = new DigitalOut(BMS_PIN_BMS_FLT); - - chargerControl = new DigitalOut(BMS_PIN_CHARGER_CONTROL); - // Set modes for IO /* palSetLineMode(LINE_BMS_FLT_LAT, PAL_MODE_INPUT); @@ -135,9 +121,9 @@ void initIO() { */ // Reset BMS fault line - bmsFault->write(1); - bmsFault->write(0); + bmsFault.write(1); + bmsFault.write(0); // Enable charging - chargerControl->write(0); + chargerControl.write(0); }