We know that it's tough to talk to the fuel gauge chip on the Fuel Tank BoosterPack. Its I2C interface is sensitive to right timings.

I tested the communication with a Dangerous Prototypes Bus Pirate, and captured some question-reply sequences with a logic analyzer.

It's now time to get it working in the final setup: with a Texas Instruments Hercules Safety microcontroller

 

fueltank boosterpack hercules launchpad i2c

 

 

The end-game of my project is to power a Hercules safety project with a LiPo battery. The Fuel Tank BoosterPack that I'm using has a 3.7V 1200 mAh battery.

(The BoosterPack is well known here at element14. It's designed by TI and e14, and has been the subject of a TI Fuel Tank BoosterPack & MSP430F5529 Launchpad and many blogs).

Monitoring the battery state is one of the parameters for a safe design. I'll check the state of the accu regularly.

I do that by firing I2C queries to the battery gauge IC that's constantly monitoring the battery health and state.

 

I've documented the protocol and queries in previous posts (see Related Posts at the end of this post). This is my first attempt to set up a communication between the Hercules microcontroller and the fuel gauge.

 

Hercules Safety Microcontroller

 

I'm using a Texas Instruments Hercules RM46L852. It's a rather beefy safety microcontroller with loads of safety features.

It has a dual ARM core in lockstep configuration. Each calculation is executed in both cores, and the results are compared for consistency.

A number of peripherals have extended error detection and recovery. Many peripherals (e.g. the ADCs) offer the option to do the same task in two separate modules, and raise an alert when there are differences.

I'm using the native I2C module to query the battery gauge.

 

Battery Monitoring IC

 

I reuse the Fuel Tank BoosterPack reference design. I believe that the BoosterPack isn't available anymore, but a Version II is announced.

I need the 3.3 and 5V Buck-Boosters, and it already has a LiPo charge circuit.

Those things i can just reuse. I don't have to interfere with them because they do their work without monitoring or ciontroller input.

The point of focus is the bq27510. I can ask the remaining charge of my battery, the voltage and current, and other attributes like number of load cycles and temperature.

I can also monitor the bat_lo/bat_gd pin and fire an interrupt when it is triggered. I can then use the microcontrollers safety functions to perform a controlled and safe shut-down.

 

First FirmWare Version

 

I got it working - kind of. I've used the I2C before. But this is the first time that I do an I2C scenario with Repeated Start.

With repeated start, you have to send a new START command to your I2C slave without doing a STOP.

And although the Hercules I2C module is capable of doing that (it's documented in the TRM), I can't get it to work yet.

 

 

It doesn't influence the scenario. The communication works also when I do send that bogus extra STOP. But it isn't as per spec. So I'll have to fix this or I won't be able to ever sleep well again .

I've raised a question on the ti e2e forum.

Here are my preliminary results:

 

stopcondition.jpg

 

Entry 5 is the unwanted STOP.

 

Below is a subset of my code. I'll add an additional blog with the full project once I have the Repeated Start working.

 

 

#define bq27510_address 0x55
#define Slave_Address  bq27510_address

uint8_t TX_Data_Master[1] = { 0x2E};
uint8_t RX_Data_Master[2] = { 0 };

void bq27510Init() {
  int delay =0;

  ///////////////////////////////////////////////////////////////
  //        Master Transfer Functionality                      //
  ///////////////////////////////////////////////////////////////
  i2cInit();

  /* Configure address of Slave to talk to */
  i2cSetSlaveAdd(i2cREG1, Slave_Address);

  /* Set direction to Transmitter */
  i2cSetDirection(i2cREG1, I2C_TRANSMITTER);

  /* Configure Data count */
  i2cSetCount(i2cREG1, 1);

  /* Set mode as Master */
  i2cSetMode(i2cREG1, I2C_MASTER);

  /* Set Stop after programmed Count  NEED TO FIX FOR REPEATED START*/
  i2cSetStop(i2cREG1);

  /* Transmit Start Condition */
  i2cSetStart(i2cREG1);

  /* Tranmit DATA_COUNT number of data in Polling mode */
  i2cSend(i2cREG1, 1, TX_Data_Master);

  /* Wait until Bus Busy is cleared */
  while(i2cIsBusBusy(i2cREG1) == true);

  /* Wait until Stop is detected  NEED TO FIX FOR REPEATED START*/
  while(i2cIsStopDetected(i2cREG1) == 0);

  /* Clear the Stop condition */
  i2cClearSCD(i2cREG1);

  ///////////////////////////////////////////////////////////////
  //        Master Receive Functionality                      //
  ///////////////////////////////////////////////////////////////

  /*****************************************/
  //// Start receving the data From Slave
  /*****************************************/

  /* wait until MST bit gets cleared, this takes
  * few cycles after Bus Busy is cleared */
  while(i2cIsMasterReady(i2cREG1) != true);

  /* Configure address of Slave to talk to */
  i2cSetSlaveAdd(i2cREG1, Slave_Address);

  /* Set direction to receiver */
  i2cSetDirection(i2cREG1, I2C_RECEIVER);

  /* Configure Data count */
  /* Note: Optional - It is done in Init, unless user want to change */
  i2cSetCount(i2cREG1, 2);

  /* Set mode as Master */
  i2cSetMode(i2cREG1, I2C_MASTER);

  /* Set Stop after programmed Count */
  i2cSetStop(i2cREG1);

  /* Transmit Start Condition */
  i2cSetStart(i2cREG1);

  /* Tranmit DATA_COUNT number of data in Polling mode */
  i2cReceive(i2cREG1, 2, RX_Data_Master);

  /* Wait until Bus Busy is cleared */
  while(i2cIsBusBusy(i2cREG1) == true);

  /* Wait until Stop is detected */
  while(i2cIsStopDetected(i2cREG1) == 0);

  /* Clear the Stop condition */
  i2cClearSCD(i2cREG1);

}



 

 

Related Posts
part 1: Communication Test with a Bus Pirate
part 2: Capture Test Communication with a Papilio
part 3: First Attempt with Hercules LaunchPad