I'm confused about i2c address

Hi All I'm new to the arduino and also to i2c, but not to electronics. This is a bit of a long post for a first post, and I kinda get there in the end but am puzzled as to why and how, so please read on.

I have a slave device (a pcb containing a video switch etc) and the documentation says it has an address of 0xba or 0xbb depending on the address A0 select line.

It actually states 'if the A0 line is high (which it is) the device has an address of 0XBA/0xBB where the LSB is the R/W flag

First Question - I'm not totally sure what that means... do I need to read from one Address and Write to the other?

I have some arduino code which is trying to send a couple of basic commands to this board, these commands simply select one or another input and route it to the output, switching every five seconds .

The slave boards API uses something it calles 'alpha commands' on the i2c bus whereby the first byte of data is the 'size' of the command in bytes then follow the actually command.

OK here is my very simple sketch

#include "Wire.h"
#define I2C_ADDRESS 0xba // slave I2C address
int led = 13;


void setup()
{
  pinMode(led, OUTPUT);     
  Wire.begin();
}

void sel1() // select input 1
{
 Wire.beginTransmission(I2C_ADDRESS);
 Wire.write(0x04); // message size
 Wire.write(0x00); // 
 Wire.write(0xca); // Select Input
 Wire.write(0x09); // 
 Wire.write(0x01); // HDMI 1
 Wire.endTransmission();
}

void sel2() // select input 2
{
 Wire.beginTransmission(I2C_ADDRESS);
Wire.write(0x04); // message size
 Wire.write(0x00); // 
 Wire.write(0xca); // Select Inout
 Wire.write(0x09); // 
 Wire.write(0x02); // HDMI 2
 Wire.endTransmission();
}

void loop()
{
 sel1();
 digitalWrite(led,HIGH);
 delay(10);

 sel2();
 digitalWrite(led,LOW);
 delay(10);
}

The flashing LED is just so I can see something is happening. The video switch does not do anything though, even though I can see it's status is READY to accept commands.

So I had a look what was happening on the i2c bus with my scope and this is what I can see:

blue trace is the clock SCL, yellow trace is the data SDA

Now if I am understanding this correctly then I can see:

a Start condition (SDA goes low while SCL is high)

some data 011101001

a stop condition (SDA goes high while SCL is high)

Now the i2c address is set to 0xBA which is 10111010 but what I see on the scope is 011101001

This kinda correlates to the address

expected 0xBA.........1 0 1 1 1 0 1 0 observed..................0 1 1 1 0 1 0 0 1

This confused me somewhat. I read that i2c uses a 7 bit address. Which is the first part of what I can see on the scope.

Second question then. If i2c uses a 7 bit address how can my device ever have an address of 0xBA ? That needs 8 bits! (anything over 0x7F does). I actually see on the scope 0x7A (first 7 bits) instead of 0xBA

Then there is this '0 1' that I can see after the seven bit address. According to the i2c docs I read, after the seven bit address there is an eigth bit (0 write 1 read) followed by an ACK (1) from the slave

Third Question: Is that what I am seeing here..... address 0x7A..... followed by 0 (write) and then 1 (ack) ?

Now I am WELL confused. The address I sent was supposed to be 0xBA but it looks lke 0x7A on the scope. If I include the read/write bit as part of the address then I am actually sending 0111 0100 (ack) which is 0x74. In that case why do I get an ACK for the wrong address?

Now I really started thinking..... If.... expected 0xBA.........1 0 1 1 1 0 1 0

gives observed..................0 1 1 1 0 1 0 0 1

and I want to observe 1 0 1 1 1 0 1 0 (where the last 0 of the address is the 'write' bit)

then in arduino should I address 0xdd (allowing for the additional read/write on the LSB and the loss of the MSB due to 7 bit address)??

because 0xdd is................... 1 1 0 1 1 1 0 1 so observed should be... ...1 0 1 1 1 0 1 0 1 which is 0xBA plus ACK

What I actually saw was 10111010 0 like 0xBA plus an ACK of 0

This is what I see now

After the address I can see the ACK (I think but it is a 0 not a 1 as I thought it would be) followed by the first byte of data 0x04

So something has started working right because my arduino now sends the rest of the sequence!

Bit why am I having to use a completely different address in Arduino to that specified in the documentation for my advice. Seeing as I have never messed with i2c until today I feel quite pleased to have got this far, but I am very confused why it was so difficult and still not sure now if I am doing this right as though my board accepts the command it still does not switch the video (yet!!)

Please someone unconfuse me

Rich PS I've ordered myself one of these 'bus pirate' devices to help me with this project as decoding i2c on an oscilloscope is do-able it seems but very fiddly

