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.

CCS/BQ76PL536A-Q1: BQ76PL536A-Q1

Part Number: BQ76PL536A-Q1

Tool/software: Code Composer Studio

Hello

I am using this device. I am facing the problem with the voltage readings.  when I try to read the voltages it gives wrong values or sometime it didn't read the LSB. I am attaching the code file. need your help regarding this.

BR

3058.code.txt
// include the library code:
#include <SPI.h>
#include <Wire.h>
#include <math.h>
#include <LiquidCrystal.h>

//Declared Variables
SPISettings settingsA(3000000, MSBFIRST, SPI_MODE1);
const byte Fault_H = 8; //Fault indication pin from bq76
const byte Alert_H = 7; //Alert indication pin from bq76
const byte DRDY_H = 6; //Data ready indication from bq76
const byte CONV_H = 5; //Conversion start pin for bq76
const byte Charge_Mode = 4; //Charger status to indicate if charging mode is active
const byte Charge_Relay = 3; //Output to toggle charger on or off
const byte slaveSelectPin = 10; //SPI slave select
const byte LED = 9; //LED indicator

const byte n_dev = 1; //Expected number of devices in stack
const byte COV = 0x2B; //Cell overvoltage (4.15V). 0x00 = 2V, bit increments increase set point by 50mV.
const byte CUV = 0x12; //Cell undervoltage (2.5V). 0x00 =0.7V, bit increments increase set point by 100mV.
const int OV = 4150; //Set point for Cell balancing
const byte FC = 0x20; //Set ratiometric mode for GPAI_REF

byte w_data[3]; //Write packet
byte r_header[3]; //Read packet header
byte r_header2[3]; //Alternate read packet header
byte drdy; //Data ready
byte CRC; //CRC

byte read_byte; //Shifted byte to read
byte write_byte; //Shifted byte to write
byte RegValue; //Value read from register
byte dev_fault; //Fault Code of current device
byte dev_alert; //Alert Code of current device


byte cell_now = 0x03; //Current selected cell reg address, must increment by 2. 0x03 to 0x0E
byte cell_num = 1; //Current selected cell number

byte alert_now = 7; //Alert bit status to be displayed
byte fault_now = 7; //Fault bit status to be displayed


byte v_msb; //MSB of volt measurement
byte v_lsb; //LSB of volt measurement
 
float volts; 
int cellno=1;

int CB_Timer; //Count for number of CB Timers active




//Functions:
void read_header(byte r_header[]);
byte read_data();
byte read_CRC();
void write_reg(byte w_data[]);
byte function_CRC(byte data[]);
void reset_all();


void auto_addr(int n_dev);
byte read_shift(byte d_addr);
byte write_shift(byte d_addr);
void batt_init(byte COV, byte CUV, byte OT, byte FC);
void conv(byte adc_ctrl[]);
int volt_calc(byte v_msb, byte v_lsb);


//CRC LUT:
byte CrcTable[] = {
0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5,
0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85,
0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2,
0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2,
0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32,
0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42,
0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C,
0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC,
0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C,
0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C,
0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B,
0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B,
0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB,
0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB,
0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
};

void setup() {
  //MCU Initialization START
pinMode(Fault_H, INPUT); // Fault_H
pinMode(Alert_H, INPUT); // Alert_H
pinMode(DRDY_H, INPUT); // DRDY_H (Data Ready)
pinMode(CONV_H, OUTPUT); // CONV_H (Conversion)
pinMode(Charge_Mode, INPUT); // Input to determine if in charging mode
pinMode(Charge_Relay, OUTPUT); // Output to turn charger on or off
//MCU Initialization END

Serial.begin(9600); // Debugging output
//lcd.begin(16, 2);

//SPI Initialization START
pinMode(slaveSelectPin, OUTPUT); //set the slaveSelectPin as an output
digitalWrite(slaveSelectPin, HIGH); //Set CS_H HIGH
SPI.begin(); //Initializes SPI bus
//SPI Initialization END

//bq76 Automatic Device Addressing START
auto_addr(n_dev);
//bq76 Automatic Device Addressing END

//Serial.println("start");
//Battery Initialization START
//batt_init(COV,CUV,FC);
//Battery Initialization END

//Clear POR Fault START
byte por_clear[] = {0x7F, 0x21, 0x08};
write_reg(por_clear);
por_clear[2] = 0x00;
write_reg(por_clear);
//Clear POR Fault END

//Clear Address Alert START
byte ar_clear[] = {0x7F, 0x20, 0x80};
write_reg(ar_clear);
ar_clear[2] = 0x00;
write_reg(ar_clear);
//Clear Address Alert END
//Serial.println("start");
}

void loop() {
  // put your main code here, to run repeatedly:

byte w_wake[] = {0x7F, 0x31, 0x00};
write_reg(w_wake);
delay (1); //Wait to stabilize the reference voltage
Serial.println("ZZZZZZZZZZZZ");
w_wake[1] = 0x20;
w_wake[2] = 0x04;   //means sleep mode was activated 
write_reg(w_wake); 
w_wake[2] = 0x00;   //Clear Sleep alert by writning this to device.
write_reg(w_wake);
Serial.println("YYYYYYYYY");
byte adc_ctrl[] = {0x7F, 0x30, 0x05}; //ADC_Ctrl to readall voltages and temps   binary  00110101  for zeon it should be 00000101
conv(adc_ctrl); //Start conversion  
drdy = digitalRead(DRDY_H);
Serial.println("TTTTTTTTTTT");
while (drdy == 0)
{ //Wait for conversion process to finish.
drdy = digitalRead(DRDY_H);
Serial.println(drdy);

Serial.println("XXXXXXXXXXX");
for (int i = 1; i<n_dev+1; i++) 
{ 
  //cycle through each device
 
for (byte j=0x03;j<=0x0E;j+0x02) 
{ //cycle through each cell
  
read_byte = read_shift(i);
Serial.print("read_byte");
Serial.println(read_byte);
byte r_header[] = {read_byte, j, 0x01};      //read from msb of volts for current cell of current device
read_header(r_header);
v_msb = read_data();
CRC = read_CRC();
Serial.print("v_msb=");
Serial.println(v_msb);
byte r_header2[] = {read_byte, j+1, 0x01}; //read from lsb of volts for current cell of current device
read_header(r_header2);
v_lsb = read_data();
Serial.print("v_Lsb=");
Serial.println(v_lsb);
CRC = read_CRC();
volts= volt_calc(v_msb, v_lsb); //Calculate voltage in mV
Serial.print(j);
Serial.print("zz=");
Serial.println(volts);
delay(5000);
  //int Zvoltage[i][cellno];
  //Zvoltage[i][cellno]= volts;
  //Serial.println(Zvoltage[i][cellno]);
  //cellno++;
}

Serial.println("finish");
//cellno=1; 

}
}

}//Function to establish device address, register address, and length for reading

void read_header(byte r_header[]) {
digitalWrite(slaveSelectPin, LOW); //Set CS_H LOW to start packet transfer
SPI.beginTransaction(settingsA);
for (int i = 0; i <=1; i++)
{
SPI.transfer(r_header[i]); //Set device address, read, register address, & length
}
}


// Shift device address left 1 bit
byte read_shift(byte d_addr)
{
byte read_byte = (d_addr << 1);
return read_byte;
}



//Function to clock in a read cycle and return the read data
byte read_data() {
byte RegValue;
RegValue = SPI.transfer(0x00);
return RegValue;
}

//Function to clock in a CRC cycle and return CRC value
byte read_CRC() {
byte CRC;
CRC = SPI.transfer(0x00);
SPI.endTransaction();
digitalWrite(slaveSelectPin, HIGH); //Set CS_H HIGH to end packet transfer
return CRC;
}


//Function to write to bq71
void write_reg(byte w_data[])
{
CRC = function_CRC(w_data);
digitalWrite(slaveSelectPin, LOW); //Set CS_H LOW to start packet transfer
SPI.beginTransaction(settingsA);
for (int i = 0; i <=1; i++)
{
SPI.transfer(w_data[i]); //Set device address, write, register address, & write data
}
SPI.transfer(CRC); // CRC Code
SPI.endTransaction();
digitalWrite(slaveSelectPin, HIGH); //Set CS_H HIGH to end packet transfer
}

