Pages: [1] 2   Go Down
Author Topic: I2C device addressing  (Read 5735 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've searched google and this forum but it seems no-one else is working with many Arduinos connected together via I2C.

I'd like to have one master Arduino node and many (say 32) Arduino's connected to that master via I2C. They are all I2C slaves and they all would be running the exact same software.

The question I have is simple: How do I allocate each slave Arduino with a unique address if they are all running the same .elf?

If each slave was running different software, I would hardcode the address of each slave in each project and all would work ok, but this simple problem is stumping me.

A few other ways to pose the same question:
  • how can I get each slave to retrieve a unique address from the master node?
  • how can I get each slave to self-allocate a unique address?
  • how can I send each slave a unique address from the master node before it has an I2C address allocated to it?

All help will be greatly appreciated!

JohnA
Logged

Manchester (England England)
Online Online
Brattain Member
*****
Karma: 634
Posts: 34572
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You can have input pins on each arduino, for 32 devices you will need five of them. You then short out a unique combination to ground on each device. Your code then reads these pins and so gives itself an address.
Logged

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17303
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Or maybe perhaps a small trimmer pot mounted on each board that supplies an adjustable voltage to a analog input pin. Each board reads its uniquely adjusted voltage and if in a narrow range supplies itself a unique address based on some calculation that results in a 1 to 127 address. Might not be all that simple from a software point of view, but simple and easy on the hardware resources required.

Lefty
Logged

Offline Offline
Edison Member
*
Karma: 3
Posts: 1001
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

There is a protocol called SM-Bus (similar to and derived from I2C) which support dynamic address assignment (the protocol is widely used to support plug-and-play style identification).

Address assignment is based on slaves initially connecting to the I2C master with an address request. Data passed on with the request include a unique identifier (similar to MAC as we know from Ethernet). The master will then allocate and return a free and unique address to the slave. A mapping table on the master is used to correlate the slave unit and address for subsequent master initiated comnmunication. This would solve the issue with I2C address assignment, but you would still need to program each slave with a unique identifier. This could be in EEPROM however and so separate from the application.
Logged

Manchester (England England)
Online Online
Brattain Member
*****
Karma: 634
Posts: 34572
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
but you would still need to program each slave with a unique identifier. This could be in EEPROM however and so separate from the application

If you are going to do that then why not just store an address in the first place.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

BenF: thanks for the heads up. I looked at the SMBus and ARP is exactly what I need. From the SMBus protocol spec it seems that it is possible to get an address even without a DUID or I could generate one randomly. In any case, I couldn't find an SMBus library for the Arduino however. Do you happen to have any links?

This post http://arduino.cc/forum/index.php?topic=61520.0 claims to implement an "I2C address scanner". The idea is that the master goes through all 120 addresses and either gets a response (and therefore an existing address) or doesn't and therefore that address is free. Essentially this gives me device enumeration like the SMBus has.

Another thought is: what if all the slave Arduino's initially start off with a known address (say 01). Then the master periodically checks if any devices are at address 01. The first one to respond is allocated the next free address.

I have seen a lot of sites explaining that all devices have to have a unique address but it is unclear exactly what happens if (by accident say) two devices have the same address.

One way around this is to have all of the devices with address 01 do a random delay before responding. The likelihood of more than one device being the first to respond is very low; generally only one device will win and be first. It seems from the scanner code, that this is not possible but I thought I'd ask anyway.

JohnA
Logged

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17303
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

BenF: thanks for the heads up. I looked at the SMBus and ARP is exactly what I need. From the SMBus protocol spec it seems that it is possible to get an address even without a DUID or I could generate one randomly. In any case, I couldn't find an SMBus library for the Arduino however. Do you happen to have any links?

This post http://arduino.cc/forum/index.php?topic=61520.0 claims to implement an "I2C address scanner". The idea is that the master goes through all 120 addresses and either gets a response (and therefore an existing address) or doesn't and therefore that address is free. Essentially this gives me device enumeration like the SMBus has.

A scanner can only tell you for sure that no one responded to a specific address, but it won't be able to tell if two or more I2C slaves are responding to the same address, there is no collision avoidance protocol in the I2C standard.

Another thought is: what if all the slave Arduino's initially start off with a known address (say 01). Then the master periodically checks if any devices are at address 01. The first one to respond is allocated the next free address.

There is not 'first one to respond', all slaves with starting address of 01 will try and respond at the very same time, results in garbage data as the slaves step all over each other.

I have seen a lot of sites explaining that all devices have to have a unique address but it is unclear exactly what happens if (by accident say) two devices have the same address.

The slaves step on each other and garbage data results and the master has no idea why.

One way around this is to have all of the devices with address 01 do a random delay before responding. The likelihood of more than one device being the first to respond is very low; generally only one device will win and be first. It seems from the scanner code, that this is not possible but I thought I'd ask anyway.

Your trying to wish that I2C was a more powerful protocol then it is. By some method you have to make sure each slave starts up life with a unique address, It can't be orchestrated at start-up by the master and the slaves can't talk to each other to negotiate unique address assignments. You need to do it with either separate sketches for each slave, or some hardware method on each slave board or have a unique address pre written into its EEPROM, etc.

JohnA

Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 129
Posts: 8601
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
what if all the slave Arduino's initially start off with a known address (say 01). Then the master periodically checks if any devices are at address 01. The first one to respond is allocated the next free address.
This can work but only if you are happy to add a single node at a time when you first set the system up. The new node gets its address then you add the next one etc etc.

______
Rob
Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Your trying to wish that I2C was a more powerful protocol then it is.
Well yes, but less like wishing and more like hacking.

The reason I think it is even possible is that the slave devices here are Arduino's and not simple chips. This opens some possibilities. For example:

  - the Arduino can be both a Master and a Slave at the same time. http://www.gammon.com.au/forum/?id=10896
  - there is bus arbitration in the I2C spec when there is more than 1 Master

Therefore it might be possible (within the defined I2C spec) to do the following:
Quote
   master is also a slave at reserved address 01
   all slaves start using  reserved address 02, or the address saved in its EEPROM (03 to 120)

   // see if any slaves are unallocated
   master: send a broadcast - Start Allocation message
                     all slaves with address 02: delay for random number of microseconds
                     slaveA (as master): creates a 32-bit random number and sends it to master 01
   master 01: associates the random number with next free address
                      slaveB (as master): creates a 32-bit random number and sends it to master 01
   master 01: associates the random number with next free address
            ... repeat until some_magic_condition occurs...

   // Assign the addresses
   master: send a broadcast - Start Assignment message
  master: broadcasts slaveA's random number and address
                      slaveA: sets it's address to the given address; saves the address in its EEPROM
   master: broadcasts slaveB's random number and address
                      slaveB: sets it's address to the given address; saves the address in its EEPROM
             ... repeat ...

    // do it again, just in case
    master: send a broadcast - Start Allocation
                     no slaves with address 02 should remain
                     if there are any remaining, then this step should allocate them
           ... repeat until some_magic_condition occurs...

    // enumerate the slaves
    master:  this should catch both the newly allocated addresses plus the previously saved addresses.

Looks clunky but might work...

John
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 129
Posts: 8601
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
all slaves with address 02: delay for random number of microseconds
How do they know another slave/master has not already started transmitting? Is there a mechanism in I2C to handle that?

_____
Rob
Logged

Rob Gray aka the GRAYnomad www.robgray.com

Manchester (England England)
Online Online
Brattain Member
*****
Karma: 634
Posts: 34572
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Is there a mechanism in I2C to handle that?
Of course not.
The OP seems supremely confident that he can hack the I2C bus protocol. All attempts to discourage / enlighten him seem to fail. He is bringing out all the old bus ideas that were rejected long ago. I don't know maybe he is young and doesn't realise many people have been round that block many times before. Simply the wrong protocol for the job.
Logged

Texas, land of the free, home of the stupid
Offline Offline
Sr. Member
****
Karma: 5
Posts: 268
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think that the first hint to his impending doom was the statement that he wanted ALL nodes running exactly the same software...

He could use I2C to have master assigned slave addresses, by controlled sequential startup of the slaves, as example.  But, there is just too much sugar for a dime in what he says that he wants to do...  Keep it simple and it will work better.

Best solution to multiple slaves is node dependent software, hardcoded addressing at the very least.  Otherwise, WHY HAVE MULTIPLE SLAVES if they are all doung the same thing and calling home with the same names???
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 129
Posts: 8601
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
ALL nodes running exactly the same software...
That's a reasonable requirement and doable and I understand why he wants to get away from having hardcoded and unique values programmed into each node, especially if this will be a product where maybe you don't know in advance how many will be plugged in and holding inventory of nodes with hardcoded addresses would be difficult.

I have a similar requirement at present (not with I2C) but the only way I know to do it is to bring the nodes online one at a time or "by controlled sequential startup of the slaves" as you say. As this is a one-off thing when you first build a system I think that's a reasonable approach.

______
Rob
Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Edison Member
*
Karma: 3
Posts: 1001
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

How do they know another slave/master has not already started transmitting? Is there a mechanism in I2C to handle that?
The AtMega's support HW multi-master bus arbitration. The scheme is based on masters listening for bus activity (start/stop) and then only claim the bus when idle. This generally works when arbitration is only required once every blue moon, but it will not work when two or more devices try to claim the bus at the exact same clock edge (such as may be the case when multiple identical devices are powered on at the same time). For this some software retry scheme will be required.

For most practical purposes (as opposed to academic), storing a unique address in EEPROM is a good option.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
The OP seems supremely confident that he can hack the I2C bus protocol. All attempts to discourage / enlighten him seem to fail. He is bringing out all the old bus ideas that were rejected long ago. I don't know maybe he is young and doesn't realise many people have been round that block many times before.
Well you are living up to your moniker! Which is cool with me by the way, too much PC BS these days.

It's been a long time since anyone's called me anything close to "supremely confident". I going to have to take it as a compliment. So thanks, appreciate it!

Not young. Here's a hint: I bought a Motorola 6800/MIKBUG based computer for $1K in 1976 just after I graduated from high school. Taught myself how to program machine language (hand assembled of course). No it wasn't an Altair, a Commodore, a PET or an Apple I - the 6502 had just come out and the Z-80 was the next big thing.

Quote
Simply the wrong protocol for the job
I agree the SMBus is the right way to go. However it isn't clear if there is an Arduino library for it. If the SMBus and I2C are "compatible" as the Intel blurbs say, then I should be able to use I2C to replicate the SMBus protocol (which implies that someone from Intel "hacked" I2C to come up with SMBus). But that doesn't sound like a pleasant thing to do.

Quote
He could use I2C to have master assigned slave addresses, by controlled sequential startup of the slaves, as example.
I don't need a "controlled sequential startup" at all. I just want the master to assign the slave addresses.

Quote
For most practical purposes (as opposed to academic), storing a unique address in EEPROM is a good option.
I agree that storing the addresses in EEPROM is easier. But being nuts is more fun. And besides once an address is assigned to a slave, it can be stored in EEPROM and the whole situation becomes sane again.

[quote\Otherwise, WHY HAVE MULTIPLE SLAVES if they are all doung the same thing and calling home with the same names???[/quote]
It is very reasonable to have a large array of slaves doing all the same thing. It is very unreasonable to have them call home with the same address -- that's why I'd like to have the addresses assigned by the master.

As BenF says, multi-master bus arbitration is available on the AtMega. Still unknown if the Arduino I2C library can handle it in a reasonable way.

The link I gave clearly shows that it is possible for an Arduino to be both Master and Slave at the same time (unless that guy was throwing some BS out into the ether).

Like I said, those two aspects open up a lot of opportunities....

Quote
This generally works when arbitration is only required once every blue moon, but it will not work when two or more devices try to claim the bus at the exact same clock edge (such as may be the case when multiple identical devices are powered on at the same time).
I think the scheme I proposed would prevent them from hitting the exact same clock edge nearly all the time, but there is a very small probability it could happen. Each slave is quiet until the master kicks the process off with the first message. The slaves all back off randomly, so with high probability, the first slave to respond after that will be the only one to respond. If the other slaves don't blindly rush forward at that point, then there will be a second slave to respond, and again with high probability the only one to respond. And so on.

This process will be slow, but once they have their addresses in EEPROMs, it doesn't need to occur again until a brand new device is added to the array.

Quote
For this some software retry scheme will be required.
Yes, as long as the collision can reliably be detected by *all* the colliding parties. If so, then random back-off would work, even if it had to be repeated until it did. It all depends on the Arduino's I2C library ability to handle collisions in a clear and reasonable way.

JohnA
Logged

Pages: [1] 2   Go Up
Jump to: