diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index fbd8e81..d3d0838 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -7,7 +7,7 @@ name: CMake # Define the workflow's triggers on: pull_request: - branches: [ main ] + branches: [main] # Set necessary environment variables env: @@ -30,8 +30,8 @@ jobs: - name: Install Compiler and Linter run: | sudo apt-get install gcc-arm-none-eabi - sudo apt-get install clang-format-12 - sudo update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-12 10000 + sudo apt-get install clang-format-15 + sudo update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-15 10000 # Build the code for all supported chips - name: F302 Build @@ -44,6 +44,10 @@ jobs: cmake -DTARGET_DEV=STM32F334x8 -B ${{github.workspace}}/build cmake --build ${{github.workspace}}/build + - name: F446 Build + run: | + cmake -DTARGET_DEV=STM32F446xx -B ${{github.workspace}}/build + # cmake --build ${{github.workspace}}/build # Apply clang-format formatting to the branch and create a new commit if any files are changed - name: Apply Formatting run: | @@ -57,4 +61,4 @@ jobs: git config --global user.name "GitHub Build" git commit -a -m "Applied Formatting Changes During GitHub Build" git push origin - fi \ No newline at end of file + fi diff --git a/include/BMS.hpp b/include/BMS.hpp index 6e68b5b..777b233 100644 --- a/include/BMS.hpp +++ b/include/BMS.hpp @@ -58,11 +58,13 @@ class BMS : public CANDevice { static constexpr IO::Pin CAN_RX_PIN = IO::Pin::PA_11; static constexpr IO::Pin I2C_SCL_PIN = IO::Pin::PB_6; static constexpr IO::Pin I2C_SDA_PIN = IO::Pin::PB_7; - static constexpr IO::Pin INTERLOCK_PIN = IO::Pin::PA_3; + static constexpr IO::Pin INTERLOCK_PIN = IO::Pin::PF_0; static constexpr IO::Pin TEMP_INPUT_PIN = IO::Pin::PA_0; static constexpr IO::Pin MUX_S1_PIN = IO::Pin::PA_15; static constexpr IO::Pin MUX_S2_PIN = IO::Pin::PB_4; static constexpr IO::Pin MUX_S3_PIN = IO::Pin::PA_8; + static constexpr IO::Pin ERROR_LED_PIN = IO::Pin::PA_7; + static constexpr IO::Pin BQ_RESET_PIN = IO::Pin::PB_1; /** Error values */ static constexpr uint8_t BQ_COMM_ERROR = 0x01; @@ -72,17 +74,19 @@ class BMS : public CANDevice { /** * Make a new instance of the BMS with the given devices * - * @param bqSettingsStorage Object used to manage BQ settings storage - * @param bq BQ chip instance - * @param interlock GPIO used to check the interlock status - * @param alarm GPIO used to check the BQ alarm status - * @param systemDetect Object used to detect what system the BMS is connected to - * @param bmsOK GPIO used to output the OK signal from the BMS - * @param thermMux MUX for pack thermistors - * @param resetHandler Handler for reset messages + * @param[in] bqSettingsStorage Object used to manage BQ settings storage + * @param[in] bq BQ chip instance + * @param[in] interlock GPIO used to check the interlock status + * @param[in] alarm GPIO used to check the BQ alarm status + * @param[in] systemDetect Object used to detect what system the BMS is connected to + * @param[in] bmsOK GPIO used to output the OK signal from the BMS + * @param[in] errorLed GPIO used to indicate a BMS error with an LED + * @param[in] thermMux MUX for pack thermistors + * @param[in] resetHandler Handler for reset messages + * @param[in] iwdg Internal watchdog to ensure the BMS code is running without getting stuck */ BMS(BQSettingsStorage& bqSettingsStorage, DEV::BQ76952 bq, DEV::Interlock& interlock, - IO::GPIO& alarm, SystemDetect& systemDetect, IO::GPIO& bmsOK, + IO::GPIO& alarm, SystemDetect& systemDetect, IO::GPIO& bmsOK, IO::GPIO& errorLed, DEV::ThermistorMux& thermMux, ResetHandler& resetHandler, EVT::core::DEV::IWDG& iwdg); /** @@ -223,6 +227,11 @@ class BMS : public CANDevice { */ IO::GPIO& bmsOK; + /** + * LED to indicate an error in the BMS + */ + IO::GPIO& errorLed; + /** * Multiplexer to handle pack thermistors */ diff --git a/include/dev/BQ76952.hpp b/include/dev/BQ76952.hpp index db91b2f..9c30e96 100644 --- a/include/dev/BQ76952.hpp +++ b/include/dev/BQ76952.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -48,8 +49,9 @@ class BQ76952 { * * @param[in] i2c I2C interface to use to communicate on the bus * @param[in] i2cAddress The address of the BQ76952 to use + * @param[in] resetPin GPIO instance to reset the BQ */ - BQ76952(EVT::core::IO::I2C& i2c, uint8_t i2cAddress); + BQ76952(EVT::core::IO::I2C& i2c, uint8_t i2cAddress, EVT::core::IO::GPIO& resetPin); /** * Write out the given setting @@ -225,6 +227,11 @@ class BQ76952 { */ Status getBQStatus(uint8_t bqStatusArr[7]); + /** + * Reset the BQ + */ + void reset(); + /** CANopen interface for probing the state of the balancing */ //CO_OBJ_TYPE balancingCANOpen; @@ -279,8 +286,10 @@ class BQ76952 { /** I2C bus to communicate over */ EVT::core::IO::I2C& i2c; - /** The address of the BQ76952 on the I2C bus */ + /** The address of the BQ on the I2C bus */ uint8_t i2cAddress; + /** Reset pin of the BQ */ + EVT::core::IO::GPIO& resetPin; }; }// namespace BMS::DEV diff --git a/src/BMS.cpp b/src/BMS.cpp index b4647e1..11f011b 100644 --- a/src/BMS.cpp +++ b/src/BMS.cpp @@ -11,12 +11,14 @@ namespace BMS { BMS::BMS(BQSettingsStorage& bqSettingsStorage, DEV::BQ76952 bq, DEV::Interlock& interlock, IO::GPIO& alarm, SystemDetect& systemDetect, - IO::GPIO& bmsOK, DEV::ThermistorMux& thermMux, + IO::GPIO& bmsOK, IO::GPIO& errorLed, DEV::ThermistorMux& thermMux, ResetHandler& resetHandler, EVT::core::DEV::IWDG& iwdg) : bqSettingsStorage(bqSettingsStorage), bq(bq), state(State::START), interlock(interlock), alarm(alarm), systemDetect(systemDetect), resetHandler(resetHandler), - bmsOK(bmsOK), thermistorMux(thermMux), iwdg(iwdg), stateChanged(true) { + bmsOK(bmsOK), errorLed(errorLed), thermistorMux(thermMux), + iwdg(iwdg), stateChanged(true) { bmsOK.writePin(IO::GPIO::State::LOW); + errorLed.writePin(IO::GPIO::State::LOW); updateBQData(); } @@ -194,6 +196,7 @@ void BMS::startState() { void BMS::initializationErrorState() { if (stateChanged) { bmsOK.writePin(BMS_NOT_OK); + errorLed.writePin(IO::GPIO::State::HIGH); stateChanged = false; clearVoltageReadings(); log::LOGGER.log(log::Logger::LogLevel::INFO, "Entering initialization error state"); @@ -202,6 +205,8 @@ void BMS::initializationErrorState() { updateThermistorReading(); if (resetHandler.shouldReset()) { + bq.reset(); + errorLed.writePin(IO::GPIO::State::LOW); state = State::START; stateChanged = true; } @@ -302,6 +307,7 @@ void BMS::systemReadyState() { void BMS::unsafeConditionsError() { if (stateChanged) { bmsOK.writePin(BMS_NOT_OK); + errorLed.writePin(IO::GPIO::State::HIGH); stateChanged = false; log::LOGGER.log(log::Logger::LogLevel::INFO, "Entering unsafe conditions state"); } @@ -310,6 +316,8 @@ void BMS::unsafeConditionsError() { updateThermistorReading(); if (resetHandler.shouldReset()) { + bq.reset(); + errorLed.writePin(IO::GPIO::State::LOW); state = State::START; stateChanged = true; } diff --git a/src/dev/BQ76952.cpp b/src/dev/BQ76952.cpp index 7b145fb..959887a 100644 --- a/src/dev/BQ76952.cpp +++ b/src/dev/BQ76952.cpp @@ -145,7 +145,7 @@ static CO_ERR COBalancingCtrl(CO_OBJ* obj, CO_NODE_T* node, uint16_t func, */ namespace BMS::DEV { -BQ76952::BQ76952(EVT::core::IO::I2C& i2c, uint8_t i2cAddress) : /* +BQ76952::BQ76952(EVT::core::IO::I2C& i2c, uint8_t i2cAddress, EVT::core::IO::GPIO& resetPin) : /* balancingCANOpen{ COBQBalancingSize, COBalancingCtrl, @@ -154,7 +154,10 @@ BQ76952::BQ76952(EVT::core::IO::I2C& i2c, uint8_t i2cAddress) : /* this, }, */ - i2c(i2c), i2cAddress(i2cAddress) {} + i2c(i2c), i2cAddress(i2cAddress), resetPin(resetPin) { + // Ensure the pin is initialized to low, so it doesn't reset or shut down the BQ + resetPin.writePin(EVT::core::IO::GPIO::State::LOW); +} BQ76952::Status BQ76952::writeSetting(BMS::BQSetting& setting) { // Right now, the BQ only accepts settings made into RAM @@ -495,4 +498,11 @@ BQ76952::Status BQ76952::getBQStatus(uint8_t bqStatusArr[7]) { return BQ76952::Status::OK; } +void BQ76952::reset() { + resetPin.writePin(EVT::core::IO::GPIO::State::HIGH); + // Wait an arbitrary amount of time to ensure the BQ actually resets + EVT::core::time::wait(10); + resetPin.writePin(EVT::core::IO::GPIO::State::LOW); +} + }// namespace BMS::DEV diff --git a/targets/DEV1-BMS/main.cpp b/targets/DEV1-BMS/main.cpp index 93b3bf6..d53a954 100644 --- a/targets/DEV1-BMS/main.cpp +++ b/targets/DEV1-BMS/main.cpp @@ -86,7 +86,7 @@ int main() { // TODO: Investigate adding CAN filters IO::CAN& can = IO::getCAN(); can.addIRQHandler(canInterruptHandler, reinterpret_cast(&canParams)); - IO::UART& uart = IO::getUART(115200, true); + IO::UART& uart = IO::getUART(115200); IO::I2C& i2c = IO::getI2C(); // Initialize the timer @@ -100,7 +100,8 @@ int main() { log::LOGGER.setLogLevel(log::Logger::LogLevel::INFO); // Initialize the BQ interfaces - BMS::DEV::BQ76952 bq(i2c, 0x08); + IO::GPIO& bqReset = IO::getGPIO(); + BMS::DEV::BQ76952 bq(i2c, 0x08, bqReset); BMS::BQSettingsStorage bqSettingsStorage(eeprom, bq); // Initialize the Interlock @@ -113,6 +114,9 @@ int main() { // Initialize the system OK pin IO::GPIO& bmsOK = IO::getGPIO(IO::GPIO::Direction::OUTPUT); + // Initialize the error LED pin + IO::GPIO& errorLed = IO::getGPIO(IO::GPIO::Direction::OUTPUT); + // Initialize the thermistor MUX IO::GPIO* muxSelectArr[3] = { &IO::getGPIO(), @@ -126,7 +130,7 @@ int main() { DEV::IWDG& iwdg = DEV::getIWDG(500); // Initialize the BMS itself - BMS::BMS bms(bqSettingsStorage, bq, interlock, alarm, systemDetect, bmsOK, thermMux, resetHandler, iwdg); + BMS::BMS bms(bqSettingsStorage, bq, interlock, alarm, systemDetect, bmsOK, errorLed, thermMux, resetHandler, iwdg); /////////////////////////////////////////////////////////////////////////// // Setup CAN configuration, this handles making drivers, applying settings. diff --git a/targets/bms_canopen/main.cpp b/targets/bms_canopen/main.cpp index 0ac50b1..0f6a90d 100644 --- a/targets/bms_canopen/main.cpp +++ b/targets/bms_canopen/main.cpp @@ -86,7 +86,7 @@ int main() { // Initialize IO IO::CAN& can = IO::getCAN(); can.addIRQHandler(canInterruptHandler, reinterpret_cast(&canParams)); - IO::UART& uart = IO::getUART(115200, true); + IO::UART& uart = IO::getUART(115200); IO::I2C& i2c = IO::getI2C(); // Initialize the timer @@ -100,7 +100,8 @@ int main() { log::LOGGER.setLogLevel(log::Logger::LogLevel::DEBUG); // Initialize the BQ interfaces - BMS::DEV::BQ76952 bq(i2c, 0x08); + IO::GPIO& bqReset = IO::getGPIO(); + BMS::DEV::BQ76952 bq(i2c, 0x08, bqReset); BMS::BQSettingsStorage bqSettingsStorage(eeprom, bq); // Initialize the Interlock @@ -113,6 +114,9 @@ int main() { // Initialize the system OK pin IO::GPIO& bmsOK = IO::getGPIO(IO::GPIO::Direction::OUTPUT); + // Initialize the error LED pin + IO::GPIO& errorLed = IO::getGPIO(IO::GPIO::Direction::OUTPUT); + // Initialize the thermistor MUX IO::GPIO* muxSelectArr[3] = { &IO::getGPIO(), @@ -126,7 +130,7 @@ int main() { DEV::IWDG& iwdg = DEV::getIWDG(500); // Initialize the BMS itself - BMS::BMS bms(bqSettingsStorage, bq, interlock, alarm, systemDetect, bmsOK, thermMux, resetHandler, iwdg); + BMS::BMS bms(bqSettingsStorage, bq, interlock, alarm, systemDetect, bmsOK, errorLed, thermMux, resetHandler, iwdg); /////////////////////////////////////////////////////////////////////////// // Setup CAN configuration, this handles making drivers, applying settings. diff --git a/targets/bq_interface/main.cpp b/targets/bq_interface/main.cpp index fd4dbfc..8322dc0 100644 --- a/targets/bq_interface/main.cpp +++ b/targets/bq_interface/main.cpp @@ -40,6 +40,7 @@ void printHelp(IO::UART& uart) { uart.printf(" i - Get interlock state\r\n"); uart.printf(" a - Get alarm state\r\n"); uart.printf(" o - Set OK signal output\r\n"); + uart.printf(" e - Set error LED output\r\n"); uart.printf(" v - Read voltages\r\n"); uart.printf(" t - Transfer settings\r\n"); @@ -319,7 +320,7 @@ void exitConfigMode(IO::UART& uart, BMS::DEV::BQ76952& bq) { void getTemperatures(IO::UART& uart, BMS::DEV::BQ76952& bq, BMS::DEV::ThermistorMux tMux) { for (uint8_t i = 0; i < 6; i++) { uint16_t temp = tMux.getTemp(i); - uart.printf("Thermistor %d: %d.%03d\r\n", i, temp / 1000, temp % 1000); + uart.printf("Thermistor %d: %d\r\n", i, temp); } uint16_t result; bq.makeDirectRead(0x68, &result); @@ -354,6 +355,19 @@ void setOK(IO::UART& uart, IO::GPIO& bmsOK) { } } +void setError(IO::UART& uart, IO::GPIO& errorLed) { + uart.printf("Set error LED pin (0/1): "); + uart.printf("\r\n"); + uart.gets(inputBuffer, MAX_BUFF); + if (inputBuffer[0] == '1') { + errorLed.writePin(IO::GPIO::State::HIGH); + uart.printf("Set error LED high\r\n"); + } else { + errorLed.writePin(IO::GPIO::State::LOW); + uart.printf("Set error LED low\r\n"); + } +} + void getVoltages(IO::UART& uart, BMS::DEV::BQ76952& bq) { uint16_t tot = 0; for (uint8_t i = 0; i < 16; i++) { @@ -415,10 +429,11 @@ int main() { EVT::core::platform::init(); IO::I2C& i2c = IO::getI2C(); - BMS::DEV::BQ76952 bq(i2c, 0x08); + IO::GPIO& bqReset = IO::getGPIO(); + BMS::DEV::BQ76952 bq(i2c, 0x08, bqReset); EVT::core::DEV::M24C32 eeprom(0x57, i2c); - IO::UART& uart = IO::getUART(115200, true); + IO::UART& uart = IO::getUART(115200); log::LOGGER.setUART(&uart); log::LOGGER.setLogLevel(log::Logger::LogLevel::DEBUG); @@ -438,6 +453,8 @@ int main() { IO::GPIO& bmsOK = IO::getGPIO(IO::GPIO::Direction::OUTPUT); + IO::GPIO& errorLed = IO::getGPIO(IO::GPIO::Direction::OUTPUT); + time::wait(500); while (true) { @@ -519,6 +536,10 @@ int main() { case 'o': setOK(uart, bmsOK); break; + // Set OK signal output + case 'e': + setError(uart, errorLed); + break; } } diff --git a/targets/bq_settings/main.cpp b/targets/bq_settings/main.cpp index 6d3e10c..f803456 100644 --- a/targets/bq_settings/main.cpp +++ b/targets/bq_settings/main.cpp @@ -140,7 +140,7 @@ void serializeDeserializeTest(IO::UART& uart) { int main() { EVT::core::platform::init(); - IO::UART& uart = IO::getUART(115200, true); + IO::UART& uart = IO::getUART(115200); uart.printf("\r\n\r\nBQ SETTING TEST\r\n"); diff --git a/targets/eeprom_dump/main.cpp b/targets/eeprom_dump/main.cpp index 3b6fc0b..5b76fc0 100644 --- a/targets/eeprom_dump/main.cpp +++ b/targets/eeprom_dump/main.cpp @@ -19,7 +19,7 @@ namespace log = EVT::core::log; int main() { EVT::core::platform::init(); - IO::UART& uart = IO::getUART(115200, true); + IO::UART& uart = IO::getUART(115200); uart.printf("\r\n\r\nEEPROM Dump\r\n"); @@ -29,7 +29,8 @@ int main() { log::LOGGER.setUART(&uart); log::LOGGER.setLogLevel(log::Logger::LogLevel::DEBUG); - BMS::DEV::BQ76952 bq(i2c, 0x08); + IO::GPIO& bqReset = IO::getGPIO(); + BMS::DEV::BQ76952 bq(i2c, 0x08, bqReset); BMS::BQSettingsStorage bqSettingsStorage(eeprom, bq); bqSettingsStorage.resetEEPROMOffset(); diff --git a/targets/reset_handler/main.cpp b/targets/reset_handler/main.cpp index 8db550e..ab234f9 100644 --- a/targets/reset_handler/main.cpp +++ b/targets/reset_handler/main.cpp @@ -29,7 +29,7 @@ void canInterruptHandler(IO::CANMessage& message, void* priv) { int main() { EVT::core::platform::init(); - IO::UART& uart = IO::getUART(115200, true); + IO::UART& uart = IO::getUART(115200); uart.printf("\r\n\r\nReset Handler Test\r\n"); diff --git a/targets/settings_transfer/main.cpp b/targets/settings_transfer/main.cpp index 3e46fb6..aa62542 100644 --- a/targets/settings_transfer/main.cpp +++ b/targets/settings_transfer/main.cpp @@ -21,7 +21,7 @@ constexpr uint8_t BQ_I2C_ADDR = 0x08; int main() { EVT::core::platform::init(); - IO::UART& uart = IO::getUART(115200, true); + IO::UART& uart = IO::getUART(115200); IO::I2C& i2c = IO::getI2C(); EVT::core::DEV::M24C32 eeprom(0x57, i2c); @@ -32,7 +32,8 @@ int main() { EVT::core::time::wait(500); - BMS::DEV::BQ76952 bq(i2c, BQ_I2C_ADDR); + IO::GPIO& bqReset = IO::getGPIO(); + BMS::DEV::BQ76952 bq(i2c, 0x08, bqReset); BMS::BQSettingsStorage settingsStorage(eeprom, bq); bool isComplete = false; diff --git a/targets/system_detect/main.cpp b/targets/system_detect/main.cpp index cf197c0..666c6e7 100644 --- a/targets/system_detect/main.cpp +++ b/targets/system_detect/main.cpp @@ -81,7 +81,7 @@ int main() { // Initialize IO IO::CAN& can = IO::getCAN(); can.addIRQHandler(canInterruptHandler, reinterpret_cast(&canParams)); - IO::UART& uart = IO::getUART(115200, true); + IO::UART& uart = IO::getUART(115200); IO::I2C& i2c = IO::getI2C(); // Initialize the timer @@ -95,11 +95,11 @@ int main() { log::LOGGER.setLogLevel(log::Logger::LogLevel::ERROR); // Initialize the BQ interfaces - BMS::DEV::BQ76952 bq(i2c, 0x08); + IO::GPIO& bqReset = IO::getGPIO(); + BMS::DEV::BQ76952 bq(i2c, 0x08, bqReset); BMS::BQSettingsStorage bqSettingsStorage(eeprom, bq); // Initialize the Interlock - // TODO: Determine actual interlock GPIO IO::GPIO& interlockGPIO = IO::getGPIO(IO::GPIO::Direction::INPUT); BMS::DEV::Interlock interlock(interlockGPIO); @@ -107,9 +107,11 @@ int main() { IO::GPIO& alarm = IO::getGPIO(IO::GPIO::Direction::INPUT); // Initialize the system OK pin - // TODO: Determine actual system ok pin IO::GPIO& bmsOK = IO::getGPIO(IO::GPIO::Direction::OUTPUT); + // Initialize the error LED pin + IO::GPIO& errorLed = IO::getGPIO(IO::GPIO::Direction::OUTPUT); + // Initialize the thermistor MUX IO::GPIO* muxSelectArr[3] = { &IO::getGPIO(), @@ -123,7 +125,7 @@ int main() { DEV::IWDG& iwdg = DEV::getIWDG(500); // Initialize the BMS itself - BMS::BMS bms(bqSettingsStorage, bq, interlock, alarm, systemDetect, bmsOK, thermMux, resetHandler, iwdg); + BMS::BMS bms(bqSettingsStorage, bq, interlock, alarm, systemDetect, bmsOK, errorLed, thermMux, resetHandler, iwdg); /////////////////////////////////////////////////////////////////////////// // Setup CAN configuration, this handles making drivers, applying settings. diff --git a/targets/thermistor_mux/main.cpp b/targets/thermistor_mux/main.cpp index f5a2743..115a2c6 100644 --- a/targets/thermistor_mux/main.cpp +++ b/targets/thermistor_mux/main.cpp @@ -18,7 +18,7 @@ int main() { EVT::core::platform::init(); IO::ADC& adc = IO::getADC(); - IO::UART& uart = IO::getUART(115200, true); + IO::UART& uart = IO::getUART(115200); IO::GPIO& muxs1 = IO::getGPIO(); IO::GPIO& muxs2 = IO::getGPIO(); diff --git a/targets/uart_settings_upload/main.cpp b/targets/uart_settings_upload/main.cpp index 18d8f91..1e00ba1 100644 --- a/targets/uart_settings_upload/main.cpp +++ b/targets/uart_settings_upload/main.cpp @@ -13,7 +13,7 @@ int main() { // Initialize system EVT::core::platform::init(); - IO::UART& uart = IO::getUART(9600, true); + IO::UART& uart = IO::getUART(9600); IO::I2C& i2c = IO::getI2C(); EVT::core::DEV::M24C32 eeprom(0x57, i2c);