//Function to generate a CRC
byte function_CRC(byte data[])
{
byte crc = 0;
int temp = 0;
for (int i = 0; i < sizeof(data) + 1; i++)
{
temp = crc ^ data[i];
crc = CrcTable[temp];
}
return crc;
}


//Broadcast RESET to all devices
void reset_all()
{
byte w_data[3] = {0x7F, 0x3C, 0xA5};
write_reg(w_data);
}


//Automatically address all devices in stack
void auto_addr(byte n_dev)
{
byte device_search = 0;
point1: reset_all();
device_search++;
byte n = 0;
point2: n++;
byte w_data[3] = {0x00, 0x3B, n}; //header for write address n to dev[0]
write_reg(w_data);
read_byte = read_shift(n);
byte r_header[3] = {read_byte, 0x3B, 0x01}; //header to read address from address_ctrl register
read_header(r_header);
RegValue = read_data();
CRC = read_CRC();
Serial.println(RegValue);
RegValue = RegValue/128;
//RegValue = RegValue;
while (RegValue != n) { //Device will be stuck in this loop if addressing fails. Requires POR to try again. Device addr critical.
//lcd.setCursor(0, 0);
Serial.println("Addr Failed on Device");
Serial.println(n);
byte por_clear[] = {0x7F, 0x21, 0x08};
write_reg(por_clear);
por_clear[2] = 0x00;
write_reg(por_clear);
//lcd.print("Addr Failed on D");
//lcd.setCursor(0, 1);
//lcd.print(n);
}
if (n < device_search) {
goto point2;
}
if (n < n_dev) {
goto point1;
}
if (n != n_dev) {
Serial.println("Address Failed 2");  

//lcd.setCursor(0, 0);
//lcd.print("Automatic Device");
//lcd.setCursor(0, 1);
//lcd.print("Address Failed 2");
}
if(n==n_dev)
{ Serial.println("adresing succesful");  }
}

// Shift device address left 1 bit then add 1 to indicate write
byte write_shift(byte d_addr)
{
byte write_byte = (d_addr << 1) + 1;
return write_byte;
}


//Overwrite EPROM values using shadow control special sequence. Write 0x35 to shdw_ctrl reg followed by set point.
void batt_init(byte COV, byte CUV, byte FC)
{
byte shdw_ctrl[3] = {0x7F, 0x3A, 0x35};
//Set Special feature config:
write_reg(shdw_ctrl);
byte w_func_con[] = {0x7F, 0x40, FC};
write_reg(w_func_con);
//Set Overvoltage:
write_reg(shdw_ctrl);
byte w_COV[3] = {0x7F, 0x42, COV};
write_reg(w_COV);
//Set Undervoltage:
write_reg(shdw_ctrl);
byte w_CUV[3] = {0x7F, 0x44, CUV};
write_reg(w_CUV);
}


//Function to assert a conversion process
void conv(byte adc_ctrl[])
{
byte conv_start[] = {0x7F, 0x34, 0x01};
write_reg(adc_ctrl); //Sets ADC control register with desired parameters
write_reg(conv_start); //Start conversion
}


