TI BQ27220 I2C based, battery State of Charge and Coulomb Counter

Fork of bq27210 by Kevin Braun

bq27210.cpp

Committer:
loopsva
Date:
2017-06-19
Revision:
1:ab433d7c3e30
Parent:
0:96d5698a376f

File content as of revision 1:ab433d7c3e30:

#include    "mbed.h"
#include    "bq27210.h"
#define i2c_Buf dataSTR.i2c_Bufx
/*
BQ27210::BQ27210(PinName p_sda, PinName p_scl) :
    _i2c(p_sda, p_scl)
{
    _i2c.frequency(100000);
}
*/

BQ27210::BQ27210(PinName p_sda, PinName p_scl, PinName p_pgrm) :
    _i2c(p_sda, p_scl),
    _pgm(p_pgrm, 0)
{
    _i2c.frequency(100000);
}

void BQ27210::default_init(BQ27210_TypeDef& dataSTR)
{
    dataSTR.shunt_res = BQ_SHUNT_RESISTOR;
    dataSTR.cmmd_key = BQ_COMMAND_0xA9;
    
    //write AR register
    i2c_Buf[0] = BQ_AR_HI;
    i2c_Buf[1] = BQ_AR_VALUE >> 8;
    _i2c.write((int)BQ27210_ADDR, i2c_Buf, 2, false);
    i2c_Buf[0] = BQ_AR_LO;
    i2c_Buf[1] = BQ_AR_VALUE & 255;
    _i2c.write((int)BQ27210_ADDR, i2c_Buf, 2, false);
}

int BQ27210::new_battery_init(BQ27210_TypeDef& dataSTR)
{   
    //get the MODE register
    i2c_Buf[0] = BQ_MODE;
    _i2c.write((int)BQ27210_ADDR, i2c_Buf, 1, true);
    _i2c.read((int)BQ27210_ADDR +1, i2c_Buf, 1, false);
    char modeR = i2c_Buf[0];
    //write DONE bit to MODE reg
    i2c_Buf[0] = BQ_MODE;
    i2c_Buf[1] = modeR | BQ_BIT_DONE;
    _i2c.write((int)BQ27210_ADDR, i2c_Buf, 2, false);
    //write command
    i2c_Buf[0] = BQ_CRTL;
    i2c_Buf[1] = BQ_COMMAND_0xA9;
    _i2c.write((int)BQ27210_ADDR, i2c_Buf, 2, false);
    int i = 0;
    for(i = 0; i < 500; i++) {
        //Thread::wait(1);
        wait_ms(1);
        i2c_Buf[0] = BQ_CRTL;
        _i2c.write((int)BQ27210_ADDR, i2c_Buf, 1, true);
        _i2c.read((int)BQ27210_ADDR +1, i2c_Buf, 1, false);
        if(!(i2c_Buf[0])) break;
    }
    if(i > 498) return(i); // 40 fails, 50 passes
    
    //get the MODE register
    i2c_Buf[0] = BQ_MODE;
    _i2c.write((int)BQ27210_ADDR, i2c_Buf, 1, true);
    _i2c.read((int)BQ27210_ADDR +1, i2c_Buf, 1, false);
    modeR = i2c_Buf[0];
    //write PRST bit to MODE reg
    i2c_Buf[0] = BQ_MODE;
    i2c_Buf[1] = modeR | BQ_BIT_PRST;
    _i2c.write((int)BQ27210_ADDR, i2c_Buf, 2, false);
    //write command
    i2c_Buf[0] = BQ_CRTL;
    i2c_Buf[1] = BQ_COMMAND_0xA9;
    _i2c.write((int)BQ27210_ADDR, i2c_Buf, 2, false);
    return(0);
}

