Having Difficulty Understand I2C Behavior

Hi guys, I am new to i2c and is practicing my skill with a XP power supply that is capable of I2C communication.

According to manufacturer, from 0x00 to 0x16, there are 16 byte of info on manufacturer.

I wrote my program with a “for” loop that uses delay(1000) each cycle. And within each loop, it calls out a function to read and print those 16 bytes.

I used wire.beginTransmission (i2c address)
wire.write (0x00)
wire.end transmission

and then wire.requestFrom(i2c address, 16)
while loop with wire.available and wire.read.

My expectation is that Arduino would hold and grab 16 bytes, print it, and then moves on to increment the for loop.

However, my program prints out the complete data, which is “XP Power LTD” only every 3 or 4 loop cycle.

The loop seems to increment at 1 second interval no matter what. I am really confused because the program IS finding the right address, IS reading from correct register. Everything is working, but whole thing is just very slow.

While I am not sure what chip is on the PS. But I would expect a $500 PS from a name brand should have a decent hardware that can handle reading couple text.

CODE:

void setup()
{
Serial.begin(9600);
while (!Serial);

Wire.begin();
Wire.setClock(100000);

}

void loop()
{
for (int i = 0; i <= 50; i++)
{
Serial.print(“This is cycle #”);
Serial.print(i);
Serial.print("\n");
readManuf (psAddress);
delay (1000);
}
}

void readManuf (byte i2cAdd)
{ // Function to read manufacturer info from register 0x00 to 0x0F
Wire.beginTransmission(i2cAdd);
Wire.write(0x00);
Wire.endTransmission();

delay (20);

Wire.requestFrom (i2cAdd, 16);
while (Wire.available())
{
char c = Wire.read();
Serial.print(c);
}
delay (100);
}

Post the code, using code tags. There should be no need to use delay().

With any new I2C device, the first step is to test basic I2C communications. The Arduino I2C address scanner program will do that for you.

1 Like

Is it a HDS or HDL series power supply ?

There is some information in this document at xppower, but this document about I2C at Digikey has more information.

I noticed a “repeated start” when requesting data.

Once you have your I2C address (as jremington wrote) then you should always use that same I2C address.

const int i2cAdd = 0x ? ? ;   // What a I2C Scanner finds

Wire.beginTransmission( i2cAdd);
Wire.write( 0x00);   // register address, 0x00 to 0x7C, see datasheet
Wire.endTransmission( false);   // repeated start
Wire.requestFrom( i2cAdd, 16);  // request 1 to 16 bytes, see datasheet
while (Wire.available())
{
  char c = Wire.read();
  Serial.print(c);
}
Serial.println();

To get the voltage, read register address 0x60 and 0x61. It might be unsigned. Register 0x60 has the lowByte and 0x61 the highByte. Combine them and you have the voltage in 0.01 Volt units.

Hi Koepel, this particular PS is HDS series.

If you look at my code and result, you can see that I am getting response from the PS. Its just in a very strange way.

I was expecting to fetch and print manufacturer info every “for loop”. However, I am getting result every 3 or 4 cycles.

As I understood Arduino I2C wire library, everything should be on hold until I get all the information in turns of a read process.

@jayliu1984, our answers were correct.

Step one: Forget about your code or what you think that it is doing.

Step two: Use a I2C Scanner sketch and show us the result. Nick Gammon’s I2C Scanner or the one at the Playground, or any other one.

Step three: Understand the difference between “I2C address” on the I2C bus and the “register address” inside the device.

Step four: Have a look at those documents that I linked to.

Hi Koepel, could you please explain the approach you are coming from?

Because I am getting response from the device, just seems not every time when I request it.

I have been on this for couple of days and I have indeed viewed all the documents from XP, as well as extensive research on the forum. And yes I have ran the scanner to find address and found out there are 15 address starting from 0x50 and above.

The documents XP has included LSB to the 7 bit address resulting 0xA0, 0xA1 etc. That actually throw me off for couple of days.

My PS has switch on position 0, which is 1010 000, so 0x50.

I also want to add, I am able to set the PS in “remote” mode, which is writing a particular bit in “control” byte.

I am able to set OUTPUT voltage, and read output voltage. But just like the manufacturer info, or internal temp, it seems I need to multiple tries in order to complete these tasks.

When using a I2C device, the first thing is always to use a I2C Scanner sketch.

A I2C Scanner should find just one address. Perhaps there is something wrong there. Maybe there are no pullup resistors or your could try to add a delay(10); after the Wire.endTransmission().

I think you mixed up “I2C address” and “register address” in the top post. You are not the only one that does that. I hope you know by now about the address on the I2C bus and the registers in the device.

Can you show your sketch that reads the manufacturer info, using a “repeated start” and a single fixed I2C address, that I wrote about.

I don’t understand the LSB for 7 bit address 0xA0, 0xA1.
When scrolling through those documents that I linked, I have not read about the “remote mode”, so I don’t know what that is.

Welcome to the forum.

Maybe the guy who build the power supply was a really good power electronics engineer but he did not know a lot about microcontrollers and used delay(). :stuck_out_tongue_winking_eye: