BQ27441-G1 - Battery Fuel Gauge: I2C Shenanigans?

Go To Last Post
20 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm prototyping a battery powered system, and got myself a 'Battery Babysitter' from Sparkfun, which is essentially a breakout board for two devices produced by Texas Instruments; one for charging, and a battery fuel gauge. The latter device is a BQ27441-G1 and communicates with a host microcontroller over I2C (/ TWI).

 

I'm prototyping said system on an Xmega A1U Xplained Pro (ATxmega128A1U) and so far I'm using one of the available TWIs to communicate with an accelerometer (LIS3DH) and a resistive touchscreen controller (STMPE811) at 400kHz, using AVR1308 - Using the XMEGA TWI with no problems, so I'm pretty sure in saying my TWI setup is working fine, however I'm having a little trouble with the TI fuel gauge...

 

As a start I'm simply trying to read the device type which according to the datasheet is 0x0421, and I'm checking the result and status of my TWI_Master_t  and everything seems fine, however the data I'm getting back is incorrect, and looking at the datasheet I'm not sure I fully follow what I have to do.

This diagram is from the datasheet...

which is pretty standard as far as datasheets for devices that use I2C goes, however not very helpful for this device as from what I can tell you have to write 4 bytes to it for every transaction, regardless of whether you're reading or writing to it? For example in my case of trying to read the device ID it seems I have to write the Control() command to it which can be seen below...

...followed by the DEVICE_TYPE subcommand...

however, I'm completely unsure as to whether I/m supposed to send those 4 bytes and then read the two ID bytes back in one consecutive TWI transaction, or split them up into several transactions or what? But so far I've not had the device spit 0x0421 back at me, so I'm obviously doing something wrong somewhere.

Now this is already quite lengthy so I won't bother adding code samples and such just yet, especially since the documentation seems so vague on this that I have a suspicion that this is the protocol that TI implement on all their devices? In which case there's bound to be someone (or many people) here that can point me in the right direction.

 

PS. I've tried to only include any necessary info from the datasheet and the 'Technical Reference Manual' in the hope of not writing a short novel, but they're in those links...

This topic has a solution.
Last Edited: Tue. Feb 28, 2017 - 07:51 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Howard_Smith wrote:

 however I'm having a little trouble with the TI fuel gauge...

 

I haven't worked with that device, but ...

 

Have you looked at the arduino source code and examples linked from the Sparkfun page?

Here's a link to the GitHub page: (Link).

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I can see why you're confused. I've worked with I2C devices for decades, and I don't understand what is required. Some examples of the control sequences would be a useful addition to the datasheet.

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Howard_Smith wrote:
I'm using one of the available TWIs to communicate with an accelerometer (LIS3DH) and a resistive touchscreen controller (STMPE811) at 400kHz, using AVR1308 - Using the XMEGA TWI with no problems, so I'm pretty sure in saying my TWI setup is working fine

Weeeeeeeeeeell ...

 

Of course, it's a very good sign; but not conclusive proof that everything is fine - there could still be faults/flaws that just happen not to affect your particular usage of those particular devices...

 

Are you trying the TI devices with all the other devices removed from the bus?

 

I have a suspicion that this is the protocol that TI implement on all their devices? In which case there's bound to be someone (or many people) here that can point me in the right direction.

Surely, the place to find people with specific knowledge of TI parts would be on the TI forums?

 

There are actually TI staff on their forums responding to questions ...

 

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Chuck99 wrote:

Have you looked at the arduino source code and examples linked from the Sparkfun page?

Here's a link to the GitHub page: (Link).

 

That's a good idea, thanks I'll take a look!

 

John_A_Brown wrote:

Some examples of the control sequences would be a useful addition to the datasheet.

 

My thoughts exactly.

 

awneil wrote:

Of course, it's a very good sign; but not conclusive proof that everything is fine - there could still be faults/flaws that just happen not to affect your particular usage of those particular devices...

 