int BQ27210::read_registers(BQ27210_TypeDef& dataSTR)
{
    i2c_Buf[0] = BQ_CRTL;
    int result = _i2c.write((int)BQ27210_ADDR, i2c_Buf, 1, true);
    if(result) return(result);
    _i2c.read((int)BQ27210_ADDR +1, i2c_Buf, 45, false);
    
    dataSTR.cntlReg = i2c_Buf[BQ_CRTL];
    dataSTR.modeReg = i2c_Buf[BQ_MODE];
    dataSTR.arReg = (i2c_Buf[BQ_AR_HI] << 8) | i2c_Buf[BQ_AR_LO];
    dataSTR.artteReg = (i2c_Buf[BQ_ARTTE_HI] << 8) | i2c_Buf[BQ_ARTTE_LO];
    dataSTR.tempReg = (i2c_Buf[BQ_TEMP_HI] << 8) | i2c_Buf[BQ_TEMP_LO];
    dataSTR.voltReg = (i2c_Buf[BQ_VOLT_HI] << 8) | i2c_Buf[BQ_VOLT_LO];
    dataSTR.flagsReg = i2c_Buf[BQ_FLAGS];
    dataSTR.rsocReg = i2c_Buf[BQ_RSOC];
    dataSTR.nacReg = (i2c_Buf[BQ_NAC_HI] << 8) | i2c_Buf[BQ_NAC_LO];
    dataSTR.lmdReg = (i2c_Buf[BQ_LMD_HI] << 8) | i2c_Buf[BQ_LMD_LO];
    dataSTR.cacReg = (i2c_Buf[BQ_CAC_HI] << 8) | i2c_Buf[BQ_CAC_LO];
    dataSTR.fcacReg = (i2c_Buf[BQ_FCAC_HI] << 8) | i2c_Buf[BQ_FCAC_LO];
    dataSTR.aiReg = (i2c_Buf[BQ_AI_HI] << 8) | i2c_Buf[BQ_AI_LO];
    dataSTR.tteReg = (i2c_Buf[BQ_TTE_HI] << 8) | i2c_Buf[BQ_TTE_LO];
    dataSTR.ttfReg = (i2c_Buf[BQ_TTF_HI] << 8) | i2c_Buf[BQ_TTF_LO];
    dataSTR.siReg = (i2c_Buf[BQ_SI_HI] << 8) | i2c_Buf[BQ_SI_LO];
    dataSTR.stteReg = (i2c_Buf[BQ_STTE_HI] << 8) | i2c_Buf[BQ_STTE_LO];
    dataSTR.junk1 = (i2c_Buf[BQ_STTE_HI +2] << 8) | i2c_Buf[BQ_STTE_LO +2];
    dataSTR.cedvReg = (i2c_Buf[BQ_CEDV_HI] << 8) | i2c_Buf[BQ_CEDV_LO];
    dataSTR.junk2 = (i2c_Buf[BQ_CEDV_HI +2] << 8) | i2c_Buf[BQ_CEDV_LO +2];
    dataSTR.junk3 = (i2c_Buf[BQ_CEDV_HI +4] << 8) | i2c_Buf[BQ_CEDV_LO +4];
    dataSTR.ttecpReg = (i2c_Buf[BQ_TTECP_HI] << 8) | i2c_Buf[BQ_TTECP_LO];
    dataSTR.cyclReg = (i2c_Buf[BQ_CYCL_HI] << 8) | i2c_Buf[BQ_CYCL_LO];
    dataSTR.cyctReg = (i2c_Buf[BQ_CYCT_HI] << 8) | i2c_Buf[BQ_CYCT_LO];
    dataSTR.csocReg = i2c_Buf[BQ_CSOC];
    return(0);
}

int BQ27210::read_eep_registers(BQ27210_TypeDef& dataSTR)
{
    i2c_Buf[0] = BQ_EE_EN;
    int result = _i2c.write((int)BQ27210_ADDR, i2c_Buf, 1, true);
    if(result) return(result);
    _i2c.read((int)BQ27210_ADDR +1, i2c_Buf, 1, false);
    dataSTR.eeEnReg = i2c_Buf[0];
    
    i2c_Buf[0] = BQ_ILMD;
    result = _i2c.write((int)BQ27210_ADDR, i2c_Buf, 1, true);
    _i2c.read((int)BQ27210_ADDR +1, i2c_Buf, 10, false);
    dataSTR.ilmdReg = i2c_Buf[0];
    dataSTR.sedvfReg = i2c_Buf[1];
    dataSTR.sedv1Reg = i2c_Buf[2];
    dataSTR.islcEdvtReg = i2c_Buf[3];
    dataSTR.dmfsdReg = i2c_Buf[4];
    dataSTR.taperReg = i2c_Buf[5];
    dataSTR.pkcfgReg = i2c_Buf[6];
    dataSTR.gafDedvReg = i2c_Buf[7];
    dataSTR.dcompReg = i2c_Buf[8];
    dataSTR.tcompReg = i2c_Buf[9];
    return(20);
}

int BQ27210::write_eep_registers(BQ27210_TypeDef& dataSTR)
{
    //first get old data and enable writing to EEPROM
    int result = read_eep_registers(dataSTR);
    if(result) return(21);
    i2c_Buf[0] = BQ_EE_EN;
    i2c_Buf[1] = BQ_EE_WRITE_EN;
    result = _i2c.write((int)BQ27210_ADDR, i2c_Buf, 2, false);
    if(result) return(22);
    
    //setup and write new values to EEPROM
    i2c_Buf[1] = BQ_ILMD;
    //i2c_Buf[2] = dataSTR.ilmdReg;
    //i2c_Buf[3] = dataSTR.sedvfReg;
    //i2c_Buf[4] = dataSTR.sedv1Reg;
    i2c_Buf[5] = dataSTR.islcEdvtReg;
    i2c_Buf[6] = dataSTR.dmfsdReg;
    i2c_Buf[7] = dataSTR.taperReg;
    i2c_Buf[8] = dataSTR.pkcfgReg;
    i2c_Buf[9] = dataSTR.gafDedvReg;
    i2c_Buf[10] = dataSTR.dcompReg;
    i2c_Buf[11] = dataSTR.tcompReg;
    
    i2c_Buf[2] = BQ_NEW_ILMD;
    i2c_Buf[3] = BQ_NEW_SEDVF;
    i2c_Buf[4] = BQ_NEW_SEDV1;
    result = _i2c.write((int)BQ27210_ADDR, i2c_Buf+1, 10, false);
    if(result) return(23);
    
    //now program each register
    int i = 0;
    for(i = BQ_ILMD; i <= BQ_TCOMP; i++) {
        i2c_Buf[0] = i2c_Buf[i + 1];
        result = _i2c.write((int)BQ27210_ADDR, i2c_Buf, 1, true);
        _i2c.read((int)BQ27210_ADDR +1, i2c_Buf, 1, false);
        _pgm = 1;
        //Thread::wait(50);
        wait_ms(50);
        _pgm = 0;
        if(result) break;
    }
    
    //finally, disable writing of EEPROM
    i2c_Buf[0] = BQ_EE_EN;
    i2c_Buf[1] = 0;
    _i2c.write((int)BQ27210_ADDR, i2c_Buf, 2, false);
    if(result) return(i);
    return(0);
}