Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
11 years, 11 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
11 years, 11 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
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 22 Jan 2013Hi 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 22 Jan 2013Seems 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);
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 22 Jan 201311 years, 11 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.
11 years, 11 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 23 May 2014