This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

INA226 calibration readback incorrect

Part Number: INA226

Calibration readback should work on the INA226 (register 0x05) should read back whatever I wrote to it, right?

I've got something odd going on.  If I reset the chip and read 0x05 I read 0x0000 which is the reset value - that's expected.  If I write the value I want to it (838 decimal) then when I read 0x05 I get back nonsense.

My write is using the wire library like this:

uint16_t cal = 838;
Wire.beginTransmission(INA_ADDR);
Wire.write(0x05); /* cal register */
Wire.write(   (cal >> 8) | 0xFF ); /* high byte */
Wire.write( cal & 0xFF ); /* low byte */
Wire.endTransmission();

When I read I have to do something completely different.  I have to set the register first, like this:

uint16_t cal = 838;
Wire.beginTransmission(INA_ADDR);
Wire.write(0x05); /* cal register */
Wire.endTransmission();

Wire.requestFrom(INADDR, 2);
byte high = Wire.read();
byte low = Wire.read();
Wire.endTransmission();

I'm not sure why, but if I try to do it in a single transaction (begin, write, read, read, end) it doesn't seem to latch the address in correctly.  They have to be two totally separate transactions.

I think my read is working fine (I can read back bus and shunt voltages and they make sense) but I think my write must somehow be off.  I tried doing the configuration in two transactions - write the register address (then endTransmission), then write the value.  It didn't work that way, either.

For those not familiar, endTransmission is essentially STOP in I2C language.

  • Hey Christopher,

    Thanks for posting to the forum. The register pointer should not change once set during a write sequence. There could be a number of things occurring.

    1. What is the clock speed?
    2. Are you ever able to correctly read back the calibration register contents of 838?
    3. After writing to the calibration register, do you read correct current and power register values? If so, then this mean the calibration register is in fact being programmed correctly.
    4. There might a violation of the following times seen in Table 3:
      1. t(BUF) – Bus free time between stop and start conditions
      2. t(HDSTA) – hold time after repeated START condition.
      3. t(SUSTA) – repeated start condition setup time.

    I would not expect your last method to work where you write register address, endTransmission, and then write back value. This is because the write command shown in datasheet shows the value coming right after the pointer address with no STOP condition in between.

    Sincerely,

    Peter

  • Thank you.  The main thing that helped was you telling me "it should work."

    It does work.  I'm only running 400 kHz, so nothing crazy.  The big problem was:

    Wire.write(   (cal >> 8) | 0xFF ); /* high byte */
    Wire.write( cal & 0xFF ); /* low byte */

    Yeaaaaaah that's not how you do it, it should have been (cal>>8) & 0xFF ... and really the mask to one byte isn't even necessary, and GCC optimizes it out anyway.  I write that way for clarity, and this time, swapping 'bit and' for 'bit or' just screwed me.  Rookie mistake, stared at it for 4 hours and didn't see it.  I hooked a logic analyzer with an I2C protocol driver and asked "Why is it writing THAT?"  ... sheesh.

    Thanks for the reply, appreciate it a lot.