//Function to calculate voltage using register values
int volt_calc(byte v_msb, byte v_lsb)
{ 
float ratio = 0.381493;
int mV = ((v_msb * 0x100) + v_lsb) * ratio;
return mV;
}
 

  • Hi Zeeshan,

    Can you please first utilize our reference material (example code and GUI) to ensure everything is working as expected? Link at the bottom of this page: https://www.ti.com/product/BQ76PL536 

    Taylor

  • Hi Taylor

    Hope you will be gine.

    I utilize the reference material but still the problem is same. PFA I attach the code file.

    BR

    code.txt
    // include the library code:
    #include <SPI.h>
    #include <Wire.h>
    #include <math.h>
    #include <LiquidCrystal.h>
    
    //Declared Variables
    SPISettings settingsA(3000000, MSBFIRST, SPI_MODE1);
    const byte Fault_H = 8; //Fault indication pin from bq76
    const byte Alert_H = 7; //Alert indication pin from bq76
    const byte DRDY_H = 6; //Data ready indication from bq76
    const byte CONV_H = 5; //Conversion start pin for bq76
    const byte Charge_Mode = 4; //Charger status to indicate if charging mode is active
    const byte Charge_Relay = 3; //Output to toggle charger on or off
    const byte slaveSelectPin = 10; //SPI slave select
    const byte LED = 9; //LED indicator
    
    const byte n_dev = 1; //Expected number of devices in stack
    const byte COV = 0x2B; //Cell overvoltage (4.15V). 0x00 = 2V, bit increments increase set point by 50mV.
    const byte CUV = 0x12; //Cell undervoltage (2.5V). 0x00 =0.7V, bit increments increase set point by 100mV.
    const int OV = 4150; //Set point for Cell balancing
    const byte FC = 0x20; //Set ratiometric mode for GPAI_REF
    
    byte w_data[3]; //Write packet
    byte r_header[3]; //Read packet header
    byte r_header2[3]; //Alternate read packet header
    byte drdy; //Data ready
    byte CRC; //CRC
    
    byte read_byte; //Shifted byte to read
    byte write_byte; //Shifted byte to write
    byte RegValue; //Value read from register
    byte dev_fault; //Fault Code of current device
    byte dev_alert; //Alert Code of current device
    
    
    byte cell_now = 0x03; //Current selected cell reg address, must increment by 2. 0x03 to 0x0E
    byte cell_num = 1; //Current selected cell number
    
    byte alert_now = 7; //Alert bit status to be displayed
    byte fault_now = 7; //Fault bit status to be displayed
    
    
    byte v_msb; //MSB of volt measurement
    byte v_lsb; //LSB of volt measurement
     
    float volts; 
    int cellno=1;
    
    int CB_Timer; //Count for number of CB Timers active
    
    
    
    
    //Functions:
    void read_header(byte r_header[]);
    byte read_data();
    byte read_CRC();
    void write_reg(byte w_data[]);
    byte function_CRC(byte data[]);
    void reset_all();
    
    
    void auto_addr(int n_dev);
    byte read_shift(byte d_addr);
    byte write_shift(byte d_addr);
    void batt_init(byte COV, byte CUV, byte OT, byte FC);
    void conv(byte adc_ctrl[]);
    int volt_calc(byte v_msb, byte v_lsb);
    
    
    //CRC LUT:
    byte CrcTable[] = {
    0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
    0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
    0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
    0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
    0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5,
    0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
    0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85,
    0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
    0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2,
    0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
    0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2,
    0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
    0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32,
    0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
    0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42,
    0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
    0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C,
    0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
    0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC,
    0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
    0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C,
    0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
    0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C,
    0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
    0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B,
    0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
    0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B,
    0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
    0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB,
    0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
    0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB,
    0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
    };
    
    void setup() {
      //MCU Initialization START
    pinMode(Fault_H, INPUT); // Fault_H
    pinMode(Alert_H, INPUT); // Alert_H
    pinMode(DRDY_H, INPUT); // DRDY_H (Data Ready)
    pinMode(CONV_H, OUTPUT); // CONV_H (Conversion)
    pinMode(Charge_Mode, INPUT); // Input to determine if in charging mode
    pinMode(Charge_Relay, OUTPUT); // Output to turn charger on or off
    //MCU Initialization END
    digitalWrite(CONV_H, LOW);
    Serial.begin(9600); // Debugging output
    //lcd.begin(16, 2);
    
    //SPI Initialization START
    pinMode(slaveSelectPin, OUTPUT); //set the slaveSelectPin as an output
    digitalWrite(slaveSelectPin, HIGH); //Set CS_H HIGH
    SPI.begin(); //Initializes SPI bus
    //SPI Initialization END
    
    //bq76 Automatic Device Addressing START
    auto_addr(n_dev);
    //bq76 Automatic Device Addressing END
    
    //Serial.println("start");
    //Battery Initialization START
    //batt_init(COV,CUV,FC);
    //Battery Initialization END
    
    //Clear POR Fault START
    byte por_clear[] = {0x7F, 0x21, 0x08};
    write_reg(por_clear);
    por_clear[2] = 0x00;
    write_reg(por_clear);
    //Clear POR Fault END
    
    //Clear Address Alert START
    byte ar_clear[] = {0x7F, 0x20, 0x80};
    write_reg(ar_clear);
    ar_clear[2] = 0x00;
    write_reg(ar_clear);
    //Clear Address Alert END
    //Serial.println("start");
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
    
    byte w_wake[] = {0x7F, 0x31, 0x00};
    write_reg(w_wake);
    delay (1); //Wait to stabilize the reference voltage
    Serial.println("ZZZZZZZZZZZZ");
    w_wake[0] = 0x7f;
    w_wake[1] = 0x20;
    w_wake[2] = 0x04;   //means sleep mode was activated 
    write_reg(w_wake); 
    w_wake[2] = 0x00;   //Clear Sleep alert by writning this to device.
    write_reg(w_wake);
    Serial.println("YYYYYYYYY");
    byte adc_ctrl[] = {0x7F, 0x30, 0x05}; //ADC_Ctrl to readall voltages and temps   binary  00110101  for zeon it should be 00000101
    conv(adc_ctrl); //Start conversion  
    drdy = digitalRead(DRDY_H);
    Serial.println("TTTTTTTTTTT");
    while (drdy == 0)
    {//Wait for conversion process to finish.
    drdy = digitalRead(DRDY_H);
    Serial.println(drdy);
    
    Serial.println("XXXXXXXXXXX");
    for (int i = 1; i<n_dev+1; i++) 
    { 
      //cycle through each device
     
    for (byte j=0x03;j<=0x0E;j+0x02) 
    { 
      //cycle through each cell
    read_byte = read_shift(n_dev);
    Serial.print("read_byte");
    Serial.println(read_byte);
    byte r_header[] = {read_byte, j, 0x01};      //read from msb of volts for current cell of current device
    read_header(r_header);
    v_msb = read_data();
    CRC = read_CRC();
    Serial.print("crc_msb");
    Serial.println(CRC);
    Serial.print("v_msb=");
    Serial.println(v_msb);
    byte r_header2[] = {read_byte, j+1, 0x01}; //read from lsb of volts for current cell of current device
    read_header(r_header2);
    v_lsb = read_data();
    CRC = read_CRC();
    volts= volt_calc(v_msb, v_lsb); //Calculate voltage in mV
    Serial.print("v_Lsb=");
    Serial.println(v_lsb);
    Serial.print(j);
    Serial.print("zz=");
    Serial.println(volts);
    delay(5000);
      //int Zvoltage[i][cellno];
      //Zvoltage[i][cellno]= volts;
      //Serial.println(Zvoltage[i][cellno]);
      //cellno++;
    }
    
    Serial.println("finish");
    //cellno=1; 
    }
    }
    }
    
    //Function to establish device address, register address, and length for reading
    
    void read_header(byte r_header[]) {
    digitalWrite(slaveSelectPin, LOW); //Set CS_H LOW to start packet transfer
    SPI.beginTransaction(settingsA);
    for (int i = 0; i <=3; i++)
    {
    SPI.transfer(r_header[i]); //Set device address, read, register address, & length
    }
    }
    
    
    // Shift device address left 1 bit
    byte read_shift(byte d_addr)
    {
    byte read_byte = (d_addr << 1);
    return read_byte;
    }
    
    
    
    //Function to clock in a read cycle and return the read data
    byte read_data() {
    byte RegValue;
    RegValue = SPI.transfer(0x00);
    return RegValue;
    }
    
    //Function to clock in a CRC cycle and return CRC value
    byte read_CRC() {
    byte CRC;
    CRC = SPI.transfer(0x00);
    SPI.endTransaction();
    digitalWrite(slaveSelectPin, HIGH); //Set CS_H HIGH to end packet transfer
    return CRC;
    }
    
    
    //Function to write to bq71
    void write_reg(byte w_data[])
    {
    CRC = function_CRC(w_data);
    digitalWrite(slaveSelectPin, LOW); //Set CS_H LOW to start packet transfer
    SPI.beginTransaction(settingsA);
    for (int i = 0; i <=3; i++)
    {
    SPI.transfer(w_data[i]); //Set device address, write, register address, & write data
    }
    SPI.transfer(CRC); // CRC Code
    SPI.endTransaction();
    digitalWrite(slaveSelectPin, HIGH); //Set CS_H HIGH to end packet transfer
    }
    
    //Function to generate a CRC
    byte function_CRC(byte data[])
    {
    byte crc = 0;
    int temp = 0;
    for (int i = 0; i < sizeof(data); i++)
    {
    temp = crc ^ data[i];
    crc = CrcTable[temp];
    }
    return crc;
    }
    
    
    //Broadcast RESET to all devices
    void reset_all()
    {
    byte w_data[3] = {0x7F, 0x3C, 0xA5};
    write_reg(w_data);
    }
    
    
    //Automatically address all devices in stack
    void auto_addr(byte n_dev)
    {
    byte device_search = 0;
    point1: reset_all();
    device_search++;
    byte n = 0;
    point2: n++;
    byte w_data[3] = {0x00, 0x3B, n}; //header for write address n to dev[0]
    write_reg(w_data);
    read_byte = read_shift(n);
    byte r_header[3] = {read_byte, 0x3B, 0x01}; //header to read address from address_ctrl register
    read_header(r_header);
    RegValue = read_data();
    CRC = read_CRC();
    Serial.println(RegValue);
    RegValue = RegValue/128;
    //RegValue = RegValue;
    while (RegValue != n) { //Device will be stuck in this loop if addressing fails. Requires POR to try again. Device addr critical.
    //lcd.setCursor(0, 0);
    Serial.println("Addr Failed on Device");
    Serial.println(n);
    byte por_clear[] = {0x7F, 0x21, 0x08};
    write_reg(por_clear);
    por_clear[2] = 0x00;
    write_reg(por_clear);
    //lcd.print("Addr Failed on D");
    //lcd.setCursor(0, 1);
    //lcd.print(n);
    }
    if (n < device_search) {
    goto point2;
    }
    if (n < n_dev) {
    goto point1;
    }
    if (n != n_dev) {
    Serial.println("Address Failed 2");  
    
    //lcd.setCursor(0, 0);
    //lcd.print("Automatic Device");
    //lcd.setCursor(0, 1);
    //lcd.print("Address Failed 2");
    }
    if(n==n_dev)
    { Serial.println("adresing succesful");  }
    }
    
    // Shift device address left 1 bit then add 1 to indicate write
    byte write_shift(byte d_addr)
    {
    byte write_byte = (d_addr << 1) + 1;
    return write_byte;
    }
    
    
    //Overwrite EPROM values using shadow control special sequence. Write 0x35 to shdw_ctrl reg followed by set point.
    void batt_init(byte COV, byte CUV, byte FC)
    {
    byte shdw_ctrl[3] = {0x7F, 0x3A, 0x35};
    //Set Special feature config:
    write_reg(shdw_ctrl);
    byte w_func_con[] = {0x7F, 0x40, FC};
    write_reg(w_func_con);
    //Set Overvoltage:
    write_reg(shdw_ctrl);
    byte w_COV[3] = {0x7F, 0x42, COV};
    write_reg(w_COV);
    //Set Undervoltage:
    write_reg(shdw_ctrl);
    byte w_CUV[3] = {0x7F, 0x44, CUV};
    write_reg(w_CUV);
    }
    
    
    //Function to assert a conversion process
    void conv(byte adc_ctrl[])
    {
    byte conv_start[] = {0x7F, 0x34, 0x01};
    write_reg(adc_ctrl); //Sets ADC control register with desired parameters
    delay(50);
    write_reg(conv_start); //Start conversion
    delay(50);
    }
    
    
    //Function to calculate voltage using register values
    int volt_calc(byte v_msb, byte v_lsb)
    { 
    float ratio = 0.381493;
    int mV = ((v_msb * 0x100) + v_lsb) * ratio;
    return mV;
    }

  • Hi Zeeshan,

    I am suggesting to first use our example software (GUI or Example code) exactly as it is ( no changes) to first establish communications so we can debug if you have a software or hardware issue. Then we can move to understanding the differences in your software from our reference. Would it be okay to do this?.

    Then we also need to understand with your example code what is working so far? For example were you able to successfully wake up device before attempting to read back data? Were you able to read back any other registers?

    Regards,

    Taylor