This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

BQ20Z95: Reading values via i2c

Part Number: BQ20Z95

Hi,

I'm not overly familiar with requesting data through i2c and so i'm after some guidance please. I am using the BQ20Z95 (info here https://www.ti.com/product/BQ20Z95?qgpn=bq20z95) and i am getting values back, but i'm not convinced the values i am receiving are correct. I have added my code snippets below, please let me know your thoughts.

Serial.print("State of Charge=");
     Serial.print(soc);
     Serial.println("%");
     Serial.print("Capacity=");
     Serial.print(remain_cap);
     Serial.println("mAh");
     Serial.print("Voltage=");
     Serial.print(voltage);
     Serial.println("mV") ;
     Serial.print("Current=");
     Serial.print(avg_current);        
     Serial.println("mA");
     Serial.print("Temp=");
     Serial.print(batt_temp);
     Serial.println(" oC");
     Serial.print("New bat level=");
     Serial.print(batt_lev);   
     Serial.println("mAh");
}

Void readSOC()
{
Wire.beginTransmission(BQ20Z95);
Wire.write(0x0d);
Wire.endTransmission();
Wire.requestFrom(BQ20Z95,1);
unsigned int low = Wire.read();
Wire.beginTransmission(BQ20Z95);
Wire.write(0x0e);
Wire.endTransmission();
Wire.requestFrom(BQ20Z95,1);
unsigned int high = Wire.read();
soc = (high + low)/2;
}

// The battery's remaining capacity in mAh
void readRemainingCapacity()
{
Wire.beginTransmission(BQ20Z95);
Wire.write(0x10);
Wire.endTransmission();
Wire.requestFrom(BQ20Z95,2);
remain_cap = Wire.read();
}


void readlev()
{
Wire.beginTransmission(BQ20Z95);
Wire.write(0x0f);
Wire.endTransmission();
Wire.requestFrom(BQ20Z95,2);
batt_lev = Wire.read();
}

void readVoltage()
{
Wire.beginTransmission(BQ20Z95);
Wire.write(0x09);
Wire.endTransmission();
Wire.requestFrom(BQ20Z95,2);
voltage = Wire.read();


}

void readAverageCurrent()
{
Wire.beginTransmission(BQ20Z95);
Wire.write(0x14);
Wire.endTransmission();
Wire.requestFrom(BQ20Z95,2);
avg_current = Wire.read();

}


void readBattTemp()
{
Wire.beginTransmission(BQ20Z95);
Wire.write(0x08);
Wire.endTransmission();
Wire.requestFrom(BQ20Z95,2);
batt_temp = Wire.read();
batt_temp = 0.1*batt_temp; // Each bit is 0.1K, so we have a value in Kelvins
batt_temp = batt_temp - 273.15; // Convert to degrees Celsius
}

  • Hello Joshua,

    It will be hard for us to help with your code because we do not know how all the libraries used are written. Can you share what is returned from the gauge?

    Sincerely,

    Wyatt Keller

  • Hi, Not sure how useful this will be but the results are below:

    State of Charge=106%
    Capacity=210mAh
    Voltage=0mV
    Current=0mA
    Temp=-26 oC
    New bat level=58mAh
    Sent Test Data
    {"soc":106,"remain_cap":210,"voltage":0,"avg_current":0,"batt_temp":-26,"power_draw":0.000000}

  • Actually getting somewhere. Turns out the customer told me the wrong chip number! So majority is working well, however i can't get my head around how to get the Voltage to show the correct figure.

    When i print to the serial monitor i get:

    vlow = 40

    vhigh = 16

    voltage = 4

    This doesn't seem right to me, my code for this snippet is below. Voltage is defined as an unsigned int, is that correct?

    void readVoltage()
    {
      Wire.beginTransmission(BQ27542G1);
      Wire.write(0x08);
      Wire.endTransmission();
      
      Wire.requestFrom(BQ27542G1,1);
      
      unsigned int vlow = Wire.read();
      
      Wire.beginTransmission(BQ27542G1);
      Wire.write(0x09);
      Wire.endTransmission();
      
      Wire.requestFrom(BQ27542G1,1);
      
      unsigned int vhigh = Wire.read();
      
      unsigned int high1 = vhigh<<8;
      
      voltage = high1 + vlow;
      Serial.print("V1 = ");
      Serial.println(vlow);
      Serial.print("V2 = ");
      Serial.println(vhigh);

    }
  • I should have added the chip is actually bq27541-g1

  • If vlow = 40 and vhigh = 16, then voltage = 16 * 256 + 40 = 4136mV, which looks reasonable for a charged battery.

    What's the data type of "voltage" in your code? How do you print the value of "voltage"?

  • Thanks Dominik,

    voltage is an unsigned int

    I print it with the below:

         Serial.print("Voltage=");
         Serial.print(voltage);
         Serial.println("mV") ;
    To help my understanding, what is the vlow and vhigh actually returning? Why do you multiply by 256?
  • The gauge uses 16-bit integer for voltage. However, I2C reads are byte-sized, hence you need to read two bytes. The order is little endian, meaning the first byte that your read represents the lower 8-bit of the 16-bit integer while the second byte that your read represents the upper 8-bit of the same 16-bit integer.

    That's why the second byte (vhigh = 16) is multiplied by 256 (which is the same as a left shift by 8 bits like in your code).

  • Thats great thank you Dominik