Indeed, that's why I said 'I'm pretty sure' as opposed to 'I know for definite' ;) Is there anything that you have in mind that could be affecting the TI device but doesn't affect the accelerometer and/ or touchscreen controller? I'm able to read and write to every register as expected with said devices...

 

awneil wrote:

Are you trying the TI devices with all the other devices removed from the bus?

 

No, the two other devices are still connected and still working as they were before. 

 

awneil wrote:

Surely, the place to find people with specific knowledge of TI parts would be on the TI forums?

 

Indeed, but I thought before I went through with the hassle of creating an account on the TI forums and such, I'd ask here first. As I mentioned before, I have a feeling that the protocol used here is used on many of their devices so I was hoping some wise soul would come along and say something along the lines of "Ah yes, this is how TI do things, you just have to do this and a bit of that" and away I'd go. Wishful thinking? Maybe, we shall see ha! I'll leave it a while and see what happens in this thread. Chuck99's suggestion of looking at the Arduino library code might lead to the answer of course. But yes, I might well have to ask on a TI forum.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Howard_Smith wrote:
Is there anything that you have in mind that could be affecting the TI device but doesn't affect the accelerometer and/ or touchscreen controller?

No, sorry 

 

Definitely take a look at the Arduino code.

 

Don't TI have any sample code?

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The I2C description looks absolutely fine to me.   Just like most I2C devices

 

You write N bytes in a sequence.   You read M bytes in a sequence.

 

From memory,  the AVR1308 example is not very intuitive.  

But the principle is the same.    Design a generic twi_transfer(slave, writebuf, N, readbuf, M) function.

Whether you poll or use interrupts,   you use it in the same way.

 

The only fiddly bit is setting up the byte sequence in writebuf[ ].

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:

The I2C description looks absolutely fine to me.   Just like most I2C devices

 

You write N bytes in a sequence.   You read M bytes in a sequence.

 

From memory,  the AVR1308 example is not very intuitive.  

But the principle is the same.    Design a generic twi_transfer(slave, writebuf, N, readbuf, M) function.

Whether you poll or use interrupts,   you use it in the same way.

 

The only fiddly bit is setting up the byte sequence in writebuf[ ].

 

David.

So what do you understand from Table 1, which states that CNTL is 0x00 and 0x01, for example? Do you have to send them both? I still maintain that it's confusing.

 

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

John_A_Brown wrote:
Table 1, which states that CNTL is 0x00 and 0x01, for example?

all of the commands in that table have two codes.

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

John_A_Brown wrote:
Table 1, which states that CNTL is 0x00 and 0x01, for example?

all of the commands in that table have two codes.

 

I think I'm in the same boat as John - given that the I2C diagram only shows 1 byte being sent at a time, does that mean you have to send each code in their own transaction/ packet? i.e with a stop condition between each one. Or is it a case that you can use either one of the codes, rather than having to send each one?

And then going further with the subcommand, its the same thing again - do I packet the subcommands in the same transaction or separate?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
Surely, the place to find people with specific knowledge of TI parts would be on the TI forums? There are actually TI staff on their forums responding to questions ...

 

Howard_Smith wrote:
before I went through with the hassle of creating an account on the TI forums and such,

 

I don't blame Howard for wanting to avoid having to create that account.  I have one and as a result I am getting hit several times a day with adverts from TI, and in spite of clicking the DO NOT SEND ME EMAIL boxes the stuff continues to stream in.  The responses from the staff can be very cryptic at times leaving you with more questions than an answer.

 

awneil wrote:
Don't TI have any sample code?

Sure, create the account, then start the search in some cases.

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I just looked through some of the PDF's that are on the devices page and they all say that its a two byte instruction with a two byte subcommand with transmission being done as two consecutive byte writes, but all the flowcharts and such only show one command instruction issued.

 

Certainly a puzzle.

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

