From 5da8b4ee2fa13a4c72844aad6cdedf273a330875 Mon Sep 17 00:00:00 2001 From: Wojtek Rzepecki Date: Fri, 22 Jan 2021 15:43:16 +0100 Subject: [PATCH] [EGD-5367] Add Fuel Gauge parameters Batery fuel aguge parametrized. Battery charger parameters also added. Appropriate measurements added and configured. --- .../rt1051/bsp/battery-charger/MAX77818.hpp | 19 +- .../bsp/battery-charger/battery_charger.cpp | 298 ++++++++++++------ .../service-evtmgr/WorkerEvent.cpp | 2 +- .../battery-level-check/BatteryLevelCheck.cpp | 6 + .../battery-level-check/BatteryLevelCheck.hpp | 2 + 5 files changed, 230 insertions(+), 97 deletions(-) diff --git a/module-bsp/board/rt1051/bsp/battery-charger/MAX77818.hpp b/module-bsp/board/rt1051/bsp/battery-charger/MAX77818.hpp index 555af190d3661e4ef7d5135dda8388a231e80fff..ff581a8dc13d18283580fdf488e280eac5dca735 100644 --- a/module-bsp/board/rt1051/bsp/battery-charger/MAX77818.hpp +++ b/module-bsp/board/rt1051/bsp/battery-charger/MAX77818.hpp @@ -77,6 +77,7 @@ namespace bsp::battery_charger VEmpty_REG = 0x3A, TIMER_REG = 0x3E, SHDNTIMER_REG = 0x3F, + CURVE = 0xb9, QRtable30_REG = 0x42, dQ_acc_REG = 0x45, @@ -84,8 +85,22 @@ namespace bsp::battery_charger ConvgCfg_REG = 0x49, VFRemCap_REG = 0x4A, QH_REG = 0x4D, - CHG_INT_REG = 0xb0, - CHG_INT_OK = 0xb2 + + CHG_INT_REG = 0xB0, + CHG_INT_OK = 0xB2, + CHG_CNFG_00 = 0xB7, + CHG_CNFG_01 = 0xB8, + CHG_CNFG_02 = 0xB9, + CHG_CNFG_03 = 0xBA, + CHG_CNFG_04 = 0xBB, + CHG_CNFG_05 = 0xBC, + CHG_CNFG_06 = 0xBD, + CHG_CNFG_07 = 0xBE, + CHG_CNFG_09 = 0xC0, + CHG_CNFG_10 = 0xC1, + CHG_CNFG_11 = 0xC2, + CHG_CNFG_12 = 0xC3 + }; // STATUS register bits diff --git a/module-bsp/board/rt1051/bsp/battery-charger/battery_charger.cpp b/module-bsp/board/rt1051/bsp/battery-charger/battery_charger.cpp index ac35996109fc10f29e13b1013279c02d6e440767..6f98bbc91a6dcf7ea51e6a5071b83a5ff15c6a1d 100644 --- a/module-bsp/board/rt1051/bsp/battery-charger/battery_charger.cpp +++ b/module-bsp/board/rt1051/bsp/battery-charger/battery_charger.cpp @@ -11,6 +11,8 @@ #include "drivers/i2c/DriverI2C.hpp" #include #include +#include +#include namespace bsp::battery_charger { @@ -18,32 +20,63 @@ namespace bsp::battery_charger { constexpr std::uint32_t i2cSubaddresSize = 1; - const auto cfgFile = purefs::dir::getCurrentOSPath() / "batteryAdjustementConfig.cfg"; - const auto cfgFilePrev = purefs::dir::getCurrentOSPath() / "batteryAdjustementConfig_old.cfg"; + const auto cfgFile = purefs::dir::getCurrentOSPath() / "batteryFuelGaugeConfig.cfg"; + constexpr auto registersToStore = 0xFF + 1; - constexpr std::uint16_t BATT_SERVICE_AVG_CURRENT_PERIOD = - 0x00; //< 0.1758 ms * 2^(2 + BATT_SERVICE_AVG_CURRENT_PERIOD) == 700ms - constexpr std::uint16_t BATT_SERVICE_AVG_CELL_VOLTAGE_PERIOD = - 0x00; //< 0.1758 ms * 2^(6 + BATT_SERVICE_AVG_CELL_VOLTAGE_PERIOD) == 11.25 s - constexpr std::uint16_t BATT_SERVICE_AVG_MIXING_PERIOD = - 0x0D; //< 0.1758 ms * 2^(5 + BATT_SERVICE_AVG_MIXING_PERIOD) == 12.8 h - constexpr std::uint16_t BATT_SERVICE_AVG_TEMP_PERIOD = - 0x01; //< 0.1758 ms * 2^(11 + BATT_SERVICE_AVG_TEMP_PERIOD) == 12 min - constexpr std::uint16_t BATT_SERVICE_AVG_NEMPTY_PERIOD = 0x00; + constexpr std::uint16_t ENABLE_ALL_IRQ_MASK = 0xF8; + constexpr std::uint8_t UNLOCK_CHARGER = 0x3 << 2; - constexpr auto ENABLE_ALL_IRQ_MASK = 0xf8; + constexpr std::uint8_t VSYS_MIN = 0x80; // 3.6V + constexpr std::uint8_t CHARGE_TARGET_VOLTAGE = 0x1D; // 4.35V - constexpr std::uint16_t nominalCapacitymAh = 3000; + constexpr std::uint8_t MAX_CHARGE_CURRENT = 0x30; // 1600mA -> 1C + constexpr std::uint8_t FAST_CHARGE_CURRENT = 0x0A; // 500mA - constexpr std::uint8_t fullyChargedPercent = 100; - constexpr std::uint8_t DischargedPercent = 15; + constexpr std::uint16_t nominalCapacitymAh = 1600; constexpr std::uint8_t maxTemperatureDegrees = 50; constexpr std::uint8_t minTemperatureDegrees = 5; - constexpr std::uint16_t maxVoltagemV = 4200; + constexpr std::uint16_t maxVoltagemV = 4350; constexpr std::uint16_t minVoltagemV = 3600; + constexpr auto currentSenseGain = 0.15625; // mA + constexpr auto voltageSenseGain = 0.078125; // mV + + // NTC calibration values + constexpr std::uint16_t temperatureConversionGain = 0xEE56; + constexpr std::uint16_t temperatureConversionOffset = 0x1DA4; + + namespace fuel_gauge_params + { + /// Parameters calculated in in MAXIM EVKIT software + /// Initial parameters for fuel gauge battery model + + constexpr std::uint16_t LearnCFG = 0x2602; + constexpr std::uint16_t FilterCFG = 0xCEA4; + constexpr std::uint16_t MiscCFG = 0x01D0; + constexpr std::uint16_t RelaxCFG = 0x2039; + constexpr std::uint16_t RCOMP0 = 0x0070; + constexpr std::uint16_t TempCo = 0x263D; + constexpr std::uint16_t QResidual00 = 0x2280; + constexpr std::uint16_t QResidual10 = 0x1000; + constexpr std::uint16_t QResidual20 = 0x0681; + constexpr std::uint16_t QResidual30 = 0x0682; + /// 1600mAh initial battery capacity + constexpr std::uint16_t FullCAPNom = 0x0C80; + constexpr std::uint16_t FullCAPRep = 0x0C80; + constexpr std::uint16_t DesignCap = 0x0C80; + constexpr std::uint16_t dQacc = 0x00C8; + constexpr std::uint16_t dPacc = 0x0C80; + /// Charge termination current = 150mA + constexpr std::uint16_t ICHGTerm = 0x03C0; + /// Empty battery = 3V + constexpr std::uint16_t V_empty = 0x965A; + /// Fully charged threshold = 90% + constexpr std::uint16_t FullSOCthr = 0x5A00; + + } // namespace fuel_gauge_params + std::shared_ptr i2c; std::shared_ptr gpio; @@ -125,97 +158,121 @@ namespace bsp::battery_charger return std::make_pair(status, value); } - batteryRetval loadConfiguration() + batteryRetval unlockProtectedChargerRegisters() { - auto fd = std::fopen(cfgFile.c_str(), "r"); - if (fd == nullptr) { - LOG_WARN("Configuration file [%s] could not be opened. Trying to open file [%s]", - cfgFile.c_str(), - cfgFilePrev.c_str()); - fd = std::fopen(cfgFilePrev.c_str(), "r"); - if (fd == nullptr) { - LOG_WARN("Configuration file [%s] could not be opened.", cfgFilePrev.c_str()); - return batteryRetval::ChargerError; - } + if (chargerWrite(Registers::CHG_CNFG_06, UNLOCK_CHARGER) != kStatus_Success) { + LOG_ERROR("Charger registers unlock failed!"); + return batteryRetval::ChargerError; } + return batteryRetval::OK; + } - std::uint16_t regValue = 0; - for (auto i = 0; i < 0xff; ++i) { - if (std::fread(®Value, sizeof(regValue), 1, fd) != sizeof(regValue)) { - LOG_ERROR("Reading register 0x%x failed.", i); - std::fclose(fd); - return batteryRetval::ChargerError; - } - - if (fuelGaugeWrite(static_cast(i), regValue) != kStatus_Success) { - LOG_ERROR("Writing register 0x%x failed.", i); - std::fclose(fd); - return batteryRetval::ChargerError; - } + batteryRetval lockProtectedChargerRegisters() + { + if (chargerWrite(Registers::CHG_CNFG_06, 0) != kStatus_Success) { + LOG_ERROR("Charger registers lock failed!"); + return batteryRetval::ChargerError; } - - std::fclose(fd); return batteryRetval::OK; } - batteryRetval storeConfiguration() + void configureBatteryCharger() { - // TODO:M.P procedure below seems to crash system, it should be fixed. - if (ff_rename(cfgFile.c_str(), cfgFilePrev.c_str(), false) != 0) { - LOG_ERROR("Could not move configuration file"); - return batteryRetval::ChargerError; + unlockProtectedChargerRegisters(); + + std::uint8_t value = CHARGE_TARGET_VOLTAGE | VSYS_MIN; + if (chargerWrite(Registers::CHG_CNFG_04, value) != kStatus_Success) { + LOG_ERROR("Charge target voltage write fail"); } - auto fd = std::fopen(cfgFile.c_str(), "w"); - if (fd == nullptr) { - LOG_ERROR("Could not open configuration file"); + value = MAX_CHARGE_CURRENT; + if (chargerWrite(Registers::CHG_CNFG_09, value) != kStatus_Success) { + LOG_ERROR("Maximum charge current write fail"); + } + + value = FAST_CHARGE_CURRENT; + if (chargerWrite(Registers::CHG_CNFG_02, value) != kStatus_Success) { + LOG_ERROR("Fast charge current write fail"); + } + + lockProtectedChargerRegisters(); + } + + batteryRetval configureFuelGaugeBatteryModel() + { + int status = fuelGaugeWrite(Registers::LearnCFG_REG, fuel_gauge_params::LearnCFG); + status |= fuelGaugeWrite(Registers::FilterCFG_REG, fuel_gauge_params::FilterCFG); + status |= fuelGaugeWrite(Registers::MiscCFG_REG, fuel_gauge_params::MiscCFG); + status |= fuelGaugeWrite(Registers::RelaxCFG_REG, fuel_gauge_params::RelaxCFG); + status |= fuelGaugeWrite(Registers::RCOMP0_REG, fuel_gauge_params::RCOMP0); + status |= fuelGaugeWrite(Registers::TempCo_REG, fuel_gauge_params::TempCo); + status |= fuelGaugeWrite(Registers::QRtable00_REG, fuel_gauge_params::QResidual00); + status |= fuelGaugeWrite(Registers::QRtable10_REG, fuel_gauge_params::QResidual10); + status |= fuelGaugeWrite(Registers::QRtable20_REG, fuel_gauge_params::QResidual20); + status |= fuelGaugeWrite(Registers::QRtable30_REG, fuel_gauge_params::QResidual30); + status |= fuelGaugeWrite(Registers::FullCAPNom_REG, fuel_gauge_params::FullCAPNom); + status |= fuelGaugeWrite(Registers::FullCapRep_REG, fuel_gauge_params::FullCAPRep); + status |= fuelGaugeWrite(Registers::DesignCap_REG, fuel_gauge_params::DesignCap); + status |= fuelGaugeWrite(Registers::dQ_acc_REG, fuel_gauge_params::dQacc); + status |= fuelGaugeWrite(Registers::dP_acc_REG, fuel_gauge_params::dPacc); + status |= fuelGaugeWrite(Registers::ICHGTERM_REG, fuel_gauge_params::ICHGTerm); + status |= fuelGaugeWrite(Registers::VEmpty_REG, fuel_gauge_params::V_empty); + status |= fuelGaugeWrite(Registers::FullSOCthr_REG, fuel_gauge_params::FullSOCthr); + + if (status != kStatus_Success) { + LOG_ERROR("configureFuelGaugeBatteryModel failed."); return batteryRetval::ChargerError; } + return batteryRetval::OK; + } - for (unsigned int i = 0; i < 0xff; ++i) { - auto regVal = fuelGaugeRead(static_cast(i)); - if (regVal.first != kStatus_Success) { - LOG_ERROR("Reading register 0x%x failed.", i); - std::fclose(fd); + batteryRetval loadConfiguration() + { + std::ifstream file(cfgFile.c_str(), std::ios::binary | std::ios::in); + if (!file.is_open()) { + LOG_WARN("Configuration file [%s] could not be opened. Loading initial configuration.", + cfgFile.c_str()); + if (configureFuelGaugeBatteryModel() == batteryRetval::OK) { + return batteryRetval::OK; + } + else { return batteryRetval::ChargerError; } + } - if (std::fwrite(®Val.second, sizeof(regVal.second), 1, fd) != sizeof(regVal.second)) { - LOG_ERROR("Storing register 0x%x failed.", i); - std::fclose(fd); - std::remove(cfgFile.c_str()); + std::uint16_t regVal; + for (auto i = 0; i < registersToStore; ++i) { + file.read(reinterpret_cast(®Val), sizeof(std::uint16_t)); + if (fuelGaugeWrite(static_cast(i), regVal) != kStatus_Success) { + LOG_ERROR("Writing register 0x%x failed.", i); + file.close(); return batteryRetval::ChargerError; } } + file.close(); - std::fclose(fd); return batteryRetval::OK; } - batteryRetval setAvgCalcPeriods() + batteryRetval storeConfiguration() { - std::uint16_t regVal = 0; - regVal |= (BATT_SERVICE_AVG_CURRENT_PERIOD << 0); - regVal |= (BATT_SERVICE_AVG_CELL_VOLTAGE_PERIOD << 4); - regVal |= (BATT_SERVICE_AVG_MIXING_PERIOD << 7); - regVal |= (BATT_SERVICE_AVG_TEMP_PERIOD << 11); - regVal |= (BATT_SERVICE_AVG_NEMPTY_PERIOD << 14); - - if (fuelGaugeWrite(Registers::FilterCFG_REG, regVal) != kStatus_Success) { - LOG_ERROR("setAvgCalcPeriods failed."); + std::ofstream file(cfgFile.c_str(), std::ios::binary | std::ios::out); + if (!file.is_open()) { + LOG_WARN("Configuration file [%s] could not be opened.", cfgFile.c_str()); return batteryRetval::ChargerError; } - return batteryRetval::OK; - } - - batteryRetval setNominalBatteryCapacity(std::uint16_t capacity) - { - std::uint16_t regVal = capacity * 2; - if (fuelGaugeWrite(Registers::DesignCap_REG, regVal) != kStatus_Success) { - LOG_ERROR("setNominalBatteryCapacity failed."); - return batteryRetval::ChargerError; + for (unsigned int i = 0; i < registersToStore; ++i) { + auto regVal = fuelGaugeRead(static_cast(i)); + if (regVal.first != kStatus_Success) { + LOG_ERROR("Reading register 0x%x failed.", i); + file.close(); + return batteryRetval::ChargerError; + } + file.write(reinterpret_cast(®Val.second), sizeof(std::uint16_t)); } + file.close(); + return batteryRetval::OK; } @@ -254,24 +311,38 @@ namespace bsp::battery_charger return batteryRetval::OK; } - batteryRetval enableFuelGuageIRQs() + batteryRetval fillConfig2RegisterValue() { - std::uint16_t regVal = static_cast(CONFIG2::dSOCen); + std::uint16_t regVal = static_cast(CONFIG2::dSOCen) | // SOC 1% change alert + static_cast(CONFIG2::OCVQen); // Enable automatic empty compensation if (fuelGaugeWrite(Registers::CONFIG2_REG, regVal) != kStatus_Success) { - LOG_ERROR("enableFuelGuageIRQs failed."); + LOG_ERROR("fillConfig2RegisterValue failed."); return batteryRetval::ChargerError; } return batteryRetval::OK; } - batteryRetval configureAlerts() + batteryRetval fillConfigRegisterValue() { - std::uint16_t regVal = static_cast(CONFIG::Aen); + std::uint16_t regVal = static_cast(CONFIG::Aen) // Enable alerts + | static_cast(CONFIG::Ten) // Enable tepreature conversion + | static_cast(CONFIG::ETHRM); // External thermistor if (fuelGaugeWrite(Registers::CONFIG_REG, regVal) != kStatus_Success) { - LOG_ERROR("configureAlerts failed."); + LOG_ERROR("fillConfigRegisterValue failed."); + return batteryRetval::ChargerError; + } + + return batteryRetval::OK; + } + + batteryRetval configureTemperatureMeasurement() + { + if ((fuelGaugeWrite(Registers::TGAIN_REG, temperatureConversionGain) & + fuelGaugeWrite(Registers::TOFF_REG, temperatureConversionOffset)) != kStatus_Success) { + LOG_ERROR("configureTemperatureMeasurement failed."); return batteryRetval::ChargerError; } @@ -313,6 +384,45 @@ namespace bsp::battery_charger gpio->EnableInterrupt(1 << static_cast(BoardDefinitions::BATTERY_CHARGER_INOKB_PIN)); gpio->EnableInterrupt(1 << static_cast(BoardDefinitions::BATTERY_CHARGER_INTB_PIN)); } + + int getCellTemperature() + { + auto value = fuelGaugeRead(Registers::TEMP_REG); + int temperature = value.second >> 8; + if (value.second & 0x8000) { + temperature *= -1; + } + LOG_INFO("Battery cell temperature = %d Cdeg.", temperature); + return temperature; + } + + int getCurrentMeasurement() + { + auto value = fuelGaugeRead(Registers::Current_REG); + int current; + // 2's compliment into decimal + if (value.second & 0x8000) { + // negative numbers + std::bitset<16> currentBitset = std::bitset<16>(value.second - 1); + currentBitset.flip(); + current = + static_cast((static_cast(currentBitset.to_ulong()) * -1) * currentSenseGain); + } + else { + // positive numbers + current = static_cast(value.second * currentSenseGain); + } + LOG_INFO("Battery current measurement = %d mA.", current); + return current; + } + + int getCellVoltage() + { + auto value = fuelGaugeRead(Registers::VCELL_REG); + int voltage = value.second * voltageSenseGain; + LOG_INFO("Battery cell voltage measurement = %d mV.", voltage); + return voltage; + } } // namespace int init(xQueueHandle queueHandle) @@ -324,21 +434,22 @@ namespace bsp::battery_charger IRQQueueHandle = queueHandle; + configureBatteryCharger(); + // check Power-On reset bit std::uint16_t status = fuelGaugeRead(Registers::STATUS_REG).second; if (status & static_cast(STATUS::POR)) { - LOG_INFO("Initializing battery charger"); + LOG_INFO("Initializing battery fuel gauge model."); loadConfiguration(); - setAvgCalcPeriods(); - setNominalBatteryCapacity(nominalCapacitymAh); - setChargingDischargingThresholds(fullyChargedPercent, DischargedPercent); - setTemperatureThresholds(maxTemperatureDegrees, minTemperatureDegrees); - setServiceVoltageThresholds(maxVoltagemV, minVoltagemV); } - configureAlerts(); - enableFuelGuageIRQs(); + setTemperatureThresholds(maxTemperatureDegrees, minTemperatureDegrees); + setServiceVoltageThresholds(maxVoltagemV, minVoltagemV); + + fillConfigRegisterValue(); + fillConfig2RegisterValue(); + configureTemperatureMeasurement(); StateOfCharge level = getBatteryLevel(); bool charging = getChargeStatus(); @@ -346,7 +457,6 @@ namespace bsp::battery_charger clearAllIRQs(); enableTopIRQs(); - IRQPinsInit(); return 0; diff --git a/module-services/service-evtmgr/WorkerEvent.cpp b/module-services/service-evtmgr/WorkerEvent.cpp index 90a01c7e82d55b69794b23cd7a458515d8930bf2..ce55633d67e041d50a632e3779403ae60caf0ae7 100644 --- a/module-services/service-evtmgr/WorkerEvent.cpp +++ b/module-services/service-evtmgr/WorkerEvent.cpp @@ -262,5 +262,5 @@ void WorkerEvent::processKeyEvent(bsp::KeyEvents event, bsp::KeyCodes code) void WorkerEvent::checkBatteryLevelCritical() { - battery_level_check::checkBatteryLevelCritical(); + battery_level_check::checkBatteryLevelCriticalWithConfirmation(); } diff --git a/module-services/service-evtmgr/battery-level-check/BatteryLevelCheck.cpp b/module-services/service-evtmgr/battery-level-check/BatteryLevelCheck.cpp index 4c1234fe530dd537cf41789f92e5c30668e41b79..4f170c11f6c7d215ea3dcbd0d4d7c26be1ac976e 100644 --- a/module-services/service-evtmgr/battery-level-check/BatteryLevelCheck.cpp +++ b/module-services/service-evtmgr/battery-level-check/BatteryLevelCheck.cpp @@ -78,6 +78,12 @@ namespace battery_level_check } } + void checkBatteryLevelCriticalWithConfirmation() + { + state = CheckState::InitialCheck; + checkBatteryLevelCritical(); + } + void setBatteryCriticalLevel(unsigned int level) { batteryLevelCritical = level; diff --git a/module-services/service-evtmgr/battery-level-check/BatteryLevelCheck.hpp b/module-services/service-evtmgr/battery-level-check/BatteryLevelCheck.hpp index 964b4371c6608f50138a44cee3ea164a85677d32..050035d046405f7ad535678893c17f568208eb73 100644 --- a/module-services/service-evtmgr/battery-level-check/BatteryLevelCheck.hpp +++ b/module-services/service-evtmgr/battery-level-check/BatteryLevelCheck.hpp @@ -16,5 +16,7 @@ namespace battery_level_check void checkBatteryLevelCritical(); + void checkBatteryLevelCriticalWithConfirmation(); + void setBatteryCriticalLevel(unsigned int level); } // namespace battery_level_check