Lots of questions, Maybe start reading this excellent source about I2C - Gammon Forum : Electronics : Microprocessors : I2C - Two-Wire Peripheral Interface - for Arduino -

the device has an address of 0XBA/0xBB where the LSB is the R/W flag

The way datasheets usually specify an I2C address and the way it is done in Arduino code are a bit different. The datasheet address of 0xBA/0xBB is 10111010/10111011. The low order 0/1 bit is the read/write bit. The upper 7 bits are the I2C address. When specifying this address to the Arduino code you drop the read/write bit so that 10111010/10111011 becomes just 1011101. In hex this is 0x5B and that is the address that you specify to the Arduino code:

#define I2C_ADDRESS 0x5B

Pete

Hi thanks Rob for the interesting link

It describes what I figured about the i2c address using my scope (though it is easier to see on his logic analyser screenshots) that the address is 7 bit and shifted left then add a LSB 0 or 1

@Pete Yeah thanks for that it is kind of what I figured.... by adjustng the address in Arduino until the data on my scope look like the correct address which made things work but it is useful to have an explanation of why this fixed the problem for me. It's a shame it took me 3 or 4 hours of head scratching to get there on my own.

However you do say the address should be 0x5b

10111010/10111011 becomes just 1011101. In hex this is 0x5B and that is the address that you specify to the Arduino cod

But I am using 0xdd and isn't 1011011 = 0x5d rather than 0x5b?

0xdd is working (I now have my video switch switching once I got my bytes in the correct order (little-endian)) so it is definitely working

I didn't try but I am sure 0x5d would also work, as the MSBit is ignored as it is a seven bit address.

I'm looking forward to getting my bus pirate logic analyzer when it turns up from Hong Kong, I'm sure this would have saved me quite some time

Cheers Rich

But I am using 0xdd and isn't 1011011 = 0x5d rather than 0x5b?

Nope. 1011 is B. 1101 is D.I don't know why 0xDD/0x5D would work.

Pete

el_supremo:

the device has an address of 0XBA/0xBB where the LSB is the R/W flag

The way datasheets usually specify an I2C address and the way it is done in Arduino code are a bit different. The datasheet address of 0xBA/0xBB is 10111010/10111011. The low order 0/1 bit is the read/write bit. The upper 7 bits are the I2C address. When specifying this address to the Arduino code you drop the read/write bit so that 10111010/10111011 becomes just 1011101. In hex this is 0x5B and that is the address that you specify to the Arduino code:

#define I2C_ADDRESS 0x5B

Pete

It's down to yyping errors on both our parts lol.... I meant to say 101 1101 is 0x5D and not 0x5B....

101 1101 is what you posted in your reply (quoted above) but then you said 101 1101 is 0x5B if you take a look ;)

The way datasheets usually specify an I2C address and the way it is done in Arduino code are a bit different.

But then again some manufactures will state the 'true' 7 bit I2C address (minus the R/W bit) on their datasheets, same as used by the arduino I2C library. It's often useful when first wiring up a I2C device to a arduino to run one of the simple I2C 'address scanner' sketches, as it will tell you two useful things, what address(s) the device is responding to and that you have the I2C bus wired correctly to the device. Then you one can get on will the task of actually creating the desired sketch application.

Lefty

@retrolefty Good advice m8 and I will remember it for future ^_^

If I had known such a thing as a i2c address scanner existed in the first place I would have used it rather than doing it using my trussty ol' 'scope and a lot of time and head-scratching lol shame all the documentation I was reading didn't mention shifting the address and adding a 0/1 at the LSbit nor the fact I could just use an address scanner

I also read since, seeing as my i2c bus has one master and one slave I could just 'broadcast' my data to all devices on address 0 (is it?) and not even bother with addressing seeing as I only have one slave

I also read since, seeing as my i2c bus has one master and one slave I could just 'broadcast' my data to all devices on address 0 (is it?) and not even bother with addressing seeing as I only have one slave

I don't believe all (or even many?) slave I2C devices do anything useful with address zero broadcast, but I could be wrong. Here is what I could find in a quick search:

"10.1.1 GENERAL CALL ADDRESS

The general call address is for addressing every device connected to the I2C-bus. However, if a device doesn’t need any of the data supplied within the general call structure, it can ignore this address by not issuing an acknowledgment. If a device does require data from a general call address, it will acknowledge this address and behave as a slave-receiver".

Lefty

but then you said 101 1101 is 0x5B

Absolutely right. My bad. Sorry :blush: The address is 0x5D. If you enter it as 0xDD, I presume that the Arduino is going to shift this up one bit so that the top bit is lost and 0xDD generates the same address 0x5D.

Pete