On the product page there are links to a Linux driver that may be of some use in understanding the bytes to be sent.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

John_A_Brown wrote:
Table 1, which states that CNTL is 0x00 and 0x01, for example?

all of the commands in that table have two codes.

 

 

Indeed. That's why I used the phrase "for example".

 

They are also all consecutive values, which leads me to believe that what TI are referring to as commands are really more like byte addresses.

 

 

Four legs good, two legs bad, three legs stable.

Last Edited: Tue. Feb 28, 2017 - 02:41 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

John_A_Brown wrote:
... leads me to believe that what TI are referring to as commands are really more like byte addresses.

Yes - it looks something like that

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The 3.1 Data Memory Parameter Update Example from the Tech Ref Manual shows how to write a sequence.

 

It is much like an 24Cxx or DS1307.   i.e. you can set the register and write an arbitrary number of data bytes in a burst.   (the register auto-increments)

Or you set the register and only write one byte at a time.

 

Personally,  I would use the burst method.   It is simpler and more efficient.   And in a DS1307 ensures that you get an ATOMIC access to the register(s).

 

No,  I have not studied the whole doc(s).   Just enough to see the question that you were unsure  of.

 

As a general rule.   Verify your hardware (and your understanding) by reading "known" values e.g. from ID register.  Then writing values to a register and reading them back.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@david.prentice

 

David, I get the impression that Howard is fairly familiar with I2C/TWI, so instead of talking in such general terms, why don't you give him your expert opinion on exactly what sequence of bytes you would read/write to achieve his ambition of reading the device type code?

 

I would also be interested in the answer. As I said, I've been writing I2C stuff of various flavours for decades, and I do not find that data to be straightforward.

 

 

 

Four legs good, two legs bad, three legs stable.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay, I think I've got it. I took a look at the Arduino library code and saw how they were doing it, then tried to replicate it myself, and voila, I can read the DEVICE_TYPE value (0x0421)

Essentially the wording of the datasheet was my undoing - as mentioned in this thread, although TI refer to them as commands, they are very much simple register addresses like with any other device that uses I2C. The way it works is you write the sub command value to the the Control() command/ register in one transmission, then read it back it another. I found this diagram from the datasheet actually points it out quite clearly, I just had to stop thinking of everything as 'commands' and more like addresses to see it.

 

 

and just to confirm, here is some example code that illustrates this (using AVR1308)

 

#define BQ72441_I2C_ADDRESS 0x55 // Default I2C address of the BQ27441-G1A
#define BQ27441_DEVICE_ID	0x0421 // Default device ID

// 'Commands' (register addresses)
#define CONTROL_HIGH        0x00
#define CONTROL_LOW         0x01

// Sub-commands
#define DEVICE_TYPE     0x0001

bool ReadId()
{
   uint8_t buffer[3] = { CONTROL_HIGH, (uint8_t)(DEVICE_TYPE & 0xff), (uint8_t)(DEVICE_TYPE << 8) };
   TWI_MasterWriteRead(&twiMaster, BQ72441_I2C_ADDRESS, &buffer, 3, 0);

   // Wait for transaction to finish
   while (twiMaster.status != TWIM_STATUS_READY)
      ;

   TWI_MasterWriteRead(&twiMaster, BQ72441_I2C_ADDRESS, &buffer, 1, 2);

   // Wait for transaction to finish
   while (twiMaster.status != TWIM_STATUS_READY)
      ;

   if (twiMaster.result != TWIM_RESULT_OK)
      return false;
   else
   {
      uint8_t temp = twiMaster.readData[0];
      temp |= (twiMaster.readData[1] << 8);

      if (temp == BQ27441_DEVICE_ID)
         return true;
      else
         return false;
   }
}

 

Last Edited: Tue. Feb 28, 2017 - 08:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So very similar, if not exactly the same as the PM I sent you 20 minutes earlier?

 

 

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Close but not quite John, see my reply...