From ca596188762687547aa648cdf01055c9f7a745d0 Mon Sep 17 00:00:00 2001 From: Ramon Borba Date: Mon, 14 Aug 2023 14:27:55 -0300 Subject: [PATCH] firmware: drivers: ds277Xg: Refactored ds277Xg init function to correctly set all the configuration registers #157 --- firmware/drivers/ds277Xg/ds277Xg.c | 178 ++++++++++++----------------- 1 file changed, 73 insertions(+), 105 deletions(-) diff --git a/firmware/drivers/ds277Xg/ds277Xg.c b/firmware/drivers/ds277Xg/ds277Xg.c index 31a2eb3..45e8adb 100644 --- a/firmware/drivers/ds277Xg/ds277Xg.c +++ b/firmware/drivers/ds277Xg/ds277Xg.c @@ -1,36 +1,36 @@ /* * ds277Xg.c - * + * * Copyright The EPS 2.0 Contributors. - * + * * This file is part of EPS 2.0. - * + * * EPS 2.0 is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * EPS 2.0 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with EPS 2.0. If not, see . - * + * */ /** * \brief DS277XG+ driver implementation. - * + * * \author Vinicius Pimenta Bernardo * \author Gabriel Mariano Marcelino * \author Ramon de Araujo Borba - * - * \version 0.2.34 - * + * + * \version 0.4.0 + * * \date 2021/08/17 - * + * * \addtogroup ds277Xg * \{ */ @@ -52,103 +52,77 @@ int ds277Xg_init(ds277Xg_config_t *config) return -1; } - + /* Protection register configuration. */ if (ds277Xg_enable_charge(config) != 0) {return -1;} if (ds277Xg_enable_discharge(config) != 0) {return -1;} /* Parameters registers configuration. */ - // Check if already set correctly from EEPROM on power-up. - bool copy_to_eeprom_flag = false; - uint8_t wr_buf[3] = {0}; - uint8_t rd_buf[2] = {0}; - - /* Checking control register */ - if (ds277Xg_read_data(config, DS277XG_CONTROL_REGISTER, rd_buf, 1) != 0) {return -1;} - else if (rd_buf[0] != 0x0C) // <-- Undervoltage treshold to 2.60V. - { - wr_buf[0] = DS277XG_CONTROL_REGISTER; - wr_buf[1] = 0x0C; // <-- Sets undervoltage treshold to 2.60V. - if (ds277Xg_write_data(config, wr_buf, 2) != 0) {return -1;} - copy_to_eeprom_flag = true; - } - - /* Checking sense resistor prime register */ - if (ds277Xg_read_data(config, DS277XG_SENSE_RESISTOR_PRIME_REGISTER, rd_buf, 1) != 0) {return -1;} - else if (rd_buf[0] != (uint8_t)(DS277XG_RSENSE_CONDUCTANCE)) // <-- Register value must be Rsense conductanvce - { - // Sets the correct value - wr_buf[0] = DS277XG_SENSE_RESISTOR_PRIME_REGISTER; - wr_buf[1] = (uint8_t)(DS277XG_RSENSE_CONDUCTANCE); - if (ds277Xg_write_data(config, wr_buf, 2) != 0) {return -1;} - if (copy_to_eeprom_flag != true) {copy_to_eeprom_flag = true;} - } - - /* Checking charge voltage register */ - if (ds277Xg_read_data(config, DS277XG_CHARGE_VOLTAGE_REGISTER, rd_buf, 1) != 0) {return -1;} - else if (rd_buf[0] != (uint8_t)(CELL_FULLY_CHARGED_VOLTAGE / DS277XG_CHARGE_VOLTAGE_REG_RESOLUTION)) // <-- Fully charged baterry voltage (in register units) - { - // Sets the correct value - wr_buf[0] = DS277XG_CHARGE_VOLTAGE_REGISTER; - wr_buf[1] = (uint8_t)(CELL_FULLY_CHARGED_VOLTAGE / DS277XG_CHARGE_VOLTAGE_REG_RESOLUTION); - if (ds277Xg_write_data(config, wr_buf, 2) != 0) {return -1;} - if (copy_to_eeprom_flag != true) {copy_to_eeprom_flag = true;} - } - - /* Checking minimum charge current ragister */ - if (ds277Xg_read_data(config, DS277XG_MINIMUM_CHARGE_CURRENT_REGISTER, rd_buf, 1) != 0) {return -1;} - else if (rd_buf[0] != (uint8_t)((CELL_MINIMUM_CHARGE_CURRENT * DS277XG_RSENSE_MOHMS) / DS277XG_MINIMUM_CHARGE_CURRENT_REG_RESOLUTION)) // <-- Minimum charging current (in register units) + bool rewrite = false; + uint8_t read_buffer[DS277XG_PARAMETER_EEPROM_SIZE] = { 0 }; + uint8_t params[DS277XG_PARAMETER_EEPROM_SIZE+1] = { + DS277XG_PARAMETER_EEPROM_ADDRESS, // First byte must be address for write operation + DS277XG_CONTROL_REG_VALUE, + DS277XG_ACCUMULATION_BIAS_REG_VALUE, + DS277XG_AGING_CAPACITY_REG_VALUE_MSB, + DS277XG_AGING_CAPACITY_REG_VALUE_LSB, + DS277XG_CHARGE_VOLTAGE_REG_VALUE, + DS277XG_MINIMUM_CHARGE_CURRENT_REG_VALUE, + DS277XG_ACTIVE_EMPTY_VOLTAGE_REG_VALUE, + DS277XG_ACTIVE_EMPTY_CURRENT_REG_VALUE, + DS277XG_ACTIVE_EMPTY_40_REG_VALUE, + DS277XG_SENSE_RESISTOR_PRIME_REG_VALUE, + DS277XG_FULL_40_MSB_REG_VALUE, + DS277XG_FULL_40_LSB_REG_VALUE, + DS277XG_FULL_SEGMENTE_4_SLOPE_REG_VALUE, + DS277XG_FULL_SEGMENTE_3_SLOPE_REG_VALUE, + DS277XG_FULL_SEGMENTE_2_SLOPE_REG_VALUE, + DS277XG_FULL_SEGMENTE_1_SLOPE_REG_VALUE, + DS277XG_AE_SEGMENTE_4_SLOPE_REG_VALUE, + DS277XG_AE_SEGMENTE_3_SLOPE_REG_VALUE, + DS277XG_AE_SEGMENTE_2_SLOPE_REG_VALUE, + DS277XG_AE_SEGMENTE_1_SLOPE_REG_VALUE, + DS277XG_SE_SEGMENTE_4_SLOPE_REG_VALUE, + DS277XG_SE_SEGMENTE_3_SLOPE_REG_VALUE, + DS277XG_SE_SEGMENTE_2_SLOPE_REG_VALUE, + DS277XG_SE_SEGMENTE_1_SLOPE_REG_VALUE, + DS277XG_SENSE_RESISTOR_GAIN_REG_VALUE_MSB, + DS277XG_SENSE_RESISTOR_GAIN_REG_VALUE_LSB, + DS277XG_SENSE_RESISTOR_TEMPERATURE_COEFFICIENT_REG_VALUE, + DS277XG_CURRENT_OFFSET_BIAS_REG_VALUE, + DS277XG_TBP34_REG_VALUE, + DS277XG_TBP23_REG_VALUE, + DS277XG_TBP12_REG_VALUE, + DS277XG_PROTECTOR_THRESHOLD_REG_VALUE, + DS277XG_TWO_WIRE_SLAVE_ADDRESS_REG_VALUE, + }; + + /* Read data from DS277Xg parameter EEPROM memory */ + if (ds277Xg_read_data(config, DS277XG_PARAMETER_EEPROM_ADDRESS, read_buffer, DS277XG_PARAMETER_EEPROM_SIZE) != 0) { return -1; }; + + /* Check if registers are set correctly */ + for (uint8_t i = 0; i < DS277XG_PARAMETER_EEPROM_SIZE; i++) { - // Sets the correct value - wr_buf[0] = DS277XG_MINIMUM_CHARGE_CURRENT_REGISTER; - wr_buf[1] = (uint8_t)((CELL_MINIMUM_CHARGE_CURRENT * DS277XG_RSENSE_MOHMS) / DS277XG_MINIMUM_CHARGE_CURRENT_REG_RESOLUTION); - if (ds277Xg_write_data(config, wr_buf, 2) != 0) {return -1;} - if (copy_to_eeprom_flag != true) {copy_to_eeprom_flag = true;} + if (read_buffer[i] != params[i+1]) + { + rewrite = true; + } } - - /* Checking active empty voltage register */ - if (ds277Xg_read_data(config, DS277XG_ACTIVE_EMPTY_VOLTAGE_REGISTER, rd_buf, 1) != 0) {return -1;} - else if (rd_buf[0] != (uint8_t)(CELL_ACTIVE_EMPTY_VOLTAGE/DS277XG_ACTIVE_EMPTY_VOLTAGE_REG_RESOLUTION)) // <-- Active empty voltage threshold (in register units) + if (rewrite) { - // Sets the correct value - wr_buf[0] = DS277XG_ACTIVE_EMPTY_VOLTAGE_REGISTER; - wr_buf[1] = /* PLACEHOLDER VALUE --> */(uint8_t)(CELL_ACTIVE_EMPTY_VOLTAGE/DS277XG_ACTIVE_EMPTY_VOLTAGE_REG_RESOLUTION); - if (ds277Xg_write_data(config, wr_buf, 2) != 0) {return -1;} - if (copy_to_eeprom_flag != true) {copy_to_eeprom_flag = true;} - } - - /* Checking active empty current register */ - if (ds277Xg_read_data(config, DS277XG_ACTIVE_EMPTY_CURRENT_REGISTER, rd_buf, 1) != 0) {return -1;} - else if (rd_buf[0] != /* PLACEHOLDER VALUE --> */(uint8_t)(CELL_ACTIVE_EMPTY_CURRENT*DS277XG_RSENSE_MOHMS/DS277XG_ACTIVE_EMPTY_CURRENT_REG_RESOLUTION)) // <-- Active empty discharge current (in register units) - { - // Sets the correct value - wr_buf[0] = DS277XG_ACTIVE_EMPTY_CURRENT_REGISTER; - wr_buf[1] = (uint8_t)(CELL_ACTIVE_EMPTY_CURRENT*DS277XG_RSENSE_MOHMS/DS277XG_ACTIVE_EMPTY_CURRENT_REG_RESOLUTION); - if (ds277Xg_write_data(config, wr_buf, 2) != 0) {return -1;} - if (copy_to_eeprom_flag != true) {copy_to_eeprom_flag = true;} - } - - /* TO DO - - Review values for: - --> Full point detection minimum current threshold (DS277XG_MINIMUM_CHARGE_CURRENT_REGISTER) - --> Full point detection charge voltage threshold (DS277XG_CHARGE_VOLTAGE_REGISTER) - --> Aging Capacity - --> Aging Scalar - - Define and set the values for: - --> Active Empty point detection voltage threshold register (DS277XG_ACTIVE_EMPTY_VOLTAGE_REGISTER) - --> Active Empty point detection current threshold register (DS277XG_ACTIVE_EMPTY_CURRENT_REGISTER) - */ - - if (copy_to_eeprom_flag == true) - { - // Copy from shadow RAM to EEPROM. - wr_buf[0] = DS277XG_TWO_WIRE_COMMAND_REGISTER; - wr_buf[1] = DS277XG_COPY_DATA_PARAMETER_EEPROM; + /* Write parameters to DS277Xg RAM memory */ + ds277Xg_write_data(config, params, DS277XG_PARAMETER_EEPROM_SIZE); + + /* Send copy data command to store the values in the DS277Xg EEPROM memory */ + uint8_t wr_buf[2] = { + DS277XG_TWO_WIRE_COMMAND_REGISTER, + DS277XG_COPY_DATA_PARAMETER_EEPROM, + }; if (ds277Xg_write_data(config, wr_buf, 2) != 0) {return -1;} } #if defined(RESET_BATTERY_TO_INITIAL_STATE) && (RESET_BATTERY_TO_INITIAL_STATE == 1) - if (ds277Xg_set_battery_to_initial_state() != 0) + if (ds277Xg_set_battery_to_initial_state(config) != 0) { sys_log_print_event_from_module(SYS_LOG_ERROR, DS277XG_MODULE_NAME, "Error configuring battery to initial state!"); sys_log_new_line(); @@ -164,13 +138,7 @@ int ds277Xg_set_battery_to_initial_state(ds277Xg_config_t *config) /* Set battery configurations to initial state */ - /* Set Aging Capacity register to maximum battery capacity */ - wr_buf[0] = DS277XG_AGING_CAPACITY_REGISTER_MSB; - wr_buf[1] = (uint8_t)((uint16_t)(MAX_BATTERY_CHARGE * DS277XG_RSENSE_MOHMS) >> 8); - wr_buf[2] = (uint8_t)((uint16_t)(MAX_BATTERY_CHARGE * DS277XG_RSENSE_MOHMS)); - if (ds277Xg_write_data(config, wr_buf, 3) != 0) {return -1;} - - /* Set Age Scalar to 95% (recomended on datasheet) */ + /* Set Age Scalar to 100% */ wr_buf[0] = DS277XG_AGE_SCALAR_REGISTER; wr_buf[1] = (uint8_t)(CELL_INITIAL_AGE_SCALAR/DS277XG_AGE_SCALAR_REG_RESOLUTION); if (ds277Xg_write_data(config, wr_buf, 2) != 0) {return -1;} @@ -360,7 +328,7 @@ int ds277Xg_write_accumulated_current_mah(ds277Xg_config_t *config, uint16_t acc int ds277Xg_write_accumulated_current_max_value(ds277Xg_config_t *config) { - return ds277Xg_write_accumulated_current_mah(config, MAX_BATTERY_CHARGE); + return ds277Xg_write_accumulated_current_mah(config, (2*MAX_BATTERY_CHARGE)); } int ds277Xg_read_accumulated_current_raw(ds277Xg_config_t *config, uint16_t *acc_current_raw) @@ -373,7 +341,7 @@ int ds277Xg_read_accumulated_current_raw(ds277Xg_config_t *config, uint16_t *acc uint16_t ds277Xg_accumulated_current_raw_to_mah(uint16_t raw) { - return raw * (DS277XG_ACCUMULATED_CURRENT_REG_RESOLUTION / 1000) / (DS277XG_RSENSE); + return raw * DS277XG_ACCUMULATED_CURRENT_REG_RESOLUTION / (DS277XG_RSENSE_MOHMS); } int ds277Xg_read_accumulated_current_mah(ds277Xg_config_t *config, uint16_t *acc_current_mah)