8 years, 8 months ago.

LTC4151 I2C comms

Has anyone had experience with the LTC4151 Current & Voltage IC using I2C comms. I am trying to simply read back two registers 02h & 03h (C_reg & D_Reg) as per the datasheet (http://cds.linear.com/docs/Datasheet/4151fe.pdf) SDA Read Byte Protocol. The device address is 0xCE in this example - had no luck so far with this. Not sure if code is wrong, or if I need to configure register 06h (G_reg) prior to read back.

Any help would be appreciated, and code sample is shown below:

/media/uploads/fraserphillips/ltc4151.cpp

3 Answers

8 years, 8 months ago.

Hi Erik,

I now have a working piece of code that performs a SDA Read Page protocol of registers 00h to 06h:

/media/uploads/fraserphillips/ltc4151_ver2.cpp

I now need to perform a HEX to DEC on the 'sense', 'vin' & 'adin' values in order to perform a scaled conversion, i.e.

float vft = (( vin(decimal) / 4096 ) * 102.4 ); float vf = (( adin(decimal) / 4096 ) * 4.096 ); float if = (( sense(decimal) / 4096 ) * 4.096 );

Question: How easy is it to convert from HEX to DEC ?

regards, Fraser

Accepted Answer

I dont understand what you want exactly. How do you mean from hex to decimal? If you read a value from your sensor it is just a value, it is neither hex nor decimal, it only becomes one when you use printf with either %X for hex or %d for decimal.

posted by Erik - 22 Jan 2013

Hi Erik,

I now have things working, I re-assigned the 'int' as a 'float' and was able to apply conversion from there, i.e.

void ltc4151_ch1() { char addrch1 = 0xCE; char rRegch1[7] = {0,0,0,0,0,0,0}; char cmdch1 = 0x00; i2c.write(addrch1, &cmdch1, 1); i2c.read(addrch1, rRegch1, 7); float sensech1 = ((rRegch1[0] << 8) + rRegch1[1] >> 4); float vinch1 = ((rRegch1[2] << 8) + rRegch1[3] >> 4); float adinch1 = ((rRegch1[4] << 8) + rRegch1[5] >> 4); pc.putc(0x0D); float ift1 = ((sensech1/4096)*4096); pc.printf("CH1 IFT = %3.2f mA",ift1); float vft1 = ((vinch1/4096)*102.4); pc.printf("CH1 VFT = %3.2f V",vft1); float vfs1 = ((adinch1/4096)*4.096); pc.printf("CH1 VFS = %1.2f V",vfs1); }

posted by FRASER PHILLIPS 22 Jan 2013

Seems to me that the conversion from the 2 registervalues to one 12 bit result is wrong. The datasheet says:

Register 0x00 holds 8 MSBs (M7..M0)

Register 0x01 holds 4 LSBs (L7..L4 B 0 0 0), where B is a busybit and 0s are reserved

Your codes uses:

float sensech1 = ((rRegch1[0] << 8) + rRegch1[1] >> 4); 

That gives you: M7...M0, 0 0 0 0 L7..L4

Where it should be: M7...M0, L7..L4

The following code should provide the correct 12 bit result

float sensech1 = ((rRegch1[0] << 4) + rRegch1[1] >> 4); 
posted by Wim Huiskamp 22 Jan 2013

Working through your observation:

Reg-0 holds M[7:0] & Reg-1 holds L[7:4] so on acquisition, rRegch1[0] holds Reg-0 and rRegch1[1] holds Reg-1. To achieve the [7:0]+L[7:4] 3-byte result, bitwise shifting is required.

Worked example:

Reg-0 = 0x00AB << 4 = 0x0AB0 Reg-1 = 0x00C0 >> 4 = 0x000C Addition = 0x0ABC

So it looks like you are correct. I will aim to update code tomorrow, and check results.

posted by FRASER PHILLIPS 22 Jan 2013
8 years, 8 months ago.

You have used the code below to read from the device

i2c.start();          		// I2C start
i2c.write(0xCE);      		// I2C slave address - 0xCE
i2c.write(0x02);      		// I2C slave register address - C_register 02h
i2c.start();          		// I2C start
i2c.write(0xCE);     		// I2C slave address - 0xCE
int msb=i2c.read(0);  		// I2C read with NAK (not-acknowledge)
i2c.stop();           		// I2C stop

When using the i2c byte operations (rather than the easier blockread/write versions) then you should also set the lsb of the address value. The lsb is the read/write bit. It should be set for read operations and reset for write operations.

i2c.start();          		// I2C start
i2c.write(0xCE);      		// I2C slave address - 0xCE  (lsb reset: write operation)
i2c.write(0x02);      		// I2C slave register address - C_register 02h
i2c.start();          		// I2C restart
i2c.write(0xCF);     		// I2C slave address - 0xCF (lsb set: read operation)
int msb=i2c.read(0);  		// I2C read with NAK (not-acknowledge)
i2c.stop();           		// I2C stop

Try this code.

8 years, 8 months ago.

Using I2C commands like that only complicates your code (didnt try if it actually compiles):

int address = 0xCE;
char data[2];

while(1) {
  data[0] = 0x02;  //register we want to read 
  int ret = i2c.write(address, data, 1, true);  //Write one byte, dont transmit stop condition, check if we get ACK
  
  if (ret == 0)  
    printf("Succesfull write\n\r");
  else
    printf("Returned: %X\n\r", ret);

  i2c.read(address, data, 2);
  printf("Data = %d\n\r", (data[0]<<8) + data[1]);
}

See if it gets acks on the write first. If it doesnt my first guess is wrong address, but I believe the value it returns should then tell us more.

Edit: well beaten. Still normally you just want to use the block operations, it is just so much easier. The whole part with 'ret' in my code can even be removed generally and is only there for debugging now.

Hello, My problem is, I am sending device address to LTC4151 through SMBUS with help of controller Silab C8051F340.But after sending device address I am not getting ACK from ltc4151.Main thing is on same SMBUS I connected EEPROM and it's working fine. I used adr0 and adr1 as float i.e. 0xD4 address.also I tried with few other address.Please suggest what is wrong.And if any one having LTC4151 interfacing experience on SMBUS please do inform.

posted by Gangaprasad Swami 23 May 2014

Check if it is powered, pull-ups there, not SDA/SCL switched around, etc.

posted by Erik - 23 May 2014