This is a library for the MAX17055 Li+ Battery Fuel Gauge.
Dependents: Low_Power_Long_Distance_IR_Vision_Robot MAX17055_EZconfig MAX17055_EZconfig_Sample Low_Power_Long_Distance_IR_Vision_Robot
Fork of max17055 by
Diff: max17055.cpp
- Revision:
- 17:7447aaa9c121
- Parent:
- 15:291446b008df
- Child:
- 18:37bca022d144
--- a/max17055.cpp Mon Jun 18 21:47:59 2018 +0000 +++ b/max17055.cpp Tue Oct 09 20:28:41 2018 +0000 @@ -36,6 +36,8 @@ /* POR Mask */ #define MAX17055_POR_MASK (0xFFFD) +#define MAX17055_CYCLE_MASK (0x0002) + /* MODELCFG register bits */ #define MAX17055_MODELCFG_REFRESH (1 << 15) @@ -47,7 +49,7 @@ /* LIBRARY FUNCTION SUCCESS*/ #define F_SUCCESS_0 0 -/* LIBRARY FUNCTION ERROR CODES */ +/* LIBRARY FUNCTION ERROR CODES */ #define F_ERROR_1 -1 //-1 if I2C read/write errors exist #define F_ERROR_2 -2 //-2 if device is not present #define F_ERROR_3 -3 //-3 if function error @@ -130,10 +132,33 @@ } /** + * @brief Reads an specified register from the MAX17055 register. + * + * @param[in] reg_addr The register address + * @param value The value + * + * @retval reg_data register data + * @retval statusRead non-0 for errors + */ + +int16_t MAX17055::get_regInfo(Registers_e reg_addr) +{ + uint16_t read_data; + int statusRead; + + statusRead = readReg(reg_addr, read_data); + if (statusRead != F_SUCCESS_0) + return statusRead; + else + return read_data; + +} + +/** * @brief Write and Verify a MAX17055 register * @par Details * This function writes and verifies if the writing process was successful - * + * * @param[in] reg_addr - register address * @param[out] reg_data - the variable that contains the data to write * to the register address @@ -152,13 +177,13 @@ do { statusWrite = writeReg(reg_addr, reg_data); if (statusWrite != F_SUCCESS_0) - ret = -6; + ret = F_ERROR_1; wait_ms(3); statusRead = readReg(reg_addr, read_data); if (statusRead != F_SUCCESS_0) - ret = -7; + ret = F_ERROR_1; if (read_data != reg_data) { - ret = -8; + ret = F_ERROR_3; retries--; } } while (retries && read_data != reg_data); @@ -173,28 +198,27 @@ * @brief Initialization Function for MAX17055. * @par Details * This function initializes the MAX17055 for the implementation of the EZconfig model.\n - * The library needs to be customized for the implementation of customize model.\n - * - * @retval 0 on success + * The library needs to be customized for the implementation of customize model.\n + * + * @retval 0 on success * @retval non-0 for errors */ int MAX17055::init(platform_data des_data) { - int status, ret; + int ret; int time_out = 10; - uint16_t hibcfg_value,read_data; + uint16_t hibcfg_value; - status = readReg(VERSION_REG, read_data); - if (status != F_SUCCESS_0) - return status; +// status = readReg(VERSION_REG, read_data); +// if (status != F_SUCCESS_0) +// return status; ///STEP 0. Check for POR (Skip load model if POR bit is cleared) if (check_POR_func() == F_ERROR_5) return F_ERROR_5; //POR not detected. Skip Initialization. - //This is not an error. ///STEP 1. Check if FStat.DNR == 0 (Do not continue until FSTAT.DNR == 0) ret = poll_flag_clear(FSTAT_REG, MAX17055_FSTAT_DNR, time_out); @@ -205,21 +229,15 @@ ///STEP 1.2. Force exit from hibernate hibcfg_value = forcedExitHiberMode(); - //printf("step 1 check \r\n"); ///STEP 2. Initialize configuration - switch (1) { - case MODEL_LOADING_OPTION1: - ///STEP 2.1. Load EZ Config - EZconfig(des_data); + ///STEP 2.1. Load EZ Config + EZconfig(des_data); - ///STEP 2.2. Poll ModelCFG.ModelRefresh bit for clear - ret = poll_flag_clear(MODELCFG_REG, MAX17055_MODELCFG_REFRESH, time_out); - if(ret < F_SUCCESS_0) { - return ret; - } - - break; + ///STEP 2.2. Poll ModelCFG.ModelRefresh bit for clear + ret = poll_flag_clear(MODELCFG_REG, MAX17055_MODELCFG_REFRESH, time_out); + if(ret < F_SUCCESS_0) { + return ret; } ///STEP3. Restore original HibCfg writeReg(HIBCFG_REG, hibcfg_value); @@ -227,7 +245,7 @@ /* Clear Status.POR */ ret = clear_POR_bit(); if (ret < F_SUCCESS_0) - return ret; //See errors + return ret; //See errors return F_SUCCESS_0; } @@ -239,17 +257,17 @@ * * @retval 0 on success (POR detected) * @retval non-0 for errors (POR not detected) - * + * */ int MAX17055::check_POR_func() { uint16_t read_data; - + readReg(STATUS_REG, read_data); - - if (!(read_data & MAX17055_STATUS_POR ) ) + printf("STATUS REF = %X \r\n", read_data); + if (!(read_data & MAX17055_STATUS_POR ) ) { return F_ERROR_5; //POR not detected. - else + } else return F_SUCCESS_0; } @@ -263,8 +281,8 @@ */ int MAX17055::clear_POR_bit() { - int status, ret; - uint16_t read_data, hibcfg_value, reg; + int status; + uint16_t read_data; status = readReg(STATUS_REG, read_data); @@ -273,12 +291,12 @@ status = write_and_verify_reg(STATUS_REG, (read_data & MAX17055_POR_MASK)); if (status != F_SUCCESS_0) return F_ERROR_1; //read or write error - else + else return F_SUCCESS_0; } /** - * @brief Poll Flag clear Function. + * @brief Poll Flag clear Function. * @par Details * This function clears status flags for the MAX17055 * @@ -286,7 +304,7 @@ * @param[in] mask - register address * @param[in] timeout - register data * - * @retval 0 on success + * @retval 0 on success * @retval non-0 negative for errors */ int MAX17055::poll_flag_clear (Registers_e reg_addr, int mask, int timeout) @@ -313,13 +331,13 @@ * @brief Get Temperature Function from the MAX17055 TEMP register. * @par Details * This function sends a request to access the TEMP register - * of the MAX17055, which reflects the temperature measured for the fuel gauge. + * of the MAX17055, which reflects the temperature measured for the fuel gauge. * The temperature values will reflect the Config Register (0x1D) selections for Tsel bit (D15). * For this library the setting are for die temperature. * The MAX32620FTHR thermistor bias pin is not connected. The biasing of the thermistor is - * done by the MAX77650. See MAX77650 library for how to enable the thermistor biasing. + * done by the MAX77650. See MAX77650 library for how to enable the thermistor biasing. * - * + * * @retval temp - Temperature value from TEMP register in °C * @retval non-0 negative values check for errors */ @@ -389,7 +407,7 @@ const int param_EZ_FG2 = 0x8000; uint16_t dpacc, ret; - ///STEP 2.1.2 Store the EZ Config values into the appropriate registers. + ///STEP 2.1.2 Store the EZ Config values into the appropriate registers. ret = writeReg(DESIGNCAP_REG, des_data.designcap); ret = writeReg(DQACC_REG, des_data.designcap >> 5); //DesignCap divide by 32 ret = writeReg(ICHGTERM_REG, des_data.ichgterm); @@ -398,7 +416,7 @@ if (des_data.vcharge > charger_th) { dpacc = (des_data.designcap >> 5) * chg_V_high / des_data.designcap; ret = writeReg(DPACC_REG, dpacc); - ret = writeReg(MODELCFG_REG, param_EZ_FG1); // + ret = writeReg(MODELCFG_REG, param_EZ_FG1); // } else { dpacc = (des_data.designcap >> 5) * chg_V_low / des_data.designcap; ret = writeReg(DPACC_REG, dpacc); @@ -407,14 +425,42 @@ return ret; } + +/** + * @brief Get reported Battery Capacity Function from MAX17055 Fuel Gauge + * @par Details + * This function sends a request to access the RepCAP register + * of the MAX17055. RepCAP is the reported Battery Capacity in mAh of the battery based on the calulation by the Fuel Gauge algorithm. + * + * @retval repcap_data - Reported SOC data from the RepSOC register in % value. + * @retval non-0 negative values check for errors + */ + +int MAX17055::get_battCAP(platform_data des_data) +{ + int ret, design_rsense; + uint16_t repcap_data; + + ret = readReg(REPCAP_REG, repcap_data); + if (ret < F_SUCCESS_0) + return ret; + else + design_rsense = des_data.rsense; + ret = raw_cap_to_uAh((uint32_t)repcap_data, design_rsense); + if (ret < F_SUCCESS_0) + return ret; + else + return ret; +} + /** * @brief Get reported State Of Charge(SOC) Function from MAX17055 Fuel Gauge. * @par Details * This function sends a request to access the RepSOC register - * of the MAX17055. RepSOC is the reported state-of-charge percentage output of the fuel gauge. + * of the MAX17055. RepSOC is the reported state-of-charge percentage output of the fuel gauge. * * @retval soc_data - Reported SOC data from the RepSOC register in % value. - * @retval non-0 negative values check for errors + * @retval non-0 negative values check for errors */ int MAX17055::get_SOC() { @@ -436,12 +482,12 @@ * @par Details * This function sends a request to access the atAvSOC register of the MAX17055. * The AvSOC registers hold the calculated available capacity and percentage of the - * battery based on all inputs from the ModelGauge m5 algorithm including empty - * compensation. These registers provide unfiltered results. Jumps in the reported + * battery based on all inputs from the ModelGauge m5 algorithm including empty + * compensation. These registers provide unfiltered results. Jumps in the reported * values can be caused by abrupt changes in load current or temperature. * - * @retval atAvSOC_data - Average SOC data from the atAVSOC register in % value. - * @retval non-0 negative values check for errors + * @retval atAvSOC_data - Average SOC data from the atAVSOC register in % value. + * @retval non-0 negative values check for errors */ int MAX17055::get_atAvSOC() { @@ -464,8 +510,8 @@ * of the MAX17055. The MixSOC registers holds the calculated * remaining capacity and percentage of the cell before any empty compensation * adjustments are performed. - * - * @retval mixSOC_data - Mixed SOC register values from the mixSOC register in % value. + * + * @retval mixSOC_data - Mixed SOC register values from the mixSOC register in % value. * @retval non-0 for errors */ int MAX17055::get_mixSOC() @@ -487,9 +533,9 @@ * @par Details * This function sends a request to access the TTE register * of the MAX17055 - * The TTE register holds the estimated time to empty for the - * application under present temperature and load conditions. The TTE value is - * determined by relating AvCap with AvgCurrent. The corresponding AvgCurrent + * The TTE register holds the estimated time to empty for the + * application under present temperature and load conditions. The TTE value is + * determined by relating AvCap with AvgCurrent. The corresponding AvgCurrent * filtering gives a delay in TTE, but provides more stable results. * * @retval tte_data - Time to Empty data from the TTE register in seconds. @@ -517,7 +563,7 @@ * This function sends a request to access the internal register * of the MAX17055 * - * @retval atTTE_data - Time to Empty data from the atTTE register in seconds. + * @retval atTTE_data - Time to Empty data from the atTTE register in seconds. * @retval non-0 negative values check for errors */ float MAX17055::get_atTTE() @@ -543,11 +589,11 @@ * The TTF register holds the estimated time to full for the application * under present conditions. The TTF value is determined by learning the * constant current and constant voltage portions of the charge cycle based - * on experience of prior charge cycles. Time to full is then estimate - * by comparing present charge current to the charge termination current. + * on experience of prior charge cycles. Time to full is then estimate + * by comparing present charge current to the charge termination current. * Operation of the TTF register assumes all charge profiles are consistent in the application. * - * @retval ttf_data - Time to Full data from the TTF register in seconds. + * @retval ttf_data - Time to Full data from the TTF register in seconds. * @retval non-0 negative values check for errors */ float MAX17055::get_TTF() @@ -570,8 +616,8 @@ * @brief Get voltage of the cell Function for MAX17055 Fuel Gauge. * @par Details * This function sends a request to access the VCell Register - * of the MAX17055 to read the measured voltage from the cell. - * + * of the MAX17055 to read the measured voltage from the cell. + * * @retval vcell_data - vcell data from the VCELL_REG register in uVolts. * @retval non-0 negative values check for errors */ @@ -590,66 +636,90 @@ } /** + * @brief Gets Average voltage of the cell Function for MAX17055 Fuel Gauge. + * @par Details + * This function sends a request to access the AvgVCell Register + * of the MAX17055 to read the measured voltage from the cell. + * + * @retval avgVcell_data - avgvcell data from the AVGVCELL_REG register in uVolts. + * @retval non-0 negative values check for errors + */ +int MAX17055::get_avgVcell() +{ + + int ret; + uint16_t avgVcell_data; + + ret = readReg(AVGVCELL_REG, avgVcell_data); + if (ret < F_SUCCESS_0) + return ret; + else + ret = lsb_to_uvolts(avgVcell_data); + return ret; +} + +/** * @brief Get current Function for MAX17055 Fuel Gauge. * @par Details * This function sends a request to access the CURRENT register - * of the MAX17055 to read the current readings. + * of the MAX17055 to read the current readings. * * @param[in] des_data - Plataform_data struct with information about the design. - * - * @retval curr_data - current data from the CURRENT register in uAmps. + * + * @retval curr_data - current data from the CURRENT register in uAmps. * @retval non-0 negative values check for errors. */ -int MAX17055::get_Current( platform_data des_data ) +float MAX17055::get_Current( platform_data des_data ) { int ret,design_rsense; uint16_t curr_data; + float f_ret; ret = readReg(CURRENT_REG, curr_data); if (ret < F_SUCCESS_0) return ret; else - design_rsense = des_data.rsense; - ret = raw_current_to_uamps((uint32_t)curr_data, design_rsense); - return ret; + design_rsense = des_data.rsense; + f_ret = raw_current_to_uamps((uint32_t)curr_data, design_rsense); + return f_ret; } /** * @brief Get average current Function for MAX17055 Fuel Gauge. * @par Details * This function sends a request to access the aveCURRENT register - * of the MAX17055 to read the average current readings. + * of the MAX17055 to read the average current readings. * * @param[in] des_data - Plataform_data struct with information about the design. - * - * @retval aveCurr_data - current data from the AVGCURRENT register in uAmps. + * + * @retval aveCurr_data - current data from the AVGCURRENT register in uAmps. * @retval non-0 negative values check for errors. */ -int MAX17055::get_AvgCurrent( platform_data des_data ) +float MAX17055::get_AvgCurrent( platform_data des_data ) { int ret, design_rsense; uint16_t data; - uint32_t aveCurr_data; + float avgCurr_data; ret = readReg(AVGCURRENT_REG, data); if (ret < F_SUCCESS_0) return ret; else - aveCurr_data = data; + avgCurr_data = data; design_rsense = des_data.rsense; - aveCurr_data = raw_current_to_uamps(aveCurr_data, design_rsense); - return aveCurr_data; + avgCurr_data = raw_current_to_uamps((uint32_t)data, design_rsense); + return avgCurr_data; } /** - * @brief lsb_to_uvolts Conversion Function + * @brief lsb_to_uvolts Conversion Function * @par Details * This function takes the lsb value of the register and convert it * to uvolts * * @param[in] lsb - value of register lsb - * @retval conv_2_uvolts - value converted lsb to uvolts + * @retval conv_2_uvolts - value converted lsb to uvolts */ int MAX17055:: lsb_to_uvolts(uint16_t lsb) { @@ -659,88 +729,118 @@ } /** - * @brief raw_current_to_uamp Conversion Function + * @brief raw_current_to_uamp Conversion Function * @par Details - * This function takes the raw current value of the register and + * This function takes the raw current value of the register and * converts it to uamps * - * @param[in] curr - raw current value of register - * @retval res - converted raw current to uamps (Signed 2's complement) + * @param[in] curr - raw current value of register + * @retval res - converted raw current to uamps (Signed 2's complement) */ -int MAX17055::raw_current_to_uamps(uint32_t curr, int rsense_value) +float MAX17055::raw_current_to_uamps(uint32_t curr, int rsense_value) { int res = curr; - /* Negative */ - if (res & 0x8000) { + float final_res; + /* Negative Check*/ + if (res & 0x8000){ res |= 0xFFFF0000; - } else { - res *= 1562500 /(rsense_value * 1000); //Change to interact with the rsense implemented in the design } + final_res = (float)res; + final_res *= 1562500 /(float)(rsense_value*1000000); + + return final_res; +} + +/** + * @brief raw_cap_to_uAh Conversion Function + * @par Details + * This function takes the raw battery capacity value of the register and + * converts it to uAh + * + * @param[in] raw_cap - raw capacity value of register + * @retval res - converted raw capacity to uAh + */ +int MAX17055::raw_cap_to_uAh(uint32_t raw_cap, int rsense_value) +{ + int res = raw_cap ; + res *= 5000000/(rsense_value * 1000000); return res; } /** - * @brief Save Learned Parameters Function for battery Fuel Gauge model. + * @brief Save Learned Parameters Function for battery Fuel Gauge model. * @par Details * It is recommended to save the learned capacity parameters every * time bit 2 of the Cycles register toggles - * (so that it is saved every 64% change in the battery) + * (so that it is saved every 64% change in the battery) * so that if power is lost the values can easily be restored. Make sure - * the data is saved on a non-volatile memory. + * the data is saved on a non-volatile memory. Call this functinton after first initialization for reference in future function calls. + * Max muber of cycles is 655.35 cycles with a LSB of 1% for the cycles register. * - * @param[in] FG_params Fuel Gauge Parameters based on design details. - * + * @param[in] FG_params Fuel Gauge Parameters based on design details. + * * @retval 0 for success * @retval non-0 negative for errors */ int MAX17055::save_Params(saved_FG_params_t FG_params) { - int ret, value; - uint16_t data[5]; + int ret; + uint16_t data[5], value; ///STEP 1. Checks if the cycel register bit 2 has changed. ret = readReg(CYCLES_REG, data[3]); - if (ret < F_SUCCESS_0) - return ret; - else { - value = data[3]; - } - - ///STEP 2. Save the capacity parameters for the specific battery. - ret = readReg(RCOMP0_REG, data[0]); + value = data[3]; if (ret < F_SUCCESS_0) return ret; - else - FG_params.rcomp0 = data[0]; + //Check if the stored cycles value is different from the read Cycles_reg value + else if (FG_params.cycles == value) + return ret; //exits the function without saving, when initializing or value did not change (calculate when the function is called in you application). + else { + value = FG_params.cycles^value; + //check with mask + value = (value & MAX17055_POR_MASK); + + if (value == 0) + return ret; + + ///STEP 2. Save the capacity parameters for the specific battery. + ret = readReg(RCOMP0_REG, data[0]); + if (ret < F_SUCCESS_0) + return ret; + else + FG_params.rcomp0 = data[0]; - ret = readReg(TEMPCO_REG, data[1]); - if (ret < F_SUCCESS_0) - return ret; - else - FG_params.temp_co = data[1]; + ret = readReg(TEMPCO_REG, data[1]); + if (ret < F_SUCCESS_0) + return ret; + else + FG_params.temp_co = data[1]; - ret = readReg(FULLCAPREP_REG, data[2]); - if (ret < F_SUCCESS_0) + ret = readReg(FULLCAPREP_REG, data[2]); + if (ret < F_SUCCESS_0) + return ret; + else + FG_params.full_cap_rep = data[2]; + + FG_params.cycles = data[3]; + + ret = readReg(FULLCAPNOM_REG, data[4]); + if (ret < F_SUCCESS_0) + return ret; + else + FG_params.full_cap_nom = data[4]; return ret; - else - FG_params.full_cap_rep = data[2]; - - FG_params.cycles = data[3]; + } +} - ret = readReg(FULLCAPNOM_REG, data[4]); - if (ret < F_SUCCESS_0) - return ret; - else - FG_params.full_cap_nom = data[4]; - return ret; -} + /** * @brief Restore Parameters Function for battery Fuel Gauge model. * @par Details - * If power is lost, then the capacity information - * can be easily restored with this function. + * If power is lost, then the capacity information + * can be easily restored with this function. * - * @param[in] FG_params Struct for Fuel Gauge Parameters + * @param[in] FG_params Struct for Fuel Gauge Parameters * @retval 0 for success * @retval non-0 negative for errors */ @@ -750,13 +850,13 @@ uint16_t temp_data, fullcapnom_data, mixCap_calc, dQacc_calc; uint16_t dPacc_value = 0x0C80;//Set it to 200% - ///STEP 1. Restoring capacity parameters + ///STEP 1. Restoring capacity parameters write_and_verify_reg(RCOMP0_REG, FG_params.rcomp0); write_and_verify_reg(TEMPCO_REG, FG_params.temp_co); write_and_verify_reg(FULLCAPNOM_REG, FG_params.full_cap_nom); - + wait_ms(350);//check the type of wait - + ///STEP 2. Restore FullCap ret = readReg(FULLCAPNOM_REG, fullcapnom_data); if (ret < F_SUCCESS_0) @@ -765,12 +865,12 @@ ret = readReg(MIXSOC_REG, temp_data); //check if Error in software guide register incorrect if (ret < F_SUCCESS_0) return ret; - + mixCap_calc = (temp_data*fullcapnom_data)/25600; write_and_verify_reg(MIXCAP_REG, mixCap_calc); write_and_verify_reg(FULLCAPREP_REG, FG_params.full_cap_rep); - + ///STEP 3. Write DQACC to 200% of Capacity and DPACC to 200% dQacc_calc = (FG_params.full_cap_nom/ 16) ; @@ -790,9 +890,9 @@ * @brief Function to Save Average Current to At Rate register. * @par Details * For User friendliness display of atTTE, atAvSOC, atAvCAP - * write the average current to At Rate registers every 10sec + * write the average current to At Rate registers every 10sec * when the battery is in use. - * NOTE: do not use this function when the Battery is charging. + * NOTE: do not use this function when the Battery is charging. * * @retval 0 for success * @retval non-0 negative for errors @@ -803,13 +903,13 @@ uint16_t avCurr_data; ret = readReg(AVGCURRENT_REG, avCurr_data); - if (ret < F_SUCCESS_0){ + if (ret < F_SUCCESS_0) { return ret = -3; - } + } //Write avCurrent to atRate Register ret = writeReg(ATRATE_REG, avCurr_data); - if (ret < F_SUCCESS_0){ + if (ret < F_SUCCESS_0) { return ret; } return F_SUCCESS_0;