Need Help with I2C comms - Page 1
Forum section: electronics / projects

author: MrAureliusR
author_rank: Unknown
timestamp: February 28, 2014, 03:28:39 am
content: I've been using I2C for a while now. I was primed by Vincent Himpe's Mastering the I2C Bus, which takes a good look at the hardware level and also all the pieces of the protocol itself. A very good read by the way.My problem is, I'm trying to communicate with a TI bq27510 Fuel Gauge chip using I2C. I've read the datasheet, and in it the I2C address is specified as 0xAA for writing, and 0XAB for reading. It even reminds you how a standard 1-byte read is done in I2C. Essentially, you need to send the following things, while clocking out each byte at the same time, and waiting for an ACK from the slave after each step:- The Start condition (a falling SDA followed within a certain period by a falling SCL -- the only time SDA can legally change while SCL is high)- The address of the chip you want to communicate with (in our case 0xAA for write)- The command or data you want to send (in our case, for example, 0x08 for voltage read)- a "repeated Start" which is another Start without first sending a Stop, this way we stay master of the bus- the read address 0xAB- then we clock out 8 bits, during which the slave should send back the requested voltage level of the attached battery.Sorry for all the rambling, but I wanted to make sure I have everything right. The API calls take care of a lot of this in TivaWare. I'm using a TM4C129XNCZAD, just for reference, at 120MHz, though that's not terribly relevant.The problem is -- no matter WHAT I send as the command (right after the write address) the slave sends a NACK (not acknowledge) immediately after the command. And not only that, sometimes it actually pulls SDA low for exactly 2 seconds (2000ms, I've measured it a couple times). However, when I send the write or read address, it will ACK those. And if I do a 'quick read' which just gets the slave to increment the address pointer and then send the data from that address, it will successfully do so! It will allow me to clock out three bytes after a 'quick read'. A quick read is accomplished by sending a Start, then the read address, and after the slave ACKs the read address we just send clock pulses and it sends back data. So I know two-way communication is working. I'm just so stumped as to why it's NACKing the commands.I've read and re-read the datasheet a bunch of times. I've tried every command they list. I really don't understand the wording of the paragraph before the command table so I feel like I'm doing something wrong, but when I look at the example code that goes along with the board I'm using, they are sending the same command bytes that I'm trying to send.Here's a link to the datasheet:http://www.farnell.com/datasheets/1775288.pdfThe commands are on page 8. It lists two different numbers as the commands, and I'm not sure if one is for the UNSEALED mode, and the other is for SEALED mode? However the example program simply sends the first number in the box, 0x08 for voltage for example. I've tried running the example code and I THINK it works but it sends the retrieved data back over UART and for some reason the UART isn't sending data correctly (that's a whole other problem, the example code is for a different processor and I do have one to test with, but I don't know that much about it and so I think I'm setting something up wrong).ANYWAY -- if anyone sees a glaring error I'm making, or something, all help is greatly, greatly appreciated!

author: andyturk
author_rank: Frequent Contributor
timestamp: February 28, 2014, 06:57:10 am
content: What a weird chip. All the other I2C devices I've seen use a simple register-based protocol. You read and write registers with an 8-bit address to make stuff happen.This beast has "commands" instead of registers and those commands are 16-bits long (some even requiring another 16-bits of sub-command). Yuk. No wonder it's NRND.I'd look for some example code from TI to see how they set up the I2C transactions. Try asking over at e2e.ti.com, as there are probably people there who've used this chip before.

author: MrAureliusR
author_rank: Unknown
timestamp: February 28, 2014, 05:36:31 pm
content: Well, the first mistake I made was that I was looking at the wrong version of the chip. I have a bq25710-G3instead of -G2. When I noticed this I practially shouted for joy, assuming that the commands were different for the G3.And then I slumped back down when I realized the commands are exactly the same. The more I dig into this, the more I can't for the life of me understand what's going on. The -G3 version has a slightly longer section on the I2C protocol, but it didn't tell me anything I didn't already know.I am just very confused right now... I might take a break from this and see if my mind figures it out. I'm absolutely sure I have the API calls right, as the logic analyzer shows the first byte sending, plus the first ACK... anyway.I did ask over at E2E on ti.com as well, haven't heard back (though usually they're pretty good over there)

author: CarlG
author_rank: Regular Contributor
timestamp: March 02, 2014, 09:03:11 pm
content: What is the I2C clock frequency?

author: MrAureliusR
author_rank: Unknown
timestamp: March 02, 2014, 11:19:51 pm
content: I've been using it at 100kHz., and I also tried it at 400kHz and 50kHz for good measure. I've used both my Bus Pirate and also my dev board to no effect. I might try an Atmel, or I might even dig out the one Arduino I have and give that a shot.I've successfully talked to the TMP100 sensor on-board, plus I've been talking to an MCP4251 via SPI. So I know the chip does the communication the way I expect it to. I've been watching it on the scope and it works beautifully. Really solid clocking, great chip indeed.However the bq27510-G3 (I was told it's a G3 though all the documentation on this board says G2, though all the commands are identical) just will not ACK the command byte. It ACKs both addresses -- any other number in the address byte and it does NACK -- but then anything sent after the address gets a NACK.

author: dannyf
author_rank: Super Contributor
timestamp: March 02, 2014, 11:27:19 pm
content: If you have a logic analyzer, you can put it on the bus and debugging is easy.if not, you have to isolate the issue to your iic routines or your chip routines.I would try software iic first to see if your chip routines are working. Google bit bang iic and you will get tons of hits..

author: hamster_nz
author_rank: Super Contributor
timestamp: March 02, 2014, 11:37:27 pm
content: I'm not so sure about the repeated start... IIRC correctly you needstart, device write address, address for read, stopstart device read address, device supplies data from 'address for read', stopGiven the other data you have supplied I would expect to see:start, 0xAA, 0x08, STOP, START, 0xAB,?, STOP.That should give you the data from register 0x08 of device ID 0x55. (read address 0xAA, write address 0xAB)However, this is from memory....(Ignoring the slave or master ACKs with each byte transfered)

author: MrAureliusR
author_rank: Unknown
timestamp: March 03, 2014, 12:27:07 am
content: No, right in the datasheet for the part it says to use a repeated start. It doesn't matter if you STOP then START or use a repeated start- the only difference is in bus arbitration. Repeated starts guarantee the master keeps control of the bus, the slave doesn't really care otherwise.And @dannyf, I said in my posts a couple times that I DO have a logic analyzer. The software IS working and is sending what I'm telling it to. I can even see the NACK in the SDA line on my analyzer, so I know the software is accurately reading back what's happening on the bus. I'm almost starting to think I have a dud chip, but that's on the far side of unlikely, so there's gotta be something else. Maybe I'll shoot a quick video showing what's going on, and upload into the thread here.

author: dannyf
author_rank: Super Contributor
timestamp: March 03, 2014, 02:01:10 am
content: In that case, you should be able to check the waveform vs. the datasheet and see what's wrong - fairly easy.Or post your code and let people see if it compiles with the datasheet - fairly easy too.