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
max17055.cpp
- Committer:
- fneirab
- Date:
- 2017-09-26
- Revision:
- 3:f77a8345b0e3
- Parent:
- 2:ff7db397b70f
- Child:
- 4:a4d6ae2182c2
File content as of revision 3:f77a8345b0e3:
/******************************************************************************* * Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Except as contained in this notice, the name of Maxim Integrated * Products, Inc. shall not be used except as stated in the Maxim Integrated * Products, Inc. Branding Policy. * * The mere transfer of this software does not imply any licenses * of trade secrets, proprietary technology, copyrights, patents, * trademarks, maskwork rights, or any other form of intellectual * property whatsoever. Maxim Integrated Products, Inc. retains all * ownership rights. * ******************************************************************************/ #include "mbed.h" #include "max17055.h" MAX17055::MAX17055(I2C &i2c): m_i2cBus(i2c) { //empty block } MAX17055::~MAX17055() { //empty block } /////////////////////////////////////////////////////////////////////////////// /** * \brief Write a value to a MAX17055 register * \par Details * This function writes a value to a MAX17055 register * * \param[in] reg_addr - register address * \param[in] reg_data - register data * * \retval 1 on success */ int MAX17055::writeReg(Registers_e reg_addr, uint16_t reg_data) { uint8_t dataLSB; uint8_t dataMSB; dataLSB = reg_data & 0x00FF; dataMSB = (reg_data >> 8) & 0x00FF; char add_plus_data[3] = {reg_addr, dataLSB, dataMSB}; if ( m_i2cBus.write(I2C_W_ADRS, add_plus_data, 3, false) == 0) return 1; else return 0; } /////////////////////////////////////////////////////////////////////////////// /** * \brief Read a MAX17055 register * \par Details * This function reads a MAX17055 register * * \param[in] reg_addr - register address * \param[out] &value - pointer that stores the register data * * \retval 1 on success */ int32_t MAX17055::readReg(Registers_e reg_addr, uint16_t &value) { int32_t result; //int16_t value2; //int16_t twoBytes; char local_data[1]; local_data[0] = reg_addr; char read_data[2]; result = m_i2cBus.write(I2C_W_ADRS, local_data, 1); if(result == 0) { result = m_i2cBus.read(I2C_R_ADRS, read_data , 2, false); if (result == 0) { value = ( ((read_data[1] & 0x00FF) << 8) + (read_data[0])); result = 1; } } return result; } /////////////////////////////////////////////////////////////////////////////// /** * \brief Write and Verify a MAX17055 register * \par Details * This function wites 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 * * \retval 1 on success */ int MAX17055::write_and_verify_reg (MAX17055::Registers_e reg_addr, uint16_t reg_data) { int retries = 8; int ret; int statusRead; int statusWrite; uint16_t read_data; do { statusWrite = writeReg(reg_addr, reg_data); if (statusWrite != 1) ret = -1; wait_ms(3); statusRead = readReg(reg_addr, read_data); if (statusRead != 1) ret = -2; if (read_data != reg_data){ ret = -3; retries--; } }while (retries && read_data != reg_data); if (ret<0) { return ret; } else return 1; } //////////////////////////////////////////////////////////////////////////////// /** * \brief Initialise Function for MAX17055 * \par Details * This function intitializes the MAX17055 * * \retval 1 on success * 0 if device is not present * -1 if errors exist */ int MAX17055::init() { int status; uint16_t read_data; status = readReg(MAX17055_VERSION_REG, read_data); if (status == 0) return status; //Device is not present in the i2c Bus /* Step 0: Check for POR */ /* Skip load model if POR bit is cleared */ readReg(MAX17055_STATUS_REG, read_data); if (!(read_data & MAX17055_STATUS_POR ) ) return -1; //POR is not set. Skip Initialization. /* Step 1: Check if FStat.DNR == 0 */ // Do not continue until FSTAT.DNR == 0 while(readReg(MAX17055_FSTAT_REG, read_data)&1) { wait_ms(10);//10 ms wait empty loop } return 1; } //////////////////////////////////////////////////////////////////////////////// /** * \brief Get Internal Temperature Function for MAX17055 * \par Details * This function sends a request to access the internal * of the MAX17055 * * \param[in] reg_addr - register address * \param[out] reg_data - the variable that contains the data to write * to the register address * \retval 1 on success * * -1 if errors exist */ int MAX17055::get_temperature(int *temp) { int ret; uint16_t data; ret = readReg(MAX17055_TEMP_REG, data); if (ret < 0) return ret; *temp = data; /* The value is signed. */ if (*temp & 0x8000) *temp |= 0xFFFF0000; /* The value is converted into centigrade scale */ /* Units of LSB = 1 / 256 degree Celsius */ *temp >>= 8; return 1; } //////////////////////////////////////////////////////////////////////////////// /** * \brief Forced Exit Hibernate Mode Function for MAX17055 * \par Details * This function executes a force exit from hibernate mode. * * \retval returns HibCFG original value before forced Exit Hybernate mode * */ uint16_t MAX17055::forcedExitHyberMode() { uint16_t hibcfg; /* Force exit from hibernate */ //STEP 0: Store original HibCFG value readReg(MAX17055_HIBCFG_REG, hibcfg); //STEP 1: Write to Soft-Wakeup Commannd Register writeReg(MAX17055_VFSOC0_QH0_LOCK_REG, 0x90); //Soft-Wakeup from hybernate //STEP 2: Write to Hibernate Configuration register writeReg(MAX17055_HIBCFG_REG, 0x0); //disable hibernate mode //STEP 3:Write to Soft-Wakeup Commannd Register writeReg(MAX17055_VFSOC0_QH0_LOCK_REG, 0x0); //Clear All commnads return hibcfg; } //step_1: // // Wait until MAX17055 complete setup operations (Data is Ready) // while(readReg(F_STAT) & 0x0001) delay(10); // /***************************************************************/ // // Setting up or initializing charging configurations down here , EZ CONFIG because no .INI file // // FIXX:: DOUBLE CHECK THE INITIALIZATION VALUES // // init values is claculated based on the register lsb's default value page 1 software implementation UG // /* Capacity is in mAH and 1 bit is 0.5mAH)*/ // temp = battery->capacity*2; // writeReg(DESIGN_CAP, temp); // writeReg(DQ_A_CC, temp/32); // /* Current measurement, assuming current input in mA */ // temp = battery->currentTerm*1000/1.5625; // writeReg(ICHG_TERM, temp); // /* FIXX: DOUBLE CHECK Vempty register (v empty | v recovery), I am assuming that // VE resolution is 10mV and VR resolution is 40mV (programmer's guide)*/ // temp =((battery->voltageMin/10) << 7 | (battery->voltageNom)/40); // writeReg(V_EMPTY ,temp); // // data = readReg(HIB_CFG); // Store original HIB_CFG inside // writeReg((Registers_e)0x60, 0x90); // Exit hibernate mode step 1 // writeReg(CONFIG_2, 0x0); // Exit hibernate mode step 2 // writeReg((Registers_e)0x60, 0x0); // Exit hibernate mode step 3 // // temp = battery->capacity*2; // if (battery->voltageMax > 4.275) { // writeReg(DP_A_CC, (temp/32)*51200/temp); // Write dPAcc // writeReg(MODEL_CFG, 0x8400); // Write ModelCFG // } else { // writeReg(DP_A_CC, (temp/32)*44138/temp); // writeReg(MODEL_CFG, 0x8000); // } // // Poll ModelCFG.refresh (highest bit), proceed to next step when ModelCFG.Refresh = 0. // while(readReg(MODEL_CFG) & 0x8000) delay(10); // writeReg(HIB_CFG, data); // Restore the original HibCFG value // /***************************************************************/ // } // /***************************************************************/ // // FIXX: DOUBLE CHECK, STEP 4 IN PROGRAMMER'S GUIDE // data = readReg(STATUS); // read status register // // if (write_and_verify_reg(STATUS, data & 0xFFFD) != E_NO_ERROR) { // return -1; // } // // Check whether there is saved history parameters // temp = saved_param->rcomp0; // temp &= saved_param ->temp_co; // temp &= saved_param->full_cap_rep; // temp &= saved_param->cycles; // temp &= saved_param->full_cap_nom; // // If there is no history setup the battery // if (temp == 0) { // // Check for MAX17055 reset // StatusPOR = readReg(STATUS) & 0x0002; // if (StatusPOR == 1) goto step_1; // } //step_4P3: // // Read the reported capacity(mAH) and SOC (percentage) // RepCap = readReg(REP_CAP); // RepSOC = readReg(REP_SOC); // // // Read the TTE (in 5.625s) // TTE_val = ((float)(readReg(TTE))) * 5.625; // // // Save learned parameters // saved_param->rcomp0 = readReg(R_COMP_0); // saved_param->temp_co = readReg(TEMP_CO); // saved_param->full_cap_rep = readReg(FULL_CAP_REP); // saved_param->cycles = readReg(CYCLES); // saved_param->full_cap_nom = readReg(FULL_CAP_NOM); // // // Restoring Capacity Parameters // if (write_and_verify_reg(R_COMP_0, saved_param->rcomp0) != E_NO_ERROR) { // return -1; // } // if (write_and_verify_reg(TEMP_CO, saved_param->temp_co) != E_NO_ERROR) { // return -1; // } // if (write_and_verify_reg(FULL_CAP_REP, saved_param->full_cap_rep) != E_NO_ERROR) { // return -1; // } // // delay(350); // // Restore FullCap // temp = readReg(FULL_CAP_NOM); // Read full_cap_nom // data = (readReg(MIX_SOC)*temp)/25600; // MIXCAP // if (write_and_verify_reg(MIX_CAP, data) != E_NO_ERROR) { // return -1; // } // if (write_and_verify_reg(FULL_CAP_REP, temp) != E_NO_ERROR) { // return -1; // } // data = saved_param->full_cap_nom/16; // This act as dQacc // if (write_and_verify_reg(DP_A_CC, 0x0C80) != E_NO_ERROR) { // return -1; // } // if (write_and_verify_reg(DQ_A_CC, temp) != E_NO_ERROR) { // return -1; // } // // delay(350); // // Restore Cycles Register // if (write_and_verify_reg(CYCLES, saved_param->cycles) != E_NO_ERROR) { // return -1; // } // //return E_NO_ERROR; // // //saved_fuel_gauge_params_t default_param = {0,0,0,0,0};