Add BMS power reset functionality (#706)

This commit is contained in:
Daniel Öster 2025-01-03 00:43:31 +03:00 committed by GitHub
parent f138f97905
commit 33aa75bd7c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 71 additions and 4 deletions

View file

@ -66,6 +66,7 @@
//#define CONTACTOR_CONTROL_DOUBLE_BATTERY //Enable this line to have the emulator hardware control secondary set of contactors for double battery setups (See wiki for pins) //#define CONTACTOR_CONTROL_DOUBLE_BATTERY //Enable this line to have the emulator hardware control secondary set of contactors for double battery setups (See wiki for pins)
//#define PWM_CONTACTOR_CONTROL //Enable this line to use PWM for CONTACTOR_CONTROL, which lowers power consumption and heat generation. CONTACTOR_CONTROL must be enabled. //#define PWM_CONTACTOR_CONTROL //Enable this line to use PWM for CONTACTOR_CONTROL, which lowers power consumption and heat generation. CONTACTOR_CONTROL must be enabled.
//#define NC_CONTACTORS //Enable this line to control normally closed contactors. CONTACTOR_CONTROL must be enabled for this option. Extremely rare setting! //#define NC_CONTACTORS //Enable this line to control normally closed contactors. CONTACTOR_CONTROL must be enabled for this option. Extremely rare setting!
//#define PERIODIC_BMS_RESET //Enable to have the emulator powercycle the connected battery every 24hours via GPIO. Useful for some batteries like Nissan LEAF
/* Shunt/Contactor settings */ /* Shunt/Contactor settings */
//#define BMW_SBOX // SBOX relay control & battery current/voltage measurement //#define BMW_SBOX // SBOX relay control & battery current/voltage measurement

View file

@ -39,6 +39,11 @@ unsigned long negativeStartTime = 0;
unsigned long prechargeCompletedTime = 0; unsigned long prechargeCompletedTime = 0;
unsigned long timeSpentInFaultedMode = 0; unsigned long timeSpentInFaultedMode = 0;
#endif #endif
unsigned long currentTime = 0;
unsigned long lastPowerRemovalTime = 0;
const unsigned long powerRemovalInterval = 24 * 60 * 60 * 1000; // 24 hours in milliseconds
const unsigned long powerRemovalDuration = 30000; // 30 seconds in milliseconds
bool isBMSResetActive = false;
void set(uint8_t pin, bool direction, uint32_t pwm_freq = 0xFFFF) { void set(uint8_t pin, bool direction, uint32_t pwm_freq = 0xFFFF) {
#ifdef PWM_CONTACTOR_CONTROL #ifdef PWM_CONTACTOR_CONTROL
@ -82,18 +87,24 @@ void init_contactors() {
set(SECOND_NEGATIVE_CONTACTOR_PIN, OFF); set(SECOND_NEGATIVE_CONTACTOR_PIN, OFF);
#endif // CONTACTOR_CONTROL_DOUBLE_BATTERY #endif // CONTACTOR_CONTROL_DOUBLE_BATTERY
// Init BMS contactor // Init BMS contactor
#ifdef HW_STARK // TODO: Rewrite this so LilyGo can also handle this BMS contactor #ifdef HW_STARK // This hardware has dedicated pin, always enable on start
pinMode(BMS_POWER, OUTPUT); pinMode(BMS_POWER, OUTPUT);
digitalWrite(BMS_POWER, HIGH); digitalWrite(BMS_POWER, HIGH);
#endif // HW_STARK #endif // HW_STARK
#ifdef PERIODIC_BMS_RESET // User has enabled BMS reset, turn on output on start
pinMode(BMS_POWER, OUTPUT);
digitalWrite(BMS_POWER, HIGH);
#endif //PERIODIC_BMS_RESET
} }
// Main functions // Main functions of the handle_contactors include checking if inverter allows for closing, checking battery 2, checking BMS power output, and actual contactor closing/precharge via GPIO
void handle_contactors() { void handle_contactors() {
#if defined(SMA_BYD_H_CAN) || defined(SMA_BYD_HVS_CAN) || defined(SMA_TRIPOWER_CAN) #if defined(SMA_BYD_H_CAN) || defined(SMA_BYD_HVS_CAN) || defined(SMA_TRIPOWER_CAN)
datalayer.system.status.inverter_allows_contactor_closing = digitalRead(INVERTER_CONTACTOR_ENABLE_PIN); datalayer.system.status.inverter_allows_contactor_closing = digitalRead(INVERTER_CONTACTOR_ENABLE_PIN);
#endif #endif
handle_BMSpower(); // Some batteries need to be periodically power cycled
#ifdef CONTACTOR_CONTROL_DOUBLE_BATTERY #ifdef CONTACTOR_CONTROL_DOUBLE_BATTERY
handle_contactors_battery2(); handle_contactors_battery2();
#endif // CONTACTOR_CONTROL_DOUBLE_BATTERY #endif // CONTACTOR_CONTROL_DOUBLE_BATTERY
@ -142,7 +153,7 @@ void handle_contactors() {
return; return;
} }
unsigned long currentTime = millis(); currentTime = millis();
if (currentTime < INTERVAL_10_S) { if (currentTime < INTERVAL_10_S) {
// Skip running the state machine before system has started up. // Skip running the state machine before system has started up.
@ -202,3 +213,39 @@ void handle_contactors_battery2() {
} }
} }
#endif // CONTACTOR_CONTROL_DOUBLE_BATTERY #endif // CONTACTOR_CONTROL_DOUBLE_BATTERY
/* Once every 24 hours we remove power from the BMS_power pin for 30 seconds. This makes the BMS recalculate all SOC% and avoid memory leaks
During that time we also set the emulator state to paused in order to not try and send CAN messages towards the battery
Feature is only used if user has enabled PERIODIC_BMS_RESET in the USER_SETTINGS */
void handle_BMSpower() {
#ifdef PERIODIC_BMS_RESET
// Get current time
currentTime = millis();
// Check if 24 hours have passed since the last power removal
if (currentTime - lastPowerRemovalTime >= powerRemovalInterval && !isBMSResetActive) {
lastPowerRemovalTime = currentTime; // Record the time when BMS reset was started
// Set emulator state to paused (Max Charge/Discharge = 0 & CAN = stop)
// TODO: We try to keep contactors engaged during this pause, and just ramp power down to 0.
// If this turns out to not work properly, set also the third option to true to open contactors
setBatteryPause(true, true, false, false);
digitalWrite(BMS_POWER, LOW); // Remove power by setting the BMS power pin to LOW
isBMSResetActive = true; // Set a flag to indicate power removal is active
}
// If power has been removed for 30 seconds, restore the power and resume the emulator
if (isBMSResetActive && currentTime - lastPowerRemovalTime >= powerRemovalDuration) {
// Reapply power to the BMS
digitalWrite(BMS_POWER, HIGH);
//Resume the battery pause and CAN communication
setBatteryPause(false, false, false, false);
isBMSResetActive = false; // Reset the power removal flag
}
#endif //PERIODIC_BMS_RESET
}

View file

@ -6,6 +6,15 @@
#include "../../datalayer/datalayer.h" #include "../../datalayer/datalayer.h"
#include "../../devboard/utils/events.h" #include "../../devboard/utils/events.h"
/**
* @brief Handle BMS power output
*
* @param[in] void
*
* @return void
*/
void handle_BMSpower();
/** /**
* @brief Contactor initialization * @brief Contactor initialization
* *

View file

@ -51,6 +51,7 @@
#define POSITIVE_CONTACTOR_PIN 32 #define POSITIVE_CONTACTOR_PIN 32
#define NEGATIVE_CONTACTOR_PIN 33 #define NEGATIVE_CONTACTOR_PIN 33
#define PRECHARGE_PIN 25 #define PRECHARGE_PIN 25
#define BMS_POWER 18 // Note, this pin collides with CAN add-ons and Chademo
// SMA CAN contactor pins // SMA CAN contactor pins
#define INVERTER_CONTACTOR_ENABLE_PIN 5 #define INVERTER_CONTACTOR_ENABLE_PIN 5

View file

@ -44,6 +44,15 @@
#endif #endif
#endif #endif
#ifdef HW_LILYGO
#ifdef PERIODIC_BMS_RESET
#if defined(CAN_ADDON) || defined(CANFD_ADDON) || defined(CHADEMO_BATTERY)
//Check that BMS reset is not used at the same time as Chademo and CAN addons
#error BMS RESET CANNOT BE USED AT SAME TIME AS CAN-ADDONS / CHADMEO! NOT ENOUGH GPIO!
#endif
#endif
#endif
#ifndef BATTERY_SELECTED #ifndef BATTERY_SELECTED
#error No battery selected! Choose one from the USER_SETTINGS.h file #error No battery selected! Choose one from the USER_SETTINGS.h file
#endif #endif